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