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