src/pyams_skin/resources/js/myams-plugins.js
changeset 557 bca7a7e058a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/resources/js/myams-plugins.js	Thu Feb 13 11:43:31 2020 +0100
@@ -0,0 +1,1817 @@
+/**
+ * MyAMS standard plug-ins
+ *
+ * Only basic JQuery, Bootstrap and MyAMS javascript extensions are typically loaded from main page.
+ * Other JQuery plug-ins may be loaded dynamically.
+ * Several JQuery extension plug-ins are already included and pre-configured by MyAMS. Other external
+ * plug-ins can be defined and loaded dynamically using simple "data" attributes.
+ *
+ * WARNING: any plug-in implicated into a form submit process (like JQuery-form or JQuery-progressbar)
+ * must be loaded in a synchronous way. Otherwise, if you use named buttons to submit your forms,
+ * dynamic hidden input fields created by JQuery-validate plug-in will be removed from the form
+ * before the form is submitted!
+ */
+(function($, globals) {
+
+	var ams = globals.MyAMS;
+
+	/**
+	 * Map of enabled plug-ins
+	 * This map can be extended by external plug-ins.
+	 *
+	 * Standard MyAMS plug-ins management method generally includes:
+	 * - applying a class matching plug-in name on a set of HTML entities to apply the plug-in
+	 * - defining a set of data-attributes on each of these entities to customize the plug-in
+	 * For each standard plug-in, you can also provide an options object (to define plug-in options not handled
+	 * by default MyAMS initialization engine) and an initialization callback (to define these options dynamically).
+	 * Another callback can also be provided to be called after plug-in initialization.
+	 *
+	 * You can also register plug-ins using the 'register' function
+	 */
+	$.extend(ams.plugins.enabled, {
+
+		/**
+		 * SVG containers
+		 */
+		svg: function(element) {
+			var svgs = $('.svg-container', element);
+			if (svgs.length > 0) {
+				svgs.each(function() {
+					var container = $(this);
+					var svg = $('svg', container),
+						width = svg.attr('width'),
+						height = svg.attr('height');
+					if (width && height) {
+						svg.get(0).setAttribute('viewBox',
+												'0 0 ' + Math.round(parseFloat(width)) + ' ' +
+													Math.round(parseFloat(height)));
+					}
+					svg.attr('width', '100%')
+						.attr('height', 'auto');
+				})
+			}
+		},
+
+		/**
+		 * Label hints
+		 */
+		hint: function(element) {
+			var hints = $('.hint:not(:parents(.nohints))', element);
+			if (hints.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.tipsy,
+										   ams.baseURL + 'ext/jquery-tipsy' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-tipsy' + ams.devext + '.css',
+														  'jquery-tipsy', function() {
+													   hints.each(function() {
+														   var hint = $(this);
+														   var data = hint.data();
+														   var dataOptions = {
+															   html: data.amsHintHtml === undefined ? (hint.attr('title') || '').startsWith('<') : data.amsHintHtml,
+															   title: ams.getFunctionByName(data.amsHintTitleGetter) || function() {
+																   var hint = $(this);
+																   var result = hint.attr('original-title') ||
+																	   hint.attr(data.amsHintTitleAttr || 'title') ||
+																	   (data.amsHintHtml ? hint.html() : hint.text());
+																   result = result.replace(/\?_="/, '?_=' + new Date().getTime() + '"');
+																   return result;
+															   },
+															   opacity: data.amsHintOpacity || 0.95,
+															   gravity: data.amsHintGravity || 'sw',
+															   offset: data.amsHintOffset || 0
+														   };
+														   var settings = $.extend({}, dataOptions, data.amsHintOptions);
+														   settings = ams.executeFunctionByName(data.amsHintInitCallback, hint, settings) || settings;
+														   var plugin = hint.tipsy(settings);
+														   ams.executeFunctionByName(data.amsHintAfterInitCallback, hint, plugin, settings);
+													   });
+												   });
+										   });
+			}
+		},
+
+		/**
+		 * Context menu plug-in
+		 */
+		contextMenu: function(element) {
+			var menus = $('.context-menu', element);
+			if (menus.length > 0) {
+				menus.each(function() {
+					var menu = $(this);
+					var data = menu.data();
+					var dataOptions = {
+						menuSelector: data.amsContextmenuSelector,
+						menuSelected: ams.helpers && ams.helpers.contextMenuHandler
+					};
+					var settings = $.extend({}, dataOptions, data.amsContextmenuOptions);
+					settings = ams.executeFunctionByName(data.amsContextmenuInitCallback, menu, settings) || settings;
+					var plugin = menu.contextMenu(settings);
+					ams.executeFunctionByName(data.amsContextmenuAfterInitCallback, menu, plugin, settings);
+				});
+			}
+		},
+
+		/**
+		 * Fieldset legend switcher
+		 */
+		switcher: function(element) {
+			$('LEGEND.switcher', element).each(function() {
+				var legend = $(this);
+				var fieldset = legend.parent('fieldset');
+				var data = legend.data();
+				if (!data.amsSwitcher) {
+					$('<i class="fa fa-fw"></i>')
+						.prependTo($(this))
+						.addClass(data.amsSwitcherState === 'open' ?
+									  (data.amsSwitcherMinusClass || 'fa-minus') :
+									  (data.amsSwitcherPlusClass || 'fa-plus'));
+					legend.on('click', function(e) {
+						e.preventDefault();
+						var veto = {};
+						legend.trigger('ams.switcher.before-switch', [legend, veto]);
+						if (veto.veto) {
+							return;
+						}
+						if (fieldset.hasClass('switched')) {
+							fieldset.removeClass('switched');
+							$('.fa', legend).removeClass(data.amsSwitcherPlusClass || 'fa-plus')
+								.addClass(data.amsSwitcherMinusClass || 'fa-minus');
+							legend.trigger('ams.switcher.opened', [legend]);
+							var id = legend.attr('id');
+							if (id) {
+								$('legend.switcher[data-ams-switcher-sync="' + id + '"]', fieldset).each(function() {
+									var switcher = $(this);
+									if (switcher.parents('fieldset').hasClass('switched')) {
+										switcher.click();
+									}
+								});
+							}
+						} else {
+							fieldset.addClass('switched');
+							$('.fa', legend).removeClass(data.amsSwitcherMinusClass || 'fa-minus')
+								.addClass(data.amsSwitcherPlusClass || 'fa-plus');
+							legend.trigger('ams.switcher.closed', [legend]);
+						}
+					});
+					if (data.amsSwitcherState !== 'open') {
+						fieldset.addClass('switched');
+					}
+					legend.data('ams-switcher', 'on');
+				}
+			});
+		},
+
+		/**
+		 * Fieldset legend checker
+		 */
+		checker: function(element) {
+			$('LEGEND.checker', element).each(function() {
+				var legend = $(this);
+				var fieldset = legend.parent('fieldset');
+				var data = legend.data();
+				if (!data.amsChecker) {
+					var checker = $('<label class="checkbox"></label>');
+					var fieldname = data.amsCheckerFieldname || ('checker_' + ams.generateId());
+					var checkboxId = fieldname.replace(/\./, '_');
+					var prefix = data.amsCheckerHiddenPrefix;
+					var hidden = null;
+					var checkedValue = data.amsCheckerHiddenValueOn || 'true';
+					var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
+					var marker = data.amsCheckerMarker || false;
+					if (prefix) {
+						hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
+							.val(data.amsCheckerState === 'on' ? checkedValue : uncheckedValue)
+							.prependTo(legend);
+					} else if (marker) {
+						$('<input type="hidden">').attr('name', marker)
+							.attr('value', 1)
+							.prependTo(legend);
+					}
+					var input = $('<input type="checkbox">').attr('name', fieldname)
+						.attr('id', checkboxId)
+						.data('ams-checker-hidden-input', hidden)
+						.data('ams-checker-init', true)
+						.val(data.amsCheckerValue || true)
+						.attr('checked', data.amsCheckerState === 'on' ? 'checked' : null);
+					if (data.amsCheckerReadonly) {
+						input.attr('disabled', 'disabled');
+					} else {
+						input.on('change', function(e) {
+							e.preventDefault();
+							var veto = {};
+							var isChecked = $(this).is(':checked');
+							legend.trigger('ams.checker.before-switch', [legend, veto]);
+							if (veto.veto) {
+								// reset checked status because event is fired after change...
+								$(this).prop('checked', !isChecked);
+								return;
+							}
+							ams.executeFunctionByName(data.amsCheckerChangeHandler, legend, isChecked);
+							if (!data.amsCheckerCancelDefault) {
+								var hidden = input.data('ams-checker-hidden-input');
+								if (isChecked) {
+									if (data.amsCheckerMode === 'disable') {
+										fieldset.removeAttr('disabled');
+										$('.select2', fieldset).removeAttr('disabled');
+									} else {
+										fieldset.removeClass('switched');
+									}
+									if (hidden) {
+										hidden.val(checkedValue);
+									}
+									$('[data-required]', fieldset).attr('required', 'required');
+									legend.trigger('ams.checker.opened', [legend]);
+								} else {
+									if (data.amsCheckerMode === 'disable') {
+										fieldset.prop('disabled', 'disabled');
+										$('.select2', fieldset).attr('disabled', 'disabled');
+									} else {
+										fieldset.addClass('switched');
+									}
+									if (hidden) {
+										hidden.val(uncheckedValue);
+									}
+									$('[data-required]', fieldset).removeAttr('required');
+									legend.trigger('ams.checker.closed', [legend]);
+								}
+							}
+						});
+					}
+					input.appendTo(checker);
+					$('>label', legend).attr('for', input.attr('id'));
+					checker.append('<i></i>')
+						.prependTo(legend);
+					var required = $('[required]', fieldset);
+					required.attr('data-required', true);
+					if (data.amsCheckerState === 'on') {
+						input.attr('checked', true);
+					} else {
+						if (data.amsCheckerMode === 'disable') {
+							fieldset.attr('disabled', 'disabled');
+							$('.select2', fieldset).attr('disabled', 'disabled');
+						} else {
+							fieldset.addClass('switched');
+						}
+						required.removeAttr('required');
+					}
+					legend.data('ams-checker', 'on');
+				}
+			});
+		},
+
+		/**
+		 * Sliders
+		 */
+		slider: function(element) {
+			var sliders = $('.slider', element);
+			if (sliders.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.slider,
+										   ams.baseURL + 'ext/bootstrap-slider-2.0.0' + ams.devext + '.js',
+										   function() {
+											   sliders.each(function() {
+												   var slider = $(this);
+												   var data = slider.data();
+												   var dataOptions = {};
+												   var settings = $.extend({}, dataOptions, slider.data.amsSliderOptions);
+												   settings = ams.executeFunctionByName(data.amsSliderInitCallback, slider, settings) || settings;
+												   var plugin = slider.slider(settings);
+												   ams.executeFunctionByName(data.amsSliderAfterInitCallback, slider, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * Draggable plug-in
+		 */
+		draggable: function(element) {
+			var draggables = $('.draggable', element);
+			if (draggables.length > 0) {
+				draggables.each(function() {
+					var draggable = $(this);
+					var data = draggable.data();
+					var dataOptions = {
+						cursor: data.amsDraggableCursor || 'move',
+						containment: data.amsDraggableContainment,
+						handle: data.amsDraggableHandle,
+						connectToSortable: data.amsDraggableConnectSortable,
+						helper: ams.getFunctionByName(data.amsDraggableHelper) || data.amsDraggableHelper,
+						start: ams.getFunctionByName(data.amsDraggableStart),
+						stop: ams.getFunctionByName(data.amsDraggableStop)
+					};
+					var settings = $.extend({}, dataOptions, data.amsDraggableOptions);
+					settings = ams.executeFunctionByName(data.amsDraggableInitCallback, draggable, settings) || settings;
+					var plugin = draggable.draggable(settings);
+					draggable.disableSelection();
+					ams.executeFunctionByName(data.amsDraggableAfterInitCallback, draggable, plugin, settings);
+				});
+			}
+		},
+
+		/**
+		 * Droppable plug-in
+		 */
+		droppable: function(element) {
+			var droppables = $('.droppable', element);
+			if (droppables.length > 0) {
+				droppables.each(function() {
+					var droppable = $(this);
+					var data = droppable.data();
+					var dataOptions = {
+						accept: data.amsdroppableAccept,
+						drop: ams.getFunctionByName(data.amsDroppableDrop)
+					};
+					var settings = $.extend({}, dataOptions, data.amsDroppableOptions);
+					settings = ams.executeFunctionByName(data.amsDroppableInitCallback, droppable, settings) || settings;
+					var plugin = droppable.droppable(settings);
+					ams.executeFunctionByName(data.amsDroppableAfterInitCallback, droppable, plugin, settings);
+				});
+			}
+		},
+
+		/**
+		 * Sortable plug-in
+		 */
+		sortable: function(element) {
+			var sortables = $('.sortable', element);
+			if (sortables.length > 0) {
+				sortables.each(function() {
+					var sortable = $(this);
+					var data = sortable.data();
+					var dataOptions = {
+						items: data.amsSortableItems,
+						handle: data.amsSortableHandle,
+						helper: data.amsSortableHelper,
+						connectWith: data.amsSortableConnectwith,
+						start: ams.getFunctionByName(data.amsSortableStart),
+						over: ams.getFunctionByName(data.amsSortableOver),
+						containment: data.amsSortableContainment,
+						placeholder: data.amsSortablePlaceholder,
+						stop: ams.getFunctionByName(data.amsSortableStop)
+					};
+					var settings = $.extend({}, dataOptions, data.amsSortableOptions);
+					settings = ams.executeFunctionByName(data.amsSortableInitCallback, sortable, settings) || settings;
+					var plugin = sortable.sortable(settings);
+					sortable.disableSelection();
+					ams.executeFunctionByName(data.amsSortableAfterInitCallback, sortable, plugin, settings);
+				});
+			}
+		},
+
+		/**
+		 * Resizable plug-in
+		 */
+		resizable: function(element) {
+			var resizables = $('.resizable', element);
+			if (resizables.length > 0) {
+				resizables.each(function() {
+					var resizable = $(this);
+					var data = resizable.data();
+					var dataOptions = {
+						autoHide: data.amsResizableAutohide === false ? true : data.amsResizableAutohide,
+						containment: data.amsResizableContainment,
+						grid: data.amsResizableGrid,
+						handles: data.amsResizableHandles,
+						start: ams.getFunctionByName(data.amsResizableStart),
+						stop: ams.getFunctionByName(data.amsResizableStop)
+					};
+					var settings = $.extend({}, dataOptions, data.amsResizableOptions);
+					settings = ams.executeFunctionByName(data.amsResizableInitCallback, resizable, settings) || settings;
+					var plugin = resizable.resizable(settings);
+					resizable.disableSelection();
+					ams.executeFunctionByName(data.amsResizableAfterInitCallback, resizable, plugin, settings);
+				});
+			}
+		},
+
+		/**
+		 * JQuery typeahead plug-in
+		 */
+		typeahead: function(element) {
+			var typeaheads = $('.typeahead', element);
+			if (typeaheads.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.typeahead,
+										   ams.baseURL + 'ext/jquery-typeahead' + ams.devext + '.js',
+										   function() {
+											   typeaheads.each(function() {
+												   var input = $(this);
+												   var data = input.data();
+												   var dataOptions = {};
+												   var settings = $.extend({}, dataOptions, data.amsTypeaheadOptions);
+												   settings = ams.executeFunctionByName(data.amsTypeaheadInitCallback, input, settings) || settings;
+												   var plugin = input.typeahead(settings);
+												   ams.executeFunctionByName(data.amsTypeaheadAfterInitCallback, input, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * Treeview plug-in
+		 */
+		treeview: function(element) {
+			var treeviews = $('.treeview', element);
+			if (treeviews.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.treview,
+										   ams.baseURL + 'ext/bootstrap-treeview' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/bootstrap-treeview' + ams.devext + '.css',
+														  'bootstrap-treeview',
+														  function() {
+															  treeviews.each(function() {
+																  var treeview = $(this);
+																  var data = treeview.data();
+																  var dataOptions = {
+																	  data: data.amsTreeviewData,
+																	  levels: data.amsTreeviewLevels,
+																	  injectStyle: data.amsTreeviewInjectStyle,
+																	  expandIcon: data.amsTreeviewExpandIcon || 'fa fa-fw fa-plus-square-o',
+																	  collapseIcon: data.amsTreeviewCollaspeIcon || 'fa fa-fw fa-minus-square-o',
+																	  emptyIcon: data.amsTreeviewEmptyIcon || 'fa fa-fw',
+																	  nodeIcon: data.amsTreeviewNodeIcon,
+																	  selectedIcon: data.amsTreeviewSelectedIcon,
+																	  checkedIcon: data.amsTreeviewCheckedIcon || 'fa fa-fw fa-check-square-o',
+																	  uncheckedIcon: data.amsTreeviewUncheckedIcon || 'fa fa-fw fa-square-o',
+																	  color: data.amsTreeviewColor,
+																	  backColor: data.amsTreeviewBackColor,
+																	  borderColor: data.amsTreeviewBorderColor,
+																	  onHoverColor: data.amsTreeviewHoverColor,
+																	  selectedColor: data.amsTreeviewSelectedColor,
+																	  selectedBackColor: data.amsTreeviewSelectedBackColor,
+																	  unselectableColor: data.amsTreeviewUnselectableColor || 'rgba(1,1,1,0.25)',
+																	  unselectableBackColor: data.amsTreeviewUnselectableBackColor || 'rgba(1,1,1,0.25)',
+																	  enableLinks: data.amsTreeviewEnableLinks,
+																	  highlightSelected: data.amsTreeviewHighlightSelected,
+																	  highlightSearchResults: data.amsTreeviewhighlightSearchResults,
+																	  showBorder: data.amsTreeviewShowBorder,
+																	  showIcon: data.amsTreeviewShowIcon,
+																	  showCheckbox: data.amsTreeviewShowCheckbox,
+																	  showTags: data.amsTreeviewShowTags,
+																	  toggleUnselectable: data.amsTreeviewToggleUnselectable,
+																	  multiSelect: data.amsTreeviewMultiSelect,
+																	  onNodeChecked: ams.getFunctionByName(data.amsTreeviewNodeChecked),
+																	  onNodeCollapsed: ams.getFunctionByName(data.amsTreeviewNodeCollapsed),
+																	  onNodeDisabled: ams.getFunctionByName(data.amsTreeviewNodeDisabled),
+																	  onNodeEnabled: ams.getFunctionByName(data.amsTreeviewNodeEnabled),
+																	  onNodeExpanded: ams.getFunctionByName(data.amsTreeviewNodeExpanded),
+																	  onNodeSelected: ams.getFunctionByName(data.amsTreeviewNodeSelected),
+																	  onNodeUnchecked: ams.getFunctionByName(data.amsTreeviewNodeUnchecked),
+																	  onNodeUnselected: ams.getFunctionByName(data.amsTreeviewNodeUnselected),
+																	  onSearchComplete: ams.getFunctionByName(data.amsTreeviewSearchComplete),
+																	  onSearchCleared: ams.getFunctionByName(data.amsTreeviewSearchCleared)
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsTreeviewOptions);
+																  settings = ams.executeFunctionByName(data.amsTreeviewInitcallback, treeview, settings) || settings;
+																  var plugin = treeview.treeview(settings);
+																  ams.executeFunctionByName(data.amsTreeviewAfterInitCallback, treeview, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * Select2 plug-in
+		 */
+		select2: function(element) {
+			var selects = $('.select2', element);
+			if (selects.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.select2,
+										   ams.baseURL + 'ext/jquery-select2-3.5.4' + ams.devext + '.js',
+										   function() {
+											   selects.each(function() {
+												   var select = $(this);
+												   var data = select.data();
+												   if (data.select2) {
+													   // Already initialized
+													   return;
+												   }
+												   var dataOptions = {
+													   placeholder: data.amsSelect2Placeholder,
+													   multiple: data.amsSelect2Multiple,
+													   minimumInputLength: data.amsSelect2MinimumInputLength || 0,
+													   maximumSelectionSize: data.amsSelect2MaximumSelectionSize,
+													   openOnEnter: data.amsSelect2EnterOpen === undefined ? true : data.amsSelect2EnterOpen,
+													   allowClear: data.amsSelect2AllowClear === undefined ? true : data.amsSelect2AllowClear,
+													   width: data.amsSelect2Width || '100%',
+													   initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
+													   formatSelection: data.amsSelect2FormatSelection === undefined
+														   ? ams.helpers && ams.helpers.select2FormatSelection
+														   : ams.getFunctionByName(data.amsSelect2FormatSelection),
+													   formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
+													   formatMatches: data.amsSelect2FormatMatches === undefined ?
+														   function(matches) {
+															   if (matches === 1) {
+																   return ams.i18n.SELECT2_MATCH;
+															   } else {
+																   return matches + ams.i18n.SELECT2_MATCHES;
+															   }
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatMatches),
+													   formatNoMatches: data.amsSelect2FormatResult === undefined ?
+														   function(term) {
+															   return ams.i18n.SELECT2_NOMATCHES;
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatResult),
+													   formatInputTooShort: data.amsSelect2FormatInputTooShort === undefined ?
+														   function(input, min) {
+															   var n = min - input.length;
+															   return ams.i18n.SELECT2_INPUT_TOOSHORT
+																   .replace(/\{0\}/, n)
+																   .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatInputTooShort),
+													   formatInputTooLong: data.amsSelect2FormatInputTooLong === undefined ?
+														   function(input, max) {
+															   var n = input.length - max;
+															   return ams.i18n.SELECT2_INPUT_TOOLONG
+																   .replace(/\{0\}/, n)
+																   .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatInputTooLong),
+													   formatSelectionTooBig: data.amsSelect2FormatSelectionTooBig === undefined ?
+														   function(limit) {
+															   return ams.i18n.SELECT2_SELECTION_TOOBIG
+																   .replace(/\{0\}/, limit)
+																   .replace(/\{1\}/, limit === 1 ? "" : ams.i18n.SELECT2_PLURAL);
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatSelectionTooBig),
+													   formatLoadMore: data.amsSelect2FormatLoadMore === undefined ?
+														   function(pageNumber) {
+															   return ams.i18n.SELECT2_LOADMORE;
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatLoadMore),
+													   formatSearching: data.amsSelect2FormatSearching === undefined ?
+														   function() {
+															   return ams.i18n.SELECT2_SEARCHING;
+														   }
+														   : ams.getFunctionByName(data.amsSelect2FormatSearching),
+													   separator: data.amsSelect2Separator || ',',
+													   tokenSeparators: data.amsSelect2TokensSeparators || [','],
+													   tokenizer: ams.getFunctionByName(data.amsSelect2Tokenizer)
+												   };
+
+												   switch (select.context.type) {
+													   case 'text':
+													   case 'hidden':
+														   if (!dataOptions.initSelection) {
+															   var valuesData = select.data('ams-select2-values');
+															   if (valuesData) {
+																   dataOptions.initSelection = function(element, callback) {
+																	   var data = [];
+																	   $(element.val().split(dataOptions.separator)).each(function() {
+																		   data.push({
+																						 id: this,
+																						 text: valuesData[this] || this
+																					 });
+																	   });
+																	   callback(data);
+																   };
+															   }
+														   }
+														   break;
+													   default:
+														   break;
+												   }
+
+												   if (select.attr('readonly')) {
+													   if (select.attr('type') === 'hidden') {
+														   dataOptions.query = function() {
+															   return [];
+														   };
+													   }
+												   } else if (data.amsSelect2Query) {
+													   // Custom query method
+													   dataOptions.query = ams.getFunctionByName(data.amsSelect2Query);
+													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
+												   } else if (data.amsSelect2QueryUrl) {
+													   // AJAX query
+													   dataOptions.ajax = {
+														   url: data.amsSelect2QueryUrl,
+														   quietMillis: data.amsSelect2QuietMillis || 200,
+														   type: data.amsSelect2QueryType || 'POST',
+														   dataType: data.amsSelect2QueryDatatype || 'json',
+														   data: function(term, page, context) {
+															   var options = {};
+															   options[data.amsSelect2QueryParamName || 'query'] = term;
+															   options[data.amsSelect2PageParamName || 'page'] = page;
+															   options[data.amsSelect2ContextParamName || 'context'] = context;
+															   return $.extend({}, options, data.amsSelect2QueryOptions);
+														   },
+														   results: ams.helpers && ams.helpers.select2QueryUrlResultsCallback
+													   };
+													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
+												   } else if (data.amsSelect2QueryMethod) {
+													   // JSON-RPC query
+													   dataOptions.query = function(options) {
+														   var settings = {
+															   id: new Date().getTime(),
+															   params: data.amsSelect2QueryParams || {},
+															   success: function(result) {
+																   return ams.helpers && ams.helpers.select2QueryMethodSuccessCallback.call(select, result, 'success', options);
+															   },
+															   error: ams.error && ams.error.show
+														   };
+														   settings.params[data.amsSelect2QueryParamName || 'query'] = options.term;
+														   settings.params[data.amsSelect2PageParamName || 'page'] = options.page;
+														   settings.params[data.amsSelect2ContextParamName || 'context'] = options.context;
+														   settings = $.extend({}, settings, data.amsSelect2QueryOptions);
+														   settings = ams.executeFunctionByName(data.amsSelect2QueryInitCallback, select, settings) || settings;
+														   ams.ajax && ams.ajax.check($.jsonRPC,
+																					  ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
+																					  function() {
+																						  $.jsonRPC.withOptions({
+																													endPoint: data.amsSelect2MethodTarget || (ams.jsonrpc && ams.jsonrpc.getAddr()),
+																													namespace: data.amsSelect2MethodNamespace,
+																													cache: false
+																												}, function() {
+																							  $.jsonRPC.request(data.amsSelect2QueryMethod, settings);
+																						  });
+																					  });
+													   };
+													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
+												   } else if (data.amsSelect2Tags) {
+													   // Tags mode
+													   dataOptions.tags = data.amsSelect2Tags;
+												   } else if (data.amsSelect2Data) {
+													   // Provided data mode
+													   dataOptions.data = data.amsSelect2Data;
+												   }
+
+												   if (data.amsSelect2EnableFreeTags) {
+													   dataOptions.createSearchChoice = function(term) {
+														   return {
+															   id: term,
+															   text: (data.amsSelect2FreeTagsPrefix || ams.i18n.SELECT2_FREETAG_PREFIX) + term
+														   };
+													   };
+												   }
+
+												   var settings = $.extend({}, dataOptions, data.amsSelect2Options);
+												   settings = ams.executeFunctionByName(data.amsSelect2InitCallback, select, settings) || settings;
+												   var plugin = select.select2(settings);
+												   ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings);
+												   if (select.hasClass('ordered')) {
+													   ams.ajax && ams.ajax.check($.fn.select2Sortable,
+																				  ams.baseURL + 'ext/jquery-select2-sortable' + ams.devext + '.js',
+																				  function() {
+																					  select.select2Sortable({
+																												 bindOrder: 'sortableStop'
+																											 });
+																				  });
+												   }
+
+												   select.on('change', function() {
+													   var validator = $(select.get(0).form).data('validator');
+													   if (validator !== undefined) {
+														   $(select).valid();
+													   }
+												   });
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * Edit mask plug-in
+		 */
+		maskedit: function(element) {
+			var masks = $('[data-mask]', element);
+			if (masks.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.mask,
+										   ams.baseURL + 'ext/jquery-maskedinput-1.4.1' + ams.devext + '.js',
+										   function() {
+											   masks.each(function() {
+												   var mask = $(this);
+												   var data = mask.data();
+												   var dataOptions = {
+													   placeholder: data.amsMaskeditPlaceholder === undefined ? 'X' : data.amsMaskeditPlaceholder,
+													   complete: ams.getFunctionByName(data.amsMaskeditComplete)
+												   };
+												   var settings = $.extend({}, dataOptions, data.amsMaskeditOptions);
+												   settings = ams.executeFunctionByName(data.amsMaskeditInitCallback, mask, settings) || settings;
+												   var plugin = mask.mask(mask.attr('data-mask'), settings);
+												   ams.executeFunctionByName(data.amsMaskeditAfterInitCallback, mask, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery input-mask plug-in
+		 *
+		 * Mask value can be set in a "data-input-mask" attribute defined:
+		 * - as a simple string containing mask
+		 * - as a JSON object defining all mask attributes, for example:
+		 *   data-input-mask='{"alias": "integer", "allowPlus": false, "allowMinus": false}'
+		 */
+		inputmask: function(element) {
+			var masks = $('input[data-input-mask]', element);
+			if (masks.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.inputmask,
+										   ams.baseURL + 'ext/jquery-inputmask-bundle-3.2.8' + ams.devext + '.js',
+										   function() {
+											   masks.each(function() {
+												   var input = $(this);
+												   var data = input.data();
+												   var dataOptions;
+												   if (typeof (data.inputMask) === 'object') {
+													   dataOptions = data.inputMask;
+												   } else {
+													   dataOptions = {
+														   mask: data.inputMask.toString()
+													   };
+												   }
+												   var settings = $.extend({}, dataOptions, data.amsInputmaskOptions);
+												   settings = ams.executeFunctionByName(data.amsInputmaskInitCallback, input, settings) || settings;
+												   var plugin = input.inputmask(settings);
+												   ams.executeFunctionByName(data.amsInputmaskAfterInitCallback, input, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery date picker
+		 */
+		datepicker: function(element) {
+			var datepickers = $('.datepicker', element);
+			if (datepickers.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.datetimepicker,
+										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
+										   function(first_load) {
+											   if (first_load) {
+												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
+											   }
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
+														  'jquery-datetimepicker',
+														  function() {
+															  datepickers.each(function() {
+																  var input = $(this);
+																  var data = input.data();
+																  var dataOptions = {
+																	  lang: data.amsDatetimepickerLang || ams.lang,
+																	  format: data.amsDatetimepickerFormat || 'd/m/y',
+																	  datepicker: true,
+																	  dayOfWeekStart: 1,
+																	  timepicker: false,
+																	  closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+																	  weeks: data.amsDatetimepickerWeeks
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
+																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
+																  var plugin = input.datetimepicker(settings);
+																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery datetime picker
+		 */
+		datetimepicker: function(element) {
+			var datetimepickers = $('.datetimepicker', element);
+			if (datetimepickers.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.datetimepicker,
+										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
+										   function(first_load) {
+											   if (first_load) {
+												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
+											   }
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
+														  'jquery-datetimepicker',
+														  function() {
+															  datetimepickers.each(function() {
+																  var input = $(this);
+																  var data = input.data();
+																  var dataOptions = {
+																	  lang: data.amsDatetimepickerLang || ams.lang,
+																	  format: data.amsDatetimepickerFormat || 'd/m/y H:i',
+																	  datepicker: true,
+																	  dayOfWeekStart: 1,
+																	  timepicker: true,
+																	  closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+																	  closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
+																	  weeks: data.amsDatetimepickerWeeks
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
+																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
+																  var plugin = input.datetimepicker(settings);
+																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery time picker
+		 */
+		timepicker: function(element) {
+			var timepickers = $('.timepicker', element);
+			if (timepickers.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.datetimepicker,
+										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
+										   function(first_load) {
+											   if (first_load) {
+												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
+											   }
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
+														  'jquery-datetimepicker',
+														  function() {
+															  timepickers.each(function() {
+																  var input = $(this);
+																  var data = input.data();
+																  var dataOptions = {
+																	  lang: data.amsDatetimepickerLang || ams.lang,
+																	  format: data.amsDatetimepickerFormat || 'H:i',
+																	  datepicker: false,
+																	  timepicker: true,
+																	  closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
+																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
+																  var plugin = input.datetimepicker(settings);
+																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery color picker
+		 */
+		colorpicker: function(element) {
+			var colorpickers = $('.colorpicker', element);
+			if (colorpickers.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.minicolors,
+										   ams.baseURL + 'ext/jquery-minicolors' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-minicolors' + ams.devext + '.css',
+														  'jquery-minicolors',
+														  function() {
+															  colorpickers.each(function() {
+																  var input = $(this);
+																  var data = input.data();
+																  var dataOptions = {
+																	  position: data.amsColorpickerPosition || input.closest('.input').data('ams-colorpicker-position') || 'bottom left'
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsColorpickerOptions);
+																  settings = ams.executeFunctionByName(data.amsColorpickerInitCallback, input, settings) || settings;
+																  var plugin = input.minicolors(settings);
+																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * Drag & drop upload plug-in
+		 */
+		dndupload: function(element) {
+			var uploads = $('.dndupload', element);
+			if (uploads.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.dndupload,
+										   ams.baseURL + 'ext/jquery-dndupload' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-dndupload' + ams.devext + '.css',
+														  'jquery-dndupload',
+														  function() {
+															  uploads.each(function() {
+																  var upload = $(this);
+																  var data = upload.data();
+																  var dataOptions = {
+																	  action: data.amsDnduploadAction || upload.attr('action') || 'upload-files',
+																	  fieldname: data.amsDnduploadFieldname || 'files',
+																	  autosubmit: data.amsDnduploadAutosubmit
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsDnduploadOptions);
+																  settings = ams.executeFunctionByName(data.amsDnduploadInitCallback, upload, settings) || settings;
+																  var plugin = upload.dndupload(settings);
+																  ams.executeFunctionByName(data.amsDnduploadAfterInitcallback, upload, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery validation plug-in
+		 */
+		validate: function(element) {
+			var forms = $('FORM:not([novalidate])', element);
+			if (forms.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.validate,
+										   ams.baseURL + 'ext/jquery-validate-1.17.0' + ams.devext + '.js',
+										   function(first_load) {
+											   if (first_load) {
+												   $.validator.setDefaults({
+																			   highlight: function(element) {
+																				   $(element).closest('.form-group, label:not(:parents(.form-group))')
+																							 .addClass('state-error');
+																			   },
+																			   unhighlight: function(element) {
+																				   $(element).closest('.form-group, label:not(:parents(.form-group))')
+																							 .removeClass('state-error');
+																			   },
+																			   errorElement: 'span',
+																			   errorClass: 'state-error',
+																			   errorPlacement: function(error, element) {
+																				   var label = element.parents('label, .input').first();
+																				   if (label.length) {
+																					   error.insertAfter(label);
+																				   } else {
+																					   error.insertAfter(element);
+																				   }
+																			   }
+																		   });
+												   if (ams.plugins && ams.plugins.i18n) {
+													   for (var key in ams.plugins.i18n.validate) {
+														   if (!ams.plugins.i18n.validate.hasOwnProperty(key)) {
+															   continue;
+														   }
+														   var message = ams.plugins.i18n.validate[key];
+														   if ((typeof (message) === 'string') &&
+															   (message.indexOf('{0}') > -1)) {
+															   ams.plugins.i18n.validate[key] = $.validator.format(message);
+														   }
+													   }
+													   $.extend($.validator.messages, ams.plugins.i18n.validate);
+												   }
+											   }
+											   forms.each(function() {
+												   var form = $(this);
+												   var data = form.data();
+												   var dataOptions = {
+													   ignore: null,
+													   submitHandler: form.attr('data-async') !== undefined ?
+														   data.amsFormSubmitHandler === undefined ?
+															   function() {
+																   // JQuery-form plug-in must be loaded synchronously!!
+																   // Otherwise, hidden input fields created by jquery-validate plug-in
+																   // and matching named buttons will be deleted (on first form submit)
+																   // before JQuery-form plug-in can get them when submitting the form...
+																   $('.state-error', form).removeClass('state-error');
+																   ams.ajax && ams.ajax.check($.fn.ajaxSubmit,
+																							  ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js');
+																   return ams.form && ams.form.submit(form);
+															   }
+															   : ams.getFunctionByName(data.amsFormSubmitHandler)
+														   : undefined,
+													   invalidHandler: data.amsFormInvalidHandler === undefined ?
+															   function(event, validator) {
+																   $('.state-error', form).removeClass('state-error');
+																   for (var index = 0; index < validator.errorList.length; index++) {
+																	   var error = validator.errorList[index];
+																	   var tabIndex = $(error.element).parents('.tab-pane').index() + 1;
+																	   if (tabIndex > 0) {
+																		   var navTabs = $('.nav-tabs', $(error.element).parents('.tabforms'));
+																		   $('li:nth-child(' + tabIndex + ')', navTabs)
+																			   .removeClassPrefix('state-')
+																			   .addClass('state-error');
+																		   $('li.state-error:first a', navTabs).click();
+																	   }
+																   }
+															   }
+															   : ams.getFunctionByName(data.amsFormInvalidHandler)
+												   };
+												   $('[data-ams-validate-rules]', form).each(function(index) {
+													   if (index === 0) {
+														   dataOptions.rules = {};
+													   }
+													   dataOptions.rules[$(this).attr('name')] = $(this).data('ams-validate-rules');
+												   });
+												   $('[data-ams-validate-messages]', form).each(function(index) {
+													   if (index === 0) {
+													   		dataOptions.messages = {};
+													   }
+													   dataOptions.messages[$(this).attr('name')] = $(this).data('ams-validate-messages');
+												   });
+												   var settings = $.extend({}, dataOptions, data.amsValidateOptions);
+												   settings = ams.executeFunctionByName(data.amsValidateInitCallback, form, settings) || settings;
+												   var plugin = form.validate(settings);
+												   ams.executeFunctionByName(data.amsValidateAfterInitCallback, form, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * JQuery dataTables
+		 */
+		datatable: function(element) {
+			var tables = $('.datatable', element);
+			if (tables.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.dataTable,
+										   ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js',
+										   function() {
+											   ams.ajax.check($.fn.dataTableExt.oPagination.bootstrap_full,
+															  ams.baseURL + 'myams-dataTables' + ams.devext + '.js',
+															  function() {
+																  $(tables).each(function() {
+																	  var table = $(this);
+																	  var data = table.data();
+																	  var extensions = (data.amsDatatableExtensions || '').split(/\s+/);
+																	  // Check DOM elements
+																	  var sDom = data.amsDatatableSdom ||
+																		  "W" +
+																		  ((extensions.indexOf('colreorder') >= 0 ||
+																			  extensions.indexOf('colreorderwithresize') >= 0) ? 'R' : '') +
+																		  "<'dt-top-row'" +
+																		  (extensions.indexOf('colvis') >= 0 ? 'C' : '') +
+																		  ((data.amsDatatablePagination === false ||
+																			  data.amsDatatablePaginationSize === false) ? '' : 'L') +
+																		  (data.amsDatatableGlobalFilter === false ? '' : 'F') +
+																		  ">r<'dt-wrapper't" +
+																		  (extensions.indexOf('scroller') >= 0 ? 'S' : '') +
+																		  "><'dt-row dt-bottom-row'<'row'<'col-sm-6'" +
+																		  (data.amsDatatableInformation === false ? '' : 'i') +
+																		  "><'col-sm-6 text-right'p>>";
+
+																	  var index;
+																	  // Check initial sorting
+																	  var sorting = data.amsDatatableSorting;
+																	  if (typeof (sorting) === 'string') {
+																		  var sortings = sorting.split(';');
+																		  sorting = [];
+																		  for (index = 0; index < sortings.length; index++) {
+																			  var colSorting = sortings[index].split(',');
+																			  colSorting[0] = parseInt(colSorting[0]);
+																			  sorting.push(colSorting);
+																		  }
+																	  }
+																	  // Check columns sortings
+																	  var columns = [];
+																	  var column;
+																	  var sortables = $('th', table).listattr('data-ams-datatable-sortable');
+																	  for (index = 0; index < sortables.length; index++) {
+																		  var sortable = sortables[index];
+																		  if (sortable !== undefined) {
+																			  column = columns[index] || {};
+																			  column.bSortable = typeof (sortable) === 'string' ? JSON.parse(sortable) : sortable;
+																			  columns[index] = column;
+																		  } else {
+																			  columns[index] = columns[index] || {};
+																		  }
+																	  }
+																	  // Check columns types
+																	  var sortTypes = $('th', table).listattr('data-ams-datatable-stype');
+																	  for (index = 0; index < sortTypes.length; index++) {
+																		  var sortType = sortTypes[index];
+																		  if (sortType) {
+																			  column = columns[index] || {};
+																			  column.sType = sortType;
+																			  columns[index] = column;
+																		  } else {
+																			  columns[index] = columns[index] || {};
+																		  }
+																	  }
+																	  // Set options
+																	  var dataOptions = {
+																		  bJQueryUI: false,
+																		  bServerSide: data.amsDatatableServerSide || false,
+																		  sAjaxSource: data.amsDatatableServerSide === true ? data.amsDatatableAjaxSource : undefined,
+																		  sServerMethod: data.amsDatatableServerSide === true ? 'POST' : undefined,
+																		  bFilter: data.amsDatatableGlobalFilter !== false || extensions.indexOf('columnfilter') >= 0,
+																		  bPaginate: data.amsDatatablePagination !== false,
+																		  bInfo: data.amsDatatableInfo !== false,
+																		  bSort: data.amsDatatableSort !== false,
+																		  aaSorting: sorting,
+																		  aoColumns: columns.length > 0 ? columns : undefined,
+																		  bDeferRender: true,
+																		  bAutoWidth: false,
+																		  iDisplayLength: data.amsDatatableDisplayLength || 25,
+																		  sPaginationType: data.amsDatatablePaginationType || 'bootstrap_full',
+																		  sDom: sDom,
+																		  oLanguage: ams.plugins && ams.plugins.i18n.datatables,
+																		  fnInitComplete: function(oSettings, json) {
+																			  $('.ColVis_Button').addClass('btn btn-default btn-sm')
+																				  .html(((ams.plugins && ams.plugins.i18n.datatables.sColumns) || "Columns") +
+																							' <i class="fa fa-fw fa-caret-down"></i>');
+																		  }
+																	  };
+																	  var settings = $.extend({}, dataOptions, data.amsDatatableOptions);
+																	  var checkers = [];
+																	  var sources = [];
+																	  var callbacks = [];
+																	  if (extensions.length > 0) {
+																		  for (index = 0; index < extensions.length; index++) {
+																			  switch (extensions[index]) {
+																				  case 'autofill':
+																					  checkers.push($.fn.dataTable.AutoFill);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-autoFill' + ams.devext + '.js');
+																					  break;
+																				  case 'columnfilter':
+																					  checkers.push($.fn.columnFilter);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-columnFilter' + ams.devext + '.js');
+																					  break;
+																				  case 'colreorder':
+																					  checkers.push($.fn.dataTable.ColReorder);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorder' + ams.devext + '.js');
+																					  break;
+																				  case 'colreorderwithresize':
+																					  checkers.push(window.ColReorder);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorderWithResize' + ams.devext + '.js');
+																					  break;
+																				  case 'colvis':
+																					  checkers.push($.fn.dataTable.ColVis);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colVis' + ams.devext + '.js');
+																					  callbacks.push(function() {
+																						  var cvDefault = {
+																							  activate: 'click',
+																							  sAlign: 'right'
+																						  };
+																						  settings.oColVis = $.extend({}, cvDefault, data.amsDatatableColvisOptions);
+																					  });
+																					  break;
+																				  case 'editable':
+																					  checkers.push($.fn.editable);
+																					  sources.push(ams.baseURL + 'ext/jquery-jeditable' + ams.devext + '.js');
+																					  checkers.push($.fn.makeEditable);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-editable' + ams.devext + '.js');
+																					  break;
+																				  case 'fixedcolumns':
+																					  checkers.push($.fn.dataTable.FixedColumns);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedColumns' + ams.devext + '.js');
+																					  break;
+																				  case 'fixedheader':
+																					  checkers.push($.fn.dataTable.Fixedheader);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedHeader' + ams.devext + '.js');
+																					  break;
+																				  case 'keytable':
+																					  checkers.push(window.keyTable);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-keyTable' + ams.devext + '.js');
+																					  break;
+																				  case 'rowgrouping':
+																					  checkers.push($.fn.rowGrouping);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-rowGrouping' + ams.devext + '.js');
+																					  break;
+																				  case 'rowreordering':
+																					  checkers.push($.fn.rowReordering);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-rowReordering' + ams.devext + '.js');
+																					  break;
+																				  case 'scroller':
+																					  checkers.push($.fn.dataTable.Scroller);
+																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-scroller' + ams.devext + '.js');
+																					  break;
+																				  default:
+																					  break;
+																			  }
+																		  }
+																	  }
+
+																	  function initTable() {
+																		  settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
+																		  try {  // Some settings can easily generate DataTables exceptions...
+																			  var plugin = table.dataTable(settings);
+																			  ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
+																			  if (extensions.length > 0) {
+																				  for (index = 0; index < extensions.length; index++) {
+																					  switch (extensions[index]) {
+																						  case 'autofill':
+																							  var afSettings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
+																							  afSettings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, afSettings) || afSettings;
+																							  table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined ?
+																								  new $.fn.dataTable.AutoFill(table, afSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, afSettings));
+																							  break;
+																						  case 'columnfilter':
+																							  var cfDefault = {
+																								  sPlaceHolder: 'head:after'
+																							  };
+																							  var cfSettings = $.extend({}, cfDefault, data.amsDatatableColumnfilterOptions, settings.columnfilter);
+																							  cfSettings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cfSettings) || cfSettings;
+																							  table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined ?
+																								  plugin.columnFilter(cfSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cfSettings));
+																							  break;
+																						  case 'editable':
+																							  var edSettings = $.extend({}, data.amsDatatableEditableOptions, settings.editable);
+																							  edSettings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, edSettings) || edSettings;
+																							  table.data('ams-editable', data.amsDatatableEditableConstructor === undefined ?
+																								  table.makeEditable(edSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, edSettings));
+																							  break;
+																						  case 'fixedcolumns':
+																							  var fcSettings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns);
+																							  fcSettings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fcSettings) || fcSettings;
+																							  table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined ?
+																								  new $.fn.dataTable.FixedColumns(table, fcSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fcSettings));
+																							  break;
+																						  case 'fixedheader':
+																							  var fhSettings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader);
+																							  fhSettings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fhSettings) || fhSettings;
+																							  table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined ?
+																								  new $.fn.dataTable.FixedHeader(table, fhSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fhSettings));
+																							  break;
+																						  case 'keytable':
+																							  var ktDefault = {
+																								  table: table.get(0),
+																								  datatable: plugin
+																							  };
+																							  var ktSettings = $.extend({}, ktDefault, data.amsDatatableKeytableOptions, settings.keytable);
+																							  ktSettings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, ktSettings) || ktSettings;
+																							  table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined ?
+																								  new KeyTable(ktSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, ktSettings));
+																							  break;
+																						  case 'rowgrouping':
+																							  var rgSettings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping);
+																							  rgSettings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rgSettings) || rgSettings;
+																							  table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined ?
+																								  table.rowGrouping(rgSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rgSettings));
+																							  break;
+																						  case 'rowreordering':
+																							  var rrSettings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering);
+																							  rrSettings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rrSettings) || rrSettings;
+																							  table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined ?
+																								  table.rowReordering(rrSettings)
+																								  : ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rrSettings));
+																							  break;
+																						  default:
+																							  break;
+																					  }
+																				  }
+																			  }
+																			  if (data.amsDatatableFinalizeCallback) {
+																				  var finalizers = data.amsDatatableFinalizeCallback.split(/\s+/);
+																				  if (finalizers.length > 0) {
+																					  for (index = 0; index < finalizers.length; index++) {
+																						  ams.executeFunctionByName(finalizers[index], table, plugin, settings);
+																					  }
+																				  }
+																			  }
+																		  } catch (e) {
+																		  }
+																	  }
+
+																	  callbacks.push(initTable);
+																	  ams.ajax && ams.ajax.check(checkers, sources, callbacks);
+																  });
+															  });
+										   });
+			}
+		},
+
+		/**
+		 * TableDND plug-in
+		 */
+		tablednd: function(element) {
+			var tables = $('.table-dnd', element);
+			if (tables.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.tableDnD,
+										   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
+										   function() {
+											   tables.each(function() {
+												   var table = $(this);
+												   var data = table.data();
+												   if (data.amsTabledndDragHandle) {
+													   $('tr', table).addClass('no-drag-handle');
+												   } else {
+													   $(table).on('mouseover', 'tr', function() {
+														   $(this.cells[0]).addClass('drag-handle');
+													   }).on('mouseout', 'tr', function() {
+														   $(this.cells[0]).removeClass('drag-handle');
+													   });
+												   }
+												   var dataOptions = {
+													   onDragClass: data.amsTabledndDragClass || 'dragging-row',
+													   onDragStart: ams.getFunctionByName(data.amsTabledndDragStart),
+													   dragHandle: data.amsTabledndDragHandle,
+													   scrollAmount: data.amsTabledndScrollAmount,
+													   onAllowDrop: data.amsTabledndAllowDrop,
+													   onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) {
+														   var target = data.amsTabledndDropTarget;
+														   if (target) {
+															   // Disable row click handler
+															   $(row).data('ams-disabled-handlers', 'click');
+															   try {
+																   var rows = [];
+																   $(dnd_table.rows).each(function() {
+																	   var rowId = $(this).data('ams-element-name');
+																	   if (rowId) {
+																		   rows.push(rowId);
+																	   }
+																   });
+																   var localTarget = ams.getFunctionByName(target);
+																   if (typeof (localTarget) === 'function') {
+																	   localTarget.call(table, dnd_table, rows);
+																   } else {
+																	   if (!target.startsWith(window.location.protocol)) {
+																		   var location = data.amsLocation;
+																		   if (location) {
+																			   target = location + '/' + target;
+																		   }
+																	   }
+																	   ams.ajax && ams.ajax.post(target, {names: JSON.stringify(rows)}, function(result, status) {
+																		   if (result.status !== 'success') {
+																			   ams.ajax.handleJSON(result);
+																		   }
+																	   });
+																   }
+															   } finally {
+																   // Restore row click handler
+																   setTimeout(function() {
+																	   $(row).removeData('ams-disabled-handlers');
+																   }, 50);
+															   }
+														   }
+														   return false;
+													   }
+												   };
+												   var settings = $.extend({}, dataOptions, data.amsTabledndOptions);
+												   settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings;
+												   var plugin = table.tableDnD(settings);
+												   ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * Wizard plug-in
+		 */
+		wizard: function(element) {
+			var wizards = $('.wizard', element);
+			if (wizards.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.bootstrapWizard,
+										   ams.baseURL + 'ext/bootstrap-wizard-1.4.2' + ams.devext + '.js',
+										   function() {
+											   wizards.each(function() {
+												   var wizard = $(this);
+												   var data = wizard.data();
+												   var dataOptions = {
+													   withVisible: data.amsWizardWithVisible === undefined ? true : data.amsWizardWithVisible,
+													   tabClass: data.amsWizardTabClass,
+													   firstSelector: data.amsWizardFirstSelector,
+													   previousSelector: data.amsWizardPreviousSelector,
+													   nextSelector: data.amsWizardNextSelector,
+													   lastSelector: data.amsWizardLastSelector,
+													   finishSelector: data.amsWizardFinishSelector,
+													   backSelector: data.amsWizardBackSelector,
+													   onInit: ams.getFunctionByName(data.amsWizardInit),
+													   onShow: ams.getFunctionByName(data.amsWizardShow),
+													   onNext: ams.getFunctionByName(data.amsWizardNext),
+													   onPrevious: ams.getFunctionByName(data.amsWizardPrevious),
+													   onFirst: ams.getFunctionByName(data.amsWizardFirst),
+													   onLast: ams.getFunctionByName(data.amsWizardLast),
+													   onBack: ams.getFunctionByName(data.amsWizardBack),
+													   onFinish: ams.getFunctionByName(data.amsWizardFinish),
+													   onTabChange: ams.getFunctionByName(data.amsWizardTabChange),
+													   onTabClick: ams.getFunctionByName(data.amsWizardTabClick),
+													   onTabShow: ams.getFunctionByName(data.amsWizardTabShow)
+												   };
+												   var settings = $.extend({}, dataOptions, data.amsWizardOptions);
+												   settings = ams.executeFunctionByName(data.amsWizardInitCallback, wizard, settings) || settings;
+												   var plugin = wizard.bootstrapWizard(settings);
+												   ams.executeFunctionByName(data.amsWizardAfterInitCallback, wizard, plugin, settings);
+											   });
+										   });
+			}
+		},
+
+		/**
+		 * TinyMCE plug-in
+		 */
+		tinymce: function(element) {
+
+			function cleanEditors() {
+				$('.tinymce', $(this)).each(function() {
+					var editor = tinymce.get($(this).attr('id'));
+					if (editor) {
+						editor.remove();
+					}
+				});
+			}
+
+			var editors = $('.tinymce', element);
+			if (editors.length > 0) {
+				var baseURL = ams.baseURL + 'ext/tinymce' + (ams.devmode ? '/dev' : '');
+				ams.ajax && ams.ajax.check(window.tinymce,
+										   baseURL + '/tinymce' + ams.devext + '.js',
+										   function(first_load) {
+
+											   function initEditors() {
+												   editors.each(function() {
+													   var editor = $(this);
+													   var data = editor.data();
+													   var dataOptions = {
+														   theme: data.amsTinymceTheme || "modern",
+														   language: ams.lang,
+														   menubar: data.amsTinymceMenubar !== false,
+														   statusbar: data.amsTinymceStatusbar !== false,
+														   plugins: data.amsTinymcePlugins || [
+															   "advlist autosave autolink lists link charmap print preview hr anchor pagebreak",
+															   "searchreplace wordcount visualblocks visualchars code fullscreen",
+															   "insertdatetime nonbreaking save table contextmenu directionality",
+															   "emoticons paste textcolor colorpicker textpattern autoresize"
+														   ],
+														   toolbar: data.amsTinymceToolbar,
+														   toolbar1: data.amsTinymceToolbar1 === false ? false : data.amsTinymceToolbar1 ||
+															   "undo redo | pastetext | styleselect | bold italic | alignleft " +
+															   "aligncenter alignright alignjustify | bullist numlist " +
+															   "outdent indent",
+														   toolbar2: data.amsTinymceToolbar2 === false ? false : data.amsTinymceToolbar2 ||
+															   "forecolor backcolor emoticons | charmap link image media | " +
+															   "fullscreen preview print | code",
+														   content_css: data.amsTinymceContentCss,
+														   formats: data.amsTinymceFormats,
+														   style_formats: data.amsTinymceStyleFormats,
+														   block_formats: data.amsTinymceBlockFormats,
+														   valid_classes: data.amsTinymceValidClasses,
+														   image_advtab: true,
+														   image_list: ams.getFunctionByName(data.amsTinymceImageList) || data.amsTinymceImageList,
+														   image_class_list: data.amsTinymceImageClassList,
+														   link_list: ams.getFunctionByName(data.amsTinymceLinkList) || data.amsTinymceLinkList,
+														   link_class_list: data.amsTinymceLinkClassList,
+														   paste_as_text: data.amsTinymcePasteAsText === undefined ? true : data.amsTinymcePasteAsText,
+														   paste_auto_cleanup_on_paste: data.amsTinymcePasteAutoCleanup === undefined ? true : data.amsTinymcePasteAutoCleanup,
+														   paste_strip_class_attributes: data.amsTinymcePasteStripClassAttributes || 'all',
+														   paste_remove_spans: data.amsTinymcePaseRemoveSpans === undefined ? true : data.amsTinymcePasteRemoveSpans,
+														   paste_remove_styles: data.amsTinymcePasteRemoveStyles === undefined ? true : data.amsTinymcePasteRemoveStyles,
+														   height: data.amsTinymceHeight || 50,
+														   min_height: 50,
+														   resize: true,
+														   autoresize_min_height: 50,
+														   autoresize_max_height: 500
+													   };
+													   if (data.amsTinymceExternalPlugins) {
+														   var names = data.amsTinymceExternalPlugins.split(/\s+/);
+														   for (var index in names) {
+															   if (!names.hasOwnProperty(index)) {
+																   continue;
+															   }
+															   var pluginSrc = editor.data('ams-tinymce-plugin-' + names[index]);
+															   tinymce.PluginManager.load(names[index], ams.getSource(pluginSrc));
+														   }
+													   }
+													   var settings = $.extend({}, dataOptions, data.amsTinymceOptions);
+													   settings = ams.executeFunctionByName(data.amsTinymceInitCallback, editor, settings) || settings;
+													   var plugin = editor.tinymce(settings);
+													   ams.executeFunctionByName(data.amsTinymceAfterInitCallback, editor, plugin, settings);
+												   });
+											   }
+
+											   if (first_load) {
+												   ams.getScript(baseURL + '/jquery.tinymce' + ams.devext + '.js', function() {
+													   tinymce.baseURL = baseURL;
+													   tinymce.suffix = ams.devext;
+													   ams.skin && ams.skin.registerCleanCallback(cleanEditors);
+													   initEditors();
+												   });
+											   } else {
+												   initEditors();
+											   }
+										   });
+			}
+		},
+
+		/**
+		 * HTML editor with syntax highlight
+		 */
+		editor: function(element) {
+			var editors = $('.text-editor textarea', element);
+			if (editors.length > 0) {
+				ams.ajax && ams.ajax.check(globals.ace,
+										   ams.baseURL + 'ext/ace/ace.js',
+										   function(first_load) {
+
+												var initEditors = function() {
+													globals.ace_loaded = true;
+													editors.each(function() {
+
+														// Find textarea attributes
+														var textarea = $(this),
+															widget = textarea.parents('.text-editor'),
+															data = widget.data(),
+															modeList = ace.require('ace/ext/modelist'),
+															mode = data.amsEditorMode || modeList.getModeForPath(data.amsEditorFilename || 'editor.txt').mode;
+
+														// Create editor DIV
+														var textEditor = $('<div>', {
+															position: 'absolute',
+															width: textarea.width(),
+															height: textarea.height(),
+															'class': textarea.attr('class')
+														}).insertBefore(textarea);
+														textarea.css('display', 'none');
+
+														// Initialize editor
+														var editor = ace.edit(textEditor[0]),
+															dataOptions = {
+																mode: mode,
+																tabSize: 4,
+																useSoftTabs: false,
+																showGutter: true,
+																showLineNumbers: true,
+																printMargin: 132,
+																showInvisibles: true
+															},
+															settings = $.extend({}, dataOptions, data.amsEditorOptions);
+														settings = ams.executeFunctionByName(data.amsEditorInitCallback, textarea, settings) || settings;
+														editor.setOptions(settings);
+														editor.session.setValue(textarea.val());
+														editor.session.on('change', function() {
+															textarea.val(editor.session.getValue());
+														});
+														widget.data('editor', editor);
+														ams.executeFunctionByName(data.amsEditorAfterInitCallback, textarea, editor, settings);
+													});
+												};
+
+												if (first_load) {
+													ace.config.set('basePath', ams.baseURL + 'ext/ace');
+													ams.ajax.check(globals.ace_loaded, [
+														ams.baseURL + 'ext/ace/ext-modelist.js'
+													], initEditors);
+												} else {
+													initEditors();
+												}
+										   });
+			}
+		},
+
+		/**
+		 * Image area select plug-in
+		 */
+		imgareaselect: function(element) {
+			var images = $('.imgareaselect', element);
+			if (images.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.imgAreaSelect,
+										   ams.baseURL + 'ext/jquery-imgareaselect-0.9.11-rc1' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + ams.devext + '.css',
+														  'jquery-imgareaselect',
+														  function() {
+															  images.each(function() {
+																  var image = $(this);
+																  var data = image.data();
+																  var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body';
+																  var dataOptions = {
+																	  instance: true,
+																	  handles: true,
+																	  parent: parent,
+																	  x1: data.amsImgareaselectX1 || 0,
+																	  y1: data.amsImgareaselectY1 || 0,
+																	  x2: data.amsImgareaselectX2 || data.amsImgareaselectImageWidth,
+																	  y2: data.amsImgareaselectY2 || data.amsImgareaselectImageHeight,
+																	  imageWidth: data.amsImgareaselectImageWidth,
+																	  imageHeight: data.amsImgareaselectImageHeight,
+																	  minWidth: 128,
+																	  minHeight: 128,
+																	  aspectRatio: data.amsImgareaselectRatio,
+																	  onSelectEnd: ams.getFunctionByName(data.amsImgareaselectSelectEnd) || function(img, selection) {
+																		  var target = data.amsImgareaselectTargetField || 'image_';
+																		  $('input[name="' + target + 'x1"]', parent).val(selection.x1);
+																		  $('input[name="' + target + 'y1"]', parent).val(selection.y1);
+																		  $('input[name="' + target + 'x2"]', parent).val(selection.x2);
+																		  $('input[name="' + target + 'y2"]', parent).val(selection.y2);
+																	  }
+																  };
+																  var settings = $.extend({}, dataOptions, data.amsImgareaselectOptions);
+																  settings = ams.executeFunctionByName(data.amsImgareaselectInitCallback, image, settings) || settings;
+																  var plugin = image.imgAreaSelect(settings);
+																  ams.executeFunctionByName(data.amsImgareaselectAfterInitCallback, image, plugin, settings);
+																  // Add update timeout when plug-in is displayed into a modal dialog
+																  setTimeout(function() {
+																	  plugin.update();
+																  }, 250);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * FancyBox plug-in
+		 */
+		fancybox: function(element) {
+			var fancyboxes = $('.fancybox', element);
+			if (fancyboxes.length > 0) {
+				ams.ajax && ams.ajax.check($.fn.fancybox,
+										   ams.baseURL + 'ext/jquery-fancybox-2.1.5' + ams.devext + '.js',
+										   function() {
+											   ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + ams.devext + '.css',
+														  'jquery-fancybox',
+														  function() {
+															  fancyboxes.each(function() {
+																  var fancybox = $(this);
+																  var data = fancybox.data();
+																  var elements = fancybox;
+																  var index,
+																	  helper;
+																  if (data.amsFancyboxElements) {
+																	  elements = $(data.amsFancyboxElements, fancybox);
+																  }
+																  var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
+																  if (helpers.length > 0) {
+																	  for (index = 0; index < helpers.length; index++) {
+																		  helper = helpers[index];
+																		  switch (helper) {
+																			  case 'buttons':
+																				  ams.ajax && ams.ajax.check($.fancybox.helpers.buttons,
+																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons' + ams.devext + '.js');
+																				  break;
+																			  case 'thumbs':
+																				  ams.ajax && ams.ajax.check($.fancybox.helpers.thumbs,
+																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-thumbs' + ams.devext + '.js');
+																				  break;
+																			  case 'media':
+																				  ams.ajax && ams.ajax.check($.fancybox.helpers.media,
+																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-media' + ams.devext + '.js');
+																				  break;
+																			  default:
+																				  break;
+																		  }
+																	  }
+																  }
+																  var dataOptions = {
+																	  type: data.amsFancyboxType,
+																	  padding: data.amsFancyboxPadding || 10,
+																	  margin: data.amsFancyboxMargin || 10,
+																	  loop: data.amsFancyboxLoop,
+																	  beforeLoad: ams.getFunctionByName(data.amsFancyboxBeforeLoad) || function() {
+																		  var title;
+																		  if (data.amsFancyboxTitleGetter) {
+																			  title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this);
+																		  }
+																		  if (!title) {
+																			  var content = $('*:first', this.element);
+																			  title = content.attr('original-title') || content.attr('title');
+																			  if (!title) {
+																				  title = $(this.element).attr('original-title') || $(this.element).attr('title');
+																			  }
+																		  }
+																		  this.title = title;
+																	  },
+																	  afterLoad: ams.getFunctionByName(data.amsFancyboxAfterLoad),
+																	  helpers: {
+																		  title: {
+																			  type: 'inside'
+																		  }
+																	  }
+																  };
+																  if (helpers.length > 0) {
+																	  for (index = 0; index < helpers.length; index++) {
+																		  helper = helpers[index];
+																		  switch (helper) {
+																			  case 'buttons':
+																				  dataOptions.helpers.buttons = {
+																					  position: data.amsFancyboxButtonsPosition || 'top'
+																				  };
+																				  break;
+																			  case 'thumbs':
+																				  dataOptions.helpers.thumbs = {
+																					  width: data.amsFancyboxThumbsWidth || 50,
+																					  height: data.amsFancyboxThumbsHeight || 50
+																				  };
+																				  break;
+																			  case 'media':
+																				  dataOptions.helpers.media = true;
+																				  break;
+																		  }
+																	  }
+																  }
+																  var settings = $.extend({}, dataOptions, data.amsFancyboxOptions);
+																  settings = ams.executeFunctionByName(data.amsFancyboxInitCallback, fancybox, settings) || settings;
+																  var plugin = elements.fancybox(settings);
+																  ams.executeFunctionByName(data.amsFancyboxAfterInitCallback, fancybox, plugin, settings);
+															  });
+														  });
+										   });
+			}
+		},
+
+		/**
+		 * Flot charts
+		 */
+		chart: function(element) {
+			var charts = $('.chart', element);
+			if (charts.length > 0) {
+				ams.ajax && ams.ajax.check([window.Flot, $.color],
+					[ams.baseURL + 'ext/flot/jquery.canvaswrapper' + ams.devext + '.js',
+					 ams.baseURL + 'ext/flot/jquery.colorhelpers' + ams.devext + '.js'],
+					function () {
+						ams.ajax.check($.fn.plot,
+							ams.baseURL + 'ext/flot/jquery.flot' + ams.devext + '.js',
+							function () {
+								charts.each(function () {
+
+									var chart = $(this),
+										data = chart.data(),
+										dataOptions = {},
+										plugin,
+										flotPlugins = (data.amsChartPlugins || '').split(/\s+/);
+
+									function checkPlugin(plugin) {
+										for (var index in $.plot.plugins) {
+											if ($.plot.plugins.hasOwnProperty(index)) {
+												var pluginInfo = $.plot.plugins[index];
+												if (pluginInfo.name === plugin) {
+													return pluginInfo;
+												}
+											}
+										}
+										return null;
+									}
+
+									function initChart() {
+										var settings = $.extend({}, dataOptions, data.amsChartOptions);
+										settings = ams.executeFunctionByName(data.amsChartInitCallback, chart, settings) || settings;
+										var chartData = data.amsChartData,
+											chartDataLoader = data.amsChartDataLoader;
+										if (chartDataLoader) {
+											$.getJSON(chartDataLoader, chartData).done(function (data) {
+												settings = $.extend({}, settings, data.settings);
+												createChart(data.data, settings);
+											});
+										} else {
+											createChart(data, settings);
+										}
+									}
+
+									function createChart(chartData, settings) {
+										chartData = ams.executeFunctionByName(data.amsChartInitData, chart, chartData) || chartData;
+										plugin = chart.plot(chartData, settings);
+										ams.executeFunctionByName(data.amsChartAfterInitCallback, chart, plugin, settings);
+									}
+
+									var deferred = [];
+									if (flotPlugins.length > 0) {
+										for (var index in flotPlugins) {
+											if (flotPlugins.hasOwnProperty(index)) {
+												var pluginName = flotPlugins[index];
+												if (!checkPlugin(pluginName)) {
+													deferred.push(ams.getScript(ams.baseURL + 'ext/flot/jquery.flot.' + pluginName + ams.devext + '.js'));
+												}
+											}
+										}
+									}
+									if (deferred.length > 0) {
+										$.when.apply($, deferred).then(function () {
+											initChart();
+										})
+									} else {
+										initChart();
+									}
+								});
+							});
+					});
+			}
+		},
+
+		/**
+		 * Sparkline graphs
+		 */
+		graphs: function(element) {
+			var graphs = $('.sparkline', element);
+			if (graphs.length > 0) {
+				ams.ajax && ams.ajax.check(ams.graphs,
+										   ams.baseURL + 'myams-graphs' + ams.devext + '.js',
+										   function() {
+											   ams.graphs.init(graphs);
+										   });
+			}
+		},
+
+		/**
+		 * Custom scrollbars
+		 */
+		scrollbars: function(element) {
+			var scrollbars = $('.scrollbar', element);
+			if (scrollbars.length > 0) {
+				ams.ajax && ams.ajax.check($.event.special.mousewheel,
+										   ams.baseURL + 'ext/jquery-mousewheel.min.js',
+										   function() {
+											   ams.ajax.check($.fn.mCustomScrollbar,
+															  ams.baseURL + 'ext/jquery-mCustomScrollbar' + ams.devext + '.js',
+															  function() {
+																  ams.getCSS(ams.baseURL + '../css/ext/jquery-mCustomScrollbar.css',
+																			 'jquery-mCustomScrollbar',
+																			 function() {
+																				 scrollbars.each(function() {
+																					 var scrollbar = $(this);
+																					 var data = scrollbar.data();
+																					 var dataOptions = {
+																						 theme: data.amsScrollbarTheme || 'light'
+																					 };
+																					 var settings = $.extend({}, dataOptions, data.amsScrollbarOptions);
+																					 settings = ams.executeFunctionByName(data.amsScrollbarInitCallback, scrollbar, settings) || settings;
+																					 var plugin = scrollbar.mCustomScrollbar(settings);
+																					 ams.executeFunctionByName(data.amsScrollbarAfterInitCallback, scrollbar, plugin, settings);
+																				 });
+																			 });
+															  });
+										   });
+			}
+		}
+	});
+
+})(jQuery, this);