src/ztfy/myams/resources/js/myams.js
changeset 118 c87d242a1176
parent 104 d25135ad3899
child 127 cf00ea83daa7
equal deleted inserted replaced
117:23c0c267b970 118:c87d242a1176
     5  * $Tag$
     5  * $Tag$
     6  * A bootstrap based application/administration skin
     6  * A bootstrap based application/administration skin
     7  *
     7  *
     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 Thierry Florac <tflorac@ulthar.net>
    10  * ©2014-2015 Thierry Florac <tflorac@ulthar.net>
    11  */
    11  */
    12 
    12 
    13 (function($) {
    13 (function($) {
    14 
    14 
    15 	/**
    15 	/**
   321 	 * MyAMS extensions to JQuery
   321 	 * MyAMS extensions to JQuery
   322 	 */
   322 	 */
   323 	if (window.MyAMS === undefined) {
   323 	if (window.MyAMS === undefined) {
   324 		window.MyAMS = {
   324 		window.MyAMS = {
   325 			devmode: true,
   325 			devmode: true,
       
   326 			lang: 'en',
   326 			throttle_delay: 350,
   327 			throttle_delay: 350,
   327 			menu_speed: 235,
   328 			menu_speed: 235,
   328 			navbar_height: 49,
   329 			navbar_height: 49,
   329 			ajax_nav: true,
   330 			ajax_nav: true,
   330 			enable_widgets: true,
   331 			enable_widgets: true,
   341 	 * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst
   342 	 * Copyright Andrew Davy: https://forrst.com/posts/Get_the_URL_of_the_current_javascript_file-Dst
   342 	 */
   343 	 */
   343 	MyAMS.baseURL = (function () {
   344 	MyAMS.baseURL = (function () {
   344 		var script = $('script[src$="/myams.js"], script[src$="/myams.min.js"]');
   345 		var script = $('script[src$="/myams.js"], script[src$="/myams.min.js"]');
   345 		var src = script.attr("src");
   346 		var src = script.attr("src");
       
   347 		ams.devmode = !src.endsWith('.min.js');
   346 		return src.substring(0, src.lastIndexOf('/') + 1);
   348 		return src.substring(0, src.lastIndexOf('/') + 1);
   347 	})();
   349 	})();
   348 
   350 
   349 
   351 
   350 	/**
   352 	/**
   770 					ams.dialog.open(result.location);
   772 					ams.dialog.open(result.location);
   771 					break;
   773 					break;
   772 				case 'reload':
   774 				case 'reload':
   773 					if (result.close_form != false)
   775 					if (result.close_form != false)
   774 						ams.dialog.close(form);
   776 						ams.dialog.close(form);
   775 					url = result.location;
   777 					url = result.location || window.location.hash;
   776 					if (url.startsWith('#'))
   778 					if (url.startsWith('#'))
   777 						url = url.substr(1);
   779 						url = url.substr(1);
   778 					ams.skin.loadURL(url, result.target || target || '#content');
   780 					ams.skin.loadURL(url, result.target || target || '#content');
   779 					break;
   781 					break;
   780 				case 'redirect':
   782 				case 'redirect':
   781 					if (result.close_form == true)
   783 					if (result.close_form == true)
   782 						ams.dialog.close(form);
   784 						ams.dialog.close(form);
   783 					url = result.location;
   785 					url = result.location || window.location.href;
   784 					if (result.window) {
   786 					if (result.window) {
   785 						window.open(url, result.window, result.options);
   787 						window.open(url, result.window, result.options);
   786 					} else {
   788 					} else {
   787 						window.location.href = url;
   789 						window.location.href = url;
   788 					}
   790 					}
   792 					break;
   794 					break;
   793 			}
   795 			}
   794 			if (result.content) {
   796 			if (result.content) {
   795 				var content = result.content;
   797 				var content = result.content;
   796 				var container = $(content.target || target || form || '#content');
   798 				var container = $(content.target || target || form || '#content');
   797 				container.html(content.html);
   799 				if (content.raw == true) {
   798 				ams.initContent(container);
   800 					container.text(content.text);
       
   801 				} else {
       
   802 					container.html(content.html);
       
   803 					ams.initContent(container);
       
   804 				}
       
   805 				if (!content.keep_hidden)
       
   806 					container.removeClass('hidden');
       
   807 			}
       
   808 			if (result.contents) {
       
   809 				var contents = result.contents;
       
   810 				for (var index in contents) {
       
   811 					content = contents[index];
       
   812 					container = $(content.target);
       
   813 					if (content.raw == true) {
       
   814 						container.text(content.text);
       
   815 					} else {
       
   816 						container.html(content.html);
       
   817 						ams.initContent(container);
       
   818 					}
       
   819 					if (!content.keep_hidden)
       
   820 						container.removeClass('hidden');
       
   821 				}
   799 			}
   822 			}
   800 			if (result.message) {
   823 			if (result.message) {
   801 				var message = result.message;
   824 				var message = result.message;
   802 				if (typeof(message) == 'string') {
   825 				if (typeof(message) == 'string') {
   803 					if ((status == 'info') || (status == 'success'))
   826 					if ((status == 'info') || (status == 'success'))
   812 								   message.status || 'success',
   835 								   message.status || 'success',
   813 								   message.header,
   836 								   message.header,
   814 								   message.body,
   837 								   message.body,
   815 								   message.subtitle);
   838 								   message.subtitle);
   816 			}
   839 			}
       
   840 			if (result.smallbox) {
       
   841 				ams.skin.smallBox(result.smallbox_status || status,
       
   842 								  {title: result.smallbox,
       
   843 								   icon: 'fa fa-fw fa-info-circle font-xs align-top margin-top-10',
       
   844 								   timeout: 3000});
       
   845 			}
   817 			if (result.messagebox) {
   846 			if (result.messagebox) {
   818 				message = result.messagebox;
   847 				message = result.messagebox;
   819 				if (typeof(message) == 'string')
   848 				if (typeof(message) == 'string')
   820 					ams.skin.messageBox('info',
   849 					ams.skin.messageBox('info',
   821 										{title: ams.i18n.ERROR_OCCURED,
   850 										{title: ams.i18n.ERROR_OCCURED,
   828 					ams.skin.messageBox(message_status,
   857 					ams.skin.messageBox(message_status,
   829 										{title: message.title || ams.i18n.ERROR_OCCURED,
   858 										{title: message.title || ams.i18n.ERROR_OCCURED,
   830 										 content: message.content,
   859 										 content: message.content,
   831 										 icon: message.icon,
   860 										 icon: message.icon,
   832 										 number: message.number,
   861 										 number: message.number,
   833 										 timeout: message.timeout || 10000});
   862 										 timeout: message.timeout == null ? undefined : (message.timeout || 10000)});
   834 				}
   863 				}
   835 			}
   864 			}
   836 			if (result.event)
   865 			if (result.event)
   837 				form.trigger(result.event, result.event_options);
   866 				form.trigger(result.event, result.event_options);
   838 			if (result.callback)
   867 			if (result.callback)
   839 				ams.executeFunctionByName(result.callback, form, result.options);
   868 				ams.executeFunctionByName(result.callback, form, result.options);
   840 			if (result.callbacks) {
   869 			if (result.callbacks) {
   841 				for (var index in result.callbacks) {
   870 				for (index in result.callbacks) {
   842 					if (!$.isNumeric(index))
   871 					if (!$.isNumeric(index))
   843 						continue;
   872 						continue;
   844 					var callback = result.callbacks[index];
   873 					var callback = result.callbacks[index];
   845 					ams.executeFunctionByName(callback, form, callback.options);
   874 					ams.executeFunctionByName(callback, form, callback.options);
   846 				}
   875 				}
  1042 				submit_options = handler;
  1071 				submit_options = handler;
  1043 				handler = undefined;
  1072 				handler = undefined;
  1044 			}
  1073 			}
  1045 			// Prevent multiple submits of the same form
  1074 			// Prevent multiple submits of the same form
  1046 			if (form.data('submitted')) {
  1075 			if (form.data('submitted')) {
  1047 				ams.skin.messageBox('warning', {
  1076 				if (!form.data('ams-form-hide-submitted')) {
  1048 					title: ams.i18n.WAIT,
  1077 					ams.skin.messageBox('warning', {
  1049 					content: ams.i18n.FORM_SUBMITTED,
  1078 						title: ams.i18n.WAIT,
  1050 					icon: 'fa fa-save shake animated',
  1079 						content: ams.i18n.FORM_SUBMITTED,
  1051 					timeout: 5000
  1080 						icon: 'fa fa-save shake animated',
  1052 				});
  1081 						timeout: form.data('ams-form-alert-timeout') || 5000
       
  1082 					});
       
  1083 				}
  1053 				return false;
  1084 				return false;
  1054 			}
  1085 			}
  1055 			// Check submit validators
  1086 			// Check submit validators
  1056 			if (!ams.form._checkSubmitValidators(form))
  1087 			if (!ams.form._checkSubmitValidators(form))
  1057 				return false;
  1088 				return false;
  1393 				ams.skin.alert(form, 'error', ams.i18n.ERROR_OCCURED, errors)
  1424 				ams.skin.alert(form, 'error', ams.i18n.ERROR_OCCURED, errors)
  1394 			} else if (errors instanceof Array) {
  1425 			} else if (errors instanceof Array) {
  1395 				var header = errors.length == 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1426 				var header = errors.length == 1 ? ams.i18n.ERROR_OCCURED : ams.i18n.ERRORS_OCCURED;
  1396 				ams.skin.alert(form, 'error', header, errors);
  1427 				ams.skin.alert(form, 'error', header, errors);
  1397 			} else {
  1428 			} else {
       
  1429 				$('.state-error', form).removeClass('state-error');
  1398 				header = errors.widgets && (errors.widgets.length > 1) ? ams.i18n.ERRORS_OCCURED : ams.i18n.ERROR_OCCURED;
  1430 				header = errors.widgets && (errors.widgets.length > 1) ? ams.i18n.ERRORS_OCCURED : ams.i18n.ERROR_OCCURED;
  1399 				var message = new Array();
  1431 				var message = new Array();
  1400 				var index;
  1432 				var index;
  1401 				for (index in errors.messages) {
  1433 				for (index in errors.messages) {
  1402 					if (!$.isNumeric(index))
  1434 					if (!$.isNumeric(index))
  1404 					message.push(errors.messages[index].message || errors.messages[index]);
  1436 					message.push(errors.messages[index].message || errors.messages[index]);
  1405 				}
  1437 				}
  1406 				for (index in errors.widgets) {
  1438 				for (index in errors.widgets) {
  1407 					if (!$.isNumeric(index))
  1439 					if (!$.isNumeric(index))
  1408 						continue;
  1440 						continue;
  1409 					var widget = errors.widgets[index];
  1441 					// set widget status message
  1410 					$('[name="' + widget.name + '"]', form).parent('label')
  1442 					var widget_data = errors.widgets[index];
  1411 														   .removeClassPrefix('state-')
  1443 					var widget = $('[name="' + widget_data.name + '"]', form);
  1412 														   .addClass('state-error')
  1444 					widget.parents('label:first')
  1413 														   .after('<span for="name" class="state-error">' + widget.message + '</span>');
  1445 						  .removeClassPrefix('state-')
  1414 					if (widget.label) {
  1446 						  .addClass('state-error')
  1415 						message.push(widget.label + ' : ' + widget.message);
  1447 						  .after('<span for="name" class="state-error">' + widget_data.message + '</span>');
       
  1448 					// complete form alert message
       
  1449 					if (widget_data.label) {
       
  1450 						message.push(widget_data.label + ' : ' + widget_data.message);
       
  1451 					}
       
  1452 					// mark parent tab (if any) with error status
       
  1453 					var tab_index = widget.parents('.tab-pane').index() + 1;
       
  1454 					if (tab_index > 0) {
       
  1455 						var nav_tabs = $('.nav-tabs', $(widget).parents('.tabforms'));
       
  1456 						$('li:nth-child(' + tab_index + ')', nav_tabs).removeClassPrefix('state-')
       
  1457 																	  .addClass('state-error');
       
  1458 						$('li.state-error:first a', form).click();
  1416 					}
  1459 					}
  1417 				}
  1460 				}
  1418 				ams.skin.alert(form, 'error', header, message, errors.error_message);
  1461 				ams.skin.alert(form, 'error', header, message, errors.error_message);
  1419 			}
  1462 			}
  1420 		}
  1463 		}
  1870 					var fieldset = legend.parent('fieldset');
  1913 					var fieldset = legend.parent('fieldset');
  1871 					var data = legend.data();
  1914 					var data = legend.data();
  1872 					if (!data.amsChecker) {
  1915 					if (!data.amsChecker) {
  1873 						var checker = $('<label class="checkbox"></label>');
  1916 						var checker = $('<label class="checkbox"></label>');
  1874 						var fieldname = data.amsCheckerFieldname || ('checker_'+ams.generateId());
  1917 						var fieldname = data.amsCheckerFieldname || ('checker_'+ams.generateId());
       
  1918 						var checkbox_id = fieldname.replace(/\./, '_');
  1875 						var prefix = data.amsCheckerHiddenPrefix;
  1919 						var prefix = data.amsCheckerHiddenPrefix;
  1876 						var hidden = null;
  1920 						var hidden = null;
  1877 						var checkedValue = data.amsCheckerHiddenValueOn || 'true';
  1921 						var checkedValue = data.amsCheckerHiddenValueOn || 'true';
  1878 						var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
  1922 						var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
       
  1923 						var marker = data.amsCheckerMarker || false;
  1879 						if (prefix) {
  1924 						if (prefix) {
  1880 							hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
  1925 							hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
  1881 															   .val(data.amsCheckerState == 'on' ? checkedValue : uncheckedValue)
  1926 															   .val(data.amsCheckerState == 'on' ? checkedValue : uncheckedValue)
  1882 															   .prependTo(legend);
  1927 															   .prependTo(legend);
       
  1928 						} else if (marker) {
       
  1929 							$('<input type="hidden">').attr('name', marker)
       
  1930 													  .attr('value', 1)
       
  1931 													  .prependTo(legend);
  1883 						}
  1932 						}
  1884 						var input = $('<input type="checkbox">').attr('name', fieldname)
  1933 						var input = $('<input type="checkbox">').attr('name', fieldname)
  1885 																.attr('id', fieldname.replace(/\./, '_'))
  1934 																.attr('id', checkbox_id)
  1886 																.data('ams-checker-hidden-input', hidden)
  1935 																.data('ams-checker-hidden-input', hidden)
  1887 																.data('ams-checker-init', true)
  1936 																.data('ams-checker-init', true)
  1888 																.val(true)
  1937 																.val(data.amsCheckerValue || true)
  1889 																.attr('checked', data.amsCheckerState == 'on' ? 'checked' : null);
  1938 																.attr('checked', data.amsCheckerState == 'on' ? 'checked' : null);
  1890 						if (data.amsCheckerReadonly) {
  1939 						if (data.amsCheckerReadonly) {
  1891 							input.attr('disabled', 'disabled');
  1940 							input.attr('disabled', 'disabled');
  1892 						} else {
  1941 						} else {
  1893 							input.on('change', function(e) {
  1942 							input.on('change', function(e) {
  1921 									}
  1970 									}
  1922 								}
  1971 								}
  1923 							});
  1972 							});
  1924 						}
  1973 						}
  1925 						input.appendTo(checker);
  1974 						input.appendTo(checker);
  1926 						$('.legend', legend).attr('for', input.attr('id'));
  1975 						$('>label', legend).attr('for', input.attr('id'));
  1927 						checker.append('<i></i>')
  1976 						checker.append('<i></i>')
  1928 							   .prependTo(legend);
  1977 							   .prependTo(legend);
  1929 						var required = $('[required]', fieldset);
  1978 						var required = $('[required]', fieldset);
  1930 						required.attr('data-required', true);
  1979 						required.attr('data-required', true);
  1931 						if (data.amsCheckerState == 'on') {
  1980 						if (data.amsCheckerState == 'on') {
  1969 			 */
  2018 			 */
  1970 			select2: function(element) {
  2019 			select2: function(element) {
  1971 				var selects = $('.select2', element);
  2020 				var selects = $('.select2', element);
  1972 				if (selects.length > 0) {
  2021 				if (selects.length > 0) {
  1973 					ams.ajax.check($.fn.select2,
  2022 					ams.ajax.check($.fn.select2,
  1974 								   ams.baseURL + 'ext/jquery-select2-3.4.5' + (ams.devmode ? '.js' : '.min.js'),
  2023 								   ams.baseURL + 'ext/jquery-select2-3.5.2' + (ams.devmode ? '.js' : '.min.js'),
  1975 								   function() {
  2024 								   function() {
  1976 										selects.each(function() {
  2025 										selects.each(function() {
  1977 											var select = $(this);
  2026 											var select = $(this);
  1978 											var data = select.data();
  2027 											var data = select.data();
  1979 											var data_options = {
  2028 											var data_options = {
  1987 												initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
  2036 												initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
  1988 												formatSelection: data.amsSelect2FormatSelection === undefined
  2037 												formatSelection: data.amsSelect2FormatSelection === undefined
  1989 																	? ams.helpers.select2FormatSelection
  2038 																	? ams.helpers.select2FormatSelection
  1990 																	: ams.getFunctionByName(data.amsSelect2FormatSelection),
  2039 																	: ams.getFunctionByName(data.amsSelect2FormatSelection),
  1991 												formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
  2040 												formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
       
  2041 												formatMatches: data.amsSelect2FormatMatches === undefined
       
  2042 																	? function(matches) {
       
  2043 																		if (matches == 1)
       
  2044 																			return ams.i18n.SELECT2_MATCH;
       
  2045 																		else
       
  2046 																			return matches + ams.i18n.SELECT2_MATCHES;
       
  2047 																	}
       
  2048 																	: ams.getFunctionByName(data.amsSelect2FormatMatches),
  1992 												formatNoMatches: data.amsSelect2FormatResult === undefined
  2049 												formatNoMatches: data.amsSelect2FormatResult === undefined
  1993 																	? function(term) {
  2050 																	? function(term) {
  1994 																		return ams.i18n.SELECT2_NOMATCHES;
  2051 																		return ams.i18n.SELECT2_NOMATCHES;
  1995 																	}
  2052 																	}
  1996 																	: ams.getFunctionByName(data.amsSelect2FormatResult),
  2053 																	: ams.getFunctionByName(data.amsSelect2FormatResult),
  2051 													break;
  2108 													break;
  2052 												default:
  2109 												default:
  2053 													break;
  2110 													break;
  2054 											}
  2111 											}
  2055 
  2112 
  2056 											if (data.amsSelect2Query) {
  2113 											if (select.attr('readonly')) {
       
  2114 												data_options.query = function() {
       
  2115 													return [];
       
  2116 												};
       
  2117 											} else if (data.amsSelect2Query) {
  2057 												// Custom query method
  2118 												// Custom query method
  2058 												data_options.query = ams.getFunctionByName(data.amsSelect2Query);
  2119 												data_options.query = ams.getFunctionByName(data.amsSelect2Query);
  2059 												data_options.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
  2120 												data_options.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
  2060 											} else if (data.amsSelect2QueryUrl) {
  2121 											} else if (data.amsSelect2QueryUrl) {
  2061 												// AJAX query
  2122 												// AJAX query
  2117 
  2178 
  2118 											var settings = $.extend({}, data_options, data.amsSelect2Options);
  2179 											var settings = $.extend({}, data_options, data.amsSelect2Options);
  2119 											settings = ams.executeFunctionByName(data.amsSelect2InitCallback, select, settings) || settings;
  2180 											settings = ams.executeFunctionByName(data.amsSelect2InitCallback, select, settings) || settings;
  2120 											var plugin = select.select2(settings);
  2181 											var plugin = select.select2(settings);
  2121 											ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings);
  2182 											ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings);
       
  2183 											if (select.hasClass('ordered')) {
       
  2184 												$(plugin.context).parents('.select2-parent').find('ul.select2-choices').sortable({
       
  2185 													containment: 'parent',
       
  2186 													start: function() {
       
  2187 														select.select2('onSortStart');
       
  2188 													},
       
  2189 													update: function() {
       
  2190 														select.select2('onSortEnd');
       
  2191 													}
       
  2192 											   })
       
  2193 											}
  2122 
  2194 
  2123 											select.on('change', function() {
  2195 											select.on('change', function() {
  2124 												var validator = $(select.get(0).form).data('validator');
  2196 												var validator = $(select.get(0).form).data('validator');
  2125 												if (validator !== undefined)
  2197 												if (validator !== undefined)
  2126 													$(select).valid();
  2198 													$(select).valid();
  2153 								   });
  2225 								   });
  2154 				}
  2226 				}
  2155 			},
  2227 			},
  2156 
  2228 
  2157 			/**
  2229 			/**
  2158 			 * JQuery-UI date picker
  2230 			 * JQuery date picker
  2159 			 */
  2231 			 */
  2160 			datepicker: function(element) {
  2232 			datepicker: function(element) {
  2161 				var datepickers = $('.datepicker', element);
  2233 				var datepickers = $('.datepicker', element);
  2162 				if (datepickers.length > 0) {
  2234 				if (datepickers.length > 0) {
  2163 					datepickers.each(function() {
  2235 					ams.ajax.check($.fn.datetimepicker,
  2164 						var picker = $(this);
  2236 								   ams.baseURL + 'ext/jquery-datetimepicker' + (ams.devmode ? '.js': '.min.js'),
  2165 						var data = picker.data();
  2237 								   function(first_load) {
  2166 						var data_options = {
  2238 										if (first_load) {
  2167 							dateFormat: data.amsDatepickerFormat || 'dd/mm/yy',
  2239 											ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + (ams.devmode ? '.css' : '.min.css'), 'jquery-datetimepicker');
  2168 							prevText: '<i class="fa fa-chevron-left"></i>',
  2240 										}
  2169 							nextText: '<i class="fa fa-chevron-right"></i>',
  2241 										datepickers.each(function() {
  2170 							changeMonth: data.amsDatepickerChangeMonth,
  2242 											var input = $(this);
  2171 							changeYear: data.amsDatepickerChangeYear,
  2243 											var data = input.data();
  2172 							showButtonPanel: !data.amsDatepickerHidePanel
  2244 											var data_options = {
  2173 						};
  2245 												lang: data.amsDatetimepickerLang || ams.lang,
  2174 						var settings = $.extend({}, data_options, data.amsDatepickerOptions);
  2246 												format: data.amsDatetimepickerFormat || 'd/m/y',
  2175 						settings = ams.executeFunctionByName(data.amsDatepickerInitCallback, picker, settings) || settings;
  2247 												datepicker: true,
  2176 						var plugin = picker.datepicker(settings);
  2248 												dayOfWeekStart: 1,
  2177 						ams.executeFunctionByName(data.amsDatepickerAfterInitCallback, picker, plugin, settings);
  2249 												timepicker: false
  2178 					});
  2250 											};
       
  2251 											var settings = $.extend({}, data_options, data.amsDatetimepickerOptions);
       
  2252 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
  2253 											var plugin = input.datetimepicker(settings);
       
  2254 											ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
  2255 										});
       
  2256 								   });
       
  2257 				}
       
  2258 			},
       
  2259 
       
  2260 			/**
       
  2261 			 * JQuery datetime picker
       
  2262 			 */
       
  2263 			datetimepicker: function(element) {
       
  2264 				var datetimepickers = $('.datetimepicker', element);
       
  2265 				if (datetimepickers.length > 0) {
       
  2266 					ams.ajax.check($.fn.datetimepicker,
       
  2267 								   ams.baseURL + 'ext/jquery-datetimepicker' + (ams.devmode ? '.js': '.min.js'),
       
  2268 								   function(first_load) {
       
  2269 										if (first_load) {
       
  2270 											ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + (ams.devmode ? '.css' : '.min.css'), 'jquery-datetimepicker');
       
  2271 										}
       
  2272 										datetimepickers.each(function() {
       
  2273 											var input = $(this);
       
  2274 											var data = input.data();
       
  2275 											var data_options = {
       
  2276 												lang: data.amsDatetimepickerLang || ams.lang,
       
  2277 												format: data.amsDatetimepickerFormat || 'd/m/y H:i',
       
  2278 												datepicker: true,
       
  2279 												dayOfWeekStart: 1,
       
  2280 												timepicker: true
       
  2281 											};
       
  2282 											var settings = $.extend({}, data_options, data.amsDatetimepickerOptions);
       
  2283 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
  2284 											var plugin = input.datetimepicker(settings);
       
  2285 											ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
  2286 										});
       
  2287 								   });
       
  2288 				}
       
  2289 			},
       
  2290 
       
  2291 			/**
       
  2292 			 * JQuery time picker
       
  2293 			 */
       
  2294 			timepicker: function(element) {
       
  2295 				var timepickers = $('.timepicker', element);
       
  2296 				if (timepickers.length > 0) {
       
  2297 					ams.ajax.check($.fn.datetimepicker,
       
  2298 								   ams.baseURL + 'ext/jquery-datetimepicker' + (ams.devmode ? '.js': '.min.js'),
       
  2299 								   function(first_load) {
       
  2300 										if (first_load) {
       
  2301 											ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + (ams.devmode ? '.css' : '.min.css'), 'jquery-datetimepicker');
       
  2302 										}
       
  2303 										timepickers.each(function() {
       
  2304 											var input = $(this);
       
  2305 											var data = input.data();
       
  2306 											var data_options = {
       
  2307 												lang: data.amsDatetimepickerLang || ams.lang,
       
  2308 												format: data.amsDatetimepickerFormat || 'H:i',
       
  2309 												datepicker: false,
       
  2310 												timepicker: true
       
  2311 											};
       
  2312 											var settings = $.extend({}, data_options, data.amsDatetimepickerOptions);
       
  2313 											settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
  2314 											var plugin = input.datetimepicker(settings);
       
  2315 											ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
  2316 										});
       
  2317 								   });
  2179 				}
  2318 				}
  2180 			},
  2319 			},
  2181 
  2320 
  2182 			/**
  2321 			/**
  2183 			 * JQuery typeahead plug-in
  2322 			 * JQuery typeahead plug-in
  2219 													$(element).closest('.form-group, label:not(:parents(.form-group))').removeClass('state-error');
  2358 													$(element).closest('.form-group, label:not(:parents(.form-group))').removeClass('state-error');
  2220 												},
  2359 												},
  2221 												errorElement: 'span',
  2360 												errorElement: 'span',
  2222 												errorClass: 'state-error',
  2361 												errorClass: 'state-error',
  2223 												errorPlacement: function(error, element) {
  2362 												errorPlacement: function(error, element) {
  2224 													if (element.parent('label').length)
  2363 													var label = element.parents('label:first');
  2225 														error.insertAfter(element.parent());
  2364 													if (label.length)
       
  2365 														error.insertAfter(label);
  2226 													else
  2366 													else
  2227 														error.insertAfter(element);
  2367 														error.insertAfter(element);
  2228 												}
  2368 												}
  2229 											});
  2369 											});
  2230 											if (ams.plugins.i18n) {
  2370 											if (ams.plugins.i18n) {
  2247 																	? function() {
  2387 																	? function() {
  2248 																		// JQuery-form plug-in must be loaded synchronously!!
  2388 																		// JQuery-form plug-in must be loaded synchronously!!
  2249 																		// Otherwise, hidden input fields created by jquery-validate plug-in
  2389 																		// Otherwise, hidden input fields created by jquery-validate plug-in
  2250 																		// and matching named buttons will be deleted (on first form submit)
  2390 																		// and matching named buttons will be deleted (on first form submit)
  2251 																		// before JQuery-form plug-in can get them when submitting the form...
  2391 																		// before JQuery-form plug-in can get them when submitting the form...
       
  2392 																		$('.state-error', form).removeClass('state-error');
  2252 																		ams.ajax.check($.fn.ajaxSubmit,
  2393 																		ams.ajax.check($.fn.ajaxSubmit,
  2253 																					   ams.baseURL + 'ext/jquery-form-3.49' + (ams.devmode ? '.js' : '.min.js'));
  2394 																					   ams.baseURL + 'ext/jquery-form-3.49' + (ams.devmode ? '.js' : '.min.js'));
  2254 																		return ams.form.submit(form);
  2395 																		return ams.form.submit(form);
  2255 																	}
  2396 																	}
  2256 																	: ams.getFunctionByName(data.amsFormSubmitHandler)
  2397 																	: ams.getFunctionByName(data.amsFormSubmitHandler)
  2257 															   : undefined
  2398 															   : undefined,
       
  2399 												invalidHandler: form.attr('data-async') !== undefined
       
  2400 																? data.amsFormInvalidHandler === undefined
       
  2401 																	? function(event, validator) {
       
  2402 																		$('.state-error', form).removeClass('state-error');
       
  2403 																		for (var index in validator.errorList) {
       
  2404 																			var error = validator.errorList[index];
       
  2405 																			var tab_index = $(error.element).parents('.tab-pane').index() + 1;
       
  2406 																			if (tab_index > 0) {
       
  2407 																				var nav_tabs = $('.nav-tabs', $(error.element).parents('.tabforms'));
       
  2408 																				$('li:nth-child(' + tab_index + ')', nav_tabs)
       
  2409 																						.removeClassPrefix('state-')
       
  2410 																						.addClass('state-error');
       
  2411 																				$('li.state-error:first a', nav_tabs).click();
       
  2412 																			}
       
  2413 																		}
       
  2414 																	}
       
  2415 																	: ams.getFunctionByName(data.amsFormInvalidHandler)
       
  2416 																: undefined
  2258 											};
  2417 											};
  2259 											var settings = $.extend({}, data_options, data.amsValidateOptions);
  2418 											var settings = $.extend({}, data_options, data.amsValidateOptions);
  2260 											settings = ams.executeFunctionByName(data.amsValidateInitCallback, form, settings) || settings;
  2419 											settings = ams.executeFunctionByName(data.amsValidateInitCallback, form, settings) || settings;
  2261 											var plugin = form.validate(settings);
  2420 											var plugin = form.validate(settings);
  2262 											ams.executeFunctionByName(data.amsValidateAfterInitCallback, form, plugin, settings);
  2421 											ams.executeFunctionByName(data.amsValidateAfterInitCallback, form, plugin, settings);
  2395 											settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
  2554 											settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
  2396 											var plugin = table.dataTable(settings);
  2555 											var plugin = table.dataTable(settings);
  2397 											ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
  2556 											ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
  2398 											if (extensions.length > 0) {
  2557 											if (extensions.length > 0) {
  2399 												for (index in extensions) {
  2558 												for (index in extensions) {
  2400 													switch(extensions[index]) {
  2559 													switch (extensions[index]) {
  2401 														case 'autofill':
  2560 														case 'autofill':
  2402 															var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
  2561 															var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
  2403 															af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings;
  2562 															af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings;
  2404 															table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined
  2563 															table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined
  2405 																						? new $.fn.dataTable.AutoFill(table, af_settings)
  2564 																						? new $.fn.dataTable.AutoFill(table, af_settings)
  2476 								   });
  2635 								   });
  2477 				}
  2636 				}
  2478 			},
  2637 			},
  2479 
  2638 
  2480 			/**
  2639 			/**
       
  2640 			 * TableDND plug-in
       
  2641 			 */
       
  2642 			tablednd: function(element) {
       
  2643 				var tables = $('.table-dnd', element);
       
  2644 				if (tables.length > 0) {
       
  2645 					ams.ajax.check($.fn.tableDnD,
       
  2646 								   ams.baseURL + 'ext/jquery-tablednd' + (ams.devmode ? '.js' : '.min.js'),
       
  2647 								   function(first_load) {
       
  2648 										tables.each(function() {
       
  2649 											var table = $(this);
       
  2650 											$(table).on('mouseover', 'tr', function() {
       
  2651 												$(this.cells[0]).addClass('drag-handle');
       
  2652 											}).on('mouseout', 'tr', function() {
       
  2653 												$(this.cells[0]).removeClass('drag-handle');
       
  2654 											});
       
  2655 											var data = table.data();
       
  2656 											var data_options = {
       
  2657 												onDragClass: data.amsTabledndDragClass || 'dragging-row',
       
  2658 												onDragStart: data.amsTabledndDragStart,
       
  2659 												dragHandle: data.amsTabledndDragHandle,
       
  2660 												scrollAmount: data.amsTabledndScrollAmount,
       
  2661 												onAllowDrop: data.amsTabledndAllowDrop,
       
  2662 												onDrop: data.amsTabledndDrop || function(dnd_table, row) {
       
  2663 													var target = data.amsTabledndDropTarget;
       
  2664 													if (target) {
       
  2665 														var rows = [];
       
  2666 														$(dnd_table.rows).each(function() {
       
  2667 															var row_id = $(this).data('ams-element-name');
       
  2668 															if (row_id)
       
  2669 																rows.push(row_id);
       
  2670 														});
       
  2671 														var local_target = ams.getFunctionByName(target);
       
  2672 														if (typeof(local_target) == 'function') {
       
  2673 															local_target.call(table, dnd_table, rows);
       
  2674 														} else {
       
  2675 															ams.ajax.post(target, {names: rows});
       
  2676 														}
       
  2677 													}
       
  2678 												}
       
  2679 											};
       
  2680 											var settings = $.extend({}, data_options, data.amsTabledndOptions);
       
  2681 											settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings;
       
  2682 											var plugin = table.tableDnD(settings);
       
  2683 											ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings);
       
  2684 										});
       
  2685 								   });
       
  2686 				}
       
  2687 			},
       
  2688 
       
  2689 			/**
       
  2690 			 * FancyBox plug-in
       
  2691 			 */
       
  2692 			fancybox: function(element) {
       
  2693 				var fancyboxes = $('.fancybox', element);
       
  2694 				if (fancyboxes.length > 0) {
       
  2695 					ams.ajax.check($.fn.fancybox,
       
  2696 								   ams.baseURL + 'ext/jquery-fancybox-2.1.5' + (ams.devmode ? '.js' : '.min.js'),
       
  2697 								   function(first_load) {
       
  2698 										if (first_load)
       
  2699 											ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + (ams.devmode ? '.css' : '.min.css'));
       
  2700 										fancyboxes.each(function() {
       
  2701 											var fancybox = $(this);
       
  2702 											var data = fancybox.data();
       
  2703 											var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
       
  2704 											if (helpers.length > 0) {
       
  2705 												for (var index in helpers) {
       
  2706 													var helper = helpers[index];
       
  2707 													switch (helper) {
       
  2708 														case 'buttons':
       
  2709 															ams.ajax.check($.fancybox.helpers.buttons,
       
  2710 																		   ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons.js' + (ams.devmode ? '.js' : '.min.js'));
       
  2711 															break;
       
  2712 														case 'thumbs':
       
  2713 															ams.ajax.check($.fancybox.helpers.thumbs,
       
  2714 																		   ams.baseURL + 'ext/fancybox-helpers/fancybox-thumbs.js' + (ams.devmode ? '.js' : '.min.js'));
       
  2715 															break;
       
  2716 														case 'media':
       
  2717 															ams.ajax.check($.fancybox.helpers.media,
       
  2718 																		   ams.baseURL + 'ext/fancybox-helpers/fancybox-media.js' + (ams.devmode ? '.js' : '.min.js'));
       
  2719 															break;
       
  2720 														default:
       
  2721 															break;
       
  2722 													}
       
  2723 												}
       
  2724 											}
       
  2725 											var data_options = {
       
  2726 												type: data.amsFancyboxType,
       
  2727 												padding: data.amsFancyboxPadding || 10,
       
  2728 												margin: data.amsFancyboxMargin || 10,
       
  2729 												beforeLoad: ams.getFunctionByName(data.amsFancyboxBeforeLoad) || function() {
       
  2730 													this.title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this) || $(this.element).attr('original-title') || $(this.element).attr('title');
       
  2731 												},
       
  2732 												helpers: {
       
  2733 													title: {
       
  2734 														type: 'inside'
       
  2735 													}
       
  2736 												}
       
  2737 											};
       
  2738 											var settings = $.extend({}, data_options, data.amsFancyboxOptions);
       
  2739 											settings = ams.executeFunctionByName(data.amsFancyboxInitCallback, fancybox, settings) || settings;
       
  2740 											var plugin = fancybox.fancybox(settings);
       
  2741 											ams.executeFunctionByName(data.amsFancyboxAfterInitCallback, fancybox, plugin, settings);
       
  2742 										});
       
  2743 								   });
       
  2744 				}
       
  2745 			},
       
  2746 
       
  2747 			/**
       
  2748 			 * Image area select plug-in
       
  2749 			 */
       
  2750 			imgareaselect: function(element) {
       
  2751 				var images = $('.imgareaselect', element);
       
  2752 				if (images.length > 0) {
       
  2753 					ams.ajax.check($.fn.imgAreaSelect,
       
  2754 								   ams.baseURL + 'ext/jquery-imgareaselect-0.9.10' + (ams.devmode ? '.js' : '.min.js'),
       
  2755 								   function(first_load) {
       
  2756 										if (first_load)
       
  2757 											ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + (ams.devmode ? '.css' : '.min.css'));
       
  2758 										images.each(function() {
       
  2759 											var image = $(this);
       
  2760 											var data = image.data();
       
  2761 											var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body';
       
  2762 											var data_options = {
       
  2763 												instance: true,
       
  2764 												handles: true,
       
  2765 												parent: parent,
       
  2766 												x1: data.amsImgareaselectX1 || 0,
       
  2767 												y1: data.amsImgareaselectY1 || 0,
       
  2768 												x2: data.amsImgareaselectX2 || data.amsImgareaselectImageWidth,
       
  2769 												y2: data.amsImgareaselectY2 || data.amsImgareaselectImageHeight,
       
  2770 												imageWidth: data.amsImgareaselectImageWidth,
       
  2771 												imageHeight: data.amsImgareaselectImageHeight,
       
  2772 												minWidth: 128,
       
  2773 												minHeight: 128,
       
  2774 												aspectRatio: data.amsImgareaselectRatio,
       
  2775 												onSelectEnd: ams.getFunctionByName(data.amsImgareaselectSelectEnd) || function(img, selection) {
       
  2776 													var target = data.amsImgareaselectTargetField || 'image_';
       
  2777 													$('input[name="' + target + 'x1"]', parent).val(selection.x1);
       
  2778 													$('input[name="' + target + 'y1"]', parent).val(selection.y1);
       
  2779 													$('input[name="' + target + 'x2"]', parent).val(selection.x2);
       
  2780 													$('input[name="' + target + 'y2"]', parent).val(selection.y2);
       
  2781 												}
       
  2782 											};
       
  2783 											var settings = $.extend({}, data_options, data.amsImgareaselectOptions);
       
  2784 											settings = ams.executeFunctionByName(data.amsImgareaselectInitCallback, image, settings) || settings;
       
  2785 											var plugin = image.imgAreaSelect(settings);
       
  2786 											ams.executeFunctionByName(data.amsImgareaselectAfterInitCallback, image, plugin, settings);
       
  2787 											// Add update timeout when plug-in is displayed into a modal dialog
       
  2788 											setTimeout(function() {
       
  2789 												plugin.update();
       
  2790 											}, 250);
       
  2791 										});
       
  2792 								   })
       
  2793 				}
       
  2794 			},
       
  2795 
       
  2796 			/**
  2481 			 * Sparkline graphs
  2797 			 * Sparkline graphs
  2482 			 */
  2798 			 */
  2483 			graphs: function(element) {
  2799 			graphs: function(element) {
  2484 				var graphs = $('.sparkline', element);
  2800 				var graphs = $('.sparkline', element);
  2485 				if (graphs.length > 0) {
  2801 				if (graphs.length > 0) {
  2606 			var settings = $.extend({}, data_options, {
  2922 			var settings = $.extend({}, data_options, {
  2607 				title: data.amsMessageboxTitle || data_options.title || '',
  2923 				title: data.amsMessageboxTitle || data_options.title || '',
  2608 				content: data.amsMessageboxContent || data_options.content || '',
  2924 				content: data.amsMessageboxContent || data_options.content || '',
  2609 				icon: data.amsMessageboxIcon || data_options.icon,
  2925 				icon: data.amsMessageboxIcon || data_options.icon,
  2610 				number: data.amsMessageboxNumber || data_options.number,
  2926 				number: data.amsMessageboxNumber || data_options.number,
  2611 				timeout: data.amsMessageboxTimeout || data_options.icon
  2927 				timeout: data.amsMessageboxTimeout || data_options.timeout
  2612 			});
  2928 			});
  2613 			var status = data.amsMessageboxStatus || data_options.status || 'info';
  2929 			var status = data.amsMessageboxStatus || data_options.status || 'info';
  2614 			var callback = ams.getFunctionByName(data.amsMessageboxCallback || data_options.callback);
  2930 			var callback = ams.getFunctionByName(data.amsMessageboxCallback || data_options.callback);
  2615 			ams.skin.messageBox(status, settings, callback);
  2931 			ams.skin.messageBox(status, settings, callback);
  2616 		},
  2932 		},
  2635 			var settings = $.extend({}, data_options, {
  2951 			var settings = $.extend({}, data_options, {
  2636 				title: data.amsSmallboxTitle || data_options.title || '',
  2952 				title: data.amsSmallboxTitle || data_options.title || '',
  2637 				content: data.amsSmallboxContent || data_options.content || '',
  2953 				content: data.amsSmallboxContent || data_options.content || '',
  2638 				icon: data.amsSmallboxIcon || data_options.icon,
  2954 				icon: data.amsSmallboxIcon || data_options.icon,
  2639 				iconSmall: data.amsSmallboxIconSmall || data_options.iconSmall,
  2955 				iconSmall: data.amsSmallboxIconSmall || data_options.iconSmall,
  2640 				timeout: data.amsSmallboxTimeout || data_options.icon
  2956 				timeout: data.amsSmallboxTimeout || data_options.timeout
  2641 			});
  2957 			});
  2642 			var status = data.amsSmallboxStatus || data_options.status || 'info';
  2958 			var status = data.amsSmallboxStatus || data_options.status || 'info';
  2643 			var callback = ams.getFunctionByName(data.amsSmallboxCallback || data_options.callback);
  2959 			var callback = ams.getFunctionByName(data.amsSmallboxCallback || data_options.callback);
  2644 			ams.skin.smallBox(status, settings, callback);
  2960 			ams.skin.smallBox(status, settings, callback);
  2645 		}
  2961 		}
  2665 				var handlers = element.data('ams-events-handlers');
  2981 				var handlers = element.data('ams-events-handlers');
  2666 				for (var event in handlers) {
  2982 				for (var event in handlers) {
  2667 					element.on(event, ams.getFunctionByName(handlers[event]));
  2983 					element.on(event, ams.getFunctionByName(handlers[event]));
  2668 				}
  2984 				}
  2669 			});
  2985 			});
       
  2986 		}
       
  2987 	};
       
  2988 
       
  2989 
       
  2990 	/**
       
  2991 	 * Container management
       
  2992 	 */
       
  2993 	MyAMS.container = {
       
  2994 
       
  2995 		/**
       
  2996 		 * Change container elements order
       
  2997 		 *
       
  2998 		 * This is a callback which may be used with TableDnD plug-in which allows you to
       
  2999 		 * change order of table rows.
       
  3000 		 * Rows order is stored in an hidden input which is defined in table's data attribute
       
  3001 		 * called 'data-ams-input-name'
       
  3002 		 */
       
  3003 		changeOrder: function(table, names) {
       
  3004 			var input = $('input[name="' + $(this).data('ams-input-name') + '"]', $(this));
       
  3005 			input.val(names.join(';'));
       
  3006 		},
       
  3007 
       
  3008 		/**
       
  3009 		 * Delete an element from a container table
       
  3010 		 *
       
  3011 		 * @param element
       
  3012 		 * @returns {Function}
       
  3013 		 */
       
  3014 		deleteElement: function(element) {
       
  3015 			return function() {
       
  3016 				var link = $(this);
       
  3017 				MyAMS.skin.bigBox({
       
  3018 					title: MyAMS.i18n.WARNING,
       
  3019 					content: '<i class="text-danger fa fa-2x fa-bell shake animated"></i>&nbsp; ' + MyAMS.i18n.DELETE_WARNING,
       
  3020 					buttons: MyAMS.i18n.BTN_OK_CANCEL
       
  3021 				}, function(button) {
       
  3022 					if (button == MyAMS.i18n.BTN_OK) {
       
  3023 						var table = link.parents('table');
       
  3024 						var location = table.data('ams-location');
       
  3025 						var tr = link.parents('tr');
       
  3026 						var delete_target = tr.data('ams-delete-target') || table.data('ams-delete-target') || 'delete-element.json';
       
  3027 						var object_name = tr.data('ams-element-name');
       
  3028 						MyAMS.ajax.post(location + '/' + delete_target, {'object_name': object_name}, function(result, status) {
       
  3029 							if (result.status == 'success') {
       
  3030 								if (table.hasClass('datatable')) {
       
  3031 									table.dataTable().fnDeleteRow(tr[0]);
       
  3032 								} else {
       
  3033 									tr.remove();
       
  3034 								}
       
  3035 							}
       
  3036 						});
       
  3037 					}
       
  3038 				});
       
  3039 			}
  2670 		}
  3040 		}
  2671 	};
  3041 	};
  2672 
  3042 
  2673 
  3043 
  2674 	/**
  3044 	/**
  3049 	 * Main page initialization
  3419 	 * Main page initialization
  3050 	 * This code is called only once to register global events and callbacks
  3420 	 * This code is called only once to register global events and callbacks
  3051 	 */
  3421 	 */
  3052 	MyAMS.initPage = function() {
  3422 	MyAMS.initPage = function() {
  3053 
  3423 
       
  3424 		var body = $('body');
       
  3425 
  3054 		/* Init main components */
  3426 		/* Init main components */
  3055 		ams.root = $('BODY');
  3427 		ams.root = body;
  3056 		ams.left_panel = $('#left-panel');
  3428 		ams.left_panel = $('#left-panel');
  3057 		ams.shortcuts = $('#shortcut');
  3429 		ams.shortcuts = $('#shortcut');
       
  3430 		ams.plugins.initData(body);
  3058 
  3431 
  3059 		// Init main AJAX events
  3432 		// Init main AJAX events
  3060 		var jquery_xhr = $.ajaxSettings.xhr;
  3433 		var jquery_xhr = $.ajaxSettings.xhr;
  3061 		$.ajaxSetup({
  3434 		$.ajaxSetup({
  3062 			progress: ams.ajax.progress,
  3435 			progress: ams.ajax.progress,
  3091 			}
  3464 			}
  3092 		}
  3465 		}
  3093 
  3466 
  3094 		// Hide menu button
  3467 		// Hide menu button
  3095 		$('#hide-menu >:first-child > A').click(function(e) {
  3468 		$('#hide-menu >:first-child > A').click(function(e) {
  3096 			$('BODY').toggleClass("hidden-menu");
  3469 			body.toggleClass("hidden-menu");
  3097 			e.preventDefault();
  3470 			e.preventDefault();
  3098 		});
  3471 		});
  3099 
  3472 
  3100 		// Switch shortcuts
  3473 		// Switch shortcuts
  3101 		$('#show-shortcut').click(function(e) {
  3474 		$('#show-shortcut').click(function(e) {
  3201 			});
  3574 			});
  3202 			e.preventDefault();
  3575 			e.preventDefault();
  3203 		});
  3576 		});
  3204 
  3577 
  3205 		// Check active pop-overs
  3578 		// Check active pop-overs
  3206 		$('BODY').on('click', function(e) {
  3579 		body.on('click', function(e) {
  3207 			var element = $(this);
  3580 			var element = $(this);
  3208 			if (!element.is(e.target) &&
  3581 			if (!element.is(e.target) &&
  3209 				element.has(e.target).length === 0 &&
  3582 				element.has(e.target).length === 0 &&
  3210 				$('.popover').has(e.target).length === 0)
  3583 				$('.popover').has(e.target).length === 0)
  3211 				element.popover('hide');
  3584 				element.popover('hide');
  3239 				e.preventDefault();
  3612 				e.preventDefault();
  3240 				var href_getter = ams.getFunctionByName(href);
  3613 				var href_getter = ams.getFunctionByName(href);
  3241 				if (typeof(href_getter) == 'function') {
  3614 				if (typeof(href_getter) == 'function') {
  3242 					href = href_getter.call(link);
  3615 					href = href_getter.call(link);
  3243 				}
  3616 				}
  3244 				var target = link.data('ams-target');
  3617 				if (typeof(href) == 'function') {
  3245 				if (target) {
  3618 					// Javascript function call
  3246 					ams.form.confirmChangedForm(target, function() {
  3619 					e.stopPropagation();
  3247 						ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback'));
  3620 					href.call(link);
  3248 					});
       
  3249 				} else {
  3621 				} else {
  3250 					ams.form.confirmChangedForm(function() {
  3622 					// Standard AJAX or browser URL call
  3251 						if (href.startsWith('#')) {
  3623 					// Convert %23 chars to #
  3252 							if (href != location.hash) {
  3624 					href = href.replace(/\%23/, '#');
  3253 								if (ams.root.hasClass('mobile-view-activated')) {
  3625 					var target = link.data('ams-target');
  3254 									ams.root.removeClass('hidden-menu');
  3626 					if (target) {
  3255 									window.setTimeout(function () {
  3627 						ams.form.confirmChangedForm(target, function () {
       
  3628 							ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback'));
       
  3629 							e.stopPropagation();
       
  3630 						});
       
  3631 					} else {
       
  3632 						ams.form.confirmChangedForm(function () {
       
  3633 							if (href.startsWith('#')) {
       
  3634 								if (href != location.hash) {
       
  3635 									if (ams.root.hasClass('mobile-view-activated')) {
       
  3636 										ams.root.removeClass('hidden-menu');
       
  3637 										window.setTimeout(function () {
       
  3638 											window.location.hash = href;
       
  3639 										}, 150);
       
  3640 									} else
  3256 										window.location.hash = href;
  3641 										window.location.hash = href;
  3257 									}, 150);
  3642 								}
  3258 								} else
  3643 							} else
  3259 									window.location.hash = href;
  3644 								window.location = href;
  3260 							}
  3645 						});
  3261 						} else
  3646 					}
  3262 							window.location = href;
       
  3263 					});
       
  3264 				}
  3647 				}
  3265 			});
  3648 			});
  3266 			$(document).on('click', 'a[target="_blank"]', function(e) {
  3649 			$(document).on('click', 'a[target="_blank"]', function(e) {
  3267 				e.preventDefault();
  3650 				e.preventDefault();
  3268 				window.open($(e.currentTarget).attr('href'));
  3651 				window.open($(e.currentTarget).attr('href'));
  3279 		}
  3662 		}
  3280 
  3663 
  3281 		// Initialize modal dialogs links
  3664 		// Initialize modal dialogs links
  3282 		$(document).off('click.modal')
  3665 		$(document).off('click.modal')
  3283 				   .on('click', '[data-toggle="modal"]', function(e) {
  3666 				   .on('click', '[data-toggle="modal"]', function(e) {
       
  3667 			var source = $(this);
       
  3668 			if (source.data('ams-stop-propagation') === true)
       
  3669 				e.stopPropagation();
  3284 			e.preventDefault();
  3670 			e.preventDefault();
  3285 			var source = $(this);
       
  3286 			ams.dialog.open(source);
  3671 			ams.dialog.open(source);
  3287 			if (source.parents('#shortcut').exists())
  3672 			if (source.parents('#shortcut').exists())
  3288 				setTimeout(ams.skin._hideShortcutButtons, 300);
  3673 				setTimeout(ams.skin._hideShortcutButtons, 300);
  3289 		});
  3674 		});
  3290 		$(document).on('shown.bs.modal', ams.dialog.shown);
  3675 		$(document).on('shown.bs.modal', ams.dialog.shown);
  3298 		// Initialize custom click handlers
  3683 		// Initialize custom click handlers
  3299 		$(document).on('click', '[data-ams-click-handler]', function(e) {
  3684 		$(document).on('click', '[data-ams-click-handler]', function(e) {
  3300 			var source = $(this);
  3685 			var source = $(this);
  3301 			var data = source.data();
  3686 			var data = source.data();
  3302 			if (data.amsClickHandler) {
  3687 			if (data.amsClickHandler) {
  3303 				if (data.amsClickStopPropagation === true)
  3688 				if ((data.amsStopPropagation === true) || (data.amsClickStopPropagation === true))
  3304 					e.stopPropagation();
  3689 					e.stopPropagation();
  3305 				if (data.amsClickKeepDefault !== true)
  3690 				if (data.amsClickKeepDefault !== true)
  3306 					e.preventDefault();
  3691 					e.preventDefault();
  3307 				var callback = ams.getFunctionByName(data.amsClickHandler);
  3692 				var callback = ams.getFunctionByName(data.amsClickHandler);
  3308 				if (callback !== undefined)
  3693 				if (callback !== undefined)
  3441 		CLEAR_STORAGE_TITLE: "Clear Local Storage",
  3826 		CLEAR_STORAGE_TITLE: "Clear Local Storage",
  3442 		CLEAR_STORAGE_CONTENT: "Would you like to RESET all your saved widgets and clear LocalStorage?",
  3827 		CLEAR_STORAGE_CONTENT: "Would you like to RESET all your saved widgets and clear LocalStorage?",
  3443 
  3828 
  3444 		BTN_OK: "OK",
  3829 		BTN_OK: "OK",
  3445 		BTN_CANCEL: "Cancel",
  3830 		BTN_CANCEL: "Cancel",
       
  3831 		BTN_OK_CANCEL: "[OK][Cancel]",
  3446 		BTN_YES: "Yes",
  3832 		BTN_YES: "Yes",
  3447 		BTN_NO: "No",
  3833 		BTN_NO: "No",
  3448 		BTN_OK_CANCEL: "[OK][Cancel]",
  3834 		BTN_YES_NO: "[Yes][No]",
  3449 
  3835 
  3450 		FORM_CHANGED_WARNING: "Some changes were not saved. These updates will be lost if you leave this page.",
  3836 		FORM_CHANGED_WARNING: "Some changes were not saved. These updates will be lost if you leave this page.",
       
  3837 		DELETE_WARNING: "This change can't be undone. Are you sure that you want to delete this element?",
  3451 		NO_UPDATE: "No changes were applied.",
  3838 		NO_UPDATE: "No changes were applied.",
  3452 		DATA_UPDATED: "Data successfully updated.",
  3839 		DATA_UPDATED: "Data successfully updated.",
  3453 
  3840 
  3454 		HOME: "Home",
  3841 		HOME: "Home",
  3455 		LOGOUT: "Logout?",
  3842 		LOGOUT: "Logout?",
  3456 		LOGOUT_COMMENT: "You can improve your security further after logging out by closing this opened browser",
  3843 		LOGOUT_COMMENT: "You can improve your security further after logging out by closing this opened browser",
  3457 
  3844 
  3458 		SELECT2_PLURAL: 's',
  3845 		SELECT2_PLURAL: 's',
       
  3846 		SELECT2_MATCH: "One result is available, press enter to select it.",
       
  3847 		SELECT2_MATCHES: " results are available, use up and down arrow keys to navigate.",
  3459 		SELECT2_NOMATCHES: "No matches found",
  3848 		SELECT2_NOMATCHES: "No matches found",
  3460 		SELECT2_SEARCHING: "Searching...",
  3849 		SELECT2_SEARCHING: "Searching...",
  3461 		SELECT2_LOADMORE: "Loading more results...",
  3850 		SELECT2_LOADMORE: "Loading more results...",
  3462 		SELECT2_INPUT_TOOSHORT: "Please enter {0} more character{1}",
  3851 		SELECT2_INPUT_TOOSHORT: "Please enter {0} more character{1}",
  3463 		SELECT2_INPUT_TOOLONG: "Please delete {0} character{1}",
  3852 		SELECT2_INPUT_TOOLONG: "Please delete {0} character{1}",