Persoenliche Mediazentrale
ulrich
2021-04-25 96031786dbecbb4e10248fcd1579c7e3b8ea22d7
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() {
7d3118 228     self.entitaet_liste('Livestreams','../api/store/Livestream/liste/', 
d027b5 229       "data/tpl/livestream_liste.txt", '../api/store/Livestream/', 
U 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/',
960317 251       '#abspielliste-name', '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/',
960317 263       '#abspieler-name', 'name', function() { 
c7030d 264           self.abspieler_auswahl_fuellen();
U 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/',
960317 272       '#livestream-name', 'name', function() { 
d027b5 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/',
960317 280       '#geraet-name', 'name', function() { 
3929b0 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/',
960317 288       '#geraet-name', 'name', function() { 
3e5a56 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/',
960317 296       '#einstellung-key', 'key', function() { 
c7030d 297           self.prefs_liste();
U 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
883f91 443     var host = 'http://' + window.location.host + '/tango';
fe0cf7 444     console.log('host: ' + host);
U 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
960317 592   this.entitaet_form = function(bname, dat, key, tpl, url, selector, keyname, cb) {
50e53e 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) {
960317 598         self.handle_submit(event, key, url, selector, keyname, cb);
c7030d 599       });
U 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    */
960317 612   this.handle_submit = function(event, existingKey, putUrl, keySelector, keyname, cb) {
48f8f9 613     event.preventDefault();
U 614     const data = new FormData(event.target);
615     const value = Object.fromEntries(data.entries());
616     var formkey = document.querySelector(keySelector).value;
960317 617     formkey = formkey.replace(' ', '');
U 618     formkey = formkey.replace(/[\W]+/g, '');
619     value[keyname] = formkey;
620     var daten = JSON.stringify(value);
48f8f9 621     if(typeof existingKey === "undefined" ||  existingKey.length < 1) {
U 622       // neu
623       self.http_put(putUrl + formkey, daten, function (responseText) {
624         if(typeof(cb) !== 'function') {
625           // ..
626         } else {
627           cb();
628         }
629       });
630     } else {
631       // aendern
632       self.http_put(putUrl + existingKey, daten, function (responseText) {
633         if(typeof(cb) !== 'function') {
634           // ..
635         } else {
636           cb();
637         }
638       });
639     }
640   };
641   
642   this.handle_del_btn = function(selectorKey, delUrl, cb) {
643     var pkey = document.querySelector(selectorKey).value;
644     var dlgdata = {"del-elem": pkey};
78d707 645     self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.txt', dlgdata, function() {
48f8f9 646       self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
U 647       self.addEvtListener('#ja-btn', 'click', function(event) {
095119 648         //console.log("loeschen geklickt.");
48f8f9 649         self.http_delete(delUrl + pkey, '', function (responseText) {
U 650           self.dialog_schliessen();
651           if(typeof(cb) !== 'function') {
652             // ..
653           } else {
654             cb();
655           }
656         });
657       });
658     });    
659   };  
748b6f 660   
U 661   /* ------------------ sonstige Helfer ----------------------- */
662       
7c22a2 663   this.addEvtListener = function(selector, eventName, func) {
U 664     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
665   };
666   
667   this.removeClassMulti = function(selector) {
668     document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); });
669   };
4f2589 670   
U 671   self.titelErmitteln = function(elem) {
672     var titelName = elem.attributes.dateiName.nodeValue;
673     var album = elem.attributes.album.nodeValue;
674     var interpret = elem.attributes.interpret.nodeValue;
675     var anzName = elem.attributes.titelAnzName.nodeValue;
676     var titel;
677     if(self.mediaPfad.endsWith('/')) {
678       titel = new Titel(titelName, self.mediaPfad, self.ortPfad, interpret, anzName, album);
679     } else {
680       titel = new Titel(titelName, self.mediaPfad + '/', self.ortPfad, interpret, anzName, album);
681     }
682     return titel;
683   };
7c22a2 684
f45e20 685   /* --------------------- asynchroner HTTP Client ----------------- */
faab2d 686   
f074f6 687   this.http_get = function (u, cb) {
b379f5 688     self.http_call('GET', u, null, cb);
U 689   };
f074f6 690
U 691   this.http_post = function (u, data, cb) {
b379f5 692     self.http_call('POST', u, data, cb);
U 693   };
694
90f5d4 695   this.http_put = function (u, data, cb) {
U 696     self.http_call('PUT', u, data, cb);
697   };
698   
5b7356 699   this.http_delete = function (u, data, cb) {
5f7e0b 700     // console.log("delete " + u);
5b7356 701     self.http_call('DELETE', u, data, cb);
U 702   };
703   
f074f6 704   this.http_call = function (method, u, data, scallback) {
b379f5 705     var xhr = new XMLHttpRequest();
U 706     var url = u;
f074f6 707     xhr.onreadystatechange = function () {
b379f5 708       if (this.readyState === 4 && this.status === 200) {
U 709         scallback(this.responseText);
710       }
711     };
712     xhr.open(method, url);
f074f6 713     if (method === 'GET') {
b379f5 714       xhr.send();
2597cd 715     } else if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
b379f5 716       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
U 717       xhr.send(data);
718     }
719   };
8239d1 720   
f45e20 721   /* ------------------------ aus App-Vorlage -------------------  */
cfa858 722
f074f6 723   this.menue_umschalten = function () {
cfa858 724     var ham = document.querySelector(".hamburger");
U 725     ham.classList.toggle("is-active"); // hamburger-icon umschalten
726     self.appMenu.toggle(); // menue oeffnen/schliessen
727   };
728
f074f6 729   this.info_dialog_zeigen = function () {
78d707 730     self.dialog_laden_und_zeigen('data/tpl/dlg-info.txt', '');
cfa858 731     self.menue_umschalten();
U 732   };
733
f074f6 734   this.seitenleiste_umschalten = function () {
cfa858 735     var ostDiv = document.querySelector('.ost');
f074f6 736     if (ostDiv.classList.contains('ost-open')) {
cfa858 737       ostDiv.classList.remove('ost-open');
f074f6 738       ostDiv.style.flexBasis = '0em';
cfa858 739     } else {
f074f6 740       ostDiv.classList.add('ost-open');
U 741       ostDiv.style.flexBasis = '6em';
cfa858 742     }
U 743     self.menue_umschalten();
744   };
745
f074f6 746   this.fusszeile_umschalten = function () {
cfa858 747     var suedDiv = document.querySelector('.sued');
f074f6 748     if (suedDiv.classList.contains('sued-open')) {
cfa858 749       suedDiv.classList.remove('sued-open');
f074f6 750       suedDiv.style.height = '0';
cfa858 751     } else {
U 752       suedDiv.classList.add('sued-open');
f074f6 753       suedDiv.style.height = '1.5em';
cfa858 754     }
U 755     self.menue_umschalten();
756   };
757
f074f6 758   this.menu_message = function (msg) {
cfa858 759     self.meldung_mit_timeout(msg, 1500);
U 760     var suedDiv = document.querySelector('.sued');
f074f6 761     if (suedDiv.classList.contains('sued-open')) {
cfa858 762     } else {
U 763       suedDiv.classList.add('sued-open');
f074f6 764       suedDiv.style.height = '1.5em';
cfa858 765     }
U 766     self.menue_umschalten();
767   };
768
f074f6 769   this.message_1 = function () {
cfa858 770     self.menu_message('Eine Mitteilung.');
U 771   };
772
f074f6 773   this.message_2 = function () {
cfa858 774     self.menu_message('Was wir schon immer sagen wollten.');
U 775   };
776
f074f6 777   this.message_3 = function (text) {
cfa858 778     self.menu_message(text);
U 779   };
780
f074f6 781   this.meldung_mit_timeout = function (meldung, timeout) {
cfa858 782     var s = document.querySelector('.sued');
a43e1a 783     s.classList.add('sued-open');
U 784     s.style.height = '1.5em';
cfa858 785     s.textContent = meldung;
f074f6 786     setTimeout(function () {
cfa858 787       s.textContent = 'Bereit.';
f074f6 788       setTimeout(function () {
cfa858 789         var suedDiv = document.querySelector('.sued');
f074f6 790         if (suedDiv.classList.contains('sued-open')) {
U 791           suedDiv.classList.remove('sued-open');
792           suedDiv.style.height = '0';
cfa858 793         }
U 794       }, 500);
795     }, timeout);
796   };
8239d1 797   
f45e20 798   /* --------------------- Dialog-Funktionen ------------------------ */
cfa858 799
U 800   /*
f074f6 801    Einen Dialog aus Vorlagen erzeugen
U 802    
803    vurl - URL zur Dialogvorlage
804    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
805    */
5b7356 806   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 807     var vorlage = self.cache[vurl];
808     if(vorlage === undefined) {
809       self.http_get(vurl, function(antwort) {
810         self.cache[vurl] = antwort;
811         self.dialog_zeigen(vurl, msgTpl, cb);
f074f6 812       });
cfa858 813     } else {
5b7356 814       self.dialog_zeigen(vurl, msgTpl, cb);
cfa858 815     }
U 816   };
817
5b7356 818   this.dialog_zeigen = function (vurl, inhalt, cb) {
U 819     var dlg = document.querySelector(".dialog");
2597cd 820     self.html_erzeugen(vurl, inhalt, function (html) {
U 821       dlg.style.height = '7em';
822       dlg.innerHTML = html;
823       document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
824       if(typeof(cb) !== 'function') {
825         // ..
826       } else {
827         cb();
828       }
829     });
5b7356 830   };
2597cd 831   
f45e20 832   this.dialog_schliessen = function () {
cfa858 833     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 834     var dlg = document.querySelector('.dialog');
835     dlg.style.height = '0';
836     dlg.innerHTML = '';
837   };
838
f45e20 839   /* ---------------------   Vorlagen   ---------------------- */
cfa858 840
U 841   /*
f074f6 842    Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt
U 843    gefüllt wird
844    
845    Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem
846    Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten.
847    Das fertige HTML wird der Callback-Funktion übergeben
848    sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der
849    Programmlauf zu diesem Zeitpunkt mittlerweile ist.
850    
851    vurl - URL zur Vorlagendatei
852    inhalt - die JSON-Struktur, deren Inhalt in die
853    Vorlage gefüllt werden soll
854    cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist.
855    Dieser Callback-Funktion wird das fertige HTML übergeben
856    */
857   this.html_erzeugen = function (vurl, inhalt, cb) {
cfa858 858     var vorlage = self.cache[vurl];
f074f6 859     if (vorlage === undefined) {
cfa858 860       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
U 861     } else {
862       self.vorlage_fuellen(vurl, inhalt, cb);
863     }
864   };
865
f074f6 866   this.vorlage_fuellen = function (vurl, inhalt, cb) {
cfa858 867     cb(Mustache.render(self.cache[vurl], inhalt));
U 868   };
869
870   /*
f074f6 871    Eine Vorlage vom Server in den lokalen Speicher laden
U 872    vurl - der URL unter dem die Vorlage zu finden ist
873    inhalt - die JSON-Struktur, deren Inhalt in die
874    Vorlage gefüllt werden soll
875    cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem
876    Inhalt gefüllt ist
877    */
878   this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) {
cfa858 879     var xmlhttp = new XMLHttpRequest();
f074f6 880     xmlhttp.onreadystatechange = function () {
cfa858 881       if (this.readyState == 4 && this.status == 200) {
U 882         self.cache[vurl] = this.responseText;
883         self.vorlage_fuellen(vurl, inhalt, cb);
884       }
885     };
886     xmlhttp.open("GET", vurl, true);
887     xmlhttp.send();
888   };
889
890
891 }
892
f45e20 893 /* ----------- Objekte ---------------- */
U 894
895 function Ablageort(n, o, u) {
896   this.name = n;
897   this.ort = o;
898   this.url = u;
899 }
900
901 function Einstellung(k, v) {
902   this.key = k;
903   this.value = v;
904 }
905
906 function Abspieler(n, u) {
907   this.name = n;
908   this.url = u;
8d7d35 909 }
U 910
d027b5 911 function Livestream(n, u) {
U 912   this.name = n;
913   this.url = u;
914 }
915
8d7d35 916 function Abspielliste(n) {
U 917   this.name = n;
e60cff 918 }
U 919
245ac1 920 function Titel(n, p, u, i, t, a) {
e60cff 921   this.katalogUrl = u;
2bdd78 922   this.pfad = p;
e60cff 923   this.name = n;
245ac1 924   this.interpret = i;
U 925   this.titelAnzName = t;
926   this.album  = a;
3929b0 927 }
U 928
a29f5c 929 function Geraet(n, e, a, s, st) {
3929b0 930   this.name = n;
U 931   this.einUrl = e;
932   this.ausUrl = a;
933   this.statusUrl = s;
a29f5c 934   this.status = st;
d6b78c 935 }