Dateiverwaltung für die WebBox
ulrich
2021-01-20 8209533883044451ce7e1742f5a10c4b78679fc3
commit | author | age
05e9c4 1 function AppVorlage() {
U 2   var self = this;
41ab37 3   this.appMenu;
4e450e 4   //this.vorlagen;
41ab37 5   this.api;
U 6   this.userid;
7   this.pfad = '';
8   this.loc;
9   this.modus = 'kacheln';
ebc1f3 10   this.cm;
4e450e 11   //this.tinymce;
U 12   this.ed;
13   this.tmo;
14   this.tmo2;
41ab37 15   this.PERS_DIR = "Persoenlich";
U 16   this.PUB_DIR = "Oeffentlich";
17   this.DAV_DIR = "Austausch";
18   this.BASE_DIR = "$basis";
19   this.DATA_DIR = "$daten";
20   this.WWW_DIR = "www";
f002d9 21   this.openEditor;
U 22   this.openFileName;
beb124 23   this.cutCopyOperation;
U 24   this.cutCopySrcDir;
25   this.cutCopyFiles;
820953 26   this.dateien;
41ab37 27   this.cache = {}; // mustache template cache
05e9c4 28
94b871 29   this.datei_neuer_text = function () {
ebc1f3 30     //self.meldung_mit_timeout("Neuer Text", 1500);
U 31     self.fm_text_edit('Neue Datei');
32   };
33   
05e9c4 34   /* Funktionen aus App-Vorlage */
94b871 35
4e450e 36   this.init = function () {    
f002d9 37     document.querySelector(".codeeditor-space").style.display = "none";
U 38     document.querySelector("#mce-editor").style.display = "none";
05e9c4 39     self.appMenu = new AppMenu();
U 40     self.appMenu.init(
94b871 41             "data/menu/",
U 42             "hauptmenue.json",
43             "data/tpl/app-menu.tpl",
44             ".west",
45             "8em");
46     document.querySelector('.hamburger').addEventListener('click', function (e) {
05e9c4 47       self.menue_umschalten();
U 48     });
f32042 49     document.querySelector('#top-neuer-text-btn').addEventListener('click', self.datei_neuer_text);
U 50     document.querySelector('#top-neuer-ordner-btn').addEventListener('click', self.datei_neuer_ordner);
51     document.querySelector('#top-close-btn').addEventListener('click', self.fm_menu_datei_schliessen);
58bcbd 52     self.fm_get_login();
41ab37 53     
U 54     var parsedUrl = new URL(window.location.href);
55     var wunschPfad = parsedUrl.searchParams.get("pfad");
56
57     if(wunschPfad !== null && wunschPfad.length > 0) {
58       self.pfad = wunschPfad;
59       self.fm_get_list(wunschPfad);
60     } else {
61       self.fm_get_list('');
62     }
ebc1f3 63     
U 64     self.seitenleiste_umschalten();
820953 65     self.fm_init_uploader();
58bcbd 66     self.loc = window.location.protocol + '//' + window.location.host;
05e9c4 67   };
820953 68   
U 69   /* ----- Uploader Anfang ----------*/
70
71   this.fm_init_uploader = function() {
72     //console.log('init_uploader');
73     self.dateien = new Array();
74     var dropzone = document.getElementById("dateien");  
75     dropzone.ondragover = dropzone.ondragenter = function(event) {  
76       event.stopPropagation();  
77       event.preventDefault();  
78     };
79
80     dropzone.ondrop = function(event) {  
81       //console.log('dateien ondrop');
82       event.stopPropagation();  
83       event.preventDefault();  
84       var fileList = event.dataTransfer.files;  
85       for (var i=0; i<fileList.length; i++) {  
86         self.dateien.push(fileList[i]);
87         //console.log('upload ' + fileList[i]);
88       }
89       self.sendFile(self.dateien.pop());
90     };
91   };
92
93   /* ----- Uploader Ende --------------- */  
05e9c4 94
58bcbd 95   this.login_zeigen = function() {
U 96     self.meldung_mit_timeout("Benutzer: " + self.userid, 1500);
97   };
98   
b20b74 99   this.fm_neuer_reiter = function() {
U 100     window.open('/file-cms/ui2/?pfad=' + self.pfad, '_blank');
101   };
820953 102   
U 103   this.fm_hilfe = function() {
104     window.open('/data/dok/wbx-doku.html#wbx-bedienung', '_blank');
105   };
106
107   this.fm_view_slideshow = function() {
108
109     // https://localhost:8443/file-cms/fotos/?o=ulrich/bilder/diashow/ordnername
110
111
112     var userid = self.userid; // $('#userMenu').text();
113     //var gewaehlte = $('.datei-gewaehlt');
114     //var gewaehlte = document.querySelector('.datei-gewaehlt');
115     //var fname = gewaehlte.textContent;
116
117     var path = self.fm_get_path(userid);
118     var restdir = path;
119     if(path.indexOf('/data/') > -1) {
120       restdir = path.substr('/data/'.length);
121     }
122
123     //window.open('/file-cms/fotos/?o=' + userid + '/' + path + '/' + fname, '_blank');
124     window.open('/file-cms/fotos/?o=' + restdir + '/' /*+ fname*/, '_blank');
125   };
126
b20b74 127   
94b871 128   this.menue_umschalten = function () {
05e9c4 129     var ham = document.querySelector(".hamburger");
U 130     ham.classList.toggle("is-active"); // hamburger-icon umschalten
131     self.appMenu.toggle(); // menue oeffnen/schliessen
132   };
133
94b871 134   this.info_dialog_zeigen = function () {
05e9c4 135     self.dialog_laden_und_zeigen('data/tpl/dlg-info.tpl', '');
e342e0 136     //self.menue_umschalten();
05e9c4 137   };
U 138
94b871 139   this.seitenleiste_umschalten = function () {
05e9c4 140     var ostDiv = document.querySelector('.ost');
94b871 141     if (ostDiv.classList.contains('ost-open')) {
05e9c4 142       ostDiv.classList.remove('ost-open');
94b871 143       ostDiv.style.flexBasis = '0em';
05e9c4 144     } else {
94b871 145       ostDiv.classList.add('ost-open');
U 146       ostDiv.style.flexBasis = '6em';
05e9c4 147     }
ebc1f3 148     //self.menue_umschalten();
05e9c4 149   };
U 150
94b871 151   this.fusszeile_umschalten = function () {
05e9c4 152     var suedDiv = document.querySelector('.sued');
94b871 153     if (suedDiv.classList.contains('sued-open')) {
05e9c4 154       suedDiv.classList.remove('sued-open');
94b871 155       suedDiv.style.height = '0';
05e9c4 156     } else {
U 157       suedDiv.classList.add('sued-open');
94b871 158       suedDiv.style.height = '1.5em';
05e9c4 159     }
U 160     self.menue_umschalten();
161   };
162
94b871 163   this.meldung_mit_timeout = function (meldung, timeout) {
05e9c4 164     var s = document.querySelector('.sued');
U 165     s.textContent = meldung;
85ba85 166     s.classList.add('sued-open');
U 167     s.style.height = '1.5em';
94b871 168     setTimeout(function () {
05e9c4 169       s.textContent = 'Bereit.';
94b871 170       setTimeout(function () {
05e9c4 171         var suedDiv = document.querySelector('.sued');
94b871 172         if (suedDiv.classList.contains('sued-open')) {
U 173           suedDiv.classList.remove('sued-open');
174           suedDiv.style.height = '0';
05e9c4 175         }
U 176       }, 500);
177     }, timeout);
178   };
ebc1f3 179   
U 180   this.fm_menu_datei_schliessen = function() {
181     if(self.openEditor === 'text') {
182       if(!self.cm.getDoc().isClean()) {
183         self.fm_ask_for_save();
184       } else {
185         self.fm_do_close();
186       }
187     } else {
4e450e 188       if(tinymce.activeEditor.undoManager.hasUndo()) {
ebc1f3 189         self.fm_ask_for_save();
U 190       } else {
191         self.fm_do_close();
192       }
193     }
194   };  
195
196   this.fm_ask_for_save = function() {
197     self.dialog_laden_und_zeigen('data/tpl/dlg-ask-save.tpl', '', function() {
198       // wenn dialog da ist, hier events verknuepfen
199       document.querySelector('#cancel-btn').addEventListener('click', function() {
200         self.fm_do_close();
201         self.dialog_schliessen();
202       });
203       document.querySelector('#speichern-btn').addEventListener('click', function() {
204         self.fm_menu_datei_speichern(function() {
205           self.fm_do_close();
206           self.dialog_schliessen();
207         });
208       });
209     });
210   };
211
212   this.fm_menu_datei_speichern = function(callback) {
213     //var fname = $('.datei-gewaehlt').text();
214     var fname = self.openFileName;
215     if(fname !== undefined && fname !== '') {
216       self.fm_save_file(fname, 'saveTextFile', callback);
03be8f 217       self.meldung_mit_timeout(fname + ' gespeichert.', 1500);
ebc1f3 218     } else {
U 219       self.fm_menu_datei_speichern_unter(callback);
220     }
221   };
222   
223   this.fm_menu_datei_speichern_unter = function(callback) {  
224     self.dialog_laden_und_zeigen('data/tpl/dlg-save-as.tpl', '', function() {
5b4d03 225       document.querySelector('#cancel-btn').addEventListener('click', function() {
U 226         //self.fm_do_close();
227         self.dialog_schliessen();
228       });
229       document.querySelector('#speichern-btn').addEventListener('click', function() {
1a9589 230         //self.fm_menu_datei_speichern(function() {
U 231           //console.log(document.querySelector('#datei-name-in').value);
03be8f 232           var fname = document.querySelector('#datei-name-in').value;
U 233           self.fm_save_file(fname, 'saveTextFileAs', callback);
234           self.meldung_mit_timeout(fname + ' gespeichert.', 1500);
4e450e 235           if(typeof(callback) !== 'function') {
03be8f 236             //self.fm_do_close();
4e450e 237             self.dialog_schliessen();
U 238           }
1a9589 239         //});
5b4d03 240       });
ebc1f3 241     });    
4e450e 242   };
U 243   
244   this.fm_menu_neues_dokument = function() {
245     self.fm_dok_edit('');
ebc1f3 246   };
05e9c4 247
U 248   /* Dialog-Funktionen */
249
250   /*
94b871 251    Einen Dialog aus Vorlagen erzeugen
U 252    
253    vurl - URL zur Dialogvorlage
254    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
255    */
ebc1f3 256   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 257     var vorlage = self.cache[vurl];
258     if(vorlage === undefined) {
259       self.fm_get(vurl, "text", function(antwort) {
260         self.cache[vurl] = antwort;
261         self.dialog_zeigen(vurl, antwort, cb);
262         //self.vorlage_fuellen(vurl, inhalt, cb);
94b871 263       });
05e9c4 264     } else {
ebc1f3 265       self.dialog_zeigen(vurl, vorlage, cb);
05e9c4 266     }
U 267   };
268
ebc1f3 269   this.dialog_zeigen = function (vurl, inhalt, cb) {
05e9c4 270     var dlg = document.querySelector(".dialog");
ebc1f3 271     self.html_erzeugen(
94b871 272             vurl,
U 273             inhalt,
274             function (html) {
275               //dlg.html(html);
1a9589 276               dlg.style.height = '7em';
94b871 277               dlg.innerHTML = html;
U 278               document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
279               //dlg.slideDown(300);
ebc1f3 280               if(typeof(cb) !== 'function') {
U 281                 // ..
282               } else {
283                 cb();
284               }
94b871 285             });
05e9c4 286   };
U 287
58bcbd 288   this.dialog_schliessen = function () {
05e9c4 289     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 290     //$('.dialog').slideUp(300);
291     var dlg = document.querySelector('.dialog');
292     //dlg.style.display = "none";
293     dlg.style.height = '0';
294     dlg.innerHTML = '';
5b4d03 295     self.removeAllListeners('#cancel-btn');
U 296     self.removeAllListeners('#speichern-btn');
05e9c4 297   };
39e714 298   
U 299   this.fm_auswahl_marke_entfernen = function() {
300     var gew = document.querySelector('.datei-gewaehlt');
301     if(gew !== null) {
302       gew.classList.remove('datei-gewaehlt');
303     }        
304   };
0783c5 305   
U 306   this.fm_view_file = function() {
307     var fname = document.querySelector('.datei-gewaehlt').textContent;
308     var path = self.fm_get_path(self.userid);
309     window.open(path + '/' + fname, '_blank');
310   };
39e714 311
0783c5 312   this.datei_ansehen_oder_bearbeiten = function(dateiname) {
U 313     if(dateiname.endsWith('htmi')) {
314       self.fm_get_file_content('doc', dateiname);
315     } else if(dateiname.endsWith('jpg') || dateiname.endsWith('png') || 
98f80c 316             dateiname.endsWith('gif') || dateiname.endsWith('pdf') ) {
U 317       self.fm_view_file();
0783c5 318     } else {
U 319       self.fm_get_file_content('text', dateiname);      
320     }
39e714 321   };
U 322   
323   /**
85ba85 324    * Hier werden die folgenden Faelle einer Datei- 
U 325    * bzw. Ordnerauswahl ausgefuehrt:
326    * 
327    * geklickt, nicht gewaehlt: 
328    *    auswaehlen, evtl. bestehende andere Auswahl entfernen
329    *    
330    * geklickt, ausgewaehlt: 
331    *    Datei ansehen oder oeffnen bzw. Ordner oeffnen
332    *    
333    * geklickt mit [Strg], nicht gewahlt: 
334    *    auswaehlen, bestehende Auswahl beibehalten (Mehrfachauswahl)
335    *    
336    * geklickt mit [Strg], gewaehlt: 
337    *    Auswahl bei diesem Element entfernen
39e714 338    * 
U 339    * Diese Fälle sind unterteilt in 
85ba85 340    *    1. Kachel-Modus
U 341    *    2. Listenmodus
39e714 342    * 
85ba85 343    * @param {type} ev Klick-Event
U 344    * @returns {undefined} nichts 
39e714 345    */
6648a8 346   this.fm_dateiwahl = function(ev) {
U 347     var elem = ev.target;
348     if(self.modus == 'kacheln') {
349       // Kacheln
0783c5 350       var par = elem.parentElement;
U 351       var dElem = par.querySelector('.dateiname');
6648a8 352       if(elem.classList.contains("icon-folder")) {
39e714 353         // Ordner
0783c5 354         //var par = elem.parentElement;
U 355         var istGewaehlt = dElem.classList.contains('datei-gewaehlt');
39e714 356         if(istGewaehlt) {
U 357           if(/*ev.shiftKey || */ ev.ctrlKey) {
358             // mehrere Ordner sind gewaehlt, diese eine wieder entfernen
0783c5 359             dElem.classList.remove('datei-gewaehlt');
6648a8 360           } else {
39e714 361             // Ordner oeffnen
0783c5 362             var ordner = dElem.textContent.trim();
39e714 363             if(self.pfad.length > 0) {
U 364               self.pfad = self.pfad + '/' + ordner;
365             } else {
366               self.pfad = ordner;
367             }
368             self.fm_get_list(self.pfad);
6648a8 369           }
39e714 370         } else {
U 371           // Ordner auswaehlen
372           if(/*ev.shiftKey || */ ev.ctrlKey) {
373             // Mehrfachauswahl
374           } else {
375             self.fm_auswahl_marke_entfernen();
376           }
0783c5 377           dElem.classList.add('datei-gewaehlt');
6648a8 378         }
U 379       } else if(elem.classList.contains('datei')) {
39e714 380         // Datei
0783c5 381         //var par = elem.parentElement;
U 382         //var dElem = par.querySelector('.dateiname');
383         var istGewaehlt = dElem.classList.contains('datei-gewaehlt');
39e714 384         if(istGewaehlt) {
U 385           if(/*ev.shiftKey || */ ev.ctrlKey) {
386             // mehrere Dateien sind gewaehlt, diese eine wieder entfernen
0783c5 387             dElem.classList.remove('datei-gewaehlt');
39e714 388           } else {
U 389             // Datei zum Bearbeiten oeffnen
0783c5 390             self.datei_ansehen_oder_bearbeiten(dElem.textContent);
39e714 391           }
U 392         } else {
393           if(/*ev.shiftKey || */ ev.ctrlKey) {
394             // mehrere Dateien sollen gewaehlt werden
395           } else {
396             self.fm_auswahl_marke_entfernen();
397           }
0783c5 398           dElem.classList.add('datei-gewaehlt');
39e714 399         }
6648a8 400       } else {
U 401         //console.log('kein folder oder file...');
402       }
403     } else {
4f01b8 404       // Liste
U 405       var pElem = elem.closest('.datei-zeile');
406       var dElem = pElem.querySelector('.datei-elem');
0783c5 407       var dnElem = pElem.querySelector('.dateiname');
U 408       var istGewaehlt = dnElem.classList.contains('datei-gewaehlt');
4f01b8 409       if(dElem.getElementsByTagName("i")[0].classList.contains('icon-doc-text-inv')) {
6648a8 410         // Datei
39e714 411         if(istGewaehlt) {
U 412           if(/*ev.shiftKey || */ ev.ctrlKey) {
413             // mehrere Dateien sind gewaehlt, diese eine wieder entfernen
0783c5 414             dnElem.classList.remove('datei-gewaehlt');
39e714 415           } else {
U 416             // gewaehlte Datei ohne [Strg] geklickt: ansehen oder oeffnen
0783c5 417             self.datei_ansehen_oder_bearbeiten(dnElem.textContent);
39e714 418           }
6648a8 419         } else {
39e714 420           if(/*ev.shiftKey || */ ev.ctrlKey) {
U 421             // mehrere Dateien sollen gewaehlt werden, Auswahl ist weiter unten
422           } else {
423             var ti = document.querySelector('.table-info');
424             if(ti !== null) {
425               ti.classList.remove('table-info');
426             }
427             self.fm_auswahl_marke_entfernen();
4f01b8 428           }
39e714 429           pElem.classList.add('table-info');
0783c5 430           dnElem.classList.add('datei-gewaehlt');
6648a8 431         }
U 432       } else {
433         // Ordner
39e714 434         if(istGewaehlt) {
U 435           if(/*ev.shiftKey || */ ev.ctrlKey) {
436             // ein gewaehlter Ordner ist mit [Strg] geklickt, Auswahl entfernen
0783c5 437             dnElem.classList.remove('datei-gewaehlt');
6648a8 438           } else {
39e714 439             // Ordner oeffnen
0783c5 440             var ordner = dnElem.textContent;
39e714 441             if(self.pfad.length > 0) {
U 442               self.pfad = self.pfad + '/' + ordner;
443             } else {
444               self.pfad = ordner;
445             }
446             self.fm_get_list(self.pfad);
6648a8 447           }
39e714 448         } else {
U 449           if(/*ev.shiftKey || */ ev.ctrlKey) {
450             // nicht gewaehlter Ordner und [Strg]: zu Mehrfachauswahl hinzufuegen
451           } else {
452             // nicht gewaehlter Ordner ohne [Strg]: andere Auswhalen entfernen und weiter unten Ordner auswaehlen
453             self.fm_auswahl_marke_entfernen();
454           }
0783c5 455           dnElem.classList.add('datei-gewaehlt');
6648a8 456         }
U 457       }   
458     }
459   };
460  
41ab37 461   
58bcbd 462   this.fm_render_list = function (fl) {
4f01b8 463     if (self.modus === 'kacheln') {
58bcbd 464       // Kachelansicht
6648a8 465       self.html_erzeugen("data/tpl/kacheln.tpl", fl, function(html) {
U 466         var elem = document.querySelector('#dateien');
467         elem.innerHTML = html;
468         self.addEvtListener('.figure', 'click', self.fm_dateiwahl);
469       });
58bcbd 470     } else {
U 471       // Listenansicht
4f01b8 472       self.html_erzeugen("data/tpl/liste.tpl", fl, function(html) {
U 473         var elem = document.querySelector('#dateien');
474         elem.innerHTML = html;
475         self.addEvtListener('.datei-zeile', 'click', self.fm_dateiwahl);
476       });
58bcbd 477     }
U 478   };
479   
480   this.fm_get_path = function (uid) {
481     var restdir;
482     if (self.pfad.indexOf(self.PUB_DIR) > -1) {
483       restdir = self.pfad.substr(self.PUB_DIR.length);
484     } else if (self.pfad.indexOf(self.PERS_DIR) > -1) {
485       restdir = self.pfad.substr(self.PERS_DIR.length);
486     } else if (self.pfad.indexOf(self.BASE_DIR) > -1) {
487       restdir = self.pfad.substr(self.BASE_DIR.length);
488     } else if (self.pfad.indexOf(self.DATA_DIR) > -1) {
489       restdir = self.pfad.substr(self.DATA_DIR.length);
490     } else if (self.pfad.indexOf(self.DAV_DIR) > -1) {
491       restdir = self.pfad.substr(self.DAV_DIR.length);
492     }
493     if (restdir !== undefined && restdir.startsWith('/')) {
494       restdir = restdir.substr(1);
495       if (restdir.indexOf(self.WWW_DIR) > -1) {
496         restdir = restdir.replace(self.WWW_DIR, 'data');
497       }
498     }
41ab37 499     var pdir = self.fm_get_base(uid);
58bcbd 500     if (restdir.length > 1) {
U 501       return pdir + "/" + restdir;
502     } else {
503       return pdir;
504     }
505   };
506
507   this.fm_get_base = function (uid) {
508     var pdir;
509     if (self.pfad.indexOf(self.PUB_DIR) > -1) {
510       pdir = '/data/' + uid;
511     } else if (self.pfad.indexOf(self.PERS_DIR) > -1) {
512       pdir = '/home/' + uid;
513     } else if (self.pfad.indexOf(self.BASE_DIR) > -1) {
514       pdir = '';
515     } else if (self.pfad.indexOf(self.DATA_DIR) > -1) {
516       pdir = '';
517     }
518     return pdir;
519   };
2864b2 520   
U 521   /**
522    * Aus einem relativen Pfad ein Array aus BcrFile Objekten 
523    * machen
524    * 
525    * @param {String} relPfad  der relative Pfad
526    * @returns {Array}  die BcrFile-Objekte zum Pfad als Array
527    */
528   this.fm_buildBreadcrumb = function(relPfad) {
529     var rp = '';
530     var dirList = new Array();
531     dirList.push(new BcrFile(rp, 'Home'));
532     if(relPfad.length > 1) {
533       var dirs = relPfad.split('/');
534       for(var i = 0; i < dirs.length; i++) {
535         if(rp.length > 0 ) {
536           // weitere Einträge
537           dirList.push(new BcrFile(rp + '/' + dirs[i], dirs[i]));
538           rp = rp + '/' + dirs[i];
539         } else {
540           // erster Eintrag
541           dirList.push(new BcrFile(dirs[i], dirs[i]));
542           rp = dirs[i];
543         }
544       }
545     }
546     return dirList;
547   };
548   
4f01b8 549   /*
U 550    * icon-th-large
551    * icon-th-list
552    * @returns {undefined}
553    */
554   this.fm_ansicht_umschalten = function() {
555     var elem = document.querySelector('#ansicht');
556     var iElem = elem.getElementsByTagName("i")[0];
557     if(iElem.classList.contains('icon-th-list')) {
558       iElem.classList.add('icon-th-large');
559       iElem.classList.remove('icon-th-list');
560       self.modus = 'liste';
561     } else {
562       iElem.classList.add('icon-th-list');
563       iElem.classList.remove('icon-th-large');
564       self.modus = 'kacheln';
565     }
566     self.fm_get_list(self.pfad);    
567   };
568
569   this.fm_set_modus = function() {
570     var elem = document.querySelector('#ansicht');
571     var iElem = elem.getElementsByTagName("i")[0];
572     if(self.modus === 'kacheln') {
573       iElem.classList.add('icon-th-list');    
574       iElem.classList.remove('icon-th-large');
575     } else {
576       iElem.classList.add('icon-th-large');
577       iElem.classList.remove('icon-th-list');
578     }    
579   };
580
581   
2864b2 582   /**
U 583    * Der letzte Eintrag in dirs ist der aktuelle Ordner und 
584    * deshalb ausgegraut.
585    * 
586    * Wenn nur ein Ordner in dirs enthalten ist, dann sind wir 
587    * an der obersten Ebene (Home).
588    * 
589    * @param {Array} dirList ein Array aus BcrFile-Objekten
590    * @returns nichts 
591    */
592   this.fm_renderBreadcrumb = function(dirList) {
593     var elem = document.querySelector('.breadcrumb');
594     if(dirList.length > 1) {
595       var last = dirList.pop();
596       var bcList = new BcrFiles(dirList);
4f01b8 597       
2864b2 598       self.html_erzeugen("data/tpl/bcr.tpl", bcList, function(html) {
4f01b8 599         var htmlGesamt = html;
2864b2 600         self.html_erzeugen("data/tpl/bcr2.tpl", last, function(html) {
4f01b8 601           htmlGesamt += html;          
U 602           self.html_erzeugen("data/tpl/bcr3.tpl", dirList[0], function(html) {
603             htmlGesamt += html;
604             elem.innerHTML = htmlGesamt;
605             self.addEvtListener('.bc-link', 'click', self.fm_bc_click);
606             self.addEvtListener('#ansicht', 'click', self.fm_ansicht_umschalten);
607             self.fm_set_modus();
608           });
609           
2864b2 610         });                  
U 611       });            
612     } else {
613       // oberste Ebene
4f01b8 614       var htmla;
U 615       var htmlb;
2864b2 616       self.html_erzeugen("data/tpl/bcr2.tpl", dirList[0], function(html) {
4f01b8 617         htmla = html;        
U 618         self.html_erzeugen("data/tpl/bcr3.tpl", dirList[0], function(html) {
619           htmlb = html;
620           elem.innerHTML = htmla + htmlb;
621           self.addEvtListener('.bc-link', 'click', self.fm_bc_click);
622           self.addEvtListener('#ansicht', 'click', self.fm_ansicht_umschalten);
623           self.fm_set_modus();
624         });
2864b2 625       });            
U 626     }
627   };
628   
629   /**
630    * Auf den Klick auf ein Breadcrumb-Element reagieren:
631    * Den Ordner-Inhalt des geklickten Elements anzeigen
632    * @returns nichts
633    */
634   this.fm_bc_click = function() {
635     var elem = this;
636     var bcPfad = elem.getAttribute("rpath");
637     if(bcPfad !== undefined) {
638       self.pfad = bcPfad;
639       self.fm_get_list(bcPfad);
640     } else {
641       pfad = '';
642       self.fm_get_list('');
643     }
644   };
645
beb124 646   /* ------- Dateifunktionen Start ----------- */
U 647
648   this.fm_menu_cut = function() {
649     console.log('fm_menu_cut');
650     self.fm_cut_files();
651   };
39e714 652   this.fm_menu_copy = function() {
03be8f 653     //console.log('fm_menu_kopie');
beb124 654     self.fm_copy_files();
U 655   };
656   this.fm_menu_paste = function() {
657     console.log('fm_menu_paste');
658     self.fm_paste_files();
659   };
660   this.fm_menu_delete = function() {
661     self.dialog_laden_und_zeigen('data/tpl/dlg-ask-del.tpl', '', function() {
662       // wenn dialog da ist, hier events verknuepfen
663       document.querySelector('#cancel-btn').addEventListener('click', function() {
664         //self.fm_do_close();
665         self.dialog_schliessen();
666       });
667       document.querySelector('#speichern-btn').addEventListener('click', function() {
39e714 668         //self.fm_menu_datei_speichern(function() {
beb124 669           self.fm_del_files();
U 670           self.dialog_schliessen();
39e714 671         //});
beb124 672       });
U 673     });
674   };
675   
676   /*
677    * Hier merkt sich die Dateiverwalting die markierten Dateien fuer 
678    * eine Dateioperation. Bei cut wird in der 'paste' Operation auf dem Server 
679    * fuer die 'gemerkten' Dateien ein Move gemacht. Die Dateien werden 
680    * vom gewaehlten Ort zum Zielort verschoben.
681    * 
682    * @returns {undefined}
683    */
684   this.fm_cut_files = function() {
685     console.log('fm_cut_files');
686     self.cutCopySrcDir = self.pfad;
687     self.cutCopyFiles = self.fm_gewaehlte_dateien();
688     self.cutCopyOperation = 'cut';
03be8f 689     self.meldung_mit_timeout('zum Ausschneiden in Zwischenablage', 1500);
beb124 690   };
U 691
692   /*
693    * Hier merkt sich die Dateiverwalting die markierten Dateien fuer 
694    * eine Dateioperation. Bei copy wird in der 'paste' Operation auf dem Server 
695    * fuer die 'gemerkten' Dateien eine Kopie gemacht. Die Dateien werden 
696    * am gewaehlten Ort behalten und am Zielort wird eine Kopier der 
697    * gewaehlten DAteien erstellt
698    * 
699    * @returns {undefined}
700    */
701   this.fm_copy_files = function() {
03be8f 702     //console.log('fm_copy_files');
beb124 703     self.cutCopySrcDir = self.pfad;
U 704     self.cutCopyFiles = self.fm_gewaehlte_dateien();
705     self.cutCopyOperation = 'copy';
03be8f 706     self.meldung_mit_timeout('in Zwischenablage kopiert', 1500);
beb124 707   };
U 708   
709   
710
711   /*
712    * Gewaehlte Dateien feststellen
713    * 
714    * @returns {String} eine per JSON.stringify schon vorbereitete List zum 
715    * Absenden als Parameter an den Server
716    */
717   this.fm_gewaehlte_dateien = function() {
718     var gewaehlte = document.querySelectorAll('.datei-gewaehlt');
719     return self.fm_dateiliste_bilden(gewaehlte);
720   };
721
722   this.fm_dateiliste_bilden = function(gewaehlte) {
723     var fnames = new Array();
724     var i = 0;
725     while(i < gewaehlte.length) {
726       var str = { "java.lang.String": gewaehlte[i].innerText};
727       fnames.push(str);
728       //console.log('loeschen ' + pfad + ' ' + $(gewaehlte[i]).text());
729       //i += 2;
730       i++;
731     }
732     var liste = '{"List":' + JSON.stringify(fnames) + '}';
733     // 'liste' enthaelt:
734     // {"List":[{"java.lang.String":"test3.txt"},{"java.lang.String":"Test1.txt"},{"java.lang.String":"Test2.txt"}]}
735     // und wird auf dem Server zu einer List[ArrayList<String>] bei der jede ArrayList<String> nur ein Element hat 
736     console.log(liste);
737     return liste;
738   };
739
98f80c 740   this.fm_menu_datei_umbenennen = function() {
U 741     //var gewaehlte = $('.datei-gewaehlt');
742     var gewaehlte = document.querySelector('.datei-gewaehlt');
743     var fname = gewaehlte.textContent;
744     
745     self.dialog_laden_und_zeigen('data/tpl/dlg-rename.tpl', '', function() {
746       document.querySelector('#cancel-btn').addEventListener('click', function() {
747         self.dialog_schliessen();
748       });
749       document.querySelector('#speichern-btn').addEventListener('click', function() {
750         self.fm_rename_file(fname, self.pfad, document.querySelector('#datei-name-in').value);
751         self.dialog_schliessen();
752       });
753     });    
754     
755     /*
756     $('#modal_ok').click(function() {
757       // hier umbenennen
758       fm_rename_file(fname, pfad, $('#dateiname').val());
759     });
760     $('#saveModalTitle').text('Datei umbenennen');
761     $('#dialogfrage').text("Neuer Dateiname?");  
762
763     if(fname !== undefined) {
764       $('#dateiname').val(fname);
765       $('#dateiname').attr('placeholder', 'Dateiname');
766       $('#saveModal').modal({
767         keyboard: false,
768         show: true
769       });
770     }
771     */
772   };
773   
beb124 774   this.fm_menu_html_export = function() {
U 775     self.fm_export_html();
776   };
777
778   /* --------- Dateifunktionen Ende ---------- */
779
94b871 780   /* API functions */
05e9c4 781
94b871 782   // http://localhost:8079/file-cms/svc?c=de.uhilger.filecms.api.FileMgr&f=JSONNICE&m=list&p=
U 783   this.fm_get_list = function (relPfad) {
784     var m = '?c=de.uhilger.filecms.api.FileMgr&m=list&p=' + relPfad;
785     var u = '../svc' + m;
58bcbd 786     self.fm_get(u, "json", function (respText) {
U 787       var resp = JSON.parse(respText);
94b871 788       if (resp.List[0].FileRef !== undefined) {
U 789         var files = new Array();
790         if (resp.List[0].FileRef instanceof Array) {
791           for (var i = 0; i < resp.List[0].FileRef.length; i++) {
792             files.push(new FileRef(resp.List[0].FileRef[i]));
05e9c4 793           }
U 794         } else {
94b871 795           files.push(new FileRef(resp.List[0].FileRef));
05e9c4 796         }
94b871 797         var fl = new FileList(files);
58bcbd 798         self.fm_render_list(fl);
94b871 799       } else {
58bcbd 800         // #dateien leeren
8ba358 801         var elem = document.querySelector("#dateien");
U 802         elem.innerHTML = '';
94b871 803       }
8ba358 804       
U 805       // Breadcrumb
806       
2864b2 807       var dirList = self.fm_buildBreadcrumb(relPfad);
4f01b8 808       self.fm_renderBreadcrumb(dirList);     
94b871 809     });
U 810   };
f002d9 811   
1a9589 812   this.datei_neuer_ordner = function() {
U 813     self.dialog_laden_und_zeigen('data/tpl/dlg-ask-folder.tpl', '', function() {
814       document.querySelector('#cancel-btn').addEventListener('click', function() {
815         self.dialog_schliessen();
816       });
817       document.querySelector('#speichern-btn').addEventListener('click', function() {
818         var m = '?c=de.uhilger.filecms.api.FileMgr&m=newFolder&p=' + 
819                 self.pfad + 
820                 '&p=' + document.querySelector('#folder-name-in').value;
821         var u = '../svc' + m;
822         self.fm_get(u, "json", function(resp) {
823           self.dialog_schliessen();
824           self.fm_get_list(self.pfad);
825         });
826       });
827     });    
828   };
03be8f 829   
U 830   this.fm_open_file = function() {
831     var gewaehlte = document.querySelector('.datei-gewaehlt');
832     var fname = gewaehlte.textContent;
e342e0 833     self.datei_ansehen_oder_bearbeiten(fname);
U 834     /*
03be8f 835     if(fname.endsWith('htmi')) {
U 836       //self.fm_edit_as_doc();
837       self.fm_get_file_content('doc', fname);
838     } else {
839       //self.fm_edit_as_text();
840       self.fm_get_file_content('text', fname);
841     }
e342e0 842     */
03be8f 843   };
1a9589 844
03be8f 845   /*
ebc1f3 846   this.fm_edit_as_text = function() {
0783c5 847     self.fm_get_sel_for_file_content('text');
4e450e 848   };
U 849   
850   this.fm_edit_as_doc = function() {
0783c5 851     self.fm_get_sel_for_file_content('doc');
ebc1f3 852   };
U 853   
98f80c 854   this.fm_get_sel_for_file_content = function(typ) {
f002d9 855     var gewaehlte = document.querySelector('.datei-gewaehlt');
U 856     //var fname = $(gewaehlte).find('.dateiname').text();
857
858     var fname = gewaehlte.textContent;
0783c5 859     self.fm_get_file_content(typ, fname);
U 860   };
03be8f 861   */
0783c5 862   
U 863   this.fm_get_file_content = function(typ, fname) {
864     //var gewaehlte = document.querySelector('.datei-gewaehlt');
865     //var fname = $(gewaehlte).find('.dateiname').text();
866
867     //var fname = gewaehlte.textContent;
ebc1f3 868     //console.log('fname: ' + fname);
f002d9 869     self.openFileName = fname;
U 870     var m = '?c=de.uhilger.filecms.api.FileMgr&m=getCode&p=' + self.pfad + '&p=' + fname;
871     var u = '../svc' + m;
872     self.fm_get(u, "text", function(resp) {
873       if(typ === 'text') {
874         var mode = "text/x-java";
875         if(fname.endsWith('js')) {
876           mode = 'javascript';
877         } else if(fname.endsWith('xml')) {
878           mode = 'xml';
879         } else if(fname.endsWith('properties')) {
880           mode = 'xml';
881         } else if(fname.endsWith('adoc')) {
882           mode = 'text/x-markdown';
883         }
884         self.fm_text_edit(resp, mode);
885       } else {
886         self.fm_dok_edit(resp);
887       }
888     });
889   };
890
ebc1f3 891   this.fm_save_file = function(saveFileName, method, callback) {
U 892     var content;
893     if(self.openEditor === 'text') {
894       content = self.cm.getValue();
895       self.cm.getDoc().markClean();
896     } else {
4e450e 897       content = self.ed.getContent();
ebc1f3 898       tinymce.activeEditor.undoManager.clear();
U 899     }
900     var m = '?c=de.uhilger.filecms.api.FileMgr&m=' + method;
5b4d03 901     var u = '../svc' + m;
c79727 902     //var data = '&p=' + self.pfad + '&p=' + saveFileName + '&p=' + 
U 903     //        encodeURIComponent(content);
904     var data = '&p=' + self.pfad + '&p=' + saveFileName + '&p=' + 
905             encodeURIComponent(content);
906     // '{"foo": "bar"}'
907     
908     //var data = '{"p1": "' + self.pfad + '", "p2": "' + saveFileName + 
909     //        '", "p3": "' + encodeURIComponent(self.escapeHtml(content)) + '"}';
5b4d03 910     self.fm_post(u, data, "text", function(resp) {
U 911       // ...
ebc1f3 912     });
U 913     self.openFileName = saveFileName;
914     if(typeof (callback) !== 'function') {
915
916     } else {
917       callback();
918     }
919   };
920
beb124 921   /*
U 922    * Hier wird fuer eine zuvor markierte Liste von Dateien, fuer die 
923    * Cut oder Copy gewaehlt wurde, die Operations ausgefuehrt (move oder copy)
924    * @returns {undefined}
925    */
926   this.fm_paste_files = function() {
927     var m;
928     if(self.cutCopyOperation === 'cut') {
929       //m = '?c=de.uhilger.filecms.api.FileMgr&m=moveFiles'; //&p=' + cutCopySrcDir + '&p=' + pfad + '&p=' + encodeURIComponent(liste);
930       m = '?c=de.uhilger.filecms.api.FileMgr&m=moveFiles&p=' + self.cutCopySrcDir + '&p=' + self.pfad + '&p=' + encodeURIComponent(self.cutCopyFiles);
931     } else {
932       //m = '?c=de.uhilger.filecms.api.FileMgr&m=copyFiles'; //&p=' + cutCopySrcDir + '&p=' + pfad + '&p=' + encodeURIComponent(liste);
933       m = '?c=de.uhilger.filecms.api.FileMgr&m=copyFiles&p=' + self.cutCopySrcDir + '&p=' + self.pfad + '&p=' + encodeURIComponent(self.cutCopyFiles);
934     }
935     var u = '../svc' + m;  
936     self.fm_get(u, "text", function(resp) {
937       // console.log('deleteFiles gab folgendes zurueck: ' + resp);
938       self.fm_get_list(self.pfad);
939     });
940   };
ebc1f3 941
beb124 942   this.fm_del_files = function() {
U 943     var liste = self.fm_gewaehlte_dateien();
944     var m = '?c=de.uhilger.filecms.api.FileMgr&m=deleteFiles&p=' + self.pfad + '&p=' + encodeURIComponent(liste);
945     var u = '../svc' + m;
946     self.fm_get(u, "text", function(resp) {
947       // console.log('deleteFiles gab folgendes zurueck: ' + resp);
948       self.fm_get_list(self.pfad);
949     });
950   };
f002d9 951
98f80c 952   this.fm_rename_file = function(fn, p, neuerName) {
U 953     var m = '?c=de.uhilger.filecms.api.FileMgr&m=renameFile';
954     m = m + '&p=' + p; 
955     m = m + '&p=' + fn; 
956     m = m + '&p=' + neuerName; 
957     var u = '../svc' + m;
958     self.fm_get(u, "text", function(resp) {
959       self.fm_get_list(self.pfad);
960     });  
961   };
962
820953 963   /* -------- upload ----------- */
U 964
965   this.sendFile = function(datei) {
966     //console.log('sendFile ' + datei);
967     var uri = "../api/upload";
968     var xhr = new XMLHttpRequest();  
969     var fd = new FormData();  
970     xhr.open("POST", uri, true);  
971     xhr.onreadystatechange = function() {  
972       if (xhr.readyState === 4 && xhr.status === 200) {  
973         self.fm_get_list(self.pfad);
974         if(self.dateien.length > 0) {
975           self.sendFile(self.dateien.pop());
976         }
977       }  
978     };  
979     fd.append('dateiauswahlfeld', datei);  
980     fd.append('pfad', self.pfad);
981     xhr.send(fd);          
982   };
983
984   /* ---- codemirror editor handling -------- */
f002d9 985
U 986   /*
987   function htmlDecode(value){ 
988     return $('<div/>').html(value).text(); 
989   }
990   */
991
992   this.fm_code_edit = function(content, m) {
ebc1f3 993     //console.log('fm_code_edit content: ' + content.substring(0,30));
U 994     self.cm = CodeMirror.fromTextArea(document.getElementById("editspace"), {
f002d9 995       lineNumbers: true,
U 996       lineWrapping: true,
997       gutters: ["CodeMirror-linenumbers", "breakpoints"],
998       mode: m,
999       viewportMargin : Infinity,
1000       tabSize: 2,
1001       extraKeys: {
1002           "F9": function(cm) {
1003           cm.setOption("fullScreen", !cm.getOption("fullScreen"));
1004         },
1005           "Esc": function(cm) {
1006           if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
1007         },
1008           ".": function(cm) {
1009           console.log('dot pressed: perhaps look up class or method name');
1010           /*
1011            * Hier kann man eine Funktion ausloesen, die fuer das 
1012            * Wort vor dem Punkt (Name der Klasse) eine Liste mit 
1013            * Vorschlaegen fuer Methodennamen einblendet.
1014            */
1015
1016           /*
1017            * CodeMirror.Pass laesst das Zeichen zum Editorinhalt durch, 
1018            * verhindert aber das Ausloesen von 'keyHandled'
1019            */
1020           return CodeMirror.Pass; 
1021         }
1022       }
1023     });
1024     //cm.setValue(htmlDecode(content));
c79727 1025     //self.cm.setValue(content);
ebc1f3 1026     self.cm.setValue(self.unescapeHtml(content));
U 1027     self.cm.getDoc().markClean();
1028     self.cm.on("gutterClick", function(theEditor, lineNumber) {
f002d9 1029       var info = theEditor.lineInfo(lineNumber);
U 1030       //--lineNumber;
1031       //console.log(info.gutterMarkers.breakpoints.message);
1032       //var marker = info.gutterMarkers.breakpoints;
1033       //$(marker).tooltip('toggle');
1034     });
1035     /*
1036     cm.on("keyHandled", function(theEditor, keyName, event){
1037       console.log('cm.keyHandled keyName: ' + keyName + ', event.type: ' + event.type);    
1038     });
1039     */
1040   };
1041
1042   this.makeMarker = function(msg) {
1043     var marker = document.createElement("div");
1044     marker.style.color = "#822";
1045     marker.innerHTML = "●";
1046     //marker.message = msg;
1047     $(marker).tooltip({
1048       placement: 'right',
1049       title: msg,
1050       offset: '0 -30'
1051     });
1052     return marker;
1053   };
1054
4e450e 1055   /* ---- TinyMCE editor handling -------- */
U 1056
1057   this.fm_dok_editor_init = function(uid) {
1058     var base = self.fm_get_path(uid);
1059     //var edCount = 0;
1060     //console.log("fm_dok_editor_init calling tinymce.init with base: " + base + "/");
1061
1062     /*
1063      * vgl.
1064      * http://stackoverflow.com/questions/4651676/how-do-i-remove-tinymce-and-then-re-add-it
1065      */
1066     //tinymce.EditorManager.execCommand('mceRemoveControl',true, 'textarea.text-editor');
1067     //tinymce.EditorManager.execCommand('mceAddControl',true, editor_id);
1068     if(self.ed !== undefined) {
1069       self.ed.destroy();
1070     }
1071     if(tinymce !== undefined) {
1072       tinymce.remove('textarea.text-editor');
1073       tinymce.EditorManager.editors = []; 
1074     }
1075
1076     /*
1077      * Konfiguration TinyMCE
1078      */
1079     tinymce.init({
1080       content_css : "/file-cms/ui/mce.css",
1081       //content_css: "/jslib/bootstrap/css/bootstrap.min.css",
1082       selector: "textarea.text-editor",
1083       statusbar: false,
1084       menubar: false,
1085       plugins: 'advlist charmap code image link lists media table print preview save table textcolor importcss',
1086       toolbar: 'undo redo | styleselect | image table | link unlink | bullist numlist | outdent indent | code',
1087       /*
1088       menu: {
1089         file: {title: 'File', items: 'savevers | exit'},
1090         edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall'},
1091         view: {title: 'View', items: 'visualaid | code | link image media | template hr'},
1092       },
1093       */
1094       resize: 'both',
1095       importcss_append: true,
1096       width: "100%",
1097       height: '100%',
1098       relative_urls : true, 
1099       convert_urls : false, 
1100       document_base_url : base + "/",
1101       setup: function (editor) {
1102         self.ed = editor;
1103       }
1104     });
1105
1106     window.addEventListener('resize', self.fm_resize_editor);
1107     //$(window).on('resize', self.fm_resize_editor);
1108     self.fm_resize_editor();
1109   };
1110
1111   this.fm_resize_editor = function() {
1112     window.clearTimeout(self.tmo);
1113     self.tmo = window.setTimeout(function () {
1114       try {
1115         var myHeight = document.querySelector('.inhalt').offsetHeight - 
1116                 document.querySelector('.nord').offsetHeight + 2; // - 4;
1117         //console.log('myHeight: ' + myHeight);
1118         self.ed.theme.resizeTo('100%', myHeight);  // sets the dimensions of the editable area
1119       } catch (err) {
1120       }
1121     }, 200);
1122   };
1123
1124
f002d9 1125   
U 1126   /* -------- Editoren --------- */
1127   
1128   this.fm_text_edit = function(content, mode) {
1129     document.querySelector(".codeeditor-space").style.display = "block";
5b4d03 1130     //document.querySelector(".code-editor-container").style.display = "block";
U 1131     //document.querySelector(".zentrum-behaelter").style.display = "none";
1132     document.querySelector(".breadcrumb").style.display = "none";
1133     document.querySelector(".zentrum").style.display = "none";
f002d9 1134     self.fm_code_edit(content, mode);  
U 1135     self.openEditor = 'text';
1136   };
1137
1138   this.fm_dok_edit = function(content) {
1139     //fm_filectls_hide();
4e450e 1140     self.fm_dok_editor_init(self.userid);
U 1141     document.querySelector("#mce-editor").style.display = "block";
1142     //$("#mce-editor").show();
1143     document.querySelector(".breadcrumb").style.display = "none";
1144     document.querySelector(".zentrum").style.display = "none";
f002d9 1145
4e450e 1146     window.clearTimeout(self.tmo2);
U 1147     self.tmo2 = window.setTimeout(function () {
f002d9 1148       try {
4e450e 1149         self.ed.setContent(content);
U 1150         self.openEditor = 'dok';  
f002d9 1151       } catch (err) {
U 1152       }
1153     }, 200);
1154   };
ebc1f3 1155   
U 1156   this.fm_do_close = function() {
1157     document.querySelector(".codeeditor-space").style.display = "none";
4e450e 1158     document.querySelector("#mce-editor").style.display = "none";
U 1159     // $("#mce-editor").hide();
5b4d03 1160     //document.querySelector(".code-editor-container").style.display = "none";
U 1161     //document.querySelector(".zentrum-behaelter").style.display = "block";
1162     document.querySelector(".breadcrumb").style.display = "block";
1163     document.querySelector(".zentrum").style.display = "block";
ebc1f3 1164     if(self.cm !== undefined) {
U 1165       self.cm.toTextArea();
1166     }
1167     self.openFileName = '';
1168     self.openEditor = '';
1169     self.fm_get_list(self.pfad);
1170   };
05e9c4 1171
94b871 1172   /* -------- An- und Abmelden ------------- */
05e9c4 1173
94b871 1174   this.fm_get_login = function() {
U 1175     var m = '?c=de.uhilger.filecms.pub.SessionManager&m=getSessionUser';
1176     var u = '../pub' + m;
1177     self.fm_get(u, "text", function (resp) {
1178       self.userid = resp;
58bcbd 1179       self.login_zeigen();
U 1180       //document.querySelector("#userMenu").textContent = resp;
94b871 1181     });
U 1182   };
05e9c4 1183
94b871 1184   this.fm_logout = function() {
U 1185     var m = '?c=de.uhilger.filecms.pub.SessionManager&m=expireSession';
1186     var u = '../pub' + m;
1187     self.fm_get(u, "text", function (resp) {
1188       //$('#userMenu').text('nicht angemeldet');
1189       window.location.href = '../logout.html';
1190     });
1191   };
41ab37 1192   
6648a8 1193   /* ----- Hilfsfunktionen ----- */
U 1194
1195   this.serialisieren = function(obj) {
1196     return '{"' + obj.constructor.name + '":' + JSON.stringify(obj) + '}';
1197   };
1198   
1199   this.addEvtListener = function(selector, eventName, func) {
1200     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
1201   };
1202   
1203   this.removeAllListeners = function(id) {
1204     var el = document.getElementById(id);
5b4d03 1205     if(el !== null) {
U 1206       elClone = el.cloneNode(true);
1207       el.parentNode.replaceChild(elClone, el);
1208     }
6648a8 1209   }; // https://stackoverflow.com/questions/19469881/remove-all-event-listeners-of-specific-type
U 1210
ebc1f3 1211   this.escapeHtml = function(text) {
U 1212     text = text.replace(/\u228/g,'&auml;');
1213     text = text.replace(/\u246/g,'&ouml;');
1214     text = text.replace(/\u252/g,'&uuml;');
1215     text = text.replace(/\u196/g,'&Auml;');
1216     text = text.replace(/\u214/g,'&Ouml;');
1217     text = text.replace(/\u220/g,'&Uuml;');
1218     text = text.replace(/\u223/g,'&szlig;');
1219     text = text.replace(/\u26/g,'&amp;');
1220     return text;
1221   };
1222
1223   this.unescapeHtml = function(text) {
1224     text = text.replace(/&auml;/g, String.fromCharCode(228));
1225     text = text.replace(/&ouml;/g, String.fromCharCode(246));
1226     text = text.replace(/&uuml;/g, String.fromCharCode(252));
1227     text = text.replace(/&Auml;/g, String.fromCharCode(196));
1228     text = text.replace(/&Ouml;/g, String.fromCharCode(214));
1229     text = text.replace(/&Uuml;/g, String.fromCharCode(220));
1230     text = text.replace(/&szlig;/g, String.fromCharCode(223));
1231     text = text.replace(/&amp;/g, String.fromCharCode(26));
1232     return text;
1233   };
1234
41ab37 1235   /* ---- Vorlagen ---- */
U 1236
1237   this.html_erzeugen = function(vurl, inhalt, cb) {
1238     var vorlage = self.cache[vurl];
1239     if(vorlage === undefined) {
1240       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
1241     } else {
1242       self.vorlage_fuellen(vurl, inhalt, cb);
1243     }
1244   };
1245
1246   this.vorlage_fuellen = function(vurl, inhalt, cb) {
1247     cb(Mustache.render(self.cache[vurl], inhalt));
1248   };
1249
1250   this.vorlage_laden_und_fuellen = function(vurl, inhalt, cb) {
1251     self.fm_get(vurl, "text", function(antwort) {
1252       self.cache[vurl] = antwort;
1253       self.vorlage_fuellen(vurl, inhalt, cb);
1254     });
1255   };
94b871 1256
U 1257   /* -------- ajax helper functions ----------- */
1258
58bcbd 1259   this.fm_get = function (u, dtype, scallback) {    
U 1260     var xmlhttp = new XMLHttpRequest();
1261     var url = u;
1262     xmlhttp.onreadystatechange = function() {
5b4d03 1263       if (this.readyState === 4 && this.status === 200) {
58bcbd 1264         scallback(this.responseText);
94b871 1265       }
58bcbd 1266     };
U 1267     xmlhttp.open("GET", url, true);
1268     xmlhttp.send();
94b871 1269   };
ebc1f3 1270   
U 1271   self.fm_post = function(u, d, dtype, scallback) {
1272     var xmlhttp = new XMLHttpRequest();
1273     var url = u;
1274     xmlhttp.onreadystatechange = function() {
5b4d03 1275       if (this.readyState === 4 && this.status === 200) {
ebc1f3 1276         scallback(this.responseText);
U 1277       }
1278     };
1279     xmlhttp.open("POST", url, true);
c79727 1280     xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
5b4d03 1281     xmlhttp.send(d);
ebc1f3 1282   };
U 1283
5b4d03 1284   /*
ebc1f3 1285   this.http_get = function(u, cb)  {
U 1286     self.http_call('GET', u, null, cb);
1287   };
1288   
1289   this.http_post = function(u, data, cb) {
1290     self.http_call('POST', u, data, cb);
1291   };
1292
1293   this.http_call = function (method, u, data, scallback) {    
1294     var xhr = new XMLHttpRequest();
1295     var url = u;
1296     xhr.onreadystatechange = function() {
1297       if (this.readyState === 4 && this.status === 200) {
1298         scallback(this.responseText);
1299       }
1300     };
5b4d03 1301     xhr.open(method, url, false);
ebc1f3 1302     if(method === 'GET')  {
U 1303       xhr.send();
1304     } else if(method === 'POST' || method === 'PUT') {
1305       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
1306       xhr.send(data);
1307     }
1308   };
5b4d03 1309   */
ebc1f3 1310
94b871 1311
05e9c4 1312 }