Persoenliche Mediazentrale
ulrich
2021-04-09 71def106dcac230c9f39f5c117ad5e275ac00d5d
commit | author | age
b379f5 1 function Mediazentrale() {
cfa858 2   var self = this;
U 3   var appMenu;
4   var cache; // mustache templates
86bbf7 5   var ortPfad;
U 6   var mediaPfad;
e60cff 7   var katUrl;
U 8   var selTitel;
f45e20 9
U 10   this.init = function () {
11     self.mediaPfad = '/';
12     self.ortPfad = '/';
13     self.cache = new Array();
14     self.appMenu = new AppMenu();
15     self.appMenu.init(
16             "data/menu/",
17             "hauptmenue.json",
18             "data/tpl/app-menu.tpl",
19             ".west",
20             "8em");
21
22     document.querySelector('.hamburger').addEventListener('click', function (e) {
23       self.menue_umschalten();
24     });
25     
26     self.addEvtListener('#mi-katalog', 'click', self.media_liste);
27     self.addEvtListener('#mi-orte', 'click', self.ablageort_liste);
28     self.addEvtListener('#mi-prefs', 'click', self.prefs_liste);
29     self.addEvtListener('#mi-player', 'click', self.abspieler_liste);
8d7d35 30     self.addEvtListener('#mi-listen', 'click', self.abspielliste_liste);
U 31     self.addEvtListener('#mi-list', 'click', self.titel_liste);
f45e20 32     
U 33     self.fusszeile_umschalten();
34     self.seitenleiste_umschalten();
35     self.dialog_unten_zeigen();
36   };
37   
71def1 38   /*
U 39    * Der StorageHandler verarbeitet Entitaeten mit z.B. 
40    * HTTP PUT Ablageort/[Name]
41    * und erwartet dabei eine JSON-Struktur, die der Entitaet entspricht. 
42    * Beim Ablageort z.B.
43    *   private String name;
44    *   private String ort;
45    *   private String url;
46    *   
47    * Im HTML-Formular muessen die input-Elemente mit name="..." 
48    * so genannt werden wie die Felder der Entitaet. Fuer Ablageort also
49    * 
50    *   <input name="name" 
51    *   <input name="ort" 
52    *   <input name="url" 
53    * 
54    * Auf diese Weise kann eine generische Funktion die Formulardaten 
55    * an den REST-Endpunkt des Servers uebermitteln.
56    */  
57   this.test_form = function() {
58     self.vorlage_laden_und_fuellen("data/tpl/test_form.tpl", "", function (html) {
59       document.querySelector(".zentraler-inhalt").innerHTML = html;
60       const form = document.querySelector('form');
61       form.addEventListener('submit', self.handleSubmit);
62     });    
63   };
64
65   this.handleSubmit = function(event) {
66     event.preventDefault();
67     const data = new FormData(event.target);
68     const value = Object.fromEntries(data.entries());
69     console.log({ value });
70     console.log(JSON.stringify(value));
71   };
72   
73   
f45e20 74   this.abspieler_auswahl_fuellen = function() {
U 75     self.http_get('../api/store/Abspieler/', function (responseText) {
76       /*
77        {"ArrayList": [{"name":"Wohnz","url":"http://rpi4-wz:9090/"},{"name":"Arbz","url":"http://rpi4-az:9090/"}]}
78        */
79       self.vorlage_laden_und_fuellen("data/tpl/abs_sel.tpl", JSON.parse(responseText), function (html) {
80         document.querySelector(".abs-sel").innerHTML = html;
81       });    
82     });
83   };
84
8d7d35 85   this.abspielliste_auswahl_fuellen = function() {
U 86     self.http_get('../api/store/Abspielliste/', function (responseText) {
87       /*
88           ?
89        */
90       self.vorlage_laden_und_fuellen("data/tpl/pl_sel.tpl", JSON.parse(responseText), function (html) {
91         document.querySelector(".pl-sel").innerHTML = html;
92       });    
93     });
94   };
95   
f45e20 96   /* Unterer Einblendbereich */
U 97   
98   this.dialog_unten_zeigen = function() {
99     self.vorlage_laden_und_fuellen("data/tpl/ctrl.tpl", "", function (html) {
100       var dlg = document.querySelector(".dialog-unten");
101       dlg.style.height = '4.5em';
102       dlg.innerHTML = html;
103       self.abspieler_auswahl_fuellen();
8d7d35 104       self.abspielliste_auswahl_fuellen();
e60cff 105       self.addEvtListener('#dazu-btn', 'click', self.addSelectedTitel);
8d7d35 106       self.media_liste();
f45e20 107     });
U 108   };
109
8d7d35 110   /* ---------------- Titel einer Abspielliste ----------------- */
U 111   
112   this.titel_liste = function() {
fcc734 113     self.reset_top_buttons();
U 114     var plname = document.querySelector('#playlist').value;
115     self.http_get('../api/alist/' + plname, function (responseText) {
116       self.vorlage_laden_und_fuellen("data/tpl/titel_liste.tpl", JSON.parse(responseText), function (html) {
8d7d35 117         document.querySelector(".zentraler-inhalt").innerHTML = html;
U 118         self.addEvtListener('.entity-eintrag', 'click', function (event) {
119           var t = event.target;
fcc734 120           self.removeClassMulti('selected');
U 121           t.classList.add('selected');
122
123           /*
8d7d35 124           self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText){
U 125             var ablageort = JSON.parse(responseText);
126             self.ablageort_form(ablageort);
127           });
fcc734 128           */
8d7d35 129         });
fcc734 130         /*
8d7d35 131         self.addEvtListener('#neu-btn', 'click', function (event) {
U 132           eval("self.ablageort_form" + "(this)");
fcc734 133         });
U 134         */
8d7d35 135       });
U 136     });
137   };
138     
139   /* ---------------- Entitaets-Listen ----------------- */
140
141   self.reset_top_buttons = function() {
142     self.vorlage_laden_und_fuellen("data/tpl/top_btns.tpl", '', function (html) {
143       document.querySelector(".top-btns").innerHTML = html;
144     });
145   };
86bbf7 146   
U 147   // auf der obersten Ebene werden die Kataloge angezeigt,
148   // darunter der Inhalt des aktuellen Pfades
149   this.media_liste = function() {
8d7d35 150     self.reset_top_buttons();
86bbf7 151     if(self.ortPfad === '/') {
U 152       // Kataloge listen
f45e20 153       self.http_get('../api/store/Ablageort/liste/', function (responseText) {
8d7d35 154         //document.querySelector('#top-up-btn').removeEventListener('click', self.media_liste_herauf);
86bbf7 155         self.vorlage_laden_und_fuellen("data/tpl/katalog_root_liste.tpl", JSON.parse(responseText), function (html) {
U 156           document.querySelector(".zentraler-inhalt").innerHTML = html;
157           self.addEvtListener('.entity-eintrag', 'click', function (event) {
158             var t = event.target;
159             self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
160               var ablageort = JSON.parse(responseText);
161               self.ortPfad = ablageort.url;
162               self.media_liste();
163             });
164           });
165         });
166       });
167     } else {
3271f1 168       var url = '..' + self.ortPfad + self.mediaPfad;
U 169       if(!url.endsWith('/')) {
170         url = url + '/';
171       }
172       self.http_get(url, function(responseText) {
86bbf7 173         self.vorlage_laden_und_fuellen("data/tpl/katalog_inhalt_liste.tpl", JSON.parse(responseText), function (html) {
U 174           document.querySelector(".zentraler-inhalt").innerHTML = html;
175           self.addEvtListener('.entity-eintrag', 'click', function (event) {
176             var t = event.target;
3271f1 177             var tx = t.textContent;
86bbf7 178             if(t.classList.contains("entity-typ-folder")) {
3271f1 179               if(self.mediaPfad.endsWith('/')) {
U 180                 self.mediaPfad = self.mediaPfad + tx;                
181               } else {
182                 self.mediaPfad = self.mediaPfad + '/' + tx;
183               }
86bbf7 184               self.media_liste();
U 185             } else {
37eadf 186               if(t.classList.contains('selected')) {
U 187                 self.addSelectedTitel();
188               } else {
189                 self.removeClassMulti('selected');
190                 t.classList.add('selected');
191               }
e60cff 192               //self.selTitel = new Titel(t.textContent, self.ortPfad);       
86bbf7 193             }
U 194           });
8d7d35 195           self.addEvtListener('#top-up-btn', 'click', function(event) {
86bbf7 196             if(self.mediaPfad === '/') {
U 197               self.ortPfad = '/';              
198             } else {
199               var pos = self.mediaPfad.lastIndexOf('/');
3271f1 200               var parent;
U 201               if(pos > 1) {
202                 parent = self.mediaPfad.substring(0, pos);
203               } else {
204                 parent = '/';
205               }
86bbf7 206               self.mediaPfad = parent;
U 207             }
208             self.media_liste();
8d7d35 209           });
86bbf7 210         });
U 211       });
212     }
e60cff 213   };
245ac1 214   
e60cff 215   this.addSelectedTitel = function() {
245ac1 216     var elem = document.querySelector(".selected");
U 217     var titelName = elem.textContent;
218     var album = elem.attributes.album.nodeValue;
219     var interpret = elem.attributes.interpret.nodeValue;
220     var anzName = elem.attributes.titelAnzName.nodeValue;
fcc734 221     var titel;
U 222     if(self.mediaPfad.endsWith('/')) {
245ac1 223       titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
fcc734 224     } else {
245ac1 225       titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
fcc734 226     }
e60cff 227     var plname = document.querySelector('#playlist').value;
U 228     self.http_put('../api/alist/' + plname, JSON.stringify(titel), function(responseText) {
8e2578 229       self.meldung_mit_timeout(responseText, 1500);
e60cff 230     });
86bbf7 231   };
cfa858 232
a43e1a 233   this.ablageort_liste = function() {
8d7d35 234     self.reset_top_buttons();
f45e20 235     self.http_get('../api/store/Ablageort/liste/', function (responseText) {
a43e1a 236       self.vorlage_laden_und_fuellen("data/tpl/ablageort_liste.tpl", JSON.parse(responseText), function (html) {
U 237         document.querySelector(".zentraler-inhalt").innerHTML = html;
238         self.addEvtListener('.entity-eintrag', 'click', function (event) {
239           var t = event.target;
90f5d4 240           self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText){
86bbf7 241             var ablageort = JSON.parse(responseText);
90f5d4 242             self.ablageort_form(ablageort);
U 243           });
a43e1a 244         });
8d7d35 245         //self.addEvtListener('#neu-btn', 'click', function (event) {
U 246         self.addEvtListener('#top-neu-btn', 'click', function(event) {
faab2d 247           eval("self.ablageort_form" + "(this)");
U 248         });        
cf6509 249       });
U 250     });
251   };
252
253   this.prefs_liste = function() {
8d7d35 254     self.reset_top_buttons();
f45e20 255     self.http_get('../api/store/Einstellung/liste/', function (responseText) {
cf6509 256       self.vorlage_laden_und_fuellen("data/tpl/einstellung_liste.tpl", JSON.parse(responseText), function (html) {
U 257         document.querySelector(".zentraler-inhalt").innerHTML = html;
258         self.addEvtListener('.entity-eintrag', 'click', function (event) {
259           var t = event.target;
260           self.http_get('../api/store/Einstellung/' + t.textContent, function(responseText){
261             var einstellung = JSON.parse(responseText);
262             self.prefs_form(einstellung);
263           });
264         });
8d7d35 265         self.addEvtListener('#top-neu-btn', 'click', function(event) {
cf6509 266           eval("self.prefs_form" + "(this)");
U 267         });        
268       });
269     });
270   };
271
3d4bca 272   this.abspieler_liste = function() {
f45e20 273     self.http_get('../api/store/Abspieler/liste/', function (responseText) {
3d4bca 274       self.vorlage_laden_und_fuellen("data/tpl/abspieler_liste.tpl", JSON.parse(responseText), function (html) {
U 275         document.querySelector(".zentraler-inhalt").innerHTML = html;
276         self.addEvtListener('.entity-eintrag', 'click', function (event) {
277           var t = event.target;
278           self.http_get('../api/store/Abspieler/' + t.textContent, function(responseText){
279             var abspieler = JSON.parse(responseText);
280             self.abspieler_form(abspieler);
281           });
282         });
8d7d35 283         self.addEvtListener('#neu-btn', 'click', function(event) {
3d4bca 284           eval("self.abspieler_form" + "(this)");
8d7d35 285         });           
U 286       });
287     });
288   };
289   
290   this.abspielliste_liste = function() {
291     self.http_get('../api/store/Abspielliste/liste/', function (responseText) {
292       self.vorlage_laden_und_fuellen("data/tpl/abspielliste_liste.tpl", JSON.parse(responseText), function (html) {
293         document.querySelector(".zentraler-inhalt").innerHTML = html;
294         self.addEvtListener('.entity-eintrag', 'click', function (event) {
295           var t = event.target;
296           self.http_get('../api/store/Abspielliste/' + t.textContent, function(responseText){
297             var abspielliste = JSON.parse(responseText);
298             self.abspielliste_form(abspielliste);
299           });
300         });
301         self.addEvtListener('#top-neu-btn', 'click', function(event) {
302           eval("self.abspielliste_form" + "(this)");
303         });            
304       });
305     });
306   };
307   
308   /* -------------------- Entitaets-Formulare ------------------ */
309   
310   this.abspielliste_form = function(al) {
311     self.vorlage_laden_und_fuellen("data/tpl/form_abspielliste.tpl", al, function (html) {
312       document.querySelector(".zentraler-inhalt").innerHTML = html;
313       self.addEvtListener('#ok-btn', 'click', function () {
314         var alname = document.querySelector('#abspielliste-name').value;
315         alname = alname.replace(' ', '').replace(/[\W]+/g, '');
316         var abspielliste = new Abspielliste(
317           alname
318         );
319         var daten = JSON.stringify(abspielliste);        
320         //if(typeof pl === "undefined" || pl.key !== plname) {
321         if(typeof al.name === "undefined" || al.name.length < 1) {
322           // neu
323           self.http_put('../api/store/Abspielliste/' + alname, daten, function (responseText) {
324             // hier die Antwort verarbeiten
325             self.abspielliste_auswahl_fuellen();
326             self.abspielliste_liste();
327           });
328         } else {
329           // aendern
330           self.http_put('../api/store/Abspielliste/' + al.name, daten, function (responseText) {
331             // hier die Antwort verarbeiten
332             self.abspielliste_auswahl_fuellen();
333             self.abspielliste_liste();
334           });
335         }
336       });
337       self.addEvtListener('#cancel-btn', 'click', function () {
338         //document.querySelector(".zentraler-inhalt").innerHTML = '';
339         self.abspielliste_liste();
340       });
341       self.addEvtListener('#loeschen-btn', 'click', function() {
342         var alname = document.querySelector('#abspielliste-name').value;
343         var dlgdata = {"del-elem": alname};
344         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
345           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
346           self.addEvtListener('#ja-btn', 'click', function() {
347             self.http_delete('../api/store/Abspielliste/' + alname, '', function (responseText) {
348               // hier die Antwort verarbeiten
349               self.dialog_schliessen();
350               //document.querySelector(".zentraler-inhalt").innerHTML = '';
351               self.abspielliste_auswahl_fuellen();
352               self.abspielliste_liste();
353             });
354           });
355         });
3d4bca 356       });
U 357     });
358   };
71def1 359   
3d4bca 360   this.abspieler_form = function(pl) {
U 361     self.vorlage_laden_und_fuellen("data/tpl/form_abspieler.tpl", pl, function (html) {
362       document.querySelector(".zentraler-inhalt").innerHTML = html;
363       self.addEvtListener('#ok-btn', 'click', function () {
364         var plname = document.querySelector('#abspieler-name').value;
365         plname = plname.replace(' ', '').replace(/[\W]+/g, '');
366         var abspieler = new Abspieler(
367           plname,
368           document.querySelector('#abspieler-url').value
369         );
370         var daten = JSON.stringify(abspieler);        
dfb7d3 371         //if(typeof pl === "undefined" || pl.key !== plname) {
U 372         if(typeof pl.name === "undefined" || pl.name.length < 1) {
3d4bca 373           // neu
dfb7d3 374           self.http_put('../api/store/Abspieler/' + plname, daten, function (responseText) {
3d4bca 375             // hier die Antwort verarbeiten
dfb7d3 376             self.abspieler_auswahl_fuellen();
U 377             self.abspieler_liste();
3d4bca 378           });
U 379         } else {
380           // aendern
dfb7d3 381           self.http_put('../api/store/Abspieler/' + pl.name, daten, function (responseText) {
3d4bca 382             // hier die Antwort verarbeiten
dfb7d3 383             self.abspieler_auswahl_fuellen();
U 384             self.abspieler_liste();
3d4bca 385           });
U 386         }
387       });
388       self.addEvtListener('#cancel-btn', 'click', function () {
389         //document.querySelector(".zentraler-inhalt").innerHTML = '';
390         self.abspieler_liste();
391       });
392       self.addEvtListener('#loeschen-btn', 'click', function() {
393         var plname = document.querySelector('#abspieler-name').value;
394         var dlgdata = {"del-elem": plname};
395         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
396           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
397           self.addEvtListener('#ja-btn', 'click', function() {
398             self.http_delete('../api/store/Abspieler/' + plname, '', function (responseText) {
399               // hier die Antwort verarbeiten
400               self.dialog_schliessen();
401               //document.querySelector(".zentraler-inhalt").innerHTML = '';
dfb7d3 402               self.abspieler_auswahl_fuellen();
3d4bca 403               self.abspieler_liste();
U 404             });
405           });
406         });
407       });
408     });
409   };
cf6509 410
71def1 411   /*
U 412    * existingKey: wenn die Entitaet existiert und geandert werden soll
413    *                 leer, wenn neue Entitaet 
414    */
415   this.handle_my_submit = function(event, existingKey, putUrl, keySelector) {
416     event.preventDefault();
417     const data = new FormData(event.target);
418     const value = Object.fromEntries(data.entries());
419     console.log({ value });
420     console.log(JSON.stringify(value));
421     var daten = JSON.stringify(value);
422     var formkey = document.querySelector(keySelector).value;
423     formkey = formkey.replace(' ', '').replace(/[\W]+/g, '');
424
425     if(typeof existingKey === "undefined" ||  existingKey.length < 1) {
426       // neu
427       self.http_put(putUrl + formkey, daten, function (responseText) {
428         // hier die Antwort verarbeiten
429         self.prefs_liste();
430       });
431     } else {
432       // aendern
433       self.http_put(putUrl + existingKey, daten, function (responseText) {
434         // hier die Antwort verarbeiten
435         self.prefs_liste();
436       });
437     }
438     
439     
440   };
441
cf6509 442   this.prefs_form = function(k) {
U 443     self.vorlage_laden_und_fuellen("data/tpl/form_einstellung.tpl", k, function (html) {
444       document.querySelector(".zentraler-inhalt").innerHTML = html;
71def1 445       const form = document.querySelector('form');
U 446       form.addEventListener('submit', function(event) {
447         self.handle_my_submit(event, k.key, '../api/store/Einstellung/', '#einstellung-key');
448       });
449       
450       
451       /*
cf6509 452       self.addEvtListener('#ok-btn', 'click', function () {
U 453         var pkey = document.querySelector('#einstellung-key').value;
454         pkey = pkey.replace(' ', '').replace(/[\W]+/g, '');
455         var pref = new Einstellung(
456           pkey,
457           document.querySelector('#einstellung-value').value
458         );
459         var daten = JSON.stringify(pref);        
dfb7d3 460         //if(typeof k === "undefined" || k.key !== pkey) {
U 461         if(typeof k.key === "undefined" ||  k.key.length < 1) {
cf6509 462           // neu
dfb7d3 463           self.http_put('../api/store/Einstellung/' + pkey, daten, function (responseText) {
cf6509 464             // hier die Antwort verarbeiten
dfb7d3 465             self.prefs_liste();
cf6509 466           });
U 467         } else {
468           // aendern
dfb7d3 469           self.http_put('../api/store/Einstellung/' + k.key, daten, function (responseText) {
cf6509 470             // hier die Antwort verarbeiten
dfb7d3 471             self.prefs_liste();
cf6509 472           });
U 473         }
474       });
71def1 475       */
cf6509 476       self.addEvtListener('#cancel-btn', 'click', function () {
U 477         //document.querySelector(".zentraler-inhalt").innerHTML = '';
478         self.prefs_liste();
479       });
480       self.addEvtListener('#loeschen-btn', 'click', function() {
481         var pkey = document.querySelector('#einstellung-key').value;
482         var dlgdata = {"del-elem": pkey};
483         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
484           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
485           self.addEvtListener('#ja-btn', 'click', function() {
486             self.http_delete('../api/store/Einstellung/' + pkey, '', function (responseText) {
487               // hier die Antwort verarbeiten
488               self.dialog_schliessen();
489               //document.querySelector(".zentraler-inhalt").innerHTML = '';
490               self.prefs_liste();
491             });
492           });
493         });
a43e1a 494       });
U 495     });
496   };
cfa858 497
90f5d4 498   /* 
U 499    * Ablageort-Formular anzeigen
500    * 
501    * {"name":"Katalog 2","ort":"/home/ulrich/Videos","url":"/media/kat2"}: 
502    * 
503    * @param {type} ablageort  der Ablageort, der bearbeitet werden soll, leer fuer neuen Ort
504    * @returns {undefined} kein Rueckgabewert
505    */
506   this.ablageort_form = function(ort) {
507     self.vorlage_laden_und_fuellen("data/tpl/form_ablageort.tpl", ort, function (html) {
b379f5 508       document.querySelector(".zentraler-inhalt").innerHTML = html;
f074f6 509       self.addEvtListener('#ok-btn', 'click', function () {
2597cd 510         var aName = document.querySelector('#ablageort-name').value;
U 511         aName = aName.replace(' ', '').replace(/[\W]+/g, '');
b379f5 512         var a = new Ablageort(
2597cd 513           aName,
b379f5 514           document.querySelector('#ablageort-ort').value,
U 515           document.querySelector('#ablageort-url').value
516         );
90f5d4 517         var daten = JSON.stringify(a);        
dfb7d3 518         //if(typeof ort === "undefined" || ort.name !== aName) {
U 519         if(typeof ort.name === "undefined"  || ort.name.length < 1) {
2597cd 520           // neu
dfb7d3 521           self.http_put('../api/store/Ablageort/' + aName, daten, function (responseText) {
90f5d4 522             // hier die Antwort verarbeiten
dfb7d3 523             self.ablageort_liste();
90f5d4 524           });
U 525         } else {
2597cd 526           // aendern
dfb7d3 527           self.http_put('../api/store/Ablageort/' + ort.name, daten, function (responseText) {
90f5d4 528             // hier die Antwort verarbeiten
dfb7d3 529             self.ablageort_liste();
90f5d4 530           });
U 531         }
b379f5 532       });
f074f6 533       self.addEvtListener('#cancel-btn', 'click', function () {
b29119 534         //document.querySelector(".zentraler-inhalt").innerHTML = '';
faab2d 535         self.ablageort_liste();
5b7356 536       });
U 537       self.addEvtListener('#loeschen-btn', 'click', function() {
538         var aoname = document.querySelector('#ablageort-name').value;
539         var dlgdata = {"del-elem": aoname};
540         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
541           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
542           self.addEvtListener('#ja-btn', 'click', function() {
90f5d4 543             self.http_delete('../api/store/Ablageort/' + aoname, '', function (responseText) {
U 544               // hier die Antwort verarbeiten
2597cd 545               self.dialog_schliessen();
b29119 546               //document.querySelector(".zentraler-inhalt").innerHTML = '';
faab2d 547               self.ablageort_liste();
90f5d4 548             });
5b7356 549           });
U 550         });
b379f5 551       });
U 552     });
553   };
554
7c22a2 555   this.addEvtListener = function(selector, eventName, func) {
U 556     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
557   };
558   
559   this.removeClassMulti = function(selector) {
560     document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); });
561   };
562
f45e20 563   /* --------------------- asynchroner HTTP Client ----------------- */
faab2d 564   
f074f6 565   this.http_get = function (u, cb) {
b379f5 566     self.http_call('GET', u, null, cb);
U 567   };
f074f6 568
U 569   this.http_post = function (u, data, cb) {
b379f5 570     self.http_call('POST', u, data, cb);
U 571   };
572
90f5d4 573   this.http_put = function (u, data, cb) {
U 574     self.http_call('PUT', u, data, cb);
575   };
576   
5b7356 577   this.http_delete = function (u, data, cb) {
2597cd 578     console.log("delete " + u);
5b7356 579     self.http_call('DELETE', u, data, cb);
U 580   };
581   
f074f6 582   this.http_call = function (method, u, data, scallback) {
b379f5 583     var xhr = new XMLHttpRequest();
U 584     var url = u;
f074f6 585     xhr.onreadystatechange = function () {
b379f5 586       if (this.readyState === 4 && this.status === 200) {
U 587         scallback(this.responseText);
588       }
589     };
590     xhr.open(method, url);
f074f6 591     if (method === 'GET') {
b379f5 592       xhr.send();
2597cd 593     } else if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
b379f5 594       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
U 595       xhr.send(data);
596     }
597   };
8239d1 598   
f45e20 599   /* ------------------------ aus App-Vorlage -------------------  */
cfa858 600
f074f6 601   this.menue_umschalten = function () {
cfa858 602     var ham = document.querySelector(".hamburger");
U 603     ham.classList.toggle("is-active"); // hamburger-icon umschalten
604     self.appMenu.toggle(); // menue oeffnen/schliessen
605   };
606
f074f6 607   this.info_dialog_zeigen = function () {
cfa858 608     self.dialog_laden_und_zeigen('data/tpl/dlg-info.tpl', '');
U 609     self.menue_umschalten();
610   };
611
f074f6 612   this.seitenleiste_umschalten = function () {
cfa858 613     var ostDiv = document.querySelector('.ost');
f074f6 614     if (ostDiv.classList.contains('ost-open')) {
cfa858 615       ostDiv.classList.remove('ost-open');
f074f6 616       ostDiv.style.flexBasis = '0em';
cfa858 617     } else {
f074f6 618       ostDiv.classList.add('ost-open');
U 619       ostDiv.style.flexBasis = '6em';
cfa858 620     }
U 621     self.menue_umschalten();
622   };
623
f074f6 624   this.fusszeile_umschalten = function () {
cfa858 625     var suedDiv = document.querySelector('.sued');
f074f6 626     if (suedDiv.classList.contains('sued-open')) {
cfa858 627       suedDiv.classList.remove('sued-open');
f074f6 628       suedDiv.style.height = '0';
cfa858 629     } else {
U 630       suedDiv.classList.add('sued-open');
f074f6 631       suedDiv.style.height = '1.5em';
cfa858 632     }
U 633     self.menue_umschalten();
634   };
635
f074f6 636   this.menu_message = function (msg) {
cfa858 637     self.meldung_mit_timeout(msg, 1500);
U 638     var suedDiv = document.querySelector('.sued');
f074f6 639     if (suedDiv.classList.contains('sued-open')) {
cfa858 640     } else {
U 641       suedDiv.classList.add('sued-open');
f074f6 642       suedDiv.style.height = '1.5em';
cfa858 643     }
U 644     self.menue_umschalten();
645   };
646
f074f6 647   this.message_1 = function () {
cfa858 648     self.menu_message('Eine Mitteilung.');
U 649   };
650
f074f6 651   this.message_2 = function () {
cfa858 652     self.menu_message('Was wir schon immer sagen wollten.');
U 653   };
654
f074f6 655   this.message_3 = function (text) {
cfa858 656     self.menu_message(text);
U 657   };
658
f074f6 659   this.meldung_mit_timeout = function (meldung, timeout) {
cfa858 660     var s = document.querySelector('.sued');
a43e1a 661     s.classList.add('sued-open');
U 662     s.style.height = '1.5em';
cfa858 663     s.textContent = meldung;
f074f6 664     setTimeout(function () {
cfa858 665       s.textContent = 'Bereit.';
f074f6 666       setTimeout(function () {
cfa858 667         var suedDiv = document.querySelector('.sued');
f074f6 668         if (suedDiv.classList.contains('sued-open')) {
U 669           suedDiv.classList.remove('sued-open');
670           suedDiv.style.height = '0';
cfa858 671         }
U 672       }, 500);
673     }, timeout);
674   };
8239d1 675   
f45e20 676   /* --------------------- Dialog-Funktionen ------------------------ */
cfa858 677
U 678   /*
f074f6 679    Einen Dialog aus Vorlagen erzeugen
U 680    
681    vurl - URL zur Dialogvorlage
682    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
683    */
5b7356 684   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 685     var vorlage = self.cache[vurl];
686     if(vorlage === undefined) {
687       self.http_get(vurl, function(antwort) {
688         self.cache[vurl] = antwort;
689         self.dialog_zeigen(vurl, msgTpl, cb);
f074f6 690       });
cfa858 691     } else {
5b7356 692       self.dialog_zeigen(vurl, msgTpl, cb);
cfa858 693     }
U 694   };
695
5b7356 696   this.dialog_zeigen = function (vurl, inhalt, cb) {
U 697     var dlg = document.querySelector(".dialog");
2597cd 698     self.html_erzeugen(vurl, inhalt, function (html) {
U 699       dlg.style.height = '7em';
700       dlg.innerHTML = html;
701       document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
702       if(typeof(cb) !== 'function') {
703         // ..
704       } else {
705         cb();
706       }
707     });
5b7356 708   };
2597cd 709   
f45e20 710   this.dialog_schliessen = function () {
cfa858 711     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 712     var dlg = document.querySelector('.dialog');
713     dlg.style.height = '0';
714     dlg.innerHTML = '';
715   };
716
f45e20 717   /* ---------------------   Vorlagen   ---------------------- */
cfa858 718
U 719   /*
f074f6 720    Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt
U 721    gefüllt wird
722    
723    Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem
724    Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten.
725    Das fertige HTML wird der Callback-Funktion übergeben
726    sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der
727    Programmlauf zu diesem Zeitpunkt mittlerweile ist.
728    
729    vurl - URL zur Vorlagendatei
730    inhalt - die JSON-Struktur, deren Inhalt in die
731    Vorlage gefüllt werden soll
732    cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist.
733    Dieser Callback-Funktion wird das fertige HTML übergeben
734    */
735   this.html_erzeugen = function (vurl, inhalt, cb) {
cfa858 736     var vorlage = self.cache[vurl];
f074f6 737     if (vorlage === undefined) {
cfa858 738       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
U 739     } else {
740       self.vorlage_fuellen(vurl, inhalt, cb);
741     }
742   };
743
f074f6 744   this.vorlage_fuellen = function (vurl, inhalt, cb) {
cfa858 745     cb(Mustache.render(self.cache[vurl], inhalt));
U 746   };
747
748   /*
f074f6 749    Eine Vorlage vom Server in den lokalen Speicher laden
U 750    vurl - der URL unter dem die Vorlage zu finden ist
751    inhalt - die JSON-Struktur, deren Inhalt in die
752    Vorlage gefüllt werden soll
753    cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem
754    Inhalt gefüllt ist
755    */
756   this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) {
cfa858 757     var xmlhttp = new XMLHttpRequest();
f074f6 758     xmlhttp.onreadystatechange = function () {
cfa858 759       if (this.readyState == 4 && this.status == 200) {
U 760         self.cache[vurl] = this.responseText;
761         self.vorlage_fuellen(vurl, inhalt, cb);
762       }
763     };
764     xmlhttp.open("GET", vurl, true);
765     xmlhttp.send();
766   };
767
768
769 }
770
f45e20 771 /* ----------- Objekte ---------------- */
U 772
773 function Ablageort(n, o, u) {
774   this.name = n;
775   this.ort = o;
776   this.url = u;
777 }
778
779 function Einstellung(k, v) {
780   this.key = k;
781   this.value = v;
782 }
783
784 function Abspieler(n, u) {
785   this.name = n;
786   this.url = u;
8d7d35 787 }
U 788
789 function Abspielliste(n) {
790   this.name = n;
e60cff 791 }
U 792
245ac1 793 function Titel(n, p, u, i, t, a) {
e60cff 794   this.katalogUrl = u;
2bdd78 795   this.pfad = p;
e60cff 796   this.name = n;
245ac1 797   this.interpret = i;
U 798   this.titelAnzName = t;
799   this.album  = a;
d6b78c 800 }