function Mediazentrale() {
var self = this;
var appMenu;
var cache; // mustache templates
var ortPfad;
var mediaPfad;
var katUrl;
var selTitel;
var katName;
this.init = function () {
self.mediaPfad = '/';
self.ortPfad = '/';
self.cache = new Array();
self.appMenu = new AppMenu();
self.appMenu.init(
"data/menu/",
"hauptmenue.json",
"data/tpl/app-menu.txt",
".west",
"8em");
document.querySelector('.hamburger').addEventListener('click', function (e) {
self.menue_umschalten();
});
self.addEvtListener('#mi-katalog', 'click', self.media_liste);
self.addEvtListener('#mi-orte', 'click', self.ablageort_liste);
self.addEvtListener('#mi-prefs', 'click', self.prefs_liste);
self.addEvtListener('#mi-player', 'click', self.abspieler_liste);
self.addEvtListener('#mi-listen', 'click', self.abspielliste_liste);
self.addEvtListener('#mi-list', 'click', self.titel_liste);
self.fusszeile_umschalten();
self.seitenleiste_umschalten();
self.dialog_unten_zeigen();
};
/* ---------------- Entitaets-Listen ----------------- */
// auf der obersten Ebene werden die Kataloge angezeigt,
// darunter der Inhalt des aktuellen Pfades
this.media_liste = function() {
self.reset_top_buttons();
//console.log("ortPfad: " + self.ortPfad + ", mediaPfad: " + self.mediaPfad);
document.querySelector('.bereich-name').textContent = '';
if(self.ortPfad === '/') {
var bb = document.querySelector('.breadcrumb-behaelter');
bb.textContent = "Kataloge";
// Kataloge listen
self.http_get('../api/store/Ablageort/liste/', function (responseText) {
//document.querySelector('#top-up-btn').removeEventListener('click', self.media_liste_herauf);
self.vorlage_laden_und_fuellen("data/tpl/katalog_root_liste.txt", JSON.parse(responseText), function (html) {
document.querySelector(".zentraler-inhalt").innerHTML = html;
self.addEvtListener('.entity-eintrag', 'click', function (event) {
var t = event.target;
self.katName = t.textContent;
self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
var ablageort = JSON.parse(responseText);
self.ortPfad = ablageort.url;
self.media_liste();
});
});
});
});
} else {
var bb = document.querySelector('.breadcrumb-behaelter');
var brPfad = self.katName + self.mediaPfad;
var breadcrumbs = brPfad.split('/');
var brLinks = "";
var brLinkPfad = "";
for(var index = 0; index < breadcrumbs.length; index++) {
// breadcrumbs[index]
if(index === 0) {
brLinkPfad = '/';
} else {
brLinkPfad = brLinkPfad + '/' + breadcrumbs[index];
}
brLinks = brLinks + "" + breadcrumbs[index] + "";
//console.log(' breadcrumbs[' + index + ']: ' + breadcrumbs[index]);
}
bb.innerHTML = brLinks;
self.addEvtListener('.breadcrumb-link', 'click', function(event) {
//console.log(event.target.attributes.brlink.nodeValue);
var neuerPfad = event.target.attributes.brlink.nodeValue;
self.mediaPfad = neuerPfad;
self.media_liste();
});
var url = '..' + self.ortPfad + self.mediaPfad;
if(!url.endsWith('/')) {
url = url + '/';
}
self.http_get(url, function(responseText) {
self.vorlage_laden_und_fuellen("data/tpl/katalog_inhalt_liste.txt", JSON.parse(responseText), function (html) {
document.querySelector(".zentraler-inhalt").innerHTML = html;
self.addEvtListener('.entity-eintrag', 'click', function (event) {
var t = event.target;
var tx = t.textContent;
if(t.classList.contains("entity-typ-folder")) {
if(self.mediaPfad.endsWith('/')) {
self.mediaPfad = self.mediaPfad + tx;
} else {
self.mediaPfad = self.mediaPfad + '/' + tx;
}
self.media_liste();
} else {
if(t.classList.contains('selected')) {
t.classList.add('added-to-playlist');
self.titelDazu();
} else {
self.removeClassMulti('selected');
t.classList.add('selected');
}
//self.selTitel = new Titel(t.textContent, self.ortPfad);
}
});
self.addEvtListener('#top-up-btn', 'click', function(event) {
if(self.mediaPfad === '/') {
self.ortPfad = '/';
} else {
var pos = self.mediaPfad.lastIndexOf('/');
var parent;
if(pos > 1) {
parent = self.mediaPfad.substring(0, pos);
} else {
parent = '/';
}
self.mediaPfad = parent;
}
self.media_liste();
});
});
});
}
};
this.ablageort_liste = function() {
self.entitaet_liste('Kataloge','../api/store/Ablageort/liste/',
"data/tpl/ablageort_liste.txt", '../api/store/Ablageort/',
"self.ablageort_form", function(responseText) {
var ablageort = JSON.parse(responseText);
self.ablageort_form(ablageort);
});
};
this.prefs_liste = function() {
self.entitaet_liste('Einstellungen','../api/store/Einstellung/liste/',
"data/tpl/einstellung_liste.txt", '../api/store/Einstellung/',
"self.prefs_form", function(responseText) {
var einstellung = JSON.parse(responseText);
self.prefs_form(einstellung);
});
};
this.abspieler_liste = function() {
self.entitaet_liste('Abspieler','../api/store/Abspieler/liste/',
"data/tpl/abspieler_liste.txt", '../api/store/Abspieler/',
"self.abspieler_form", function(responseText) {
var abspieler = JSON.parse(responseText);
self.abspieler_form(abspieler);
});
};
this.abspielliste_liste = function() {
self.entitaet_liste('Abspielliste','../api/store/Abspielliste/liste/',
"data/tpl/abspielliste_liste.txt", '../api/store/Abspielliste/',
"self.abspielliste_form", function(responseText) {
//console.log("responseTest: '" + responseText + "'");
var abspielliste = JSON.parse(responseText);
self.abspielliste_form(abspielliste);
});
};
/* -------------------- Entitaets-Formulare ------------------ */
this.abspielliste_form = function(al) {
self.entitaet_form('Abspielliste', al, al.name,
"data/tpl/form_abspielliste.txt", '../api/store/Abspielliste/',
'#abspielliste-name', function(event) {
if(event !== undefined) {
event.preventDefault();
}
self.abspielliste_auswahl_fuellen();
self.abspielliste_liste();
});
};
this.abspieler_form = function(pl) {
self.entitaet_form('Abspieler', pl, pl.key,
"data/tpl/form_abspieler.txt", '../api/store/Abspieler/',
'#abspieler-name', function() {
self.abspieler_auswahl_fuellen();
self.abspieler_liste();
});
};
this.prefs_form = function(k) {
self.entitaet_form('Einstellung', k, k.key,
"data/tpl/form_einstellung.txt", '../api/store/Einstellung/',
'#einstellung-key', function() {
self.prefs_liste();
});
};
/*
* Ablageort-Formular anzeigen
*
* {"name":"Katalog 2","ort":"/home/ulrich/Videos","url":"/media/kat2"}:
*
* @param {type} ablageort der Ablageort, der bearbeitet werden soll, leer fuer neuen Ort
* @returns {undefined} kein Rueckgabewert
*/
this.ablageort_form = function(ort) {
self.entitaet_form('Katalog', ort, ort.name,
"data/tpl/form_ablageort.txt", '../api/store/Ablageort/',
'#ablageort-name', function() {
self.ablageort_liste();
});
};
/* ------------------------------- UI-Dynamik ----------------------- */
self.reset_top_buttons = function() {
self.vorlage_laden_und_fuellen("data/tpl/top_btns.txt", '', function (html) {
document.querySelector(".top-btns").innerHTML = html;
});
};
this.abspieler_auswahl_fuellen = function() {
self.http_get('../api/store/Abspieler/liste/', function (responseText) {
self.vorlage_laden_und_fuellen("data/tpl/abs_sel.txt", JSON.parse(responseText), function (html) {
document.querySelector(".abs-sel").innerHTML = html;
});
});
};
this.abspielliste_auswahl_fuellen = function() {
self.http_get('../api/store/Abspielliste/', function (responseText) {
self.vorlage_laden_und_fuellen("data/tpl/pl_sel.txt", JSON.parse(responseText), function (html) {
document.querySelector(".pl-sel").innerHTML = html;
self.addEvtListener('#playlist', 'change', function() {
self.titel_liste();
});
});
});
};
/* Unterer Einblendbereich */
this.dialog_unten_zeigen = function() {
self.vorlage_laden_und_fuellen("data/tpl/ctrl.txt", "", function (html) {
var dlg = document.querySelector(".dialog-unten");
dlg.style.height = '4.5em';
dlg.innerHTML = html;
self.abspieler_auswahl_fuellen();
self.abspielliste_auswahl_fuellen();
self.addEvtListener('#dazu-btn', 'click', self.titelDazu);
self.addEvtListener('#play-btn', 'click', self.play);
self.addEvtListener('#stop-btn', 'click', function() {
self.kommando('stop');
});
self.addEvtListener('#pause-btn', 'click', function() {
self.kommando('pause');
});
self.addEvtListener('#weiter-btn', 'click', function() {
self.kommando('weiter');
});
/*
*/
self.addEvtListener('#weg-btn', 'click', self.titelWeg);
self.addEvtListener('#leeren-btn', 'click', self.alleTitelEntfernen);
self.media_liste();
});
};
/* Titel einer Abspielliste */
this.titel_liste = function() {
self.reset_top_buttons();
var plname = document.querySelector('#playlist').value;
document.querySelector('.bereich-name').textContent = 'Abspielliste ' + plname;
var bb = document.querySelector('.breadcrumb-behaelter');
bb.textContent = "";
self.http_get('../api/alist/' + plname, function (responseText) {
self.vorlage_laden_und_fuellen("data/tpl/titel_liste.txt", JSON.parse(responseText), function (html) {
document.querySelector(".zentraler-inhalt").innerHTML = html;
self.addEvtListener('.entity-eintrag', 'click', function (event) {
var t = event.target;
self.removeClassMulti('selected');
t.classList.add('selected');
});
});
});
};
/* ------------- Media-Steuerung ------------------------- */
this.play = function() {
var abs = document.querySelector('#abspieler').value;
var lst = document.querySelector('#playlist').value;
console.log(
"play playlist.value: " + document.querySelector('#playlist').value +
", abspieler.value: " + document.querySelector('#abspieler').value);
self.http_get('../api/strg/' + abs + '/play/liste/' + lst, function(responseText) {
self.meldung_mit_timeout(responseText, 1500);
});
};
this.kommando = function(kommando) {
var abs = document.querySelector('#abspieler').value;
self.http_get('../api/strg/' + abs + '/' + kommando, function(responseText) {
self.meldung_mit_timeout(responseText, 1500);
});
};
/* ------------- Verwaltungsfunktionen Abspielliste -------------------- */
self.alleTitelEntfernen = function() {
var plname = document.querySelector('#playlist').value;
self.http_delete('../api/alist/' + plname + '/alle', '', function(responseText) {
// DELETE http://localhost:9090/mz/api/alist/liste1/0
//self.meldung_mit_timeout(responseText, 1500);
self.titel_liste();
});
};
this.titelDazu = function() {
var elem = document.querySelector(".selected");
//var titelName = elem.textContent;
var titelName = elem.attributes.dateiName.nodeValue;
var album = elem.attributes.album.nodeValue;
var interpret = elem.attributes.interpret.nodeValue;
var anzName = elem.attributes.titelAnzName.nodeValue;
var titel;
if(self.mediaPfad.endsWith('/')) {
titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
} else {
titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
}
var plname = document.querySelector('#playlist').value;
self.http_put('../api/alist/' + plname, JSON.stringify(titel), function(responseText) {
//self.meldung_mit_timeout(responseText, 1500);
});
};
this.titelWeg = function() {
var elem = document.querySelector(".selected");
var parentElem = elem.parentNode;
//console.log("elem: " + elem.nodeName + ", parent: " + parentElem.nodeName + ", len: " + parentElem.childNodes.length);
var liElems = parentElem.getElementsByTagName(elem.nodeName); // nur die LI Elemente
//console.log("liElems.anz: " + liElems.length);
var gefunden = false;
for(var i = 0; i < liElems.length && !gefunden; i++) {
//console.log(liElems.item(i).textContent);
if(liElems.item(i).classList.contains("selected")) {
gefunden = true;
var index = i;
//console.log(elem.textContent + ' hat Index ' + i);
}
}
// /mz/api/alist/[pl-name]/[nr]
var plname = document.querySelector('#playlist').value;
self.http_delete('../api/alist/' + plname + '/' + index,'', function(responseText) {
// DELETE http://localhost:9090/mz/api/alist/liste1/0
//self.meldung_mit_timeout(responseText, 1500);
self.titel_liste();
});
};
/* ------------- Helfer fuer Entitaets-Formulare ----------------------- */
/*
* url: '../api/store/Ablageort/liste/'
* tpl: "data/tpl/ablageort_liste.txt"
* storeUrl: '../api/store/Ablageort/'
* formFunc: "self.ablageort_form"
* cb: etwas wie
* function(responseText){
* var ablageort = JSON.parse(responseText);
* self.ablageort_form(ablageort);
* });
*/
this.entitaet_liste = function(bname, listUrl, tpl, storeUrl, formFunc, cb) {
self.reset_top_buttons();
document.querySelector('.bereich-name').textContent = bname;
var bb = document.querySelector('.breadcrumb-behaelter');
bb.textContent = "";
self.http_get(listUrl, function (responseText) {
self.vorlage_laden_und_fuellen(tpl, JSON.parse(responseText), function (html) {
document.querySelector(".zentraler-inhalt").innerHTML = html;
self.addEvtListener('.entity-eintrag', 'click', function (event) {
var t = event.target;
self.http_get(storeUrl + t.textContent, cb);
});
//self.addEvtListener('#neu-btn', 'click', function (event) {
self.addEvtListener('#top-neu-btn', 'click', function(event) {
eval(formFunc + "(this)");
});
});
});
};
/*
* dat: gefuelltes Datenobjekt bei Aenderung
* key: der alte schluesselbegriff bei Aenderung (z.B. al.name)
* tpl: "data/tpl/form_abspielliste.txt"
* url: '../api/store/Abspielliste/'
* selector: '#abspielliste-name'
* cbOk: etwas wie
* function() {
* self.abspielliste_auswahl_fuellen();
* self.abspielliste_liste();
* });
* delSelector: '#abspielliste-name'
* cbDel: etwas wie
* function() {
* self.abspielliste_auswahl_fuellen();
* self.abspielliste_liste();
* });
*/
this.entitaet_form = function(bname, dat, key, tpl, url, selector, cb) {
document.querySelector('.bereich-name').textContent = bname;
self.vorlage_laden_und_fuellen(tpl, dat, function (html) {
document.querySelector(".zentraler-inhalt").innerHTML = html;
const form = document.querySelector('form');
form.addEventListener('submit', function(event) {
self.handle_submit(event, key, url, selector, cb);
});
self.addEvtListener('#cancel-btn', 'click', cb);
self.addEvtListener('#loeschen-btn', 'click', function(event) {
event.preventDefault();
self.handle_del_btn(selector, url, cb);
});
});
};
/*
* existingKey: wenn die Entitaet existiert und geandert werden soll
* leer, wenn neue Entitaet
*/
this.handle_submit = function(event, existingKey, putUrl, keySelector, cb) {
event.preventDefault();
const data = new FormData(event.target);
const value = Object.fromEntries(data.entries());
//console.log({ value });
//console.log(JSON.stringify(value));
var daten = JSON.stringify(value);
var formkey = document.querySelector(keySelector).value;
formkey = formkey.replace(' ', '').replace(/[\W]+/g, '');
if(typeof existingKey === "undefined" || existingKey.length < 1) {
// neu
self.http_put(putUrl + formkey, daten, function (responseText) {
if(typeof(cb) !== 'function') {
// ..
} else {
cb();
}
});
} else {
// aendern
self.http_put(putUrl + existingKey, daten, function (responseText) {
if(typeof(cb) !== 'function') {
// ..
} else {
cb();
}
});
}
};
this.handle_del_btn = function(selectorKey, delUrl, cb) {
var pkey = document.querySelector(selectorKey).value;
var dlgdata = {"del-elem": pkey};
self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.txt', dlgdata, function() {
self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
self.addEvtListener('#ja-btn', 'click', function(event) {
//console.log("loeschen geklickt.");
self.http_delete(delUrl + pkey, '', function (responseText) {
self.dialog_schliessen();
if(typeof(cb) !== 'function') {
// ..
} else {
cb();
}
});
});
});
};
/* ------------------ sonstige Helfer ----------------------- */
this.addEvtListener = function(selector, eventName, func) {
document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
};
this.removeClassMulti = function(selector) {
document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); });
};
/* --------------------- asynchroner HTTP Client ----------------- */
this.http_get = function (u, cb) {
self.http_call('GET', u, null, cb);
};
this.http_post = function (u, data, cb) {
self.http_call('POST', u, data, cb);
};
this.http_put = function (u, data, cb) {
self.http_call('PUT', u, data, cb);
};
this.http_delete = function (u, data, cb) {
// console.log("delete " + u);
self.http_call('DELETE', u, data, cb);
};
this.http_call = function (method, u, data, scallback) {
var xhr = new XMLHttpRequest();
var url = u;
xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
scallback(this.responseText);
}
};
xhr.open(method, url);
if (method === 'GET') {
xhr.send();
} else if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(data);
}
};
/* ------------------------ aus App-Vorlage ------------------- */
this.menue_umschalten = function () {
var ham = document.querySelector(".hamburger");
ham.classList.toggle("is-active"); // hamburger-icon umschalten
self.appMenu.toggle(); // menue oeffnen/schliessen
};
this.info_dialog_zeigen = function () {
self.dialog_laden_und_zeigen('data/tpl/dlg-info.txt', '');
self.menue_umschalten();
};
this.seitenleiste_umschalten = function () {
var ostDiv = document.querySelector('.ost');
if (ostDiv.classList.contains('ost-open')) {
ostDiv.classList.remove('ost-open');
ostDiv.style.flexBasis = '0em';
} else {
ostDiv.classList.add('ost-open');
ostDiv.style.flexBasis = '6em';
}
self.menue_umschalten();
};
this.fusszeile_umschalten = function () {
var suedDiv = document.querySelector('.sued');
if (suedDiv.classList.contains('sued-open')) {
suedDiv.classList.remove('sued-open');
suedDiv.style.height = '0';
} else {
suedDiv.classList.add('sued-open');
suedDiv.style.height = '1.5em';
}
self.menue_umschalten();
};
this.menu_message = function (msg) {
self.meldung_mit_timeout(msg, 1500);
var suedDiv = document.querySelector('.sued');
if (suedDiv.classList.contains('sued-open')) {
} else {
suedDiv.classList.add('sued-open');
suedDiv.style.height = '1.5em';
}
self.menue_umschalten();
};
this.message_1 = function () {
self.menu_message('Eine Mitteilung.');
};
this.message_2 = function () {
self.menu_message('Was wir schon immer sagen wollten.');
};
this.message_3 = function (text) {
self.menu_message(text);
};
this.meldung_mit_timeout = function (meldung, timeout) {
var s = document.querySelector('.sued');
s.classList.add('sued-open');
s.style.height = '1.5em';
s.textContent = meldung;
setTimeout(function () {
s.textContent = 'Bereit.';
setTimeout(function () {
var suedDiv = document.querySelector('.sued');
if (suedDiv.classList.contains('sued-open')) {
suedDiv.classList.remove('sued-open');
suedDiv.style.height = '0';
}
}, 500);
}, timeout);
};
/* --------------------- Dialog-Funktionen ------------------------ */
/*
Einen Dialog aus Vorlagen erzeugen
vurl - URL zur Dialogvorlage
msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
*/
this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
var vorlage = self.cache[vurl];
if(vorlage === undefined) {
self.http_get(vurl, function(antwort) {
self.cache[vurl] = antwort;
self.dialog_zeigen(vurl, msgTpl, cb);
});
} else {
self.dialog_zeigen(vurl, msgTpl, cb);
}
};
this.dialog_zeigen = function (vurl, inhalt, cb) {
var dlg = document.querySelector(".dialog");
self.html_erzeugen(vurl, inhalt, function (html) {
dlg.style.height = '7em';
dlg.innerHTML = html;
document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
if(typeof(cb) !== 'function') {
// ..
} else {
cb();
}
});
};
this.dialog_schliessen = function () {
document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
var dlg = document.querySelector('.dialog');
dlg.style.height = '0';
dlg.innerHTML = '';
};
/* --------------------- Vorlagen ---------------------- */
/*
Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt
gefüllt wird
Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem
Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten.
Das fertige HTML wird der Callback-Funktion übergeben
sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der
Programmlauf zu diesem Zeitpunkt mittlerweile ist.
vurl - URL zur Vorlagendatei
inhalt - die JSON-Struktur, deren Inhalt in die
Vorlage gefüllt werden soll
cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist.
Dieser Callback-Funktion wird das fertige HTML übergeben
*/
this.html_erzeugen = function (vurl, inhalt, cb) {
var vorlage = self.cache[vurl];
if (vorlage === undefined) {
self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
} else {
self.vorlage_fuellen(vurl, inhalt, cb);
}
};
this.vorlage_fuellen = function (vurl, inhalt, cb) {
cb(Mustache.render(self.cache[vurl], inhalt));
};
/*
Eine Vorlage vom Server in den lokalen Speicher laden
vurl - der URL unter dem die Vorlage zu finden ist
inhalt - die JSON-Struktur, deren Inhalt in die
Vorlage gefüllt werden soll
cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem
Inhalt gefüllt ist
*/
this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
self.cache[vurl] = this.responseText;
self.vorlage_fuellen(vurl, inhalt, cb);
}
};
xmlhttp.open("GET", vurl, true);
xmlhttp.send();
};
}
/* ----------- Objekte ---------------- */
function Ablageort(n, o, u) {
this.name = n;
this.ort = o;
this.url = u;
}
function Einstellung(k, v) {
this.key = k;
this.value = v;
}
function Abspieler(n, u) {
this.name = n;
this.url = u;
}
function Abspielliste(n) {
this.name = n;
}
function Titel(n, p, u, i, t, a) {
this.katalogUrl = u;
this.pfad = p;
this.name = n;
this.interpret = i;
this.titelAnzName = t;
this.album = a;
}