Persoenliche Mediazentrale
ulrich
2021-04-20 d769f3445ed4779715b5c2570731b4bb73d8d2aa
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;
78d707 9   var katName;
f45e20 10
U 11   this.init = function () {
12     self.mediaPfad = '/';
13     self.ortPfad = '/';
14     self.cache = new Array();
15     self.appMenu = new AppMenu();
16     self.appMenu.init(
17             "data/menu/",
18             "hauptmenue.json",
78d707 19             "data/tpl/app-menu.txt",
f45e20 20             ".west",
0866ae 21             "6em");
f45e20 22
U 23     document.querySelector('.hamburger').addEventListener('click', function (e) {
24       self.menue_umschalten();
25     });
26     
27     self.addEvtListener('#mi-katalog', 'click', self.media_liste);
28     self.addEvtListener('#mi-orte', 'click', self.ablageort_liste);
29     self.addEvtListener('#mi-prefs', 'click', self.prefs_liste);
30     self.addEvtListener('#mi-player', 'click', self.abspieler_liste);
8d7d35 31     self.addEvtListener('#mi-listen', 'click', self.abspielliste_liste);
U 32     self.addEvtListener('#mi-list', 'click', self.titel_liste);
d027b5 33     self.addEvtListener('#mi-live', 'click', self.livestream_liste);
3929b0 34     self.addEvtListener('#mi-devices', 'click', self.geraet_liste);
f45e20 35     
U 36     self.fusszeile_umschalten();
37     self.seitenleiste_umschalten();
38     self.dialog_unten_zeigen();
39   };
40   
8d7d35 41   /* ---------------- Entitaets-Listen ----------------- */
d027b5 42   
U 43   this.livestream_selection = function() {
44     document.querySelector('.breadcrumb-behaelter').textContent = '';
45     document.querySelector('.bereich-name').textContent = 'Livestream-Auswahl'; 
46     self.http_get('../api/store/Livestream/liste/', function(responseText) {
47       self.vorlage_laden_und_fuellen("data/tpl/livestream_liste.txt", JSON.parse(responseText), function (html) {
48         document.querySelector(".zentraler-inhalt").innerHTML = html;
49         self.addEvtListener('.entity-eintrag', 'click', function (event) {
50           var t = event.target;
51           self.removeClassMulti('selected');
52           t.classList.add('selected');          
53         });
54       });
55     });
56   };
8d7d35 57
86bbf7 58   // auf der obersten Ebene werden die Kataloge angezeigt,
U 59   // darunter der Inhalt des aktuellen Pfades
60   this.media_liste = function() {
78d707 61     self.reset_top_buttons(); 
095119 62     //console.log("ortPfad: " + self.ortPfad + ", mediaPfad: " + self.mediaPfad);
78d707 63     document.querySelector('.bereich-name').textContent = '';    
86bbf7 64     if(self.ortPfad === '/') {
78d707 65       var bb = document.querySelector('.breadcrumb-behaelter');
U 66       bb.textContent = "Kataloge";
86bbf7 67       // Kataloge listen
f45e20 68       self.http_get('../api/store/Ablageort/liste/', function (responseText) {
8d7d35 69         //document.querySelector('#top-up-btn').removeEventListener('click', self.media_liste_herauf);
78d707 70         self.vorlage_laden_und_fuellen("data/tpl/katalog_root_liste.txt", JSON.parse(responseText), function (html) {
86bbf7 71           document.querySelector(".zentraler-inhalt").innerHTML = html;
U 72           self.addEvtListener('.entity-eintrag', 'click', function (event) {
73             var t = event.target;
78d707 74             self.katName = t.textContent;
d027b5 75             if(self.katName !== "Livestreams") {
U 76               self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
77                 var ablageort = JSON.parse(responseText);
78                 self.ortPfad = ablageort.url;
79                 self.media_liste();
80               });
81             } else {
82               self.livestream_selection();
83             }
86bbf7 84           });
U 85         });
86       });
87     } else {
78d707 88       var bb = document.querySelector('.breadcrumb-behaelter');
U 89       var brPfad = self.katName + self.mediaPfad;
90       var breadcrumbs = brPfad.split('/');
91       var brLinks = "";
92       var brLinkPfad = "";
93       for(var index = 0; index < breadcrumbs.length; index++) {
94         // <a class="breadcrumb-link" href="#">breadcrumbs[index]</a>
95         if(index === 0) {
96           brLinkPfad = '/';
97         } else {
98           brLinkPfad = brLinkPfad + '/' + breadcrumbs[index];
99         }
100         brLinks = brLinks + "<a brlink='" + brLinkPfad + "' class='breadcrumb-link' href='#'>" + breadcrumbs[index] + "</a>";
101         //console.log('   breadcrumbs[' + index + ']: ' + breadcrumbs[index]);
102       }
103       bb.innerHTML = brLinks;
104       self.addEvtListener('.breadcrumb-link', 'click', function(event) {
095119 105         //console.log(event.target.attributes.brlink.nodeValue);
78d707 106         var neuerPfad = event.target.attributes.brlink.nodeValue;
U 107         self.mediaPfad = neuerPfad;
108         self.media_liste();
109       });
3271f1 110       var url = '..' + self.ortPfad + self.mediaPfad;
U 111       if(!url.endsWith('/')) {
112         url = url + '/';
113       }
114       self.http_get(url, function(responseText) {
78d707 115         self.vorlage_laden_und_fuellen("data/tpl/katalog_inhalt_liste.txt", JSON.parse(responseText), function (html) {
86bbf7 116           document.querySelector(".zentraler-inhalt").innerHTML = html;
U 117           self.addEvtListener('.entity-eintrag', 'click', function (event) {
118             var t = event.target;
3271f1 119             var tx = t.textContent;
86bbf7 120             if(t.classList.contains("entity-typ-folder")) {
3271f1 121               if(self.mediaPfad.endsWith('/')) {
U 122                 self.mediaPfad = self.mediaPfad + tx;                
123               } else {
124                 self.mediaPfad = self.mediaPfad + '/' + tx;
125               }
86bbf7 126               self.media_liste();
U 127             } else {
37eadf 128               if(t.classList.contains('selected')) {
78d707 129                 t.classList.add('added-to-playlist');
095119 130                 self.titelDazu();
37eadf 131               } else {
U 132                 self.removeClassMulti('selected');
133                 t.classList.add('selected');
134               }
e60cff 135               //self.selTitel = new Titel(t.textContent, self.ortPfad);       
86bbf7 136             }
U 137           });
8d7d35 138           self.addEvtListener('#top-up-btn', 'click', function(event) {
86bbf7 139             if(self.mediaPfad === '/') {
U 140               self.ortPfad = '/';              
141             } else {
142               var pos = self.mediaPfad.lastIndexOf('/');
3271f1 143               var parent;
U 144               if(pos > 1) {
145                 parent = self.mediaPfad.substring(0, pos);
146               } else {
147                 parent = '/';
148               }
86bbf7 149               self.mediaPfad = parent;
U 150             }
151             self.media_liste();
8d7d35 152           });
86bbf7 153         });
U 154       });
155     }
e60cff 156   };
245ac1 157   
3e5a56 158   this.geraet_schalt_liste = function() {
U 159     self.entitaet_liste('Geräte schalten','../api/store/Geraet/liste/', 
160       "data/tpl/geraet_schalt_liste.txt", '../api/store/Geraet/', 
161       "self.form_geraet_status", function(responseText) {
162         var geraet = JSON.parse(responseText);
163         self.geraet_status_form(geraet);
849ee2 164       }, function() {
U 165         self.addEvtListener('#ein-btn', 'click', function (event) {
166           var geraetName = event.target.attributes.gname.nodeValue;
167           //var geraetName = document.querySelector('.schalt-geraet-name').textContent;
168           self.http_get('../api/gstrg/geraet/' + geraetName + "/ein", function(responseText) {
169             console.log(responseText);
170           });
171         });
172         self.addEvtListener('#aus-btn', 'click', function (event) {
173           var geraetName = event.target.attributes.gname.nodeValue;
174           //var geraetName = document.querySelector('.schalt-geraet-name').textContent;
175           self.http_get('../api/gstrg/geraet/' + geraetName + "/aus", function(responseText) {
176             console.log(responseText);
177           });
178         });        
3e5a56 179       });
U 180   };
181   
3929b0 182   this.geraet_liste = function() {
U 183     self.entitaet_liste('Geräte','../api/store/Geraet/liste/', 
184       "data/tpl/geraet_liste.txt", '../api/store/Geraet/', 
185       "self.geraet_form", function(responseText) {
186         var geraet = JSON.parse(responseText);
187         self.geraet_form(geraet);
188       });
189   };
190
a43e1a 191   this.ablageort_liste = function() {
78d707 192     self.entitaet_liste('Kataloge','../api/store/Ablageort/liste/', 
U 193       "data/tpl/ablageort_liste.txt", '../api/store/Ablageort/', 
e44ed0 194       "self.ablageort_form", function(responseText) {
U 195         var ablageort = JSON.parse(responseText);
196         self.ablageort_form(ablageort);
197       });
cf6509 198   };
U 199
200   this.prefs_liste = function() {
50e53e 201     self.entitaet_liste('Einstellungen','../api/store/Einstellung/liste/', 
78d707 202       "data/tpl/einstellung_liste.txt", '../api/store/Einstellung/', 
e44ed0 203       "self.prefs_form", function(responseText) {
U 204         var einstellung = JSON.parse(responseText);
205         self.prefs_form(einstellung);
206       });
cf6509 207   };
U 208
3d4bca 209   this.abspieler_liste = function() {
50e53e 210     self.entitaet_liste('Abspieler','../api/store/Abspieler/liste/', 
78d707 211       "data/tpl/abspieler_liste.txt", '../api/store/Abspieler/', 
e44ed0 212       "self.abspieler_form", function(responseText) {
U 213         var abspieler = JSON.parse(responseText);
214         self.abspieler_form(abspieler);
215       });
8d7d35 216   };
U 217   
d027b5 218   this.livestream_liste = function() {
U 219     self.entitaet_liste('Livestream','../api/store/Livestream/liste/', 
220       "data/tpl/livestream_liste.txt", '../api/store/Livestream/', 
221       "self.livestream_form", function(responseText) {
222         var livestream = JSON.parse(responseText);
223         self.livestream_form(livestream);
224       });
225   };
226   
8d7d35 227   this.abspielliste_liste = function() {
50e53e 228     self.entitaet_liste('Abspielliste','../api/store/Abspielliste/liste/', 
78d707 229       "data/tpl/abspielliste_liste.txt", '../api/store/Abspielliste/', 
e44ed0 230       "self.abspielliste_form", function(responseText) {
095119 231         //console.log("responseTest: '" + responseText + "'");
e44ed0 232         var abspielliste = JSON.parse(responseText);
U 233         self.abspielliste_form(abspielliste);
234       });
8d7d35 235   };
U 236   
c7030d 237   /* -------------------- Entitaets-Formulare ------------------ */  
8d7d35 238   
U 239   this.abspielliste_form = function(al) {
50e53e 240     self.entitaet_form('Abspielliste', al, al.name,
78d707 241       "data/tpl/form_abspielliste.txt", '../api/store/Abspielliste/',
9865bd 242       '#abspielliste-name', function(event) {
095119 243           if(event !== undefined) {
U 244             event.preventDefault();
245           }
c7030d 246           self.abspielliste_auswahl_fuellen();
U 247           self.abspielliste_liste();
248     });
3d4bca 249   };
71def1 250   
3d4bca 251   this.abspieler_form = function(pl) {
50e53e 252     self.entitaet_form('Abspieler', pl, pl.key,
78d707 253       "data/tpl/form_abspieler.txt", '../api/store/Abspieler/',
c7030d 254       '#abspieler-name', function() { 
U 255           self.abspieler_auswahl_fuellen();
256           self.abspieler_liste();
d027b5 257     });
U 258   };
259
260   this.livestream_form = function(ls) {
261     self.entitaet_form('Livestream', ls, ls.name,
262       "data/tpl/form_livestream.txt", '../api/store/Livestream/',
263       '#livestream-name', function() { 
264           self.livestream_liste();
3929b0 265     });
U 266   };
267
268   this.geraet_form = function(ge) {
269     self.entitaet_form('Gerät', ge, ge.name,
270       "data/tpl/form_geraet.txt", '../api/store/Geraet/',
271       '#geraet-name', function() { 
272           self.geraet_liste();
3e5a56 273     });
U 274   };
275
276   this.geraet_status_form = function(ge) {
277     self.entitaet_form('Gerät', ge, ge.name,
278       "data/tpl/form_geraet_status.txt", '../api/store/Geraet/',
279       '#geraet-name', function() { 
280           self.geraet_schalt_liste();
c7030d 281     });
71def1 282   };
U 283
cf6509 284   this.prefs_form = function(k) {
78d707 285     self.entitaet_form('Einstellung', k, k.key,
U 286       "data/tpl/form_einstellung.txt", '../api/store/Einstellung/',
c7030d 287       '#einstellung-key', function() { 
U 288           self.prefs_liste();
289     });
a43e1a 290   };
cfa858 291
90f5d4 292   /* 
U 293    * Ablageort-Formular anzeigen
294    * 
295    * {"name":"Katalog 2","ort":"/home/ulrich/Videos","url":"/media/kat2"}: 
296    * 
297    * @param {type} ablageort  der Ablageort, der bearbeitet werden soll, leer fuer neuen Ort
298    * @returns {undefined} kein Rueckgabewert
299    */
300   this.ablageort_form = function(ort) {
78d707 301     self.entitaet_form('Katalog', ort, ort.name,
U 302       "data/tpl/form_ablageort.txt", '../api/store/Ablageort/',
c7030d 303       '#ablageort-name', function() { 
U 304         self.ablageort_liste();
305     });
b379f5 306   };
48f8f9 307   
748b6f 308   /* ------------------------------- UI-Dynamik ----------------------- */
48f8f9 309   
748b6f 310   self.reset_top_buttons = function() {
78d707 311     self.vorlage_laden_und_fuellen("data/tpl/top_btns.txt", '', function (html) {
748b6f 312       document.querySelector(".top-btns").innerHTML = html;
U 313     });
314   };
315   
316   this.abspieler_auswahl_fuellen = function() {
b56bb3 317     self.http_get('../api/store/Abspieler/liste/', function (responseText) {
78d707 318       self.vorlage_laden_und_fuellen("data/tpl/abs_sel.txt", JSON.parse(responseText), function (html) {
748b6f 319         document.querySelector(".abs-sel").innerHTML = html;
U 320       });    
321     });
322   };
323
324   this.abspielliste_auswahl_fuellen = function() {
325     self.http_get('../api/store/Abspielliste/', function (responseText) {
78d707 326       self.vorlage_laden_und_fuellen("data/tpl/pl_sel.txt", JSON.parse(responseText), function (html) {
748b6f 327         document.querySelector(".pl-sel").innerHTML = html;
b56bb3 328         self.addEvtListener('#playlist', 'change', function() {
U 329           self.titel_liste();
330         });
748b6f 331       });    
U 332     });
333   };
334   
335   /* Unterer Einblendbereich */
336   
337   this.dialog_unten_zeigen = function() {
78d707 338     self.vorlage_laden_und_fuellen("data/tpl/ctrl.txt", "", function (html) {
748b6f 339       var dlg = document.querySelector(".dialog-unten");
U 340       dlg.style.height = '4.5em';
341       dlg.innerHTML = html;
342       self.abspieler_auswahl_fuellen();
343       self.abspielliste_auswahl_fuellen();
095119 344       self.addEvtListener('#dazu-btn', 'click', self.titelDazu);
b56bb3 345       self.addEvtListener('#play-btn', 'click', self.play);
9e14ef 346       self.addEvtListener('#stop-btn', 'click', function() {
U 347         self.kommando('stop');
348       });
349       self.addEvtListener('#pause-btn', 'click', function() {
350         self.kommando('pause');
351       });
352       self.addEvtListener('#weiter-btn', 'click', function() {
353         self.kommando('weiter');
354       });
355       
356 /*
357     <button class="ctrl-btn ctrl-item" id="hier-btn" title="hier spielen"><i class="icon-tablet"></i></button>
358  */      
359       
095119 360       self.addEvtListener('#weg-btn', 'click', self.titelWeg);
U 361       self.addEvtListener('#leeren-btn', 'click', self.alleTitelEntfernen);
748b6f 362       self.media_liste();
U 363     });
364   };
365   
366   /* Titel einer Abspielliste */
367   
368   this.titel_liste = function() {
369     self.reset_top_buttons();
370     var plname = document.querySelector('#playlist').value;
78d707 371     document.querySelector('.bereich-name').textContent = 'Abspielliste ' + plname;
U 372     var bb = document.querySelector('.breadcrumb-behaelter');
373     bb.textContent = "";
748b6f 374     self.http_get('../api/alist/' + plname, function (responseText) {
78d707 375       self.vorlage_laden_und_fuellen("data/tpl/titel_liste.txt", JSON.parse(responseText), function (html) {
748b6f 376         document.querySelector(".zentraler-inhalt").innerHTML = html;
U 377         self.addEvtListener('.entity-eintrag', 'click', function (event) {
378           var t = event.target;
379           self.removeClassMulti('selected');
380           t.classList.add('selected');
381         });
382       });
383     });
384   };  
385   
b56bb3 386   /* ------------- Media-Steuerung ------------------------- */
U 387   
388   this.play = function() {
658c14 389     var bereichName = document.querySelector('.bereich-name').textContent;
U 390     if(bereichName === '') {
4f2589 391       var titel = self.titelErmitteln(document.querySelector(".selected"));
658c14 392       //var titelName = elem.textContent;
4f2589 393       /*
658c14 394       var titelName = elem.attributes.dateiName.nodeValue;
U 395       var album = elem.attributes.album.nodeValue;
396       var interpret = elem.attributes.interpret.nodeValue;
397       var anzName = elem.attributes.titelAnzName.nodeValue;
398       var titel;
399       if(self.mediaPfad.endsWith('/')) {
400         titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
401       } else {
402         titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
403       }
4f2589 404       */
1c5fa4 405       var playername = document.querySelector('#abspieler').value;
U 406       /*      
407       HTTP POST /mz/api/strg/abspieler/play mit Titel im Body
658c14 408       
1c5fa4 409       url: /media/test/M/Muenchener-Freiheit/01-Ohne-Dich-schlaf-ich-heut-Nacht-nicht-ein.mp3      
658c14 410       */
U 411       console.log('plname: ' + playername + ' url: ' + titel.katalogUrl + titel.pfad + titel.name);
d027b5 412       self.http_post('../api/strg/' + playername + '/titel', JSON.stringify(titel), function(responseText) {
658c14 413         self.meldung_mit_timeout(responseText, 1500);
d027b5 414       });   
U 415     } else if(bereichName === 'Livestream-Auswahl') {
416       var streamName = document.querySelector(".selected").textContent;
417       var playername = document.querySelector('#abspieler').value;
418       var stream = new Livestream(streamName, '-');
419       self.http_post('../api/strg/' + playername + '/stream', JSON.stringify(stream), function(responseText) {
420         self.meldung_mit_timeout(responseText, 1500);
421       });   
658c14 422     } else {
U 423       var abs = document.querySelector('#abspieler').value;
424       var lst = document.querySelector('#playlist').value;
425       console.log(
426         "play playlist.value: " + document.querySelector('#playlist').value + 
427         ", abspieler.value: " + document.querySelector('#abspieler').value);
428       self.http_get('../api/strg/' + abs + '/play/liste/' + lst, function(responseText) {
429         self.meldung_mit_timeout(responseText, 1500);
430       });
431     }
095119 432   };
U 433   
9e14ef 434   this.kommando = function(kommando) {
U 435     var abs = document.querySelector('#abspieler').value;
436     self.http_get('../api/strg/' + abs + '/' + kommando, function(responseText) {
437       self.meldung_mit_timeout(responseText, 1500);
438     });
439   };
440     
095119 441   /* ------------- Verwaltungsfunktionen Abspielliste -------------------- */
U 442   
443   self.alleTitelEntfernen = function() {
444     var plname = document.querySelector('#playlist').value;
445     self.http_delete('../api/alist/' + plname + '/alle', '', function(responseText) {
446       // DELETE    http://localhost:9090/mz/api/alist/liste1/0
447       //self.meldung_mit_timeout(responseText, 1500);
448       self.titel_liste();
449     });
450   };
451   
452   this.titelDazu = function() {
4f2589 453     var titel = self.titelErmitteln(document.querySelector(".selected"));
095119 454     //var titelName = elem.textContent;
4f2589 455     /*
095119 456     var titelName = elem.attributes.dateiName.nodeValue;
U 457     var album = elem.attributes.album.nodeValue;
458     var interpret = elem.attributes.interpret.nodeValue;
459     var anzName = elem.attributes.titelAnzName.nodeValue;
460     var titel;
461     if(self.mediaPfad.endsWith('/')) {
462       titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
463     } else {
464       titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
465     }
4f2589 466     */
095119 467     var plname = document.querySelector('#playlist').value;
U 468     self.http_put('../api/alist/' + plname, JSON.stringify(titel), function(responseText) {
469       //self.meldung_mit_timeout(responseText, 1500);
470     });
471   };  
472   
473   this.titelWeg = function() {
474     var elem = document.querySelector(".selected");
475     var parentElem = elem.parentNode;
476     //console.log("elem: " + elem.nodeName + ", parent: " + parentElem.nodeName + ", len: " + parentElem.childNodes.length);
477     var liElems = parentElem.getElementsByTagName(elem.nodeName); // nur die LI Elemente
478     //console.log("liElems.anz: " + liElems.length);
479     var gefunden = false;
480     for(var i = 0; i < liElems.length && !gefunden; i++) {
481       //console.log(liElems.item(i).textContent);
482       if(liElems.item(i).classList.contains("selected")) {
483         gefunden = true;
484         var index = i;
485         //console.log(elem.textContent + ' hat Index ' + i);
486       }
487     }
488     // /mz/api/alist/[pl-name]/[nr] 
489     var plname = document.querySelector('#playlist').value;
490     self.http_delete('../api/alist/' + plname + '/' + index,'', function(responseText) {
491       // DELETE    http://localhost:9090/mz/api/alist/liste1/0
492       //self.meldung_mit_timeout(responseText, 1500);
493       self.titel_liste();
494     });
495     
b56bb3 496   };
U 497   
748b6f 498   /* ------------- Helfer fuer Entitaets-Formulare ----------------------- */
14638b 499   
U 500   /*
501    * url: '../api/store/Ablageort/liste/'
78d707 502    * tpl: "data/tpl/ablageort_liste.txt"
14638b 503    * storeUrl: '../api/store/Ablageort/'
U 504    * formFunc: "self.ablageort_form"
505    * cb: etwas wie
506    *   function(responseText){
507    *     var ablageort = JSON.parse(responseText);
508    *     self.ablageort_form(ablageort);
509    *   });
510    */
849ee2 511   this.entitaet_liste = function(bname, listUrl, tpl, storeUrl, formFunc, cb, customListCode) {
14638b 512     self.reset_top_buttons();
50e53e 513     document.querySelector('.bereich-name').textContent = bname;
78d707 514     var bb = document.querySelector('.breadcrumb-behaelter');
U 515     bb.textContent = "";
14638b 516     self.http_get(listUrl, function (responseText) {
U 517       self.vorlage_laden_und_fuellen(tpl, JSON.parse(responseText), function (html) {
518         document.querySelector(".zentraler-inhalt").innerHTML = html;
519         self.addEvtListener('.entity-eintrag', 'click', function (event) {
520           var t = event.target;
521           self.http_get(storeUrl + t.textContent, cb);
522         });
523         //self.addEvtListener('#neu-btn', 'click', function (event) {
524         self.addEvtListener('#top-neu-btn', 'click', function(event) {
525           eval(formFunc + "(this)");
849ee2 526         });                
U 527         if(typeof(customListCode) !== 'function') {
528           // ..
529         } else {
530           customListCode();
531         }        
14638b 532       });
U 533     });
534   };  
748b6f 535       
48f8f9 536   /*
c7030d 537    * dat: gefuelltes Datenobjekt bei Aenderung
U 538    * key: der alte schluesselbegriff bei Aenderung (z.B. al.name)
78d707 539    * tpl: "data/tpl/form_abspielliste.txt"
c7030d 540    * url: '../api/store/Abspielliste/'
U 541    * selector: '#abspielliste-name'
542    * cbOk: etwas wie
543    *    function() {
544    *       self.abspielliste_auswahl_fuellen();
545    *       self.abspielliste_liste();
546    *     });
547    * delSelector: '#abspielliste-name'
548    * cbDel: etwas wie
549    *    function() {
550    *       self.abspielliste_auswahl_fuellen();
551    *       self.abspielliste_liste();
552    *     });
553    */
554
50e53e 555   this.entitaet_form = function(bname, dat, key, tpl, url, selector, cb) {
U 556     document.querySelector('.bereich-name').textContent = bname;
c7030d 557     self.vorlage_laden_und_fuellen(tpl, dat, function (html) {
U 558       document.querySelector(".zentraler-inhalt").innerHTML = html;
559       const form = document.querySelector('form');      
560       form.addEventListener('submit', function(event) {
561         self.handle_submit(event, key, url, selector, cb);
562       });
563       self.addEvtListener('#cancel-btn', 'click', cb);
564       self.addEvtListener('#loeschen-btn', 'click', function(event) {
565         event.preventDefault();
566         self.handle_del_btn(selector, url, cb);
567       });
568     });
569   };
570   
571   /*
48f8f9 572    * existingKey: wenn die Entitaet existiert und geandert werden soll
U 573    *                 leer, wenn neue Entitaet 
574    */
575   this.handle_submit = function(event, existingKey, putUrl, keySelector, cb) {
576     event.preventDefault();
577     const data = new FormData(event.target);
578     const value = Object.fromEntries(data.entries());
579     var daten = JSON.stringify(value);
580     var formkey = document.querySelector(keySelector).value;
581     formkey = formkey.replace(' ', '').replace(/[\W]+/g, '');
582     if(typeof existingKey === "undefined" ||  existingKey.length < 1) {
583       // neu
584       self.http_put(putUrl + formkey, daten, function (responseText) {
585         if(typeof(cb) !== 'function') {
586           // ..
587         } else {
588           cb();
589         }
590       });
591     } else {
592       // aendern
593       self.http_put(putUrl + existingKey, daten, function (responseText) {
594         if(typeof(cb) !== 'function') {
595           // ..
596         } else {
597           cb();
598         }
599       });
600     }
601   };
602   
603   this.handle_del_btn = function(selectorKey, delUrl, cb) {
604     var pkey = document.querySelector(selectorKey).value;
605     var dlgdata = {"del-elem": pkey};
78d707 606     self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.txt', dlgdata, function() {
48f8f9 607       self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
U 608       self.addEvtListener('#ja-btn', 'click', function(event) {
095119 609         //console.log("loeschen geklickt.");
48f8f9 610         self.http_delete(delUrl + pkey, '', function (responseText) {
U 611           self.dialog_schliessen();
612           if(typeof(cb) !== 'function') {
613             // ..
614           } else {
615             cb();
616           }
617         });
618       });
619     });    
620   };  
748b6f 621   
U 622   /* ------------------ sonstige Helfer ----------------------- */
623       
7c22a2 624   this.addEvtListener = function(selector, eventName, func) {
U 625     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
626   };
627   
628   this.removeClassMulti = function(selector) {
629     document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); });
630   };
4f2589 631   
U 632   self.titelErmitteln = function(elem) {
633     var titelName = elem.attributes.dateiName.nodeValue;
634     var album = elem.attributes.album.nodeValue;
635     var interpret = elem.attributes.interpret.nodeValue;
636     var anzName = elem.attributes.titelAnzName.nodeValue;
637     var titel;
638     if(self.mediaPfad.endsWith('/')) {
639       titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
640     } else {
641       titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
642     }
643     return titel;
644   };
7c22a2 645
f45e20 646   /* --------------------- asynchroner HTTP Client ----------------- */
faab2d 647   
f074f6 648   this.http_get = function (u, cb) {
b379f5 649     self.http_call('GET', u, null, cb);
U 650   };
f074f6 651
U 652   this.http_post = function (u, data, cb) {
b379f5 653     self.http_call('POST', u, data, cb);
U 654   };
655
90f5d4 656   this.http_put = function (u, data, cb) {
U 657     self.http_call('PUT', u, data, cb);
658   };
659   
5b7356 660   this.http_delete = function (u, data, cb) {
5f7e0b 661     // console.log("delete " + u);
5b7356 662     self.http_call('DELETE', u, data, cb);
U 663   };
664   
f074f6 665   this.http_call = function (method, u, data, scallback) {
b379f5 666     var xhr = new XMLHttpRequest();
U 667     var url = u;
f074f6 668     xhr.onreadystatechange = function () {
b379f5 669       if (this.readyState === 4 && this.status === 200) {
U 670         scallback(this.responseText);
671       }
672     };
673     xhr.open(method, url);
f074f6 674     if (method === 'GET') {
b379f5 675       xhr.send();
2597cd 676     } else if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
b379f5 677       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
U 678       xhr.send(data);
679     }
680   };
8239d1 681   
f45e20 682   /* ------------------------ aus App-Vorlage -------------------  */
cfa858 683
f074f6 684   this.menue_umschalten = function () {
cfa858 685     var ham = document.querySelector(".hamburger");
U 686     ham.classList.toggle("is-active"); // hamburger-icon umschalten
687     self.appMenu.toggle(); // menue oeffnen/schliessen
688   };
689
f074f6 690   this.info_dialog_zeigen = function () {
78d707 691     self.dialog_laden_und_zeigen('data/tpl/dlg-info.txt', '');
cfa858 692     self.menue_umschalten();
U 693   };
694
f074f6 695   this.seitenleiste_umschalten = function () {
cfa858 696     var ostDiv = document.querySelector('.ost');
f074f6 697     if (ostDiv.classList.contains('ost-open')) {
cfa858 698       ostDiv.classList.remove('ost-open');
f074f6 699       ostDiv.style.flexBasis = '0em';
cfa858 700     } else {
f074f6 701       ostDiv.classList.add('ost-open');
U 702       ostDiv.style.flexBasis = '6em';
cfa858 703     }
U 704     self.menue_umschalten();
705   };
706
f074f6 707   this.fusszeile_umschalten = function () {
cfa858 708     var suedDiv = document.querySelector('.sued');
f074f6 709     if (suedDiv.classList.contains('sued-open')) {
cfa858 710       suedDiv.classList.remove('sued-open');
f074f6 711       suedDiv.style.height = '0';
cfa858 712     } else {
U 713       suedDiv.classList.add('sued-open');
f074f6 714       suedDiv.style.height = '1.5em';
cfa858 715     }
U 716     self.menue_umschalten();
717   };
718
f074f6 719   this.menu_message = function (msg) {
cfa858 720     self.meldung_mit_timeout(msg, 1500);
U 721     var suedDiv = document.querySelector('.sued');
f074f6 722     if (suedDiv.classList.contains('sued-open')) {
cfa858 723     } else {
U 724       suedDiv.classList.add('sued-open');
f074f6 725       suedDiv.style.height = '1.5em';
cfa858 726     }
U 727     self.menue_umschalten();
728   };
729
f074f6 730   this.message_1 = function () {
cfa858 731     self.menu_message('Eine Mitteilung.');
U 732   };
733
f074f6 734   this.message_2 = function () {
cfa858 735     self.menu_message('Was wir schon immer sagen wollten.');
U 736   };
737
f074f6 738   this.message_3 = function (text) {
cfa858 739     self.menu_message(text);
U 740   };
741
f074f6 742   this.meldung_mit_timeout = function (meldung, timeout) {
cfa858 743     var s = document.querySelector('.sued');
a43e1a 744     s.classList.add('sued-open');
U 745     s.style.height = '1.5em';
cfa858 746     s.textContent = meldung;
f074f6 747     setTimeout(function () {
cfa858 748       s.textContent = 'Bereit.';
f074f6 749       setTimeout(function () {
cfa858 750         var suedDiv = document.querySelector('.sued');
f074f6 751         if (suedDiv.classList.contains('sued-open')) {
U 752           suedDiv.classList.remove('sued-open');
753           suedDiv.style.height = '0';
cfa858 754         }
U 755       }, 500);
756     }, timeout);
757   };
8239d1 758   
f45e20 759   /* --------------------- Dialog-Funktionen ------------------------ */
cfa858 760
U 761   /*
f074f6 762    Einen Dialog aus Vorlagen erzeugen
U 763    
764    vurl - URL zur Dialogvorlage
765    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
766    */
5b7356 767   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 768     var vorlage = self.cache[vurl];
769     if(vorlage === undefined) {
770       self.http_get(vurl, function(antwort) {
771         self.cache[vurl] = antwort;
772         self.dialog_zeigen(vurl, msgTpl, cb);
f074f6 773       });
cfa858 774     } else {
5b7356 775       self.dialog_zeigen(vurl, msgTpl, cb);
cfa858 776     }
U 777   };
778
5b7356 779   this.dialog_zeigen = function (vurl, inhalt, cb) {
U 780     var dlg = document.querySelector(".dialog");
2597cd 781     self.html_erzeugen(vurl, inhalt, function (html) {
U 782       dlg.style.height = '7em';
783       dlg.innerHTML = html;
784       document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
785       if(typeof(cb) !== 'function') {
786         // ..
787       } else {
788         cb();
789       }
790     });
5b7356 791   };
2597cd 792   
f45e20 793   this.dialog_schliessen = function () {
cfa858 794     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 795     var dlg = document.querySelector('.dialog');
796     dlg.style.height = '0';
797     dlg.innerHTML = '';
798   };
799
f45e20 800   /* ---------------------   Vorlagen   ---------------------- */
cfa858 801
U 802   /*
f074f6 803    Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt
U 804    gefüllt wird
805    
806    Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem
807    Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten.
808    Das fertige HTML wird der Callback-Funktion übergeben
809    sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der
810    Programmlauf zu diesem Zeitpunkt mittlerweile ist.
811    
812    vurl - URL zur Vorlagendatei
813    inhalt - die JSON-Struktur, deren Inhalt in die
814    Vorlage gefüllt werden soll
815    cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist.
816    Dieser Callback-Funktion wird das fertige HTML übergeben
817    */
818   this.html_erzeugen = function (vurl, inhalt, cb) {
cfa858 819     var vorlage = self.cache[vurl];
f074f6 820     if (vorlage === undefined) {
cfa858 821       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
U 822     } else {
823       self.vorlage_fuellen(vurl, inhalt, cb);
824     }
825   };
826
f074f6 827   this.vorlage_fuellen = function (vurl, inhalt, cb) {
cfa858 828     cb(Mustache.render(self.cache[vurl], inhalt));
U 829   };
830
831   /*
f074f6 832    Eine Vorlage vom Server in den lokalen Speicher laden
U 833    vurl - der URL unter dem die Vorlage zu finden ist
834    inhalt - die JSON-Struktur, deren Inhalt in die
835    Vorlage gefüllt werden soll
836    cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem
837    Inhalt gefüllt ist
838    */
839   this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) {
cfa858 840     var xmlhttp = new XMLHttpRequest();
f074f6 841     xmlhttp.onreadystatechange = function () {
cfa858 842       if (this.readyState == 4 && this.status == 200) {
U 843         self.cache[vurl] = this.responseText;
844         self.vorlage_fuellen(vurl, inhalt, cb);
845       }
846     };
847     xmlhttp.open("GET", vurl, true);
848     xmlhttp.send();
849   };
850
851
852 }
853
f45e20 854 /* ----------- Objekte ---------------- */
U 855
856 function Ablageort(n, o, u) {
857   this.name = n;
858   this.ort = o;
859   this.url = u;
860 }
861
862 function Einstellung(k, v) {
863   this.key = k;
864   this.value = v;
865 }
866
867 function Abspieler(n, u) {
868   this.name = n;
869   this.url = u;
8d7d35 870 }
U 871
d027b5 872 function Livestream(n, u) {
U 873   this.name = n;
874   this.url = u;
875 }
876
8d7d35 877 function Abspielliste(n) {
U 878   this.name = n;
e60cff 879 }
U 880
245ac1 881 function Titel(n, p, u, i, t, a) {
e60cff 882   this.katalogUrl = u;
2bdd78 883   this.pfad = p;
e60cff 884   this.name = n;
245ac1 885   this.interpret = i;
U 886   this.titelAnzName = t;
887   this.album  = a;
3929b0 888 }
U 889
890 function Geraet(n, e, a, s) {
891   this.name = n;
892   this.einUrl = e;
893   this.ausUrl = a;
894   this.statusUrl = s;
d6b78c 895 }