/* Proto - Ein Rumpf-Konstrukt fuer Webapps Copyright (C) 2021 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ function Proto() { var self = this; var appMenu; var cache; // mustache templates this.init = function() { self.cache = new Array(); self.appMenu = new AppMenu(); self.appMenu.init( "data/menu/", "hauptmenue.json", "data/tpl/app-menu.txt", ".west", "8em"); document.querySelector('.hamburger').addEventListener('click', function(e) { self.menue_umschalten(); }); self.fusszeile_umschalten(); self.seitenleiste_umschalten(); }; /* ------------------ sonstige Helfer ----------------------- */ this.addEvtListener = function(selector, eventName, func) { document.querySelectorAll(selector).forEach(elem => { elem.addEventListener(eventName, func); }); }; this.removeClassMulti = function(selector) { document.querySelectorAll('.' + selector).forEach(elem => { elem.classList.remove(selector); }); }; /* --------------------- asynchroner HTTP Client ----------------- */ this.http_get = function (u, cb) { self.http_call('GET', u, null, cb); }; this.http_post = function (u, data, cb) { self.http_call('POST', u, data, cb); }; this.http_put = function (u, data, cb) { self.http_call('PUT', u, data, cb); }; this.http_delete = function (u, data, cb) { // console.log("delete " + u); self.http_call('DELETE', u, data, cb); }; this.http_call = function (method, callurl, data, scallback) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { scallback(this.responseText); } }; xhr.open(method, callurl); if (method === 'GET') { xhr.send(); } else if (method === 'POST' || method === 'PUT' || method === 'DELETE') { xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(data); } }; /* ------------------------ aus App-Vorlage ------------------- */ this.menue_umschalten = function () { var ham = document.querySelector(".hamburger"); ham.classList.toggle("is-active"); // hamburger-icon umschalten self.appMenu.toggle(); // menue oeffnen/schliessen }; this.info_dialog_zeigen = function () { self.dialog_laden_und_zeigen('data/tpl/dlg-info.txt', ''); self.menue_umschalten(); }; this.seitenleiste_umschalten = function () { var ostDiv = document.querySelector('.ost'); if (ostDiv.classList.contains('ost-open')) { ostDiv.classList.remove('ost-open'); ostDiv.style.flexBasis = '0em'; } else { ostDiv.classList.add('ost-open'); ostDiv.style.flexBasis = '6em'; } self.menue_umschalten(); }; this.fusszeile_umschalten = function () { var suedDiv = document.querySelector('.sued'); if (suedDiv.classList.contains('sued-open')) { suedDiv.classList.remove('sued-open'); suedDiv.style.height = '0'; } else { suedDiv.classList.add('sued-open'); suedDiv.style.height = '1.5em'; } self.menue_umschalten(); }; this.menu_message = function (msg) { self.meldung_mit_timeout(msg, 1500); var suedDiv = document.querySelector('.sued'); if (suedDiv.classList.contains('sued-open')) { } else { suedDiv.classList.add('sued-open'); suedDiv.style.height = '1.5em'; } self.menue_umschalten(); }; this.message_1 = function () { self.menu_message('Eine Mitteilung.'); }; this.message_2 = function () { self.menu_message('Was wir schon immer sagen wollten.'); }; this.message_3 = function (text) { self.menu_message(text); }; this.meldung_mit_timeout = function (meldung, timeout) { var s = document.querySelector('.sued'); s.classList.add('sued-open'); s.style.height = '1.5em'; s.textContent = meldung; setTimeout(function () { s.textContent = 'Bereit.'; setTimeout(function () { var suedDiv = document.querySelector('.sued'); if (suedDiv.classList.contains('sued-open')) { suedDiv.classList.remove('sued-open'); suedDiv.style.height = '0'; } }, 500); }, timeout); }; /* --------------------- Dialog-Funktionen ------------------------ */ /* Einen Dialog aus Vorlagen erzeugen vurl - URL zur Dialogvorlage msgTpl - URL mit einer Vorlage eines Mitteilungstextes (optional) */ this.dialog_laden_und_zeigen = function (vurl, msgTpl, cb) { var vorlage = self.cache[vurl]; if(vorlage === undefined) { self.http_get(vurl, function(antwort) { self.cache[vurl] = antwort; self.dialog_zeigen(vurl, msgTpl, cb); }); } else { self.dialog_zeigen(vurl, msgTpl, cb); } }; this.dialog_zeigen = function (vurl, inhalt, cb) { var dlg = document.querySelector(".dialog"); self.html_erzeugen(vurl, inhalt, function (html) { dlg.style.height = '7em'; dlg.innerHTML = html; document.querySelector('.close-btn').addEventListener('click', self.dialog_schliessen); if(typeof(cb) !== 'function') { // .. } else { cb(); } }); }; this.dialog_schliessen = function () { document.querySelector('.close-btn').removeEventListener('click', self.dialog_schliessen); var dlg = document.querySelector('.dialog'); dlg.style.height = '0'; dlg.innerHTML = ''; }; /* --------------------- Vorlagen ---------------------- */ /* Das HTML erzeugen, das entsteht, wenn eine Vorlage mit Inhalt gefüllt wird Das Füllen erfolgt asynchron, d.h. der Programmlauf geht nach dem Aufruf weiter ohne auf das Laden und Füllen der Vorlage zu warten. Das fertige HTML wird der Callback-Funktion übergeben sobald die Vorlage geladen und gefüllt ist, unabhängig davon, wo der Programmlauf zu diesem Zeitpunkt mittlerweile ist. vurl - URL zur Vorlagendatei inhalt - die JSON-Struktur, deren Inhalt in die Vorlage gefüllt werden soll cb - Callback-Funktion, die gerufen wird, wenn die Vorlage gefüllt ist. Dieser Callback-Funktion wird das fertige HTML übergeben */ this.html_erzeugen = function (vurl, inhalt, cb) { var vorlage = self.cache[vurl]; if (vorlage === undefined) { self.vorlage_laden_und_fuellen(vurl, inhalt, cb); } else { self.vorlage_fuellen(vurl, inhalt, cb); } }; this.vorlage_fuellen = function (vurl, inhalt, cb) { cb(Mustache.render(self.cache[vurl], inhalt)); }; /* Eine Vorlage vom Server in den lokalen Speicher laden vurl - der URL unter dem die Vorlage zu finden ist inhalt - die JSON-Struktur, deren Inhalt in die Vorlage gefüllt werden soll cb - callback: Diese Funktion wird gerufen, wenn die Vorlage mit dem Inhalt gefüllt ist */ this.vorlage_laden_und_fuellen = function (vurl, inhalt, cb) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { self.cache[vurl] = this.responseText; self.vorlage_fuellen(vurl, inhalt, cb); } }; xmlhttp.open("GET", vurl, true); xmlhttp.send(); }; }