4278 lines
139 KiB
JavaScript
Executable File
4278 lines
139 KiB
JavaScript
Executable File
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;
|
||
}
|
||
|
||
getShowFor(){
|
||
return this.showFor;
|
||
}
|
||
|
||
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; i < this._copies.length; 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; i < this.actions.length; 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; i < this.parentElements.length; i++) {
|
||
let elem = this.parentElements[i].querySelector("[data-id=\""+action.getId()+"\"]");
|
||
Helper.isNull(elem) || elements.push(elem);
|
||
}
|
||
return elements
|
||
}
|
||
|
||
updateAction(action)
|
||
{
|
||
console.log("update action here!");
|
||
let oldElements = this._getElementsForAction(action);
|
||
if (oldElements.length === 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
let element = this.renderAction(action);
|
||
action._htmlElement = element;
|
||
|
||
for (let i = 0; i < oldElements.length; 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; i < this.parentElements.length; 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; i < stringToEncode.length; 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; i < ActionBarMenu.queries.length; i++) {
|
||
let query = ActionBarMenu.queries[i];
|
||
|
||
if (matchMedia(query.value).matches) {
|
||
matched = query;
|
||
}
|
||
}
|
||
|
||
if (typeof matched === 'object') {
|
||
return matched._name;
|
||
} else {
|
||
return matched;
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
renderLiElement(aElement, action) {
|
||
let liElement = super.renderLiElement(aElement, action);
|
||
liElement.classList.add(action.getShowFor());
|
||
return liElement;
|
||
}
|
||
|
||
updateToggleButton() {
|
||
let size = ActionBarMenu._getCurrentSize();
|
||
let firstParentElement = this.parentElements[0];
|
||
if ((size === "medium" || size === "smedium" || size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_LARGE)).length > 0 ||
|
||
(size === "smedium" || size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_MEDIUM)).length > 0 ||
|
||
(size === "small") && ActionBarMenu.filterVisibleElements(firstParentElement.getElementsByClassName(Menu.SHOW_FOR_SMEDIUM)).length > 0 ||
|
||
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 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))
|
||
{
|
||
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 {
|
||
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 ChainAble{
|
||
constructor()
|
||
{
|
||
this.promise = Promise.resolve();
|
||
}
|
||
|
||
_chain(func){
|
||
if (typeof func !== "function")
|
||
{
|
||
return this._chain(function(){
|
||
return Promise.resolve(func);
|
||
});
|
||
}
|
||
else
|
||
{
|
||
this.promise = this.promise.then(func);
|
||
}
|
||
return this;
|
||
}
|
||
}
|
||
|
||
class Dialog {
|
||
constructor(content, title) {
|
||
this.resolver = null;
|
||
this.content = null;
|
||
this.backgroundElement = null;
|
||
this.cancelable = true;
|
||
this.title = Helper.nonNull(title, "");
|
||
this.translatable = true;
|
||
this.additionalClasses = "";
|
||
this.buttons = [];
|
||
this.result = null;
|
||
|
||
if (Helper.isNotNull(content)) {
|
||
this.setContent(content);
|
||
}
|
||
}
|
||
|
||
setTitle(title) {
|
||
this.title = title;
|
||
return this;
|
||
}
|
||
|
||
setTranslatable(translatable) {
|
||
this.translatable = translatable;
|
||
}
|
||
|
||
setAdditionalClasses(classes) {
|
||
this.additionalClasses = classes;
|
||
}
|
||
|
||
getTitle() {
|
||
return this.title;
|
||
}
|
||
|
||
setCancelable(cancelable) {
|
||
this.cancelable = (cancelable === true);
|
||
return this;
|
||
}
|
||
|
||
async setContent(content) {
|
||
this.contentPromise = Promise.resolve(content);
|
||
this.content = await this.contentPromise;
|
||
return this;
|
||
}
|
||
|
||
addButton(elementOrText, listenerOrResult, shouldClose) {
|
||
shouldClose = Helper.nonNull(shouldClose, true);
|
||
|
||
let button = null;
|
||
if (typeof elementOrText === "string") {
|
||
button = document.createElement("button");
|
||
button.classList.add("button");
|
||
button.classList.add("right");
|
||
button.appendChild(Translator.makePersistentTranslation(elementOrText));
|
||
}
|
||
else {
|
||
button = elementOrText;
|
||
}
|
||
|
||
let self = this;
|
||
if (typeof listenerOrResult !== "function") {
|
||
let result = listenerOrResult;
|
||
listenerOrResult = function () {
|
||
self.result = result;
|
||
};
|
||
}
|
||
|
||
let callback = null;
|
||
if (shouldClose) {
|
||
callback = function (e) {
|
||
if (Helper.isNotNull(listenerOrResult)) {
|
||
listenerOrResult(e);
|
||
}
|
||
self.close();
|
||
};
|
||
}
|
||
else {
|
||
callback = listenerOrResult;
|
||
}
|
||
|
||
if (Helper.isNotNull(callback)) {
|
||
button.addEventListener("click", callback);
|
||
}
|
||
this.buttons.push(button);
|
||
}
|
||
|
||
async show() {
|
||
|
||
let titleElement = document.createElement("span");
|
||
titleElement.classList.add("title");
|
||
if (this.translatable && this.title !== "") {
|
||
titleElement.appendChild(Translator.makePersistentTranslation(this.title));
|
||
}
|
||
else {
|
||
titleElement.innerHTML = this.title;
|
||
}
|
||
|
||
let titleBar = document.createElement("div");
|
||
titleBar.appendChild(titleElement);
|
||
|
||
let contentContainer = document.createElement("div");
|
||
contentContainer.classList.add("content-container");
|
||
|
||
let modalDialog = document.createElement("div");
|
||
modalDialog.className = this.additionalClasses;
|
||
modalDialog.classList.add("modal");
|
||
modalDialog.appendChild(titleBar);
|
||
modalDialog.appendChild(contentContainer);
|
||
|
||
let buttonBar = document.createElement("div");
|
||
buttonBar.classList.add("modal-button-container");
|
||
|
||
for (let i = 0, n = this.buttons.length; i < n; i++) {
|
||
buttonBar.appendChild(this.buttons[i]);
|
||
}
|
||
|
||
await this.contentPromise;
|
||
if (!(this.content instanceof Node)) {
|
||
this.content = (this.translatable) ? Translator.makePersistentTranslation(this.content) : document.createTextNode(this.content);
|
||
}
|
||
contentContainer.appendChild(this.content);
|
||
|
||
this.backgroundElement = document.createElement("div");
|
||
this.backgroundElement.classList.add("background");
|
||
this.backgroundElement.appendChild(modalDialog);
|
||
|
||
this.backgroundElement.querySelector(".modal").appendChild(buttonBar);
|
||
this.backgroundElement.style.display = "block";
|
||
|
||
let self = this;
|
||
if (this.cancelable) {
|
||
let closeButton = document.createElement("span");
|
||
closeButton.classList.add("close");
|
||
closeButton.innerHTML = "×";
|
||
|
||
titleBar.appendChild(closeButton);
|
||
closeButton.addEventListener("click", function () {
|
||
self.close();
|
||
});
|
||
window.addEventListener("click", function (e) {
|
||
if (e.target === self.backgroundElement) {
|
||
self.close();
|
||
}
|
||
});
|
||
}
|
||
|
||
document.body.appendChild(this.backgroundElement);
|
||
Translator.getInstance().updateTranslations();
|
||
|
||
return new Promise(function (resolve) {
|
||
self.resolver = resolve;
|
||
});
|
||
}
|
||
|
||
close() {
|
||
if (Helper.isNotNull(this.backgroundElement)) {
|
||
this.backgroundElement.style.display = "none";
|
||
this.backgroundElement.remove();
|
||
this.backgroundElement = null;
|
||
}
|
||
if (Helper.isNotNull(this.resolver)) {
|
||
this.resolver(this.result);
|
||
}
|
||
}
|
||
|
||
addDefaultButton(){
|
||
this.addButton("confirm-button");
|
||
}
|
||
}
|
||
|
||
class ConfirmDialog extends Dialog {
|
||
constructor(content, title) {
|
||
super(content, title);
|
||
}
|
||
|
||
async show() {
|
||
this.addButton("confirm-button", true);
|
||
this.addButton("cancel-button", false);
|
||
|
||
return super.show();
|
||
}
|
||
|
||
|
||
close() {
|
||
if (Helper.isNull(this.result))
|
||
{
|
||
this.result = false;
|
||
}
|
||
return super.close();
|
||
}
|
||
}
|
||
|
||
class FlashMessenger {
|
||
static deleteMessage(_idNumber, _delayInMilliSeconds) {
|
||
_delayInMilliSeconds = Helper.nonNull(_delayInMilliSeconds, 0);
|
||
setTimeout(function () {
|
||
let elem = document.getElementById("flashMessage" + _idNumber);
|
||
elem.fadeOut(.2).then(function () {
|
||
elem.remove();
|
||
});
|
||
}, _delayInMilliSeconds);
|
||
}
|
||
|
||
static addMessage(messageType, messageText, timeToShow, translate){
|
||
|
||
let translationArgs = null;
|
||
if (Helper.isNull(messageText) || typeof messageText === "object")
|
||
{
|
||
translationArgs = messageText;
|
||
messageText = messageType;
|
||
messageType = FlashMessenger.MESSAGE_TYPE_SUCCESS;
|
||
translate = true;
|
||
}
|
||
translate = Helper.nonNull(translate, false);
|
||
|
||
let id = FlashMessenger.messageCount;
|
||
|
||
let wrapper = document.createElement("div");
|
||
|
||
let _flashMessage = document.createElement("div");
|
||
_flashMessage.className = "flashMessage " + messageType;
|
||
_flashMessage.id = "flashMessage" + id;
|
||
_flashMessage.style.opacity = '0';
|
||
_flashMessage.addEventListener("click", function () {
|
||
FlashMessenger.deleteMessage(id);
|
||
});
|
||
_flashMessage.appendChild((translate) ? Translator.makePersistentTranslation(messageText, translationArgs, "span") : document.createTextNode(messageText));
|
||
|
||
wrapper.appendChild(_flashMessage);
|
||
document.getElementById("flashMessageContainer").appendChild(wrapper);
|
||
_flashMessage.fadeIn();
|
||
timeToShow = Helper.nonNull(timeToShow, FlashMessenger.defaultTimeToShow);
|
||
if (timeToShow > 0) {
|
||
FlashMessenger.deleteMessage(FlashMessenger.messageCount, timeToShow);
|
||
}
|
||
FlashMessenger.messageCount++;
|
||
}
|
||
}
|
||
|
||
FlashMessenger.messageCount = 0;
|
||
FlashMessenger.defaultTimeToShow = 3500;
|
||
FlashMessenger.LENGTH_SHORT= 1000;
|
||
|
||
FlashMessenger.MESSAGE_TYPE_SUCCESS = 'success';
|
||
FlashMessenger.MESSAGE_TYPE_ERROR = 'error';
|
||
FlashMessenger.MESSAGE_TYPE_DEFAULT = 'default';
|
||
FlashMessenger.MESSAGE_TYPE_INFO = 'info';
|
||
FlashMessenger.MESSAGE_TYPE_WARNING = 'warning';
|
||
|
||
class AbstractService{
|
||
constructor(gapiHandler)
|
||
{
|
||
this.gapiHandler = gapiHandler;
|
||
}
|
||
}
|
||
|
||
class AbstractGapiResponse extends ChainAble{
|
||
constructor(gameService, params)
|
||
{
|
||
super();
|
||
this.gameService = gameService;
|
||
if (Helper.isNotNull(params))
|
||
{
|
||
this.setValues(params);
|
||
}
|
||
}
|
||
setValues(params){}
|
||
load(){}
|
||
}
|
||
|
||
class Achievement extends AbstractGapiResponse {
|
||
setHiddenIconUrl(hiddenIconUrl)
|
||
{
|
||
this.hiddenIconUrl = hiddenIconUrl;
|
||
}
|
||
|
||
setValues(params) {
|
||
let self = this;
|
||
this._chain(params)._chain(function (res) {
|
||
self.achievementType = res["achievementType"];
|
||
self.description = res["description"];
|
||
self.experiencePoints = res["experiencePoints"];
|
||
self.id = res["id"];
|
||
self.initialState = res["initialState"];
|
||
self.isRevealedIconUrlDefault = res["isRevealedIconUrlDefault"];
|
||
self.isUnlockedIconUrlDefault = res["isUnlockedIconUrlDefault"];
|
||
self.name = res["name"];
|
||
self.revealedIconUrl = res["revealedIconUrl"];
|
||
self.unlockedIconUrl = res["unlockedIconUrl"];
|
||
|
||
self.achievementState = res["achievementState"];
|
||
// self.experiencePoints = res["experiencePoints"]; //oben bereits gesetzt
|
||
// self.id = res["id"]; //oben bereits gesetzt
|
||
self.lastUpdatedTimestamp = res["lastUpdatedTimestamp"];
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
show(elem) {
|
||
let self = this;
|
||
this._chain(function () {
|
||
let achievementImg = elem.querySelector(".achievement-img");
|
||
let achievementTitle = elem.querySelector(".achievement-title");
|
||
let achievementDescription = elem.querySelector(".achievement-description");
|
||
let achievementLastTimestamp = elem.querySelector(".achievement-lastTimestamp");
|
||
let achievementXp = elem.querySelector(".achievement-xp");
|
||
|
||
if (self.achievementState === "UNLOCKED") {
|
||
achievementImg.src = self.unlockedIconUrl;
|
||
achievementLastTimestamp.innerText = Helper.strftime("%d %a %Y", parseInt(self.lastUpdatedTimestamp));
|
||
}
|
||
else if (self.achievementState === "REVEALED") {
|
||
achievementImg.src = self.revealedIconUrl;
|
||
}
|
||
else {
|
||
achievementImg.src = self.hiddenIconUrl;
|
||
achievementTitle.appendChild(Translator.makePersistentTranslation("achievement-hidden-title"));
|
||
achievementDescription.appendChild(Translator.makePersistentTranslation("achievement-hidden-description"));
|
||
return;
|
||
}
|
||
|
||
achievementTitle.innerText = self.name;
|
||
achievementDescription.innerText = self.description;
|
||
achievementXp.innerText = self.experiencePoints+" XP";
|
||
});
|
||
return this.promise;
|
||
}
|
||
}
|
||
|
||
class AchievementList extends AbstractGapiResponse {
|
||
constructor(gameService, params) {
|
||
super(gameService, params);
|
||
this.removedAchievementIds = [];
|
||
}
|
||
|
||
setHiddenImgLink(hiddenImgLink) {
|
||
this.hiddenIconUrl = hiddenImgLink;
|
||
}
|
||
|
||
setRemovedAchievementIds(removedAchievementIds) {
|
||
this.removedAchievementIds = removedAchievementIds;
|
||
}
|
||
|
||
load(maxResults, pageToken, language) {
|
||
return this.setValues(Promise.all([this.gameService.getAchievements(maxResults, pageToken, null, language), this.gameService.getPlayerAchievements(null, maxResults, pageToken, null, language)]).then(function (res) {
|
||
if (Helper.isNotNull(res[0]["items"]) && Helper.isNotNull(res[1]["items"])) {
|
||
for (let i = 0, n = Math.min(res[0]["items"].length, res[1]["items"].length); i < n; i++) {
|
||
for (let key in res[1]["items"][i]) {
|
||
res[0]["items"][i][key] = res[1]["items"][i][key];
|
||
}
|
||
}
|
||
}
|
||
return res[0];
|
||
})
|
||
);
|
||
}
|
||
|
||
setValues(params) {
|
||
let self = this;
|
||
this._chain(params)._chain(function (res) {
|
||
let promises = [];
|
||
|
||
self.nextPageToken = res["nextPageToken"];
|
||
|
||
self.items = [];
|
||
if (Helper.isNotNull(res["items"])) {
|
||
for (let i = 0, n = res["items"].length; i < n; i++) {
|
||
if (self.removedAchievementIds.indexOf(res["items"][i]["id"]) === -1) {
|
||
|
||
let achievement = new Achievement(self.gameService, res["items"][i]);
|
||
achievement.setHiddenIconUrl(self.hiddenIconUrl);
|
||
self.items.push(achievement);
|
||
promises.push(achievement.promise);
|
||
}
|
||
}
|
||
}
|
||
return Promise.all(promises);
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
show(elem) {
|
||
let self = this;
|
||
this._chain(function () {
|
||
let nextButton = elem.querySelector("#achievement-list-next-button");
|
||
let achievementTemplate = elem.querySelector("#achievement-list-achievement-template");
|
||
let parentAchievementTemplate = achievementTemplate.parentElement;
|
||
parentAchievementTemplate.removeAllChildren();
|
||
achievementTemplate.id = "";
|
||
|
||
let promises = [];
|
||
for (let i = 0, n = self.items.length; i < n; i++) {
|
||
let achievementElem = Helper.cloneNode(achievementTemplate);
|
||
promises.push(self.items[i].show(achievementElem));
|
||
parentAchievementTemplate.appendChild(achievementElem);
|
||
}
|
||
return Promise.all(promises);
|
||
});
|
||
return this.promise;
|
||
}
|
||
}
|
||
|
||
class GameService extends AbstractService {
|
||
getLeaderboards(maxResults, pageToken, language, consistencyToken) {
|
||
language = Helper.nonNull(language, Translator.currentLanguage);
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["leaderboards"]["list"]({
|
||
"maxResults": maxResults,
|
||
"consistencyToken": consistencyToken,
|
||
"pageToken": pageToken,
|
||
"language": language
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
getScoresAroundPlayer(leaderboardId, collection, timeSpan, maxResults, pageToken, resultsAbove, returnTopIfAbsent, consistencyToken, language) {
|
||
language = Helper.nonNull(language, Translator.currentLanguage);
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["scores"]["listWindow"]({
|
||
"collection": collection,
|
||
"leaderboardId": leaderboardId,
|
||
"timeSpan": timeSpan,
|
||
"consistencyToken": consistencyToken,
|
||
"language": language,
|
||
"maxResults": maxResults,
|
||
"pageToken": pageToken,
|
||
"resultsAbove": resultsAbove,
|
||
"returnTopIfAbsent": returnTopIfAbsent
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
getAchievements(maxResults, pageToken, consistencyToken, language) {
|
||
language = Helper.nonNull(language, Translator.currentLanguage);
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["achievementDefinitions"]["list"]({
|
||
"consistencyToken": consistencyToken,
|
||
"language": language,
|
||
"maxResults": maxResults,
|
||
"pageToken": pageToken,
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
getPlayerAchievements(playerId, maxResults, pageToken, consistencyToken, language) {
|
||
playerId = Helper.nonNull(playerId, "me");
|
||
language = Helper.nonNull(language, Translator.currentLanguage);
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["achievements"]["list"]({
|
||
"playerId": playerId,
|
||
"consistencyToken": consistencyToken,
|
||
"language": language,
|
||
"maxResults": maxResults,
|
||
"pageToken": pageToken,
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
submitScore(leaderboardId, score) {
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["scores"]["submit"]({
|
||
"leaderboardId": leaderboardId,
|
||
"score": score
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
revealAchievement(achievementId) {
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["achievements"]["reveal"]({
|
||
"achievementId": achievementId
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
unlockAchievement(achievementId, showIsNewAchievement) {
|
||
return this.gapiHandler.promise.then(function () {
|
||
return new Promise(function (resolve) {
|
||
gapi["client"]["games"]["achievements"]["unlock"]({
|
||
"achievementId": achievementId
|
||
})["execute"](function (response) {
|
||
resolve(response);
|
||
});
|
||
});
|
||
}).then(function(response){
|
||
if (showIsNewAchievement && response["newlyUnlocked"])
|
||
{
|
||
FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("new-unlocked-achievement"));
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
GameService.COLLECTION_PUBLIC = "PUBLIC";
|
||
GameService.COLLECTION_SOCIAL = "SOCIAL";
|
||
GameService.COLLECTION_SOCIAL_1P = "SOCIAL_1P";
|
||
|
||
GameService.TIME_SPAN_ALL_TIME = "ALL_TIME";
|
||
GameService.TIME_SPAN_DAILY = "DAILY";
|
||
GameService.TIME_SPAN_WEEKLY = "WEEKLY";
|
||
|
||
class GapiPlayer extends AbstractGapiResponse{
|
||
setValues(params)
|
||
{
|
||
let self = this;
|
||
this._chain(params)._chain(function(res){
|
||
self.playerId = res["playerId"];
|
||
self.displayName = res["displayName"];
|
||
self.avatarImageUrl = res["avatarImageUrl"];
|
||
self.experienceInfo = res["experienceInfo"];
|
||
// self.bannerUrlPortrait = res["scoreValue"];
|
||
// self.formattedScore = res["formattedScore"];
|
||
// self.timeSpan = res["timeSpan"];
|
||
// self.writeTimestampMillis = res["writeTimestampMillis"];
|
||
// self.scoreTag = res["scoreTag"];
|
||
});
|
||
return this.promise;
|
||
}
|
||
}
|
||
|
||
class Score extends AbstractGapiResponse
|
||
{
|
||
setValues(params)
|
||
{
|
||
let self = this;
|
||
this._chain(params)._chain(function(res){
|
||
self.player = new GapiPlayer(self.gameService, res["player"]);
|
||
self.scoreRank = res["scoreRank"];
|
||
self.formattedScoreRank = res["formattedScoreRank"];
|
||
self.scoreValue = res["scoreValue"];
|
||
self.formattedScore = res["formattedScore"];
|
||
self.timeSpan = res["timeSpan"];
|
||
self.writeTimestampMillis = res["writeTimestampMillis"];
|
||
self.scoreTag = res["scoreTag"];
|
||
|
||
return self.player.promise;
|
||
});
|
||
return this.promise;
|
||
}
|
||
}
|
||
|
||
class Leaderboard extends AbstractGapiResponse {
|
||
setValues(params) {
|
||
let self = this;
|
||
this.promise = this.promise.then(function () {
|
||
return Promise.resolve(params);
|
||
}).then(function (res) {
|
||
let promises = [];
|
||
|
||
self.nextPageToken = res["nextPageToken"];
|
||
self.previousPageToken = res["prevPageToken"];
|
||
self.numScores = res["numScores"];
|
||
self.playerScore = new Score(self.gameService, res["playerScore"]);
|
||
|
||
promises.push(self.playerScore.promise);
|
||
|
||
self.items = [];
|
||
if (Helper.isNotNull(res["items"])) {
|
||
for (let i = 0, n = res["items"].length; i < n; i++) {
|
||
self.items.push(new Score(self.gameService, res["items"][i]));
|
||
promises.push(self.items[i].promise);
|
||
}
|
||
}
|
||
|
||
return Promise.all(promises);
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
setLeaderboardId(leaderboardId) {
|
||
this.leaderboardId = leaderboardId;
|
||
}
|
||
|
||
load(maxResults, pageToken, resultsAbove) {
|
||
return this.setValues(this.gameService.getScoresAroundPlayer(this.leaderboardId, this.collection, this.timeSpan, maxResults, pageToken, resultsAbove));
|
||
}
|
||
|
||
setCollection(collection) {
|
||
this.collection = collection;
|
||
}
|
||
|
||
setTimeSpan(timeSpan) {
|
||
this.timeSpan = timeSpan;
|
||
}
|
||
|
||
setDisplayName(name)
|
||
{
|
||
this.displayName = name;
|
||
}
|
||
|
||
show(elem, buildTimeSelect, buildCollectionSelect, isTime) {
|
||
buildCollectionSelect = Helper.nonNull(buildCollectionSelect, true);
|
||
buildTimeSelect = Helper.nonNull(buildTimeSelect, true);
|
||
isTime = Helper.nonNull(isTime, false);
|
||
let args = arguments;
|
||
|
||
let self = this;
|
||
this._chain(function () {
|
||
let prevButton = elem.querySelector("#leaderboard-previous-button");
|
||
let nextButton = elem.querySelector("#leaderboard-next-button");
|
||
let scoreTemplate = elem.querySelector("#leaderboard-score-template");
|
||
let parentScoreElem = scoreTemplate.parentElement;
|
||
parentScoreElem.removeAllChildren();
|
||
|
||
let timeElem = self._buildTime(buildTimeSelect);
|
||
elem.querySelector("#leaderboard-time-span").removeAllChildren().appendChild(timeElem);
|
||
|
||
let collectionElem = self._buildCollection(buildCollectionSelect);
|
||
elem.querySelector("#leaderboard-collection").removeAllChildren().appendChild(collectionElem);
|
||
|
||
timeElem.onchange = function () {
|
||
self._updateWithDataFromElem(elem, parentScoreElem, scoreTemplate, args);
|
||
};
|
||
|
||
collectionElem.onchange = function () {
|
||
self._updateWithDataFromElem(elem, parentScoreElem, scoreTemplate, args);
|
||
};
|
||
|
||
for (let i = 0, n = self.items.length; i < n; i++) {
|
||
let score = self.items[i];
|
||
let scoreElem = Helper.cloneNode(scoreTemplate);
|
||
scoreElem.querySelector(".leaderboard-rank").innerText = score.scoreRank;
|
||
scoreElem.querySelector(".leaderboard-player-img").src = score.player.avatarImageUrl;
|
||
scoreElem.querySelector(".leaderboard-player-name").innerText = score.player.displayName;
|
||
scoreElem.querySelector(".leaderboard-points").innerText = (isTime)?Helper.strftime("%H:%M:%S", new Date(parseInt(score.scoreValue)), true):score.formattedScore;
|
||
scoreElem.id = "";
|
||
|
||
if (Helper.isNotNull(self.playerScore) && Helper.isNotNull(self.playerScore.player) && score.player.playerId === self.playerScore.player.playerId) {
|
||
scoreElem.classList.add("leaderboard-current-player");
|
||
}
|
||
parentScoreElem.appendChild(scoreElem);
|
||
}
|
||
if (self.items.length === 0)
|
||
{
|
||
parentScoreElem.appendChild(Translator.makePersistentTranslation("no-scores-available"));
|
||
}
|
||
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
_buildCollection(buildCollectionSelect) {
|
||
if (buildCollectionSelect) {
|
||
let select = document.createElement("select");
|
||
let publicOption = document.createElement("option");
|
||
publicOption.value = GameService.COLLECTION_PUBLIC;
|
||
publicOption.innerHTML = Translator.translate(GameService.COLLECTION_PUBLIC);
|
||
publicOption.dataset["translate"] = GameService.COLLECTION_PUBLIC;
|
||
|
||
if (GameService.COLLECTION_PUBLIC === this.collection) {
|
||
publicOption.selected = true;
|
||
}
|
||
|
||
let socialOption = document.createElement("option");
|
||
socialOption.value = GameService.COLLECTION_SOCIAL;
|
||
socialOption.innerHTML = Translator.translate(GameService.COLLECTION_SOCIAL);
|
||
socialOption.dataset["translate"] = GameService.COLLECTION_SOCIAL;
|
||
|
||
if (GameService.COLLECTION_SOCIAL === this.collection) {
|
||
socialOption.selected = true;
|
||
}
|
||
|
||
select.appendChild(socialOption);
|
||
select.appendChild(publicOption);
|
||
return select;
|
||
}
|
||
else {
|
||
return Translator.makePersistentTranslation(this.collection);
|
||
}
|
||
}
|
||
|
||
_updateWithDataFromElem(rootElem, scoreTable, scoreTemplate, args) {
|
||
let loadingSymbol = Helper.createLoadingSymbol();
|
||
rootElem.replaceWith(loadingSymbol);
|
||
scoreTable.removeAllChildren().appendChild(scoreTemplate);
|
||
|
||
let collectionElem = rootElem.querySelector("#leaderboard-collection select");
|
||
if (Helper.isNotNull(collectionElem)) {
|
||
this.collection = collectionElem.options[collectionElem.selectedIndex].value;
|
||
}
|
||
|
||
let timeSpanElem = rootElem.querySelector("#leaderboard-time-span select");
|
||
if (Helper.isNotNull(timeSpanElem)) {
|
||
this.timeSpan = timeSpanElem.options[timeSpanElem.selectedIndex].value;
|
||
}
|
||
|
||
this.load();
|
||
this.show.apply(this, args).then(function () {
|
||
loadingSymbol.replaceWith(rootElem);
|
||
});
|
||
}
|
||
|
||
_buildTime(buildTimeSelect) {
|
||
if (buildTimeSelect) {
|
||
let select = document.createElement("select");
|
||
let allTime = document.createElement("option");
|
||
allTime.value = GameService.TIME_SPAN_ALL_TIME;
|
||
allTime.innerHTML = Translator.translate(GameService.TIME_SPAN_ALL_TIME);
|
||
allTime.dataset["translate"] = GameService.TIME_SPAN_ALL_TIME;
|
||
|
||
if (GameService.TIME_SPAN_ALL_TIME === this.timeSpan) {
|
||
allTime.selected = true;
|
||
}
|
||
|
||
let weeklyOption = document.createElement("option");
|
||
weeklyOption.value = GameService.TIME_SPAN_WEEKLY;
|
||
weeklyOption.innerHTML = Translator.translate(GameService.TIME_SPAN_WEEKLY);
|
||
weeklyOption.dataset["translate"] = GameService.TIME_SPAN_WEEKLY;
|
||
|
||
if (GameService.TIME_SPAN_WEEKLY === this.timeSpan) {
|
||
weeklyOption.selected = true;
|
||
}
|
||
|
||
let dailyOption = document.createElement("option");
|
||
dailyOption.value = GameService.TIME_SPAN_DAILY;
|
||
dailyOption.innerHTML = Translator.translate(GameService.TIME_SPAN_DAILY);
|
||
dailyOption.dataset["translate"] = GameService.TIME_SPAN_DAILY;
|
||
|
||
if (GameService.TIME_SPAN_DAILY === this.timeSpan) {
|
||
dailyOption.selected = true;
|
||
}
|
||
|
||
select.appendChild(dailyOption);
|
||
select.appendChild(weeklyOption);
|
||
select.appendChild(allTime);
|
||
return select;
|
||
}
|
||
else {
|
||
return Translator.makePersistentTranslation(this.timeSpan);
|
||
}
|
||
}
|
||
}
|
||
|
||
class GapiHandler {
|
||
constructor() {
|
||
this.loginCallbacks = [];
|
||
this.games = new GameService(this);
|
||
}
|
||
|
||
init() {
|
||
this.promise = new Promise(function (resolver) {
|
||
let scriptElem = document.createElement("script");
|
||
scriptElem.src = "https://apis.google.com/js/api.js";
|
||
scriptElem.async = true;
|
||
scriptElem.defer = true;
|
||
scriptElem.onload = resolver;
|
||
scriptElem.onreadystatechange = function () {
|
||
if (this.readyState === "complete") {
|
||
resolver();
|
||
}
|
||
};
|
||
document.body.appendChild(scriptElem);
|
||
}).then(function () {
|
||
window["gapi"] = gapi;
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
load(libs) {
|
||
this.promise = this.promise.then(function () {
|
||
return new Promise(function (resolver) {
|
||
gapi["load"](libs, resolver);
|
||
});
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
initClient(apiKey, clientId, scope, discoveryDocs, fetchBasicProfile, uxMode) {
|
||
scope = Helper.nonNull(scope, "profile");
|
||
fetchBasicProfile = Helper.nonNull(fetchBasicProfile, false);
|
||
discoveryDocs = Helper.nonNull(discoveryDocs, []);
|
||
uxMode = Helper.nonNull(uxMode,"popup");
|
||
let self = this;
|
||
this.promise = this.promise.then(function () {
|
||
return gapi["client"]["init"]({
|
||
"apiKey": apiKey,
|
||
"discoveryDocs": discoveryDocs,
|
||
"clientId": clientId,
|
||
"scope": scope,
|
||
"fetch_basic_profile":fetchBasicProfile,
|
||
"ux_mode":uxMode
|
||
});
|
||
}).then(function () {
|
||
let authInstance = gapi["auth2"]["getAuthInstance"]();
|
||
authInstance["isSignedIn"]["listen"](function (isLoggedIn) {
|
||
for (let i = 0, n = self.loginCallbacks.length; i < n; i++) {
|
||
self.loginCallbacks[i](isLoggedIn);
|
||
}
|
||
});
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
loadClient(lib, version)
|
||
{
|
||
this.promise = this.promise.then(function () {
|
||
return new Promise(function (resolver) {
|
||
gapi["client"]["load"](lib, version, resolver);
|
||
});
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
addLoginCallback(callback) {
|
||
this.loginCallbacks.push(callback);
|
||
let authInstance = gapi["auth2"]["getAuthInstance"]();
|
||
callback(authInstance["isSignedIn"]["get"]());
|
||
}
|
||
|
||
addLoginAction(app, callback) {
|
||
let self = this;
|
||
callback = Helper.nonNull(callback, function(){
|
||
self.login();
|
||
});
|
||
this.loginAction = new MenuAction("login", callback, MenuAction.SHOW_NEVER, 10001);
|
||
app.addDefaultAction(this.loginAction);
|
||
ActionBarMenu.currentMenu.addAction(this.loginAction.copy());
|
||
}
|
||
|
||
removeLoginAction(app) {
|
||
app.removeDefaultAction(this.loginAction);
|
||
}
|
||
|
||
login() {
|
||
this.promise = this.promise.then(function () {
|
||
let authInstance = gapi["auth2"]["getAuthInstance"]();
|
||
return authInstance["signIn"]();
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
logout() {
|
||
this.promise = this.promise.then(function () {
|
||
let authInstance = gapi["auth2"]["getAuthInstance"]();
|
||
return authInstance["signOut"]();
|
||
});
|
||
return this.promise;
|
||
}
|
||
|
||
isLoggedIn() {
|
||
return this.promise.then(function () {
|
||
let authInstance = gapi["auth2"]["getAuthInstance"]();
|
||
return authInstance["isSignedIn"]["get"]();
|
||
})
|
||
}
|
||
}
|
||
|
||
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 MyDb {
|
||
constructor(dbName, version) {
|
||
let indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
|
||
this._conn = indexedDB.open(dbName, version);
|
||
|
||
let myDB = this;
|
||
this._conn.onupgradeneeded = function (upgradeEvent) {
|
||
myDB.upgrade(myDB._conn.result, upgradeEvent.oldVersion, upgradeEvent.newVersion, upgradeEvent);
|
||
};
|
||
this.queryPromise = new Promise(function (resolve) {
|
||
myDB._conn.onsuccess = function (e) {
|
||
myDB._db = myDB._conn.result;
|
||
resolve(e);
|
||
};
|
||
});
|
||
}
|
||
|
||
openTransaction(name, transactionMode, callback) {
|
||
let myDb = this;
|
||
if (typeof transactionMode === 'function' && Helper.isNull(callback)) {
|
||
callback = transactionMode;
|
||
transactionMode = "read";
|
||
}
|
||
|
||
this.queryPromise.then(function () {
|
||
let res = null;
|
||
try {
|
||
res = myDb._conn.result.transaction(name, transactionMode);
|
||
}
|
||
catch (e) {
|
||
console.warn(e);
|
||
res = myDb._conn.result.transaction(name);
|
||
}
|
||
callback(res);
|
||
});
|
||
}
|
||
|
||
openStore(name, transactionMode, callback) {
|
||
if (typeof transactionMode === 'function' && Helper.isNull(callback)) {
|
||
callback = transactionMode;
|
||
transactionMode = "readonly";
|
||
}
|
||
this.openTransaction(name, transactionMode, function (t) {
|
||
callback(t.objectStore(name));
|
||
});
|
||
}
|
||
|
||
saveObj(obj, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, "readwrite", function (store) {
|
||
let request = store.put(obj);
|
||
request.onsuccess = resolve;
|
||
request.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-error",
|
||
"event": e
|
||
}
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
saveMany(manyObj, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, "readwrite", function (store) {
|
||
let promises = [];
|
||
for (let i = 0, n = manyObj.length; i < n; i++) {
|
||
promises.push(new Promise(function (resolveInner) {
|
||
let request = store.put(manyObj[i]);
|
||
request.onsuccess = resolveInner;
|
||
request.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-error",
|
||
"event": e
|
||
}
|
||
};
|
||
}));
|
||
}
|
||
resolve(Promise.all(promises));
|
||
});
|
||
});
|
||
}
|
||
|
||
load(key, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, function (store) {
|
||
let request = store.get(key);
|
||
request.onsuccess = function (e) {
|
||
resolve(e.currentTarget.result);
|
||
};
|
||
request.onerror = function (e) {
|
||
console.warn(e);
|
||
throw {
|
||
"type": "indexed-db-load-error",
|
||
"event": e
|
||
}
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
loadAll(objectStore, query, count)
|
||
{
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, function (store) {
|
||
let request = store.getAll(query, count);
|
||
request.onsuccess = function (e) {
|
||
resolve(e.currentTarget.result);
|
||
};
|
||
request.onerror = function (e) {
|
||
console.warn(e);
|
||
throw {
|
||
"type": "indexed-db-load-error",
|
||
"event": e
|
||
}
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
loadMany(index, value, objectStore, limit, direction) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, function (store) {
|
||
let indexRequest = store.index(index);
|
||
indexRequest.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-index-error",
|
||
"event": e
|
||
}
|
||
};
|
||
let request = indexRequest.openCursor(value, direction);
|
||
request.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-index-error",
|
||
"event": e
|
||
}
|
||
};
|
||
let objects = [];
|
||
let numberResults = 0;
|
||
request.onsuccess = function (e) {
|
||
let cursor = e.target.result;
|
||
if (cursor) {
|
||
objects.push(cursor.value);
|
||
numberResults++;
|
||
if (Helper.isNull(limit) || numberResults < limit) {
|
||
cursor.continue();
|
||
return;
|
||
}
|
||
}
|
||
resolve(objects);
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
remove(id, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, "readwrite", function (store) {
|
||
let deleteRequest = store.delete(id);
|
||
deleteRequest.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-delete-error",
|
||
"event": e
|
||
}
|
||
};
|
||
deleteRequest.onsuccess = function (e) {
|
||
resolve();
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
removeMany(ids, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, "readwrite", function (store) {
|
||
let promises = [];
|
||
for (let i = 0, n = ids.length; i < n; i++) {
|
||
let deleteRequest = store.delete(ids[i]);
|
||
deleteRequest.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-delete-error",
|
||
"event": e
|
||
}
|
||
};
|
||
promises.push(new Promise(function (resolve) {
|
||
deleteRequest.onsuccess = function () {
|
||
resolve();
|
||
};
|
||
}));
|
||
}
|
||
resolve(Promise.all(promises));
|
||
});
|
||
});
|
||
}
|
||
|
||
removeWithIndex(index, value, objectStore) {
|
||
let self = this;
|
||
return new Promise(function (resolve) {
|
||
self.openStore(objectStore, "readwrite", function (store) {
|
||
let indexRequest = store.index(index);
|
||
indexRequest.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-index-error",
|
||
"event": e
|
||
}
|
||
};
|
||
let request = indexRequest.openCursor(value);
|
||
request.onerror = function (e) {
|
||
throw {
|
||
"type": "indexed-db-index-error",
|
||
"event": e
|
||
}
|
||
};
|
||
request.onsuccess = function (e) {
|
||
let cursor = e.target.result;
|
||
if (cursor) {
|
||
cursor.delete();
|
||
cursor.continue();
|
||
}
|
||
else {
|
||
resolve();
|
||
}
|
||
};
|
||
});
|
||
});
|
||
}
|
||
|
||
upgrade(db) {
|
||
};
|
||
}
|
||
|
||
class Prioritised {
|
||
constructor(resultPromises, callback) {
|
||
this.result = null;
|
||
this.prioResult = -1;
|
||
this.callback = null;
|
||
this.hasResult = false;
|
||
this.highestPrio = -1;
|
||
|
||
let self = this;
|
||
this.callbackCalledPromise = new Promise(function (resolver) {
|
||
self.callbackCalledPromiseResolver = resolver;
|
||
});
|
||
|
||
this.endPromise = new Promise(function (resolver) {
|
||
self.endPromiseResolver = resolver;
|
||
});
|
||
|
||
this.setCallback(callback);
|
||
|
||
for (let k in resultPromises) {
|
||
this.registerResultPromise(k, resultPromises[k]);
|
||
}
|
||
}
|
||
|
||
async registerResultPromise(prio, promise) {
|
||
this.highestPrio = Math.max(prio, this.highestPrio);
|
||
let res = await Promise.resolve(promise);
|
||
this._setResult(prio, res);
|
||
}
|
||
|
||
_setResult(prio, result) {
|
||
if (this.prioResult <= prio || !this.hasResult) {
|
||
this.hasResult = true;
|
||
|
||
this.prioResult = prio;
|
||
this.result = result;
|
||
if (Helper.isNotNull(this.callback)) {
|
||
this.callback(result, prio, this);
|
||
this.callbackCalledPromiseResolver();
|
||
}
|
||
|
||
|
||
if (prio == this.highestPrio) {
|
||
console.log("endPromise resolved!");
|
||
this.endPromiseResolver();
|
||
}
|
||
}
|
||
}
|
||
|
||
setCallback(callback) {
|
||
this.callback = callback;
|
||
if (this.hasResult && Helper.isNotNull(callback)) {
|
||
callback(this.result, this.prioResult, this);
|
||
this.callbackCalledPromiseResolver();
|
||
}
|
||
}
|
||
|
||
getCallbackCalledPromise() {
|
||
return this.callbackCalledPromise;
|
||
}
|
||
|
||
getEndPromise() {
|
||
return this.endPromise;
|
||
}
|
||
}
|
||
|
||
class ScriptLoader {
|
||
static loadScript(scriptSrc) {
|
||
if (Helper.isNotNull(ScriptLoader.scriptPromises[scriptSrc])) {
|
||
return ScriptLoader.scriptPromises[scriptSrc];
|
||
}
|
||
else {
|
||
let scriptPromise = new Promise(function (resolve) {
|
||
let script = document.createElement("script");
|
||
script.src = Helper.basePath(scriptSrc);
|
||
script.onload = resolve;
|
||
|
||
document.body.appendChild(script);
|
||
});
|
||
ScriptLoader.scriptPromises[scriptSrc] = scriptPromise;
|
||
return scriptPromise;
|
||
}
|
||
}
|
||
static loadCss(cssFile, media){
|
||
if (Helper.isNotNull(ScriptLoader.cssPromises[cssFile])) {
|
||
return ScriptLoader.cssPromises[cssFile];
|
||
}
|
||
else {
|
||
media = Helper.nonNull(media, "all");
|
||
let cssPromise = new Promise(function (resolve) {
|
||
let link = document.createElement("link");
|
||
link.rel='stylesheet';
|
||
link.type="text/css";
|
||
link.href = Helper.basePath(cssFile);
|
||
link.media = media;
|
||
link.onload = resolve;
|
||
|
||
document.head.appendChild(link);
|
||
});
|
||
ScriptLoader.cssPromises[cssFile] = cssPromise;
|
||
return cssPromise;
|
||
}
|
||
}
|
||
}
|
||
|
||
ScriptLoader.scriptPromises = {};
|
||
ScriptLoader.cssPromises = {};
|
||
|
||
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 CopyShareButton extends ShareButton
|
||
{
|
||
constructor(icon) {
|
||
super(ShareButton.TYPE_ALL, icon, function (link) {
|
||
try{
|
||
let elementToCopy = document.createElement("div");
|
||
elementToCopy.style.position = "fixed";
|
||
elementToCopy.style.top = 0;
|
||
elementToCopy.style.left = 0;
|
||
elementToCopy.style.width = "0em";
|
||
elementToCopy.style.height = "0em";
|
||
elementToCopy.style.padding = 0;
|
||
elementToCopy.style.border = "none";
|
||
elementToCopy.style.outline = "none";
|
||
elementToCopy.style.boxShadow = "none";
|
||
elementToCopy.style.backgroundElement = "transparent";
|
||
elementToCopy.style.color = "transparent";
|
||
elementToCopy.innerText = link;
|
||
document.body.appendChild(elementToCopy);
|
||
Helper.select(elementToCopy);
|
||
if (document.execCommand("copy")) {
|
||
FlashMessenger.addMessage(FlashMessenger.MESSAGE_TYPE_SUCCESS, Translator.translate("copied"), 1800);
|
||
}
|
||
elementToCopy.remove();
|
||
} catch(e) {
|
||
console.error(e);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
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 SimpleWS{
|
||
static _initMe(ws, url, protocols) {
|
||
ws._connectionPromise = new Promise(function (resolve) {
|
||
ws._ws = new WebSocket(url, protocols);
|
||
ws._ws.onopen = function () {
|
||
resolve();
|
||
for (let i = 0, n = ws._openListeners.length; i < n; i++) {
|
||
if (Helper.isNotNull(ws._openListeners[i])) {
|
||
ws._openListeners[i]();
|
||
}
|
||
}
|
||
};
|
||
|
||
ws._ws.onerror = function (err) {
|
||
resolve(Promise.reject("WS-Error"));
|
||
console.error(err);
|
||
for (let i = 0, n = ws._errorListeners.length; i < n; i++) {
|
||
if (Helper.isNotNull(ws._errorListeners[i])) {
|
||
ws._errorListeners[i](err);
|
||
}
|
||
}
|
||
};
|
||
|
||
ws._ws.onclose = function (e) {
|
||
console.log("ws-close");
|
||
for (let i = 0, n = ws._closeListeners.length; i < n; i++) {
|
||
if (Helper.isNotNull(ws._closeListeners[i])) {
|
||
ws._closeListeners[i](e, ws._shouldReconnectAfterClose);
|
||
}
|
||
}
|
||
if (ws._shouldReconnectAfterClose) {
|
||
setTimeout(function () {
|
||
SimpleWS._initMe(ws, url, protocols);
|
||
}, 200);
|
||
}
|
||
};
|
||
|
||
ws._ws.onmessage = function (message) {
|
||
if (message.data === "pong") {
|
||
ws.ping();
|
||
return;
|
||
}
|
||
|
||
let jsonMessage = JSON.parse(message.data);
|
||
for (let i = 0, n = ws._messageListeners.length; i < n; i++) {
|
||
if (ws._messageListeners[i]) {
|
||
ws._messageListeners[i](jsonMessage, message);
|
||
}
|
||
}
|
||
};
|
||
});
|
||
}
|
||
|
||
constructor(url, protocols, shouldReconnectAfterClose) {
|
||
this._shouldReconnectAfterClose = Helper.nonNull(shouldReconnectAfterClose, true);
|
||
this._ws = null;
|
||
|
||
this._openListeners = [];
|
||
this._errorListeners = [];
|
||
this._messageListeners = [];
|
||
this._closeListeners = [];
|
||
|
||
this._connectionPromise = Promise.resolve();
|
||
this._pong = null;
|
||
this._ping = null;
|
||
|
||
SimpleWS._initMe(this, url, protocols);
|
||
this.activatePingPong();
|
||
}
|
||
|
||
ping(interval, answerTime) {
|
||
interval = Helper.nonNull(interval, 5000);
|
||
answerTime = Helper.nonNull(answerTime, 5000);
|
||
if (this._pong !== null) {
|
||
clearTimeout(this._pong);
|
||
}
|
||
if (this._ping !== null) {
|
||
clearTimeout(this._ping);
|
||
}
|
||
|
||
let self = this;
|
||
this._ping = setTimeout(function () {
|
||
self.send({'action':"ping"});
|
||
self._pong = setTimeout(function () {
|
||
self._ws.close();
|
||
}, answerTime);
|
||
}, interval);
|
||
}
|
||
|
||
activatePingPong() {
|
||
this.ping();
|
||
}
|
||
|
||
send(jsonMessage) {
|
||
let ws = this;
|
||
return this._connectionPromise.then(function () {
|
||
ws._ws.send(JSON.stringify(jsonMessage));
|
||
});
|
||
}
|
||
|
||
connectedPromise()
|
||
{
|
||
let self = this;
|
||
return new Promise(function(resolve){
|
||
self.addOpenListener(function(){
|
||
resolve();
|
||
}, true);
|
||
})
|
||
}
|
||
|
||
promiseSend(jsonMessage)
|
||
{
|
||
let self = this;
|
||
return this.connectedPromise().then(function(){
|
||
return self.send(jsonMessage);
|
||
});
|
||
}
|
||
|
||
close() {
|
||
this._shouldReconnectAfterClose = false;
|
||
this._ws.close();
|
||
}
|
||
|
||
addErrorListener(listener) {
|
||
if (typeof listener === 'function') {
|
||
return this._errorListeners.push(listener) - 1;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
removeErrorListener(listenerId) {
|
||
if (listenerId < this._errorListeners.length && listenerId >= 0) {
|
||
this._errorListeners[listenerId] = null;
|
||
}
|
||
}
|
||
|
||
addCloseListener(listener, callNowIfClosed) {
|
||
callNowIfClosed = Helper.nonNull(callNowIfClosed, false);
|
||
if (typeof listener === 'function') {
|
||
if (callNowIfClosed && this.status() !== WebSocket.OPEN) {
|
||
listener();
|
||
}
|
||
return this._closeListeners.push(listener) - 1;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
removeCloseListener(listenerId) {
|
||
if (listenerId < this._closeListeners.length && listenerId >= 0) {
|
||
this._closeListeners[listenerId] = null;
|
||
}
|
||
}
|
||
|
||
addOpenListener(listener, callNowIfOpen) {
|
||
callNowIfOpen = Helper.nonNull(callNowIfOpen, false);
|
||
if (typeof listener === 'function') {
|
||
if (callNowIfOpen && this.status() === WebSocket.OPEN) {
|
||
listener();
|
||
}
|
||
return this._openListeners.push(listener) - 1;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
removeOpenListener(listenerId) {
|
||
if (listenerId < this._openListeners.length && listenerId >= 0) {
|
||
this._openListeners[listenerId] = null;
|
||
}
|
||
}
|
||
|
||
addMessageListener(listener) {
|
||
if (typeof listener === 'function') {
|
||
return this._messageListeners.push(listener) - 1;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
removeMessageListener(listenerId) {
|
||
if (listenerId < this._messageListeners.length && listenerId >= 0) {
|
||
this._messageListeners[listenerId] = null;
|
||
}
|
||
}
|
||
|
||
status() {
|
||
return this._ws.readyState;
|
||
}
|
||
}
|
||
|
||
class Fragment extends Context
|
||
{
|
||
constructor(site, view)
|
||
{
|
||
super(view);
|
||
this.site = site;
|
||
this.active = true;
|
||
}
|
||
|
||
getSite()
|
||
{
|
||
return this.site;
|
||
}
|
||
|
||
isActive()
|
||
{
|
||
return this.active;
|
||
}
|
||
}
|
||
|
||
class Theme
|
||
{
|
||
constructor(name, className, icon)
|
||
{
|
||
this._name = name;
|
||
this._className = className;
|
||
this._icon = icon;
|
||
}
|
||
}
|
||
|
||
class DBTranslator extends Translator {
|
||
_loadLanguage(language) {
|
||
let self = this;
|
||
return this._db.loadTranslationsForLang(language).then(function (res) {
|
||
self._translations[language] = Object.assign(res, self._translations[language]);
|
||
}).catch(function (err) {
|
||
console.error("could not load lang " + language + " because of error: ", err);
|
||
});
|
||
}
|
||
|
||
loadUserLanguage() {
|
||
this._currentLanguage = null;
|
||
let self = this;
|
||
return this._db.getLanguage().then(function (userLanguage) {
|
||
if (Helper.isNull(userLanguage) || self._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(self._baseLanguage);
|
||
|
||
if (userLanguages !== undefined) {
|
||
for (let i = 0, numLanguages = userLanguages.length; i < numLanguages; i++) {
|
||
if (self._supportedLanguages.indexOf(userLanguages[i]) !== -1) {
|
||
userLanguage = userLanguages[i];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return self.setLanguage(userLanguage.toLowerCase())
|
||
});
|
||
}
|
||
}
|
||
|
||
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;
|
||
});
|
||
|
||
|
||
window["fetch"] = Helper.nonNull(window["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;
|
||
});
|
||
}
|
||
|
||
export { App, ChainAble, CookieCompliance, ConfirmDialog, Dialog, FlashMessenger, AbstractService, AbstractGapiResponse, Achievement, AchievementList, GameService, GapiPlayer, Leaderboard, Score, GapiHandler, Helper, InitPromise, ActionBarMenu, Menu, MenuAction, OpenSubmenuAction, Submenu, MyDb, Prioritised, ScriptLoader, CopyShareButton, ShareButton, ShareManager, SmsShareButton, TelegramShareButton, WhatsappShareButton, SimpleWS, AbstractSite, Context, Fragment, PauseSite, SiteContainer, SiteManager, SystemSettings, Theme, ThemeManager, DBTranslator, Translator, TranslatorDB, ViewInflater, applyPolyfills };
|