'use strict'; /* global dijit, App, dojo, __csrf_token */ /* eslint-disable no-new */ /* exported __ */ function __(msg) { if (typeof App != "undefined") { return App.l10n.__(msg); } else { return msg; } } /* exported ngettext */ function ngettext(msg1, msg2, n) { return __((parseInt(n) > 1) ? msg2 : msg1); } /* exported $ */ function $(id) { console.warn("FIXME: please use App.byId() or document.getElementById() instead of $():", id); return document.getElementById(id); } /* exported $$ */ function $$(query) { console.warn("FIXME: please use App.findAll() or document.querySelectorAll() instead of $$():", query); return document.querySelectorAll(query); } // polyfill for safari https://raw.githubusercontent.com/pladaria/requestidlecallback-polyfill/master/index.js window.requestIdleCallback = window.requestIdleCallback || function (callback) { const start = Date.now(); return setTimeout(() => { callback({ didTimeout: false, timeRemaining: () => Math.max(0, 50 - (Date.now() - start)) }, ); }, 1); }; window.cancelIdleCallback = window.cancelIdleCallback || function (id) { clearTimeout(id); }; Element.prototype.hasClassName = function(className) { return this.classList.contains(className); }; Element.prototype.addClassName = function(className) { return this.classList.add(className); }; Element.prototype.removeClassName = function(className) { return this.classList.remove(className); }; Element.prototype.toggleClassName = function(className) { if (this.hasClassName(className)) return this.removeClassName(className); else return this.addClassName(className); }; Element.prototype.setStyle = function(args) { Object.keys(args).forEach((k) => { this.style[k] = args[k]; }); }; Element.prototype.show = function() { this.style.display = ""; }; Element.prototype.hide = function() { this.style.display = "none"; }; Element.prototype.toggle = function() { if (this.visible()) this.hide(); else this.show(); }; // https://gist.github.com/alirezas/c4f9f43e9fe1abba9a4824dd6fc60a55 Element.prototype.fadeOut = function() { this.style.opacity = 1; const self = this; (function fade() { if ((self.style.opacity -= 0.1) < 0) { self.style.display = "none"; } else { requestAnimationFrame(fade); } }()); }; Element.prototype.fadeIn = function(display = undefined){ this.style.opacity = 0; this.style.display = display == undefined ? "block" : display; const self = this; (function fade() { let val = parseFloat(self.style.opacity); if (!((val += 0.1) > 1)) { self.style.opacity = val; requestAnimationFrame(fade); } }()); }; Element.prototype.visible = function() { return window.getComputedStyle(this).display != "none"; //&& this.offsetHeight != 0 && this.offsetWidth != 0; } Element.visible = function(elem) { if (typeof elem == "string") elem = document.getElementById(elem); return elem.visible(); } Element.show = function(elem) { if (typeof elem == "string") elem = document.getElementById(elem); return elem.show(); } Element.hide = function(elem) { if (typeof elem == "string") elem = document.getElementById(elem); return elem.hide(); } Element.toggle = function(elem) { if (typeof elem == "string") elem = document.getElementById(elem); return elem.toggle(); } Element.hasClassName = function (elem, className) { if (typeof elem == "string") elem = document.getElementById(elem); return elem.hasClassName(className); } Array.prototype.remove = function(s) { for (let i=0; i < this.length; i++) { if (s == this[i]) this.splice(i, 1); } }; Array.prototype.uniq = function() { return this.filter((v, i, a) => a.indexOf(v) === i); }; String.prototype.stripTags = function() { return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, ''); } /* exported xhr */ const xhr = { _ts: 0, post: function(url, params = {}, complete = undefined, failed = undefined) { this._ts = new Date().getTime(); console.log('xhr.post', '>>>', params); return new Promise((resolve, reject) => { if (typeof __csrf_token != "undefined") params = {...params, ...{csrf_token: __csrf_token}}; dojo.xhrPost({url: url, postData: dojo.objectToQuery(params), handleAs: "text", error: function(error) { if (failed != undefined) failed(error); reject(error); }, load: function(data, ioargs) { console.log('xhr.post', '<<<', ioargs.xhr, (new Date().getTime() - xhr._ts) + " ms"); if (complete != undefined) complete(data, ioargs.xhr); resolve(data) }} ); }); }, json: function(url, params = {}, complete = undefined, failed = undefined) { return new Promise((resolve, reject) => this.post(url, params, null, failed).then((data) => { let obj = null; try { obj = JSON.parse(data); } catch (e) { console.error("xhr.json", e, xhr); if (failed != undefined) failed(e); reject(e); return; } console.log('xhr.json', '<<<', obj, (new Date().getTime() - xhr._ts) + " ms"); if (obj && typeof App != "undefined") if (!App.handleRpcJson(obj)) { if (failed != undefined) failed(obj); reject(obj); return; } if (complete != undefined) complete(obj); resolve(obj); } )); } }; /* exported xhrPost */ function xhrPost(url, params = {}, complete = undefined) { console.log("xhrPost:", params); return new Promise((resolve, reject) => { if (typeof __csrf_token != "undefined") params = {...params, ...{csrf_token: __csrf_token}}; dojo.xhrPost({url: url, postData: dojo.objectToQuery(params), handleAs: "text", error: function(error) { reject(error); }, load: function(data, ioargs) { if (complete != undefined) complete(ioargs.xhr); resolve(ioargs.xhr) }}); }); } /* exported xhrJson */ function xhrJson(url, params = {}, complete = undefined) { return xhr.json(url, params, complete); } /* common helpers not worthy of separate Dojo modules */ /* exported Lists */ const Lists = { onRowChecked: function(elem) { const checked = elem.domNode ? elem.attr("checked") : elem.checked; // account for dojo checkboxes elem = elem.domNode || elem; const row = elem.closest("li"); if (row) checked ? row.addClassName("Selected") : row.removeClassName("Selected"); }, select: function(elem, selected) { if (typeof elem == "string") elem = document.getElementById(elem); elem.querySelectorAll("li").forEach((row) => { const checkNode = row.querySelector(".dijitCheckBox,input[type=checkbox]"); if (checkNode) { const widget = dijit.getEnclosingWidget(checkNode); if (widget) { widget.attr("checked", selected); } else { checkNode.checked = selected; } this.onRowChecked(widget); } }); }, getSelected: function(elem) { const rv = []; if (typeof elem == "string") elem = document.getElementById(elem); elem.querySelectorAll("li").forEach((row) => { if (row.hasClassName("Selected")) { const rowVal = row.getAttribute("data-row-value"); if (rowVal) { rv.push(rowVal); } else { // either older prefix-XXX notation or separate attribute const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, ""); if (!isNaN(rowId)) rv.push(parseInt(rowId)); } } }); return rv; } }; /* exported Tables */ const Tables = { onRowChecked: function(elem) { // account for dojo checkboxes const checked = elem.domNode ? elem.attr("checked") : elem.checked; elem = elem.domNode || elem; const row = elem.closest("tr"); if (row) checked ? row.addClassName("Selected") : row.removeClassName("Selected"); }, select: function(elem, selected) { if (typeof elem == "string") elem = document.getElementById(elem); elem.querySelectorAll("tr").forEach((row) => { const checkNode = row.querySelector(".dijitCheckBox,input[type=checkbox]"); if (checkNode) { const widget = dijit.getEnclosingWidget(checkNode); if (widget) { widget.attr("checked", selected); } else { checkNode.checked = selected; } this.onRowChecked(widget); } }); }, getSelected: function(elem) { const rv = []; if (typeof elem == "string") elem = document.getElementById(elem); elem.querySelectorAll("tr").forEach((row) => { if (row.hasClassName("Selected")) { const rowVal = row.getAttribute("data-row-value"); if (rowVal) { rv.push(rowVal); } else { // either older prefix-XXX notation or separate attribute const rowId = row.getAttribute("data-row-id") || row.id.replace(/^[A-Z]*?-/, ""); if (!isNaN(rowId)) rv.push(parseInt(rowId)); } } }); return rv; } }; /* exported Cookie */ const Cookie = { set: function (name, value, lifetime) { const d = new Date(); d.setTime(d.getTime() + lifetime * 1000); const expires = "expires=" + d.toUTCString(); document.cookie = name + "=" + encodeURIComponent(value) + "; " + expires; }, get: function (name) { name = name + "="; const ca = document.cookie.split(';'); for (let i=0; i < ca.length; i++) { let c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1); if (c.indexOf(name) == 0) return decodeURIComponent(c.substring(name.length, c.length)); } return ""; }, delete: function(name) { const expires = "expires=Thu, 01-Jan-1970 00:00:01 GMT"; document.cookie = name + "=; " + expires; } }; /* runtime notifications */ /* exported Notify */ const Notify = { KIND_GENERIC: 0, KIND_INFO: 1, KIND_ERROR: 2, KIND_PROGRESS: 3, timeout: 0, default_timeout: 5 * 1000, close: function() { this.msg(""); }, msg: function(msg, keep, kind) { kind = kind || this.KIND_GENERIC; keep = keep || false; const notify = App.byId("notify"); window.clearTimeout(this.timeout); if (!msg) { notify.removeClassName("visible"); return; } let msgfmt = "%s".replace("%s", __(msg)); let icon = ""; notify.className = "notify"; console.warn('notify', msg, kind); switch (kind) { case this.KIND_INFO: notify.addClassName("notify_info") icon = "notifications"; break; case this.KIND_ERROR: notify.addClassName("notify_error"); icon = "error"; break; case this.KIND_PROGRESS: notify.addClassName("notify_progress"); icon = App.getInitParam("icon_oval") break; default: icon = "notifications"; } if (icon) if (icon.indexOf("data:image") != -1) msgfmt = "".replace("%s", icon) + msgfmt; else msgfmt = "%s".replace("%s", icon) + msgfmt; msgfmt += "close"; notify.innerHTML = msgfmt; notify.addClassName("visible"); if (!keep) this.timeout = window.setTimeout(() => { notify.removeClassName("visible"); }, this.default_timeout); }, info: function(msg, keep) { keep = keep || false; this.msg(msg, keep, this.KIND_INFO); }, progress: function(msg, keep) { keep = keep || true; this.msg(msg, keep, this.KIND_PROGRESS); }, error: function(msg, keep) { keep = keep || true; this.msg(msg, keep, this.KIND_ERROR); } };