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