--- a/src/pyams_skin/resources/js/myams-core.js Sun Jul 19 02:02:20 2020 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,582 +0,0 @@
-/*
- * MyAMS
- * « My Application Management Skin »
- *
- * $Tag$ (rev. 1)
- * A bootstrap based application/administration skin
- *
- * Custom administration and application skin tools
- * Released under Zope Public License ZPL 1.1
- * ©2014-2020 Thierry Florac <tflorac@ulthar.net>
- */
-
-"use strict";
-
-(function ($, globals) {
-
- var console = globals.console;
-
- /**
- * String prototype extensions
- */
- String.prototype.startsWith = function (str) {
- var slen = this.length,
- dlen = str.length;
- if (slen < dlen) {
- return false;
- }
- return (this.substr(0, dlen) === str);
- };
-
- String.prototype.endsWith = function (str) {
- var slen = this.length,
- dlen = str.length;
- if (slen < dlen) {
- return false;
- }
- return (this.substr(slen - dlen) === str);
- };
-
- String.prototype.unserialize = function (str) {
- var str = decodeURIComponent(this);
- var chunks = str.split('&'),
- obj = {};
- for (var c = 0; c < chunks.length; c++) {
- var split = chunks[c].split('=', 2);
- obj[split[0]] = split[1];
- }
- return obj;
- };
-
- /**
- * Array prototype extensions
- */
- if (!Array.prototype.indexOf) {
- Array.prototype.indexOf = function (elt, from) {
- var len = this.length;
-
- from = Number(from) || 0;
- from = (from < 0) ? Math.ceil(from) : Math.floor(from);
- if (from < 0) {
- from += len;
- }
-
- for (; from < len; from++) {
- if (from in this && this[from] === elt) {
- return from;
- }
- }
- return -1;
- };
- }
-
-
- /**
- * JQuery 'hasvalue' expression
- * Filter inputs containing value
- */
- $.expr[":"].hasvalue = function (obj, index, meta /*, stack*/) {
- return $(obj).val() !== "";
- };
-
-
- /**
- * JQuery 'econtains' expression
- * Case insensitive contains expression
- */
- $.expr[":"].econtains = function (obj, index, meta /*, stack*/) {
- return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() === meta[3].toLowerCase();
- };
-
-
- /**
- * JQuery 'withtext' expression
- * Case sensitive exact search expression
- */
- $.expr[":"].withtext = function (obj, index, meta /*, stack*/) {
- return (obj.textContent || obj.innerText || $(obj).text() || "") === meta[3];
- };
-
-
- /**
- * JQuery filter on parents class
- * This filter is often combined with ":not()" to select DOM objects which don't have
- * parents of a given class.
- * For example:
- *
- * $('.hint:not(:parents(.nohints))', element);
- *
- * will select all elements with ".hint" class which don't have a parent with '.nohints' class.
- */
- $.expr[':'].parents = function (obj, index, meta /*, stack*/) {
- return $(obj).parents(meta[3]).length > 0;
- };
-
-
- /**
- * JQuery 'scrollbarWidth' function
- * Get width of default vertical scrollbar
- */
- if ($.scrollbarWidth === undefined) {
- $.scrollbarWidth = function () {
- var parent = $('<div style="width: 50px; height: 50px; overflow: auto"><div/></div>').appendTo('body');
- var child = parent.children();
- var width = child.innerWidth() - child.height(99).innerWidth();
- parent.remove();
- return width;
- };
- }
-
-
- /**
- * MyAMS JQuery extensions
- */
- $.fn.extend({
-
- /**
- * Check if current object is empty or not
- */
- exists: function () {
- return $(this).length > 0;
- },
-
- /**
- * Get object if it supports given CSS class,
- * otherwise look for parents
- */
- objectOrParentWithClass: function (klass) {
- if (this.hasClass(klass)) {
- return this;
- } else {
- return this.parents('.' + klass);
- }
- },
-
- /**
- * Build an array of attributes of the given selection
- */
- listattr: function (attr) {
- var result = [];
- this.each(function () {
- result.push($(this).attr(attr));
- });
- return result;
- },
-
- /**
- * CSS style function
- * Code from Aram Kocharyan on stackoverflow.com
- */
- style: function (styleName, value, priority) {
- // DOM node
- var node = this.get(0);
- // Ensure we have a DOM node
- if (typeof(node) === 'undefined') {
- return;
- }
- // CSSStyleDeclaration
- var style = this.get(0).style;
- // Getter/Setter
- if (typeof(styleName) !== 'undefined') {
- if (typeof(value) !== 'undefined') {
- // Set style property
- priority = typeof(priority) !== 'undefined' ? priority : '';
- style.setProperty(styleName, value, priority);
- return this;
- } else {
- // Get style property
- return style.getPropertyValue(styleName);
- }
- } else {
- // Get CSSStyleDeclaration
- return style;
- }
- },
-
- /**
- * Remove CSS classes starting with a given prefix
- */
- removeClassPrefix: function (prefix) {
- this.each(function (i, it) {
- var classes = it.className.split(" ").map(function (item) {
- return item.startsWith(prefix) ? "" : item;
- });
- it.className = $.trim(classes.join(" "));
- });
- return this;
- }
- });
-
-
- /**
- * MyAMS extensions to JQuery
- */
- if (globals.MyAMS === undefined) {
- globals.MyAMS = {
- devmode: true,
- devext: '',
- lang: 'en',
- throttleDelay: 350,
- menuSpeed: 235,
- navbarHeight: 49,
- ajaxNav: true,
- safeMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'],
- csrfCookieName: 'csrf_token',
- csrfHeaderName: 'X-CSRF-Token',
- enableWidgets: true,
- enableMobile: false,
- enableFastclick: false,
- warnOnFormChange: false,
- formChangedCallback: null,
- ismobile: (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()))
- };
- }
- var MyAMS = globals.MyAMS;
- var ams = MyAMS;
-
- /**
- * Get MyAMS base URL
- * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst
- */
- MyAMS.baseURL = (function () {
- var script = $('script[src*="/myams.js"], script[src*="/myams.min.js"], ' +
- 'script[src*="/myams-core.js"], script[src*="/myams-core.min.js"], ' +
- 'script[src*="/myams-require.js"], script[src*="/myams-require.min.js"]');
- var src = script.attr("src");
- ams.devmode = src.indexOf('.min.js') < 0;
- ams.devext = ams.devmode ? '' : '.min';
- return src.substring(0, src.lastIndexOf('/') + 1);
- })();
-
-
- /**
- * Basic logging function which log all arguments to console
- */
- MyAMS.log = function () {
- if (console) {
- console.debug && console.debug(this, arguments);
- }
- };
-
-
- /**
- * Extract parameter value from given query string
- */
- MyAMS.getQueryVar = function (src, varName) {
- // Check src
- if (src.indexOf('?') < 0) {
- return false;
- }
- if (!src.endsWith('&')) {
- src += '&';
- }
- // Dynamic replacement RegExp
- var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
- // Apply RegExp to the query string
- var val = src.replace(regex, "$1");
- // If the string is the same, we didn't find a match - return false
- return val === src ? false : val;
- };
-
-
- /**
- * Color conversion function
- */
- MyAMS.rgb2hex = function (color) {
- return "#" + $.map(color.match(/\b(\d+)\b/g), function (digit) {
- return ('0' + parseInt(digit).toString(16)).slice(-2);
- }).join('');
- };
-
-
- /**
- * Generate a random ID
- */
- MyAMS.generateId = function () {
- function s4() {
- return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
- }
-
- return s4() + s4() + s4() + s4();
- };
-
-
- /**
- * Generate a random UUID
- */
- MyAMS.generateUUID = function () {
- var d = new Date().getTime();
- var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
- var r = (d + Math.random() * 16) % 16 | 0;
- d = Math.floor(d / 16);
- return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
- });
- return uuid;
- };
-
-
- /**
- * Get an object given by name
- */
- MyAMS.getObject = function (objectName, context) {
- if (!objectName) {
- return undefined;
- }
- if (typeof(objectName) !== 'string') {
- return objectName;
- }
- var namespaces = objectName.split(".");
- context = (context === undefined || context === null) ? window : context;
- for (var i = 0; i < namespaces.length; i++) {
- try {
- context = context[namespaces[i]];
- } catch (e) {
- return undefined;
- }
- }
- return context;
- };
-
- /**
- * Get and execute a function given by name
- * Small piece of code by Jason Bunting
- */
- MyAMS.getFunctionByName = function (functionName, context) {
- if (functionName === undefined) {
- return undefined;
- } else if (typeof(functionName) === 'function') {
- return functionName;
- }
- var namespaces = functionName.split(".");
- var func = namespaces.pop();
- context = (context === undefined || context === null) ? window : context;
- for (var i = 0; i < namespaces.length; i++) {
- try {
- context = context[namespaces[i]];
- } catch (e) {
- return undefined;
- }
- }
- try {
- return context[func];
- } catch (e) {
- return undefined;
- }
- };
-
- MyAMS.executeFunctionByName = function (functionName, context /*, args */) {
- var func = ams.getFunctionByName(functionName, window);
- if (typeof(func) === 'function') {
- var args = Array.prototype.slice.call(arguments, 2);
- return func.apply(context, args);
- }
- };
-
- /**
- * Check to know if given element is still present in DOM
- */
- MyAMS.isInDOM = function (element) {
- element = $(element);
- if (!element.exists()) {
- return false;
- }
- return globals.document.body.contains(element[0]);
- };
-
- /**
- * Get target URL matching given source
- *
- * Given URL can include variable names (with their namespace), given between braces, as in {MyAMS.baseURL}
- */
- MyAMS.getSource = function (url) {
- return url.replace(/{[^{}]*}/g, function (match) {
- return ams.getFunctionByName(match.substr(1, match.length - 2));
- });
- };
-
- /**
- * Script loader function
- *
- * @param url: script URL
- * @param callback: a callback to be called after script loading
- * @param options: a set of options to be added to AJAX call
- * @param onerror: an error callback to be called instead of generic callback
- */
- MyAMS.getScript = function (url, callback, options, onerror) {
- if (typeof(callback) === 'object') {
- onerror = options;
- options = callback;
- callback = null;
- }
- if (options === undefined) {
- options = {};
- }
- var defaults = {
- dataType: 'script',
- url: ams.getSource(url),
- success: callback,
- error: onerror || ams.error.show,
- cache: !ams.devmode,
- async: options.async === undefined ? typeof(callback) === 'function' : options.async
- };
- var settings = $.extend({}, defaults, options);
- return $.ajax(settings);
- };
-
- /**
- * CSS file loader function
- * Cross-browser code copied from Stoyan Stefanov blog to be able to
- * call a callback when CSS is realy loaded.
- * See: https://www.phpied.com/when-is-a-stylesheet-really-loaded
- *
- * @param url: CSS file URL
- * @param id: a unique ID given to CSS file
- * @param callback: optional callback function to be called when CSS file is loaded. If set, callback is called
- * with a 'first_load' boolean argument to indicate is CSS was already loaded (*false* value) or not (*true*
- * value).
- * @param options: callback options
- */
- MyAMS.getCSS = function (url, id, callback, options) {
- if (callback) {
- callback = ams.getFunctionByName(callback);
- }
- var head = $('HEAD');
- var style = $('style[data-ams-id="' + id + '"]', head);
- if (style.length === 0) {
- style = $('<style>').attr('data-ams-id', id)
- .text('@import "' + ams.getSource(url) + '";');
- if (callback) {
- var styleInterval = setInterval(function () {
- try {
- var _check = style[0].sheet.cssRules; // Is only populated when file is loaded
- callback.call(window, true, options);
- clearInterval(styleInterval);
- } catch (e) {
- // CSS is not loaded yet...
- }
- }, 10);
- }
- style.appendTo(head);
- } else {
- if (callback) {
- callback.call(window, false, options);
- }
- }
- };
-
- /**
- * Initialize main events handlers
- */
- MyAMS.initHandlers = function(element) {
-
- // Initialize custom click handlers
- $(element).on('click', '[data-ams-click-handler]', function(event) {
- var source = $(this);
- var handlers = source.data('ams-disabled-handlers');
- if ((handlers === true) || (handlers === 'click') || (handlers === 'all')) {
- return;
- }
- var data = source.data();
- if (data.amsClickHandler) {
- if ((data.amsStopPropagation === true) || (data.amsClickStopPropagation === true)) {
- event.stopPropagation();
- }
- if (data.amsClickKeepDefault !== true) {
- event.preventDefault();
- }
- var clickHandlers = data.amsClickHandler.split(/\s+/);
- for (var index=0; index < clickHandlers.length; index++) {
- var callback = ams.getFunctionByName(clickHandlers[index]);
- if (callback !== undefined) {
- callback.call(source, event, data.amsClickHandlerOptions);
- }
- }
- }
- });
-
- // Initialize custom change handlers
- $(element).on('change', '[data-ams-change-handler]', function(event) {
- var source = $(this);
- // Disable change handlers for readonly inputs
- // These change handlers are activated by IE!!!
- if (source.prop('readonly')) {
- return;
- }
- var handlers = source.data('ams-disabled-handlers');
- if ((handlers === true) || (handlers === 'change') || (handlers === 'all')) {
- return;
- }
- var data = source.data();
- if (data.amsChangeHandler) {
- if ((data.amsStopPropagation === true) || (data.amsChangeStopPropagation === true)) {
- event.stopPropagation();
- }
- if (data.amsChangeKeepDefault !== true) {
- event.preventDefault();
- }
- var changeHandlers = data.amsChangeHandler.split(/\s+/);
- for (var index=0; index < changeHandlers.length; index++) {
- var callback = ams.getFunctionByName(changeHandlers[index]);
- if (callback !== undefined) {
- callback.call(source, event, data.amsChangeHandlerOptions);
- }
- }
- }
- });
-
- // Notify reset to update Select2 widgets
- $(element).on('reset', 'form', function(e) {
- var form = $(this);
- setTimeout(function() {
- $('.alert-danger, SPAN.state-error', form).not('.persistent').remove();
- $('LABEL.state-error', form).removeClass('state-error');
- $('INPUT.select2[type="hidden"]', form).each(function() {
- var input = $(this);
- var select = input.data('select2');
- var value = input.data('ams-select2-input-value');
- if (value) {
- input.select2('val', value.split(select.opts.separator));
- }
- });
- form.find('.select2').trigger('change');
- $('[data-ams-reset-callback]', form).each(function() {
- var element = $(this);
- var data = element.data();
- var callback = ams.getFunctionByName(data.amsResetCallback);
- if (callback !== undefined) {
- callback.call(form, element, data.amsResetCallbackOptions);
- }
- });
- }, 10);
- ams.form && ams.form.setFocus(form);
- });
-
- // Initialize custom reset handlers
- $(element).on('reset', '[data-ams-reset-handler]', function(e) {
- var form = $(this);
- var data = form.data();
- if (data.amsResetHandler) {
- if (data.amsResetKeepDefault !== true) {
- e.preventDefault();
- }
- var callback = ams.getFunctionByName(data.amsResetHandler);
- if (callback !== undefined) {
- callback.call(form, data.amsResetHandlerOptions);
- }
- }
- });
-
- // Initialize custom event on click
- $(element).on('click', '[data-ams-click-event]', function(e) {
- var source = $(this);
- $(e.target).trigger(source.data('ams-click-event'),
- source.data('ams-click-event-options'));
- });
-
- // Cancel clicks on readonly checkbox
- $(element).on('click', 'input[type="checkbox"][readonly]', function() {
- return false;
- });
- };
-
-})(jQuery, this);