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