src/pyams_skin/resources/js/myams-core.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
--- 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);