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