3080 lines
96 KiB
JavaScript
3080 lines
96 KiB
JavaScript
class SystemSettings {
|
||
static setBasePath(basePath)
|
||
{
|
||
SystemSettings._basePath = basePath;
|
||
}
|
||
static getBasePath()
|
||
{
|
||
return SystemSettings._basePath;
|
||
}
|
||
}
|
||
SystemSettings.setBasePath("/");
|
||
|
||
class MenuAction {
|
||
constructor(title, callback, showFor, order) {
|
||
this.title = Helper.nonNull(title, null);
|
||
this.callback = callback;
|
||
this.showFor = Helper.nonNull(showFor, MenuAction.SHOW_FOR_MEDIUM);
|
||
this.order = Helper.nonNull(order, 1000);
|
||
|
||
this._menu = null;
|
||
this._activated = true;
|
||
this._visible = true;
|
||
this.id = MenuAction.maxId++;
|
||
this._icon = null;
|
||
this._shouldTranslate = true;
|
||
this._copies = [];
|
||
}
|
||
|
||
setTitle(title)
|
||
{
|
||
this.title = title;
|
||
}
|
||
|
||
setShouldTranslate(shouldTranslate)
|
||
{
|
||
this._shouldTranslate = shouldTranslate;
|
||
}
|
||
|
||
getTitle()
|
||
{
|
||
return this.title;
|
||
}
|
||
|
||
getShouldTranslate()
|
||
{
|
||
return this._shouldTranslate;
|
||
}
|
||
|
||
remove(removeCopies) {
|
||
removeCopies = Helper.nonNull(removeCopies, false);
|
||
if (Helper.isNotNull(this._menu)) {
|
||
console.log(this._menu);
|
||
this._menu.removeAction(this);
|
||
this._menu = null;
|
||
}
|
||
if (removeCopies)
|
||
{
|
||
for (let i = 0, n = this._copies.length; i < n; i++) {
|
||
this._copies[i].remove();
|
||
}
|
||
}
|
||
}
|
||
|
||
getMenu() {
|
||
return this._menu;
|
||
}
|
||
|
||
setMenu(value) {
|
||
this._menu = value;
|
||
}
|
||
|
||
getVisible() {
|
||
return this._visible;
|
||
}
|
||
|
||
setVisible(value) {
|
||
if (value !== this._visible) {
|
||
this._visible = value;
|
||
this.redraw();
|
||
}
|
||
}
|
||
|
||
getActivated() {
|
||
return this._activated;
|
||
}
|
||
|
||
getIcon() {
|
||
return this._icon;
|
||
}
|
||
|
||
setIcon(value) {
|
||
this._icon = value;
|
||
}
|
||
|
||
getId()
|
||
{
|
||
return this.id;
|
||
}
|
||
|
||
redraw() {
|
||
if (Helper.isNotNull(this._menu)) {
|
||
this._menu.updateAction(this);
|
||
}
|
||
}
|
||
copy(instance){
|
||
let copy = Helper.nonNull(instance, new MenuAction());
|
||
copy.title = this.title;
|
||
copy.callback = this.callback;
|
||
copy.showFor = this.showFor;
|
||
copy.order = this.order;
|
||
|
||
copy._activated = this._activated;
|
||
copy._visible = this._visible;
|
||
copy._icon = this._icon;
|
||
copy._shouldTranslate = this._shouldTranslate;
|
||
|
||
copy._menu = null;
|
||
copy.id = MenuAction.maxId++;
|
||
this._copies.push(copy);
|
||
return copy;
|
||
}
|
||
|
||
redrawMenu()
|
||
{
|
||
if (Helper.isNotNull(this._menu)) {
|
||
this._menu.redraw();
|
||
}
|
||
}
|
||
}
|
||
MenuAction.maxId = 0;
|
||
|
||
MenuAction.SHOW_ALWAYS = "always";
|
||
MenuAction.SHOW_FOR_MEDIUM = "medium";
|
||
MenuAction.SHOW_FOR_LARGE = "large";
|
||
MenuAction.SHOW_NEVER = "never";
|
||
|
||
class OpenSubmenuAction extends MenuAction {
|
||
constructor(title, menu, showFor, order) {
|
||
super(title, function (action) {
|
||
action.getSubmenu().toggle();
|
||
action.redraw();
|
||
}, showFor, order);
|
||
|
||
this.submenu = menu;
|
||
menu.setParentAction(this);
|
||
}
|
||
|
||
getSubmenu() {
|
||
return this.submenu;
|
||
}
|
||
|
||
copy(instance) {
|
||
instance = super.copy(Helper.nonNull(instance, new OpenSubmenuAction(null, this.submenu.copy())));
|
||
return instance;
|
||
}
|
||
}
|
||
|
||
class Menu {
|
||
constructor(parentElementSelector) {
|
||
this.actions = [];
|
||
this.submenus = [];
|
||
if (typeof parentElementSelector === 'string') {
|
||
this.parentElements = document.querySelectorAll(parentElementSelector);
|
||
}
|
||
else if (Array.isArray(parentElementSelector)) {
|
||
this.parentElements = parentElementSelector;
|
||
}
|
||
else {
|
||
this.parentElements = [parentElementSelector];
|
||
}
|
||
}
|
||
|
||
copy(instance)
|
||
{
|
||
instance = Helper.nonNull(instance, new Menu([]));
|
||
|
||
instance.actions = [];
|
||
for (let i = 0, n = this.actions.length; i < n; i++) {
|
||
instance.actions.push(this.actions[i].copy());
|
||
}
|
||
|
||
instance.submenus = [];
|
||
for (let i = 0, n = this.submenus.length; i < n; i++) {
|
||
instance.submenus.push(this.submenus[i].copy());
|
||
}
|
||
|
||
return instance;
|
||
}
|
||
|
||
addAction(action) {
|
||
if (Helper.includesNot(this.actions, action)) {
|
||
this.actions.push(action);
|
||
this.redraw();
|
||
action.setMenu(this);
|
||
if (action instanceof OpenSubmenuAction) {
|
||
this.submenus.push(action.getSubmenu());
|
||
}
|
||
}
|
||
}
|
||
|
||
draw() {
|
||
if (Helper.isNotNull(this.parentElements)) {
|
||
this.sortActions();
|
||
|
||
let actionElements = [];
|
||
for (let i = 0, n = this.actions.length; i < n; i++) {
|
||
let element = this.renderAction(this.actions[i]);
|
||
this.actions[i]._htmlElement = element;
|
||
actionElements.push(element);
|
||
}
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
this.parentElements[i].removeAllChildren();
|
||
for (let i2 = 0, n2 = actionElements.length; i2 < n2; i2++) {
|
||
this.parentElements[i].appendChild(Helper.cloneNode(actionElements[i2]));
|
||
}
|
||
this.parentElements[i].onclick = this._getOnClickListener();
|
||
}
|
||
}
|
||
}
|
||
|
||
_getOnClickListener() {
|
||
let menu = this;
|
||
return function (event) {
|
||
let _element = event.target;
|
||
if (_element.matches('.action') || _element.matches('.action *')) {
|
||
// while (!_element.matches('.action > a')) {
|
||
// _element = _element.parentNode;
|
||
// }
|
||
_element = _element.closest(".action");
|
||
let actionId = parseInt(_element.dataset["id"]);
|
||
for (let i = 0, n = menu.actions.length; i < n; i++) {
|
||
if (menu.actions[i].id === actionId) {
|
||
if (typeof menu.actions[i].callback === 'function' && menu.actions[i].getActivated()) {
|
||
menu.actions[i].callback(menu.actions[i], event);
|
||
}
|
||
return menu.actions[i];
|
||
}
|
||
}
|
||
for (let i = 0, n = menu.submenus.length; i < n; i++) {
|
||
if (menu.submenus[i].click(actionId, event)) {
|
||
return menu.submenus[i];
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
}
|
||
|
||
/** @protected */
|
||
renderAction(action) {
|
||
let aElement = document.createElement("a");
|
||
if (typeof action.callback === 'string') {
|
||
aElement.href = action.callback;
|
||
}
|
||
|
||
if (Helper.isNotNull(action.getIcon())) {
|
||
let iconElement = document.createElement("img");
|
||
iconElement.src = action.getIcon();
|
||
iconElement.classList.add('action-image');
|
||
if (action.getShouldTranslate())
|
||
{
|
||
iconElement.dataset["translationTitle"] = action.title;
|
||
}
|
||
aElement.appendChild(iconElement);
|
||
}
|
||
let title = action.getTitle();
|
||
if (action.getShouldTranslate())
|
||
{
|
||
title = Translator.makePersistentTranslation(title);
|
||
}
|
||
else
|
||
{
|
||
title = document.createTextNode(title);
|
||
}
|
||
aElement.appendChild(title);
|
||
|
||
return this.renderLiElement(aElement, action)
|
||
}
|
||
|
||
/** @protected */
|
||
renderLiElement(aElement, action) {
|
||
let liElement = document.createElement("li");
|
||
liElement.classList.add('action');
|
||
liElement.appendChild(aElement);
|
||
liElement.dataset["id"] = action.id;
|
||
if (Helper.isNotNull(action.getIcon())) {
|
||
liElement.classList.add("img");
|
||
}
|
||
|
||
if (!action.getVisible())
|
||
{
|
||
liElement.classList.add("hidden");
|
||
}
|
||
|
||
if (action instanceof OpenSubmenuAction) {
|
||
action.getSubmenu().draw();
|
||
liElement.appendChild(action.getSubmenu().getParentElement());
|
||
liElement.classList.add("is-dropdown-submenu-parent");
|
||
liElement.classList.add("opens-right");
|
||
}
|
||
return liElement;
|
||
}
|
||
|
||
/** @private */
|
||
sortActions() {
|
||
this.actions = this.actions.sort(function (first, second) {
|
||
return first.order - second.order;
|
||
});
|
||
}
|
||
|
||
_getElementsForAction(action){
|
||
let elements = [];
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
let elem = this.parentElements[i].querySelector("[data-id=\""+action.getId()+"\"]");
|
||
Helper.isNull(elem) || elements.push(elem);
|
||
}
|
||
return elements
|
||
}
|
||
|
||
updateAction(action)
|
||
{
|
||
let oldElements = this._getElementsForAction(action);
|
||
if (oldElements.length === 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
let element = this.renderAction(action);
|
||
action._htmlElement = element;
|
||
|
||
for (let i = 0, n = oldElements.length; i < n; i++) {
|
||
oldElements[i].replaceWith(Helper.cloneNode(element));
|
||
}
|
||
}
|
||
|
||
removeAction(action)
|
||
{
|
||
let index = this.actions.indexOf(action);
|
||
if (index > 0)
|
||
{
|
||
this.actions.splice(index, 1);
|
||
let oldElements = this._getElementsForAction(action);
|
||
for (let i = 0, n = oldElements.length; i < n; i++) {
|
||
oldElements[i].remove();
|
||
}
|
||
if (action instanceof OpenSubmenuAction) {
|
||
let index = this.submenus.indexOf(action.getSubmenu());
|
||
this.submenus.splice(index, 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
redraw() {
|
||
this.draw();
|
||
}
|
||
}
|
||
|
||
Menu.SHOW_ALWAYS = "always";
|
||
Menu.SHOW_FOR_MEDIUM = "medium";
|
||
Menu.SHOW_FOR_SMEDIUM = "smedium";
|
||
Menu.SHOW_FOR_LARGE = "large";
|
||
Menu.SHOW_NEVER = "never";
|
||
|
||
class Submenu extends Menu
|
||
{
|
||
constructor()
|
||
{
|
||
let menuElement = document.createElement("ul");
|
||
menuElement.classList.add("menu");
|
||
menuElement.classList.add("vertical");
|
||
menuElement.classList.add("submenu");
|
||
menuElement.classList.add("is-dropdown-submenu");
|
||
menuElement.classList.add("first-sub");
|
||
super(menuElement);
|
||
|
||
this.parentAction = null;
|
||
this.isOpen = false;
|
||
}
|
||
|
||
|
||
|
||
copy(instance)
|
||
{
|
||
instance = super.copy(Helper.nonNull(instance, new Submenu()));
|
||
instance.parentElements = [];
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
instance.parentElements.push(Helper.cloneNode(this.parentElements[i]));
|
||
}
|
||
instance.parentAction = this.parentAction;
|
||
instance.isOpen = this.isOpen;
|
||
return instance;
|
||
}
|
||
|
||
setParentAction(action)
|
||
{
|
||
this.parentAction = action;
|
||
}
|
||
|
||
draw()
|
||
{
|
||
super.draw();
|
||
if (Helper.isNotNull(this.parentElements))
|
||
{
|
||
let self = this;
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
let closeListener = document.createElement("div");
|
||
closeListener.classList.add("close-listener");
|
||
closeListener.onclick = function(e){
|
||
console.log(e);
|
||
self.close();
|
||
};
|
||
this.parentElements[i].insertBefore(closeListener, this.parentElements[i].firstElementChild);
|
||
}
|
||
}
|
||
}
|
||
|
||
getParentElement()
|
||
{
|
||
return this.parentElements[0];
|
||
}
|
||
|
||
_getOnClickListener()
|
||
{
|
||
return function () {};
|
||
}
|
||
|
||
click(actionId, event)
|
||
{
|
||
for (let i = 0, n = this.actions.length; i < n; i++) {
|
||
if (this.actions[i].id === actionId)
|
||
{
|
||
if (typeof this.actions[i].callback === 'function' && this.actions[i].getActivated()) {
|
||
this.actions[i].callback(this.actions[i], event);
|
||
}
|
||
this.close();
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
toggle()
|
||
{
|
||
if (this.isOpen)
|
||
{
|
||
this.close();
|
||
}
|
||
else
|
||
{
|
||
this.open();
|
||
}
|
||
}
|
||
|
||
open()
|
||
{
|
||
this.isOpen = true;
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
this.parentElements[i].classList.add("js-dropdown-active");
|
||
}
|
||
if (Helper.isNotNull(this.parentAction))
|
||
{
|
||
this.parentAction.redraw();
|
||
}
|
||
}
|
||
close()
|
||
{
|
||
this.isOpen = false;
|
||
for (let i = 0, n = this.parentElements.length; i < n; i++) {
|
||
this.parentElements[i].classList.remove("js-dropdown-active");
|
||
}
|
||
if (Helper.isNotNull(this.parentAction))
|
||
{
|
||
this.parentAction.redraw();
|
||
}
|
||
}
|
||
}
|
||
|
||
class TranslatorDB {
|
||
constructor() {
|
||
this._indexedDB = indexedDB || mozIndexedDB || webkitIndexedDB || msIndexedDB;
|
||
this._version = 3;
|
||
|
||
let self = this;
|
||
this._dbPromise = new Promise(function (resolve, reject) {
|
||
let request = self._indexedDB.open("Translator", self._version);
|
||
request.onupgradeneeded = function (event) {
|
||
let db = event.target.result;
|
||
self._upgradeDb(db);
|
||
};
|
||
request.onsuccess = function (event) {
|
||
let db = event.target.result;
|
||
resolve(db);
|
||
};
|
||
request.onerror = function (event) {
|
||
reject(event);
|
||
};
|
||
}).catch(function(e){
|
||
console.error(e);
|
||
});
|
||
}
|
||
|
||
_upgradeDb(db) {
|
||
try {
|
||
db.deleteObjectStore("currentLang");
|
||
db.deleteObjectStore("translations");
|
||
}
|
||
catch (e) {
|
||
console.warn(e);
|
||
}
|
||
let currentLangObjectStore = db.createObjectStore("currentLang", {"keyPath": "id"});
|
||
let translationsObjectStore = db.createObjectStore("translations", {"keyPath": ["lang","key"]});
|
||
translationsObjectStore.createIndex("lang", "lang", {"unique": false});
|
||
}
|
||
|
||
setLanguage(lang) {
|
||
this._dbPromise.then(function (db) {
|
||
let transaction = TranslatorDB._openTransaction(["currentLang"], "readwrite", db);
|
||
let currentLangObjectStore = transaction.objectStore("currentLang");
|
||
currentLangObjectStore.put({"id": 1, "lang": lang});
|
||
}).catch(function(e){
|
||
console.error(e);
|
||
});
|
||
}
|
||
|
||
saveTranslationsForLang(lang, translations) {
|
||
return this._dbPromise.then(function (db) {
|
||
return new Promise(function (resolve) {
|
||
let transaction = TranslatorDB._openTransaction(["translations"], "readwrite", db);
|
||
let translationsObjectStore = transaction.objectStore("translations");
|
||
for (let k in translations) {
|
||
translationsObjectStore.put({"lang": lang, "key": k, "translation": translations[k]});
|
||
}
|
||
transaction.oncomplete = function () {
|
||
resolve();
|
||
};
|
||
});
|
||
}).catch(function(e){
|
||
// console.error(e);
|
||
});
|
||
}
|
||
|
||
loadTranslationsForLang(lang) {
|
||
return this._dbPromise.then(function (db) {
|
||
return new Promise(function (resolve) {
|
||
let transaction = TranslatorDB._openTransaction(["translations"], "readonly", db);
|
||
let translationsObjectStore = transaction.objectStore("translations");
|
||
let index = translationsObjectStore.index("lang");
|
||
let request = index.openCursor(IDBKeyRange.only(lang));
|
||
|
||
let translations = {};
|
||
request.onsuccess = function (e) {
|
||
let cursor = e.target.result;
|
||
if (cursor) {
|
||
|
||
let translation = cursor.value;
|
||
translations[translation["key"]] = translation["translation"];
|
||
cursor.continue();
|
||
}
|
||
};
|
||
transaction.oncomplete = function(){
|
||
resolve(translations);
|
||
};
|
||
});
|
||
}).catch(function(e){
|
||
console.error(e);
|
||
return {};
|
||
});
|
||
}
|
||
|
||
getLanguage() {
|
||
return this._dbPromise.then(function (db) {
|
||
return new Promise(function (resolve) {
|
||
let transaction = TranslatorDB._openTransaction(["currentLang"], "readonly", db);
|
||
let currentLangObjectStore = transaction.objectStore("currentLang");
|
||
let req = currentLangObjectStore.get(1);
|
||
req.onsuccess = function (e) {
|
||
let data = e.currentTarget.result;
|
||
if (data)
|
||
{
|
||
resolve(data["lang"]);
|
||
}
|
||
else
|
||
{
|
||
resolve(null);
|
||
}
|
||
};
|
||
req.onerror = function (e) {
|
||
resolve(null);
|
||
};
|
||
});
|
||
}).catch(function(e){
|
||
// console.error(e);
|
||
});
|
||
}
|
||
|
||
static _openTransaction(name, transactionMode, db) {
|
||
let transaction = null;
|
||
try {
|
||
transaction = db.transaction(name, transactionMode);
|
||
}
|
||
catch (e) {
|
||
console.warn(e);
|
||
transaction = db.transaction(name);
|
||
}
|
||
return transaction;
|
||
}
|
||
}
|
||
|
||
class Translator {
|
||
constructor() {
|
||
this._translations = [];
|
||
this._db = new TranslatorDB();
|
||
this._currentLanguage = null;
|
||
this._supportedLanguages = Translator.supportedLanguages;
|
||
this._baseLanguage = Translator.baseLanguage;
|
||
this._languageBasePath = Translator.languageBasePath;
|
||
this._markUntranslatedTranslations = Translator.markUntranslatedTranslations;
|
||
this._markTranslations = Translator.markTranslations;
|
||
|
||
let self = this;
|
||
this._initPromise = this.loadBaseLanguage().then(function () {
|
||
return self.loadUserLanguage();
|
||
});
|
||
}
|
||
|
||
_loadLanguage(language) {
|
||
let self = this;
|
||
return fetch(Helper.basePath(this._languageBasePath + language + ".json")).then(function (result) {
|
||
return result.json();
|
||
}).then(function (res) {
|
||
self._translations[language] = Object.assign(res, self._translations[language]);
|
||
self._db.saveTranslationsForLang(language, self._translations[language]);
|
||
}).catch(function (err) {
|
||
console.error("could not load lang " + language + " because of error: ", err);
|
||
});
|
||
}
|
||
|
||
loadBaseLanguage() {
|
||
let self = this;
|
||
return this._loadLanguage(this._baseLanguage).then(function () {
|
||
self._currentLanguage = self._baseLanguage;
|
||
if (typeof document !== 'undefined') {
|
||
document.getElementsByTagName("html")[0].setAttribute("lang", self._baseLanguage);
|
||
}
|
||
});
|
||
};
|
||
|
||
static setLanguage(language) {
|
||
let instance = Translator.getInstance();
|
||
if (instance) {
|
||
return instance.setLanguage(language);
|
||
}
|
||
}
|
||
|
||
setLanguage(language) {
|
||
if (this._currentLanguage === language) {
|
||
this.updateTranslations();
|
||
return Promise.resolve();
|
||
}
|
||
|
||
if (this._supportedLanguages.indexOf(language) === -1) {
|
||
return Promise.resolve();
|
||
}
|
||
|
||
this._currentLanguage = language;
|
||
if (typeof localStorage !== 'undefined') {
|
||
localStorage.setItem("language", language);
|
||
}
|
||
this._db.setLanguage(language);
|
||
|
||
let self = this;
|
||
return this._loadLanguage(language).then(function () {
|
||
if (typeof document !== 'undefined') {
|
||
document.getElementsByTagName("html")[0].setAttribute("lang", language);
|
||
}
|
||
self.updateTranslations();
|
||
});
|
||
}
|
||
|
||
static translate(key, args) {
|
||
let instance = Translator.getInstance();
|
||
if (instance) {
|
||
return instance.translate(key, args);
|
||
}
|
||
return "";
|
||
}
|
||
|
||
translate(key, args) {
|
||
if (typeof key === 'object' && Helper.isNotNull(key)) {
|
||
key = this.addDynamicTranslation(key);
|
||
}
|
||
|
||
let translation = null;
|
||
if (Helper.isNotNull(this._translations[this._currentLanguage]) && Helper.isNotNull(this._translations[this._currentLanguage][key])) {
|
||
translation = this._translations[this._currentLanguage][key];
|
||
}
|
||
|
||
if (Helper.isNull(translation)) {
|
||
if (Translator.logMissingTranslations) {
|
||
console.warn("missing translation for language " + this._currentLanguage + " and key " + key);
|
||
}
|
||
if (Helper.isNotNull(this._translations[this._baseLanguage])) {
|
||
translation = this._translations[this._baseLanguage][key];
|
||
}
|
||
|
||
if (Helper.isNull(translation)) {
|
||
if (Translator.logMissingTranslations) {
|
||
console.error("missing base translation for key " + key + ". FIX IT");
|
||
}
|
||
translation = key;
|
||
}
|
||
if (this._markUntranslatedTranslations) {
|
||
translation = ">>" + translation + "<<";
|
||
}
|
||
}
|
||
|
||
if (this._markTranslations) {
|
||
translation = "$" + translation + "$";
|
||
}
|
||
|
||
if (args !== undefined) {
|
||
translation = translation.format(args);
|
||
}
|
||
|
||
return translation;
|
||
}
|
||
|
||
static addDynamicTranslation(trans) {
|
||
let instance = Translator.getInstance();
|
||
if (instance) {
|
||
return instance.addDynamicTranslation(trans);
|
||
}
|
||
}
|
||
|
||
addDynamicTranslation(trans) {
|
||
let key = trans["key"];
|
||
delete trans["key"];
|
||
for (let lang in trans) {
|
||
if (trans.hasOwnProperty(lang)) {
|
||
if (Helper.isNull(this._translations[lang])) {
|
||
this._translations[lang] = {};
|
||
}
|
||
this._translations[lang][key] = trans[lang];
|
||
}
|
||
}
|
||
return key;
|
||
}
|
||
|
||
updateTranslations() {
|
||
if (typeof document !== 'undefined') {
|
||
let elements = document.querySelectorAll("[data-translation]");
|
||
for (let i = 0, max = elements.length; i < max; i++) {
|
||
if (elements[i].dataset["translation"] != "") {
|
||
try {
|
||
elements[i].innerHTML = this.translate(elements[i].dataset["translation"], (elements[i].dataset["translationArgs"] !== undefined) ? JSON.parse(elements[i].dataset["translationArgs"]) : undefined);
|
||
}
|
||
catch (err) {
|
||
console.error("wrong configured translation: " + err);
|
||
}
|
||
}
|
||
for (let k in elements[i].dataset) {
|
||
if (k.startsWith("translation") && !k.endsWith("Args")) {
|
||
try {
|
||
elements[i][k.substr(11).toLowerCase()] = this.translate(elements[i].dataset[k], (elements[i].dataset[k + "Args"] !== undefined) ? JSON.parse(elements[i].dataset[k + "Args"]) : undefined);
|
||
}
|
||
catch (err) {
|
||
console.error("wrong configured translation: " + err);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
loadUserLanguage() {
|
||
let userLanguage = localStorage.getItem("language");
|
||
if (Helper.isNull(userLanguage) || this._supportedLanguages.indexOf(userLanguage) === -1) {
|
||
let userLanguages = [];
|
||
if (Helper.isNotNull(navigator.languages)) {
|
||
userLanguages = navigator.languages.slice(0); //.slice(0) klont das Array. Behebt einen Bug in Firefox
|
||
}
|
||
|
||
if (navigator.language !== undefined) {
|
||
userLanguages.push(navigator.language);
|
||
}
|
||
//sicherstellen, dass überhaupt eine Sprache gefunden wird
|
||
userLanguages.push(this._baseLanguage);
|
||
|
||
if (userLanguages !== undefined) {
|
||
for (let i = 0, numLanguages = userLanguages.length; i < numLanguages; i++) {
|
||
if (this._supportedLanguages.indexOf(userLanguages[i]) !== -1) {
|
||
userLanguage = userLanguages[i];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return this.setLanguage(userLanguage.toLowerCase())
|
||
}
|
||
|
||
static makePersistentTranslation(key, args, tag) {
|
||
tag = Helper.nonNull(tag, "span");
|
||
if (typeof key === 'object') {
|
||
key = Translator.addDynamicTranslation(key);
|
||
}
|
||
|
||
if (typeof document !== 'undefined') {
|
||
let htmlElem = document.createElement(tag);
|
||
htmlElem.dataset["translation"] = key;
|
||
if (args !== undefined) {
|
||
htmlElem.dataset["translationArgs"] = JSON.stringify(args);
|
||
}
|
||
htmlElem.innerHTML = Translator.translate(key, args);
|
||
return htmlElem;
|
||
}
|
||
}
|
||
|
||
static generateChangeLanguageMenuAction() {
|
||
let submenu = new Submenu();
|
||
submenu.addAction(new MenuAction("en", function () {
|
||
Translator.getInstance().setLanguage("en");
|
||
}));
|
||
submenu.addAction(new MenuAction("de", function () {
|
||
Translator.getInstance().setLanguage("de");
|
||
}));
|
||
return new OpenSubmenuAction("current-lang", submenu, Menu.SHOW_ALWAYS)
|
||
}
|
||
|
||
static init() {
|
||
Translator.instance = new Translator();
|
||
// Translator.loadBaseLanguage().then(function () {
|
||
// Translator.loadUserLanguage();
|
||
// });
|
||
}
|
||
|
||
static getInstance() {
|
||
return Translator.instance;
|
||
}
|
||
}
|
||
Translator.logMissingTranslations = false;
|
||
|
||
Translator.instance = null;
|
||
|
||
Translator.baseLanguage = "en";
|
||
Translator.supportedLanguages = [
|
||
"de",
|
||
"en"
|
||
];
|
||
Translator.markUntranslatedTranslations = true;
|
||
Translator.markTranslations = false;
|
||
Translator.languageBasePath = "js/lang/";
|
||
Translator.currentLanguage = null;
|
||
Translator.translations = {};
|
||
|
||
class Helper {
|
||
static init() {
|
||
Helper.heightMmToPxFactor = null;
|
||
Helper.widthMmToPxFactor = null;
|
||
}
|
||
|
||
static includesNot(array, value, fromIndex) {
|
||
return -1 === array.indexOf(value, fromIndex);
|
||
}
|
||
|
||
static includes(array, value, fromIndex) {
|
||
return !Helper.includesNot(array, value, fromIndex);
|
||
}
|
||
|
||
static isSet() {
|
||
if (arguments.length > 0) {
|
||
const object = arguments[0];
|
||
let keys = Array.prototype.slice.call(arguments, 1);
|
||
return (Helper.isNotNull(object) && (keys.length === 0 || Helper.isSet.apply(null, [object[keys[0]]].concat(keys.slice(1)))));
|
||
}
|
||
return false;
|
||
}
|
||
|
||
static isNull(variable) {
|
||
return (variable === null || variable === undefined);
|
||
}
|
||
|
||
static isNotNull(variable) {
|
||
return !Helper.isNull(variable);
|
||
}
|
||
|
||
static nonNull(val1, val2) {
|
||
if (Helper.isNotNull(val1)) {
|
||
return val1;
|
||
}
|
||
return val2;
|
||
}
|
||
|
||
static notEmpty(value) {
|
||
return !Helper.empty(value);
|
||
}
|
||
|
||
static buildQuery(values) {
|
||
let queryStrings = [];
|
||
for (let k in values) {
|
||
queryStrings.push(encodeURIComponent(k) + "=" + encodeURIComponent(values[k]));
|
||
}
|
||
return "?" + queryStrings.join("&");
|
||
}
|
||
|
||
static empty(value) {
|
||
return (Helper.isNull(value) || (typeof value === 'string' && value.trim() === ""))
|
||
}
|
||
|
||
static inflateElementsFromString(string) {
|
||
let template = document.createElement('template');
|
||
template.innerHTML = string;
|
||
return template.content.childNodes;
|
||
}
|
||
|
||
static createLoadingSymbol() {
|
||
let svgNS = "http://www.w3.org/2000/svg";
|
||
|
||
let loader = document.createElement("div");
|
||
loader.className = 'loader';
|
||
|
||
let svg = document.createElementNS(svgNS, "svg");
|
||
svg.setAttribute('viewBox', "0 0 32 32");
|
||
svg.setAttribute("widh", "32");
|
||
svg.setAttribute("height", "32");
|
||
|
||
let circle = document.createElementNS(svgNS, "circle");
|
||
circle.setAttribute("id", "spinner");
|
||
circle.setAttribute("cx", "16");
|
||
circle.setAttribute("cy", "16");
|
||
circle.setAttribute("r", "14");
|
||
circle.setAttribute("fill", "none");
|
||
|
||
svg.appendChild(circle);
|
||
loader.appendChild(svg);
|
||
|
||
return loader;
|
||
}
|
||
|
||
static basePath(url) {
|
||
return SystemSettings.getBasePath() + url;
|
||
}
|
||
|
||
static isMobileApple() {
|
||
return navigator.userAgent.match(/iPhone|iPad|iPod/i);
|
||
}
|
||
|
||
static isMobile() {
|
||
return (navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || Helper.isMobileApple() || (typeof window.orientation !== "undefined" || window.orientation === false || window.orientation === null));
|
||
}
|
||
|
||
static select(e) {
|
||
let range = document.createRange();
|
||
range.selectNodeContents(e);
|
||
let sel = window.getSelection();
|
||
sel.removeAllRanges();
|
||
sel.addRange(range);
|
||
}
|
||
|
||
static format(number, leadingZeros) {
|
||
number = "" + number;
|
||
while (number.length < leadingZeros) {
|
||
number = "0" + number;
|
||
}
|
||
return number;
|
||
}
|
||
|
||
static cloneNode(srcNode) {
|
||
let destNode = srcNode.cloneNode(true);
|
||
destNode.onclick = srcNode.onclick;
|
||
return destNode;
|
||
}
|
||
|
||
static encodeToBase(stringToEncode, base) {
|
||
let encodedString = "";
|
||
let charlength = Math.floor(Math.log(265) / Math.log(base));
|
||
for (let i = 0, n = stringToEncode.length; i < n; i++) {
|
||
let value = stringToEncode.charCodeAt(i).toString(base);
|
||
let joinLength = value.length % charlength;
|
||
if (joinLength > 0) {
|
||
let joinArray = new Array(charlength + 1 - (joinLength)); //+1, da join nur zwischen elemente einfügt
|
||
value = joinArray.join("0") + value;
|
||
}
|
||
encodedString += value;
|
||
}
|
||
return encodedString;
|
||
}
|
||
|
||
static decodeToBase(stringToDecode, base) {
|
||
let charlength = Math.floor(Math.log(265) / Math.log(base));
|
||
let values = stringToDecode.match(new RegExp(".{1," + charlength + "}", "g")) || [];
|
||
let encodedString = "";
|
||
for (let i = 0, n = values.length; i < n; i++) {
|
||
encodedString += String.fromCharCode(parseInt(values[i], base));
|
||
}
|
||
return encodedString;
|
||
}
|
||
|
||
static toggleVisibility(elem) {
|
||
if (elem.style.display === "none") {
|
||
elem.style.display = "";
|
||
return true;
|
||
}
|
||
else {
|
||
elem.style.display = "none";
|
||
return false;
|
||
}
|
||
}
|
||
|
||
static print(content) {
|
||
let printContent = document.getElementById("print-content");
|
||
if (content instanceof Element) {
|
||
printContent.removeAllChildren();
|
||
printContent.appendChild(content);
|
||
}
|
||
else {
|
||
printContent.innerHTML = content;
|
||
}
|
||
window.print();
|
||
}
|
||
|
||
static strftime(sFormat, date, useUTC) {
|
||
if (!(date instanceof Date)) date = new Date(date);
|
||
useUTC = Helper.nonNull(useUTC, false);
|
||
let nDay = (useUTC) ? date.getUTCDay() : date.getDay(),
|
||
nDate = (useUTC) ? date.getUTCDate() : date.getDate(),
|
||
nMonth = (useUTC) ? date.getUTCMonth() : date.getMonth(),
|
||
nYear = (useUTC) ? date.getUTCFullYear() : date.getFullYear(),
|
||
nHour = (useUTC) ? date.getUTCHours() : date.getHours(),
|
||
aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||
aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||
aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
|
||
isLeapYear = function () {
|
||
if ((nYear & 3) !== 0) return false;
|
||
return nYear % 100 !== 0 || nYear % 400 === 0;
|
||
},
|
||
getThursday = function () {
|
||
let target = new Date(date);
|
||
target.setDate(nDate - ((nDay + 6) % 7) + 3);
|
||
return target;
|
||
},
|
||
zeroPad = function (nNum, nPad) {
|
||
return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
|
||
};
|
||
|
||
return sFormat.replace(/%[a-z]/gi, function (sMatch) {
|
||
return {
|
||
'%a': Translator.makePersistentTranslation(aDays[nDay].slice(0, 3)).outerHTML,
|
||
'%A': Translator.makePersistentTranslation(aDays[nDay]).outerHTML,
|
||
'%b': Translator.makePersistentTranslation(aMonths[nMonth].slice(0, 3)).outerHTML,
|
||
'%B': Translator.makePersistentTranslation(aMonths[nMonth]).outerHTML,
|
||
'%c': date.toUTCString(),
|
||
'%C': Math.floor(nYear / 100),
|
||
'%d': zeroPad(nDate, 2),
|
||
'%e': nDate,
|
||
'%f': zeroPad(date.getTime() % 1000, 4),
|
||
'%F': date.toISOString().slice(0, 10),
|
||
'%G': getThursday().getFullYear(),
|
||
'%g': ('' + getThursday().getFullYear()).slice(2),
|
||
'%H': zeroPad(nHour, 2),
|
||
'%I': zeroPad((nHour + 11) % 12 + 1, 2),
|
||
'%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth > 1 && isLeapYear()) ? 1 : 0), 3),
|
||
'%k': '' + nHour,
|
||
'%l': (nHour + 11) % 12 + 1,
|
||
'%m': zeroPad(nMonth + 1, 2),
|
||
'%M': zeroPad(date.getMinutes(), 2),
|
||
'%p': (nHour < 12) ? 'AM' : 'PM',
|
||
'%P': (nHour < 12) ? 'am' : 'pm',
|
||
'%s': Math.round(date.getTime() / 1000),
|
||
'%S': zeroPad(date.getSeconds(), 2),
|
||
'%u': nDay || 7,
|
||
'%V': (function () {
|
||
let target = getThursday(),
|
||
n1stThu = target.valueOf();
|
||
target.setMonth(0, 1);
|
||
let nJan1 = target.getDay();
|
||
if (nJan1 !== 4) target.setMonth(0, 1 + ((4 - nJan1) + 7) % 7);
|
||
return zeroPad(1 + Math.ceil((n1stThu - target) / 604800000), 2);
|
||
})(),
|
||
'%w': '' + nDay,
|
||
'%x': date.toLocaleDateString(),
|
||
'%X': date.toLocaleTimeString(),
|
||
'%y': ('' + nYear).slice(2),
|
||
'%Y': nYear,
|
||
'%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
|
||
'%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
|
||
}[sMatch] || sMatch;
|
||
});
|
||
}
|
||
|
||
static cloneJson(obj) {
|
||
// https://stackoverflow.com/questions/4120475/how-to-create-and-clone-a-json-object/17502990#17502990
|
||
let i;
|
||
|
||
// basic type deep copy
|
||
if (Helper.isNull(obj) || typeof obj !== 'object') {
|
||
return obj
|
||
}
|
||
// array deep copy
|
||
if (obj instanceof Array) {
|
||
let cloneA = [];
|
||
for (i = 0; i < obj.length; ++i) {
|
||
cloneA[i] = Helper.cloneJson(obj[i]);
|
||
}
|
||
return cloneA;
|
||
}
|
||
if (obj instanceof Date)
|
||
{
|
||
return new Date(obj.getTime());
|
||
}
|
||
// object deep copy
|
||
let cloneO = {};
|
||
for (i in obj) {
|
||
cloneO[i] = Helper.cloneJson(obj[i]);
|
||
}
|
||
return cloneO;
|
||
}
|
||
|
||
static htmlspecialcharsDecode(text) {
|
||
const map = {
|
||
'&': '&',
|
||
'&': "&",
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
''': "'",
|
||
'’': "’",
|
||
'‘': "‘",
|
||
'–': "–",
|
||
'—': "—",
|
||
'…': "…",
|
||
'”': '”'
|
||
};
|
||
|
||
if (Helper.isNotNull(text) && typeof text.replace === "function") {
|
||
return text.replace(/\&[\w\d\#]{2,5}\;/g, function (m) {
|
||
return map[m];
|
||
});
|
||
}
|
||
return text;
|
||
}
|
||
|
||
static formDataFromObject(obj) {
|
||
let formData = new FormData();
|
||
for (let k in obj) {
|
||
formData.set(k, obj[k]);
|
||
}
|
||
return formData;
|
||
}
|
||
|
||
static scaleContentRecursive(element, content) {
|
||
|
||
let elementStyle = window.getComputedStyle(element);
|
||
let contentStyle = window.getComputedStyle(content);
|
||
|
||
if (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) {
|
||
return Helper.scaleDownContentRecursive(element, content);
|
||
}
|
||
}
|
||
|
||
static scaleDownContentRecursive(element, content) {
|
||
Helper.convertChildrenToRelativeRecursive(element);
|
||
|
||
let elementStyle = window.getComputedStyle(element);
|
||
let contentStyle = window.getComputedStyle(content);
|
||
|
||
let runs = 0;
|
||
let fontSize = parseFloat(contentStyle.getPropertyValue("font-size"));
|
||
let width = contentStyle.width;
|
||
let height = contentStyle.height;
|
||
while (contentStyle.height > elementStyle.height || contentStyle.width > elementStyle.width) {
|
||
fontSize *= 0.95;
|
||
|
||
if (height > elementStyle.height) {
|
||
height *= 0.95;
|
||
}
|
||
if (width > contentStyle.width) {
|
||
width *= 0.95;
|
||
}
|
||
content.style["font-size"] = fontSize + "px";
|
||
content.style["max-height"] = height + "px";
|
||
content.style["max-width"] = width + "px";
|
||
|
||
runs++;
|
||
if (runs > 2000) {
|
||
console.log("breaked");
|
||
break;
|
||
}
|
||
}
|
||
Helper.convertToRelative(content);
|
||
|
||
contentStyle = window.getComputedStyle(content);
|
||
content.style["font-size"] = (parseFloat(contentStyle.getPropertyValue("font-size")) / parseFloat(document.documentElement.clientHeight) * 100) + "vh";
|
||
}
|
||
|
||
static convertChildrenToRelativeRecursive(element) {
|
||
let children = element.childNodes;
|
||
for (let i = 0, n = children.length; i < n; i++) {
|
||
if (children[i] instanceof Element) {
|
||
Helper.convertToRelative(children[i]);
|
||
Helper.convertChildrenToRelativeRecursive(children[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
static convertToRelative(element) {
|
||
let hasTransitionClass = (element.classList.contains("no-transtition"));
|
||
|
||
element.classList.add("no-transition");
|
||
|
||
let parent = element.parentNode;
|
||
|
||
console.log(element);
|
||
let elementStyle = window.getComputedStyle(element);
|
||
let parentStyle = window.getComputedStyle(parent);
|
||
|
||
let fontSize = parseFloat(elementStyle.getPropertyValue("font-size")) / parseFloat(parentStyle.getPropertyValue("font-size"));
|
||
|
||
let maxHeight = elementStyle.height;
|
||
let maxWidth = elementStyle.width;
|
||
|
||
let pHeight = parentStyle.height;
|
||
let pWidth = parentStyle.width;
|
||
|
||
let relativeAttributes = element.style;
|
||
relativeAttributes['max-height'] = Math.floor(maxHeight / pHeight * 100) + "%";
|
||
relativeAttributes['margin-left'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-left')) / pWidth * 100) + "%";
|
||
relativeAttributes['margin-right'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-right')) / pWidth * 100) + "%";
|
||
relativeAttributes['margin-top'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-top')) / pHeight * 100) + "%";
|
||
relativeAttributes['margin-bottom'] = Math.floor(parseFloat(elementStyle.getPropertyValue('margin-bottom')) / pHeight * 100) + "%";
|
||
relativeAttributes['max-width'] = Math.floor(maxWidth / pWidth * 100) + "%";
|
||
relativeAttributes["font-size"] = fontSize + "em";
|
||
// console.log(relativeAttributes);
|
||
// element.css(relativeAttributes);
|
||
|
||
if (!hasTransitionClass) {
|
||
element.classList.remove("no-transition");
|
||
}
|
||
}
|
||
|
||
static isChrome() {
|
||
let isChromium = window.chrome,
|
||
winNav = window.navigator,
|
||
vendorName = winNav.vendor,
|
||
isOpera = winNav.userAgent.indexOf("OPR") > -1,
|
||
isIEedge = winNav.userAgent.indexOf("Edge") > -1,
|
||
isIOSChrome = winNav.userAgent.match("CriOS");
|
||
|
||
if (isIOSChrome) {
|
||
return true;
|
||
} else {
|
||
return isChromium !== null &&
|
||
typeof isChromium !== "undefined" &&
|
||
vendorName === "Google Inc." &&
|
||
isOpera === false &&
|
||
isIEedge === false;
|
||
}
|
||
}
|
||
|
||
static getIndexedObject(array, keyValue) {
|
||
let obj = {};
|
||
for (let i = 0, n = array.length; i < n; i++) {
|
||
obj[array[i][keyValue]] = array[i];
|
||
}
|
||
return obj;
|
||
}
|
||
|
||
static invertKeyValues(obj) {
|
||
let new_obj = {};
|
||
|
||
for (let prop in obj) {
|
||
if (obj.hasOwnProperty(prop)) {
|
||
new_obj[obj[prop]] = prop;
|
||
}
|
||
}
|
||
|
||
return new_obj;
|
||
}
|
||
|
||
static toArray(object) {
|
||
let res = [];
|
||
for (let k in object) {
|
||
res.push(object[k]);
|
||
}
|
||
return res;
|
||
}
|
||
}
|
||
Helper.init();
|
||
|
||
class ThemeManager {
|
||
static init() {
|
||
ThemeManager.loadCurrentTheme();
|
||
}
|
||
|
||
static changeCurrentTheme(newTheme) {
|
||
let theme = null;
|
||
if (typeof newTheme === 'string') {
|
||
let themes = ThemeManager.themes.filter(function (theme) {
|
||
return theme._name === newTheme;
|
||
});
|
||
if (themes.length > 0) {
|
||
theme = themes[0];
|
||
}
|
||
}
|
||
else if (ThemeManager.themes.indexOf(newTheme) !== -1) {
|
||
theme = newTheme;
|
||
}
|
||
if (Helper.isNotNull(theme)) {
|
||
localStorage.setItem("currentTheme", theme._name);
|
||
let themePromise = new Promise(function (resolve) {
|
||
document.querySelector("nav.top-bar").addEventListener("transitionend", function(){
|
||
resolve();
|
||
});
|
||
});
|
||
document.body.className = theme._className;
|
||
ThemeManager.currentTheme = theme;
|
||
for (let i = 0, n = ThemeManager.changeListeners.length; i < n; i++) {
|
||
ThemeManager.changeListeners[i](ThemeManager.currentTheme, themePromise);
|
||
}
|
||
}
|
||
}
|
||
|
||
static addTheme(theme) {
|
||
ThemeManager.themes.push(theme);
|
||
}
|
||
|
||
static loadCurrentTheme() {
|
||
ThemeManager.changeCurrentTheme(localStorage.getItem("currentTheme"));
|
||
if (Helper.isNull(ThemeManager.currentTheme)) {
|
||
let className = document.body.className;
|
||
let themes = ThemeManager.themes.filter(function (theme) {
|
||
return theme._className === className;
|
||
});
|
||
if (themes.length > 0) {
|
||
ThemeManager.changeCurrentTheme(themes[0]);
|
||
}
|
||
else if (ThemeManager.themes.length > 0) {
|
||
ThemeManager.changeCurrentTheme(ThemeManager.themes[0]);
|
||
}
|
||
}
|
||
}
|
||
|
||
static generateChangeThemeMenuAction() {
|
||
return new MenuAction(ThemeManager.currentTheme._name, function (action) {
|
||
let currentThemeIndex = ThemeManager.themes.indexOf(ThemeManager.currentTheme);
|
||
let nextIndex = (currentThemeIndex + 1) % ThemeManager.themes.length;
|
||
ThemeManager.changeCurrentTheme(ThemeManager.themes[nextIndex]);
|
||
action.title = ThemeManager.currentTheme._name;
|
||
action._menu.redraw();
|
||
}, Menu.SHOW_ALWAYS)
|
||
}
|
||
|
||
static addChangeListener(listener) {
|
||
ThemeManager.changeListeners.push(listener);
|
||
}
|
||
}
|
||
|
||
ThemeManager.themes = [];
|
||
ThemeManager.changeListeners = [];
|
||
|
||
class CookieCompliance {
|
||
constructor(cookieContainerId) {
|
||
this.cookieContainerId = cookieContainerId;
|
||
this.dropCookie = true;
|
||
this.cookieDuration = 365 * 10;
|
||
this.cookieName = 'complianceCookie';
|
||
this.cookieValue = 'true';
|
||
}
|
||
|
||
showIfNeeded()
|
||
{
|
||
if (CookieCompliance.checkCookie(this.cookieName) !== this.cookieValue) {
|
||
this.show();
|
||
}
|
||
}
|
||
|
||
removeMe() {
|
||
this.createCookie(this.cookieName, this.cookieValue, this.cookieDuration);
|
||
}
|
||
|
||
createCookie(name, value, days) {
|
||
let expires;
|
||
if (Helper.isNotNull(days)) {
|
||
const date = new Date();
|
||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||
expires = "; expires=" + date.toGMTString();
|
||
}
|
||
else {
|
||
expires = "";
|
||
}
|
||
if (this.dropCookie) {
|
||
document.cookie = name + "=" + value + expires + "; path=/";
|
||
}
|
||
}
|
||
|
||
eraseCookie(name) {
|
||
this.createCookie(name, "", -1);
|
||
}
|
||
|
||
static checkCookie(name) {
|
||
const nameEQ = name + "=";
|
||
const cookies = document.cookie.split(';');
|
||
for (let i = 0; i < cookies.length; i++) {
|
||
let c = cookies[i];
|
||
while (c.charAt(0) === ' ') {
|
||
c = c.substring(1, c.length);
|
||
}
|
||
if (c.indexOf(nameEQ) === 0) {
|
||
return c.substring(nameEQ.length, c.length);
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
show() {
|
||
let cookieCompliance = this;
|
||
const cookieMessage = document.getElementById(this.cookieContainerId);
|
||
cookieMessage.style.display='block';
|
||
cookieMessage.querySelector("#close-cookie-msg").onclick = function(){
|
||
cookieCompliance.removeMe();
|
||
cookieMessage.remove();
|
||
};
|
||
|
||
}
|
||
}
|
||
|
||
class ActionBarMenu extends Menu {
|
||
static init() {
|
||
function parseStyleToObject(str) {
|
||
let styleObject = {};
|
||
|
||
if (typeof str !== 'string') {
|
||
return styleObject;
|
||
}
|
||
|
||
str = str.trim().slice(1, -1); // browsers re-quote string style values
|
||
|
||
if (!str) {
|
||
return styleObject;
|
||
}
|
||
|
||
styleObject = str.split('&').reduce(function (ret, param) {
|
||
const parts = param.replace(/\+/g, ' ').split('=');
|
||
let key = parts[0];
|
||
let val = parts[1];
|
||
key = decodeURIComponent(key);
|
||
|
||
// missing `=` should be `null`:
|
||
// http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
|
||
val = val === undefined ? null : decodeURIComponent(val);
|
||
|
||
if (!ret.hasOwnProperty(key)) {
|
||
ret[key] = val;
|
||
} else if (Array.isArray(ret[key])) {
|
||
ret[key].push(val);
|
||
} else {
|
||
ret[key] = [ret[key], val];
|
||
}
|
||
return ret;
|
||
}, {});
|
||
|
||
return styleObject;
|
||
}
|
||
|
||
let cssStyle = document.getElementsByClassName('foundation-mq');
|
||
if (cssStyle.length === 0) {
|
||
return;
|
||
}
|
||
let queries = [];
|
||
cssStyle = parseStyleToObject(window.getComputedStyle(cssStyle[0]).getPropertyValue('font-family'));
|
||
for (let key in cssStyle) {
|
||
if (cssStyle.hasOwnProperty(key)) {
|
||
queries.push({
|
||
_name: key,
|
||
value: 'only screen and (min-width: ' + cssStyle[key] + ')'
|
||
});
|
||
}
|
||
}
|
||
|
||
window.addEventListener('resize', function () {
|
||
if (Helper.isNotNull(ActionBarMenu.currentMenu)) {
|
||
ActionBarMenu.currentMenu.updateToggleButton();
|
||
}
|
||
});
|
||
let responsiveMenu = document.getElementById("responsive-menu");
|
||
document.getElementById("responsive-menu-toggle").onclick = function () {
|
||
if (window.getComputedStyle(responsiveMenu).getPropertyValue('display') === 'none') {
|
||
responsiveMenu.style.display = 'block';
|
||
}
|
||
else if (Helper.isNotNull(ActionBarMenu.currentMenu)) {
|
||
ActionBarMenu.currentMenu.close();
|
||
|
||
}
|
||
};
|
||
responsiveMenu.firstElementChild.addEventListener("click", function (e) {
|
||
if (e.target === responsiveMenu.firstElementChild && Helper.isNotNull(ActionBarMenu.currentMenu)) {
|
||
ActionBarMenu.currentMenu.close();
|
||
|
||
}
|
||
}
|
||
);
|
||
ActionBarMenu.queries = queries;
|
||
}
|
||
|
||
static _getCurrentSize() {
|
||
let matched;
|
||
|
||
for (let i = 0, n = ActionBarMenu.queries.length; i < n; i++) {
|
||
let query = ActionBarMenu.queries[i];
|
||
|
||
if (matchMedia(query.value).matches) {
|
||
matched = query;
|
||
}
|
||
}
|
||
|
||
if (typeof matched === 'object') {
|
||
return matched._name;
|
||
} else {
|
||
return matched;
|
||
}
|
||
}
|
||
|
||
renderLiElement(aElement, action) {
|
||
let liElement = super.renderLiElement(aElement, action);
|
||
liElement.classList.add(action.showFor);
|
||
return liElement;
|
||
}
|
||
|
||
static filterVisibleElements(elements) {
|
||
let visibleElements = [];
|
||
for (let i = 0, n = elements.length; i < n; i++) {
|
||
if (!elements[i].classList.contains("hidden")) {
|
||
visibleElements.push(elements[i]);
|
||
}
|
||
}
|
||
return visibleElements;
|
||
}
|
||
|
||
updateToggleButton() {
|
||
let size = ActionBarMenu._getCurrentSize();
|
||
let firstParentElement = this.parentElements[0];
|
||
if (ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_LARGE)).length > 0 && (size === "medium" || size === "smedium" || size === "small") ||
|
||
ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_MEDIUM)).length > 0 && (size === "smedium" || size === "small") ||
|
||
ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_SMEDIUM)).length > 0 && (size === "small") ||
|
||
ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_NEVER)).length > 0) {
|
||
document.getElementById("responsive-menu-toggle").style.display = 'block';
|
||
} else {
|
||
document.getElementById("responsive-menu-toggle").style.display = 'none';
|
||
if (Helper.isNotNull(ActionBarMenu.currentMenu)) {
|
||
ActionBarMenu.currentMenu.close();
|
||
}
|
||
}
|
||
}
|
||
|
||
_getOnClickListener() {
|
||
let superListener = super._getOnClickListener();
|
||
return function (event) {
|
||
let action = superListener(event);
|
||
if (!(action instanceof OpenSubmenuAction) && Helper.isNotNull(ActionBarMenu.currentMenu)) {
|
||
ActionBarMenu.currentMenu.close();
|
||
}
|
||
}
|
||
}
|
||
|
||
draw(parentElement) {
|
||
let returnValue = super.draw(parentElement);
|
||
this.updateToggleButton();
|
||
|
||
ActionBarMenu.currentMenu = this;
|
||
return returnValue;
|
||
}
|
||
|
||
close() {
|
||
document.getElementById("responsive-menu").style.display = 'none';
|
||
for (let i = 0, n = this.submenus.length; i < n; i++) {
|
||
this.submenus[i].close();
|
||
}
|
||
}
|
||
|
||
|
||
removeAction(action) {
|
||
let res = super.removeAction(action);
|
||
this.updateToggleButton();
|
||
return res;
|
||
}
|
||
}
|
||
|
||
ActionBarMenu.queries = [];
|
||
ActionBarMenu.currentMenu = null;
|
||
ActionBarMenu.init();
|
||
|
||
class ViewInflater {
|
||
static inflate(viewUrl, parentUrls) {
|
||
parentUrls = Helper.nonNull(parentUrls, []).slice(0);
|
||
|
||
let resultPromise = Promise.resolve();
|
||
if (viewUrl instanceof Element) {
|
||
resultPromise = Promise.resolve(viewUrl);
|
||
}
|
||
else {
|
||
if (parentUrls.indexOf(viewUrl) !== -1) {
|
||
return Promise.reject("views are in a circuit! cannot resolve view for url " + parentUrls[0] + "! url " + viewUrl + " is in stack before!");
|
||
}
|
||
parentUrls.push(viewUrl);
|
||
resultPromise = fetch(Helper.basePath(viewUrl), {credentials: "same-origin"}).then(function (result) {
|
||
return result.text();
|
||
}).then(function (htmlText) {
|
||
let doc = (new DOMParser()).parseFromString(htmlText, "text/html");
|
||
if (Helper.isNull(doc)) {
|
||
doc = document.implementation.createHTMLDocument('');
|
||
doc.body.innerHTML = htmlText;
|
||
}
|
||
return doc.body.firstChild
|
||
});
|
||
}
|
||
|
||
return resultPromise.then(function (parentElement) {
|
||
let promises = [];
|
||
let childViews = parentElement.querySelectorAll("[data-view]");
|
||
|
||
for (let i = 0, n = childViews.length; i < n; i++) {
|
||
promises.push(ViewInflater.inflate(childViews[i].dataset["view"], parentUrls).then(function (element) {
|
||
childViews[i].replaceWith(element);
|
||
}));
|
||
}
|
||
return Promise.all(promises).then(function () {
|
||
return parentElement;
|
||
});
|
||
});
|
||
}
|
||
}
|
||
|
||
class Context {
|
||
constructor(view) {
|
||
let self = this;
|
||
this._siteContent = null;
|
||
this.firstStart = true;
|
||
this.inflatePromise = new Promise(function (resolver) {
|
||
self.inflatePromiseResolver = resolver;
|
||
});
|
||
this.fragments = {};
|
||
|
||
if (Helper.isNotNull(view)) {
|
||
this.inflateView(view);
|
||
}
|
||
}
|
||
|
||
onConstruct() {
|
||
let results = [];
|
||
for (let k in this.fragments) {
|
||
results.push(this.fragments[k].onConstruct.apply(this.fragments[k], arguments));
|
||
results.push(this.fragments[k].inflatePromise);
|
||
}
|
||
return Promise.all(results);
|
||
}
|
||
|
||
onStart() {
|
||
if (this.firstStart) {
|
||
this.onFirstStart();
|
||
this.firstStart = false;
|
||
}
|
||
|
||
for (let k in this.fragments) {
|
||
let fragment = this.fragments[k];
|
||
fragment.onStart.apply(this.fragments[k], arguments);
|
||
this.fragments[k].inflatePromise.then(function (fragmentView) {
|
||
if (fragment.isActive()) {
|
||
fragmentView.classList.remove("hidden");
|
||
}
|
||
else {
|
||
fragmentView.classList.add("hidden");
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
onFirstStart() {
|
||
// for (let k in this.fragments) {
|
||
// this.fragments[k].onFirstStart.apply(this.fragments[k], arguments);
|
||
// }
|
||
}
|
||
|
||
onPause() {
|
||
for (let k in this.fragments) {
|
||
this.fragments[k].onPause.apply(this.fragments[k], arguments);
|
||
}
|
||
}
|
||
|
||
onDestroy() {
|
||
for (let k in this.fragments) {
|
||
this.fragments[k].onDestroy.apply(this.fragments[k], arguments);
|
||
}
|
||
}
|
||
|
||
addFragment(viewQuery, fragment) {
|
||
this.fragments[viewQuery] = fragment;
|
||
this.inflatePromise = this.inflatePromise.then(function (siteContent) {
|
||
return fragment.inflatePromise.then(function (fragmentView) {
|
||
siteContent.querySelector(viewQuery).appendChild(fragmentView);
|
||
return siteContent;
|
||
});
|
||
});
|
||
}
|
||
|
||
/** @protected */
|
||
inflateView(link) {
|
||
let self = this;
|
||
this.inflatePromiseResolver(ViewInflater.inflate(link).then(function (siteContent) {
|
||
self._siteContent = siteContent;
|
||
return siteContent;
|
||
}));
|
||
|
||
return this.inflatePromise;
|
||
}
|
||
|
||
findBy(query, all, asPromise) {
|
||
all = Helper.nonNull(all, false);
|
||
asPromise = Helper.nonNull(asPromise, false);
|
||
|
||
let getVal = function (root) {
|
||
let res = null;
|
||
if (all) {
|
||
res = root.querySelectorAll(query);
|
||
if (root.matches(query)) {
|
||
res.push(root);
|
||
}
|
||
}
|
||
else {
|
||
if (root.matches(query)) {
|
||
res = root;
|
||
}
|
||
else {
|
||
res = root.querySelector(query);
|
||
}
|
||
}
|
||
return res;
|
||
};
|
||
|
||
if (asPromise) {
|
||
return this.inflatePromise.then(function (rootView) {
|
||
return getVal(rootView);
|
||
});
|
||
}
|
||
return getVal(this._siteContent);
|
||
}
|
||
}
|
||
|
||
class AbstractSite$1 extends Context {
|
||
constructor(siteManager, view, deepLink) {
|
||
super(view);
|
||
|
||
this.isVisible = false;
|
||
this.siteManager = siteManager;
|
||
this.isFinishing = false;
|
||
this.actionMenu = null;
|
||
this.url = "";
|
||
this.deepLink = deepLink;
|
||
this.startArgs = {};
|
||
this.title = siteManager.getDefaultTitle();
|
||
}
|
||
|
||
setTitle(titleElement, title) {
|
||
if (typeof titleElement === "string") {
|
||
title = titleElement;
|
||
titleElement = document.createTextNode(titleElement);
|
||
}
|
||
this.title = {
|
||
element: titleElement
|
||
};
|
||
this.title["title"] = Helper.nonNull(title, this.title["title"]);
|
||
|
||
if (this.isVisible) {
|
||
this.siteManager.updateTitle();
|
||
}
|
||
}
|
||
|
||
startStartsite() {
|
||
return this.startSite(this.siteManager.getStartSiteName());
|
||
}
|
||
|
||
inflateView(link) {
|
||
let self = this;
|
||
return super.inflateView(link).then(function (res) {
|
||
let promises = [];
|
||
for (let i = 0, n = self.fragments.length; i < n; i++) {
|
||
promises.push(self.fragments[i].inflatePromise);
|
||
}
|
||
return Promise.all(promises).then(function () {
|
||
return res;
|
||
});
|
||
});
|
||
}
|
||
|
||
onConstruct(args) {
|
||
this.startArgs = args;
|
||
if (Helper.isNotNull(this.deepLink)) {
|
||
this.setUrlFromParams(args);
|
||
}
|
||
return super.onConstruct(args);
|
||
}
|
||
|
||
onStart(args) {
|
||
this.isVisible = true;
|
||
let res = super.onStart(args);
|
||
this.actionMenu.redraw();
|
||
return res;
|
||
}
|
||
|
||
onPause(args) {
|
||
super.onPause(args);
|
||
this.isVisible = false;
|
||
}
|
||
|
||
finish(result) {
|
||
if (!this.isFinishing) {
|
||
this.isFinishing = true;
|
||
this.siteManager.endSite(this, result);
|
||
}
|
||
}
|
||
|
||
startSite(siteName, args) {
|
||
return this.siteManager.startSite(siteName, args);
|
||
}
|
||
|
||
toForeground() {
|
||
this.siteManager.toForeground(this);
|
||
}
|
||
|
||
finishAndStartNext(siteName, startParams, finishResult) {
|
||
this.startSite(siteName, startParams);
|
||
this.finish(finishResult);
|
||
}
|
||
|
||
createActionBarMenu(menu) {
|
||
let defaultActions = this.siteManager.getDefaultActions();
|
||
for (let i = 0, n = defaultActions.length; i < n; i++) {
|
||
menu.addAction(defaultActions[i].copy());
|
||
}
|
||
return menu;
|
||
}
|
||
|
||
setUrl(url) {
|
||
this.url = url;
|
||
this.siteManager.updateUrl(this);
|
||
}
|
||
|
||
setUrlFromParams(params) {
|
||
this.setUrl(this.deepLink + Helper.buildQuery(params));
|
||
}
|
||
|
||
updateUrlParams(params) {
|
||
this.startArgs = Object.assign(this.startArgs, params);
|
||
this.setUrlFromParams(this.startArgs);
|
||
}
|
||
|
||
getUrl() {
|
||
return this.url;
|
||
}
|
||
|
||
getFullUrl() {
|
||
return Helper.basePath(this.url);
|
||
}
|
||
|
||
onBackPressed() {
|
||
}
|
||
|
||
addListener(event, selector, listenerFunction) {
|
||
this.siteManager.addListener(this, event, selector, listenerFunction);
|
||
}
|
||
|
||
addKeyListener(keycode, listenerFunction)
|
||
{
|
||
this.siteManager.addKeyListener(this, keycode, listenerFunction);
|
||
}
|
||
|
||
addKeyAndEventListener(keycode, event, selector, listenerFunction) {
|
||
this.siteManager.addKeyAndEventListener(this, keycode, event, selector, listenerFunction);
|
||
}
|
||
}
|
||
|
||
class SiteContainer {
|
||
constructor(site, finishResolver) {
|
||
this._site = site;
|
||
this._siteContent = null;
|
||
this._pauseParameters = {};
|
||
this._startParameters = {};
|
||
this._finishResolver = finishResolver;
|
||
}
|
||
getSite() {
|
||
return this._site;
|
||
}
|
||
|
||
setSite(site) {
|
||
if (site instanceof AbstractSite) {
|
||
this._site = site;
|
||
}
|
||
}
|
||
|
||
getSiteContent() {
|
||
return this._siteContent;
|
||
}
|
||
|
||
setSiteContent(value) {
|
||
this._siteContent = value;
|
||
}
|
||
|
||
getPauseParameters() {
|
||
return this._pauseParameters;
|
||
}
|
||
|
||
setPauseParameters(value) {
|
||
this._pauseParameters = value;
|
||
}
|
||
|
||
getStartParameters() {
|
||
return this._startParameters;
|
||
}
|
||
|
||
setStartParameters(value) {
|
||
this._startParameters = value;
|
||
}
|
||
|
||
getFinishResolver() {
|
||
return this._finishResolver;
|
||
}
|
||
|
||
setFinishResolver(value) {
|
||
this._finishResolver = value;
|
||
}
|
||
}
|
||
|
||
class SiteManager {
|
||
constructor(siteDivId, actionBarMenuSelector) {
|
||
this.siteDiv = document.getElementById(siteDivId);
|
||
this.siteContainerStack = [];
|
||
this.currentSiteContainerToShow = null;
|
||
this.actionBarMenuSelector = Helper.nonNull(actionBarMenuSelector, '.action-bar');
|
||
|
||
this.siteStartingPromise = Promise.resolve();
|
||
this.defaultActions = [];
|
||
this.startSiteName = null;
|
||
|
||
this.titleElement = document.querySelector(".top-bar-title");
|
||
|
||
const defaultTitleElem = document.createElement("span");
|
||
while(this.titleElement.childNodes.length > 0)
|
||
{
|
||
const child = this.titleElement.firstChild;
|
||
child.remove();
|
||
defaultTitleElem.appendChild(child);
|
||
}
|
||
|
||
this.defaultTitle = {
|
||
element: defaultTitleElem,
|
||
title: document.title
|
||
};
|
||
console.log(this.defaultTitle);
|
||
|
||
let siteManager = this;
|
||
window.onpopstate = function (e) {
|
||
if (siteManager.siteContainerStack.length >= 1) {
|
||
let site = siteManager.siteContainerStack[siteManager.siteContainerStack.length - 1].getSite();
|
||
if (site.onBackPressed() !== false) {
|
||
siteManager.endSite(site);
|
||
}
|
||
}
|
||
};
|
||
}
|
||
|
||
getDefaultTitle() {
|
||
return this.defaultTitle;
|
||
}
|
||
|
||
setStartSiteName(startSiteName) {
|
||
this.startSiteName = startSiteName;
|
||
}
|
||
|
||
getStartSiteName() {
|
||
return this.startSiteName;
|
||
}
|
||
|
||
addDefaultAction(action) {
|
||
this.defaultActions.push(action);
|
||
}
|
||
|
||
getDefaultActions() {
|
||
return this.defaultActions;
|
||
}
|
||
|
||
startSite(siteConstructor, paramsPromise) {
|
||
if (!(siteConstructor.prototype instanceof AbstractSite$1))
|
||
{
|
||
throw {
|
||
"error": "wrong class given! Expected AbstractSite, given "+siteConstructor.name
|
||
};
|
||
}
|
||
|
||
let site = new siteConstructor(this);
|
||
let resolver = {};
|
||
let finishPromise = new Promise(function (resolve, reject) {
|
||
resolver.resolve = resolve;
|
||
resolver.reject = reject;
|
||
});
|
||
let siteContainer = new SiteContainer(site, resolver);
|
||
this.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol());
|
||
|
||
let manager = this;
|
||
this.siteStartingPromise = new Promise(function (resolve) {
|
||
Promise.resolve(paramsPromise).then(function (params) {
|
||
siteContainer.setStartParameters(params);
|
||
return Promise.all([site.onConstruct(params), site.inflatePromise]);
|
||
}).then(function () {
|
||
site.actionMenu = site.createActionBarMenu(manager.buildActionBarMenu());
|
||
}).then(function () {
|
||
resolve(manager.show(siteContainer));
|
||
});
|
||
});
|
||
|
||
return finishPromise;
|
||
}
|
||
|
||
endSite(site, result) {
|
||
let manager = this;
|
||
this.siteStartingPromise.then(function () {
|
||
let index = manager.findContainerIndexBySite(site);
|
||
let container = manager.siteContainerStack.splice(index, 1);
|
||
container = container[0];
|
||
|
||
let showSiteContainer = null;
|
||
if (container === manager.currentSiteContainerToShow) {
|
||
manager.currentSiteContainerToShow.getSite().onPause();
|
||
manager.currentSiteContainerToShow = null;
|
||
let newSiteContainerIndex = manager.siteContainerStack.length - 1;
|
||
if (newSiteContainerIndex < 0) {
|
||
|
||
manager.showAppEndedMessage();
|
||
manager.startSite(manager.startSiteName);
|
||
return;
|
||
}
|
||
manager.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol());
|
||
showSiteContainer = manager.siteContainerStack[newSiteContainerIndex];
|
||
}
|
||
container.getSite().onDestroy();
|
||
|
||
Promise.resolve(result).then(function (resValue) {
|
||
container.getFinishResolver().resolve(resValue);
|
||
if (Helper.isNotNull(showSiteContainer)) {
|
||
manager.show(showSiteContainer);
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
addListener(site, event, _selector, listener) {
|
||
this.siteDiv.addEventListener(event, function (_event) {
|
||
let _element = _event.target;
|
||
if (site.isVisible && _element.matches(_selector)) {
|
||
listener(_element, _event);
|
||
}
|
||
});
|
||
}
|
||
|
||
addKeyAndEventListener(site, keycode, event, selector, listener) {
|
||
this.addListener(site, event, selector, listener);
|
||
this.addKeyListener(site, keycode, listener);
|
||
}
|
||
|
||
addKeyListener(site, keycode, listener) {
|
||
window.addEventListener("keydown", function (e) {
|
||
if (site.isVisible && e.which === keycode) {
|
||
listener(this, e);
|
||
}
|
||
});
|
||
}
|
||
|
||
toForeground(site) {
|
||
let index = this.findContainerIndexBySite(site);
|
||
let container = this.siteContainerStack.splice(index, 1);
|
||
container = container[0];
|
||
|
||
this.show(container);
|
||
}
|
||
|
||
refreshCurrentSite() {
|
||
return this.show(this.currentSiteContainerToShow);
|
||
}
|
||
|
||
/** @private */
|
||
show(siteContainer) {
|
||
if (Helper.isNotNull(this.currentSiteContainerToShow)) {
|
||
this.currentSiteContainerToShow.setPauseParameters(this.currentSiteContainerToShow.getSite().onPause());
|
||
this.currentSiteContainerToShow.setSiteContent(this.siteDiv.innerHTML);
|
||
}
|
||
this.siteDiv.removeAllChildren().appendChild(Helper.createLoadingSymbol());
|
||
|
||
let siteManager = this;
|
||
this.currentSiteContainerToShow = siteContainer;
|
||
if (-1 === this.siteContainerStack.indexOf(siteContainer)) {
|
||
this.siteContainerStack.push(siteContainer);
|
||
}
|
||
|
||
return siteContainer.getSite().inflatePromise.then(function (data) {
|
||
siteContainer.getSite().actionMenu.redraw();
|
||
siteManager.siteDiv.removeAllChildren().appendChild(data);
|
||
siteManager.updateTitle();
|
||
Translator.getInstance().updateTranslations();
|
||
return data;
|
||
}).then(function (data) {
|
||
siteContainer.getSite().onStart(siteContainer.getPauseParameters());
|
||
history.pushState({
|
||
'siteName': siteContainer.getSite().constructor.name,
|
||
'siteData': data.outerHTML,
|
||
'stackPosition': siteManager.siteContainerStack.length - 1
|
||
}, siteContainer.getSite().constructor.name, siteContainer.getSite().getFullUrl());
|
||
});
|
||
}
|
||
|
||
updateUrl(site) {
|
||
if (Helper.isNotNull(this.currentSiteContainerToShow) && this.currentSiteContainerToShow.getSite() === site) {
|
||
let self = this;
|
||
history.replaceState({
|
||
'siteName': site.constructor.name,
|
||
'siteData': site._siteContent.outerHTML,
|
||
'stackPosition': self.siteContainerStack.length - 1
|
||
}, site.constructor.name, site.getFullUrl());
|
||
}
|
||
}
|
||
|
||
getCurrentSite() {
|
||
if (this.currentSiteContainerToShow != null)
|
||
return this.currentSiteContainerToShow.getSite();
|
||
}
|
||
|
||
redrawCurrentActionBar() {
|
||
if (this.currentSiteContainerToShow != null)
|
||
this.currentSiteContainerToShow.getSite().actionMenu.redraw();
|
||
}
|
||
|
||
updateTitle() {
|
||
let title = this.getCurrentSite().title;
|
||
this.titleElement.removeAllChildren().appendChild(title.element);
|
||
document.title = Helper.nonNull(title.title, this.defaultTitle.title);
|
||
}
|
||
|
||
/** @private */
|
||
findContainerIndexBySite(site) {
|
||
for (let i = 0, n = this.siteContainerStack.length; i < n; i++) {
|
||
if (this.siteContainerStack[i].getSite() === site) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/** @private */
|
||
findContainerBySite(site) {
|
||
let index = this.findContainerIndexBySite(site);
|
||
if (index === -1) {
|
||
return null;
|
||
}
|
||
return this.siteContainerStack[index];
|
||
}
|
||
|
||
/** @private */
|
||
showAppEndedMessage() {
|
||
this.siteDiv.removeAllChildren().appendChild(Translator.makePersistentTranslation("The app has ended! Please close the window."));
|
||
}
|
||
|
||
/** @private */
|
||
buildActionBarMenu() {
|
||
return new ActionBarMenu(this.actionBarMenuSelector);
|
||
}
|
||
}
|
||
|
||
class PauseSite extends AbstractSite$1 {
|
||
onConstruct(args) {
|
||
let pausedElement = null;
|
||
|
||
if (Helper.isSet(args, "url")) {
|
||
pausedElement = args["url"];
|
||
}
|
||
else {
|
||
pausedElement = document.createElement("div");
|
||
pausedElement.innerHTML = "Paused...";
|
||
}
|
||
|
||
this.inflateView(pausedElement);
|
||
}
|
||
}
|
||
|
||
class App {
|
||
constructor() {
|
||
this._siteManager = null;
|
||
this._actionBarMenuSelector = '.action-bar';
|
||
this._basePath = SystemSettings.getBasePath();
|
||
this._siteContentId = 'site-content';
|
||
this._deepLinks = new Map();
|
||
this._defaultActions = [];
|
||
this._addThemeAction = false;
|
||
this._showCookieCompliance = true;
|
||
this._startSite = null;
|
||
}
|
||
|
||
getSiteManager()
|
||
{
|
||
return this._siteManager;
|
||
}
|
||
|
||
addDefaultAction(action) {
|
||
this._defaultActions.push(action);
|
||
}
|
||
|
||
setAddThemeAction(addThemeAction) {
|
||
this._addThemeAction = addThemeAction;
|
||
}
|
||
|
||
getSiteContentId() {
|
||
return this._siteContentId;
|
||
}
|
||
|
||
setSiteContentId(value) {
|
||
this._siteContentId = value;
|
||
}
|
||
|
||
getActionBarMenuSelector() {
|
||
return this._actionBarMenuSelector;
|
||
}
|
||
|
||
setActionBarMenuSelector(value) {
|
||
this._actionBarMenuSelector = value;
|
||
}
|
||
|
||
getBasePath() {
|
||
return this._basePath;
|
||
}
|
||
|
||
setBasePath(value) {
|
||
this._basePath = value;
|
||
}
|
||
|
||
addDeepLink(alias, site) {
|
||
this._deepLinks.set(alias.toLowerCase(), site);
|
||
}
|
||
|
||
setShowCookieCompliance(cookieCompliance)
|
||
{
|
||
this._showCookieCompliance = cookieCompliance;
|
||
}
|
||
|
||
refreshCurrentSite()
|
||
{
|
||
this._siteManager.refreshCurrentSite();
|
||
}
|
||
|
||
pause(elementToShow){
|
||
this.startSite(PauseSite, {"url": elementToShow});
|
||
}
|
||
|
||
resume(){
|
||
const currentSite = this._siteManager.getCurrentSite();
|
||
if (currentSite instanceof PauseSite)
|
||
{
|
||
currentSite.finish();
|
||
}
|
||
}
|
||
|
||
_resolveDeepLink(deepLink) {
|
||
deepLink = deepLink.toLowerCase();
|
||
if (this._deepLinks.has(deepLink)) {
|
||
return this._deepLinks.get(deepLink);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
_getDeepLink() {
|
||
let deepLink = "";
|
||
if (window.location.pathname.search(this._basePath) === 0) {
|
||
deepLink = window.location.pathname.substr(this._basePath.length).trim();
|
||
}
|
||
if (deepLink.charAt(0) === '/') {
|
||
deepLink = deepLink.substr(1).trim();
|
||
}
|
||
if (deepLink.charAt(deepLink.length - 1) === '/') {
|
||
deepLink = deepLink.substr(0, deepLink.length - 2).trim();
|
||
}
|
||
if (deepLink.length === 0 && window.location.hash) {
|
||
deepLink = window.location.hash.substr(1).trim();
|
||
}
|
||
|
||
return this._resolveDeepLink(deepLink);
|
||
}
|
||
|
||
_addDeepLinksListener() {
|
||
let app = this;
|
||
let elements = document.getElementsByClassName("deep-link");
|
||
for (let i = 0, n = elements.length; i < n; i++) {
|
||
elements[i].addEventListener("click", function (e) {
|
||
e.preventDefault();
|
||
app._siteManager.startSite(Helper.nonNull(app._resolveDeepLink(this.dataset["siteName"]), app._startSite), App._extractParams(this.dataset["siteArgs"]));
|
||
return true;
|
||
});
|
||
}
|
||
}
|
||
|
||
removeDefaultAction(action)
|
||
{
|
||
let index = this._defaultActions.indexOf(action);
|
||
if (index >= 0)
|
||
{
|
||
this._defaultActions[index].remove(true);
|
||
this._defaultActions.splice(index, 1);
|
||
}
|
||
}
|
||
|
||
startSite(site, parameter)
|
||
{
|
||
return this._siteManager.startSite(site, parameter);
|
||
}
|
||
|
||
start(fallbackStartSite) {
|
||
SystemSettings.setBasePath(this._basePath);
|
||
let startSite = Helper.nonNull(this._getDeepLink(), fallbackStartSite);
|
||
let startParams = App._getStartParams();
|
||
this._startSite = fallbackStartSite;
|
||
|
||
Translator.init();
|
||
ThemeManager.init();
|
||
if (this._addThemeAction) {
|
||
this.addDefaultAction(ThemeManager.generateChangeThemeMenuAction());
|
||
}
|
||
this._siteManager = new SiteManager(this._siteContentId, this._actionBarMenuSelector);
|
||
this._siteManager.defaultActions = this._defaultActions;
|
||
this._siteManager.setStartSiteName(fallbackStartSite);
|
||
this._siteManager.startSite(startSite, startParams);
|
||
this._addDeepLinksListener();
|
||
|
||
if (this._showCookieCompliance)
|
||
{
|
||
new CookieCompliance('cookie-compliance').showIfNeeded();
|
||
}
|
||
}
|
||
|
||
static _extractParams(paramString) {
|
||
if (Helper.isNull(paramString)) {
|
||
return null;
|
||
}
|
||
let result = {}, tmp = [];
|
||
let items = paramString.split("&");
|
||
for (let index = 0; index < items.length; index++) {
|
||
tmp = items[index].split("=");
|
||
if (tmp[0].trim().length > 0) {
|
||
result[tmp[0]] = decodeURIComponent(tmp[1]);
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
static _getStartParams() {
|
||
return App._extractParams(window.location.search.substr(1));
|
||
}
|
||
}
|
||
|
||
class InitPromise
|
||
{
|
||
static addPromise(promise)
|
||
{
|
||
if (typeof promise === 'function')
|
||
{
|
||
let func = promise;
|
||
promise = InitPromise.mainPromise.then(function(app){
|
||
return (func(app));
|
||
});
|
||
}
|
||
InitPromise.promises.push(promise);
|
||
}
|
||
|
||
static resolve(app)
|
||
{
|
||
InitPromise.mainResolver(app);
|
||
return InitPromise.mainPromise.then(function(){
|
||
return Promise.all(InitPromise.promises);
|
||
});
|
||
}
|
||
}
|
||
InitPromise.promises = [];
|
||
InitPromise.mainPromise = new Promise(function(resolver){
|
||
InitPromise.mainResolver = resolver;
|
||
});
|
||
|
||
class ShareButton {
|
||
constructor(deviceType, icon, callback)
|
||
{
|
||
this._deviceType = deviceType;
|
||
this._icon = icon;
|
||
this._callback = callback;
|
||
}
|
||
|
||
shouldShowFor(deviceType)
|
||
{
|
||
return (deviceType === (deviceType & this._deviceType))
|
||
}
|
||
|
||
getIcon()
|
||
{
|
||
return this._icon;
|
||
}
|
||
|
||
getCallback()
|
||
{
|
||
return this._callback;
|
||
}
|
||
}
|
||
ShareButton.TYPE_DESKTOP = 1;
|
||
ShareButton.TYPE_MOBILE_APPLE = 2;
|
||
ShareButton.TYPE_MOBILE_LEFTOVER = 4;
|
||
ShareButton.TYPE_MOBILE = ShareButton.TYPE_MOBILE_APPLE+ShareButton.TYPE_MOBILE_LEFTOVER;
|
||
ShareButton.TYPE_ALL = ShareButton.TYPE_DESKTOP+ShareButton.TYPE_MOBILE;
|
||
|
||
class ShareManager {
|
||
static init() {
|
||
ShareManager.shareButtons = [];
|
||
}
|
||
|
||
static addShareButton(shareButton) {
|
||
ShareManager.shareButtons.push(shareButton);
|
||
}
|
||
|
||
static generateDefaultShareElement(shareUrl)
|
||
{
|
||
return ShareManager.generateShareElement(shareUrl, ShareManager.getDefaultGenerateCallback());
|
||
}
|
||
|
||
static generateDefaultShareElementForButtons(shareUrl, buttons)
|
||
{
|
||
return ShareManager.generateShareElementForButtons(shareUrl, buttons, ShareManager.getDefaultGenerateCallback());
|
||
}
|
||
|
||
static generateShareElement(shareUrl, generateCallback) {
|
||
return ShareManager.generateShareElementForButtons(shareUrl, ShareManager.shareButtons, generateCallback);
|
||
}
|
||
|
||
static generateShareElementForButtons(shareUrl, buttons, generateCallback)
|
||
{
|
||
let shareButtonElement = document.createElement("div");
|
||
let currentDeviceType = ShareManager.getCurrentDeviceType();
|
||
for (let i = 0, n = buttons.length; i < n; i++) {
|
||
if (buttons[i].shouldShowFor(currentDeviceType)) {
|
||
let elem = generateCallback(buttons[i], shareUrl);
|
||
elem.onclick = function(event){
|
||
buttons[i].getCallback()(shareUrl, this, event);
|
||
};
|
||
shareButtonElement.appendChild(elem);
|
||
}
|
||
}
|
||
return shareButtonElement;
|
||
}
|
||
|
||
static getCurrentDeviceType() {
|
||
if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) {
|
||
return ShareButton.TYPE_MOBILE_APPLE;
|
||
}
|
||
else if ((navigator.userAgent.match(/Android|BlackBerry|Opera Mini|IEMobile/i) !== null || (typeof window.orientation !== "undefined"))) {
|
||
return ShareButton.TYPE_MOBILE_LEFTOVER;
|
||
}
|
||
else {
|
||
return ShareButton.TYPE_DESKTOP;
|
||
}
|
||
}
|
||
|
||
static getDefaultGenerateCallback()
|
||
{
|
||
return function(button){
|
||
let linkElement = document.createElement("a");
|
||
let iconElement = document.createElement("img");
|
||
linkElement.appendChild(iconElement);
|
||
|
||
iconElement.src = Helper.basePath(button.getIcon());
|
||
iconElement.classList.add("share-icon");
|
||
|
||
return linkElement;
|
||
}
|
||
}
|
||
}
|
||
|
||
ShareManager.init();
|
||
|
||
class SmsShareButton extends ShareButton
|
||
{
|
||
constructor(icon) {
|
||
super(ShareButton.TYPE_MOBILE, icon, function (link) {
|
||
let linkToOpen = "";
|
||
if (ShareManager.getCurrentDeviceType() === ShareButton.TYPE_MOBILE_APPLE) {
|
||
linkToOpen = "sms:&body="+encodeURIComponent(link);
|
||
}
|
||
else {
|
||
linkToOpen = "sms:?body=" + encodeURIComponent(link);
|
||
}
|
||
window.open(linkToOpen, '_blank');
|
||
});
|
||
}
|
||
}
|
||
|
||
class TelegramShareButton extends ShareButton {
|
||
constructor(icon) {
|
||
super(ShareButton.TYPE_ALL, icon, function (link) {
|
||
let linkToOpen = "https://t.me/share/url?url="+encodeURIComponent(link);
|
||
window.open(linkToOpen, '_blank');
|
||
});
|
||
}
|
||
}
|
||
|
||
class WhatsappShareButton extends ShareButton {
|
||
constructor(icon) {
|
||
super(ShareButton.TYPE_ALL, icon, function (link) {
|
||
let linkToOpen = "";
|
||
if (ShareManager.getCurrentDeviceType() === ShareButton.TYPE_DESKTOP) {
|
||
linkToOpen = "https://web.whatsapp.com/send?text="+encodeURIComponent(link);
|
||
}
|
||
else {
|
||
linkToOpen = "whatsapp://send?text=" + encodeURIComponent(link);
|
||
}
|
||
window.open(linkToOpen, '_blank');
|
||
});
|
||
}
|
||
}
|
||
|
||
class Theme
|
||
{
|
||
constructor(name, className, icon)
|
||
{
|
||
this._name = name;
|
||
this._className = className;
|
||
this._icon = icon;
|
||
}
|
||
}
|
||
|
||
function applyPolyfills(){
|
||
if (!String.prototype.format) {
|
||
String.prototype.format = function (args) {
|
||
return this.replace(/{(\d+)}/g, function (match, number) {
|
||
return args[number] !== undefined
|
||
? args[number]
|
||
: match
|
||
;
|
||
});
|
||
};
|
||
}
|
||
Object.assign = Helper.nonNull(Object.assign, function (base, obj) {
|
||
base = Helper.nonNull(base, {});
|
||
if (obj === null || typeof(obj) !== 'object' || 'isActiveClone' in obj)
|
||
return base;
|
||
|
||
// if (obj instanceof Date) {
|
||
// temp = new obj.constructor(); //or new Date(obj);
|
||
// }
|
||
// else {
|
||
// temp = obj.constructor();
|
||
// }
|
||
|
||
for (let key in obj) {
|
||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||
obj['isActiveClone'] = null;
|
||
base[key] = obj[key];
|
||
delete obj['isActiveClone'];
|
||
}
|
||
}
|
||
|
||
return base;
|
||
});
|
||
|
||
if (typeof window !== 'undefined') {
|
||
if (Helper.isNotNull(window["Node"]) && !window["Node"]["prototype"]["removeAllChildren"]) {
|
||
Node.prototype["removeAllChildren"] = function () {
|
||
while (this.firstChild) {
|
||
this.removeChild(this.firstChild);
|
||
}
|
||
return this;
|
||
};
|
||
}
|
||
|
||
if (HTMLElement) {
|
||
|
||
HTMLElement.prototype["fadeOut"] = Helper.nonNull(HTMLElement.prototype["fadeOut"],
|
||
function (time, effect, delay) {
|
||
time = Helper.nonNull(time, 0.5);
|
||
effect = Helper.nonNull(effect, "ease-in-out");
|
||
delay = Helper.nonNull(delay, 0);
|
||
this.style.transition = "opacity " + time + "s " + effect + " " + delay + "s";
|
||
let elem = this;
|
||
let animPromise = new Promise(function (resolve) {
|
||
let transEndLis = function (e) {
|
||
elem.removeEventListener("transitionend", transEndLis);
|
||
elem.removeEventListener("transitioncancel", transCancelledLis);
|
||
elem.style.opacity = null;
|
||
elem.style.transition = null;
|
||
resolve(true, e);
|
||
};
|
||
|
||
let transCancelledLis = function (e) {
|
||
elem.removeEventListener("transitionend", transEndLis);
|
||
elem.removeEventListener("transitioncancel", transCancelledLis);
|
||
elem.style.opacity = null;
|
||
elem.style.transition = null;
|
||
resolve(false, e);
|
||
};
|
||
elem.addEventListener("transitionend", transEndLis);
|
||
elem.addEventListener("transitioncancel", transCancelledLis);
|
||
});
|
||
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
|
||
requestAnimationFrame(function () {
|
||
requestAnimationFrame(function () {
|
||
elem.style.opacity = 0;
|
||
});
|
||
});
|
||
return animPromise
|
||
});
|
||
|
||
HTMLElement.prototype["fadeIn"] = Helper.nonNull(HTMLElement.prototype["fadeIn"], function (time, effect, delay) {
|
||
time = Helper.nonNull(time, 0.5);
|
||
effect = Helper.nonNull(effect, "ease-in-out");
|
||
delay = Helper.nonNull(delay, 0);
|
||
this.style.transition = "opacity " + time + "s " + effect + " " + delay + "s";
|
||
|
||
let elem = this;
|
||
let animPromise = new Promise(function (resolve) {
|
||
let transEndLis = function (e) {
|
||
elem.removeEventListener("transitionend", transEndLis);
|
||
elem.removeEventListener("transitioncancel", transCancelledLis);
|
||
elem.style.opacity = null;
|
||
elem.style.transition = null;
|
||
resolve(true, e);
|
||
};
|
||
|
||
let transCancelledLis = function (e) {
|
||
elem.removeEventListener("transitionend", transEndLis);
|
||
elem.removeEventListener("transitioncancel", transCancelledLis);
|
||
elem.style.opacity = null;
|
||
elem.style.transition = null;
|
||
resolve(false, e);
|
||
};
|
||
elem.addEventListener("transitionend", transEndLis);
|
||
elem.addEventListener("transitioncancel", transCancelledLis);
|
||
});
|
||
|
||
//Nach Seitenneuzeichnen, damit chrome das immer macht (und FF auch)
|
||
requestAnimationFrame(function () {
|
||
requestAnimationFrame(function () {
|
||
elem.style.opacity = 1;
|
||
});
|
||
});
|
||
return animPromise;
|
||
});
|
||
}
|
||
|
||
if (Node) {
|
||
Node.prototype["replaceWith"] = Helper.nonNull(Node.prototype["replaceWith"], function (elem) {
|
||
this.parentElement.replaceChild(elem, this);
|
||
});
|
||
Node.prototype["remove"] = Helper.nonNull(Node.prototype["remove"], function () {
|
||
this.parentElement.removeChild(this);
|
||
});
|
||
}
|
||
|
||
if (Element) {
|
||
Element.prototype.matches = Helper.nonNull(Element.prototype.matches, Helper.nonNull(Element.prototype["matchesSelector"], Element.prototype["webkitMatchesSelector"]));
|
||
|
||
window["Element"]["prototype"]["closest"] = Helper.nonNull(window["Element"]["prototype"]["getAll"], function (s) {
|
||
// if (!Element.prototype.matches)
|
||
// Element.prototype.matches = Element.prototype.msMatchesSelector ||
|
||
// Element.prototype.webkitMatchesSelector;
|
||
//
|
||
// if (!Element.prototype.closest)
|
||
// Element.prototype.closest = function(s) {
|
||
let el = this;
|
||
if (!document.documentElement.contains(el)) return null;
|
||
do {
|
||
if (el.matches(s)) return el;
|
||
el = el.parentElement;
|
||
} while (el !== null);
|
||
return null;
|
||
// };
|
||
});
|
||
}
|
||
|
||
window["IDBObjectStore"]["prototype"]["getAll"] = Helper.nonNull(window["IDBObjectStore"]["prototype"]["getAll"], function () {
|
||
let res = {};
|
||
let items = [];
|
||
this.openCursor().onsuccess = function (e) {
|
||
let cursor = e.target.result;
|
||
if (Helper.isNotNull(cursor)) {
|
||
items.push(cursor.value);
|
||
cursor.continue();
|
||
}
|
||
else if (Helper.isNotNull(res.onsuccess)) {
|
||
res.onsuccess({currentTarget: {result: items}});
|
||
}
|
||
};
|
||
return res;
|
||
});
|
||
}
|
||
|
||
String.prototype.startsWith = Helper.nonNull(String.prototype.startsWith, function (searchString, position) {
|
||
position = position || 0;
|
||
return this.indexOf(searchString, position) === position;
|
||
});
|
||
|
||
String.prototype.endsWith = Helper.nonNull(String.prototype.endsWith, function (searchString, position) {
|
||
var subjectString = this.toString();
|
||
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
|
||
position = subjectString.length;
|
||
}
|
||
position -= searchString.length;
|
||
var lastIndex = subjectString.indexOf(searchString, position);
|
||
return lastIndex !== -1 && lastIndex === position;
|
||
});
|
||
|
||
|
||
var fetch = Helper.nonNull(fetch, function (url) {
|
||
console.log("customFetch", url);
|
||
let request = null;
|
||
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
|
||
request = new XMLHttpRequest();
|
||
} else if (window.ActiveXObject) { // IE
|
||
try {
|
||
request = new ActiveXObject('Msxml2.XMLHTTP');
|
||
}
|
||
catch (e) {
|
||
try {
|
||
request = new ActiveXObject('Microsoft.XMLHTTP');
|
||
}
|
||
catch (e) {
|
||
}
|
||
}
|
||
}
|
||
|
||
let resultPromise = new Promise(function (resolve) {
|
||
request.onload = function () {
|
||
let data = this.responseText;
|
||
let response = {
|
||
json: function () {
|
||
return Promise.resolve(JSON.parse(data));
|
||
},
|
||
text: function () {
|
||
return Promise.resolve(data);
|
||
}
|
||
};
|
||
resolve(response);
|
||
};
|
||
request.onerror = function (err) {
|
||
resolve(Promise.reject(err));
|
||
};
|
||
});
|
||
request.open('get', url, true);
|
||
request.send();
|
||
return resultPromise;
|
||
});
|
||
}
|
||
|
||
SystemSettings.setBasePath("/pwa/wordRotator/public/");
|
||
Translator.supportedLanguages = ["de", "en"];
|
||
Translator.markTranslations = false;
|
||
|
||
class Segment{
|
||
constructor(element){
|
||
this.rotation = 0;
|
||
this.element = element;
|
||
}
|
||
|
||
isSolved(){
|
||
return (this.rotation === 0);
|
||
}
|
||
|
||
rotate(){};
|
||
|
||
_updateElement(){};
|
||
|
||
applyRotations(rotations){
|
||
return rotations;
|
||
}
|
||
|
||
getElement()
|
||
{
|
||
return this.element;
|
||
}
|
||
}
|
||
|
||
class ParentSegment extends Segment {
|
||
constructor(element) {
|
||
super(element);
|
||
this.children = [];
|
||
this.class = "rotate-0";
|
||
}
|
||
|
||
rotate() {
|
||
this.rotation += 90;
|
||
this.rotation %= 360;
|
||
|
||
this._updateRotationClass();
|
||
}
|
||
|
||
applyRotations(rotations) {
|
||
// debugger;
|
||
this.rotation = rotations[0];
|
||
rotations.splice(0, 1);
|
||
for (let i = 0, n = this.children.length; i < n; i++) {
|
||
rotations = this.children[i].applyRotations(rotations);
|
||
}
|
||
return rotations;
|
||
}
|
||
|
||
isSolved() {
|
||
for (let i = 0, n = this.children.length; i < n; i++) {
|
||
if (!this.children[i].isSolved()) {
|
||
return false;
|
||
}
|
||
}
|
||
return super.isSolved();
|
||
}
|
||
|
||
setChildren(children) {
|
||
this.children = [];
|
||
for (let i = 0, n = children.length; i < n; i++) {
|
||
this.addChild(children[i]);
|
||
}
|
||
}
|
||
|
||
addChild(child) {
|
||
this.children.push(child);
|
||
this._updateElement();
|
||
}
|
||
|
||
_updateRotationClass() {
|
||
// this.style.transform = "rotate("+this.rotation+"deg)";
|
||
this.element.classList.remove(this.class);
|
||
this.class = "rotate-" + this.rotation;
|
||
if (this.class === "rotate-0")
|
||
{
|
||
this.class = "rotate-360";
|
||
}
|
||
this.element.classList.add(this.class);
|
||
|
||
// if (this.rotation === 0) {
|
||
// const self = this;
|
||
// self.element.classList.add("no-transition");
|
||
//
|
||
// setTimeout(() => {
|
||
// if (self.class === "rotate-0") {
|
||
// requestAnimationFrame(()=>{
|
||
//
|
||
// self.element.classList.remove("rotate-0");
|
||
// self.element.classList.remove("no-transition");
|
||
// });
|
||
// }
|
||
// }, 250);
|
||
// }
|
||
}
|
||
|
||
_updateElement() {
|
||
const childContainer = this.element.querySelector(".child-container");
|
||
childContainer.removeAllChildren();
|
||
|
||
this._updateRotationClass();
|
||
|
||
const self = this;
|
||
this.element.onclick = function () {
|
||
self.rotate();
|
||
};
|
||
|
||
for (let i = 0, n = this.children.length; i < n; i++) {
|
||
this.children[i]._updateElement();
|
||
childContainer.appendChild(this.children[i].getElement());
|
||
}
|
||
}
|
||
}
|
||
|
||
class LeafSegment extends Segment{
|
||
|
||
constructor(element, leaf) {
|
||
super(element);
|
||
this.leaf = 'A';
|
||
if (Helper.isNotNull(leaf))
|
||
{
|
||
this.setLeaf(leaf);
|
||
}
|
||
}
|
||
|
||
setLeaf(leaf)
|
||
{
|
||
this.leaf = leaf;
|
||
}
|
||
|
||
_updateElement() {
|
||
this.element.querySelector(".leaf-element").removeAllChildren().appendChild(document.createTextNode(this.leaf));
|
||
}
|
||
}
|
||
|
||
class TemplateContainer{
|
||
constructor(leafTemplate, parentTemplate, rowTemplate){
|
||
this.leafTemplate = leafTemplate;
|
||
this.parentTemplate = parentTemplate;
|
||
this.rowTemplate = rowTemplate;
|
||
}
|
||
|
||
copyLeafTemplate()
|
||
{
|
||
return Helper.cloneNode(this.leafTemplate);
|
||
}
|
||
|
||
copyParentTemplate()
|
||
{
|
||
return Helper.cloneNode(this.parentTemplate);
|
||
}
|
||
|
||
copyRowTemplate()
|
||
{
|
||
return Helper.cloneNode(this.rowTemplate);
|
||
}
|
||
}
|
||
|
||
class Level {
|
||
constructor(templateContainer) {
|
||
this.rootSegment = null;
|
||
this.words = [];
|
||
this.startRotations = [];
|
||
this.templateContainer = templateContainer;
|
||
}
|
||
|
||
setWords(words)
|
||
{
|
||
this.words = [];
|
||
for (let i = 0, n = words.length; i < n; i++) {
|
||
this.words.push(words[i].toUpperCase());
|
||
}
|
||
}
|
||
|
||
setStartRotations(rotations)
|
||
{
|
||
this.startRotations = rotations;
|
||
}
|
||
|
||
hasWon() {
|
||
return this.rootSegment.isSolved();
|
||
}
|
||
|
||
getRootSegment(){
|
||
return this.rootSegment;
|
||
}
|
||
|
||
createSegments() {};
|
||
|
||
static _createLeafsForWord(word, leafSegmentTemplate)
|
||
{
|
||
let leafSegments = [];
|
||
for (let i = 0, n = word.length; i < n; i++) {
|
||
leafSegments.push(new LeafSegment(Helper.cloneNode(leafSegmentTemplate), word.charAt(i)));
|
||
}
|
||
return leafSegments;
|
||
}
|
||
}
|
||
|
||
class RowSegment extends ParentSegment{
|
||
rotate() {}
|
||
|
||
applyRotations(rotations)
|
||
{
|
||
for (let i = 0, n = this.children.length; i < n; i++) {
|
||
rotations = this.children[i].applyRotations(rotations);
|
||
}
|
||
return rotations;
|
||
}
|
||
}
|
||
|
||
class SimpleLevel extends Level{
|
||
|
||
createSegments() {
|
||
if (this.words.length >= 2 && this.words[0].length >= 6 &&this.words[1].length >= 6){
|
||
|
||
let leafsWordOne = Level._createLeafsForWord(this.words[0], this.templateContainer.copyLeafTemplate());
|
||
let leafsWordTwo = Level._createLeafsForWord(this.words[1], this.templateContainer.copyLeafTemplate());
|
||
|
||
let segmentOne = new ParentSegment(this.templateContainer.copyParentTemplate());
|
||
let segmentTwo = new ParentSegment(this.templateContainer.copyParentTemplate());
|
||
let segmentThree = new ParentSegment(this.templateContainer.copyParentTemplate());
|
||
|
||
segmentOne.addChild(leafsWordOne[0]);
|
||
segmentOne.addChild(leafsWordOne[1]);
|
||
segmentOne.addChild(leafsWordTwo[0]);
|
||
segmentOne.addChild(leafsWordTwo[1]);
|
||
|
||
segmentTwo.addChild(leafsWordOne[2]);
|
||
segmentTwo.addChild(leafsWordOne[3]);
|
||
segmentTwo.addChild(leafsWordTwo[2]);
|
||
segmentTwo.addChild(leafsWordTwo[3]);
|
||
|
||
segmentThree.addChild(leafsWordOne[4]);
|
||
segmentThree.addChild(leafsWordOne[5]);
|
||
segmentThree.addChild(leafsWordTwo[4]);
|
||
segmentThree.addChild(leafsWordTwo[5]);
|
||
|
||
this.rootSegment = new RowSegment(this.templateContainer.copyRowTemplate());
|
||
this.rootSegment.addChild(segmentOne);
|
||
this.rootSegment.addChild(segmentTwo);
|
||
this.rootSegment.addChild(segmentThree);
|
||
|
||
this.rootSegment.applyRotations(this.startRotations);
|
||
}
|
||
}
|
||
}
|
||
|
||
class LevelSite extends AbstractSite$1{
|
||
constructor(siteManager) {
|
||
super(siteManager, "html/application/level.html", "level");
|
||
}
|
||
|
||
onConstruct(args) {
|
||
this.setTitle("Level");
|
||
return super.onConstruct(args);
|
||
}
|
||
|
||
onFirstStart() {
|
||
super.onFirstStart();
|
||
|
||
let leafSegmentTemplate = this.findBy("#segment-leaf-template");
|
||
let parentSegmentTemplate = this.findBy("#segment-parent-template");
|
||
let rowSegmentTemplate = this.findBy("#segment-row-template");
|
||
|
||
leafSegmentTemplate.id = null;
|
||
parentSegmentTemplate.id = null;
|
||
rowSegmentTemplate.id = null;
|
||
|
||
leafSegmentTemplate.remove();
|
||
parentSegmentTemplate.remove();
|
||
rowSegmentTemplate.remove();
|
||
|
||
let templateContainer = new TemplateContainer(leafSegmentTemplate, parentSegmentTemplate, rowSegmentTemplate);
|
||
|
||
|
||
let level = new SimpleLevel(templateContainer);
|
||
level.setWords([
|
||
"Dynamo",
|
||
"Abhang"
|
||
]);
|
||
level.setStartRotations([0,90,180]);
|
||
|
||
level.createSegments();
|
||
level.getRootSegment()._updateElement();
|
||
this.findBy("#level").appendChild(level.getRootSegment().getElement());
|
||
}
|
||
}
|
||
|
||
applyPolyfills();
|
||
|
||
ThemeManager.addTheme(new Theme('red', ''));
|
||
ThemeManager.addTheme(new Theme("blue", "blue"));
|
||
ThemeManager.addTheme(new Theme("black", "black"));
|
||
ThemeManager.addTheme(new Theme("green", "green"));
|
||
ThemeManager.addTheme(new Theme("pink", "pink"));
|
||
|
||
ShareManager.addShareButton(new WhatsappShareButton('img/whatsapp.svg'));
|
||
ShareManager.addShareButton(new SmsShareButton('img/sms.svg'));
|
||
ShareManager.addShareButton(new TelegramShareButton('img/telegram.svg'));
|
||
// ShareManager.addShareButton(new CopyShareButton('img/copy.svg'));
|
||
|
||
let app = new App();
|
||
// app.addDeepLink("policy", PrivatePolicySite.name);
|
||
app.setAddThemeAction(true);
|
||
app.addDefaultAction(Translator.generateChangeLanguageMenuAction());
|
||
|
||
//bridge für Android
|
||
// window["ThemeManager"] = ThemeManager;
|
||
// window["ThemeManager"]["addChangeListener"] = ThemeManager.addChangeListener;
|
||
// window["app"] = app;
|
||
// window["app"]["refreshCurrentSite"] = app.refreshCurrentSite;
|
||
// window["Translator"] = Translator;
|
||
// window["Translator"]["setLanguage"] = Translator.setLanguage;
|
||
|
||
InitPromise.resolve(app).then(function(){
|
||
app.start(LevelSite);
|
||
Translator.setLanguage("de");
|
||
});
|