src/pyams_skin/resources/js/myams.js
changeset 118 391ad752903e
parent 99 c628592aa86e
child 121 2c87fbbec680
equal deleted inserted replaced
117:00bfb7b29d9e 118:391ad752903e
     8  * Custom administration and application skin tools
     8  * Custom administration and application skin tools
     9  * Released under Zope Public License ZPL 1.1
     9  * Released under Zope Public License ZPL 1.1
    10  * ©2014-2015 Thierry Florac <tflorac@ulthar.net>
    10  * ©2014-2015 Thierry Florac <tflorac@ulthar.net>
    11  */
    11  */
    12 
    12 
    13 (function($) {
    13 (function($, globals) {
       
    14 
       
    15 	"use strict";
    14 
    16 
    15 	/**
    17 	/**
    16 	 * String prototype extensions
    18 	 * String prototype extensions
    17 	 */
    19 	 */
    18 	String.prototype.startsWith = function(str) {
    20 	String.prototype.startsWith = function(str) {
    19 		var slen = this.length;
    21 		var slen = this.length,
    20 		var dlen = str.length;
    22 			dlen = str.length;
    21 		if (slen < dlen) {
    23 		if (slen < dlen) {
    22 			return false;
    24 			return false;
    23 		}
    25 		}
    24 		return (this.substr(0,dlen) == str);
    26 		return (this.substr(0,dlen) === str);
    25 	};
    27 	};
    26 
    28 
    27 	String.prototype.endsWith = function(str) {
    29 	String.prototype.endsWith = function(str) {
    28 		var slen = this.length;
    30 		var slen = this.length,
    29 		var dlen = str.length;
    31 			dlen = str.length;
    30 		if (slen < dlen) {
    32 		if (slen < dlen) {
    31 			return false;
    33 			return false;
    32 		}
    34 		}
    33 		return (this.substr(slen-dlen) == str);
    35 		return (this.substr(slen-dlen) === str);
    34 	};
    36 	};
    35 
    37 
    36 
    38 
    37 	/**
    39 	/**
    38 	 * Array prototype extensions
    40 	 * Array prototype extensions
    39 	 */
    41 	 */
    40 	if (!Array.prototype.indexOf) {
    42 	if (!Array.prototype.indexOf) {
    41 		Array.prototype.indexOf = function(elt /*, from*/) {
    43 		Array.prototype.indexOf = function(elt, from) {
    42 			var len = this.length;
    44 			var len = this.length;
    43 
    45 
    44 			var from = Number(arguments[1]) || 0;
    46 			from = Number(from) || 0;
    45 			from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    47 			from = (from < 0) ? Math.ceil(from) : Math.floor(from);
    46 			if (from < 0)
    48 			if (from < 0) {
    47 				from += len;
    49 				from += len;
       
    50 			}
    48 
    51 
    49 			for (; from < len; from++) {
    52 			for (; from < len; from++) {
    50 				if (from in this &&
    53 				if (from in this && this[from] === elt) {
    51 					this[from] === elt)
       
    52 					return from;
    54 					return from;
       
    55 				}
    53 			}
    56 			}
    54 			return -1;
    57 			return -1;
    55 		};
    58 		};
    56 	}
    59 	}
    57 
    60 
    59 	/**
    62 	/**
    60 	 * JQuery 'econtains' expression
    63 	 * JQuery 'econtains' expression
    61 	 * Case insensitive contains expression
    64 	 * Case insensitive contains expression
    62 	 */
    65 	 */
    63 	$.expr[":"].econtains = function(obj, index, meta /*, stack*/) {
    66 	$.expr[":"].econtains = function(obj, index, meta /*, stack*/) {
    64 		return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() == meta[3].toLowerCase();
    67 		return (obj.textContent || obj.innerText || $(obj).text() || "").toLowerCase() === meta[3].toLowerCase();
    65 	};
    68 	};
    66 
    69 
    67 
    70 
    68 	/**
    71 	/**
    69 	 * JQuery 'withtext' expression
    72 	 * JQuery 'withtext' expression
    70 	 * Case sensitive exact search expression
    73 	 * Case sensitive exact search expression
    71 	 */
    74 	 */
    72 	$.expr[":"].withtext = function(obj, index, meta /*, stack*/) {
    75 	$.expr[":"].withtext = function(obj, index, meta /*, stack*/) {
    73 		return (obj.textContent || obj.innerText || $(obj).text() || "") == meta[3];
    76 		return (obj.textContent || obj.innerText || $(obj).text() || "") === meta[3];
    74 	};
    77 	};
    75 
    78 
    76 
    79 
    77 	/**
    80 	/**
    78 	 * JQuery filter on parents class
    81 	 * JQuery filter on parents class
    86 	 * JQuery 'scrollbarWidth' function
    89 	 * JQuery 'scrollbarWidth' function
    87 	 * Get width of vertical scrollbar
    90 	 * Get width of vertical scrollbar
    88 	 */
    91 	 */
    89 	if ($.scrollbarWidth === undefined) {
    92 	if ($.scrollbarWidth === undefined) {
    90 		$.scrollbarWidth = function() {
    93 		$.scrollbarWidth = function() {
    91 			var parent = $('<div style="width:50px;height:50px;overflow:auto"><div/></div>').appendTo('body');
    94 			var parent = $('<div style="width:50px; height:50px; overflow:auto"><div/></div>').appendTo('body');
    92 			var child = parent.children();
    95 			var child = parent.children();
    93 			var width = child.innerWidth() - child.height(99).innerWidth();
    96 			var width = child.innerWidth() - child.height(99).innerWidth();
    94 			parent.remove();
    97 			parent.remove();
    95 			return width;
    98 			return width;
    96 		};
    99 		};
   112 		/*
   115 		/*
   113 		 * Get object if it supports given CSS class,
   116 		 * Get object if it supports given CSS class,
   114 		 * otherwise looks for parents
   117 		 * otherwise looks for parents
   115 		 */
   118 		 */
   116 		objectOrParentWithClass: function(klass) {
   119 		objectOrParentWithClass: function(klass) {
   117 			if (this.hasClass(klass))
   120 			if (this.hasClass(klass)) {
   118 				return this;
   121 				return this;
   119 			else
   122 			} else {
   120 				return this.parents('.' + klass);
   123 				return this.parents('.' + klass);
       
   124 			}
   121 		},
   125 		},
   122 
   126 
   123 		/*
   127 		/*
   124 		 * Build an array of attributes of the given selection
   128 		 * Build an array of attributes of the given selection
   125 		 */
   129 		 */
   137 		 */
   141 		 */
   138 		style: function(styleName, value, priority) {
   142 		style: function(styleName, value, priority) {
   139 			// DOM node
   143 			// DOM node
   140 			var node = this.get(0);
   144 			var node = this.get(0);
   141 			// Ensure we have a DOM node
   145 			// Ensure we have a DOM node
   142 			if (typeof node == 'undefined') {
   146 			if (typeof(node) === 'undefined') {
   143 				return;
   147 				return;
   144 			}
   148 			}
   145 			// CSSStyleDeclaration
   149 			// CSSStyleDeclaration
   146 			var style = this.get(0).style;
   150 			var style = this.get(0).style;
   147 			// Getter/Setter
   151 			// Getter/Setter
   148 			if (typeof styleName != 'undefined') {
   152 			if (typeof(styleName) !== 'undefined') {
   149 				if (typeof value != 'undefined') {
   153 				if (typeof(value) !== 'undefined') {
   150 					// Set style property
   154 					// Set style property
   151 					priority = typeof priority != 'undefined' ? priority : '';
   155 					priority = typeof(priority) !== 'undefined' ? priority : '';
   152 					style.setProperty(styleName, value, priority);
   156 					style.setProperty(styleName, value, priority);
   153 					return this;
   157 					return this;
   154 				} else {
   158 				} else {
   155 					// Get style property
   159 					// Get style property
   156 					return style.getPropertyValue(styleName);
   160 					return style.getPropertyValue(styleName);
   165 		 * Remove CSS classes starting with a given prefix
   169 		 * Remove CSS classes starting with a given prefix
   166 		 */
   170 		 */
   167 		removeClassPrefix: function (prefix) {
   171 		removeClassPrefix: function (prefix) {
   168 			this.each(function (i, it) {
   172 			this.each(function (i, it) {
   169 				var classes = it.className.split(" ").map(function(item) {
   173 				var classes = it.className.split(" ").map(function(item) {
   170 					return item.startsWith(prefix) ? "" : item
   174 					return item.startsWith(prefix) ? "" : item;
   171 				});
   175 				});
   172 				it.className = $.trim(classes.join(" "))
   176 				it.className = $.trim(classes.join(" "));
   173 			});
   177 			});
   174 			return this;
   178 			return this;
   175 		},
   179 		},
   176 
   180 
   177 		/*
   181 		/*
   182 			function getMenuPosition(mouse, direction, scrollDir) {
   186 			function getMenuPosition(mouse, direction, scrollDir) {
   183 				var win = $(window)[direction](),
   187 				var win = $(window)[direction](),
   184 					menu = $(settings.menuSelector)[direction](),
   188 					menu = $(settings.menuSelector)[direction](),
   185 					position = mouse;
   189 					position = mouse;
   186 				// opening menu would pass the side of the page
   190 				// opening menu would pass the side of the page
   187 				if (mouse + menu > win && menu < mouse)
   191 				if (mouse + menu > win && menu < mouse) {
   188 					position -= menu;
   192 					position -= menu;
       
   193 				}
   189 				return position;
   194 				return position;
   190 			}
   195 			}
   191 
   196 
   192 			return this.each(function () {
   197 			return this.each(function () {
   193 
   198 
   195 				$('a', $(settings.menuSelector)).each(function() {
   200 				$('a', $(settings.menuSelector)).each(function() {
   196 					$(this).data('ams-context-menu', true);
   201 					$(this).data('ams-context-menu', true);
   197 				});
   202 				});
   198 				$(this).on("contextmenu", function (e) {
   203 				$(this).on("contextmenu", function (e) {
   199 					// return native menu if pressing control
   204 					// return native menu if pressing control
   200 					if (e.ctrlKey)
   205 					if (e.ctrlKey) {
   201 						return;
   206 						return;
       
   207 					}
   202 					//open menu
   208 					//open menu
   203 					$(settings.menuSelector).data("invokedOn", $(e.target))
   209 					$(settings.menuSelector).data("invokedOn", $(e.target))
   204 											.show()
   210 											.show()
   205 											.css({
   211 											.css({
   206 												position: 'fixed',
   212 												position: 'fixed',
   250 					menu_item.find("A:first")
   256 					menu_item.find("A:first")
   251 							 .append("<b class='collapse-sign'>" + settings.closedSign + "</b>");
   257 							 .append("<b class='collapse-sign'>" + settings.closedSign + "</b>");
   252 
   258 
   253 					// avoid jumping to the top of the page when the href is an #
   259 					// avoid jumping to the top of the page when the href is an #
   254 					var first_link = menu_item.find("A:first");
   260 					var first_link = menu_item.find("A:first");
   255 					if (first_link.attr('href') == "#") {
   261 					if (first_link.attr('href') === "#") {
   256 						first_link.click(function() {
   262 						first_link.click(function() {
   257 							return false;
   263 							return false;
   258 						});
   264 						});
   259 					}
   265 					}
   260 				}
   266 				}
   264 			menu.find("LI.active").each(function() {
   270 			menu.find("LI.active").each(function() {
   265 				var active_parent = $(this).parents('UL');
   271 				var active_parent = $(this).parents('UL');
   266 				var active_item = active_parent.parent('LI');
   272 				var active_item = active_parent.parent('LI');
   267 				active_parent.slideDown(settings.speed);
   273 				active_parent.slideDown(settings.speed);
   268 				active_item.find("b:first").html(settings.openedSign);
   274 				active_item.find("b:first").html(settings.openedSign);
   269 				active_item.addClass("open")
   275 				active_item.addClass("open");
   270 			});
   276 			});
   271 
   277 
   272 			menu.find("LI A").on('click', function() {
   278 			menu.find("LI A").on('click', function() {
   273 				var link = $(this);
   279 				var link = $(this);
       
   280 				if (link.hasClass('active')) {
       
   281 					return;
       
   282 				}
       
   283 				var href = link.attr('href').replace(/^#/,'');
   274 				var parent_ul = link.parent().find("UL");
   284 				var parent_ul = link.parent().find("UL");
   275 				if (settings.accordion) {
   285 				if (settings.accordion) {
   276 					var parents = link.parent().parents("UL");
   286 					var parents = link.parent().parents("UL");
   277 					var visible = menu.find("UL:visible");
   287 					var visible = menu.find("UL:visible");
   278 					visible.each(function(visibleIndex) {
   288 					visible.each(function(visibleIndex) {
   279 						var close = true;
   289 						var close = true;
   280 						parents.each(function(parentIndex) {
   290 						parents.each(function(parentIndex) {
   281 							if (parents[parentIndex] == visible[visibleIndex]) {
   291 							if (parents[parentIndex] === visible[visibleIndex]) {
   282 								close = false;
   292 								close = false;
   283 								return false;
   293 								return false;
   284 							}
   294 							}
   285 						});
   295 						});
   286 						if (close) {
   296 						if (close) {
   287 							if (parent_ul != visible[visibleIndex]) {
   297 							if (parent_ul !== visible[visibleIndex]) {
   288 								$(visible[visibleIndex]).slideUp(settings.speed, function() {
   298 								var visibleItem = $(visible[visibleIndex]);
   289 									link.parent("LI")
   299 								if (href || !visibleItem.hasClass('active')) {
   290 										.find("b:first")
   300 									visibleItem.slideUp(settings.speed, function () {
   291 										.html(settings.closedSign);
   301 										$(this).parent("LI")
   292 									link.parent("LI")
   302 											.removeClass('open')
   293 										.removeClass("open");
   303 											.find("B:first")
   294 								});
   304 											.delay(settings.speed)
       
   305 											.html(settings.closedSign);
       
   306 									});
       
   307 								}
   295 							}
   308 							}
   296 						}
   309 						}
   297 					});
   310 					});
   298 				}
   311 				}
   299 				var first_ul = link.parent().find("UL:first");
   312 				var first_ul = link.parent().find("UL:first");
   300 				if (!link.attr('href').replace(/^#/,'') &&
   313 				if (!href && first_ul.is(":visible") && !first_ul.hasClass("active")) {
   301 					first_ul.is(":visible") &&
       
   302 					!first_ul.hasClass("active")) {
       
   303 					first_ul.slideUp(settings.speed, function() {
   314 					first_ul.slideUp(settings.speed, function() {
   304 						link.parent("LI")
   315 						link.parent("LI")
   305 							.removeClass("open")
   316 							.removeClass("open")
   306 							.find("B:first")
   317 							.find("B:first")
   307 							.delay(settings.speed)
   318 							.delay(settings.speed)
   308 							.html(settings.closedSign);
   319 							.html(settings.closedSign);
   309 					});
   320 					});
   310 				} else /*if (link.attr('href') != location.hash)*/ {
   321 				} else /*if (link.attr('href') !== location.hash)*/ {
   311 					first_ul.slideDown(settings.speed, function() {
   322 					first_ul.slideDown(settings.speed, function() {
   312 						link.parent("LI")
   323 						link.parent("LI")
   313 							.addClass("open")
   324 							.addClass("open")
   314 							.find("B:first")
   325 							.find("B:first")
   315 							.delay(settings.speed)
   326 							.delay(settings.speed)
   386 
   397 
   387 
   398 
   388 	/**
   399 	/**
   389 	 * MyAMS extensions to JQuery
   400 	 * MyAMS extensions to JQuery
   390 	 */
   401 	 */
   391 	if (window.MyAMS === undefined) {
   402 	if (globals.MyAMS === undefined) {
   392 		window.MyAMS = {
   403 		globals.MyAMS = {
   393 			devmode: true,
   404 			devmode: true,
   394 			devext: '',
   405 			devext: '',
   395 			lang: 'en',
   406 			lang: 'en',
   396 			throttle_delay: 350,
   407 			throttle_delay: 350,
   397 			menu_speed: 235,
   408 			menu_speed: 235,
   402 			enable_fastclick: false,
   413 			enable_fastclick: false,
   403 			warn_on_form_change: false,
   414 			warn_on_form_change: false,
   404 			ismobile: (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()))
   415 			ismobile: (/iphone|ipad|ipod|android|blackberry|mini|windows\sce|palm/i.test(navigator.userAgent.toLowerCase()))
   405 		};
   416 		};
   406 	}
   417 	}
       
   418 	var MyAMS = globals.MyAMS;
   407 	var ams = MyAMS;
   419 	var ams = MyAMS;
   408 
   420 
   409 	/**
   421 	/**
   410 	 * Get MyAMS base URL
   422 	 * Get MyAMS base URL
   411 	 * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst
   423 	 * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst
   422 	/**
   434 	/**
   423 	 * Extract parameter value from given query string
   435 	 * Extract parameter value from given query string
   424 	 */
   436 	 */
   425 	MyAMS.getQueryVar = function(src, varName) {
   437 	MyAMS.getQueryVar = function(src, varName) {
   426 		// Check src
   438 		// Check src
   427 		if (src.indexOf('?') < 0)
   439 		if (src.indexOf('?') < 0) {
   428 			return false;
   440 			return false;
   429 		if (!src.endsWith('&'))
   441 		}
       
   442 		if (!src.endsWith('&')) {
   430 			src += '&';
   443 			src += '&';
       
   444 		}
   431 		// Dynamic replacement RegExp
   445 		// Dynamic replacement RegExp
   432 		var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
   446 		var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
   433 		// Apply RegExp to the query string
   447 		// Apply RegExp to the query string
   434 		var val = src.replace(regex, "$1");
   448 		var val = src.replace(regex, "$1");
   435 		// If the string is the same, we didn't find a match - return false
   449 		// If the string is the same, we didn't find a match - return false
   436 		return val == src ? false : val;
   450 		return val === src ? false : val;
   437 	};
   451 	};
   438 
   452 
   439 
   453 
   440 	/**
   454 	/**
   441 	 * Color conversion function
   455 	 * Color conversion function
   442 	 */
   456 	 */
   443 	MyAMS.rgb2hex = function(color) {
   457 	MyAMS.rgb2hex = function(color) {
   444 		return "#" + $.map(color.match(/\b(\d+)\b/g), function(digit) {
   458 		return "#" + $.map(color.match(/\b(\d+)\b/g), function(digit) {
   445 			return ('0' + parseInt(digit).toString(16)).slice(-2)
   459 			return ('0' + parseInt(digit).toString(16)).slice(-2);
   446 		}).join('');
   460 		}).join('');
   447 	};
   461 	};
   448 
   462 
   449 
   463 
   450 	/**
   464 	/**
   463 	/**
   477 	/**
   464 	 * Get and execute a function given by name
   478 	 * Get and execute a function given by name
   465 	 * Small piece of code by Jason Bunting
   479 	 * Small piece of code by Jason Bunting
   466 	 */
   480 	 */
   467 	MyAMS.getFunctionByName = function(functionName, context) {
   481 	MyAMS.getFunctionByName = function(functionName, context) {
   468 		if (functionName === undefined)
   482 		if (functionName === undefined) {
   469 			return undefined;
   483 			return undefined;
   470 		else if (typeof(functionName) == 'function')
   484 		} else if (typeof(functionName) === 'function') {
   471 			return functionName;
   485 			return functionName;
       
   486 		}
   472 		var namespaces = functionName.split(".");
   487 		var namespaces = functionName.split(".");
   473 		var func = namespaces.pop();
   488 		var func = namespaces.pop();
   474 		context = (context === undefined || context === null) ? window : context;
   489 		context = (context === undefined || context === null) ? window : context;
   475 		for (var i=0; i < namespaces.length; i++) {
   490 		for (var i=0; i < namespaces.length; i++) {
   476 			try {
   491 			try {
   486 		}
   501 		}
   487 	};
   502 	};
   488 
   503 
   489 	MyAMS.executeFunctionByName = function(functionName, context /*, args */) {
   504 	MyAMS.executeFunctionByName = function(functionName, context /*, args */) {
   490 		var func = ams.getFunctionByName(functionName, window);
   505 		var func = ams.getFunctionByName(functionName, window);
   491 		if (typeof(func) == 'function') {
   506 		if (typeof(func) === 'function') {
   492 			var args = Array.prototype.slice.call(arguments, 2);
   507 			var args = Array.prototype.slice.call(arguments, 2);
   493 			return func.apply(context, args);
   508 			return func.apply(context, args);
   494 		}
   509 		}
   495 	};
   510 	};
   496 
   511 
   511 			dataType: 'script',
   526 			dataType: 'script',
   512 			url: ams.getSource(url),
   527 			url: ams.getSource(url),
   513 			success: callback,
   528 			success: callback,
   514 			error: ams.error.show,
   529 			error: ams.error.show,
   515 			cache: !ams.devmode,
   530 			cache: !ams.devmode,
   516 			async: typeof(callback) == 'function'
   531 			async: typeof(callback) === 'function'
   517 		};
   532 		};
   518 		var settings = $.extend({}, defaults, options);
   533 		var settings = $.extend({}, defaults, options);
   519 		return $.ajax(settings);
   534 		return $.ajax(settings);
   520 	};
   535 	};
   521 
   536 
   522 	MyAMS.getCSS = function(url, id) {
   537 	MyAMS.getCSS = function(url, id) {
   523 		var head = $('HEAD');
   538 		var head = $('HEAD');
   524 		var css = $('link[data-ams-id="' + id + '"]', head);
   539 		var css = $('link[data-ams-id="' + id + '"]', head);
   525 		if (css.length == 0) {
   540 		if (css.length === 0) {
   526 			var source = ams.getSource(url);
   541 			var source = ams.getSource(url);
   527 			if (ams.devmode)
   542 			if (ams.devmode) {
   528 				source += '?_=' + new Date().getTime();
   543 				source += '?_=' + new Date().getTime();
       
   544 			}
   529 			$('<link />').attr({rel: 'stylesheet',
   545 			$('<link />').attr({rel: 'stylesheet',
   530 								type: 'text/css',
   546 								type: 'text/css',
   531 								href: source,
   547 								href: source,
   532 								'data-ams-id': id})
   548 								'data-ams-id': id})
   533 						 .appendTo(head);
   549 						 .appendTo(head);
   562 	 */
   578 	 */
   563 	MyAMS.browser = {
   579 	MyAMS.browser = {
   564 
   580 
   565 		getInternetExplorerVersion: function() {
   581 		getInternetExplorerVersion: function() {
   566 			var rv = -1;
   582 			var rv = -1;
   567 			if (navigator.appName == "Microsoft Internet Explorer") {
   583 			if (navigator.appName === "Microsoft Internet Explorer") {
   568 				var ua = navigator.userAgent;
   584 				var ua = navigator.userAgent;
   569 				var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
   585 				var re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
   570 				if (re.exec(ua) != null)
   586 				if (re.exec(ua) !== null) {
   571 					rv = parseFloat(RegExp.$1);
   587 					rv = parseFloat(RegExp.$1);
       
   588 				}
   572 			}
   589 			}
   573 			return rv;
   590 			return rv;
   574 		},
   591 		},
   575 
   592 
   576 		checkVersion: function() {
   593 		checkVersion: function() {
   577 			var msg = "You're not using Windows Internet Explorer.";
   594 			var msg = "You're not using Windows Internet Explorer.";
   578 			var ver = this.getInternetExplorerVersion();
   595 			var ver = this.getInternetExplorerVersion();
   579 			if (ver > -1) {
   596 			if (ver > -1) {
   580 				if (ver >= 8)
   597 				if (ver >= 8) {
   581 					msg = "You're using a recent copy of Windows Internet Explorer.";
   598 					msg = "You're using a recent copy of Windows Internet Explorer.";
   582 				else
   599 				} else {
   583 					msg = "You should upgrade your copy of Windows Internet Explorer.";
   600 					msg = "You should upgrade your copy of Windows Internet Explorer.";
   584 			}
   601 				}
   585 			alert(msg);
   602 			}
       
   603 			if (globals.alert) {
       
   604 				globals.alert(msg);
       
   605 			}
   586 		},
   606 		},
   587 
   607 
   588 		isIE8orlower: function() {
   608 		isIE8orlower: function() {
   589 			var msg = "0";
   609 			var msg = "0";
   590 			var ver = this.getInternetExplorerVersion();
   610 			var ver = this.getInternetExplorerVersion();
   591 			if (ver > -1) {
   611 			if (ver > -1) {
   592 				if (ver >= 9)
   612 				if (ver >= 9) {
   593 					msg = 0;
   613 					msg = 0;
   594 				else
   614 				} else {
   595 					msg = 1;
   615 					msg = 1;
       
   616 				}
   596 			}
   617 			}
   597 			return msg;
   618 			return msg;
   598 		},
   619 		},
   599 
   620 
   600 		copyToClipboard: function() {
   621 		copyToClipboard: function() {
   601 			return function() {
   622 			return function() {
   602 				var source = $(this);
   623 				var source = $(this);
   603 				source.parents('.btn-group').removeClass('open');
   624 				source.parents('.btn-group').removeClass('open');
   604 				window.prompt(MyAMS.i18n.CLIPBOARD_COPY, source.text());
   625 				if (globals.prompt) {
   605 			}
   626 					globals.prompt(MyAMS.i18n.CLIPBOARD_COPY, source.text());
       
   627 				}
       
   628 			};
   606 		}
   629 		}
   607 	};
   630 	};
   608 
   631 
   609 
   632 
   610 	/**
   633 	/**
   613 	MyAMS.error = {
   636 	MyAMS.error = {
   614 
   637 
   615 		/**
   638 		/**
   616 		 * Default JQuery AJAX error handler
   639 		 * Default JQuery AJAX error handler
   617 		 */
   640 		 */
   618 		ajax: function(event, request /*, settings*/) {
   641 		ajax: function(event, response, request, error) {
   619 			if (request.statusText == 'OK')
   642 			if (response.statusText === 'OK') {
   620 				return;
   643 				return;
   621 			var response = ams.ajax.getResponse(request);
   644 			}
   622 			if (response.content_type == 'json') {
   645 			var ajax_response = ams.ajax.getResponse(response);
   623 				ams.ajax.handleJSON(response.data);
   646 			if (ajax_response.content_type === 'json') {
       
   647 				ams.ajax.handleJSON(ajax_response.data);
   624 			} else {
   648 			} else {
   625 				var title = event.statusText || event.type;
   649 				var title = event.statusText || event.type;
   626 				var message = request.responseText;
   650 				var message = response.responseText;
   627 				ams.skin.messageBox('error', {
   651 				ams.skin.messageBox('error', {
   628 					title: ams.i18n.ERROR_OCCURED,
   652 					title: ams.i18n.ERROR_OCCURED,
   629 					content: '<h4>' + title + '</h4><p>' + message + '</p>',
   653 					content: '<h4>' + title + '</h4><p>' + message + '</p>',
   630 					icon: 'fa fa-warning animated shake',
   654 					icon: 'fa fa-warning animated shake',
   631 					timeout: 10000
   655 					timeout: 10000
   632 				});
   656 				});
   633 			}
   657 			}
   634 			if (window.console) {
   658 			if (globals.console) {
   635 				console.error(event);
   659 				globals.console.error(event);
   636 				console.debug(request);
   660 				globals.console.debug(response);
   637 			}
   661 			}
   638 		},
   662 		},
   639 
   663 
   640 		/**
   664 		/**
   641 		 * Show AJAX error
   665 		 * Show AJAX error
   642 		 */
   666 		 */
   643 		show: function(request, status, error) {
   667 		show: function(request, status, error) {
   644 			if (!error)
   668 			if (!error) {
   645 				return;
   669 				return;
       
   670 			}
   646 			var response = ams.ajax.getResponse(request);
   671 			var response = ams.ajax.getResponse(request);
   647 			if (response.content_type == 'json') {
   672 			if (response.content_type === 'json') {
   648 				ams.ajax.handleJSON(response.data);
   673 				ams.ajax.handleJSON(response.data);
   649 			} else {
   674 			} else {
   650 				ams.skin.messageBox('error', {
   675 				ams.skin.messageBox('error', {
   651 					title: ams.i18n.ERRORS_OCCURED,
   676 					title: ams.i18n.ERRORS_OCCURED,
   652 					content: '<h4>' + status + '</h4><p>' + error + '</p>',
   677 					content: '<h4>' + status + '</h4><p>' + error + '</p>',
   653 					icon: "fa fa-warning animated shake",
   678 					icon: "fa fa-warning animated shake",
   654 					timeout: 10000
   679 					timeout: 10000
   655 				});
   680 				});
   656 			}
   681 			}
   657 			if (window.console) {
   682 			if (globals.console) {
   658 				console.error(error);
   683 				globals.console.error(error);
   659 				console.debug(request);
   684 				globals.console.debug(request);
   660 			}
   685 			}
   661 		}
   686 		}
   662 	};
   687 	};
   663 
   688 
   664 
   689 
   676 		 *   argument of this callback is a boolean value indicating if the script was just downloaded (true)
   701 		 *   argument of this callback is a boolean value indicating if the script was just downloaded (true)
   677 		 *   or if the requested object was already loaded (false)
   702 		 *   or if the requested object was already loaded (false)
   678 		 * @options: callback options
   703 		 * @options: callback options
   679 		 */
   704 		 */
   680 		check: function(checker, source, callback, options) {
   705 		check: function(checker, source, callback, options) {
   681 			if (typeof(callback) == 'object') {
   706 			if (typeof(callback) === 'object') {
   682 				options = callback;
   707 				options = callback;
   683 				callback = undefined;
   708 				callback = undefined;
   684 			}
   709 			}
   685 			var defaults = {
   710 			var defaults = {
   686 				async: typeof(callback) == 'function'
   711 				async: typeof(callback) === 'function'
   687 			};
   712 			};
   688 			var settings = $.extend({}, defaults, options);
   713 			var settings = $.extend({}, defaults, options);
   689 			if (checker === undefined) {
   714 			if (checker === undefined) {
   690 				ams.getScript(source, function() {
   715 				ams.getScript(source, function() {
   691 					if (typeof(callback) == 'function')
   716 					if (typeof(callback) === 'function') {
   692 						callback(true, options);
   717 						callback(true, options);
       
   718 					}
   693 				}, settings);
   719 				}, settings);
   694 			} else {
   720 			} else {
   695 				if (typeof(callback) == 'function')
   721 				if (typeof(callback) === 'function') {
   696 					callback(false, options);
   722 					callback(false, options);
       
   723 				}
   697 			}
   724 			}
   698 		},
   725 		},
   699 
   726 
   700 		/**
   727 		/**
   701 		 * Get address relative to current page
   728 		 * Get address relative to current page
   725 		 * @param event: the source event
   752 		 * @param event: the source event
   726 		 * @param request: the request
   753 		 * @param request: the request
   727 		 * @param options: AJAX options
   754 		 * @param options: AJAX options
   728 		 */
   755 		 */
   729 		progress: function(event) {
   756 		progress: function(event) {
   730 			if (!event.lengthComputable)
   757 			if (!event.lengthComputable) {
   731 				return;
   758 				return;
   732 			if (event.loaded >= event.total)
   759 			}
       
   760 			if (event.loaded >= event.total) {
   733 				return;
   761 				return;
   734 			console.log(parseInt((event.loaded / event.total * 100), 10) + "%");
   762 			}
       
   763 			if (globals.console) {
       
   764 				globals.console.log(parseInt((event.loaded / event.total * 100), 10) + "%");
       
   765 			}
   735 		},
   766 		},
   736 
   767 
   737 		/**
   768 		/**
   738 		 * Post data to given URL
   769 		 * Post data to given URL
   739 		 */
   770 		 */
   740 		post: function(url, data, options, callback) {
   771 		post: function(url, data, options, callback) {
   741 			if (url.startsWith(window.location.protocol))
   772 			var addr;
   742 				var addr = url;
   773 			if (url.startsWith(window.location.protocol)) {
   743 			else
   774 				addr = url;
       
   775 			} else {
   744 				addr = this.getAddr() + url;
   776 				addr = this.getAddr() + url;
   745 			if (typeof(options) == 'function') {
   777 			}
       
   778 			if (typeof(options) === 'function') {
   746 				callback = options;
   779 				callback = options;
   747 				options = {}
   780 				options = {};
   748 			} else if (!options) {
   781 			} else if (!options) {
   749 				options = {};
   782 				options = {};
   750 			}
   783 			}
   751 			if (typeof(callback) == 'undefined')
   784 			if (typeof(callback) === 'undefined') {
   752 				callback = options.callback;
   785 				callback = options.callback;
   753 			if (typeof(callback) == 'string')
   786 			}
       
   787 			if (typeof(callback) === 'string') {
   754 				callback = ams.getFunctionByName(callback);
   788 				callback = ams.getFunctionByName(callback);
       
   789 			}
   755 			delete options.callback;
   790 			delete options.callback;
   756 
   791 
   757 			var result = undefined;
   792 			var result;
   758 			var defaults = {
   793 			var defaults = {
   759 				url: addr,
   794 				url: addr,
   760 				type: 'post',
   795 				type: 'post',
   761 				cache: false,
   796 				cache: false,
   762 				async: typeof(callback) == 'function',
   797 				async: typeof(callback) === 'function',
   763 				data: $.param(data),
   798 				data: $.param(data),
   764 				dataType: 'json',
   799 				dataType: 'json',
   765 				success: callback || function(data /*, status*/) {
   800 				success: callback || function(data /*, status*/) {
   766 					result = data.result;
   801 					result = data.result;
   767 				},
   802 				}
   768 				error: ams.error.show
       
   769 			};
   803 			};
   770 			var settings = $.extend({}, defaults, options);
   804 			var settings = $.extend({}, defaults, options);
   771 			$.ajax(settings);
   805 			$.ajax(settings);
   772 			return result;
   806 			return result;
   773 		},
   807 		},
   790 				} else if (content_type.startsWith('text/xml')) {
   824 				} else if (content_type.startsWith('text/xml')) {
   791 					data_type = 'xml';
   825 					data_type = 'xml';
   792 					result = request.responseText;
   826 					result = request.responseText;
   793 				} else {
   827 				} else {
   794 					result = request.responseJSON;
   828 					result = request.responseJSON;
   795 					if (result)
   829 					if (result) {
   796 						data_type = 'json';
   830 						data_type = 'json';
   797 					else {
   831 					} else {
   798 						try {
   832 						try {
   799 							result = JSON.parse(request.responseText);
   833 							result = JSON.parse(request.responseText);
   800 							data_type = 'json';
   834 							data_type = 'json';
   801 						} catch (e) {
   835 						} catch (e) {
   802 							result = request.responseText;
   836 							result = request.responseText;
   842 		handleJSON: function(result, form, target) {
   876 		handleJSON: function(result, form, target) {
   843 			var status = result.status;
   877 			var status = result.status;
   844 			var url;
   878 			var url;
   845 			switch (status) {
   879 			switch (status) {
   846 				case 'alert':
   880 				case 'alert':
   847 					alert(result.alert.title + '\n\n' + result.alert.content);
   881 					if (globals.alert) {
       
   882 						globals.alert(result.alert.title + '\n\n' + result.alert.content);
       
   883 					}
   848 					break;
   884 					break;
   849 				case 'error':
   885 				case 'error':
   850 					ams.form.showErrors(form, result);
   886 					ams.form.showErrors(form, result);
   851 					break;
   887 					break;
   852 				case 'info':
   888 				case 'info':
   853 				case 'success':
   889 				case 'success':
   854 					if (result.close_form != false)
   890 					if (result.close_form !== false) {
   855 						ams.dialog.close(form);
   891 						ams.dialog.close(form);
       
   892 					}
   856 					break;
   893 					break;
   857 				case 'message':
   894 				case 'message':
   858 				case 'messagebox':
   895 				case 'messagebox':
   859 					break;
   896 					break;
   860 				case 'notify':
   897 				case 'notify':
   861 				case 'callback':
   898 				case 'callback':
   862 				case 'callbacks':
   899 				case 'callbacks':
   863 					if (result.close_form != false)
   900 					if (result.close_form !== false) {
   864 						ams.dialog.close(form);
   901 						ams.dialog.close(form);
       
   902 					}
   865 					break;
   903 					break;
   866 				case 'modal':
   904 				case 'modal':
   867 					ams.dialog.open(result.location);
   905 					ams.dialog.open(result.location);
   868 					break;
   906 					break;
   869 				case 'reload':
   907 				case 'reload':
   870 					if (result.close_form != false)
   908 					if (result.close_form !== false) {
   871 						ams.dialog.close(form);
   909 						ams.dialog.close(form);
       
   910 					}
   872 					url = result.location || window.location.hash;
   911 					url = result.location || window.location.hash;
   873 					if (url.startsWith('#'))
   912 					if (url.startsWith('#')) {
   874 						url = url.substr(1);
   913 						url = url.substr(1);
       
   914 					}
   875 					ams.skin.loadURL(url, result.target || target || '#content');
   915 					ams.skin.loadURL(url, result.target || target || '#content');
   876 					break;
   916 					break;
   877 				case 'redirect':
   917 				case 'redirect':
   878 					if (result.close_form == true)
   918 					if (result.close_form === true) {
   879 						ams.dialog.close(form);
   919 						ams.dialog.close(form);
       
   920 					}
   880 					url = result.location || window.location.href;
   921 					url = result.location || window.location.href;
   881 					if (result.window) {
   922 					if (result.window) {
   882 						window.open(url, result.window, result.options);
   923 						window.open(url, result.window, result.options);
   883 					} else {
   924 					} else {
   884 						if (window.location.href == url) {
   925 						if (window.location.href === url) {
   885 							window.location.reload(true);
   926 							window.location.reload(true);
   886 						} else {
   927 						} else {
   887 							window.location.href = url;
   928 							window.location.href = url;
   888 						}
   929 						}
   889 					}
   930 					}
   890 					break;
   931 					break;
   891 				default:
   932 				default:
   892 					console.log("Unhandled status: " + status);
   933 					if (globals.console) {
   893 					break;
   934 						globals.console.log("Unhandled status: " + status);
   894 			}
   935 					}
       
   936 			}
       
   937 
       
   938 			var index;
       
   939 			var content;
       
   940 			var container;
   895 			if (result.content) {
   941 			if (result.content) {
   896 				var content = result.content;
   942 				content = result.content;
   897 				var container = $(content.target || target || form || '#content');
   943 				container = $(content.target || target || form || '#content');
   898 				if (content.raw == true) {
   944 				if (content.raw === true) {
   899 					container.text(content.text);
   945 					container.text(content.text);
   900 				} else {
   946 				} else {
   901 					container.html(content.html);
   947 					container.html(content.html);
   902 					ams.initContent(container);
   948 					ams.initContent(container);
   903 				}
   949 				}
   904 				if (!content.keep_hidden)
   950 				if (!content.keep_hidden) {
   905 					container.removeClass('hidden');
   951 					container.removeClass('hidden');
       
   952 				}
   906 			}
   953 			}
   907 			if (result.contents) {
   954 			if (result.contents) {
   908 				var contents = result.contents;
   955 				var contents = result.contents;
   909 				for (var index in contents) {
   956 				for (index=0; index < contents.length; index++) {
   910 					content = contents[index];
   957 					content = contents[index];
   911 					container = $(content.target);
   958 					container = $(content.target);
   912 					if (content.raw == true) {
   959 					if (content.raw === true) {
   913 						container.text(content.text);
   960 						container.text(content.text);
   914 					} else {
   961 					} else {
   915 						container.html(content.html);
   962 						container.html(content.html);
   916 						ams.initContent(container);
   963 						ams.initContent(container);
   917 					}
   964 					}
   918 					if (!content.keep_hidden)
   965 					if (!content.keep_hidden) {
   919 						container.removeClass('hidden');
   966 						container.removeClass('hidden');
   920 				}
   967 					}
   921 			}
   968 				}
       
   969 			}
       
   970 
       
   971 			var message;
   922 			if (result.message) {
   972 			if (result.message) {
   923 				var message = result.message;
   973 				message = result.message;
   924 				if (typeof(message) == 'string') {
   974 				if (typeof(message) === 'string') {
   925 					if ((status == 'info') || (status == 'success'))
   975 					if ((status === 'info') || (status === 'success')) {
   926 						ams.skin.smallBox(status,
   976 						ams.skin.smallBox(status,
   927 										  {title: message,
   977 										  {
   928 										   icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
   978 											  title: message,
   929 										   timeout: 3000});
   979 											  icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
   930 					else
   980 											  timeout: 3000
       
   981 										  });
       
   982 					} else {
   931 						ams.skin.alert($(form || '#content'), status, message);
   983 						ams.skin.alert($(form || '#content'), status, message);
   932 				} else
   984 					}
       
   985 				} else {
   933 					ams.skin.alert($(message.target || target || form || '#content'),
   986 					ams.skin.alert($(message.target || target || form || '#content'),
   934 								   message.status || 'success',
   987 								   message.status || 'success',
   935 								   message.header,
   988 								   message.header,
   936 								   message.body,
   989 								   message.body,
   937 								   message.subtitle);
   990 								   message.subtitle);
       
   991 				}
   938 			}
   992 			}
   939 			if (result.smallbox) {
   993 			if (result.smallbox) {
   940 				ams.skin.smallBox(result.smallbox_status || status,
   994 				ams.skin.smallBox(result.smallbox_status || status,
   941 								  {title: result.smallbox,
   995 								  {title: result.smallbox,
   942 								   icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
   996 								   icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
   943 								   timeout: 3000});
   997 								   timeout: 3000});
   944 			}
   998 			}
   945 			if (result.messagebox) {
   999 			if (result.messagebox) {
   946 				message = result.messagebox;
  1000 				message = result.messagebox;
   947 				if (typeof(message) == 'string')
  1001 				if (typeof(message) === 'string') {
   948 					ams.skin.messageBox('info',
  1002 					ams.skin.messageBox('info',
   949 										{title: ams.i18n.ERROR_OCCURED,
  1003 										{
   950 										 content: message,
  1004 											title: ams.i18n.ERROR_OCCURED,
   951 										 timeout: 10000});
  1005 											content: message,
   952 				else {
  1006 											timeout: 10000
       
  1007 										});
       
  1008 				} else {
   953 					var message_status = message.status || 'info';
  1009 					var message_status = message.status || 'info';
   954 					if (message_status == 'error' && form && target)
  1010 					if (message_status === 'error' && form && target) {
   955 						ams.executeFunctionByName(form.data('ams-form-submit-error') || 'MyAMS.form.finalizeSubmitOnError', form, target);
  1011 						ams.executeFunctionByName(form.data('ams-form-submit-error') || 'MyAMS.form.finalizeSubmitOnError', form, target);
       
  1012 					}
   956 					ams.skin.messageBox(message_status,
  1013 					ams.skin.messageBox(message_status,
   957 										{title: message.title || ams.i18n.ERROR_OCCURED,
  1014 										{title: message.title || ams.i18n.ERROR_OCCURED,
   958 										 content: message.content,
  1015 										 content: message.content,
   959 										 icon: message.icon,
  1016 										 icon: message.icon,
   960 										 number: message.number,
  1017 										 number: message.number,
   961 										 timeout: message.timeout == null ? undefined : (message.timeout || 10000)});
  1018 										 timeout: message.timeout === null ? undefined : (message.timeout || 10000)});
   962 				}
  1019 				}
   963 			}
  1020 			}
   964 			if (result.event)
  1021 			if (result.event) {
   965 				form.trigger(result.event, result.event_options);
  1022 				form.trigger(result.event, result.event_options);
   966 			if (result.callback)
  1023 			}
       
  1024 			if (result.callback) {
   967 				ams.executeFunctionByName(result.callback, form, result.options);
  1025 				ams.executeFunctionByName(result.callback, form, result.options);
       
  1026 			}
   968 			if (result.callbacks) {
  1027 			if (result.callbacks) {
   969 				for (index in result.callbacks) {
  1028 				var callback;
   970 					if (!$.isNumeric(index))
  1029 				for (index=0; index < result.callbacks.length; index++) {
   971 						continue;
  1030 					callback = result.callbacks[index];
   972 					var callback = result.callbacks[index];
       
   973 					ams.executeFunctionByName(callback, form, callback.options);
  1031 					ams.executeFunctionByName(callback, form, callback.options);
   974 				}
  1032 				}
   975 			}
  1033 			}
   976 		}
  1034 		}
   977 	};
  1035 	};
  1000 		 *  - @method: name of JSON-RPC procedure to call
  1058 		 *  - @method: name of JSON-RPC procedure to call
  1001 		 *  - @options: additional JSON-RPC procedure parameters
  1059 		 *  - @options: additional JSON-RPC procedure parameters
  1002 		 *  - @callback: name of a callback which will be called on server response
  1060 		 *  - @callback: name of a callback which will be called on server response
  1003 		 */
  1061 		 */
  1004 		query: function(query, method, options, callback) {
  1062 		query: function(query, method, options, callback) {
  1005 			ams.ajax.check($.jsonRpc,
  1063 			ams.ajax.check($.jsonRPC,
  1006 						   ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
  1064 						   ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
  1007 						   function() {
  1065 						   function() {
  1008 								var result;
  1066 								if (typeof(options) === 'function') {
  1009 								if (typeof(options) == 'function') {
       
  1010 									callback = options;
  1067 									callback = options;
  1011 									options = {};
  1068 									options = {};
  1012 								}
  1069 								}
  1013 								else if (!options)
  1070 								else if (!options) {
  1014 									options = {};
  1071 									options = {};
  1015 								if (typeof(callback) == 'undefined')
  1072 								}
       
  1073 								if (callback === 'undefined') {
  1016 									callback = options.callback;
  1074 									callback = options.callback;
  1017 								if (typeof(callback) == 'string')
  1075 								}
       
  1076 								if (typeof(callback) === 'string') {
  1018 									callback = ams.getFunctionByName(callback);
  1077 									callback = ams.getFunctionByName(callback);
       
  1078 								}
  1019 								delete options.callback;
  1079 								delete options.callback;
  1020 
  1080 
  1021 								var params = {};
  1081 								var params = {};
  1022 								if (typeof(query) == 'string')
  1082 								if (typeof(query) === 'string') {
  1023 									params['query'] = query;
  1083 									params.query = query;
  1024 								else if (typeof(query) == 'object')
  1084 								} else if (typeof(query) === 'object') {
  1025 									$.extend(params, query);
  1085 									$.extend(params, query);
       
  1086 								}
  1026 								$.extend(params, options);
  1087 								$.extend(params, options);
  1027 
  1088 
  1028 								var settings = {
  1089 								var result;
  1029 									url: ams.jsonrpc.getAddr(options.url),
  1090 								var defaults = {
  1030 									type: 'post',
  1091 									id: new Date().getTime(),
  1031 									cache: false,
       
  1032 									method: method,
       
  1033 									params: params,
  1092 									params: params,
  1034 									async: typeof(callback) == 'function',
  1093 									success: callback || function(data) {
  1035 									success: callback || function(data /*, status*/) {
  1094 										result = data;
  1036 										result = data.result;
       
  1037 									},
  1095 									},
  1038 									error: ams.error.show
  1096 									error: ams.error.show
  1039 								};
  1097 								};
  1040 								$.jsonRpc(settings);
  1098 								var settings = $.extend({}, defaults, options);
       
  1099 								$.jsonRPC.withOptions({
       
  1100 									endPoint: ams.jsonrpc.getAddr(options.url),
       
  1101 									namespace: options.namespace,
       
  1102 									cache: false
       
  1103 								}, function() {
       
  1104 									$.jsonRPC.request(method, settings);
       
  1105 								});
  1041 								return result;
  1106 								return result;
  1042 						   });
  1107 						   });
  1043 		},
  1108 		},
  1044 
  1109 
  1045 		/**
  1110 		/**
  1052 		 */
  1117 		 */
  1053 		post: function(method, data, options, callback) {
  1118 		post: function(method, data, options, callback) {
  1054 			ams.ajax.check($.jsonRPC,
  1119 			ams.ajax.check($.jsonRPC,
  1055 						   ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
  1120 						   ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
  1056 						   function() {
  1121 						   function() {
  1057 								if (typeof(options) == 'function') {
  1122 								if (typeof(options) === 'function') {
  1058 									callback = options;
  1123 									callback = options;
  1059 									options = {};
  1124 									options = {};
  1060 								}
  1125 								}
  1061 								else if (!options)
  1126 								else if (!options) {
  1062 									options = {};
  1127 									options = {};
  1063 								if (typeof(callback) == 'undefined')
  1128 								}
       
  1129 								if (typeof(callback) === 'undefined') {
  1064 									callback = options.callback;
  1130 									callback = options.callback;
  1065 								if (typeof(callback) == 'string')
  1131 								}
       
  1132 								if (typeof(callback) === 'string') {
  1066 									callback = ams.getFunctionByName(callback);
  1133 									callback = ams.getFunctionByName(callback);
       
  1134 								}
  1067 								delete options.callback;
  1135 								delete options.callback;
  1068 
  1136 
  1069 								var result;
  1137 								var result;
  1070 								var defaults = {
  1138 								var defaults = {
  1071 									id: new Date().getTime(),
  1139 									id: new Date().getTime(),
  1114 		 */
  1182 		 */
  1115 		post: function(url, method, data, options, callback) {
  1183 		post: function(url, method, data, options, callback) {
  1116 			ams.ajax.check($.xmlrpc,
  1184 			ams.ajax.check($.xmlrpc,
  1117 						   ams.baseURL + 'ext/jquery-xmlrpc' + ams.devext + '.js',
  1185 						   ams.baseURL + 'ext/jquery-xmlrpc' + ams.devext + '.js',
  1118 						   function() {
  1186 						   function() {
  1119 								var result;
  1187 								if (typeof(options) === 'function') {
  1120 								if (typeof(options) == 'function') {
       
  1121 									callback = options;
  1188 									callback = options;
  1122 									options = {};
  1189 									options = {};
  1123 								}
  1190 								}
  1124 								else if (!options)
  1191 								else if (!options) {
  1125 									options = {};
  1192 									options = {};
  1126 								if (typeof(callback) == 'undefined')
  1193 								}
       
  1194 								if (typeof(callback) === 'undefined') {
  1127 									callback = options.callback;
  1195 									callback = options.callback;
  1128 								if (typeof(callback) == 'string')
  1196 								}
       
  1197 								if (typeof(callback) === 'string') {
  1129 									callback = ams.getFunctionByName(callback);
  1198 									callback = ams.getFunctionByName(callback);
       
  1199 								}
  1130 								delete options.callback;
  1200 								delete options.callback;
  1131 
  1201 
       
  1202 								var result;
  1132 								var defaults = {
  1203 								var defaults = {
  1133 									url: ams.xmlrpc.getAddr(url),
  1204 									url: ams.xmlrpc.getAddr(url),
  1134 									methodName: method,
  1205 									methodName: method,
  1135 									params: data,
  1206 									params: data,
  1136 									success: callback || function(response /*, status, xhr*/) {
  1207 									success: callback || function(response /*, status, xhr*/) {
  1156 		 *
  1227 		 *
  1157 		 * @param element: the parent element
  1228 		 * @param element: the parent element
  1158 		 */
  1229 		 */
  1159 		init: function(element) {
  1230 		init: function(element) {
  1160 			// Activate form changes if required
  1231 			// Activate form changes if required
  1161 			if (ams.warn_on_form_change)
  1232 			var forms;
  1162 				var forms = $('FORM[data-ams-warn-on-change!="false"]', element);
  1233 			if (ams.warn_on_form_change) {
  1163 			else
  1234 				forms = $('FORM[data-ams-warn-on-change!="false"]', element);
       
  1235 			} else {
  1164 				forms = $('FORM[data-ams-warn-on-change="true"]', element);
  1236 				forms = $('FORM[data-ams-warn-on-change="true"]', element);
       
  1237 			}
  1165 			forms.each(function() {
  1238 			forms.each(function() {
  1166 				var form = $(this);
  1239 				var form = $(this);
  1167 				$('INPUT[type="text"], ' +
  1240 				$('INPUT[type="text"], ' +
  1168 				  'INPUT[type="checkbox"], ' +
  1241 				  'INPUT[type="checkbox"], ' +
  1169 				  'INPUT[type="radio"], ' +
  1242 				  'INPUT[type="radio"], ' +
  1183 				});
  1256 				});
  1184 			});
  1257 			});
  1185 		},
  1258 		},
  1186 
  1259 
  1187 		/**
  1260 		/**
       
  1261 		 * Set focus to first container input
       
  1262 		 */
       
  1263 		setFocus: function(container) {
       
  1264 			var focused = $('[data-ams-focus-target]', container).first();
       
  1265 			if (!focused.exists()) {
       
  1266 				focused = $('input, select', container).first();
       
  1267 			}
       
  1268 			if (focused.exists()) {
       
  1269 				if (focused.hasClass('select2')) {
       
  1270 					setTimeout(function() {
       
  1271 						focused.select2('focus');
       
  1272 						focused.select2('open');
       
  1273 					}, 100);
       
  1274 				} else {
       
  1275 					focused.focus();
       
  1276 				}
       
  1277 			}
       
  1278 		},
       
  1279 
       
  1280 		/**
  1188 		 * Check for modified forms before exiting
  1281 		 * Check for modified forms before exiting
  1189 		 */
  1282 		 */
  1190 		checkBeforeUnload: function() {
  1283 		checkBeforeUnload: function() {
  1191 			var forms = $('FORM[data-ams-form-changed="true"]');
  1284 			var forms = $('FORM[data-ams-form-changed="true"]');
  1192 			if (forms.exists()) {
  1285 			if (forms.exists()) {
  1196 
  1289 
  1197 		/**
  1290 		/**
  1198 		 * Check for modified forms before loading new inner content
  1291 		 * Check for modified forms before loading new inner content
  1199 		 */
  1292 		 */
  1200 		confirmChangedForm: function(element, callback) {
  1293 		confirmChangedForm: function(element, callback) {
  1201 			if (typeof(element) == 'function') {
  1294 			if (typeof(element) === 'function') {
  1202 				callback = element;
  1295 				callback = element;
  1203 				element = undefined;
  1296 				element = undefined;
  1204 			}
  1297 			}
  1205 			var forms = $('FORM[data-ams-form-changed="true"]', element);
  1298 			var forms = $('FORM[data-ams-form-changed="true"]', element);
  1206 			if (forms.exists()) {
  1299 			if (forms.exists()) {
  1207 				ams.skin.bigBox({
  1300 				ams.skin.bigBox({
  1208 					title: ams.i18n.WARNING,
  1301 					title: ams.i18n.WARNING,
  1209 					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + ams.i18n.FORM_CHANGED_WARNING,
  1302 					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + ams.i18n.FORM_CHANGED_WARNING,
  1210 					buttons: ams.i18n.BTN_OK_CANCEL
  1303 					buttons: ams.i18n.BTN_OK_CANCEL
  1211 				}, function(button) {
  1304 				}, function(button) {
  1212 					if (button == ams.i18n.BTN_OK)
  1305 					if (button === ams.i18n.BTN_OK) {
  1213 						callback.call(element);
  1306 						callback.call(element);
       
  1307 					}
  1214 				});
  1308 				});
  1215 			} else {
  1309 			} else {
  1216 				callback.call(element);
  1310 				callback.call(element);
  1217 			}
  1311 			}
  1218 		},
  1312 		},
  1221 		 * Submit given form
  1315 		 * Submit given form
  1222 		 */
  1316 		 */
  1223 		submit: function(form, handler, submit_options) {
  1317 		submit: function(form, handler, submit_options) {
  1224 			// Check params
  1318 			// Check params
  1225 			form = $(form);
  1319 			form = $(form);
  1226 			if (!form.exists())
  1320 			if (!form.exists()) {
  1227 				return false;
  1321 				return false;
  1228 			if (typeof(handler) == 'object') {
  1322 			}
       
  1323 			if (typeof(handler) === 'object') {
  1229 				submit_options = handler;
  1324 				submit_options = handler;
  1230 				handler = undefined;
  1325 				handler = undefined;
  1231 			}
  1326 			}
  1232 			// Prevent multiple submits of the same form
  1327 			// Prevent multiple submits of the same form
  1233 			if (form.data('submitted')) {
  1328 			if (form.data('submitted')) {
  1240 					});
  1335 					});
  1241 				}
  1336 				}
  1242 				return false;
  1337 				return false;
  1243 			}
  1338 			}
  1244 			// Check submit validators
  1339 			// Check submit validators
  1245 			if (!ams.form._checkSubmitValidators(form))
  1340 			if (!ams.form._checkSubmitValidators(form)) {
  1246 				return false;
  1341 				return false;
       
  1342 			}
  1247 			// Remove remaining status messages
  1343 			// Remove remaining status messages
  1248 			$('.alert-danger, SPAN.state-error', form).remove();
  1344 			$('.alert-danger, SPAN.state-error', form).not('.persistent').remove();
  1249 			$('.state-error', form).removeClassPrefix('state-');
  1345 			$('.state-error', form).removeClassPrefix('state-');
  1250 			// Check submit button
  1346 			// Check submit button
  1251 			var button = $(form.data('ams-submit-button'));
  1347 			var button = $(form.data('ams-submit-button'));
  1252 			if (button && !button.data('ams-form-hide-loading'))
  1348 			if (button && !button.data('ams-form-hide-loading')) {
  1253 				button.button('loading');
  1349 				button.button('loading');
       
  1350 			}
  1254 			ams.ajax.check($.fn.ajaxSubmit,
  1351 			ams.ajax.check($.fn.ajaxSubmit,
  1255 						   ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js',
  1352 						   ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js',
  1256 						   function() {
  1353 						   function() {
  1257 
  1354 
  1258 								function _submitAjaxForm(form, options) {
  1355 								function _submitAjaxForm(form, options) {
  1259 
  1356 
  1260 									var button;
  1357 									var button;
  1261 									var data = form.data();
  1358 									var data = form.data();
  1262 									var form_options = data.amsFormOptions;
  1359 									var form_options = data.amsFormOptions;
  1263 
  1360 									var form_data;
  1264 									if (submit_options)
  1361 									var form_data_callback;
  1265 										var form_data_callback = submit_options.formDataInitCallback;
  1362 
  1266 									if (form_data_callback)
  1363 									if (submit_options) {
       
  1364 										form_data_callback = submit_options.formDataInitCallback;
       
  1365 									}
       
  1366 									if (form_data_callback) {
  1267 										delete submit_options.formDataInitCallback;
  1367 										delete submit_options.formDataInitCallback;
  1268 									else
  1368 									} else {
  1269 										form_data_callback = data.amsFormDataInitCallback;
  1369 										form_data_callback = data.amsFormDataInitCallback;
       
  1370 									}
  1270 									if (form_data_callback) {
  1371 									if (form_data_callback) {
  1271 										var veto = {};
  1372 										var veto = {};
  1272 										if (typeof(form_data_callback) == 'function')
  1373 										if (typeof(form_data_callback) === 'function') {
  1273 											var form_data = form_data_callback.call(form, veto);
  1374 											form_data = form_data_callback.call(form, veto);
  1274 										else
  1375 										} else {
  1275 											form_data = ams.executeFunctionByName(form_data_callback, form, veto);
  1376 											form_data = ams.executeFunctionByName(form_data_callback, form, veto);
       
  1377 										}
  1276 										if (veto.veto) {
  1378 										if (veto.veto) {
  1277 											button = form.data('ams-submit-button');
  1379 											button = form.data('ams-submit-button');
  1278 											if (button)
  1380 											if (button) {
  1279 												button.button('reset');
  1381 												button.button('reset');
       
  1382 											}
  1280 											ams.form.finalizeSubmitFooter.call(form);
  1383 											ams.form.finalizeSubmitFooter.call(form);
  1281 											return false;
  1384 											return false;
  1282 										}
  1385 										}
  1283 									} else {
  1386 									} else {
  1284 										form_data = data.amsFormData || {};
  1387 										form_data = data.amsFormData || {};
  1290 									if (button) {
  1393 									if (button) {
  1291 										buttonHandler = button.data('ams-form-handler');
  1394 										buttonHandler = button.data('ams-form-handler');
  1292 										buttonTarget = button.data('ams-form-submit-target');
  1395 										buttonTarget = button.data('ams-form-submit-target');
  1293 									}
  1396 									}
  1294 
  1397 
       
  1398 									var url;
  1295 									var form_handler = handler || buttonHandler || data.amsFormHandler || '';
  1399 									var form_handler = handler || buttonHandler || data.amsFormHandler || '';
  1296 									if (form_handler.startsWith(window.location.protocol)) {
  1400 									if (form_handler.startsWith(window.location.protocol)) {
  1297 										var url = form_handler;
  1401 										url = form_handler;
  1298 									} else {
  1402 									} else {
  1299 										var action = form.attr('action').replace(/#/, '');
  1403 										var action = form.attr('action').replace(/#/, '');
  1300 										if (action.startsWith(window.location.protocol))
  1404 										if (action.startsWith(window.location.protocol)) {
  1301 											url = action;
  1405 											url = action;
  1302 										else
  1406 										} else {
  1303 											url = ams.ajax.getAddr() + action;
  1407 											url = ams.ajax.getAddr() + action;
       
  1408 										}
  1304 										url += form_handler;
  1409 										url += form_handler;
  1305 									}
  1410 									}
  1306 
  1411 
  1307 									var target = null;
  1412 									var target = null;
  1308 									if (data.amsFormInitSubmitTarget) {
  1413 									if (submit_options && submit_options.initSubmitTarget) {
  1309 										target = $(buttonTarget || data.amsFormSubmitTarget || '#content');
  1414 										ams.executeFunctionByName(submit_options.initSubmitTarget);
  1310 										ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmit', form, target);
  1415 									} else {
  1311 									} else if (!data.amsFormHideSubmitFooter)
  1416 										if (data.amsFormInitSubmitTarget) {
  1312 										ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmitFooter', form);
  1417 											target = $(buttonTarget || data.amsFormSubmitTarget || '#content');
  1313 
  1418 											ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmit', form, target);
  1314 									var hasUpload = typeof(options.uuid) != 'undefined';
  1419 										} else if (!data.amsFormHideSubmitFooter) {
       
  1420 											ams.executeFunctionByName(data.amsFormInitSubmit || 'MyAMS.form.initSubmitFooter', form);
       
  1421 										}
       
  1422 									}
       
  1423 
       
  1424 									var hasUpload = typeof(options.uuid) !== 'undefined';
  1315 									if (hasUpload) {
  1425 									if (hasUpload) {
  1316 										if (url.indexOf('X-Progress-ID') < 0)
  1426 										if (url.indexOf('X-Progress-ID') < 0) {
  1317 											url += "?X-Progress-ID=" + options.uuid;
  1427 											url += "?X-Progress-ID=" + options.uuid;
       
  1428 										}
  1318 										delete options.uuid;
  1429 										delete options.uuid;
  1319 									}
  1430 									}
  1320 
  1431 
       
  1432 									if (submit_options) {
       
  1433 										form_data = $.extend({}, form_data, submit_options.form_data);
       
  1434 									}
  1321 									var defaults = {
  1435 									var defaults = {
  1322 										url: url,
  1436 										url: url,
  1323 										type: 'post',
  1437 										type: 'post',
  1324 										cache: false,
  1438 										cache: false,
  1325 										data: form_data,
  1439 										data: form_data,
  1326 										dataType: data.amsFormDatatype,
  1440 										dataType: data.amsFormDatatype,
  1327 										beforeSerialize: function(/*form, options*/) {
  1441 										beforeSerialize: function(/*form, options*/) {
  1328 											if (typeof(tinyMCE) != 'undefined')
  1442 											if (typeof(globals.tinyMCE) !== 'undefined') {
  1329 												tinyMCE.triggerSave();
  1443 												globals.tinyMCE.triggerSave();
       
  1444 											}
  1330 										},
  1445 										},
  1331 										beforeSubmit: function(data, form /*, options*/) {
  1446 										beforeSubmit: function(data, form /*, options*/) {
  1332 											form.data('submitted', true);
  1447 											form.data('submitted', true);
  1333 										},
  1448 										},
  1334 										error: function(request, status, error, form) {
  1449 										error: function(request, status, error, form) {
  1335 											if (target)
  1450 											if (target) {
  1336 												ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target);
  1451 												ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target);
       
  1452 											}
  1337 											if (form.is(':visible')) {
  1453 											if (form.is(':visible')) {
  1338 												var button = form.data('ams-submit-button');
  1454 												var button = form.data('ams-submit-button');
  1339 												if (button)
  1455 												if (button) {
  1340 													button.button('reset');
  1456 													button.button('reset');
       
  1457 												}
  1341 												ams.form.finalizeSubmitFooter.call(form);
  1458 												ams.form.finalizeSubmitFooter.call(form);
  1342 											}
  1459 											}
  1343 											form.data('submitted', false);
  1460 											form.data('submitted', false);
  1344 											form.removeData('ams-submit-button');
  1461 											form.removeData('ams-submit-button');
  1345 										},
  1462 										},
  1346 										iframe: hasUpload
  1463 										iframe: hasUpload
  1347 									}
  1464 									};
  1348 									var download_target = data.amsFormDownloadTarget;
  1465 									var download_target = (submit_options && submit_options.downloadTarget) || data.amsFormDownloadTarget;
  1349 									if (download_target) {
  1466 									if (download_target) {
  1350 										var iframe = $('iframe[name="' + download_target + '"]');
  1467 										var iframe = $('iframe[name="' + download_target + '"]');
  1351 										if (!iframe.exists())
  1468 										if (!iframe.exists()) {
  1352 											iframe = $('<iframe></iframe>').hide()
  1469 											iframe = $('<iframe></iframe>').hide()
  1353 																		   .attr('name', download_target)
  1470 																		   .attr('name', download_target)
  1354 																		   .appendTo(form);
  1471 																		   .appendTo(form);
       
  1472 										}
  1355 										defaults = $.extend({}, defaults, {
  1473 										defaults = $.extend({}, defaults, {
  1356 											iframe: true,
  1474 											iframe: true,
  1357 											iframeTarget: iframe,
  1475 											iframeTarget: iframe,
  1358 											success: function(result, status, request, form) {
  1476 											success: function(result, status, request, form) {
  1359 												var modal = $(form).parents('.modal-dialog');
  1477 												var modal = $(form).parents('.modal-dialog');
  1360 												if (modal.exists()) {
  1478 												if (modal.exists()) {
  1361 													ams.dialog.close(form);
  1479 													ams.dialog.close(form);
  1362 												} else {
  1480 												} else {
  1363 													var callback;
  1481 													var callback;
  1364 													var button = form.data('ams-submit-button');
  1482 													var button = form.data('ams-submit-button');
  1365 													if (button)
  1483 													if (button) {
  1366 														callback = button.data('ams-form-submit-callback');
  1484 														callback = button.data('ams-form-submit-callback');
  1367 													if (!callback)
  1485 													}
       
  1486 													if (!callback) {
  1368 														callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback;
  1487 														callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback;
       
  1488 													}
  1369 													callback.call(form, result, status, request, form);
  1489 													callback.call(form, result, status, request, form);
  1370 													if (form.is(':visible') && button)
  1490 													if (form.is(':visible') && button) {
  1371 														button.button('reset');
  1491 														button.button('reset');
       
  1492 													}
  1372 													form.data('submitted', false);
  1493 													form.data('submitted', false);
  1373 													form.removeData('ams-submit-button');
  1494 													form.removeData('ams-submit-button');
  1374 													form.removeAttr('data-ams-form-changed');
  1495 													form.removeAttr('data-ams-form-changed');
  1375 												}
  1496 												}
  1376 											}
  1497 											}
  1377 										});
  1498 										});
  1378 									} else {
  1499 									} else {
  1379 										defaults = $.extend({}, defaults, {
  1500 										defaults = $.extend({}, defaults, {
  1380 											error: function(request, status, error, form) {
  1501 											error: function(request, status, error, form) {
  1381 												if (target)
  1502 												if (target) {
  1382 													ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target);
  1503 													ams.executeFunctionByName(data.amsFormSubmitError || 'MyAMS.form.finalizeSubmitOnError', form, target);
       
  1504 												}
  1383 												if (form.is(':visible')) {
  1505 												if (form.is(':visible')) {
  1384 													var button = form.data('ams-submit-button');
  1506 													var button = form.data('ams-submit-button');
  1385 													if (button)
  1507 													if (button) {
  1386 														button.button('reset');
  1508 														button.button('reset');
       
  1509 													}
  1387 													ams.form.finalizeSubmitFooter.call(form);
  1510 													ams.form.finalizeSubmitFooter.call(form);
  1388 												}
  1511 												}
  1389 												form.data('submitted', false);
  1512 												form.data('submitted', false);
  1390 												form.removeData('ams-submit-button');
  1513 												form.removeData('ams-submit-button');
  1391 											},
  1514 											},
  1392 											success: function(result, status, request, form) {
  1515 											success: function(result, status, request, form) {
  1393 												var callback;
  1516 												var callback;
  1394 												var button = form.data('ams-submit-button');
  1517 												var button = form.data('ams-submit-button');
  1395 												if (button)
  1518 												if (button) {
  1396 													callback = button.data('ams-form-submit-callback');
  1519 													callback = button.data('ams-form-submit-callback');
  1397 												if (!callback)
  1520 												}
       
  1521 												if (!callback) {
  1398 													callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback;
  1522 													callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback;
       
  1523 												}
  1399 												callback.call(form, result, status, request, form);
  1524 												callback.call(form, result, status, request, form);
  1400 												if (form.is(':visible') && button)
  1525 												if (form.is(':visible') && button) {
  1401 													button.button('reset');
  1526 													button.button('reset');
       
  1527 												}
  1402 												form.data('submitted', false);
  1528 												form.data('submitted', false);
  1403 												form.removeData('ams-submit-button');
  1529 												form.removeData('ams-submit-button');
  1404 												form.removeAttr('data-ams-form-changed');
  1530 												form.removeAttr('data-ams-form-changed');
  1405 											},
  1531 											},
  1406 											iframe: hasUpload
  1532 											iframe: hasUpload
  1413 										var modal = $(form).parents('.modal-dialog');
  1539 										var modal = $(form).parents('.modal-dialog');
  1414 										if (modal.exists()) {
  1540 										if (modal.exists()) {
  1415 											ams.dialog.close(form);
  1541 											ams.dialog.close(form);
  1416 										} else {
  1542 										} else {
  1417 											ams.form.finalizeSubmitFooter.call(form);
  1543 											ams.form.finalizeSubmitFooter.call(form);
  1418 											if (button)
  1544 											if (button) {
  1419 												button.button('reset');
  1545 												button.button('reset');
       
  1546 											}
  1420 											form.data('submitted', false);
  1547 											form.data('submitted', false);
  1421 											form.removeData('ams-submit-button');
  1548 											form.removeData('ams-submit-button');
  1422 											form.removeAttr('data-ams-form-changed');
  1549 											form.removeAttr('data-ams-form-changed');
  1423 										}
  1550 										}
  1424 									}
  1551 									}
  1434 												   ams.baseURL + 'ext/jquery-progressbar' + ams.devext + '.js');
  1561 												   ams.baseURL + 'ext/jquery-progressbar' + ams.devext + '.js');
  1435 									var settings = $.extend({}, {
  1562 									var settings = $.extend({}, {
  1436 										uuid: $.progressBar.submit(form)
  1563 										uuid: $.progressBar.submit(form)
  1437 									});
  1564 									});
  1438 									_submitAjaxForm(form, settings);
  1565 									_submitAjaxForm(form, settings);
  1439 								} else
  1566 								} else {
  1440 									_submitAjaxForm(form, {});
  1567 									_submitAjaxForm(form, {});
       
  1568 								}
  1441 						   });
  1569 						   });
  1442 			return false;
  1570 			return false;
  1443 		},
  1571 		},
  1444 
  1572 
  1445 		/**
  1573 		/**
  1450 		 * @param message: the optional message
  1578 		 * @param message: the optional message
  1451 		 */
  1579 		 */
  1452 		initSubmit: function(target, message) {
  1580 		initSubmit: function(target, message) {
  1453 			var form = $(this);
  1581 			var form = $(this);
  1454 			var spin = '<i class="fa fa-3x fa-gear fa-spin"></i>';
  1582 			var spin = '<i class="fa fa-3x fa-gear fa-spin"></i>';
  1455 			if (!message)
  1583 			if (!message) {
  1456 				message = form.data('ams-form-submit-message');
  1584 				message = form.data('ams-form-submit-message');
  1457 			if (message)
  1585 			}
       
  1586 			if (message) {
  1458 				spin += '<strong>' + message + '</strong>';
  1587 				spin += '<strong>' + message + '</strong>';
       
  1588 			}
  1459 			$(target).html('<div class="row margin-20"><div class="text-center">' + spin + '</div></div>');
  1589 			$(target).html('<div class="row margin-20"><div class="text-center">' + spin + '</div></div>');
  1460 			$(target).parents('.hidden').removeClass('hidden');
  1590 			$(target).parents('.hidden').removeClass('hidden');
  1461 		},
  1591 		},
  1462 
  1592 
  1463 		/**
  1593 		/**
  1478 		 * @param message: the optional submit message
  1608 		 * @param message: the optional submit message
  1479 		 */
  1609 		 */
  1480 		initSubmitFooter: function(message) {
  1610 		initSubmitFooter: function(message) {
  1481 			var form = $(this);
  1611 			var form = $(this);
  1482 			var spin = '<i class="fa fa-3x fa-gear fa-spin"></i>';
  1612 			var spin = '<i class="fa fa-3x fa-gear fa-spin"></i>';
  1483 			if (!message)
  1613 			if (!message) {
  1484 				message = $(this).data('ams-form-submit-message');
  1614 				message = $(this).data('ams-form-submit-message');
  1485 			if (message)
  1615 			}
       
  1616 			if (message) {
  1486 				spin += '<strong class="submit-message align-top padding-left-10 margin-top-10">' + message + '</strong>';
  1617 				spin += '<strong class="submit-message align-top padding-left-10 margin-top-10">' + message + '</strong>';
       
  1618 			}
  1487 			var footer = $('footer', form);
  1619 			var footer = $('footer', form);
  1488 			$('button', footer).hide();
  1620 			$('button', footer).hide();
  1489 			footer.append('<div class="row"><div class="text-center">' + spin + '</div></div>');
  1621 			footer.append('<div class="row"><div class="text-center">' + spin + '</div></div>');
  1490 		},
  1622 		},
  1491 
  1623 
  1521 		 *     - redirect: redirect browser to given URL
  1653 		 *     - redirect: redirect browser to given URL
  1522 		 *   Each JSON response can also specify an HTML content, a message and a callback (
  1654 		 *   Each JSON response can also specify an HTML content, a message and a callback (
  1523 		 */
  1655 		 */
  1524 		_submitCallback: function(result, status, request, form) {
  1656 		_submitCallback: function(result, status, request, form) {
  1525 
  1657 
       
  1658 			var button;
  1526 			if (form.is(':visible')) {
  1659 			if (form.is(':visible')) {
  1527 				ams.form.finalizeSubmitFooter.call(form);
  1660 				ams.form.finalizeSubmitFooter.call(form);
  1528 				var button = form.data('ams-submit-button');
  1661 				button = form.data('ams-submit-button');
  1529 				if (button)
  1662 				if (button) {
  1530 					button.button('reset');
  1663 					button.button('reset');
  1531 			}
  1664 				}
       
  1665 			}
       
  1666 
  1532 			var data = form.data();
  1667 			var data = form.data();
  1533 			if (data.amsFormDatatype)
  1668 			var data_type;
  1534 				var data_type = data.amsFormDatatype;
  1669 			if (data.amsFormDatatype) {
  1535 			else {
  1670 				data_type = data.amsFormDatatype;
       
  1671 			} else {
  1536 				var request_data = ams.ajax.getResponse(request);
  1672 				var request_data = ams.ajax.getResponse(request);
  1537 				data_type = request_data.content_type;
  1673 				data_type = request_data.content_type;
  1538 				result = request_data.data;
  1674 				result = request_data.data;
  1539 			}
  1675 			}
  1540 
  1676 
  1541 			if (button)
  1677 			var target;
  1542 				var target = $(button.amsFormSubmitTarget || data.amsFormSubmitTarget || '#content');
  1678 			if (button) {
  1543 			else
  1679 				target = $(button.data('ams-form-submit-target') || data.amsFormSubmitTarget || '#content');
       
  1680 			} else {
  1544 				target = $(data.amsFormSubmitTarget || '#content');
  1681 				target = $(data.amsFormSubmitTarget || '#content');
       
  1682 			}
  1545 
  1683 
  1546 			switch (data_type) {
  1684 			switch (data_type) {
  1547 				case 'json':
  1685 				case 'json':
  1548 					ams.ajax.handleJSON(result, form, target);
  1686 					ams.ajax.handleJSON(result, form, target);
  1549 					break;
  1687 					break;
  1550 				case 'script':
  1688 				case 'script':
  1551 					break;
  1689 					break;
  1552 				case 'xml':
  1690 				case 'xml':
  1553 					break;
  1691 					break;
  1554 				case 'html':
  1692 				case 'html':
       
  1693 					/* falls through */
  1555 				case 'text':
  1694 				case 'text':
       
  1695 					/* falls through */
  1556 				default:
  1696 				default:
  1557 					if (button && (button.data('ams-keep-modal') !== true))
  1697 					if (button && (button.data('ams-keep-modal') !== true)) {
  1558 						ams.dialog.close(form);
  1698 						ams.dialog.close(form);
  1559 					if (!target.exists())
  1699 					}
       
  1700 					if (!target.exists()) {
  1560 						target = $('body');
  1701 						target = $('body');
       
  1702 					}
  1561 					target.parents('.hidden').removeClass('hidden');
  1703 					target.parents('.hidden').removeClass('hidden');
  1562 					$('.alert', target.parents('.alerts-container')).remove();
  1704 					$('.alert', target.parents('.alerts-container')).remove();
  1563 					target.css({opacity: '0.0'})
  1705 					target.css({opacity: '0.0'})
  1564 						  .html(result)
  1706 						  .html(result)
  1565 						  .delay(50)
  1707 						  .delay(50)
  1566 						  .animate({opacity: '1.0'}, 300);
  1708 						  .animate({opacity: '1.0'}, 300);
  1567 					ams.initContent(target);
  1709 					ams.initContent(target);
       
  1710 					ams.form.setFocus(target);
  1568 			}
  1711 			}
  1569 			var callback = request.getResponseHeader('X-AMS-Callback');
  1712 			var callback = request.getResponseHeader('X-AMS-Callback');
  1570 			if (callback) {
  1713 			if (callback) {
  1571 				var options = request.getResponseHeader('X-AMS-Callback-Options');
  1714 				var options = request.getResponseHeader('X-AMS-Callback-Options');
  1572 				ams.executeFunctionByName(callback, form, options === undefined ? {} : JSON.parse(options), request);
  1715 				ams.executeFunctionByName(callback, form, options === undefined ? {} : JSON.parse(options), request);
  1575 
  1718 
  1576 		/**
  1719 		/**
  1577 		 * Get list of custom validators called before submit
  1720 		 * Get list of custom validators called before submit
  1578 		 */
  1721 		 */
  1579 		_getSubmitValidators: function(form) {
  1722 		_getSubmitValidators: function(form) {
  1580 			var validators = new Array();
  1723 			var validators = [];
  1581 			var form_validator = form.data('ams-form-validator');
  1724 			var form_validator = form.data('ams-form-validator');
  1582 			if (form_validator)
  1725 			if (form_validator) {
  1583 				validators.push([form, form_validator]);
  1726 				validators.push([form, form_validator]);
       
  1727 			}
  1584 			$('[data-ams-form-validator]', form).each(function() {
  1728 			$('[data-ams-form-validator]', form).each(function() {
  1585 				var source = $(this);
  1729 				var source = $(this);
  1586 				validators.push([source, source.data('ams-form-validator')]);
  1730 				validators.push([source, source.data('ams-form-validator')]);
  1587 			});
  1731 			});
  1588 			return validators;
  1732 			return validators;
  1597 		 *  - an array containing a list of string error messages
  1741 		 *  - an array containing a list of string error messages
  1598 		 * Any other value (undefined, null, True...) will lead to a successful submit.
  1742 		 * Any other value (undefined, null, True...) will lead to a successful submit.
  1599 		 */
  1743 		 */
  1600 		_checkSubmitValidators: function(form) {
  1744 		_checkSubmitValidators: function(form) {
  1601 			var validators = ams.form._getSubmitValidators(form);
  1745 			var validators = ams.form._getSubmitValidators(form);
  1602 			if (!validators.length)
  1746 			if (!validators.length) {
  1603 				return true;
  1747 				return true;
  1604 			var output = new Array();
  1748 			}
       
  1749 			var output = [];
  1605 			var result = true;
  1750 			var result = true;
  1606 			for (var index in validators) {
  1751 			for (var index=0; index < validators.length; index++) {
  1607 				if (!$.isNumeric(index))  // IE check !
       
  1608 					continue;
       
  1609 				var validator = validators[index];
  1752 				var validator = validators[index];
  1610 				var source = validator[0];
  1753 				var source = validator[0];
  1611 				var handler = validator[1];
  1754 				var handler = validator[1];
  1612 				var validator_result = ams.executeFunctionByName(handler, form, source);
  1755 				var validator_result = ams.executeFunctionByName(handler, form, source);
  1613 				if (validator_result === false)
  1756 				if (validator_result === false) {
  1614 					result = false;
  1757 					result = false;
  1615 				else if (typeof(validator_result) == 'string')
  1758 				} else if (typeof(validator_result) === 'string') {
  1616 					output.push(validator_result);
  1759 					output.push(validator_result);
  1617 				else if (result.length && (result.length > 0))
  1760 				} else if (result.length && (result.length > 0)) {
  1618 					output = output.concat(result);
  1761 					output = output.concat(result);
       
  1762 				}
  1619 			}
  1763 			}
  1620 			if (output.length > 0) {
  1764 			if (output.length > 0) {
  1621 				var header = output.length == 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1765 				var header = output.length === 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1622 				ams.skin.alert(form, 'danger', header, output);
  1766 				ams.skin.alert(form, 'danger', header, output);
  1623 				return false;
  1767 				return false;
  1624 			} else
  1768 			} else {
  1625 				return result;
  1769 				return result;
       
  1770 			}
  1626 		},
  1771 		},
  1627 
  1772 
  1628 		/**
  1773 		/**
  1629 		 * Display JSON errors
  1774 		 * Display JSON errors
  1630 		 * JSON errors should be defined in an object as is:
  1775 		 * JSON errors should be defined in an object as is:
  1637 		 *            {label: "Second widget name",
  1782 		 *            {label: "Second widget name",
  1638 		 *             name: "field-name-2",
  1783 		 *             name: "field-name-2",
  1639 		 *             message: "Second error message"},...]}
  1784 		 *             message: "Second error message"},...]}
  1640 		 */
  1785 		 */
  1641 		showErrors: function(form, errors) {
  1786 		showErrors: function(form, errors) {
  1642 			if (typeof(errors) == 'string') {
  1787 			var header;
  1643 				ams.skin.alert(form, 'error', ams.i18n.ERROR_OCCURED, errors)
  1788 			if (typeof(errors) === 'string') {
       
  1789 				ams.skin.alert(form, 'error', ams.i18n.ERROR_OCCURED, errors);
  1644 			} else if (errors instanceof Array) {
  1790 			} else if (errors instanceof Array) {
  1645 				var header = errors.length == 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1791 				header = errors.length === 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1646 				ams.skin.alert(form, 'error', header, errors);
  1792 				ams.skin.alert(form, 'error', header, errors);
  1647 			} else {
  1793 			} else {
  1648 				$('.state-error', form).removeClass('state-error');
  1794 				$('.state-error', form).removeClass('state-error');
  1649 				header = errors.error_header ||
  1795 				header = errors.error_header ||
  1650 						 (errors.widgets && (errors.widgets.length > 1) ? ams.i18n.ERRORS_OCCURED : ams.i18n.ERROR_OCCURED);
  1796 						 (errors.widgets && (errors.widgets.length > 1) ? ams.i18n.ERRORS_OCCURED : ams.i18n.ERROR_OCCURED);
  1651 				var message = new Array();
  1797 				var message = [];
  1652 				var index;
  1798 				var index;
  1653 				for (index in errors.messages) {
  1799 				if (errors.messages) {
  1654 					if (!$.isNumeric(index))
  1800 					for (index = 0; index < errors.messages.length; index++) {
  1655 						continue;
  1801 						var msg = errors.messages[index];
  1656 					if (errors.messages[index].header) {
  1802 						if (msg.header) {
  1657 						message.push('<strong>' + errors.messages[index].header + '</strong><br />' + errors.messages[index].message);
  1803 							message.push('<strong>' + msg.header + '</strong><br />' + msg.message);
  1658 					} else {
  1804 						} else {
  1659 						message.push(errors.messages[index].message || errors.messages[index]);
  1805 							message.push(msg.message || msg);
       
  1806 						}
  1660 					}
  1807 					}
  1661 				}
  1808 				}
  1662 				for (index in errors.widgets) {
  1809 				if (errors.widgets) {
  1663 					if (!$.isNumeric(index))
  1810 					for (index = 0; index < errors.widgets.length; index++) {
  1664 						continue;
  1811 						// set widget status message
  1665 					// set widget status message
  1812 						var widget_data = errors.widgets[index];
  1666 					var widget_data = errors.widgets[index];
  1813 						var widget = $('[name="' + widget_data.name + '"]', form);
  1667 					var widget = $('[name="' + widget_data.name + '"]', form);
  1814 						widget.parents('label:first')
  1668 					widget.parents('label:first')
  1815 								.removeClassPrefix('state-')
  1669 						  .removeClassPrefix('state-')
  1816 								.addClass('state-error')
  1670 						  .addClass('state-error')
  1817 								.after('<span for="name" class="state-error">' + widget_data.message + '</span>');
  1671 						  .after('<span for="name" class="state-error">' + widget_data.message + '</span>');
  1818 						// complete form alert message
  1672 					// complete form alert message
  1819 						if (widget_data.label) {
  1673 					if (widget_data.label) {
  1820 							message.push(widget_data.label + ' : ' + widget_data.message);
  1674 						message.push(widget_data.label + ' : ' + widget_data.message);
  1821 						}
       
  1822 						// mark parent tab (if any) with error status
       
  1823 						var tab_index = widget.parents('.tab-pane').index() + 1;
       
  1824 						if (tab_index > 0) {
       
  1825 							var nav_tabs = $('.nav-tabs', $(widget).parents('.tabforms'));
       
  1826 							$('li:nth-child(' + tab_index + ')', nav_tabs).removeClassPrefix('state-')
       
  1827 									.addClass('state-error');
       
  1828 							$('li.state-error:first a', form).click();
       
  1829 						}
  1675 					}
  1830 					}
  1676 					// mark parent tab (if any) with error status
  1831 				}
  1677 					var tab_index = widget.parents('.tab-pane').index() + 1;
  1832 				ams.skin.alert($('fieldset:first', form), errors.error_level || 'error', header, message, errors.error_message);
  1678 					if (tab_index > 0) {
       
  1679 						var nav_tabs = $('.nav-tabs', $(widget).parents('.tabforms'));
       
  1680 						$('li:nth-child(' + tab_index + ')', nav_tabs).removeClassPrefix('state-')
       
  1681 																	  .addClass('state-error');
       
  1682 						$('li.state-error:first a', form).click();
       
  1683 					}
       
  1684 				}
       
  1685 				ams.skin.alert(form, errors.error_level || 'error', header, message, errors.error_message);
       
  1686 			}
  1833 			}
  1687 		}
  1834 		}
  1688 	};
  1835 	};
  1689 
  1836 
  1690 
  1837 
  1704 		registerShownCallback: function(callback, element) {
  1851 		registerShownCallback: function(callback, element) {
  1705 			var dialog;
  1852 			var dialog;
  1706 			if (element) {
  1853 			if (element) {
  1707 				dialog = element.objectOrParentWithClass('modal-dialog');
  1854 				dialog = element.objectOrParentWithClass('modal-dialog');
  1708 			}
  1855 			}
       
  1856 
       
  1857 			var callbacks;
  1709 			if (dialog && dialog.exists()) {
  1858 			if (dialog && dialog.exists()) {
  1710 				var callbacks = dialog.data('shown-callbacks');
  1859 				callbacks = dialog.data('shown-callbacks');
  1711 				if (callbacks === undefined) {
  1860 				if (callbacks === undefined) {
  1712 					callbacks = [];
  1861 					callbacks = [];
  1713 					dialog.data('shown-callbacks', callbacks);
  1862 					dialog.data('shown-callbacks', callbacks);
  1714 				}
  1863 				}
  1715 			} else {
  1864 			} else {
  1716 				callbacks = ams.dialog._shown_callbacks;
  1865 				callbacks = ams.dialog._shown_callbacks;
  1717 			}
  1866 			}
  1718 			if (callbacks.indexOf(callback) < 0)
  1867 			if (callbacks.indexOf(callback) < 0) {
  1719 				callbacks.push(callback);
  1868 				callbacks.push(callback);
       
  1869 			}
  1720 		},
  1870 		},
  1721 
  1871 
  1722 		/**
  1872 		/**
  1723 		 * List of registered 'hide' callbacks
  1873 		 * List of registered 'hide' callbacks
  1724 		 */
  1874 		 */
  1730 		registerHideCallback: function(callback, element) {
  1880 		registerHideCallback: function(callback, element) {
  1731 			var dialog;
  1881 			var dialog;
  1732 			if (element) {
  1882 			if (element) {
  1733 				dialog = element.objectOrParentWithClass('modal-dialog');
  1883 				dialog = element.objectOrParentWithClass('modal-dialog');
  1734 			}
  1884 			}
       
  1885 
       
  1886 			var callbacks;
  1735 			if (dialog && dialog.exists()) {
  1887 			if (dialog && dialog.exists()) {
  1736 				var callbacks = dialog.data('hide-callbacks');
  1888 				callbacks = dialog.data('hide-callbacks');
  1737 				if (callbacks === undefined) {
  1889 				if (callbacks === undefined) {
  1738 					callbacks = [];
  1890 					callbacks = [];
  1739 					dialog.data('hide-callbacks', callbacks);
  1891 					dialog.data('hide-callbacks', callbacks);
  1740 				}
  1892 				}
  1741 			} else {
  1893 			} else {
  1742 				callbacks = ams.dialog._hide_callbacks;
  1894 				callbacks = ams.dialog._hide_callbacks;
  1743 			}
  1895 			}
  1744 			if (callbacks.indexOf(callback) < 0)
  1896 			if (callbacks.indexOf(callback) < 0) {
  1745 				callbacks.push(callback);
  1897 				callbacks.push(callback);
       
  1898 			}
  1746 		},
  1899 		},
  1747 
  1900 
  1748 		/**
  1901 		/**
  1749 		 * Modal dialog opener
  1902 		 * Modal dialog opener
  1750 		 */
  1903 		 */
  1762 												'<div class="progress progress-striped active">' +
  1915 												'<div class="progress progress-striped active">' +
  1763 													'<div class="progress-bar" style="width: 100%;"></div>' +
  1916 													'<div class="progress-bar" style="width: 100%;"></div>' +
  1764 												'</div>' +
  1917 												'</div>' +
  1765 											'</div>';
  1918 											'</div>';
  1766 									}
  1919 									}
  1767 									if (typeof(source) == 'string') {
  1920 
  1768 										var source_data = {};
  1921 									var source_data;
  1769 										var url = source;
  1922 									var url;
       
  1923 									if (typeof(source) === 'string') {
       
  1924 										source_data = {};
       
  1925 										url = source;
  1770 									} else {
  1926 									} else {
  1771 										source_data = source.data();
  1927 										source_data = source.data();
  1772 										url = source.attr('href') || source_data.amsUrl;
  1928 										url = source.attr('href') || source_data.amsUrl;
  1773 										var url_getter = ams.getFunctionByName(url);
  1929 										var url_getter = ams.getFunctionByName(url);
  1774 										if (typeof(url_getter) == 'function') {
  1930 										if (typeof(url_getter) === 'function') {
  1775 											url = url_getter.call(source);
  1931 											url = url_getter.call(source);
  1776 										}
  1932 										}
  1777 									}
  1933 									}
  1778 									if (!url)
  1934 									if (!url) {
  1779 										return;
  1935 										return;
       
  1936 									}
  1780 									$('body').modalmanager('loading');
  1937 									$('body').modalmanager('loading');
  1781 									if (url.indexOf('#') == 0) {
  1938 									if (url.indexOf('#') === 0) {
  1782 										// Inner hidden modal dialog
  1939 										// Inner hidden modal dialog
  1783 										$(url).modal('show');
  1940 										$(url).modal('show');
  1784 									} else {
  1941 									} else {
  1785 										// Remote URL modal dialog
  1942 										// Remote URL modal dialog
  1786 										$.ajax({
  1943 										$.ajax({
  1800 													case 'script':
  1957 													case 'script':
  1801 														break;
  1958 														break;
  1802 													case 'xml':
  1959 													case 'xml':
  1803 														break;
  1960 														break;
  1804 													case 'html':
  1961 													case 'html':
       
  1962 														/* falls through */
  1805 													case 'text':
  1963 													case 'text':
       
  1964 														/* falls through */
  1806 													default:
  1965 													default:
  1807 														var content = $(result);
  1966 														var content = $(result);
  1808 														var dialog = $('.modal-dialog', content.wrap('<div></div>').parent());
  1967 														var dialog = $('.modal-dialog', content.wrap('<div></div>').parent());
  1809 														var dialog_data = dialog.data();
  1968 														var dialog_data = dialog.data();
  1810 														var data_options = {
  1969 														var data_options = {
       
  1970 															backdrop: 'static',
  1811 															overflow: dialog_data.amsModalOverflow || '.modal-viewport',
  1971 															overflow: dialog_data.amsModalOverflow || '.modal-viewport',
  1812 															maxHeight: dialog_data.amsModalMaxHeight === undefined
  1972 															maxHeight: dialog_data.amsModalMaxHeight === undefined ?
  1813 																	? function() {
  1973 																	function() {
  1814 																		return $(window).height() -
  1974 																		return $(window).height() -
  1815 																					$('.modal-header', content).outerHeight(true) -
  1975 																					$('.modal-header', content).outerHeight(true) -
  1816 																					$('footer', content).outerHeight(true) - 85;
  1976 																					$('footer', content).outerHeight(true) - 85;
  1817 																	}
  1977 																	}
  1818 																	: ams.getFunctionByName(dialog_data.amsModalMaxHeight)
  1978 																	: ams.getFunctionByName(dialog_data.amsModalMaxHeight)
  1840 		shown: function(e) {
  2000 		shown: function(e) {
  1841 
  2001 
  1842 			function resetViewport(ev) {
  2002 			function resetViewport(ev) {
  1843 				var top = $('.scrollmarker.top', viewport);
  2003 				var top = $('.scrollmarker.top', viewport);
  1844 				var top_position = viewport.scrollTop();
  2004 				var top_position = viewport.scrollTop();
  1845 				if (top_position > 0)
  2005 				if (top_position > 0) {
  1846 					top.show();
  2006 					top.show();
  1847 				else
  2007 				} else {
  1848 					top.hide();
  2008 					top.hide();
       
  2009 				}
  1849 				var bottom = $('.scrollmarker.bottom', viewport);
  2010 				var bottom = $('.scrollmarker.bottom', viewport);
  1850 				if (maxHeight + top_position >= viewport.get(0).scrollHeight)
  2011 				if (maxHeight + top_position >= viewport.get(0).scrollHeight) {
  1851 					bottom.hide();
  2012 					bottom.hide();
  1852 				else
  2013 				} else {
  1853 					bottom.show();
  2014 					bottom.show();
       
  2015 				}
  1854 			}
  2016 			}
  1855 
  2017 
  1856 			var modal = e.target;
  2018 			var modal = e.target;
  1857 			var viewport = $('.modal-viewport', modal);
  2019 			var viewport = $('.modal-viewport', modal);
  1858 			if (viewport.exists()) {
  2020 			if (viewport.exists()) {
  1859 				var maxHeight = parseInt(viewport.css('max-height'));
  2021 				var maxHeight = parseInt(viewport.css('max-height'));
  1860 				var barWidth = $.scrollbarWidth();
  2022 				var barWidth = $.scrollbarWidth();
  1861 				if (viewport.height() == maxHeight) {
  2023 				if (viewport.height() === maxHeight) {
  1862 					$('<div></div>').addClass('scrollmarker')
  2024 					$('<div></div>').addClass('scrollmarker')
  1863 						.addClass('top')
  2025 						.addClass('top')
  1864 						.css('top', 0)
  2026 						.css('top', 0)
  1865 						.css('width', viewport.width() - barWidth)
  2027 						.css('width', viewport.width() - barWidth)
  1866 						.hide()
  2028 						.hide()
  1877 					$('.scrollmarker', viewport).remove();
  2039 					$('.scrollmarker', viewport).remove();
  1878 				}
  2040 				}
  1879 			}
  2041 			}
  1880 
  2042 
  1881 			// Call shown callbacks registered for this dialog
  2043 			// Call shown callbacks registered for this dialog
       
  2044 			var index;
  1882 			var callbacks = $('.modal-dialog', modal).data('shown-callbacks');
  2045 			var callbacks = $('.modal-dialog', modal).data('shown-callbacks');
  1883 			if (callbacks) {
  2046 			if (callbacks) {
  1884 				for (var index in callbacks) {
  2047 				for (index=0; index < callbacks.length; index++) {
  1885 					callbacks[index].call(modal);
  2048 					callbacks[index].call(modal);
  1886 				}
  2049 				}
  1887 			}
  2050 			}
  1888 			// Call globally registered shown callbacks
  2051 			// Call globally registered shown callbacks
  1889 			callbacks = ams.dialog._shown_callbacks;
  2052 			callbacks = ams.dialog._shown_callbacks;
  1890 			for (index in callbacks) {
  2053 			if (callbacks) {
  1891 				callbacks[index].call(modal);
  2054 				for (index=0; index < callbacks.length; index++) {
  1892 			}
  2055 					callbacks[index].call(modal);
       
  2056 				}
       
  2057 			}
       
  2058 
       
  2059 			ams.form.setFocus(modal);
  1893 		},
  2060 		},
  1894 
  2061 
  1895 		/**
  2062 		/**
  1896 		 * Close modal dialog associated with given context
  2063 		 * Close modal dialog associated with given context
  1897 		 */
  2064 		 */
  1898 		close: function(context) {
  2065 		close: function(context) {
  1899 			var modal = context.parents('.modal').data('modal');
  2066 			var modal = context.parents('.modal').data('modal');
  1900 			if (modal) {
  2067 			if (modal) {
  1901 				var manager = $('body').data('modalmanager');
  2068 				var manager = $('body').data('modalmanager');
  1902 				if (manager && (manager.getOpenModals().indexOf(modal) >= 0))
  2069 				if (manager && (manager.getOpenModals().indexOf(modal) >= 0)) {
  1903 					modal.hide();
  2070 					modal.hide();
       
  2071 				}
  1904 			}
  2072 			}
  1905 		},
  2073 		},
  1906 
  2074 
  1907 		/**
  2075 		/**
  1908 		 * Modals hidden callback
  2076 		 * Modals hidden callback
  1911 		hidden: function(e) {
  2079 		hidden: function(e) {
  1912 			var modal = e.target;
  2080 			var modal = e.target;
  1913 			// Call registered cleaning callbacks
  2081 			// Call registered cleaning callbacks
  1914 			ams.skin.cleanContainer(modal);
  2082 			ams.skin.cleanContainer(modal);
  1915 			// Call hide callbacks registered for this dialog
  2083 			// Call hide callbacks registered for this dialog
       
  2084 			var index;
  1916 			var callbacks = $('.modal-dialog', modal).data('hide-callbacks');
  2085 			var callbacks = $('.modal-dialog', modal).data('hide-callbacks');
  1917 			if (callbacks) {
  2086 			if (callbacks) {
  1918 				for (var index in callbacks) {
  2087 				for (index=0; index < callbacks.length; index++) {
  1919 					callbacks[index].call(modal);
  2088 					callbacks[index].call(modal);
  1920 				}
  2089 				}
  1921 			}
  2090 			}
  1922 			// Call globally registered hide callbacks
  2091 			// Call globally registered hide callbacks
  1923 			callbacks = ams.dialog._hide_callbacks;
  2092 			callbacks = ams.dialog._hide_callbacks;
  1924 			for (index in callbacks) {
  2093 			if (callbacks) {
  1925 				callbacks[index].call(modal);
  2094 				for (index=0; index < callbacks.length; index++) {
       
  2095 					callbacks[index].call(modal);
       
  2096 				}
  1926 			}
  2097 			}
  1927 		}
  2098 		}
  1928 	};
  2099 	};
  1929 
  2100 
  1930 
  2101 
  1947 
  2118 
  1948 		/** Select2 selection formatter */
  2119 		/** Select2 selection formatter */
  1949 		select2FormatSelection: function(object, container) {
  2120 		select2FormatSelection: function(object, container) {
  1950 			if (object instanceof Array) {
  2121 			if (object instanceof Array) {
  1951 				$(object).each(function() {
  2122 				$(object).each(function() {
  1952 					if (typeof(this) == 'object')
  2123 					if (typeof(this) === 'object') {
  1953 						container.append(this.text);
  2124 						container.append(this.text);
  1954 					else
  2125 					} else {
  1955 						container.append(this);
  2126 						container.append(this);
       
  2127 					}
  1956 				});
  2128 				});
  1957 			} else {
  2129 			} else {
  1958 				if (typeof(object) == 'object')
  2130 				if (typeof(object) === 'object') {
  1959 					container.append(object.text);
  2131 					container.append(object.text);
  1960 				else
  2132 				} else {
  1961 					container.append(object);
  2133 					container.append(object);
       
  2134 				}
  1962 			}
  2135 			}
  1963 		},
  2136 		},
  1964 
  2137 
  1965 		/** Select2 query results callback */
  2138 		/** Select2 query results callback */
  1966 		select2QueryUrlResultsCallback: function(data, page, context) {
  2139 		select2QueryUrlResultsCallback: function(data, page, context) {
  1973 						timeout: 10000
  2146 						timeout: 10000
  1974 					});
  2147 					});
  1975 					break;
  2148 					break;
  1976 				case 'modal':
  2149 				case 'modal':
  1977 					$(this).data('select2').dropdown.hide();
  2150 					$(this).data('select2').dropdown.hide();
  1978 					ams.dialog.open(result.location);
  2151 					ams.dialog.open(data.location);
  1979 					break;
  2152 					break;
  1980 				default:
  2153 				default:
  1981 					return {
  2154 					return {
  1982 						results: data.results || data,
  2155 						results: data.results || data,
  1983 						more: data.has_more || false,
  2156 						more: data.has_more || false,
  1987 		},
  2160 		},
  1988 
  2161 
  1989 		/** Select2 JSON-RPC success callback */
  2162 		/** Select2 JSON-RPC success callback */
  1990 		select2QueryMethodSuccessCallback: function(data, status, options) {
  2163 		select2QueryMethodSuccessCallback: function(data, status, options) {
  1991 			var result = data.result;
  2164 			var result = data.result;
  1992 			if (typeof(result) == 'string') {
  2165 			if (typeof(result) === 'string') {
  1993 				try {
  2166 				try {
  1994 					result = JSON.parse(result);
  2167 					result = JSON.parse(result);
  1995 				} catch (e) {}
  2168 				} catch (e) {}
  1996 			}
  2169 			}
  1997 			switch (result.status) {
  2170 			switch (result.status) {
  2017 		},
  2190 		},
  2018 
  2191 
  2019 		/** Context menu handler */
  2192 		/** Context menu handler */
  2020 		contextMenuHandler: function(target, menu) {
  2193 		contextMenuHandler: function(target, menu) {
  2021 			var menu_data = menu.data();
  2194 			var menu_data = menu.data();
  2022 			if (menu_data.toggle == 'modal') {
  2195 			if (menu_data.toggle === 'modal') {
  2023 				ams.dialog.open(menu);
  2196 				ams.dialog.open(menu);
  2024 			} else {
  2197 			} else {
  2025 				var href = menu.attr('href') || menu_data.amsUrl;
  2198 				var href = menu.attr('href') || menu_data.amsUrl;
  2026 				if (!href || href.startsWith('javascript:') || menu.attr('target'))
  2199 				if (!href || href.startsWith('javascript') || menu.attr('target')) {
  2027 					return;
  2200 					return;
       
  2201 				}
  2028 				ams.event.stop();
  2202 				ams.event.stop();
  2029 				var href_getter = ams.getFunctionByName(href);
  2203 				var href_getter = ams.getFunctionByName(href);
  2030 				if (typeof(href_getter) == 'function') {
  2204 				if (typeof(href_getter) === 'function') {
  2031 					href = href_getter.call(menu, target);
  2205 					href = href_getter.call(menu, target);
  2032 				}
  2206 				}
  2033 				if (typeof(href) == 'function') {
  2207 				if (typeof(href) === 'function') {
  2034 					// Javascript function call
  2208 					// Javascript function call
  2035 					href.call(menu, target);
  2209 					href.call(menu, target);
  2036 				} else {
  2210 				} else {
  2037 					// Standard AJAX or browser URL call
  2211 					// Standard AJAX or browser URL call
  2038 					// Convert %23 chars to #
  2212 					// Convert %23 chars to #
  2039 					href = href.replace(/\%23/, '#');
  2213 					href = href.replace(/\%23/, '#');
  2040 					var target = menu.data('ams-target');
  2214 					target = menu.data('ams-target');
  2041 					if (target) {
  2215 					if (target) {
  2042 						ams.form.confirmChangedForm(target, function () {
  2216 						ams.form.confirmChangedForm(target, function () {
  2043 							ams.skin.loadURL(href, target, menu.data('ams-link-options'), menu.data('ams-link-callback'));
  2217 							ams.skin.loadURL(href, target, menu.data('ams-link-options'), menu.data('ams-link-callback'));
  2044 						});
  2218 						});
  2045 					} else {
  2219 					} else {
  2046 						ams.form.confirmChangedForm(function () {
  2220 						ams.form.confirmChangedForm(function () {
  2047 							if (href.startsWith('#')) {
  2221 							if (href.startsWith('#')) {
  2048 								if (href != location.hash) {
  2222 								if (href !== location.hash) {
  2049 									if (ams.root.hasClass('mobile-view-activated')) {
  2223 									if (ams.root.hasClass('mobile-view-activated')) {
  2050 										ams.root.removeClass('hidden-menu');
  2224 										ams.root.removeClass('hidden-menu');
  2051 										window.setTimeout(function () {
  2225 										window.setTimeout(function () {
  2052 											window.location.hash = href;
  2226 											window.location.hash = href;
  2053 										}, 150);
  2227 										}, 150);
  2054 									} else
  2228 									} else {
  2055 										window.location.hash = href;
  2229 										window.location.hash = href;
       
  2230 									}
  2056 								}
  2231 								}
  2057 							} else
  2232 							} else {
  2058 								window.location = href;
  2233 								window.location = href;
       
  2234 							}
  2059 						});
  2235 						});
  2060 					}
  2236 					}
  2061 				}
  2237 				}
  2062 			}
  2238 			}
  2063 		},
  2239 		},
  2091 
  2267 
  2092 			// Initialize custom data attributes
  2268 			// Initialize custom data attributes
  2093 			ams.plugins.initData(element);
  2269 			ams.plugins.initData(element);
  2094 
  2270 
  2095 			// Check for disabled plug-ins
  2271 			// Check for disabled plug-ins
  2096 			var disabled = new Array();
  2272 			var disabled = [];
  2097 			$('[data-ams-plugins-disabled]', element).each(function() {
  2273 			$('[data-ams-plugins-disabled]', element).each(function() {
  2098 				var plugins = $(this).data('ams-plugins-disabled').split(/\s+/);
  2274 				var plugins = $(this).data('ams-plugins-disabled').split(/\s+/);
  2099 				for (var name in plugins) {
  2275 				for (var index=0; index < plugins.length; index++) {
  2100 					disabled.push(plugins[name]);
  2276 					disabled.push(plugins[index]);
  2101 				}
  2277 				}
  2102 			});
  2278 			});
  2103 
  2279 
  2104 			// Load and register new plug-ins
  2280 			// Scan new element for plug-ins
       
  2281 			var plugins = {};
       
  2282 			var plugin;
  2105 			var name;
  2283 			var name;
       
  2284 
  2106 			$('[data-ams-plugins]', element).each(function() {
  2285 			$('[data-ams-plugins]', element).each(function() {
       
  2286 
       
  2287 				function registerPlugin(name, new_plugin) {
       
  2288 					if (plugins.hasOwnProperty(name)) {
       
  2289 						var plugin = plugins[name];
       
  2290 						plugin.css = plugin.css || new_plugin.css;
       
  2291 						if (new_plugin.callback) {
       
  2292 							plugin.callbacks.push(new_plugin.callback);
       
  2293 						}
       
  2294 						if (new_plugin.register) {
       
  2295 							plugin.register = true;
       
  2296 						}
       
  2297 						if (new_plugin.async === false) {
       
  2298 							plugin.async = false;
       
  2299 						}
       
  2300 					} else {
       
  2301 						plugins[name] = {
       
  2302 							src: new_plugin.src,
       
  2303 							css: new_plugin.css,
       
  2304 							callbacks: new_plugin.callback ? [new_plugin.callback] : [],
       
  2305 							register: new_plugin.register,
       
  2306 							async: new_plugin.async
       
  2307 						}
       
  2308 					}
       
  2309 				}
       
  2310 
  2107 				var source = $(this);
  2311 				var source = $(this);
  2108 				var plugins = {}
  2312 				var ams_plugins = source.data('ams-plugins');
  2109 				if (typeof(source.data('ams-plugins')) === 'string') {
  2313 				if (typeof(ams_plugins) === 'string') {
  2110 					var names = source.data('ams-plugins').split(/\s+/);
  2314 					var names = source.data('ams-plugins').split(/\s+/);
  2111 					for (var index in names) {
  2315 					for (var index = 0; index < names.length; index++) {
  2112 						name = names[index];
  2316 						name = names[index];
  2113 						var plugin_options = {
  2317 						var new_plugin = {
  2114 							src: source.data('ams-plugin-' + name + '-src'),
  2318 							src: source.data('ams-plugin-' + name + '-src'),
  2115 							css: source.data('ams-plugin-' + name + '-css'),
  2319 							css: source.data('ams-plugin-' + name + '-css'),
  2116 							callback: source.data('ams-plugin-' + name + '-callback'),
  2320 							callback: source.data('ams-plugin-' + name + '-callback'),
  2117 							register: source.data('ams-plugin-' + name + '-register'),
  2321 							register: source.data('ams-plugin-' + name + '-register'),
  2118 							async: source.data('ams-plugin-' + name + '-async')
  2322 							async: source.data('ams-plugin-' + name + '-async')
  2119 						}
  2323 						};
  2120 						plugins[name] = plugin_options;
  2324 						registerPlugin(name, new_plugin);
  2121 					}
  2325 					}
  2122 				} else {
  2326 				} else {
  2123 					plugins = source.data('ams-plugins');
  2327 					for (name in ams_plugins) {
  2124 				}
  2328 						if (!ams_plugins.hasOwnProperty(name)) {
  2125 				for (name in plugins) {
  2329 							continue;
  2126 					if (ams.plugins.enabled[name] === undefined) {
  2330 						}
  2127 						var plugin = plugins[name];
  2331 						registerPlugin(name, ams_plugins[name]);
  2128 						ams.getScript(plugin.src, function() {
  2332 					}
  2129 							var callback = plugin.callback;
  2333 				}
  2130 							if (callback) {
  2334 			});
  2131 								var called = ams.getFunctionByName(callback);
  2335 
  2132 								if (plugin.register !== false)
  2336 			// Load new plug-ins and execute async ones
  2133 									ams.plugins.enabled[name] = called;
  2337 			for (name in plugins) {
  2134 							} else {
  2338 				if (ams.plugins.enabled[name] === undefined) {
  2135 								if (plugin.register !== false)
  2339 					plugin = plugins[name];
  2136 									ams.plugins.enabled[name] = null;
  2340 					ams.getScript(plugin.src, function() {
       
  2341 						var index;
       
  2342 						var callbacks = plugin.callbacks;
       
  2343 						if (callbacks) {
       
  2344 							for (index=0; index < callbacks.length; index++) {
       
  2345 								var called = ams.getFunctionByName(callbacks[index]);
       
  2346 								if (plugin.register !== false) {
       
  2347 									var enabled = ams.plugins.enabled;
       
  2348 									if (enabled.hasOwnProperty(name)) {
       
  2349 										enabled[name].push(called);
       
  2350 									} else {
       
  2351 										enabled[name] = [called];
       
  2352 									}
       
  2353 								}
  2137 							}
  2354 							}
  2138 							var css = plugin['css'];
  2355 						} else {
  2139 							if (css) {
  2356 							if (plugin.register !== false) {
  2140 								ams.getCSS(css, name + '_css');
  2357 								ams.plugins.enabled[name] = null;
  2141 							}
  2358 							}
  2142 						}, {
  2359 						}
  2143 							async: plugin.async === undefined ? true : plugin.async
  2360 						var css = plugin.css;
  2144 						});
  2361 						if (css) {
  2145 					}
  2362 							ams.getCSS(css, name + '_css');
  2146 				}
  2363 						}
  2147 			});
  2364 						// If running in async mode, registered plug-ins are run
       
  2365 						// before callback is called so we call plug-in manually
       
  2366 						if (callbacks && (plugin.async !== false)) {
       
  2367 							for (index=0; index < callbacks.length; index++) {
       
  2368 								callbacks[index](element);
       
  2369 							}
       
  2370 						}
       
  2371 					}, {
       
  2372 						async: plugin.async === undefined ? true : plugin.async
       
  2373 					});
       
  2374 				}
       
  2375 			}
  2148 
  2376 
  2149 			// Run all enabled plug-ins
  2377 			// Run all enabled plug-ins
  2150 			for (var index in ams.plugins.enabled) {
  2378 			for (var index in ams.plugins.enabled) {
  2151 				if (disabled.indexOf(index) >= 0)
  2379 				if (!ams.plugins.enabled.hasOwnProperty(index)) {
  2152 					continue;
  2380 					continue;
  2153 				var plugin = ams.plugins.enabled[index];
  2381 				}
  2154 				if (typeof(plugin) == 'function')
  2382 				if (disabled.indexOf(index) >= 0) {
  2155 					plugin(element);
  2383 					continue;
       
  2384 				}
       
  2385 				var callbacks = ams.plugins.enabled[index];
       
  2386 				switch (typeof(callbacks)) {
       
  2387 					case 'function':
       
  2388 						callbacks(element);
       
  2389 						break;
       
  2390 					default:
       
  2391 						for (var cb_index = 0; cb_index < callbacks.length; cb_index++) {
       
  2392 							var callback = callbacks[cb_index];
       
  2393 							if (typeof(callback) === 'function') {
       
  2394 								callback(element);
       
  2395 							}
       
  2396 						}
       
  2397 				}
  2156 			}
  2398 			}
  2157 		},
  2399 		},
  2158 
  2400 
  2159 		/**
  2401 		/**
  2160 		 * Data initializer
  2402 		 * Data initializer
  2164 		 */
  2406 		 */
  2165 		initData: function(element) {
  2407 		initData: function(element) {
  2166 			$('[data-ams-data]', element).each(function() {
  2408 			$('[data-ams-data]', element).each(function() {
  2167 				var handler = $(this);
  2409 				var handler = $(this);
  2168 				var data = handler.data('ams-data');
  2410 				var data = handler.data('ams-data');
  2169 				for (var index in data) {
  2411 				if (data) {
  2170 					handler.attr('data-' + index, data[index]);
  2412 					for (var name in data) {
       
  2413 						if (data.hasOwnProperty(name)) {
       
  2414 							handler.attr('data-' + name, data[name]);
       
  2415 						}
       
  2416 					}
  2171 				}
  2417 				}
  2172 			});
  2418 			});
  2173 		},
  2419 		},
  2174 
  2420 
  2175 		/**
  2421 		/**
  2178 		 * @plugin: plugin function caller or object containing plug-in properties
  2424 		 * @plugin: plugin function caller or object containing plug-in properties
  2179 		 * @name: if @plugin is a function, defines plug-in name
  2425 		 * @name: if @plugin is a function, defines plug-in name
  2180 		 * @callback: a callback function which can be called after plug-in registry
  2426 		 * @callback: a callback function which can be called after plug-in registry
  2181 		 */
  2427 		 */
  2182 		register: function(plugin, name, callback) {
  2428 		register: function(plugin, name, callback) {
  2183 			if (typeof(name) == 'function') {
  2429 			if (typeof(name) === 'function') {
  2184 				callback = name;
  2430 				callback = name;
  2185 				name = null;
  2431 				name = null;
  2186 			}
  2432 			}
  2187 			name = name || plugin.name;
  2433 			name = name || plugin.name;
  2188 			if (ams.plugins.enabled.indexOf(name) >= 0) {
  2434 			if (ams.plugins.enabled.indexOf(name) >= 0) {
  2189 				if (window.console)
  2435 				if (globals.console) {
  2190 					console.warn("Plugin "+name+" is already registered!");
  2436 					globals.console.warn("Plugin " + name + " is already registered!");
       
  2437 				}
  2191 				return;
  2438 				return;
  2192 			}
  2439 			}
  2193 			if (typeof(plugin) == 'object') {
  2440 			if (typeof(plugin) === 'object') {
  2194 				var src = plugin.src;
  2441 				var src = plugin.src;
  2195 				if (src) {
  2442 				if (src) {
  2196 					ams.ajax.check(plugin.callback, src, function(first_load) {
  2443 					ams.ajax.check(plugin.callback, src, function(first_load) {
  2197 						if (first_load) {
  2444 						if (first_load) {
  2198 							ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback);
  2445 							ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback);
  2201 							}
  2448 							}
  2202 							if (callback) {
  2449 							if (callback) {
  2203 								ams.executeFunctionByName(callback);
  2450 								ams.executeFunctionByName(callback);
  2204 							}
  2451 							}
  2205 						}
  2452 						}
  2206 					})
  2453 					});
  2207 				} else {
  2454 				} else {
  2208 					ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback);
  2455 					ams.plugins.enabled[name] = ams.getFunctionByName(plugin.callback);
  2209 					if (plugin.css) {
  2456 					if (plugin.css) {
  2210 						ams.getCSS(plugin.css, name + '_css');
  2457 						ams.getCSS(plugin.css, name + '_css');
  2211 					}
  2458 					}
  2212 					if (callback) {
  2459 					if (callback) {
  2213 						ams.executeFunctionByName(callback);
  2460 						ams.executeFunctionByName(callback);
  2214 					}
  2461 					}
  2215 				}
  2462 				}
  2216 			} else if (typeof(plugin) == 'function') {
  2463 			} else if (typeof(plugin) === 'function') {
  2217 				ams.plugins.enabled[name] = plugin;
  2464 				ams.plugins.enabled[name] = plugin;
  2218 				if (callback) {
  2465 				if (callback) {
  2219 					ams.executeFunctionByName(callback);
  2466 					ams.executeFunctionByName(callback);
  2220 				}
  2467 				}
  2221 			}
  2468 			}
  2239 			/**
  2486 			/**
  2240 			 * Label hints
  2487 			 * Label hints
  2241 			 */
  2488 			 */
  2242 			hint: function(element) {
  2489 			hint: function(element) {
  2243 				var hints = $('.hint:not(:parents(.nohints))', element);
  2490 				var hints = $('.hint:not(:parents(.nohints))', element);
  2244 				if (hints.length > 0)
  2491 				if (hints.length > 0) {
  2245 					ams.ajax.check($.fn.tipsy,
  2492 					ams.ajax.check($.fn.tipsy,
  2246 								   ams.baseURL + 'ext/jquery-tipsy' + ams.devext + '.js',
  2493 								   ams.baseURL + 'ext/jquery-tipsy' + ams.devext + '.js',
  2247 								   function() {
  2494 								   function () {
  2248 										ams.getCSS(ams.baseURL + '../css/ext/jquery-tipsy' + ams.devext + '.css',
  2495 									   ams.getCSS(ams.baseURL + '../css/ext/jquery-tipsy' + ams.devext + '.css',
  2249 												  'jquery-tipsy');
  2496 												  'jquery-tipsy');
  2250 										hints.each(function() {
  2497 									   hints.each(function () {
  2251 											var hint = $(this);
  2498 										   var hint = $(this);
  2252 											var data = hint.data();
  2499 										   var data = hint.data();
  2253 											var data_options = {
  2500 										   var data_options = {
  2254 												html: data.amsHintHtml,
  2501 											   html: data.amsHintHtml,
  2255 												title: ams.getFunctionByName(data.amsHintTitleGetter) || function() {
  2502 											   title: ams.getFunctionByName(data.amsHintTitleGetter) || function () {
  2256 													var hint = $(this);
  2503 												   var hint = $(this);
  2257 													return hint.attr('original-title') ||
  2504 												   return hint.attr('original-title') ||
  2258 														   hint.attr(data.amsHintTitleAttr || 'title') ||
  2505 														   hint.attr(data.amsHintTitleAttr || 'title') ||
  2259 														   (data.amsHintHtml ? hint.html() : hint.text());
  2506 														   (data.amsHintHtml ? hint.html() : hint.text());
  2260 												},
  2507 											   },
  2261 												opacity: data.amsHintOpacity || 0.95,
  2508 											   opacity: data.amsHintOpacity || 0.95,
  2262 												gravity: data.amsHintGravity || 'sw',
  2509 											   gravity: data.amsHintGravity || 'sw',
  2263 												offset: data.amsHintOffset || 0
  2510 											   offset: data.amsHintOffset || 0
  2264 											};
  2511 										   };
  2265 											var settings = $.extend({}, data_options, data.amsHintOptions);
  2512 										   var settings = $.extend({}, data_options, data.amsHintOptions);
  2266 											settings = ams.executeFunctionByName(data.amsHintInitCallback, hint, settings) || settings;
  2513 										   settings = ams.executeFunctionByName(data.amsHintInitCallback, hint, settings) || settings;
  2267 											var plugin = hint.tipsy(settings);
  2514 										   var plugin = hint.tipsy(settings);
  2268 											ams.executeFunctionByName(data.amsHintAfterInitCallback, hint, plugin, settings);
  2515 										   ams.executeFunctionByName(data.amsHintAfterInitCallback, hint, plugin, settings);
  2269 										});
  2516 									   });
  2270 								   });
  2517 								   });
       
  2518 				}
  2271 			},
  2519 			},
  2272 
  2520 
  2273 			/**
  2521 			/**
  2274 			 * Context menu plug-in
  2522 			 * Context menu plug-in
  2275 			 */
  2523 			 */
  2300 					var fieldset = legend.parent('fieldset');
  2548 					var fieldset = legend.parent('fieldset');
  2301 					var data = legend.data();
  2549 					var data = legend.data();
  2302 					if (!data.amsSwitcher) {
  2550 					if (!data.amsSwitcher) {
  2303 						$('<i class="fa fa-fw"></i>')
  2551 						$('<i class="fa fa-fw"></i>')
  2304 							.prependTo($(this))
  2552 							.prependTo($(this))
  2305 							.addClass(data.amsSwitcherState == 'open' ?
  2553 							.addClass(data.amsSwitcherState === 'open' ?
  2306 									  (data.amsSwitcherMinusClass || 'fa-minus') :
  2554 									  (data.amsSwitcherMinusClass || 'fa-minus') :
  2307 									  (data.amsSwitcherPlusClass || 'fa-plus'));
  2555 									  (data.amsSwitcherPlusClass || 'fa-plus'));
  2308 						legend.on('click', function(e) {
  2556 						legend.on('click', function(e) {
  2309 							e.preventDefault();
  2557 							e.preventDefault();
  2310 							var veto = {};
  2558 							var veto = {};
  2311 							legend.trigger('ams.switcher.before-switch', [legend, veto]);
  2559 							legend.trigger('ams.switcher.before-switch', [legend, veto]);
  2312 							if (veto.veto)
  2560 							if (veto.veto) {
  2313 								return;
  2561 								return;
       
  2562 							}
  2314 							if (fieldset.hasClass('switched')) {
  2563 							if (fieldset.hasClass('switched')) {
  2315 								fieldset.removeClass('switched');
  2564 								fieldset.removeClass('switched');
  2316 								$('.fa', legend).removeClass(data.amsSwitcherPlusClass || 'fa-plus')
  2565 								$('.fa', legend).removeClass(data.amsSwitcherPlusClass || 'fa-plus')
  2317 												.addClass(data.amsSwitcherMinusClass || 'fa-minus');
  2566 												.addClass(data.amsSwitcherMinusClass || 'fa-minus');
  2318 								legend.trigger('ams.switcher.opened', [legend]);
  2567 								legend.trigger('ams.switcher.opened', [legend]);
  2319 								var id = legend.attr('id');
  2568 								var id = legend.attr('id');
  2320 								if (id) {
  2569 								if (id) {
  2321 									$('legend.switcher[data-ams-switcher-sync="'+id+'"]', fieldset).each(function() {
  2570 									$('legend.switcher[data-ams-switcher-sync="'+id+'"]', fieldset).each(function() {
  2322 										var switcher = $(this);
  2571 										var switcher = $(this);
  2323 										if (switcher.parents('fieldset').hasClass('switched'))
  2572 										if (switcher.parents('fieldset').hasClass('switched')) {
  2324 											switcher.click();
  2573 											switcher.click();
       
  2574 										}
  2325 									});
  2575 									});
  2326 								}
  2576 								}
  2327 							} else {
  2577 							} else {
  2328 								fieldset.addClass('switched');
  2578 								fieldset.addClass('switched');
  2329 								$('.fa', legend).removeClass(data.amsSwitcherMinusClass || 'fa-minus')
  2579 								$('.fa', legend).removeClass(data.amsSwitcherMinusClass || 'fa-minus')
  2330 												.addClass(data.amsSwitcherPlusClass || 'fa-plus');
  2580 												.addClass(data.amsSwitcherPlusClass || 'fa-plus');
  2331 								legend.trigger('ams.switcher.closed', [legend]);
  2581 								legend.trigger('ams.switcher.closed', [legend]);
  2332 							}
  2582 							}
  2333 						});
  2583 						});
  2334 						if (data.amsSwitcherState != 'open')
  2584 						if (data.amsSwitcherState !== 'open') {
  2335 							fieldset.addClass('switched');
  2585 							fieldset.addClass('switched');
       
  2586 						}
  2336 						legend.data('ams-switcher', 'on');
  2587 						legend.data('ams-switcher', 'on');
  2337 					}
  2588 					}
  2338 				});
  2589 				});
  2339 			},
  2590 			},
  2340 
  2591 
  2355 						var checkedValue = data.amsCheckerHiddenValueOn || 'true';
  2606 						var checkedValue = data.amsCheckerHiddenValueOn || 'true';
  2356 						var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
  2607 						var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
  2357 						var marker = data.amsCheckerMarker || false;
  2608 						var marker = data.amsCheckerMarker || false;
  2358 						if (prefix) {
  2609 						if (prefix) {
  2359 							hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
  2610 							hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
  2360 															   .val(data.amsCheckerState == 'on' ? checkedValue : uncheckedValue)
  2611 															   .val(data.amsCheckerState === 'on' ? checkedValue : uncheckedValue)
  2361 															   .prependTo(legend);
  2612 															   .prependTo(legend);
  2362 						} else if (marker) {
  2613 						} else if (marker) {
  2363 							$('<input type="hidden">').attr('name', marker)
  2614 							$('<input type="hidden">').attr('name', marker)
  2364 													  .attr('value', 1)
  2615 													  .attr('value', 1)
  2365 													  .prependTo(legend);
  2616 													  .prependTo(legend);
  2367 						var input = $('<input type="checkbox">').attr('name', fieldname)
  2618 						var input = $('<input type="checkbox">').attr('name', fieldname)
  2368 																.attr('id', checkbox_id)
  2619 																.attr('id', checkbox_id)
  2369 																.data('ams-checker-hidden-input', hidden)
  2620 																.data('ams-checker-hidden-input', hidden)
  2370 																.data('ams-checker-init', true)
  2621 																.data('ams-checker-init', true)
  2371 																.val(data.amsCheckerValue || true)
  2622 																.val(data.amsCheckerValue || true)
  2372 																.attr('checked', data.amsCheckerState == 'on' ? 'checked' : null);
  2623 																.attr('checked', data.amsCheckerState === 'on' ? 'checked' : null);
  2373 						if (data.amsCheckerReadonly) {
  2624 						if (data.amsCheckerReadonly) {
  2374 							input.attr('disabled', 'disabled');
  2625 							input.attr('disabled', 'disabled');
  2375 						} else {
  2626 						} else {
  2376 							input.on('change', function(e) {
  2627 							input.on('change', function(e) {
  2377 								e.preventDefault();
  2628 								e.preventDefault();
  2385 								}
  2636 								}
  2386 								ams.executeFunctionByName(data.amsCheckerChangeHandler, legend, isChecked);
  2637 								ams.executeFunctionByName(data.amsCheckerChangeHandler, legend, isChecked);
  2387 								if (!data.amsCheckerCancelDefault) {
  2638 								if (!data.amsCheckerCancelDefault) {
  2388 									var hidden = input.data('ams-checker-hidden-input');
  2639 									var hidden = input.data('ams-checker-hidden-input');
  2389 									if (isChecked) {
  2640 									if (isChecked) {
  2390 										if (data.amsCheckerMode == 'disable')
  2641 										if (data.amsCheckerMode === 'disable') {
  2391 											fieldset.removeAttr('disabled');
  2642 											fieldset.removeAttr('disabled');
  2392 										else
  2643 										} else {
  2393 											fieldset.removeClass('switched');
  2644 											fieldset.removeClass('switched');
  2394 										if (hidden)
  2645 										}
       
  2646 										if (hidden) {
  2395 											hidden.val(checkedValue);
  2647 											hidden.val(checkedValue);
       
  2648 										}
  2396 										$('[data-required]', fieldset).attr('required', 'required');
  2649 										$('[data-required]', fieldset).attr('required', 'required');
  2397 										legend.trigger('ams.checker.opened', [legend]);
  2650 										legend.trigger('ams.checker.opened', [legend]);
  2398 									} else {
  2651 									} else {
  2399 										if (data.amsCheckerMode == 'disable')
  2652 										if (data.amsCheckerMode === 'disable') {
  2400 											fieldset.prop('disabled', 'disabled');
  2653 											fieldset.prop('disabled', 'disabled');
  2401 										else
  2654 										} else {
  2402 											fieldset.addClass('switched');
  2655 											fieldset.addClass('switched');
  2403 										if (hidden)
  2656 										}
       
  2657 										if (hidden) {
  2404 											hidden.val(uncheckedValue);
  2658 											hidden.val(uncheckedValue);
       
  2659 										}
  2405 										$('[data-required]', fieldset).removeAttr('required');
  2660 										$('[data-required]', fieldset).removeAttr('required');
  2406 										legend.trigger('ams.checker.closed', [legend]);
  2661 										legend.trigger('ams.checker.closed', [legend]);
  2407 									}
  2662 									}
  2408 								}
  2663 								}
  2409 							});
  2664 							});
  2412 						$('>label', legend).attr('for', input.attr('id'));
  2667 						$('>label', legend).attr('for', input.attr('id'));
  2413 						checker.append('<i></i>')
  2668 						checker.append('<i></i>')
  2414 							   .prependTo(legend);
  2669 							   .prependTo(legend);
  2415 						var required = $('[required]', fieldset);
  2670 						var required = $('[required]', fieldset);
  2416 						required.attr('data-required', true);
  2671 						required.attr('data-required', true);
  2417 						if (data.amsCheckerState == 'on') {
  2672 						if (data.amsCheckerState === 'on') {
  2418 							input.attr('checked', true);
  2673 							input.attr('checked', true);
  2419 						} else {
  2674 						} else {
  2420 							if (data.amsCheckerMode == 'disable')
  2675 							if (data.amsCheckerMode === 'disable') {
  2421 								fieldset.attr('disabled', 'disabled');
  2676 								fieldset.attr('disabled', 'disabled');
  2422 							else
  2677 							} else {
  2423 								fieldset.addClass('switched');
  2678 								fieldset.addClass('switched');
       
  2679 							}
  2424 							required.removeAttr('required');
  2680 							required.removeAttr('required');
  2425 						}
  2681 						}
  2426 						legend.data('ams-checker', 'on');
  2682 						legend.data('ams-checker', 'on');
  2427 					}
  2683 					}
  2428 				});
  2684 				});
  2569 												maximumSelectionSize: data.amsSelect2MaximumSelectionSize,
  2825 												maximumSelectionSize: data.amsSelect2MaximumSelectionSize,
  2570 												openOnEnter: data.amsSelect2EnterOpen === undefined ? true : data.amsSelect2EnterOpen,
  2826 												openOnEnter: data.amsSelect2EnterOpen === undefined ? true : data.amsSelect2EnterOpen,
  2571 												allowClear: data.amsSelect2AllowClear === undefined ? true : data.amsSelect2AllowClear,
  2827 												allowClear: data.amsSelect2AllowClear === undefined ? true : data.amsSelect2AllowClear,
  2572 												width: data.amsSelect2Width || '100%',
  2828 												width: data.amsSelect2Width || '100%',
  2573 												initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
  2829 												initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
  2574 												formatSelection: data.amsSelect2FormatSelection === undefined
  2830 												formatSelection: data.amsSelect2FormatSelection === undefined ?
  2575 																	? ams.helpers.select2FormatSelection
  2831 																	ams.helpers.select2FormatSelection
  2576 																	: ams.getFunctionByName(data.amsSelect2FormatSelection),
  2832 																	: ams.getFunctionByName(data.amsSelect2FormatSelection),
  2577 												formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
  2833 												formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
  2578 												formatMatches: data.amsSelect2FormatMatches === undefined
  2834 												formatMatches: data.amsSelect2FormatMatches === undefined ?
  2579 																	? function(matches) {
  2835 																	function(matches) {
  2580 																		if (matches == 1)
  2836 																		if (matches === 1) {
  2581 																			return ams.i18n.SELECT2_MATCH;
  2837 																			return ams.i18n.SELECT2_MATCH;
  2582 																		else
  2838 																		} else {
  2583 																			return matches + ams.i18n.SELECT2_MATCHES;
  2839 																			return matches + ams.i18n.SELECT2_MATCHES;
       
  2840 																		}
  2584 																	}
  2841 																	}
  2585 																	: ams.getFunctionByName(data.amsSelect2FormatMatches),
  2842 																	: ams.getFunctionByName(data.amsSelect2FormatMatches),
  2586 												formatNoMatches: data.amsSelect2FormatResult === undefined
  2843 												formatNoMatches: data.amsSelect2FormatResult === undefined ?
  2587 																	? function(term) {
  2844 																	function(term) {
  2588 																		return ams.i18n.SELECT2_NOMATCHES;
  2845 																		return ams.i18n.SELECT2_NOMATCHES;
  2589 																	}
  2846 																	}
  2590 																	: ams.getFunctionByName(data.amsSelect2FormatResult),
  2847 																	: ams.getFunctionByName(data.amsSelect2FormatResult),
  2591 												formatInputTooShort: data.amsSelect2FormatInputTooShort === undefined
  2848 												formatInputTooShort: data.amsSelect2FormatInputTooShort === undefined ?
  2592 																	? function(input, min) {
  2849 																	function(input, min) {
  2593 																		var n = min - input.length;
  2850 																		var n = min - input.length;
  2594 																		return ams.i18n.SELECT2_INPUT_TOOSHORT
  2851 																		return ams.i18n.SELECT2_INPUT_TOOSHORT
  2595 																						.replace(/\{0\}/, n)
  2852 																						.replace(/\{0\}/, n)
  2596 																						.replace(/\{1\}/, n == 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2853 																						.replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2597 																	}
  2854 																	}
  2598 																	: ams.getFunctionByName(data.amsSelect2FormatInputTooShort),
  2855 																	: ams.getFunctionByName(data.amsSelect2FormatInputTooShort),
  2599 												formatInputTooLong: data.amsSelect2FormatInputTooLong === undefined
  2856 												formatInputTooLong: data.amsSelect2FormatInputTooLong === undefined ?
  2600 																	? function(input, max) {
  2857 																	function(input, max) {
  2601 																		var n = input.length - max;
  2858 																		var n = input.length - max;
  2602 																		return ams.i18n.SELECT2_INPUT_TOOLONG
  2859 																		return ams.i18n.SELECT2_INPUT_TOOLONG
  2603 																						.replace(/\{0\}/, n)
  2860 																						.replace(/\{0\}/, n)
  2604 																						.replace(/\{1\}/, n == 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2861 																						.replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2605 																	}
  2862 																	}
  2606 																	: ams.getFunctionByName(data.amsSelect2FormatInputTooLong),
  2863 																	: ams.getFunctionByName(data.amsSelect2FormatInputTooLong),
  2607 												formatSelectionTooBig: data.amsSelect2FormatSelectionTooBig === undefined
  2864 												formatSelectionTooBig: data.amsSelect2FormatSelectionTooBig === undefined ?
  2608 																	? function(limit) {
  2865 																	function(limit) {
  2609 																		return ams.i18n.SELECT2_SELECTION_TOOBIG
  2866 																		return ams.i18n.SELECT2_SELECTION_TOOBIG
  2610 																						.replace(/\{0\}/, limit)
  2867 																						.replace(/\{0\}/, limit)
  2611 																						.replace(/\{1\}/, limit == 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2868 																						.replace(/\{1\}/, limit === 1 ? "" : ams.i18n.SELECT2_PLURAL);
  2612 																	}
  2869 																	}
  2613 																	: ams.getFunctionByName(data.amsSelect2FormatSelectionTooBig),
  2870 																	: ams.getFunctionByName(data.amsSelect2FormatSelectionTooBig),
  2614 												formatLoadMore: data.amsSelect2FormatLoadMore === undefined
  2871 												formatLoadMore: data.amsSelect2FormatLoadMore === undefined ?
  2615 																	? function (pageNumber) {
  2872 																	function (pageNumber) {
  2616 																		return ams.i18n.SELECT2_LOADMORE;
  2873 																		return ams.i18n.SELECT2_LOADMORE;
  2617 																	}
  2874 																	}
  2618 																	: ams.getFunctionByName(data.amsSelect2FormatLoadMore),
  2875 																	: ams.getFunctionByName(data.amsSelect2FormatLoadMore),
  2619 												formatSearching: data.amsSelect2FormatSearching === undefined
  2876 												formatSearching: data.amsSelect2FormatSearching === undefined ?
  2620 																	? function() {
  2877 																	function() {
  2621 																		return ams.i18n.SELECT2_SEARCHING;
  2878 																		return ams.i18n.SELECT2_SEARCHING;
  2622 																	}
  2879 																	}
  2623 																	: ams.getFunctionByName(data.amsSelect2FormatSearching),
  2880 																	: ams.getFunctionByName(data.amsSelect2FormatSearching),
  2624 												separator: data.amsSelect2Separator || ',',
  2881 												separator: data.amsSelect2Separator || ',',
  2625 												tokenSeparators: data.amsSelect2TokensSeparators || [','],
  2882 												tokenSeparators: data.amsSelect2TokensSeparators || [','],
  2637 																$(element.val().split(data_options.separator)).each(function() {
  2894 																$(element.val().split(data_options.separator)).each(function() {
  2638 																	data.push({id: this,
  2895 																	data.push({id: this,
  2639 																			   text: values_data[this] || this});
  2896 																			   text: values_data[this] || this});
  2640 																});
  2897 																});
  2641 																callback(data);
  2898 																callback(data);
  2642 															}
  2899 															};
  2643 														}
  2900 														}
  2644 													}
  2901 													}
  2645 													break;
  2902 													break;
  2646 												default:
  2903 												default:
  2647 													break;
  2904 													break;
  2648 											}
  2905 											}
  2649 
  2906 
  2650 											if (select.attr('readonly')) {
  2907 											if (select.attr('readonly')) {
  2651 												if (select.attr('type') == 'hidden') {
  2908 												if (select.attr('type') === 'hidden') {
  2652 													data_options.query = function () {
  2909 													data_options.query = function () {
  2653 														return [];
  2910 														return [];
  2654 													};
  2911 													};
  2655 												}
  2912 												}
  2656 											} else if (data.amsSelect2Query) {
  2913 											} else if (data.amsSelect2Query) {
  2732 															   });
  2989 															   });
  2733 											}
  2990 											}
  2734 
  2991 
  2735 											select.on('change', function() {
  2992 											select.on('change', function() {
  2736 												var validator = $(select.get(0).form).data('validator');
  2993 												var validator = $(select.get(0).form).data('validator');
  2737 												if (validator !== undefined)
  2994 												if (validator !== undefined) {
  2738 													$(select).valid();
  2995 													$(select).valid();
       
  2996 												}
  2739 											});
  2997 											});
  2740 										});
  2998 										});
  2741 								   });
  2999 								   });
  2742 				}
  3000 				}
  2743 			},
  3001 			},
  2753 								   function() {
  3011 								   function() {
  2754 										masks.each(function() {
  3012 										masks.each(function() {
  2755 											var mask = $(this);
  3013 											var mask = $(this);
  2756 											var data = mask.data();
  3014 											var data = mask.data();
  2757 											var data_options = {
  3015 											var data_options = {
  2758 												placeholder: data.amsMaskeditPlaceholder || 'X'
  3016 												placeholder: data.amsMaskeditPlaceholder === undefined ? 'X' : data.amsMaskeditPlaceholder,
       
  3017 												complete: ams.getFunctionByName(data.amsMaskeditComplete)
  2759 											};
  3018 											};
  2760 											var settings = $.extend({}, data_options, data.amsMaskeditOptions);
  3019 											var settings = $.extend({}, data_options, data.amsMaskeditOptions);
  2761 											settings = ams.executeFunctionByName(data.amsMaskeditInitCallback, mask, settings) || settings;
  3020 											settings = ams.executeFunctionByName(data.amsMaskeditInitCallback, mask, settings) || settings;
  2762 											var plugin = mask.mask(mask.attr('data-mask'), settings);
  3021 											var plugin = mask.mask(mask.attr('data-mask'), settings);
  2763 											ams.executeFunctionByName(data.amsMaskeditAfterInitCallback, mask, plugin, settings);
  3022 											ams.executeFunctionByName(data.amsMaskeditAfterInitCallback, mask, plugin, settings);
  2907 												},
  3166 												},
  2908 												errorElement: 'span',
  3167 												errorElement: 'span',
  2909 												errorClass: 'state-error',
  3168 												errorClass: 'state-error',
  2910 												errorPlacement: function(error, element) {
  3169 												errorPlacement: function(error, element) {
  2911 													var label = element.parents('label:first');
  3170 													var label = element.parents('label:first');
  2912 													if (label.length)
  3171 													if (label.length) {
  2913 														error.insertAfter(label);
  3172 														error.insertAfter(label);
  2914 													else
  3173 													} else {
  2915 														error.insertAfter(element);
  3174 														error.insertAfter(element);
       
  3175 													}
  2916 												}
  3176 												}
  2917 											});
  3177 											});
  2918 											if (ams.plugins.i18n) {
  3178 											if (ams.plugins.i18n) {
  2919 												for (var key in ams.plugins.i18n.validate) {
  3179 												for (var key in ams.plugins.i18n.validate) {
       
  3180 													if (!ams.plugins.i18n.validate.hasOwnProperty(key)) {
       
  3181 														continue;
       
  3182 													}
  2920 													var message = ams.plugins.i18n.validate[key];
  3183 													var message = ams.plugins.i18n.validate[key];
  2921 													if ((typeof(message) == 'string') &&
  3184 													if ((typeof(message) === 'string') &&
  2922 														(message.indexOf('{0}') > -1))
  3185 														(message.indexOf('{0}') > -1)) {
  2923 														ams.plugins.i18n.validate[key] = $.validator.format(message);
  3186 														ams.plugins.i18n.validate[key] = $.validator.format(message);
       
  3187 													}
  2924 												}
  3188 												}
  2925 												$.extend($.validator.messages, ams.plugins.i18n.validate);
  3189 												$.extend($.validator.messages, ams.plugins.i18n.validate);
  2926 											}
  3190 											}
  2927 										}
  3191 										}
  2928 										forms.each(function() {
  3192 										forms.each(function() {
  2929 											var form = $(this);
  3193 											var form = $(this);
  2930 											var data = form.data();
  3194 											var data = form.data();
  2931 											var data_options = {
  3195 											var data_options = {
  2932 												ignore: null,
  3196 												ignore: null,
  2933 												submitHandler: form.attr('data-async') !== undefined
  3197 												submitHandler: form.attr('data-async') !== undefined ?
  2934 															   ? data.amsFormSubmitHandler === undefined
  3198 															   data.amsFormSubmitHandler === undefined ?
  2935 																	? function() {
  3199 																	function() {
  2936 																		// JQuery-form plug-in must be loaded synchronously!!
  3200 																		// JQuery-form plug-in must be loaded synchronously!!
  2937 																		// Otherwise, hidden input fields created by jquery-validate plug-in
  3201 																		// Otherwise, hidden input fields created by jquery-validate plug-in
  2938 																		// and matching named buttons will be deleted (on first form submit)
  3202 																		// and matching named buttons will be deleted (on first form submit)
  2939 																		// before JQuery-form plug-in can get them when submitting the form...
  3203 																		// before JQuery-form plug-in can get them when submitting the form...
  2940 																		$('.state-error', form).removeClass('state-error');
  3204 																		$('.state-error', form).removeClass('state-error');
  2942 																					   ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js');
  3206 																					   ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js');
  2943 																		return ams.form.submit(form);
  3207 																		return ams.form.submit(form);
  2944 																	}
  3208 																	}
  2945 																	: ams.getFunctionByName(data.amsFormSubmitHandler)
  3209 																	: ams.getFunctionByName(data.amsFormSubmitHandler)
  2946 															   : undefined,
  3210 															   : undefined,
  2947 												invalidHandler: form.attr('data-async') !== undefined
  3211 												invalidHandler: form.attr('data-async') !== undefined ?
  2948 																? data.amsFormInvalidHandler === undefined
  3212 																data.amsFormInvalidHandler === undefined ?
  2949 																	? function(event, validator) {
  3213 																	function(event, validator) {
  2950 																		$('.state-error', form).removeClass('state-error');
  3214 																		$('.state-error', form).removeClass('state-error');
  2951 																		for (var index in validator.errorList) {
  3215 																		for (var index=0; index < validator.errorList.length; index++) {
  2952 																			var error = validator.errorList[index];
  3216 																			var error = validator.errorList[index];
  2953 																			var tab_index = $(error.element).parents('.tab-pane').index() + 1;
  3217 																			var tab_index = $(error.element).parents('.tab-pane').index() + 1;
  2954 																			if (tab_index > 0) {
  3218 																			if (tab_index > 0) {
  2955 																				var nav_tabs = $('.nav-tabs', $(error.element).parents('.tabforms'));
  3219 																				var nav_tabs = $('.nav-tabs', $(error.element).parents('.tabforms'));
  2956 																				$('li:nth-child(' + tab_index + ')', nav_tabs)
  3220 																				$('li:nth-child(' + tab_index + ')', nav_tabs)
  2980 				if (tables.length > 0) {
  3244 				if (tables.length > 0) {
  2981 					ams.ajax.check($.fn.dataTable,
  3245 					ams.ajax.check($.fn.dataTable,
  2982 								   ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js',
  3246 								   ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js',
  2983 								   function(first_load) {
  3247 								   function(first_load) {
  2984 										$(tables).each(function() {
  3248 										$(tables).each(function() {
  2985 											ams.ajax.check($.fn.dataTableExt.oPagination['bootstrap_full'],
  3249 											ams.ajax.check($.fn.dataTableExt.oPagination.bootstrap_full,
  2986 														   ams.baseURL + 'myams-dataTables' + ams.devext + '.js');
  3250 														   ams.baseURL + 'myams-dataTables' + ams.devext + '.js');
  2987 											var table = $(this);
  3251 											var table = $(this);
  2988 											var data = table.data();
  3252 											var data = table.data();
  2989 											var extensions = (data.amsDatatableExtensions || '').split(/\s+/);
  3253 											var extensions = (data.amsDatatableExtensions || '').split(/\s+/);
  2990 											// Check DOM elements
  3254 											// Check DOM elements
  3000 												">r<'dt-wrapper't" +
  3264 												">r<'dt-wrapper't" +
  3001 												(extensions.indexOf('scroller') >= 0 ? 'S' : '') +
  3265 												(extensions.indexOf('scroller') >= 0 ? 'S' : '') +
  3002 												"><'dt-row dt-bottom-row'<'row'<'col-sm-6'" +
  3266 												"><'dt-row dt-bottom-row'<'row'<'col-sm-6'" +
  3003 												(data.amsDatatableInformation === false ? '': 'i') +
  3267 												(data.amsDatatableInformation === false ? '': 'i') +
  3004 												"><'col-sm-6 text-right'p>>";
  3268 												"><'col-sm-6 text-right'p>>";
       
  3269 
  3005 											var index;
  3270 											var index;
  3006 											// Check initial sorting
  3271 											// Check initial sorting
  3007 											var sorting = data.amsDatatableSorting;
  3272 											var sorting = data.amsDatatableSorting;
  3008 											if (typeof(sorting) === 'string') {
  3273 											if (typeof(sorting) === 'string') {
  3009 												var sortings = sorting.split(';');
  3274 												var sortings = sorting.split(';');
  3010 												sorting = [];
  3275 												sorting = [];
  3011 												for (index in sortings) {
  3276 												for (index=0; index < sortings.length; index++) {
  3012 													var col_sorting = sortings[index].split(',');
  3277 													var col_sorting = sortings[index].split(',');
  3013 													col_sorting[0] = parseInt(col_sorting[0]);
  3278 													col_sorting[0] = parseInt(col_sorting[0]);
  3014 													sorting.push(col_sorting);
  3279 													sorting.push(col_sorting);
  3015 												}
  3280 												}
  3016 											}
  3281 											}
  3017 											// Check columns types
  3282 											// Check columns types
  3018 											var columns = [];
  3283 											var columns = [];
  3019 											var sort_types = $('th', table).listattr('data-ams-datatable-stype');
  3284 											var sort_types = $('th', table).listattr('data-ams-datatable-stype');
  3020 											for (index in sort_types) {
  3285 											for (index=0; index < sort_types.length; index++) {
  3021 												var sort_type = sort_types[index];
  3286 												var sort_type = sort_types[index];
  3022 												if (sort_type) {
  3287 												if (sort_type) {
  3023 													var column = columns[index] || {};
  3288 													var column = columns[index] || {};
  3024 													column.sType = sort_type;
  3289 													column.sType = sort_type;
  3025 													columns[index] = column;
  3290 													columns[index] = column;
  3045 																	   .html((ams.plugins.i18n.datatables.sColumns || "Columns") + ' <i class="fa fa-fw fa-caret-down"></i>');
  3310 																	   .html((ams.plugins.i18n.datatables.sColumns || "Columns") + ' <i class="fa fa-fw fa-caret-down"></i>');
  3046 												}
  3311 												}
  3047 											};
  3312 											};
  3048 											var settings = $.extend({}, data_options, data.amsDatatableOptions);
  3313 											var settings = $.extend({}, data_options, data.amsDatatableOptions);
  3049 											if (extensions.length > 0) {
  3314 											if (extensions.length > 0) {
  3050 												for (index in extensions) {
  3315 												for (index=0; index < extensions.length; index++) {
  3051 													switch (extensions[index]) {
  3316 													switch (extensions[index]) {
  3052 														case 'autofill':
  3317 														case 'autofill':
  3053 															ams.ajax.check($.fn.dataTable.AutoFill,
  3318 															ams.ajax.check($.fn.dataTable.AutoFill,
  3054 																		   ams.baseURL + 'ext/jquery-dataTables-autoFill' + ams.devext + '.js');
  3319 																		   ams.baseURL + 'ext/jquery-dataTables-autoFill' + ams.devext + '.js');
  3055 															break;
  3320 															break;
  3112 											settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
  3377 											settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
  3113 											try {  // Some settings can easilly generate DataTables exceptions...
  3378 											try {  // Some settings can easilly generate DataTables exceptions...
  3114 												var plugin = table.dataTable(settings);
  3379 												var plugin = table.dataTable(settings);
  3115 												ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
  3380 												ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
  3116 												if (extensions.length > 0) {
  3381 												if (extensions.length > 0) {
  3117 													for (index in extensions) {
  3382 													for (index=0; index < extensions.length; index++) {
  3118 														switch (extensions[index]) {
  3383 														switch (extensions[index]) {
  3119 															case 'autofill':
  3384 															case 'autofill':
  3120 																var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
  3385 																var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
  3121 																af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings;
  3386 																af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings;
  3122 																table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined
  3387 																table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined ?
  3123 																							? new $.fn.dataTable.AutoFill(table, af_settings)
  3388 																							new $.fn.dataTable.AutoFill(table, af_settings)
  3124 																							: ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, af_settings));
  3389 																							: ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, af_settings));
  3125 																break;
  3390 																break;
  3126 															case 'columnfilter':
  3391 															case 'columnfilter':
  3127 																var cf_default = {
  3392 																var cf_default = {
  3128 																	sPlaceHolder: 'head:after'
  3393 																	sPlaceHolder: 'head:after'
  3129 																};
  3394 																};
  3130 																var cf_settings = $.extend({}, cf_default, data.amsDatatableColumnfilterOptions, settings.columnfilter);
  3395 																var cf_settings = $.extend({}, cf_default, data.amsDatatableColumnfilterOptions, settings.columnfilter);
  3131 																cf_settings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cf_settings) || cf_settings;
  3396 																cf_settings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cf_settings) || cf_settings;
  3132 																table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined
  3397 																table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined ?
  3133 																							? plugin.columnFilter(cf_settings)
  3398 																							plugin.columnFilter(cf_settings)
  3134 																							: ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cf_settings));
  3399 																							: ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cf_settings));
  3135 																break;
  3400 																break;
  3136 															case 'editable':
  3401 															case 'editable':
  3137 																var ed_settings = $.extend({}, data.amsDatatableEditableOptions, settings.editable);
  3402 																var ed_settings = $.extend({}, data.amsDatatableEditableOptions, settings.editable);
  3138 																ed_settings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, ed_settings) || ed_settings;
  3403 																ed_settings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, ed_settings) || ed_settings;
  3139 																table.data('ams-editable', data.amsDatatableEditableConstructor === undefined
  3404 																table.data('ams-editable', data.amsDatatableEditableConstructor === undefined ?
  3140 																							? table.makeEditable(ed_settings)
  3405 																							table.makeEditable(ed_settings)
  3141 																							: ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, ed_settings));
  3406 																							: ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, ed_settings));
  3142 																break;
  3407 																break;
  3143 															case 'fixedcolumns':
  3408 															case 'fixedcolumns':
  3144 																var fc_settings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns);
  3409 																var fc_settings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns);
  3145 																fc_settings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fc_settings) || fc_settings;
  3410 																fc_settings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fc_settings) || fc_settings;
  3146 																table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined
  3411 																table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined ?
  3147 																							? new $.fn.dataTable.FixedColumns(table, fc_settings)
  3412 																							new $.fn.dataTable.FixedColumns(table, fc_settings)
  3148 																							: ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fc_settings));
  3413 																							: ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fc_settings));
  3149 																break;
  3414 																break;
  3150 															case 'fixedheader':
  3415 															case 'fixedheader':
  3151 																var fh_settings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader);
  3416 																var fh_settings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader);
  3152 																fh_settings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fh_settings) || fh_settings;
  3417 																fh_settings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fh_settings) || fh_settings;
  3153 																table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined
  3418 																table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined ?
  3154 																							? new $.fn.dataTable.FixedHeader(table, fh_settings)
  3419 																							new $.fn.dataTable.FixedHeader(table, fh_settings)
  3155 																							: ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fh_settings));
  3420 																							: ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fh_settings));
  3156 																break;
  3421 																break;
  3157 															case 'keytable':
  3422 															case 'keytable':
  3158 																var kt_default = {
  3423 																var kt_default = {
  3159 																	table: table.get(0),
  3424 																	table: table.get(0),
  3160 																	datatable: plugin
  3425 																	datatable: plugin
  3161 																};
  3426 																};
  3162 																var kt_settings = $.extend({}, kt_default, data.amsDatatableKeytableOptions, settings.keytable);
  3427 																var kt_settings = $.extend({}, kt_default, data.amsDatatableKeytableOptions, settings.keytable);
  3163 																kt_settings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, kt_settings) || kt_settings;
  3428 																kt_settings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, kt_settings) || kt_settings;
  3164 																table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined
  3429 																table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined ?
  3165 																							? new KeyTable(kt_settings)
  3430 																							new KeyTable(kt_settings)
  3166 																							: ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, kt_settings));
  3431 																							: ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, kt_settings));
  3167 																break;
  3432 																break;
  3168 															case 'rowgrouping':
  3433 															case 'rowgrouping':
  3169 																var rg_settings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping);
  3434 																var rg_settings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping);
  3170 																rg_settings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rg_settings) || rg_settings;
  3435 																rg_settings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rg_settings) || rg_settings;
  3171 																table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined
  3436 																table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined ?
  3172 																							? table.rowGrouping(rg_settings)
  3437 																							table.rowGrouping(rg_settings)
  3173 																							: ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rg_settings));
  3438 																							: ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rg_settings));
  3174 																break;
  3439 																break;
  3175 															case 'rowreordering':
  3440 															case 'rowreordering':
  3176 																var rr_settings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering);
  3441 																var rr_settings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering);
  3177 																rr_settings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rr_settings) || rr_settings;
  3442 																rr_settings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rr_settings) || rr_settings;
  3178 																table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined
  3443 																table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined ?
  3179 																							? table.rowReordering(rr_settings)
  3444 																							table.rowReordering(rr_settings)
  3180 																							: ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rr_settings));
  3445 																							: ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rr_settings));
  3181 																break;
  3446 																break;
  3182 															default:
  3447 															default:
  3183 																break;
  3448 																break;
  3184 														}
  3449 														}
  3185 													}
  3450 													}
  3186 												}
  3451 												}
  3187 												var finalizers = (data.amsDatatableFinalizeCallback || '').split(/\s+/);
  3452 												var finalizers = (data.amsDatatableFinalizeCallback || '').split(/\s+/);
  3188 												if (finalizers.length > 0) {
  3453 												if (finalizers.length > 0) {
  3189 													for (index in finalizers) {
  3454 													for (index=0; index < finalizers.length; index++) {
  3190 														ams.executeFunctionByName(finalizers[index], table, plugin, settings);
  3455 														ams.executeFunctionByName(finalizers[index], table, plugin, settings);
  3191 													}
  3456 													}
  3192 												}
  3457 												}
  3193 											}
  3458 											}
  3194 											catch (e) {}
  3459 											catch (e) {}
  3206 					ams.ajax.check($.fn.tableDnD,
  3471 					ams.ajax.check($.fn.tableDnD,
  3207 								   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
  3472 								   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
  3208 								   function(first_load) {
  3473 								   function(first_load) {
  3209 										tables.each(function() {
  3474 										tables.each(function() {
  3210 											var table = $(this);
  3475 											var table = $(this);
  3211 											$(table).on('mouseover', 'tr', function() {
       
  3212 												$(this.cells[0]).addClass('drag-handle');
       
  3213 											}).on('mouseout', 'tr', function() {
       
  3214 												$(this.cells[0]).removeClass('drag-handle');
       
  3215 											});
       
  3216 											var data = table.data();
  3476 											var data = table.data();
       
  3477 											if (data.amsTabledndDragHandle) {
       
  3478 												$('tr', table).addClass('no-drag-handle');
       
  3479 											} else {
       
  3480 												$(table).on('mouseover', 'tr', function () {
       
  3481 													$(this.cells[0]).addClass('drag-handle');
       
  3482 												}).on('mouseout', 'tr', function () {
       
  3483 													$(this.cells[0]).removeClass('drag-handle');
       
  3484 												});
       
  3485 											}
  3217 											var data_options = {
  3486 											var data_options = {
  3218 												onDragClass: data.amsTabledndDragClass || 'dragging-row',
  3487 												onDragClass: data.amsTabledndDragClass || 'dragging-row',
  3219 												onDragStart: data.amsTabledndDragStart,
  3488 												onDragStart: ams.getFunctionByName(data.amsTabledndDragStart),
  3220 												dragHandle: data.amsTabledndDragHandle,
  3489 												dragHandle: data.amsTabledndDragHandle,
  3221 												scrollAmount: data.amsTabledndScrollAmount,
  3490 												scrollAmount: data.amsTabledndScrollAmount,
  3222 												onAllowDrop: data.amsTabledndAllowDrop,
  3491 												onAllowDrop: data.amsTabledndAllowDrop,
  3223 												onDrop: data.amsTabledndDrop || function(dnd_table, row) {
  3492 												onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) {
  3224 													var target = data.amsTabledndDropTarget;
  3493 													var target = data.amsTabledndDropTarget;
  3225 													if (target) {
  3494 													if (target) {
       
  3495 														// Disable row click handler
       
  3496 														$(row).data('ams-disabled-handlers', 'click');
  3226 														var rows = [];
  3497 														var rows = [];
  3227 														$(dnd_table.rows).each(function() {
  3498 														$(dnd_table.rows).each(function() {
  3228 															var row_id = $(this).data('ams-element-name');
  3499 															var row_id = $(this).data('ams-element-name');
  3229 															if (row_id)
  3500 															if (row_id) {
  3230 																rows.push(row_id);
  3501 																rows.push(row_id);
       
  3502 															}
  3231 														});
  3503 														});
  3232 														var local_target = ams.getFunctionByName(target);
  3504 														var local_target = ams.getFunctionByName(target);
  3233 														if (typeof(local_target) == 'function') {
  3505 														if (typeof(local_target) === 'function') {
  3234 															local_target.call(table, dnd_table, rows);
  3506 															local_target.call(table, dnd_table, rows);
  3235 														} else {
  3507 														} else {
  3236 															ams.ajax.post(target, {names: JSON.stringify(rows)});
  3508 															ams.ajax.post(target, {names: JSON.stringify(rows)});
  3237 														}
  3509 														}
       
  3510 														// Restore row click handler
       
  3511 														setTimeout(function() {
       
  3512 															$(row).removeData('ams-disabled-handlers');
       
  3513 														}, 50);
  3238 													}
  3514 													}
  3239 													return false;
  3515 													return false;
  3240 												}
  3516 												}
  3241 											};
  3517 											};
  3242 											var settings = $.extend({}, data_options, data.amsTabledndOptions);
  3518 											var settings = $.extend({}, data_options, data.amsTabledndOptions);
  3280 											var data_options = {
  3556 											var data_options = {
  3281 												theme: "modern",
  3557 												theme: "modern",
  3282 												language: ams.lang,
  3558 												language: ams.lang,
  3283 												plugins: [
  3559 												plugins: [
  3284 													"advlist autosave autolink lists link image charmap print preview hr anchor pagebreak",
  3560 													"advlist autosave autolink lists link image charmap print preview hr anchor pagebreak",
  3285 													"searchreplace wordcount visualblocks visualchars code fullscreen",
  3561 													"searchreplace wordcount visualblocks visualchars code",
  3286 													"insertdatetime media nonbreaking save table contextmenu directionality",
  3562 													"insertdatetime media nonbreaking save table contextmenu directionality",
  3287 													"emoticons paste textcolor colorpicker textpattern"
  3563 													"emoticons paste textcolor colorpicker textpattern"
  3288 												],
  3564 												],
  3289 												toolbar1: "newdocument undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
  3565 												toolbar1: "newdocument undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
  3290 												toolbar2: "print preview media | forecolor backcolor emoticons | code fullscreen",
  3566 												toolbar2: "print preview media | forecolor backcolor emoticons | code",
  3291 												content_css: data.amsTinymceContentCss,
  3567 												content_css: data.amsTinymceContentCss,
  3292 												formats: data.amsTinymceFormats,
  3568 												formats: data.amsTinymceFormats,
  3293 												style_formats: data.amsTinymceStyleFormats,
  3569 												style_formats: data.amsTinymceStyleFormats,
  3294 												block_formats: data.amsTinymceBlockFormats,
  3570 												block_formats: data.amsTinymceBlockFormats,
  3295 												valid_classes: data.amsTinymceValidClasses,
  3571 												valid_classes: data.amsTinymceValidClasses,
  3323 				var images = $('.imgareaselect', element);
  3599 				var images = $('.imgareaselect', element);
  3324 				if (images.length > 0) {
  3600 				if (images.length > 0) {
  3325 					ams.ajax.check($.fn.imgAreaSelect,
  3601 					ams.ajax.check($.fn.imgAreaSelect,
  3326 								   ams.baseURL + 'ext/jquery-imgareaselect-0.9.10' + ams.devext + '.js',
  3602 								   ams.baseURL + 'ext/jquery-imgareaselect-0.9.10' + ams.devext + '.js',
  3327 								   function(first_load) {
  3603 								   function(first_load) {
  3328 									   if (first_load)
  3604 									   if (first_load) {
  3329 										   ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + ams.devext + '.css');
  3605 										   ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + ams.devext + '.css');
       
  3606 									   }
  3330 									   images.each(function() {
  3607 									   images.each(function() {
  3331 										   var image = $(this);
  3608 										   var image = $(this);
  3332 										   var data = image.data();
  3609 										   var data = image.data();
  3333 										   var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body';
  3610 										   var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body';
  3334 										   var data_options = {
  3611 										   var data_options = {
  3359 										   // Add update timeout when plug-in is displayed into a modal dialog
  3636 										   // Add update timeout when plug-in is displayed into a modal dialog
  3360 										   setTimeout(function() {
  3637 										   setTimeout(function() {
  3361 											   plugin.update();
  3638 											   plugin.update();
  3362 										   }, 250);
  3639 										   }, 250);
  3363 									   });
  3640 									   });
  3364 								   })
  3641 								   });
  3365 				}
  3642 				}
  3366 			},
  3643 			},
  3367 
  3644 
  3368 			/**
  3645 			/**
  3369 			 * FancyBox plug-in
  3646 			 * FancyBox plug-in
  3372 				var fancyboxes = $('.fancybox', element);
  3649 				var fancyboxes = $('.fancybox', element);
  3373 				if (fancyboxes.length > 0) {
  3650 				if (fancyboxes.length > 0) {
  3374 					ams.ajax.check($.fn.fancybox,
  3651 					ams.ajax.check($.fn.fancybox,
  3375 								   ams.baseURL + 'ext/jquery-fancybox-2.1.5' + ams.devext + '.js',
  3652 								   ams.baseURL + 'ext/jquery-fancybox-2.1.5' + ams.devext + '.js',
  3376 								   function(first_load) {
  3653 								   function(first_load) {
  3377 										if (first_load)
  3654 										if (first_load) {
  3378 											ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + ams.devext + '.css');
  3655 											ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + ams.devext + '.css');
       
  3656 										}
  3379 										fancyboxes.each(function() {
  3657 										fancyboxes.each(function() {
  3380 											var fancybox = $(this);
  3658 											var fancybox = $(this);
  3381 											var data = fancybox.data();
  3659 											var data = fancybox.data();
  3382 											var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
  3660 											var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
  3383 											if (helpers.length > 0) {
  3661 											if (helpers.length > 0) {
  3384 												for (var index in helpers) {
  3662 												for (var index=0; index < helpers.length; index++) {
  3385 													var helper = helpers[index];
  3663 													var helper = helpers[index];
  3386 													switch (helper) {
  3664 													switch (helper) {
  3387 														case 'buttons':
  3665 														case 'buttons':
  3388 															ams.ajax.check($.fancybox.helpers.buttons,
  3666 															ams.ajax.check($.fancybox.helpers.buttons,
  3389 																		   ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons' + ams.devext + '.js');
  3667 																		   ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons' + ams.devext + '.js');
  3491 								   ams.baseURL + 'ext/jquery-mousewheel.min.js',
  3769 								   ams.baseURL + 'ext/jquery-mousewheel.min.js',
  3492 								   function() {
  3770 								   function() {
  3493 										ams.ajax.check($.fn.mCustomScrollbar,
  3771 										ams.ajax.check($.fn.mCustomScrollbar,
  3494 													   ams.baseURL + 'ext/jquery-mCustomScrollbar' + ams.devext + '.js',
  3772 													   ams.baseURL + 'ext/jquery-mCustomScrollbar' + ams.devext + '.js',
  3495 													   function(first_load) {
  3773 													   function(first_load) {
  3496 															if (first_load)
  3774 															if (first_load) {
  3497 																ams.getCSS(ams.baseURL + '../css/ext/jquery-mCustomScrollbar.css',
  3775 																ams.getCSS(ams.baseURL + '../css/ext/jquery-mCustomScrollbar.css',
  3498 																		  'jquery-mCustomScrollbar');
  3776 																		   'jquery-mCustomScrollbar');
       
  3777 															}
  3499 															scrollbars.each(function() {
  3778 															scrollbars.each(function() {
  3500 																var scrollbar = $(this);
  3779 																var scrollbar = $(this);
  3501 																var data = scrollbar.data();
  3780 																var data = scrollbar.data();
  3502 																var data_options = {
  3781 																var data_options = {
  3503 																	theme: data.amsScrollbarTheme || 'light'
  3782 																	theme: data.amsScrollbarTheme || 'light'
  3541 					if (data.amsCallbackSource) {
  3820 					if (data.amsCallbackSource) {
  3542 						ams.getScript(data.amsCallbackSource,
  3821 						ams.getScript(data.amsCallbackSource,
  3543 									  function() {
  3822 									  function() {
  3544 										ams.executeFunctionByName(data.amsCallback, self, data.amsCallbackOptions);
  3823 										ams.executeFunctionByName(data.amsCallback, self, data.amsCallbackOptions);
  3545 									  });
  3824 									  });
  3546 					} else if (window.console) {
  3825 					} else if (globals.console) {
  3547 						console.warn("Undefined callback: " + data.amsCallback);
  3826 						globals.console.warn("Undefined callback: " + data.amsCallback);
  3548 					}
  3827 					}
  3549 				} else {
  3828 				} else {
  3550 					callback.call(self, data.amsCallbackOptions);
  3829 					callback.call(self, data.amsCallbackOptions);
  3551 				}
  3830 				}
  3552 			})
  3831 			});
  3553 		},
  3832 		},
  3554 
  3833 
  3555 		/**
  3834 		/**
  3556 		 * Standard alert message callback
  3835 		 * Standard alert message callback
  3557 		 *
  3836 		 *
  3651 		 */
  3930 		 */
  3652 		init: function(element) {
  3931 		init: function(element) {
  3653 			$('[data-ams-events-handlers]', element).each(function() {
  3932 			$('[data-ams-events-handlers]', element).each(function() {
  3654 				var element = $(this);
  3933 				var element = $(this);
  3655 				var handlers = element.data('ams-events-handlers');
  3934 				var handlers = element.data('ams-events-handlers');
  3656 				for (var event in handlers) {
  3935 				if (handlers) {
  3657 					element.on(event, ams.getFunctionByName(handlers[event]));
  3936 					for (var event in handlers) {
       
  3937 						if (handlers.hasOwnProperty(event)) {
       
  3938 							element.on(event, ams.getFunctionByName(handlers[event]));
       
  3939 						}
       
  3940 					}
  3658 				}
  3941 				}
  3659 			});
  3942 			});
  3660 		}
  3943 		}
  3661 	};
  3944 	};
  3662 
  3945 
  3691 				MyAMS.skin.bigBox({
  3974 				MyAMS.skin.bigBox({
  3692 					title: ams.i18n.WARNING,
  3975 					title: ams.i18n.WARNING,
  3693 					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + ams.i18n.DELETE_WARNING,
  3976 					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + ams.i18n.DELETE_WARNING,
  3694 					buttons: ams.i18n.BTN_OK_CANCEL
  3977 					buttons: ams.i18n.BTN_OK_CANCEL
  3695 				}, function(button) {
  3978 				}, function(button) {
  3696 					if (button == ams.i18n.BTN_OK) {
  3979 					if (button === ams.i18n.BTN_OK) {
  3697 						var table = link.parents('table');
  3980 						var table = link.parents('table');
  3698 						var location = table.data('ams-location') || '';
  3981 						var location = table.data('ams-location') || '';
  3699 						var tr = link.parents('tr');
  3982 						var tr = link.parents('tr');
  3700 						var delete_target = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json';
  3983 						var delete_target = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json';
  3701 						var object_name = tr.data('ams-element-name');
  3984 						var object_name = tr.data('ams-element-name');
  3702 						MyAMS.ajax.post(location + '/' + delete_target, {'object_name': object_name}, function(result, status) {
  3985 						MyAMS.ajax.post(location + '/' + delete_target, {'object_name': object_name}, function(result, status) {
  3703 							if (result.status == 'success') {
  3986 							if (result.status === 'success') {
  3704 								if (table.hasClass('datatable')) {
  3987 								if (table.hasClass('datatable')) {
  3705 									table.dataTable().fnDeleteRow(tr[0]);
  3988 									table.dataTable().fnDeleteRow(tr[0]);
  3706 								} else {
  3989 								} else {
  3707 									tr.remove();
  3990 									tr.remove();
  3708 								}
  3991 								}
  3709 							}
  3992 							}
  3710 						});
  3993 						});
  3711 					}
  3994 					}
  3712 				});
  3995 				});
  3713 			}
  3996 			};
  3714 		}
  3997 		}
  3715 	};
  3998 	};
  3716 
  3999 
  3717 
  4000 
  3718 	/**
  4001 	/**
  3738 
  4021 
  3739 		/**
  4022 		/**
  3740 		 * Check width for mobile devices
  4023 		 * Check width for mobile devices
  3741 		 */
  4024 		 */
  3742 		_checkMobileWidth: function() {
  4025 		_checkMobileWidth: function() {
  3743 			if ($(window).width() < 979)
  4026 			if ($(window).width() < 979) {
  3744 				ams.root.addClass('mobile-view-activated')
  4027 				ams.root.addClass('mobile-view-activated');
  3745 			else if (ams.root.hasClass('mobile-view-activated'))
  4028 			} else if (ams.root.hasClass('mobile-view-activated')) {
  3746 				ams.root.removeClass('mobile-view-activated');
  4029 				ams.root.removeClass('mobile-view-activated');
       
  4030 			}
  3747 		},
  4031 		},
  3748 
  4032 
  3749 		/**
  4033 		/**
  3750 		 * Show/hide shortcut buttons
  4034 		 * Show/hide shortcut buttons
  3751 		 */
  4035 		 */
  3753 			ams.shortcuts.animate({
  4037 			ams.shortcuts.animate({
  3754 				height: 'show'
  4038 				height: 'show'
  3755 			}, 200, 'easeOutCirc');
  4039 			}, 200, 'easeOutCirc');
  3756 			ams.root.addClass('shortcut-on');
  4040 			ams.root.addClass('shortcut-on');
  3757 		},
  4041 		},
  3758 		
  4042 
  3759 		_hideShortcutButtons: function() {
  4043 		_hideShortcutButtons: function() {
  3760 			ams.shortcuts.animate({
  4044 			ams.shortcuts.animate({
  3761 				height: 'hide'
  4045 				height: 'hide'
  3762 			}, 300, 'easeOutCirc');
  4046 			}, 300, 'easeOutCirc');
  3763 			ams.root.removeClass('shortcut-on');
  4047 			ams.root.removeClass('shortcut-on');
  3765 
  4049 
  3766 		/**
  4050 		/**
  3767 		 * Check notification badge
  4051 		 * Check notification badge
  3768 		 */
  4052 		 */
  3769 		checkNotification: function() {
  4053 		checkNotification: function() {
  3770 			$this = $('#activity > .badge');
  4054 			var badge = $('#activity > .badge');
  3771 			if (parseInt($this.text()) > 0)
  4055 			if (parseInt(badge.text()) > 0) {
  3772 				$this.removeClass("hidden")
  4056 				badge.removeClass("hidden")
  3773 					 .addClass("bg-color-red bounceIn animated");
  4057 					 .addClass("bg-color-red bounceIn animated");
  3774 			else
  4058 			} else {
  3775 				$this.addClass("hidden")
  4059 				badge.addClass("hidden")
  3776 					 .removeClass("bg-color-red bounceIn animated");
  4060 					 .removeClass("bg-color-red bounceIn animated");
       
  4061 			}
  3777 		},
  4062 		},
  3778 
  4063 
  3779 		/**
  4064 		/**
  3780 		 * Initialize desktop and mobile widgets
  4065 		 * Initialize desktop and mobile widgets
  3781 		 */
  4066 		 */
  3782 		_initDesktopWidgets: function(element) {
  4067 		_initDesktopWidgets: function(element) {
  3783 			if (ams.enable_widgets) {
  4068 			if (ams.enable_widgets) {
  3784 				var widgets = $('.ams-widget', element);
  4069 				var widgets = $('.ams-widget', element);
  3785 				if (widgets.length > 0)
  4070 				if (widgets.length > 0) {
  3786 					ams.ajax.check($.fn.MyAMSWidget,
  4071 					ams.ajax.check($.fn.MyAMSWidget,
  3787 								   ams.baseURL + 'myams-widgets' + ams.devext + '.js',
  4072 								   ams.baseURL + 'myams-widgets' + ams.devext + '.js',
  3788 								   function() {
  4073 								   function () {
  3789 										widgets.each(function() {
  4074 									   widgets.each(function () {
  3790 											var widget = $(this);
  4075 										   var widget = $(this);
  3791 											var data = widget.data();
  4076 										   var data = widget.data();
  3792 											var data_options = {
  4077 										   var data_options = {
  3793 												deleteSettingsKey: '#deletesettingskey-options',
  4078 											   deleteSettingsKey: '#deletesettingskey-options',
  3794 												deletePositionKey: '#deletepositionkey-options'
  4079 											   deletePositionKey: '#deletepositionkey-options'
  3795 											};
  4080 										   };
  3796 											var settings = $.extend({}, data_options, data.amsWidgetOptions);
  4081 										   var settings = $.extend({}, data_options, data.amsWidgetOptions);
  3797 											settings = ams.executeFunctionByName(data.amsWidgetInitcallback, widget, settings) || settings;
  4082 										   settings = ams.executeFunctionByName(data.amsWidgetInitcallback, widget, settings) || settings;
  3798 											widget.MyAMSWidget(settings);
  4083 										   widget.MyAMSWidget(settings);
  3799 										});
  4084 									   });
  3800 										MyAMSWidget.initWidgetsGrid($('.ams-widget-grid', element));
  4085 									   globals.MyAMSWidget.initWidgetsGrid($('.ams-widget-grid', element));
  3801 									});
  4086 								   });
       
  4087 				}
  3802 			}
  4088 			}
  3803 		},
  4089 		},
  3804 
  4090 
  3805 		_initMobileWidgets: function(element) {
  4091 		_initMobileWidgets: function(element) {
  3806 			if (ams.enable_mobile && ams.enable_widgets)
  4092 			if (ams.enable_mobile && ams.enable_widgets) {
  3807 				ams.skin._initDesktopWidgets(element);
  4093 				ams.skin._initDesktopWidgets(element);
       
  4094 			}
  3808 		},
  4095 		},
  3809 
  4096 
  3810 		/**
  4097 		/**
  3811 		 * Add an alert on top of a container
  4098 		 * Add an alert on top of a container
  3812 		 *
  4099 		 *
  3816 		 * @message: main alert message
  4103 		 * @message: main alert message
  3817 		 * @subtitle: optional subtitle
  4104 		 * @subtitle: optional subtitle
  3818 		 * @margin: if true, a margin will be displayed around alert
  4105 		 * @margin: if true, a margin will be displayed around alert
  3819 		 */
  4106 		 */
  3820 		alert: function(parent, status, header, message, subtitle, margin) {
  4107 		alert: function(parent, status, header, message, subtitle, margin) {
  3821 			$('.alert', parent).remove();
  4108 			if (status === 'error') {
  3822 			if (status == 'error')
       
  3823 				status = 'danger';
  4109 				status = 'danger';
  3824 			var content = '<div class="' + (margin ? 'margin-10' : '') + ' alert alert-block alert-' + status + ' fade in">' +
  4110 			}
  3825 							'<a class="close" data-dismiss="alert"><i class="fa fa-check"></i></a>' +
  4111 			$('.alert-' + status, parent).remove();
  3826 							'<h4 class="alert-heading">' +
  4112 			var content = '<div class="' + (margin ? 'margin-10' : '') + ' alert alert-block alert-' + status + ' padding-5 fade in">' +
  3827 								'<i class="fa fa-fw fa-warning"></i> ' + header +
  4113 				'<a class="close" data-dismiss="alert"><i class="fa fa-check"></i></a>' +
  3828 							'</h4>' +
  4114 				'<h4 class="alert-heading">' +
  3829 							(subtitle ? ('<p>' + subtitle + '</p>') : '');
  4115 				'<i class="fa fa-fw fa-warning"></i> ' + header +
  3830 			if (typeof(message) == 'string')
  4116 				'</h4>' +
       
  4117 				(subtitle ? ('<p>' + subtitle + '</p>') : '');
       
  4118 			if (typeof(message) === 'string') {
  3831 				content += '<ul><li>' + message + '</li></ul>';
  4119 				content += '<ul><li>' + message + '</li></ul>';
  3832 			else if (message) {
  4120 			} else if (message) {
  3833 				content += '<ul>';
  4121 				content += '<ul>';
  3834 				for (var index in message) {
  4122 				for (var index in message) {
  3835 					if (!$.isNumeric(index))  // IE check
  4123 					if (!$.isNumeric(index)) {  // IE check
  3836 						continue;
  4124 						continue;
       
  4125 					}
  3837 					content += '<li>' + message[index] + '</li>';
  4126 					content += '<li>' + message[index] + '</li>';
  3838 				};
  4127 				}
  3839 				content += '</ul>';
  4128 				content += '</ul>';
  3840 			}
  4129 			}
  3841 			content += '</div>';
  4130 			content += '</div>';
  3842 			var alert = $(content).prependTo(parent);
  4131 			var alert = $(content).prependTo(parent);
  3843 			if (parent.exists) {
  4132 			if (parent.exists) {
  3844 				ams.ajax.check($.scrollTo,
  4133 				ams.ajax.check($.scrollTo,
  3845 							   ams.baseURL + 'ext/jquery-scrollTo.min.js',
  4134 							   ams.baseURL + 'ext/jquery-scrollTo.min.js',
  3846 							   function() {
  4135 							   function() {
  3847 									$.scrollTo(parent, {offset: {top: -50}});
  4136 								   $.scrollTo(parent, {offset: {top: -50}});
  3848 							   });
  4137 							   });
  3849 			}
  4138 			}
  3850 		},
  4139 		},
  3851 
  4140 
  3852 		/**
  4141 		/**
  3862 
  4151 
  3863 		/**
  4152 		/**
  3864 		 * Medium notification message box, displayed on page's bottom right
  4153 		 * Medium notification message box, displayed on page's bottom right
  3865 		 */
  4154 		 */
  3866 		messageBox: function(status, options, callback) {
  4155 		messageBox: function(status, options, callback) {
  3867 			if (typeof(status) == 'object') {
  4156 			if (typeof(status) === 'object') {
  3868 				callback = options;
  4157 				callback = options;
  3869 				options = status || {};
  4158 				options = status || {};
  3870 				status = 'info';
  4159 				status = 'info';
  3871 			}
  4160 			}
  3872 			ams.ajax.check(ams.notify,
  4161 			ams.ajax.check(ams.notify,
  3873 						   ams.baseURL + 'myams-notify' + ams.devext + '.js',
  4162 						   ams.baseURL + 'myams-notify' + ams.devext + '.js',
  3874 						   function() {
  4163 						   function() {
  3875 								switch (status) {
  4164 							   switch (status) {
  3876 									case 'error':
  4165 								   case 'error':
  3877 									case 'danger':
  4166 								   case 'danger':
  3878 										options.color = '#C46A69';
  4167 									   options.color = '#C46A69';
  3879 										break;
  4168 									   break;
  3880 									case 'warning':
  4169 								   case 'warning':
  3881 										options.color = '#C79121';
  4170 									   options.color = '#C79121';
  3882 										break;
  4171 									   break;
  3883 									case 'success':
  4172 								   case 'success':
  3884 										options.color = '#739E73';
  4173 									   options.color = '#739E73';
  3885 										break;
  4174 									   break;
  3886 									default:
  4175 								   default:
  3887 										options.color = options.color || '#3276B1';
  4176 									   options.color = options.color || '#3276B1';
  3888 								}
  4177 							   }
  3889 								options.sound = false;
  4178 							   options.sound = false;
  3890 								ams.notify.bigBox(options, callback);
  4179 							   ams.notify.bigBox(options, callback);
  3891 						   });
  4180 						   });
  3892 		},
  4181 		},
  3893 
  4182 
  3894 		/**
  4183 		/**
  3895 		 * Small notification message box, displayed on page's top right
  4184 		 * Small notification message box, displayed on page's top right
  3896 		 */
  4185 		 */
  3897 		smallBox: function(status, options, callback) {
  4186 		smallBox: function(status, options, callback) {
  3898 			if (typeof(status) == 'object') {
  4187 			if (typeof(status) === 'object') {
  3899 				callback = options;
  4188 				callback = options;
  3900 				options = status || {};
  4189 				options = status || {};
  3901 				status = 'info';
  4190 				status = 'info';
  3902 			}
  4191 			}
  3903 			ams.ajax.check(ams.notify,
  4192 			ams.ajax.check(ams.notify,
  3904 						   ams.baseURL + 'myams-notify' + ams.devext + '.js',
  4193 						   ams.baseURL + 'myams-notify' + ams.devext + '.js',
  3905 						   function() {
  4194 						   function () {
  3906 								switch (status) {
  4195 							   switch (status) {
  3907 									case 'error':
  4196 								   case 'error':
  3908 									case 'danger':
  4197 								   case 'danger':
  3909 										options.color = '#C46A69';
  4198 									   options.color = '#C46A69';
  3910 										break;
  4199 									   break;
  3911 									case 'warning':
  4200 								   case 'warning':
  3912 										options.color = '#C79121';
  4201 									   options.color = '#C79121';
  3913 										break;
  4202 									   break;
  3914 									case 'success':
  4203 								   case 'success':
  3915 										options.color = '#739E73';
  4204 									   options.color = '#739E73';
  3916 										break;
  4205 									   break;
  3917 									default:
  4206 								   default:
  3918 										options.color = options.color || '#3276B1';
  4207 									   options.color = options.color || '#3276B1';
  3919 								}
  4208 							   }
  3920 								options.sound = false;
  4209 							   options.sound = false;
  3921 								ams.notify.smallBox(options, callback);
  4210 							   ams.notify.smallBox(options, callback);
  3922 						   });
  4211 						   });
  3923 		},
  4212 		},
  3924 
  4213 
  3925 		/**
  4214 		/**
  3926 		 * Initialize breadcrumbs based on active menu position
  4215 		 * Initialize breadcrumbs based on active menu position
  3927 		 */
  4216 		 */
  3928 		_drawBreadCrumb: function() {
  4217 		_drawBreadCrumb: function() {
  3929 			var crumb = $('#ribbon OL.breadcrumb');
  4218 			var crumb = $('#ribbon OL.breadcrumb');
  3930 			crumb.empty()
  4219 			$('li', crumb).not('.parent').remove();
  3931 				 .append($('<li></li>').append($('<a></a>').text(ams.i18n.HOME)
  4220 			if (!$('li', crumb).exists()) {
  3932 				 										   .attr('href', $('nav a[href!="#"]:first').attr('href'))));
  4221 				crumb.append($('<li></li>').append($('<a></a>').text(ams.i18n.HOME)
       
  4222 															   .addClass('padding-right-5')
       
  4223 															   .attr('href', $('nav a[href!="#"]:first').attr('href'))));
       
  4224 			}
  3933 			$('nav LI.active >A').each(function() {
  4225 			$('nav LI.active >A').each(function() {
  3934 				var menu = $(this);
  4226 				var menu = $(this);
  3935 				var body = $.trim(menu.clone()
  4227 				var body = $.trim(menu.clone()
  3936 									  .children(".badge")
  4228 									  .children(".badge")
  3937 									  .remove()
  4229 									  .remove()
  3938 									  .end()
  4230 									  .end()
  3939 									  .text());
  4231 									  .text());
  3940 				var item = $("<li></li>").append(menu.attr('href').replace(/^#/, '')
  4232 				var item = $("<li></li>").append(menu.attr('href').replace(/^#/, '') ?
  3941 													? $("<a></a>").html(body)
  4233 												 $("<a></a>").html(body).attr('href', menu.attr('href'))
  3942 																  .attr('href', menu.attr('href'))
  4234 												 : body);
  3943 													: body);
       
  3944 				crumb.append(item);
  4235 				crumb.append(item);
  3945 			});
  4236 			});
  3946 		},
  4237 		},
  3947 
  4238 
  3948 		/**
  4239 		/**
  3949 		 * Check URL matching current location hash
  4240 		 * Check URL matching current location hash
  3950 		 */
  4241 		 */
  3951 		checkURL: function() {
  4242 		checkURL: function() {
  3952 
  4243 
  3953 			function updateActiveMenus(menu) {
  4244 			function updateActiveMenus(menu) {
  3954 				$('nav .active').removeClass('active');
  4245 				$('.active', nav).removeClass('active');
  3955 				menu.addClass('open')
  4246 				menu.addClass('open')
  3956 					.addClass('active');
  4247 					.addClass('active');
  3957 				menu.parents('li').addClass('open active')
  4248 				menu.parents('li').addClass('open active')
  3958 								  .children('ul').addClass('active')
  4249 					.children('ul').addClass('active')
  3959 												 .show();
  4250 					.show();
  3960 				menu.parents('li:first').removeClass('open');
  4251 				menu.parents('li:first').removeClass('open');
  3961 				menu.parents('ul').addClass(menu.attr('href').replace(/^#/, '') ? 'active' : '')
  4252 				menu.parents('ul').addClass(menu.attr('href').replace(/^#/, '') ? 'active' : '')
  3962 								  .show();
  4253 					.show();
  3963 			}
  4254 			}
  3964 
  4255 
       
  4256 			var menu;
       
  4257 			var nav = $('nav');
  3965 			var hash = location.hash;
  4258 			var hash = location.hash;
  3966 			var url = hash.replace(/^#/, '');
  4259 			var url = hash.replace(/^#/, '');
  3967 			if (url) {
  4260 			if (url) {
  3968 				var container = $('#content');
  4261 				var container = $('#content');
  3969 				if (!container.exists())
  4262 				if (!container.exists()) {
  3970 					container = $('body');
  4263 					container = $('body');
  3971 				var menu = $('nav A[href="' + hash + '"]');
  4264 				}
  3972 				if (menu.exists())
  4265 				menu = $('A[href="' + hash + '"]', nav);
       
  4266 				if (menu.exists()) {
  3973 					updateActiveMenus(menu);
  4267 					updateActiveMenus(menu);
       
  4268 				}
  3974 				ams.skin.loadURL(url, container);
  4269 				ams.skin.loadURL(url, container);
  3975 				document.title = $('[data-ams-page-title]:first', container).data('ams-page-title') ||
  4270 				document.title = $('[data-ams-page-title]:first', container).data('ams-page-title') ||
  3976 								 menu.attr('title') ||
  4271 								 menu.attr('title') ||
  3977 								 document.title;
  4272 								 document.title;
  3978 			} else {
  4273 			} else {
  3979 				var active_url = $('[data-ams-active-menu]').data('ams-active-menu');
  4274 				var active_url = $('[data-ams-active-menu]').data('ams-active-menu');
  3980 				if (active_url) {
  4275 				if (active_url) {
  3981 					menu = $('nav A[href="' + active_url + '"]');
  4276 					menu = $('A[href="' + active_url + '"]', nav);
  3982 				} else {
  4277 				} else {
  3983 					menu = $('nav >UL >LI >A[href!="#"]').first();
  4278 					menu = $('>UL >LI >A[href!="#"]', nav).first();
  3984 				}
  4279 				}
  3985 				if (menu.exists()) {
  4280 				if (menu.exists()) {
  3986 					updateActiveMenus(menu);
  4281 					updateActiveMenus(menu);
  3987 					if (active_url)
  4282 					if (active_url) {
  3988 						ams.skin._drawBreadCrumb();
  4283 						ams.skin._drawBreadCrumb();
  3989 					else
  4284 					} else {
  3990 						window.location.hash = menu.attr('href');
  4285 						window.location.hash = menu.attr('href');
       
  4286 					}
  3991 				}
  4287 				}
  3992 			}
  4288 			}
  3993 		},
  4289 		},
  3994 
  4290 
  3995 		/**
  4291 		/**
  4002 		/**
  4298 		/**
  4003 		 * Register a callback which should be called before a container is replaced
  4299 		 * Register a callback which should be called before a container is replaced
  4004 		 */
  4300 		 */
  4005 		registerCleanCallback: function(callback) {
  4301 		registerCleanCallback: function(callback) {
  4006 			var callbacks = ams.skin._clean_callbacks;
  4302 			var callbacks = ams.skin._clean_callbacks;
  4007 			if (callbacks.indexOf(callback) < 0)
  4303 			if (callbacks.indexOf(callback) < 0) {
  4008 				callbacks.push(callback);
  4304 				callbacks.push(callback);
       
  4305 			}
  4009 		},
  4306 		},
  4010 
  4307 
  4011 		/**
  4308 		/**
  4012 		 * Call registered cleaning callbacks on given container
  4309 		 * Call registered cleaning callbacks on given container
  4013 		 */
  4310 		 */
  4014 		cleanContainer: function(container) {
  4311 		cleanContainer: function(container) {
  4015 			var callbacks = ams.skin._clean_callbacks;
  4312 			var callbacks = ams.skin._clean_callbacks;
  4016 			for (var index in callbacks) {
  4313 			for (var index=0; index < callbacks.length; index++) {
  4017 				callbacks[index].call(container);
  4314 				callbacks[index].call(container);
  4018 			}
  4315 			}
  4019 		},
  4316 		},
  4020 
  4317 
  4021 		/**
  4318 		/**
  4023 		 */
  4320 		 */
  4024 		loadURL: function(url, container, options, callback) {
  4321 		loadURL: function(url, container, options, callback) {
  4025 			if (url.startsWith('#')) {
  4322 			if (url.startsWith('#')) {
  4026 				url = url.substr(1);
  4323 				url = url.substr(1);
  4027 			}
  4324 			}
  4028 			if (typeof(options) == 'function') {
  4325 			if (typeof(options) === 'function') {
  4029 				callback = options;
  4326 				callback = options;
  4030 				options = {};
  4327 				options = {};
  4031 			}
  4328 			}
  4032 			container = $(container);
  4329 			container = $(container);
  4033 			var defaults = {
  4330 			var defaults = {
  4036 				dataType: 'html',
  4333 				dataType: 'html',
  4037 				cache: false,
  4334 				cache: false,
  4038 				beforeSend: function() {
  4335 				beforeSend: function() {
  4039 					ams.skin.cleanContainer(container);
  4336 					ams.skin.cleanContainer(container);
  4040 					container.html('<h1 class="loading"><i class="fa fa-cog fa-spin"></i> Loading... </h1>');
  4337 					container.html('<h1 class="loading"><i class="fa fa-cog fa-spin"></i> Loading... </h1>');
  4041 					if (container[0] == $('#content')[0]) {
  4338 					if (container[0] === $('#content')[0]) {
  4042 						ams.skin._drawBreadCrumb();
  4339 						ams.skin._drawBreadCrumb();
  4043 						document.title = $('.breadcrumb LI:last-child').text();
  4340 						document.title = $('.breadcrumb LI:last-child').text();
  4044 						$('html, body').animate({scrollTop: 0}, 'fast');
  4341 						$('html, body').animate({scrollTop: 0}, 'fast');
  4045 					} else {
  4342 					} else {
  4046 						container.animate({scrollTop: 0}, 'fast');
  4343 						container.animate({scrollTop: 0}, 'fast');
  4047 					}
  4344 					}
  4048 				},
  4345 				},
  4049 				success: function(data, status, request) {
  4346 				success: function(data, status, request) {
  4050 					if (callback)
  4347 					if (callback) {
  4051 						ams.executeFunctionByName(callback, this, data, status, request, options);
  4348 						ams.executeFunctionByName(callback, this, data, status, request, options);
  4052 					else {
  4349 					} else {
  4053 						var request_data = ams.ajax.getResponse(request);
  4350 						var request_data = ams.ajax.getResponse(request);
  4054 						var data_type = request_data.content_type;
  4351 						var data_type = request_data.content_type;
  4055 						var result = request_data.data;
  4352 						var result = request_data.data;
  4056 						$('.loading', container).remove();
  4353 						$('.loading', container).remove();
  4057 						switch (data_type) {
  4354 						switch (data_type) {
  4061 							case 'script':
  4358 							case 'script':
  4062 								break;
  4359 								break;
  4063 							case 'xml':
  4360 							case 'xml':
  4064 								break;
  4361 								break;
  4065 							case 'html':
  4362 							case 'html':
       
  4363 								/* falls through */
  4066 							case 'text':
  4364 							case 'text':
       
  4365 								/* falls through */
  4067 							default:
  4366 							default:
       
  4367 								// Show and init container
  4068 								container.parents('.hidden').removeClass('hidden');
  4368 								container.parents('.hidden').removeClass('hidden');
  4069 								$('.alert', container.parents('.alerts-container')).remove();
  4369 								$('.alert', container.parents('.alerts-container')).remove();
  4070 								container.css({opacity: '0.0'})
  4370 								container.css({opacity: '0.0'})
  4071 										 .html(data)
  4371 										 .html(data)
  4072 										 .removeClass('hidden')
  4372 										 .removeClass('hidden')
  4073 										 .delay(50)
  4373 										 .delay(50)
  4074 										 .animate({opacity: '1.0'}, 300);
  4374 										 .animate({opacity: '1.0'}, 300);
  4075 								ams.initContent(container);
  4375 								ams.initContent(container);
       
  4376 								ams.form.setFocus(container);
  4076 						}
  4377 						}
  4077 						if (options && options.afterLoadCallback) {
  4378 						if (options && options.afterLoadCallback) {
  4078 							ams.executeFunctionByName(options.afterLoadCallback, this);
  4379 							ams.executeFunctionByName(options.afterLoadCallback, this);
  4079 						}
  4380 						}
  4080 					}
  4381 					}
  4120 		}
  4421 		}
  4121 	};
  4422 	};
  4122 
  4423 
  4123 
  4424 
  4124 	/**
  4425 	/**
       
  4426 	 * Statistics management
       
  4427 	 */
       
  4428 	MyAMS.stats = {
       
  4429 
       
  4430 		/**
       
  4431 		 * Send event to Google Analytics platform
       
  4432 		 *
       
  4433 		 * @param category
       
  4434 		 * @param action
       
  4435 		 * @param label
       
  4436 		 */
       
  4437 		logEvent: function(category, action, label) {
       
  4438 			if (typeof(globals._gaq) === 'undefined') {
       
  4439 				return;
       
  4440 			}
       
  4441 			if (typeof(category) === 'object') {
       
  4442 				action = category.action;
       
  4443 				label = category.label;
       
  4444 				category = category.category;
       
  4445 			}
       
  4446 			globals._gaq.push(['_trackEvent', category, action, label]);
       
  4447 		}
       
  4448 	};
       
  4449 
       
  4450 
       
  4451 	/**
  4125 	 * Main page initialization
  4452 	 * Main page initialization
  4126 	 * This code is called only once to register global events and callbacks
  4453 	 * This code is called only once to register global events and callbacks
  4127 	 */
  4454 	 */
  4128 	MyAMS.initPage = function() {
  4455 	MyAMS.initPage = function() {
  4129 
  4456 
  4130 		var body = $('body');
  4457 		var body = $('body');
  4131 
  4458 
  4132 		/* Init main components */
  4459 		/* Init main components */
  4133 		ams.root = body;
  4460 		ams.root = body;
  4134 		ams.left_panel = $('#left-panel');
  4461 		ams.left_panel = $('#left-panel');
  4135 		ams.shortcuts = $('#shortcut');
  4462 		ams.shortcuts = $('#shortcuts');
  4136 		ams.plugins.initData(body);
  4463 		ams.plugins.initData(body);
  4137 
  4464 
  4138 		// Init main AJAX events
  4465 		// Init main AJAX events
  4139 		var jquery_xhr = $.ajaxSettings.xhr;
  4466 		var jquery_xhr = $.ajaxSettings.xhr;
  4140 		$.ajaxSetup({
  4467 		$.ajaxSetup({
  4141 			progress: ams.ajax.progress,
  4468 			progress: ams.ajax.progress,
  4142 			progressUpload: ams.ajax.progress,
  4469 			progressUpload: ams.ajax.progress,
  4143 			xhr: function() {
  4470 			xhr: function() {
  4144 				var request = jquery_xhr();
  4471 				var request = jquery_xhr();
  4145 				if (request && (typeof(request.addEventListener) == "function")) {
  4472 				if (request && (typeof(request.addEventListener) === "function")) {
  4146 					var that = this;
  4473 					var that = this;
  4147 					request.addEventListener("progress", function(evt) {
  4474 					request.addEventListener("progress", function(evt) {
  4148 						that.progress(evt);
  4475 						that.progress(evt);
  4149 					}, false);
  4476 					}, false);
  4150 				}
  4477 				}
  4165 			if (ams.enable_fastclick) {
  4492 			if (ams.enable_fastclick) {
  4166 				ams.ajax.check($.fn.noClickDelay,
  4493 				ams.ajax.check($.fn.noClickDelay,
  4167 							   ams.baseURL + '/ext/jquery-smartclick' + ams.devext + '.js',
  4494 							   ams.baseURL + '/ext/jquery-smartclick' + ams.devext + '.js',
  4168 							   function() {
  4495 							   function() {
  4169 								   $('NAV UL A').noClickDelay();
  4496 								   $('NAV UL A').noClickDelay();
  4170 								   $('#hide-menu A').noClickDelay();
  4497 								   $('A', '#hide-menu').noClickDelay();
  4171 							   });
  4498 							   });
  4172 			}
  4499 			}
  4173 		}
  4500 		}
  4174 
  4501 
  4175 		// Hide menu button
  4502 		// Hide menu button
  4177 			body.toggleClass("hidden-menu");
  4504 			body.toggleClass("hidden-menu");
  4178 			e.preventDefault();
  4505 			e.preventDefault();
  4179 		});
  4506 		});
  4180 
  4507 
  4181 		// Switch shortcuts
  4508 		// Switch shortcuts
  4182 		$('#show-shortcut').click(function(e) {
  4509 		$('#show-shortcuts').click(function(e) {
  4183 			if (ams.shortcuts.is(":visible")) {
  4510 			if (ams.shortcuts.is(":visible")) {
  4184 				ams.skin._hideShortcutButtons();
  4511 				ams.skin._hideShortcutButtons();
  4185 			} else {
  4512 			} else {
  4186 				ams.skin._showShortcutButtons();
  4513 				ams.skin._showShortcutButtons();
  4187 			}
  4514 			}
  4190 		ams.shortcuts.click(function(e) {
  4517 		ams.shortcuts.click(function(e) {
  4191 			ams.skin._hideShortcutButtons();
  4518 			ams.skin._hideShortcutButtons();
  4192 		});
  4519 		});
  4193 
  4520 
  4194 		$(document).mouseup(function(e) {
  4521 		$(document).mouseup(function(e) {
  4195 			if (!ams.shortcuts.is(e.target)
  4522 			if (!ams.shortcuts.is(e.target) &&
  4196 				&& ams.shortcuts.has(e.target).length === 0) {
  4523 				ams.shortcuts.has(e.target).length === 0) {
  4197 				ams.skin._hideShortcutButtons();
  4524 				ams.skin._hideShortcutButtons();
  4198 			}
  4525 			}
  4199 		});
  4526 		});
  4200 
  4527 
  4201 		// Show & hide mobile search field
  4528 		// Show & hide mobile search field
  4215 				dropdown.css('left', activity.position().left - dropdown.innerWidth() / 2 + activity.innerWidth() / 2)
  4542 				dropdown.css('left', activity.position().left - dropdown.innerWidth() / 2 + activity.innerWidth() / 2)
  4216 						.fadeIn(150);
  4543 						.fadeIn(150);
  4217 				activity.addClass('active');
  4544 				activity.addClass('active');
  4218 			} else {
  4545 			} else {
  4219 				dropdown.fadeOut(150);
  4546 				dropdown.fadeOut(150);
  4220 				activity.removeClass('active')
  4547 				activity.removeClass('active');
  4221 			}
  4548 			}
  4222 			e.preventDefault();
  4549 			e.preventDefault();
  4223 		});
  4550 		});
  4224 		ams.skin.checkNotification();
  4551 		ams.skin.checkNotification();
  4225 
  4552 
  4232 			}
  4559 			}
  4233 		});
  4560 		});
  4234 
  4561 
  4235 		$('input[name="activity"]').change(function() {
  4562 		$('input[name="activity"]').change(function() {
  4236 			var url = $(this).data('ams-url');
  4563 			var url = $(this).data('ams-url');
  4237 			container = $('.ajax-notifications');
  4564 			var container = $('.ajax-notifications');
  4238 			ams.skin.loadURL(url, container);
  4565 			ams.skin.loadURL(url, container);
  4239 		});
  4566 		});
  4240 
  4567 
  4241 		// Logout button
  4568 		// Logout button
  4242 		$('#logout a').click(function(e) {
  4569 		$('a', '#user-menu LI.logout').click(function(e) {
  4243 			e.preventDefault();
  4570 			e.preventDefault();
  4244 			e.stopPropagation();
  4571 			e.stopPropagation();
  4245 			//get the link
  4572 			//get the link
  4246 			ams.loginURL = $(this).attr('href');
  4573 			ams.loginURL = $(this).attr('href');
  4247 			// ask verification
  4574 			// ask verification
  4249 				title : "<i class='fa fa-sign-out txt-color-orangeDark'></i> " + ams.i18n.LOGOUT +
  4576 				title : "<i class='fa fa-sign-out txt-color-orangeDark'></i> " + ams.i18n.LOGOUT +
  4250 						" <span class='txt-color-orangeDark'><strong>" + $('#show-shortcut').text() + "</strong></span> ?",
  4577 						" <span class='txt-color-orangeDark'><strong>" + $('#show-shortcut').text() + "</strong></span> ?",
  4251 				content : ams.i18n.LOGOUT_COMMENT,
  4578 				content : ams.i18n.LOGOUT_COMMENT,
  4252 				buttons : '['+ams.i18n.BTN_NO+']['+ams.i18n.BTN_YES+']'
  4579 				buttons : '['+ams.i18n.BTN_NO+']['+ams.i18n.BTN_YES+']'
  4253 			}, function(ButtonPressed) {
  4580 			}, function(ButtonPressed) {
  4254 				if (ButtonPressed == ams.i18n.BTN_YES) {
  4581 				if (ButtonPressed === ams.i18n.BTN_YES) {
  4255 					ams.root.addClass('animated fadeOutUp');
  4582 					ams.root.addClass('animated fadeOutUp');
  4256 					setTimeout(ams.skin.logout, 1000)
  4583 					setTimeout(ams.skin.logout, 1000);
  4257 				}
  4584 				}
  4258 			});
  4585 			});
  4259 		});
  4586 		});
  4260 
  4587 
  4261 		// Initialize left nav
  4588 		// Initialize left nav
  4262 		$('NAV UL').myams_menu({
  4589 		var nav = $('nav');
  4263 			accordion : true,
  4590 		$('UL', nav).myams_menu({
       
  4591 			accordion : nav.data('ams-menu-accordion') !== false,
  4264 			speed : ams.menu_speed
  4592 			speed : ams.menu_speed
  4265 		});
  4593 		});
  4266 
  4594 
  4267 		// Left navigation collapser
  4595 		// Left navigation collapser
  4268 		$('.minifyme').click(function(e) {
  4596 		$('.minifyme').click(function(e) {
  4276 			ams.skin.bigBox({
  4604 			ams.skin.bigBox({
  4277 				title: "<i class='fa fa-refresh' style='color: green'></i> " + ams.i18n.CLEAR_STORAGE_TITLE,
  4605 				title: "<i class='fa fa-refresh' style='color: green'></i> " + ams.i18n.CLEAR_STORAGE_TITLE,
  4278 				content: ams.i18n.CLEAR_STORAGE_CONTENT,
  4606 				content: ams.i18n.CLEAR_STORAGE_CONTENT,
  4279 				buttons: '['+ams.i18n.BTN_CANCEL+']['+ams.i18n.BTN_OK+']'
  4607 				buttons: '['+ams.i18n.BTN_CANCEL+']['+ams.i18n.BTN_OK+']'
  4280 			}, function(buttonPressed) {
  4608 			}, function(buttonPressed) {
  4281 				if (buttonPressed == ams.i18n.BTN_OK && localStorage) {
  4609 				if (buttonPressed === ams.i18n.BTN_OK && localStorage) {
  4282 					localStorage.clear();
  4610 					localStorage.clear();
  4283 					location.reload();
  4611 					location.reload();
  4284 				}
  4612 				}
  4285 			});
  4613 			});
  4286 			e.preventDefault();
  4614 			e.preventDefault();
  4289 		// Check active pop-overs
  4617 		// Check active pop-overs
  4290 		body.on('click', function(e) {
  4618 		body.on('click', function(e) {
  4291 			var element = $(this);
  4619 			var element = $(this);
  4292 			if (!element.is(e.target) &&
  4620 			if (!element.is(e.target) &&
  4293 				element.has(e.target).length === 0 &&
  4621 				element.has(e.target).length === 0 &&
  4294 				$('.popover').has(e.target).length === 0)
  4622 				$('.popover').has(e.target).length === 0) {
  4295 				element.popover('hide');
  4623 				element.popover('hide');
       
  4624 			}
  4296 		});
  4625 		});
  4297 
  4626 
  4298 		// Resize events
  4627 		// Resize events
  4299 		ams.ajax.check($.resize,
  4628 		ams.ajax.check($.resize,
  4300 					   ams.baseURL + 'ext/jquery-resize' + ams.devext + '.js',
  4629 					   ams.baseURL + 'ext/jquery-resize' + ams.devext + '.js',
  4301 					   function() {
  4630 					   function() {
  4302 						   $('#main').resize(function() {
  4631 						   $('#main').resize(function() {
  4303 							   ams.skin._setPageHeight();
  4632 							   ams.skin._setPageHeight();
  4304 							   ams.skin._checkMobileWidth();
  4633 							   ams.skin._checkMobileWidth();
  4305 						   });
  4634 						   });
  4306 						   $('nav').resize(function() {
  4635 						   nav.resize(function() {
  4307 							   ams.skin._setPageHeight();
  4636 							   ams.skin._setPageHeight();
  4308 						   });
  4637 						   });
  4309 					   });
  4638 					   });
  4310 
  4639 
  4311 		// Init AJAX navigation
  4640 		// Init AJAX navigation
  4313 			$(document).on('click', 'a[href="#"]', function(e) {
  4642 			$(document).on('click', 'a[href="#"]', function(e) {
  4314 				e.preventDefault();
  4643 				e.preventDefault();
  4315 			});
  4644 			});
  4316 			$(document).on('click', 'a[href!="#"]:not([data-toggle]), [data-ams-url]:not([data-toggle])', function(e) {
  4645 			$(document).on('click', 'a[href!="#"]:not([data-toggle]), [data-ams-url]:not([data-toggle])', function(e) {
  4317 				var link = $(e.currentTarget);
  4646 				var link = $(e.currentTarget);
       
  4647 				var handlers = link.data('ams-disabled-handlers');
       
  4648 				if ((handlers == true) || (handlers == 'click')) {
       
  4649 					return;
       
  4650 				}
  4318 				var href = link.attr('href') || link.data('ams-url');
  4651 				var href = link.attr('href') || link.data('ams-url');
  4319 				if (!href || href.startsWith('javascript:') || link.attr('target') || (link.data('ams-context-menu') === true))
  4652 				if (!href || href.startsWith('javascript') || link.attr('target') || (link.data('ams-context-menu') === true)) {
  4320 					return;
  4653 					return;
       
  4654 				}
  4321 				e.preventDefault();
  4655 				e.preventDefault();
  4322 				e.stopPropagation();
  4656 				e.stopPropagation();
  4323 				var href_getter = ams.getFunctionByName(href);
  4657 				var href_getter = ams.getFunctionByName(href);
  4324 				if (typeof(href_getter) == 'function') {
  4658 				if (typeof(href_getter) === 'function') {
  4325 					href = href_getter.call(link);
  4659 					href = href_getter.call(link);
  4326 				}
  4660 				}
  4327 				if (typeof(href) == 'function') {
  4661 				if (typeof(href) === 'function') {
  4328 					// Javascript function call
  4662 					// Javascript function call
  4329 					href.call(link);
  4663 					href.call(link);
  4330 				} else {
  4664 				} else {
  4331 					// Standard AJAX or browser URL call
  4665 					// Standard AJAX or browser URL call
  4332 					// Convert %23 chars to #
  4666 					// Convert %23 chars to #
  4337 							ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback'));
  4671 							ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback'));
  4338 						});
  4672 						});
  4339 					} else {
  4673 					} else {
  4340 						ams.form.confirmChangedForm(function () {
  4674 						ams.form.confirmChangedForm(function () {
  4341 							if (href.startsWith('#')) {
  4675 							if (href.startsWith('#')) {
  4342 								if (href != location.hash) {
  4676 								if (href !== location.hash) {
  4343 									if (ams.root.hasClass('mobile-view-activated')) {
  4677 									if (ams.root.hasClass('mobile-view-activated')) {
  4344 										ams.root.removeClass('hidden-menu');
  4678 										ams.root.removeClass('hidden-menu');
  4345 										window.setTimeout(function () {
  4679 										window.setTimeout(function () {
  4346 											window.location.hash = href;
  4680 											window.location.hash = href;
  4347 										}, 50);
  4681 										}, 50);
  4348 									} else
  4682 									} else {
  4349 										window.location.hash = href;
  4683 										window.location.hash = href;
       
  4684 									}
  4350 								}
  4685 								}
  4351 							} else
  4686 							} else {
  4352 								window.location = href;
  4687 								window.location = href;
       
  4688 							}
  4353 						});
  4689 						});
  4354 					}
  4690 					}
  4355 				}
  4691 				}
  4356 			});
  4692 			});
  4357 			$(document).on('click', 'a[target="_blank"]', function(e) {
  4693 			$(document).on('click', 'a[target="_blank"]', function(e) {
  4371 
  4707 
  4372 		// Initialize modal dialogs links
  4708 		// Initialize modal dialogs links
  4373 		$(document).off('click.modal')
  4709 		$(document).off('click.modal')
  4374 				   .on('click', '[data-toggle="modal"]', function(e) {
  4710 				   .on('click', '[data-toggle="modal"]', function(e) {
  4375 			var source = $(this);
  4711 			var source = $(this);
  4376 			if (source.data('ams-context-menu') === true)
  4712 			var handlers = source.data('ams-disabled-handlers');
       
  4713 			if ((handlers == true) || (handlers == 'click')) {
  4377 				return;
  4714 				return;
  4378 			if (source.data('ams-stop-propagation') === true)
  4715 			}
       
  4716 			if (source.data('ams-context-menu') === true) {
       
  4717 				return;
       
  4718 			}
       
  4719 			if (source.data('ams-stop-propagation') === true) {
  4379 				e.stopPropagation();
  4720 				e.stopPropagation();
       
  4721 			}
  4380 			e.preventDefault();
  4722 			e.preventDefault();
  4381 			ams.dialog.open(source);
  4723 			ams.dialog.open(source);
  4382 			if (source.parents('#shortcut').exists())
  4724 			if (source.parents('#shortcut').exists()) {
  4383 				setTimeout(ams.skin._hideShortcutButtons, 300);
  4725 				setTimeout(ams.skin._hideShortcutButtons, 300);
       
  4726 			}
  4384 		});
  4727 		});
  4385 
  4728 
  4386 		// Initialize form buttons
  4729 		// Initialize form buttons
  4387 		$(document).on('click', 'button[type="submit"], button.submit', function() {
  4730 		$(document).on('click', 'button[type="submit"], button.submit', function() {
  4388 			var button = $(this);
  4731 			var button = $(this);
  4390 		});
  4733 		});
  4391 
  4734 
  4392 		// Initialize custom click handlers
  4735 		// Initialize custom click handlers
  4393 		$(document).on('click', '[data-ams-click-handler]', function(e) {
  4736 		$(document).on('click', '[data-ams-click-handler]', function(e) {
  4394 			var source = $(this);
  4737 			var source = $(this);
       
  4738 			var handlers = source.data('ams-disabled-handlers');
       
  4739 			if ((handlers == true) || (handlers == 'click')) {
       
  4740 				return;
       
  4741 			}
  4395 			var data = source.data();
  4742 			var data = source.data();
  4396 			if (data.amsClickHandler) {
  4743 			if (data.amsClickHandler) {
  4397 				if ((data.amsStopPropagation === true) || (data.amsClickStopPropagation === true))
  4744 				if ((data.amsStopPropagation === true) || (data.amsClickStopPropagation === true)) {
  4398 					e.stopPropagation();
  4745 					e.stopPropagation();
  4399 				if (data.amsClickKeepDefault !== true)
  4746 				}
       
  4747 				if (data.amsClickKeepDefault !== true) {
  4400 					e.preventDefault();
  4748 					e.preventDefault();
       
  4749 				}
  4401 				var callback = ams.getFunctionByName(data.amsClickHandler);
  4750 				var callback = ams.getFunctionByName(data.amsClickHandler);
  4402 				if (callback !== undefined)
  4751 				if (callback !== undefined) {
  4403 					callback.call(source, data.amsClickHandlerOptions);
  4752 					callback.call(source, data.amsClickHandlerOptions);
       
  4753 				}
  4404 			}
  4754 			}
  4405 		});
  4755 		});
  4406 
  4756 
  4407 		// Initialize custom change handlers
  4757 		// Initialize custom change handlers
  4408 		$(document).on('change', '[data-ams-change-handler]', function(e) {
  4758 		$(document).on('change', '[data-ams-change-handler]', function(e) {
  4409 			var source = $(this);
  4759 			var source = $(this);
       
  4760 			var handlers = source.data('ams-disabled-handlers');
       
  4761 			if ((handlers == true) || (handlers == 'change')) {
       
  4762 				return;
       
  4763 			}
  4410 			var data = source.data();
  4764 			var data = source.data();
  4411 			if (data.amsChangeHandler) {
  4765 			if (data.amsChangeHandler) {
  4412 				if (data.amsChangeKeepDefault !== true)
  4766 				if (data.amsChangeKeepDefault !== true) {
  4413 					e.preventDefault();
  4767 					e.preventDefault();
       
  4768 				}
  4414 				var callback = ams.getFunctionByName(data.amsChangeHandler);
  4769 				var callback = ams.getFunctionByName(data.amsChangeHandler);
  4415 				if (callback !== undefined)
  4770 				if (callback !== undefined) {
  4416 					callback.call(source, data.amsChangeHandlerOptions);
  4771 					callback.call(source, data.amsChangeHandlerOptions);
       
  4772 				}
  4417 			}
  4773 			}
  4418 		});
  4774 		});
  4419 
  4775 
  4420 		// Notify reset to update Select2 widgets
  4776 		// Notify reset to update Select2 widgets
  4421 		$(document).on('reset', 'form', function(e) {
  4777 		$(document).on('reset', 'form', function(e) {
  4422 			var form = $(this);
  4778 			var form = $(this);
  4423 			setTimeout(function() {
  4779 			setTimeout(function() {
  4424 				form.find('.select2').trigger('change');
  4780 				form.find('.select2').trigger('change');
  4425 			}, 10);
  4781 			}, 10);
       
  4782 			ams.form.setFocus(form);
  4426 		});
  4783 		});
  4427 
  4784 
  4428 		// Initialize custom reset handlers
  4785 		// Initialize custom reset handlers
  4429 		$(document).on('reset', '[data-ams-reset-handler]', function(e) {
  4786 		$(document).on('reset', '[data-ams-reset-handler]', function(e) {
  4430 			var form = $(this);
  4787 			var form = $(this);
  4431 			var data = form.data();
  4788 			var data = form.data();
  4432 			if (data.amsResetHandler) {
  4789 			if (data.amsResetHandler) {
  4433 				if (data.amsResetKeepDefault !== true)
  4790 				if (data.amsResetKeepDefault !== true) {
  4434 					e.preventDefault();
  4791 					e.preventDefault();
       
  4792 				}
  4435 				var callback = ams.getFunctionByName(data.amsResetHandler);
  4793 				var callback = ams.getFunctionByName(data.amsResetHandler);
  4436 				if (callback !== undefined)
  4794 				if (callback !== undefined) {
  4437 					callback.call(form, data.amsResetHandlerOptions);
  4795 					callback.call(form, data.amsResetHandlerOptions);
       
  4796 				}
  4438 			}
  4797 			}
  4439 		});
  4798 		});
  4440 
  4799 
  4441 		// Handle update on file upload placeholder
  4800 		// Handle update on file upload placeholder
  4442 		$(document).on('change', 'input[type="file"]', function(e) {
  4801 		$(document).on('change', 'input[type="file"]', function(e) {
  4466 		// Enable tabs dynamic loading
  4825 		// Enable tabs dynamic loading
  4467 		$(document).on('show.bs.tab', function(e) {
  4826 		$(document).on('show.bs.tab', function(e) {
  4468 			var link = $(e.target);
  4827 			var link = $(e.target);
  4469 			var data = link.data();
  4828 			var data = link.data();
  4470 			if (data.amsUrl) {
  4829 			if (data.amsUrl) {
  4471 				if (data.amsTabLoaded)
  4830 				if (data.amsTabLoaded) {
  4472 					return;
  4831 					return;
       
  4832 				}
  4473 				try {
  4833 				try {
  4474 					link.append('<i class="fa fa-spin fa-cog margin-left-5"></i>');
  4834 					link.append('<i class="fa fa-spin fa-cog margin-left-5"></i>');
  4475 					ams.skin.loadURL(data.amsUrl, link.attr('href'));
  4835 					ams.skin.loadURL(data.amsUrl, link.attr('href'));
  4476 					if (data.amsTabLoadOnce)
  4836 					if (data.amsTabLoadOnce) {
  4477 						link.data('ams-tab-loaded', true);
  4837 						link.data('ams-tab-loaded', true);
       
  4838 					}
  4478 				}
  4839 				}
  4479 				finally {
  4840 				finally {
  4480 					$('i', link).remove();
  4841 					$('i', link).remove();
  4481 				}
  4842 				}
  4482 			}
  4843 			}
  4483 		});
  4844 		});
  4484 
  4845 
  4485 		// Init page content
  4846 		// Init page content
  4486 		ams.initContent(document);
  4847 		ams.initContent(document);
  4487 		if (ams.ajax_nav && $('nav').exists())
  4848 		if (ams.ajax_nav && nav.exists()) {
  4488 			ams.skin.checkURL();
  4849 			ams.skin.checkURL();
       
  4850 		}
       
  4851 		ams.form.setFocus(document);
  4489 
  4852 
  4490 		// Add unload event listener to check for modified forms
  4853 		// Add unload event listener to check for modified forms
  4491 		$(window).on('beforeunload', ams.form.checkBeforeUnload);
  4854 		$(window).on('beforeunload', ams.form.checkBeforeUnload);
  4492 
  4855 
  4493 	};
  4856 	};
  4517 		ams.callbacks.init(element);
  4880 		ams.callbacks.init(element);
  4518 		ams.events.init(element);
  4881 		ams.events.init(element);
  4519 		ams.form.init(element);
  4882 		ams.form.init(element);
  4520 
  4883 
  4521 		// Initialize widgets
  4884 		// Initialize widgets
  4522 		if (ams.device === 'desktop')
  4885 		if (ams.device === 'desktop') {
  4523 			ams.skin._initDesktopWidgets(element);
  4886 			ams.skin._initDesktopWidgets(element);
  4524 		else
  4887 		} else {
  4525 			ams.skin._initMobileWidgets(element);
  4888 			ams.skin._initMobileWidgets(element);
       
  4889 		}
  4526 		ams.skin._setPageHeight();
  4890 		ams.skin._setPageHeight();
  4527 
  4891 
  4528 	};
  4892 	};
  4529 
  4893 
  4530 
  4894 
  4599 		} else {
  4963 		} else {
  4600 			MyAMS.initPage();
  4964 			MyAMS.initPage();
  4601 		}
  4965 		}
  4602 	});
  4966 	});
  4603 
  4967 
  4604 })(jQuery);
  4968 })(jQuery, this);