Dateiverwaltung für die WebBox
ulrich
2021-01-16 ffc2b770a5181d3294813d16f745dfbc709f09df
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;
41ab37 23   this.cache = {}; // mustache template cache
05e9c4 24
94b871 25   this.datei_neuer_text = function () {
ebc1f3 26     //self.meldung_mit_timeout("Neuer Text", 1500);
U 27     self.fm_text_edit('Neue Datei');
28   };
29   
05e9c4 30   /* Funktionen aus App-Vorlage */
94b871 31
4e450e 32   this.init = function () {    
f002d9 33     document.querySelector(".codeeditor-space").style.display = "none";
U 34     document.querySelector("#mce-editor").style.display = "none";
05e9c4 35     self.appMenu = new AppMenu();
U 36     self.appMenu.init(
94b871 37             "data/menu/",
U 38             "hauptmenue.json",
39             "data/tpl/app-menu.tpl",
40             ".west",
41             "8em");
42     document.querySelector('.hamburger').addEventListener('click', function (e) {
05e9c4 43       self.menue_umschalten();
U 44     });
58bcbd 45     self.fm_get_login();
41ab37 46     
U 47     var parsedUrl = new URL(window.location.href);
48     var wunschPfad = parsedUrl.searchParams.get("pfad");
49
50     if(wunschPfad !== null && wunschPfad.length > 0) {
51       self.pfad = wunschPfad;
52       self.fm_get_list(wunschPfad);
53     } else {
54       self.fm_get_list('');
55     }
ebc1f3 56     
U 57     self.seitenleiste_umschalten();
41ab37 58     //fm_init_uploader();
58bcbd 59     self.loc = window.location.protocol + '//' + window.location.host;
05e9c4 60   };
U 61
58bcbd 62   this.login_zeigen = function() {
U 63     self.meldung_mit_timeout("Benutzer: " + self.userid, 1500);
64   };
65   
94b871 66   this.menue_umschalten = function () {
05e9c4 67     var ham = document.querySelector(".hamburger");
U 68     ham.classList.toggle("is-active"); // hamburger-icon umschalten
69     self.appMenu.toggle(); // menue oeffnen/schliessen
70   };
71
94b871 72   this.info_dialog_zeigen = function () {
05e9c4 73     self.dialog_laden_und_zeigen('data/tpl/dlg-info.tpl', '');
U 74     self.menue_umschalten();
75   };
76
94b871 77   this.seitenleiste_umschalten = function () {
05e9c4 78     var ostDiv = document.querySelector('.ost');
94b871 79     if (ostDiv.classList.contains('ost-open')) {
05e9c4 80       ostDiv.classList.remove('ost-open');
94b871 81       ostDiv.style.flexBasis = '0em';
05e9c4 82     } else {
94b871 83       ostDiv.classList.add('ost-open');
U 84       ostDiv.style.flexBasis = '6em';
05e9c4 85     }
ebc1f3 86     //self.menue_umschalten();
05e9c4 87   };
U 88
94b871 89   this.fusszeile_umschalten = function () {
05e9c4 90     var suedDiv = document.querySelector('.sued');
94b871 91     if (suedDiv.classList.contains('sued-open')) {
05e9c4 92       suedDiv.classList.remove('sued-open');
94b871 93       suedDiv.style.height = '0';
05e9c4 94     } else {
U 95       suedDiv.classList.add('sued-open');
94b871 96       suedDiv.style.height = '1.5em';
05e9c4 97     }
U 98     self.menue_umschalten();
99   };
100
94b871 101   this.meldung_mit_timeout = function (meldung, timeout) {
05e9c4 102     var s = document.querySelector('.sued');
U 103     s.textContent = meldung;
94b871 104     setTimeout(function () {
05e9c4 105       s.textContent = 'Bereit.';
94b871 106       setTimeout(function () {
05e9c4 107         var suedDiv = document.querySelector('.sued');
94b871 108         if (suedDiv.classList.contains('sued-open')) {
U 109           suedDiv.classList.remove('sued-open');
110           suedDiv.style.height = '0';
05e9c4 111         }
U 112       }, 500);
113     }, timeout);
114   };
ebc1f3 115   
U 116   this.fm_menu_datei_schliessen = function() {
117     if(self.openEditor === 'text') {
118       if(!self.cm.getDoc().isClean()) {
119         self.fm_ask_for_save();
120       } else {
121         self.fm_do_close();
122       }
123     } else {
4e450e 124       if(tinymce.activeEditor.undoManager.hasUndo()) {
ebc1f3 125         self.fm_ask_for_save();
U 126       } else {
127         self.fm_do_close();
128       }
129     }
130   };  
131
132   this.fm_ask_for_save = function() {
133     self.dialog_laden_und_zeigen('data/tpl/dlg-ask-save.tpl', '', function() {
134       // wenn dialog da ist, hier events verknuepfen
135       document.querySelector('#cancel-btn').addEventListener('click', function() {
136         self.fm_do_close();
137         self.dialog_schliessen();
138       });
139       document.querySelector('#speichern-btn').addEventListener('click', function() {
140         self.fm_menu_datei_speichern(function() {
141           self.fm_do_close();
142           self.dialog_schliessen();
143         });
144       });
145     });
146   };
147
148   this.fm_menu_datei_speichern = function(callback) {
149     //var fname = $('.datei-gewaehlt').text();
150     var fname = self.openFileName;
151     if(fname !== undefined && fname !== '') {
152       self.fm_save_file(fname, 'saveTextFile', callback);
153     } else {
154       self.fm_menu_datei_speichern_unter(callback);
155     }
156   };
157   
158   this.fm_menu_datei_speichern_unter = function(callback) {  
159     self.dialog_laden_und_zeigen('data/tpl/dlg-save-as.tpl', '', function() {
5b4d03 160       document.querySelector('#cancel-btn').addEventListener('click', function() {
U 161         //self.fm_do_close();
162         self.dialog_schliessen();
163       });
164       document.querySelector('#speichern-btn').addEventListener('click', function() {
1a9589 165         //self.fm_menu_datei_speichern(function() {
U 166           //console.log(document.querySelector('#datei-name-in').value);
5b4d03 167           self.fm_save_file(document.querySelector('#datei-name-in').value, 'saveTextFileAs', callback);
4e450e 168           if(typeof(callback) !== 'function') {
U 169             self.fm_do_close();
170             self.dialog_schliessen();
171           }
1a9589 172         //});
5b4d03 173       });
ebc1f3 174     });    
4e450e 175   };
U 176   
177   this.fm_menu_neues_dokument = function() {
178     self.fm_dok_edit('');
ebc1f3 179   };
05e9c4 180
U 181   /* Dialog-Funktionen */
182
183   /*
94b871 184    Einen Dialog aus Vorlagen erzeugen
U 185    
186    vurl - URL zur Dialogvorlage
187    msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional)
188    */
ebc1f3 189   this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) {
U 190     var vorlage = self.cache[vurl];
191     if(vorlage === undefined) {
192       self.fm_get(vurl, "text", function(antwort) {
193         self.cache[vurl] = antwort;
194         self.dialog_zeigen(vurl, antwort, cb);
195         //self.vorlage_fuellen(vurl, inhalt, cb);
94b871 196       });
05e9c4 197     } else {
ebc1f3 198       self.dialog_zeigen(vurl, vorlage, cb);
05e9c4 199     }
U 200   };
201
ebc1f3 202   this.dialog_zeigen = function (vurl, inhalt, cb) {
05e9c4 203     var dlg = document.querySelector(".dialog");
ebc1f3 204     self.html_erzeugen(
94b871 205             vurl,
U 206             inhalt,
207             function (html) {
208               //dlg.html(html);
1a9589 209               dlg.style.height = '7em';
94b871 210               dlg.innerHTML = html;
U 211               document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen);
212               //dlg.slideDown(300);
ebc1f3 213               if(typeof(cb) !== 'function') {
U 214                 // ..
215               } else {
216                 cb();
217               }
94b871 218             });
05e9c4 219   };
U 220
58bcbd 221   this.dialog_schliessen = function () {
05e9c4 222     document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen);
U 223     //$('.dialog').slideUp(300);
224     var dlg = document.querySelector('.dialog');
225     //dlg.style.display = "none";
226     dlg.style.height = '0';
227     dlg.innerHTML = '';
5b4d03 228     self.removeAllListeners('#cancel-btn');
U 229     self.removeAllListeners('#speichern-btn');
05e9c4 230   };
6648a8 231  
U 232   this.fm_dateiwahl = function(ev) {
233     var elem = ev.target;
234     if(self.modus == 'kacheln') {
235       // Kacheln
236       if(elem.classList.contains("icon-folder")) {
237         if(/*ev.shiftKey || */ ev.ctrlKey) {
4f01b8 238           var par = elem.parentElement;
U 239           par.querySelector('.dateiname').classList.add('datei-gewaehlt');
6648a8 240         } else {
U 241           var ordner = elem.parentElement.querySelector('.dateiname').textContent.trim();
242           if(self.pfad.length > 0) {
243             self.pfad = self.pfad + '/' + ordner;
244           } else {
245             self.pfad = ordner;
246           }
247           self.fm_get_list(self.pfad);
248         }
249       } else if(elem.classList.contains('datei')) {
250         if(/*ev.shiftKey || */ ev.ctrlKey) {
251           // mehrere Dateien sollen gewaehlt werden
252         } else {
253           var gew = document.querySelector('.datei-gewaehlt');
254           if(gew != undefined) {
255             gew.classList.remove('datei-gewaehlt');
256           }        
257         }
258         var par = elem.parentElement;
259         par.querySelector('.dateiname').classList.add('datei-gewaehlt');
260       } else {
261         //console.log('kein folder oder file...');
262       }
263     } else {
4f01b8 264       // Liste
U 265       var pElem = elem.closest('.datei-zeile');
266       var dElem = pElem.querySelector('.datei-elem');
267       if(dElem.getElementsByTagName("i")[0].classList.contains('icon-doc-text-inv')) {
6648a8 268         // Datei
U 269         if(/*ev.shiftKey || */ ev.ctrlKey) {
270           // mehrere Dateien sollen gewaehlt werden
271         } else {
4f01b8 272           var ti = document.querySelector('.table-info');
U 273           if(ti !== null) {
274             ti.classList.remove('table-info');
275           }
276           var dg = document.querySelector('.datei-gewaehlt');
277           if(dg !== null) {
278             dg.classList.remove('datei-gewaehlt');
279           }
6648a8 280         }
4f01b8 281         pElem.classList.add('table-info');
U 282         pElem.querySelector('.dateiname').classList.add('datei-gewaehlt');
6648a8 283       } else {
U 284         // Ordner
285         if(/*ev.shiftKey || */ ev.ctrlKey) {
4f01b8 286           //elem.children[0].classList.add('datei-gewaehlt');
U 287           pElem.querySelector('.dateiname').classList.add('datei-gewaehlt');
6648a8 288         } else {
4f01b8 289           var ordner = pElem.querySelector('.dateiname').textContent;
6648a8 290           if(self.pfad.length > 0) {
U 291             self.pfad = self.pfad + '/' + ordner;
292           } else {
293             self.pfad = ordner;
294           }
4f01b8 295           self.fm_get_list(self.pfad);
6648a8 296         }
U 297       }   
298     }
299   };
300  
41ab37 301   
58bcbd 302   this.fm_render_list = function (fl) {
4f01b8 303     if (self.modus === 'kacheln') {
58bcbd 304       // Kachelansicht
6648a8 305       self.html_erzeugen("data/tpl/kacheln.tpl", fl, function(html) {
U 306         var elem = document.querySelector('#dateien');
307         elem.innerHTML = html;
308         self.addEvtListener('.figure', 'click', self.fm_dateiwahl);
309       });
58bcbd 310     } else {
U 311       // Listenansicht
4f01b8 312       self.html_erzeugen("data/tpl/liste.tpl", fl, function(html) {
U 313         var elem = document.querySelector('#dateien');
314         elem.innerHTML = html;
315         self.addEvtListener('.datei-zeile', 'click', self.fm_dateiwahl);
316       });
58bcbd 317     }
U 318   };
319   
320   this.fm_get_path = function (uid) {
321     var restdir;
322     if (self.pfad.indexOf(self.PUB_DIR) > -1) {
323       restdir = self.pfad.substr(self.PUB_DIR.length);
324     } else if (self.pfad.indexOf(self.PERS_DIR) > -1) {
325       restdir = self.pfad.substr(self.PERS_DIR.length);
326     } else if (self.pfad.indexOf(self.BASE_DIR) > -1) {
327       restdir = self.pfad.substr(self.BASE_DIR.length);
328     } else if (self.pfad.indexOf(self.DATA_DIR) > -1) {
329       restdir = self.pfad.substr(self.DATA_DIR.length);
330     } else if (self.pfad.indexOf(self.DAV_DIR) > -1) {
331       restdir = self.pfad.substr(self.DAV_DIR.length);
332     }
333     if (restdir !== undefined && restdir.startsWith('/')) {
334       restdir = restdir.substr(1);
335       if (restdir.indexOf(self.WWW_DIR) > -1) {
336         restdir = restdir.replace(self.WWW_DIR, 'data');
337       }
338     }
41ab37 339     var pdir = self.fm_get_base(uid);
58bcbd 340     if (restdir.length > 1) {
U 341       return pdir + "/" + restdir;
342     } else {
343       return pdir;
344     }
345   };
346
347   this.fm_get_base = function (uid) {
348     var pdir;
349     if (self.pfad.indexOf(self.PUB_DIR) > -1) {
350       pdir = '/data/' + uid;
351     } else if (self.pfad.indexOf(self.PERS_DIR) > -1) {
352       pdir = '/home/' + uid;
353     } else if (self.pfad.indexOf(self.BASE_DIR) > -1) {
354       pdir = '';
355     } else if (self.pfad.indexOf(self.DATA_DIR) > -1) {
356       pdir = '';
357     }
358     return pdir;
359   };
2864b2 360   
U 361   /**
362    * Aus einem relativen Pfad ein Array aus BcrFile Objekten 
363    * machen
364    * 
365    * @param {String} relPfad  der relative Pfad
366    * @returns {Array}  die BcrFile-Objekte zum Pfad als Array
367    */
368   this.fm_buildBreadcrumb = function(relPfad) {
369     var rp = '';
370     var dirList = new Array();
371     dirList.push(new BcrFile(rp, 'Home'));
372     if(relPfad.length > 1) {
373       var dirs = relPfad.split('/');
374       for(var i = 0; i < dirs.length; i++) {
375         if(rp.length > 0 ) {
376           // weitere Einträge
377           dirList.push(new BcrFile(rp + '/' + dirs[i], dirs[i]));
378           rp = rp + '/' + dirs[i];
379         } else {
380           // erster Eintrag
381           dirList.push(new BcrFile(dirs[i], dirs[i]));
382           rp = dirs[i];
383         }
384       }
385     }
386     return dirList;
387   };
388   
4f01b8 389   /*
U 390    * icon-th-large
391    * icon-th-list
392    * @returns {undefined}
393    */
394   this.fm_ansicht_umschalten = function() {
395     var elem = document.querySelector('#ansicht');
396     var iElem = elem.getElementsByTagName("i")[0];
397     if(iElem.classList.contains('icon-th-list')) {
398       iElem.classList.add('icon-th-large');
399       iElem.classList.remove('icon-th-list');
400       self.modus = 'liste';
401     } else {
402       iElem.classList.add('icon-th-list');
403       iElem.classList.remove('icon-th-large');
404       self.modus = 'kacheln';
405     }
406     self.fm_get_list(self.pfad);    
407   };
408
409   this.fm_set_modus = function() {
410     var elem = document.querySelector('#ansicht');
411     var iElem = elem.getElementsByTagName("i")[0];
412     if(self.modus === 'kacheln') {
413       iElem.classList.add('icon-th-list');    
414       iElem.classList.remove('icon-th-large');
415     } else {
416       iElem.classList.add('icon-th-large');
417       iElem.classList.remove('icon-th-list');
418     }    
419   };
420
421   
2864b2 422   /**
U 423    * Der letzte Eintrag in dirs ist der aktuelle Ordner und 
424    * deshalb ausgegraut.
425    * 
426    * Wenn nur ein Ordner in dirs enthalten ist, dann sind wir 
427    * an der obersten Ebene (Home).
428    * 
429    * @param {Array} dirList ein Array aus BcrFile-Objekten
430    * @returns nichts 
431    */
432   this.fm_renderBreadcrumb = function(dirList) {
433     var elem = document.querySelector('.breadcrumb');
434     if(dirList.length > 1) {
435       var last = dirList.pop();
436       var bcList = new BcrFiles(dirList);
4f01b8 437       
2864b2 438       self.html_erzeugen("data/tpl/bcr.tpl", bcList, function(html) {
4f01b8 439         var htmlGesamt = html;
2864b2 440         self.html_erzeugen("data/tpl/bcr2.tpl", last, function(html) {
4f01b8 441           htmlGesamt += html;          
U 442           self.html_erzeugen("data/tpl/bcr3.tpl", dirList[0], function(html) {
443             htmlGesamt += html;
444             elem.innerHTML = htmlGesamt;
445             self.addEvtListener('.bc-link', 'click', self.fm_bc_click);
446             self.addEvtListener('#ansicht', 'click', self.fm_ansicht_umschalten);
447             self.fm_set_modus();
448           });
449           
2864b2 450         });                  
U 451       });            
452     } else {
453       // oberste Ebene
4f01b8 454       var htmla;
U 455       var htmlb;
2864b2 456       self.html_erzeugen("data/tpl/bcr2.tpl", dirList[0], function(html) {
4f01b8 457         htmla = html;        
U 458         self.html_erzeugen("data/tpl/bcr3.tpl", dirList[0], function(html) {
459           htmlb = html;
460           elem.innerHTML = htmla + htmlb;
461           self.addEvtListener('.bc-link', 'click', self.fm_bc_click);
462           self.addEvtListener('#ansicht', 'click', self.fm_ansicht_umschalten);
463           self.fm_set_modus();
464         });
2864b2 465       });            
U 466     }
467   };
468   
469   /**
470    * Auf den Klick auf ein Breadcrumb-Element reagieren:
471    * Den Ordner-Inhalt des geklickten Elements anzeigen
472    * @returns nichts
473    */
474   this.fm_bc_click = function() {
475     var elem = this;
476     var bcPfad = elem.getAttribute("rpath");
477     if(bcPfad !== undefined) {
478       self.pfad = bcPfad;
479       self.fm_get_list(bcPfad);
480     } else {
481       pfad = '';
482       self.fm_get_list('');
483     }
484   };
485
94b871 486   /* API functions */
05e9c4 487
94b871 488   // http://localhost:8079/file-cms/svc?c=de.uhilger.filecms.api.FileMgr&f=JSONNICE&m=list&p=
U 489   this.fm_get_list = function (relPfad) {
490     var m = '?c=de.uhilger.filecms.api.FileMgr&m=list&p=' + relPfad;
491     var u = '../svc' + m;
58bcbd 492     self.fm_get(u, "json", function (respText) {
U 493       var resp = JSON.parse(respText);
94b871 494       if (resp.List[0].FileRef !== undefined) {
U 495         var files = new Array();
496         if (resp.List[0].FileRef instanceof Array) {
497           for (var i = 0; i < resp.List[0].FileRef.length; i++) {
498             files.push(new FileRef(resp.List[0].FileRef[i]));
05e9c4 499           }
U 500         } else {
94b871 501           files.push(new FileRef(resp.List[0].FileRef));
05e9c4 502         }
94b871 503         var fl = new FileList(files);
58bcbd 504         self.fm_render_list(fl);
94b871 505       } else {
58bcbd 506         // #dateien leeren
8ba358 507         var elem = document.querySelector("#dateien");
U 508         elem.innerHTML = '';
94b871 509       }
8ba358 510       
U 511       // Breadcrumb
512       
2864b2 513       var dirList = self.fm_buildBreadcrumb(relPfad);
4f01b8 514       self.fm_renderBreadcrumb(dirList);     
94b871 515     });
U 516   };
f002d9 517   
1a9589 518   this.datei_neuer_ordner = function() {
U 519     self.dialog_laden_und_zeigen('data/tpl/dlg-ask-folder.tpl', '', function() {
520       document.querySelector('#cancel-btn').addEventListener('click', function() {
521         self.dialog_schliessen();
522       });
523       document.querySelector('#speichern-btn').addEventListener('click', function() {
524         var m = '?c=de.uhilger.filecms.api.FileMgr&m=newFolder&p=' + 
525                 self.pfad + 
526                 '&p=' + document.querySelector('#folder-name-in').value;
527         var u = '../svc' + m;
528         self.fm_get(u, "json", function(resp) {
529           self.dialog_schliessen();
530           self.fm_get_list(self.pfad);
531         });
532       });
533     });    
534   };
535
ebc1f3 536   this.fm_edit_as_text = function() {
U 537     self.fm_get_file_content('text');
4e450e 538   };
U 539   
540   this.fm_edit_as_doc = function() {
541     self.fm_get_file_content('doc');
ebc1f3 542   };
U 543   
f002d9 544   this.fm_get_file_content = function(typ) {
U 545     var gewaehlte = document.querySelector('.datei-gewaehlt');
546     //var fname = $(gewaehlte).find('.dateiname').text();
547
548     var fname = gewaehlte.textContent;
ebc1f3 549     //console.log('fname: ' + fname);
f002d9 550     self.openFileName = fname;
U 551     var m = '?c=de.uhilger.filecms.api.FileMgr&m=getCode&p=' + self.pfad + '&p=' + fname;
552     var u = '../svc' + m;
553     self.fm_get(u, "text", function(resp) {
554       if(typ === 'text') {
555         var mode = "text/x-java";
556         if(fname.endsWith('js')) {
557           mode = 'javascript';
558         } else if(fname.endsWith('xml')) {
559           mode = 'xml';
560         } else if(fname.endsWith('properties')) {
561           mode = 'xml';
562         } else if(fname.endsWith('adoc')) {
563           mode = 'text/x-markdown';
564         }
565         self.fm_text_edit(resp, mode);
566       } else {
567         self.fm_dok_edit(resp);
568       }
569     });
570   };
571
ebc1f3 572   this.fm_save_file = function(saveFileName, method, callback) {
U 573     var content;
574     if(self.openEditor === 'text') {
575       content = self.cm.getValue();
576       self.cm.getDoc().markClean();
577     } else {
4e450e 578       content = self.ed.getContent();
ebc1f3 579       tinymce.activeEditor.undoManager.clear();
U 580     }
581     var m = '?c=de.uhilger.filecms.api.FileMgr&m=' + method;
5b4d03 582     var u = '../svc' + m;
U 583     var data = '&p=' + self.pfad + '&p=' + saveFileName + '&p=' + encodeURIComponent(content);
584     self.fm_post(u, data, "text", function(resp) {
585       // ...
ebc1f3 586     });
U 587     self.openFileName = saveFileName;
588     if(typeof (callback) !== 'function') {
589
590     } else {
591       callback();
592     }
593   };
594
595
f002d9 596
U 597 /* ---- codemirror editor handling -------- */
598
599   /*
600   function htmlDecode(value){ 
601     return $('<div/>').html(value).text(); 
602   }
603   */
604
605   this.fm_code_edit = function(content, m) {
ebc1f3 606     //console.log('fm_code_edit content: ' + content.substring(0,30));
U 607     self.cm = CodeMirror.fromTextArea(document.getElementById("editspace"), {
f002d9 608       lineNumbers: true,
U 609       lineWrapping: true,
610       gutters: ["CodeMirror-linenumbers", "breakpoints"],
611       mode: m,
612       viewportMargin : Infinity,
613       tabSize: 2,
614       extraKeys: {
615           "F9": function(cm) {
616           cm.setOption("fullScreen", !cm.getOption("fullScreen"));
617         },
618           "Esc": function(cm) {
619           if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
620         },
621           ".": function(cm) {
622           console.log('dot pressed: perhaps look up class or method name');
623           /*
624            * Hier kann man eine Funktion ausloesen, die fuer das 
625            * Wort vor dem Punkt (Name der Klasse) eine Liste mit 
626            * Vorschlaegen fuer Methodennamen einblendet.
627            */
628
629           /*
630            * CodeMirror.Pass laesst das Zeichen zum Editorinhalt durch, 
631            * verhindert aber das Ausloesen von 'keyHandled'
632            */
633           return CodeMirror.Pass; 
634         }
635       }
636     });
637     //cm.setValue(htmlDecode(content));
638     //cm.setValue(content);
ebc1f3 639     self.cm.setValue(self.unescapeHtml(content));
U 640     self.cm.getDoc().markClean();
641     self.cm.on("gutterClick", function(theEditor, lineNumber) {
f002d9 642       var info = theEditor.lineInfo(lineNumber);
U 643       //--lineNumber;
644       //console.log(info.gutterMarkers.breakpoints.message);
645       //var marker = info.gutterMarkers.breakpoints;
646       //$(marker).tooltip('toggle');
647     });
648     /*
649     cm.on("keyHandled", function(theEditor, keyName, event){
650       console.log('cm.keyHandled keyName: ' + keyName + ', event.type: ' + event.type);    
651     });
652     */
653   };
654
655   this.makeMarker = function(msg) {
656     var marker = document.createElement("div");
657     marker.style.color = "#822";
658     marker.innerHTML = "●";
659     //marker.message = msg;
660     $(marker).tooltip({
661       placement: 'right',
662       title: msg,
663       offset: '0 -30'
664     });
665     return marker;
666   };
667
4e450e 668   /* ---- TinyMCE editor handling -------- */
U 669
670   this.fm_dok_editor_init = function(uid) {
671     var base = self.fm_get_path(uid);
672     //var edCount = 0;
673     //console.log("fm_dok_editor_init calling tinymce.init with base: " + base + "/");
674
675     /*
676      * vgl.
677      * http://stackoverflow.com/questions/4651676/how-do-i-remove-tinymce-and-then-re-add-it
678      */
679     //tinymce.EditorManager.execCommand('mceRemoveControl',true, 'textarea.text-editor');
680     //tinymce.EditorManager.execCommand('mceAddControl',true, editor_id);
681     if(self.ed !== undefined) {
682       self.ed.destroy();
683     }
684     if(tinymce !== undefined) {
685       tinymce.remove('textarea.text-editor');
686       tinymce.EditorManager.editors = []; 
687     }
688
689     /*
690      * Konfiguration TinyMCE
691      */
692     tinymce.init({
693       content_css : "/file-cms/ui/mce.css",
694       //content_css: "/jslib/bootstrap/css/bootstrap.min.css",
695       selector: "textarea.text-editor",
696       statusbar: false,
697       menubar: false,
698       plugins: 'advlist charmap code image link lists media table print preview save table textcolor importcss',
699       toolbar: 'undo redo | styleselect | image table | link unlink | bullist numlist | outdent indent | code',
700       /*
701       menu: {
702         file: {title: 'File', items: 'savevers | exit'},
703         edit: {title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall'},
704         view: {title: 'View', items: 'visualaid | code | link image media | template hr'},
705       },
706       */
707       resize: 'both',
708       importcss_append: true,
709       width: "100%",
710       height: '100%',
711       relative_urls : true, 
712       convert_urls : false, 
713       document_base_url : base + "/",
714       setup: function (editor) {
715         self.ed = editor;
716       }
717     });
718
719     window.addEventListener('resize', self.fm_resize_editor);
720     //$(window).on('resize', self.fm_resize_editor);
721     self.fm_resize_editor();
722   };
723
724   this.fm_resize_editor = function() {
725     window.clearTimeout(self.tmo);
726     self.tmo = window.setTimeout(function () {
727       try {
728         var myHeight = document.querySelector('.inhalt').offsetHeight - 
729                 document.querySelector('.nord').offsetHeight + 2; // - 4;
730         //console.log('myHeight: ' + myHeight);
731         self.ed.theme.resizeTo('100%', myHeight);  // sets the dimensions of the editable area
732       } catch (err) {
733       }
734     }, 200);
735   };
736
737
f002d9 738   
U 739   /* -------- Editoren --------- */
740   
741   this.fm_text_edit = function(content, mode) {
742     document.querySelector(".codeeditor-space").style.display = "block";
5b4d03 743     //document.querySelector(".code-editor-container").style.display = "block";
U 744     //document.querySelector(".zentrum-behaelter").style.display = "none";
745     document.querySelector(".breadcrumb").style.display = "none";
746     document.querySelector(".zentrum").style.display = "none";
f002d9 747     self.fm_code_edit(content, mode);  
U 748     self.openEditor = 'text';
749   };
750
751   this.fm_dok_edit = function(content) {
752     //fm_filectls_hide();
4e450e 753     self.fm_dok_editor_init(self.userid);
U 754     document.querySelector("#mce-editor").style.display = "block";
755     //$("#mce-editor").show();
756     document.querySelector(".breadcrumb").style.display = "none";
757     document.querySelector(".zentrum").style.display = "none";
f002d9 758
4e450e 759     window.clearTimeout(self.tmo2);
U 760     self.tmo2 = window.setTimeout(function () {
f002d9 761       try {
4e450e 762         self.ed.setContent(content);
U 763         self.openEditor = 'dok';  
f002d9 764       } catch (err) {
U 765       }
766     }, 200);
767   };
ebc1f3 768   
U 769   this.fm_do_close = function() {
770     document.querySelector(".codeeditor-space").style.display = "none";
4e450e 771     document.querySelector("#mce-editor").style.display = "none";
U 772     // $("#mce-editor").hide();
5b4d03 773     //document.querySelector(".code-editor-container").style.display = "none";
U 774     //document.querySelector(".zentrum-behaelter").style.display = "block";
775     document.querySelector(".breadcrumb").style.display = "block";
776     document.querySelector(".zentrum").style.display = "block";
ebc1f3 777     if(self.cm !== undefined) {
U 778       self.cm.toTextArea();
779     }
780     self.openFileName = '';
781     self.openEditor = '';
782     self.fm_get_list(self.pfad);
783   };
05e9c4 784
94b871 785   /* -------- An- und Abmelden ------------- */
05e9c4 786
94b871 787   this.fm_get_login = function() {
U 788     var m = '?c=de.uhilger.filecms.pub.SessionManager&m=getSessionUser';
789     var u = '../pub' + m;
790     self.fm_get(u, "text", function (resp) {
791       self.userid = resp;
58bcbd 792       self.login_zeigen();
U 793       //document.querySelector("#userMenu").textContent = resp;
94b871 794     });
U 795   };
05e9c4 796
94b871 797   this.fm_logout = function() {
U 798     var m = '?c=de.uhilger.filecms.pub.SessionManager&m=expireSession';
799     var u = '../pub' + m;
800     self.fm_get(u, "text", function (resp) {
801       //$('#userMenu').text('nicht angemeldet');
802       window.location.href = '../logout.html';
803     });
804   };
41ab37 805   
6648a8 806   /* ----- Hilfsfunktionen ----- */
U 807
808   this.serialisieren = function(obj) {
809     return '{"' + obj.constructor.name + '":' + JSON.stringify(obj) + '}';
810   };
811   
812   this.addEvtListener = function(selector, eventName, func) {
813     document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); });
814   };
815   
816   this.removeAllListeners = function(id) {
817     var el = document.getElementById(id);
5b4d03 818     if(el !== null) {
U 819       elClone = el.cloneNode(true);
820       el.parentNode.replaceChild(elClone, el);
821     }
6648a8 822   }; // https://stackoverflow.com/questions/19469881/remove-all-event-listeners-of-specific-type
U 823
ebc1f3 824   this.escapeHtml = function(text) {
U 825     text = text.replace(/\u228/g,'&auml;');
826     text = text.replace(/\u246/g,'&ouml;');
827     text = text.replace(/\u252/g,'&uuml;');
828     text = text.replace(/\u196/g,'&Auml;');
829     text = text.replace(/\u214/g,'&Ouml;');
830     text = text.replace(/\u220/g,'&Uuml;');
831     text = text.replace(/\u223/g,'&szlig;');
832     text = text.replace(/\u26/g,'&amp;');
833     return text;
834   };
835
836   this.unescapeHtml = function(text) {
837     text = text.replace(/&auml;/g, String.fromCharCode(228));
838     text = text.replace(/&ouml;/g, String.fromCharCode(246));
839     text = text.replace(/&uuml;/g, String.fromCharCode(252));
840     text = text.replace(/&Auml;/g, String.fromCharCode(196));
841     text = text.replace(/&Ouml;/g, String.fromCharCode(214));
842     text = text.replace(/&Uuml;/g, String.fromCharCode(220));
843     text = text.replace(/&szlig;/g, String.fromCharCode(223));
844     text = text.replace(/&amp;/g, String.fromCharCode(26));
845     return text;
846   };
847
41ab37 848   /* ---- Vorlagen ---- */
U 849
850   this.html_erzeugen = function(vurl, inhalt, cb) {
851     var vorlage = self.cache[vurl];
852     if(vorlage === undefined) {
853       self.vorlage_laden_und_fuellen(vurl, inhalt, cb);
854     } else {
855       self.vorlage_fuellen(vurl, inhalt, cb);
856     }
857   };
858
859   this.vorlage_fuellen = function(vurl, inhalt, cb) {
860     cb(Mustache.render(self.cache[vurl], inhalt));
861   };
862
863   this.vorlage_laden_und_fuellen = function(vurl, inhalt, cb) {
864     self.fm_get(vurl, "text", function(antwort) {
865       self.cache[vurl] = antwort;
866       self.vorlage_fuellen(vurl, inhalt, cb);
867     });
868   };
94b871 869
U 870   /* -------- ajax helper functions ----------- */
871
58bcbd 872   this.fm_get = function (u, dtype, scallback) {    
U 873     var xmlhttp = new XMLHttpRequest();
874     var url = u;
875     xmlhttp.onreadystatechange = function() {
5b4d03 876       if (this.readyState === 4 && this.status === 200) {
58bcbd 877         scallback(this.responseText);
94b871 878       }
58bcbd 879     };
U 880     xmlhttp.open("GET", url, true);
881     xmlhttp.send();
94b871 882   };
ebc1f3 883   
U 884   self.fm_post = function(u, d, dtype, scallback) {
885     var xmlhttp = new XMLHttpRequest();
886     var url = u;
887     xmlhttp.onreadystatechange = function() {
5b4d03 888       if (this.readyState === 4 && this.status === 200) {
ebc1f3 889         scallback(this.responseText);
U 890       }
891     };
892     xmlhttp.open("POST", url, true);
893     xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
5b4d03 894     xmlhttp.send(d);
ebc1f3 895   };
U 896
5b4d03 897   /*
ebc1f3 898   this.http_get = function(u, cb)  {
U 899     self.http_call('GET', u, null, cb);
900   };
901   
902   this.http_post = function(u, data, cb) {
903     self.http_call('POST', u, data, cb);
904   };
905
906   this.http_call = function (method, u, data, scallback) {    
907     var xhr = new XMLHttpRequest();
908     var url = u;
909     xhr.onreadystatechange = function() {
910       if (this.readyState === 4 && this.status === 200) {
911         scallback(this.responseText);
912       }
913     };
5b4d03 914     xhr.open(method, url, false);
ebc1f3 915     if(method === 'GET')  {
U 916       xhr.send();
917     } else if(method === 'POST' || method === 'PUT') {
918       xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
919       xhr.send(data);
920     }
921   };
5b4d03 922   */
ebc1f3 923
94b871 924
05e9c4 925 }