Persoenliche Mediazentrale
ulrich
2021-04-07 dce2c79a03b834887f4da33b090a430e9756aac1
commit | author | age
b379f5 1 function Ablageort(n, o, u) {
U 2   this.name = n;
3   this.ort = o;
4   this.url = u;
5 }
6
cf6509 7 function Einstellung(k, v) {
U 8   this.key = k;
9   this.value = v;
10 }
b379f5 11
U 12
13 function Mediazentrale() {
cfa858 14   var self = this;
U 15   var appMenu;
16   var cache; // mustache templates
86bbf7 17   var ortPfad;
U 18   var mediaPfad;
19   
20   // auf der obersten Ebene werden die Kataloge angezeigt,
21   // darunter der Inhalt des aktuellen Pfades
22   this.media_liste = function() {
23     if(self.ortPfad === '/') {
24       // Kataloge listen
25       self.http_get('../api/store/Ablageort/', function (responseText) {
26         self.vorlage_laden_und_fuellen("data/tpl/katalog_root_liste.tpl", JSON.parse(responseText), function (html) {
27           document.querySelector(".zentraler-inhalt").innerHTML = html;
28           self.addEvtListener('.entity-eintrag', 'click', function (event) {
29             var t = event.target;
30             self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText) {
31               var ablageort = JSON.parse(responseText);
32               self.ortPfad = ablageort.url;
33               self.media_liste();
34             });
35           });
36         });
37       });
38     } else {
39       // Pfad listen
40       self.http_get('..' + self.ortPfad + '/' + self.mediaPfad + '/', function(responseText) {
ca9872 41         //console.log(responseText);
86bbf7 42         self.vorlage_laden_und_fuellen("data/tpl/katalog_inhalt_liste.tpl", JSON.parse(responseText), function (html) {
U 43           document.querySelector(".zentraler-inhalt").innerHTML = html;
44           self.addEvtListener('.entity-eintrag', 'click', function (event) {
45             var t = event.target;
ca9872 46             //console.log(t.textContent);
86bbf7 47             if(t.classList.contains("entity-typ-folder")) {
U 48               self.mediaPfad = self.mediaPfad + '/' + t.textContent;
49               self.media_liste();
50             } else {
51               console.log("Media-Inhalt auswaehlen oder abspielen");
7c22a2 52               self.removeClassMulti('selected');
U 53               t.classList.add('selected');
86bbf7 54             }
U 55           });
56           self.addEvtListener('#zurueck-btn', 'click', function (event) {
57             if(self.mediaPfad === '/') {
58               self.ortPfad = '/';              
59             } else {
60               var pos = self.mediaPfad.lastIndexOf('/');
61               var parent = self.mediaPfad.substring(0, pos);
ca9872 62               //console.log("Parent: " + parent);
86bbf7 63               self.mediaPfad = parent;
U 64             }
65             self.media_liste();
66           });        
67         });
68       });
69     }
70   };
cf6509 71   
U 72   /* Die folgenden '_liste' Funktionen koennen noch vereinheitlicht werden */
cfa858 73
a43e1a 74   this.ablageort_liste = function() {
U 75     self.http_get('../api/store/Ablageort/', function (responseText) {
76       self.vorlage_laden_und_fuellen("data/tpl/ablageort_liste.tpl", JSON.parse(responseText), function (html) {
77         document.querySelector(".zentraler-inhalt").innerHTML = html;
78         self.addEvtListener('.entity-eintrag', 'click', function (event) {
79           var t = event.target;
90f5d4 80           self.http_get('../api/store/Ablageort/' + t.textContent, function(responseText){
86bbf7 81             var ablageort = JSON.parse(responseText);
90f5d4 82             self.ablageort_form(ablageort);
U 83           });
a43e1a 84         });
faab2d 85         self.addEvtListener('#neu-btn', 'click', function (event) {
U 86           eval("self.ablageort_form" + "(this)");
87         });        
cf6509 88       });
U 89     });
90   };
91
92   this.prefs_liste = function() {
93     self.http_get('../api/store/Einstellung/', function (responseText) {
94       self.vorlage_laden_und_fuellen("data/tpl/einstellung_liste.tpl", JSON.parse(responseText), function (html) {
95         document.querySelector(".zentraler-inhalt").innerHTML = html;
96         self.addEvtListener('.entity-eintrag', 'click', function (event) {
97           var t = event.target;
98           self.http_get('../api/store/Einstellung/' + t.textContent, function(responseText){
99             var einstellung = JSON.parse(responseText);
100             self.prefs_form(einstellung);
101           });
102         });
103         self.addEvtListener('#neu-btn', 'click', function (event) {
104           eval("self.prefs_form" + "(this)");
105         });        
106       });
107     });
108   };
109
110   /* Die folgenden '_form' Funktionen koennen noch vereinheitlicht werden */
111
112   this.prefs_form = function(k) {
113     self.vorlage_laden_und_fuellen("data/tpl/form_einstellung.tpl", k, function (html) {
114       document.querySelector(".zentraler-inhalt").innerHTML = html;
115       self.addEvtListener('#ok-btn', 'click', function () {
116         var pkey = document.querySelector('#einstellung-key').value;
117         pkey = pkey.replace(' ', '').replace(/[\W]+/g, '');
118         var pref = new Einstellung(
119           pkey,
120           document.querySelector('#einstellung-value').value
121         );
122         var daten = JSON.stringify(pref);        
123         if(typeof k === "undefined" || k.key !== pkey) {
124           // neu
125           self.http_post('../api/store/Einstellung', daten, function (responseText) {
126             // hier die Antwort verarbeiten
127           });
128         } else {
129           // aendern
130           self.http_put('../api/store/Einstellung', daten, function (responseText) {
131             // hier die Antwort verarbeiten
132           });
133         }
134         //document.querySelector(".zentraler-inhalt").innerHTML = '';
135         self.prefs_liste();
136       });
137       self.addEvtListener('#cancel-btn', 'click', function () {
138         //document.querySelector(".zentraler-inhalt").innerHTML = '';
139         self.prefs_liste();
140       });
141       self.addEvtListener('#loeschen-btn', 'click', function() {
142         var pkey = document.querySelector('#einstellung-key').value;
143         var dlgdata = {"del-elem": pkey};
144         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
145           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
146           self.addEvtListener('#ja-btn', 'click', function() {
147             self.http_delete('../api/store/Einstellung/' + pkey, '', function (responseText) {
148               // hier die Antwort verarbeiten
149               self.dialog_schliessen();
150               //document.querySelector(".zentraler-inhalt").innerHTML = '';
151               self.prefs_liste();
152             });
153           });
154         });
a43e1a 155       });
U 156     });
157   };
cfa858 158
90f5d4 159   /* 
U 160    * Ablageort-Formular anzeigen
161    * 
162    * {"name":"Katalog 2","ort":"/home/ulrich/Videos","url":"/media/kat2"}: 
163    * 
164    * @param {type} ablageort  der Ablageort, der bearbeitet werden soll, leer fuer neuen Ort
165    * @returns {undefined} kein Rueckgabewert
166    */
167   this.ablageort_form = function(ort) {
168     self.vorlage_laden_und_fuellen("data/tpl/form_ablageort.tpl", ort, function (html) {
b379f5 169       document.querySelector(".zentraler-inhalt").innerHTML = html;
f074f6 170       self.addEvtListener('#ok-btn', 'click', function () {
2597cd 171         var aName = document.querySelector('#ablageort-name').value;
U 172         aName = aName.replace(' ', '').replace(/[\W]+/g, '');
b379f5 173         var a = new Ablageort(
2597cd 174           aName,
b379f5 175           document.querySelector('#ablageort-ort').value,
U 176           document.querySelector('#ablageort-url').value
177         );
90f5d4 178         var daten = JSON.stringify(a);        
2597cd 179         if(typeof ort === "undefined" || ort.name !== aName) {
U 180           // neu
90f5d4 181           self.http_post('../api/store/Ablageort', daten, function (responseText) {
U 182             // hier die Antwort verarbeiten
183           });
184         } else {
2597cd 185           // aendern
90f5d4 186           self.http_put('../api/store/Ablageort', daten, function (responseText) {
U 187             // hier die Antwort verarbeiten
188           });
189         }
b29119 190         //document.querySelector(".zentraler-inhalt").innerHTML = '';
faab2d 191         self.ablageort_liste();
b379f5 192       });
f074f6 193       self.addEvtListener('#cancel-btn', 'click', function () {
b29119 194         //document.querySelector(".zentraler-inhalt").innerHTML = '';
faab2d 195         self.ablageort_liste();
5b7356 196       });
U 197       self.addEvtListener('#loeschen-btn', 'click', function() {
198         var aoname = document.querySelector('#ablageort-name').value;
199         var dlgdata = {"del-elem": aoname};
200         self.dialog_laden_und_zeigen('data/tpl/dlg-loeschen.tpl', dlgdata, function() {
201           self.addEvtListener('#nein-btn', 'click', self.dialog_schliessen);
202           self.addEvtListener('#ja-btn', 'click', function() {
90f5d4 203             self.http_delete('../api/store/Ablageort/' + aoname, '', function (responseText) {
U 204               // hier die Antwort verarbeiten
2597cd 205               self.dialog_schliessen();
b29119 206               //document.querySelector(".zentraler-inhalt").innerHTML = '';
faab2d 207               self.ablageort_liste();
90f5d4 208             });
5b7356 209           });
U 210         });
b379f5 211       });
U 212     });
213   };
214
7c22a2 215   this.addEvtListener = function(selector, eventName, func) {
U 216     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
217   };
218   
219   this.removeClassMulti = function(selector) {
220     document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); });
221   };
222
223   /*
f074f6 224   this.addEvtListener = function (selector, eventName, func) {
b379f5 225     var elems = document.querySelectorAll(selector);
U 226     var index;
227     for (index = 0; index < elems.length; index++) {
228       elems[index].addEventListener(eventName, func);
229     }
230   };
7c22a2 231   */
U 232   
233   // document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
f074f6 234
faab2d 235   /* asynchroner HTTP Client */
U 236   
f074f6 237   this.http_get = function (u, cb) {
b379f5 238     self.http_call('GET', u, null, cb);
U 239   };
f074f6 240
U 241   this.http_post = function (u, data, cb) {
b379f5 242     self.http_call('POST', u, data, cb);
U 243   };
244
90f5d4 245   this.http_put = function (u, data, cb) {
U 246     self.http_call('PUT', u, data, cb);
247   };
248   
5b7356 249   this.http_delete = function (u, data, cb) {
2597cd 250     console.log("delete " + u);
5b7356 251     self.http_call('DELETE', u, data, cb);
U 252   };
253   
f074f6 254   this.http_call = function (method, u, data, scallback) {
b379f5 255     var xhr = new XMLHttpRequest();
U 256     var url = u;
f074f6 257     xhr.onreadystatechange = function () {
b379f5 258       if (this.readyState === 4 && this.status === 200) {
U 259         scallback(this.responseText);
260       }
261     };
262     xhr.open(method, url);
f074f6 263     if (method === 'GET') {
b379f5 264       xhr.send();
2597cd 265     } else if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
b379f5 266       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
U 267       xhr.send(data);
268     }
269   };
8239d1 270   
U 271   /* Unterer Einblendbereich */
272   
273   self.dialog_unten_zeigen = function() {
bebd47 274     self.vorlage_laden_und_fuellen("data/tpl/ctrl.tpl", "", function (html) {
U 275       var dlg = document.querySelector(".dialog-unten");
276       dlg.style.height = '4.5em';
277       dlg.innerHTML = html;
278     });
8239d1 279   };
f074f6 280
U 281   /* ab hier aus App-Vorlage */
282
283   this.init = function () {
cfa858 284     //self.vorlagen = new Vorlagen();
86bbf7 285     self.mediaPfad = '/';
U 286     self.ortPfad = '/';
cfa858 287     self.cache = new Array();
U 288     self.appMenu = new AppMenu();
289     self.appMenu.init(
f074f6 290             "data/menu/",
U 291             "hauptmenue.json",
292             "data/tpl/app-menu.tpl",
293             ".west",
294             "8em");
cfa858 295
f074f6 296     document.querySelector('.hamburger').addEventListener('click', function (e) {
cfa858 297       self.menue_umschalten();
U 298     });
f074f6 299     
b90d67 300     self.addEvtListener('#mi-katalog', 'click', self.media_liste);
U 301     self.addEvtListener('#mi-orte', 'click', self.ablageort_liste);
cf6509 302     self.addEvtListener('#mi-prefs', 'click', self.prefs_liste);
b90d67 303     //self.addEvtListener('#mi-list', 'click', self.media_liste);    
U 304     
f074f6 305     self.fusszeile_umschalten();
U 306     self.seitenleiste_umschalten();
bebd47 307     self.dialog_unten_zeigen();
cfa858 308   };
U 309
f074f6 310   this.menue_umschalten = function () {
cfa858 311     var ham = document.querySelector(".hamburger");
U 312     ham.classList.toggle("is-active"); // hamburger-icon umschalten
313     self.appMenu.toggle(); // menue oeffnen/schliessen
314   };
315
f074f6 316   this.info_dialog_zeigen = function () {
cfa858 317     self.dialog_laden_und_zeigen('data/tpl/dlg-info.tpl', '');
U 318     self.menue_umschalten();
319   };
320
f074f6 321   this.seitenleiste_umschalten = function () {
cfa858 322     var ostDiv = document.querySelector('.ost');
f074f6 323     if (ostDiv.classList.contains('ost-open')) {
cfa858 324       ostDiv.classList.remove('ost-open');
f074f6 325       ostDiv.style.flexBasis = '0em';
cfa858 326     } else {
f074f6 327       ostDiv.classList.add('ost-open');
U 328       ostDiv.style.flexBasis = '6em';
cfa858 329     }
U 330     self.menue_umschalten();
331   };
332
f074f6 333   this.fusszeile_umschalten = function () {
cfa858 334     var suedDiv = document.querySelector('.sued');
f074f6 335     if (suedDiv.classList.contains('sued-open')) {
cfa858 336       suedDiv.classList.remove('sued-open');
f074f6 337       suedDiv.style.height = '0';
cfa858 338     } else {
U 339       suedDiv.classList.add('sued-open');
f074f6 340       suedDiv.style.height = '1.5em';
cfa858 341     }
U 342     self.menue_umschalten();
343   };
344
f074f6 345   this.menu_message = function (msg) {
cfa858 346     self.meldung_mit_timeout(msg, 1500);
U 347     var suedDiv = document.querySelector('.sued');
f074f6 348     if (suedDiv.classList.contains('sued-open')) {
cfa858 349     } else {
U 350       suedDiv.classList.add('sued-open');
f074f6 351       suedDiv.style.height = '1.5em';
cfa858 352     }
U 353     self.menue_umschalten();
354   };
355
f074f6 356   this.message_1 = function () {
cfa858 357     self.menu_message('Eine Mitteilung.');
U 358   };
359
f074f6 360   this.message_2 = function () {
cfa858 361     self.menu_message('Was wir schon immer sagen wollten.');
U 362   };
363
f074f6 364   this.message_3 = function (text) {
cfa858 365     self.menu_message(text);
U 366   };
367
f074f6 368   this.meldung_mit_timeout = function (meldung, timeout) {
cfa858 369     var s = document.querySelector('.sued');
a43e1a 370     s.classList.add('sued-open');
U 371     s.style.height = '1.5em';
cfa858 372     s.textContent = meldung;
f074f6 373     setTimeout(function () {
cfa858 374       s.textContent = 'Bereit.';
f074f6 375       setTimeout(function () {
cfa858 376         var suedDiv = document.querySelector('.sued');
f074f6 377         if (suedDiv.classList.contains('sued-open')) {
U 378           suedDiv.classList.remove('sued-open');
379           suedDiv.style.height = '0';
cfa858 380         }
U 381       }, 500);
382     }, timeout);
383   };
8239d1 384   
cfa858 385   /* Dialog-Funktionen */
U 386
387   /*
f074f6 388    Einen Dialog aus Vorlagen erzeugen
U 389    
390    vurl - URL zur Dialogvorlage
391    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
392    */
5b7356 393   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 394     var vorlage = self.cache[vurl];
395     if(vorlage === undefined) {
396       self.http_get(vurl, function(antwort) {
397         self.cache[vurl] = antwort;
398         self.dialog_zeigen(vurl, msgTpl, cb);
f074f6 399       });
cfa858 400     } else {
5b7356 401       self.dialog_zeigen(vurl, msgTpl, cb);
cfa858 402     }
U 403   };
404
5b7356 405   this.dialog_zeigen = function (vurl, inhalt, cb) {
U 406     var dlg = document.querySelector(".dialog");
2597cd 407     self.html_erzeugen(vurl, inhalt, function (html) {
U 408       dlg.style.height = '7em';
409       dlg.innerHTML = html;
410       document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
411       if(typeof(cb) !== 'function') {
412         // ..
413       } else {
414         cb();
415       }
416     });
5b7356 417   };
2597cd 418   
f074f6 419   self.dialog_schliessen = function () {
cfa858 420     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 421     var dlg = document.querySelector('.dialog');
422     dlg.style.height = '0';
423     dlg.innerHTML = '';
424   };
425
426   /* Vorlagen */
427
428   /*
f074f6 429    Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt
U 430    gefüllt wird
431    
432    Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem
433    Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten.
434    Das fertige HTML wird der Callback-Funktion übergeben
435    sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der
436    Programmlauf zu diesem Zeitpunkt mittlerweile ist.
437    
438    vurl - URL zur Vorlagendatei
439    inhalt - die JSON-Struktur, deren Inhalt in die
440    Vorlage gefüllt werden soll
441    cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist.
442    Dieser Callback-Funktion wird das fertige HTML übergeben
443    */
444   this.html_erzeugen = function (vurl, inhalt, cb) {
cfa858 445     var vorlage = self.cache[vurl];
f074f6 446     if (vorlage === undefined) {
cfa858 447       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
U 448     } else {
449       self.vorlage_fuellen(vurl, inhalt, cb);
450     }
451   };
452
f074f6 453   this.vorlage_fuellen = function (vurl, inhalt, cb) {
cfa858 454     cb(Mustache.render(self.cache[vurl], inhalt));
U 455   };
456
457   /*
f074f6 458    Eine Vorlage vom Server in den lokalen Speicher laden
U 459    vurl - der URL unter dem die Vorlage zu finden ist
460    inhalt - die JSON-Struktur, deren Inhalt in die
461    Vorlage gefüllt werden soll
462    cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem
463    Inhalt gefüllt ist
464    */
465   this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) {
cfa858 466     var xmlhttp = new XMLHttpRequest();
f074f6 467     xmlhttp.onreadystatechange = function () {
cfa858 468       if (this.readyState == 4 && this.status == 200) {
U 469         self.cache[vurl] = this.responseText;
470         self.vorlage_fuellen(vurl, inhalt, cb);
471       }
472     };
473     xmlhttp.open("GET", vurl, true);
474     xmlhttp.send();
475   };
476
477
478 }
479