src/pyams_skin/resources/js/myams-plugins.js
changeset 557 bca7a7e058a3
equal deleted inserted replaced
-1:000000000000 557:bca7a7e058a3
       
     1 /**
       
     2  * MyAMS standard plug-ins
       
     3  *
       
     4  * Only basic JQuery, Bootstrap and MyAMS javascript extensions are typically loaded from main page.
       
     5  * Other JQuery plug-ins may be loaded dynamically.
       
     6  * Several JQuery extension plug-ins are already included and pre-configured by MyAMS. Other external
       
     7  * plug-ins can be defined and loaded dynamically using simple "data" attributes.
       
     8  *
       
     9  * WARNING: any plug-in implicated into a form submit process (like JQuery-form or JQuery-progressbar)
       
    10  * must be loaded in a synchronous way. Otherwise, if you use named buttons to submit your forms,
       
    11  * dynamic hidden input fields created by JQuery-validate plug-in will be removed from the form
       
    12  * before the form is submitted!
       
    13  */
       
    14 (function($, globals) {
       
    15 
       
    16 	var ams = globals.MyAMS;
       
    17 
       
    18 	/**
       
    19 	 * Map of enabled plug-ins
       
    20 	 * This map can be extended by external plug-ins.
       
    21 	 *
       
    22 	 * Standard MyAMS plug-ins management method generally includes:
       
    23 	 * - applying a class matching plug-in name on a set of HTML entities to apply the plug-in
       
    24 	 * - defining a set of data-attributes on each of these entities to customize the plug-in
       
    25 	 * For each standard plug-in, you can also provide an options object (to define plug-in options not handled
       
    26 	 * by default MyAMS initialization engine) and an initialization callback (to define these options dynamically).
       
    27 	 * Another callback can also be provided to be called after plug-in initialization.
       
    28 	 *
       
    29 	 * You can also register plug-ins using the 'register' function
       
    30 	 */
       
    31 	$.extend(ams.plugins.enabled, {
       
    32 
       
    33 		/**
       
    34 		 * SVG containers
       
    35 		 */
       
    36 		svg: function(element) {
       
    37 			var svgs = $('.svg-container', element);
       
    38 			if (svgs.length > 0) {
       
    39 				svgs.each(function() {
       
    40 					var container = $(this);
       
    41 					var svg = $('svg', container),
       
    42 						width = svg.attr('width'),
       
    43 						height = svg.attr('height');
       
    44 					if (width && height) {
       
    45 						svg.get(0).setAttribute('viewBox',
       
    46 												'0 0 ' + Math.round(parseFloat(width)) + ' ' +
       
    47 													Math.round(parseFloat(height)));
       
    48 					}
       
    49 					svg.attr('width', '100%')
       
    50 						.attr('height', 'auto');
       
    51 				})
       
    52 			}
       
    53 		},
       
    54 
       
    55 		/**
       
    56 		 * Label hints
       
    57 		 */
       
    58 		hint: function(element) {
       
    59 			var hints = $('.hint:not(:parents(.nohints))', element);
       
    60 			if (hints.length > 0) {
       
    61 				ams.ajax && ams.ajax.check($.fn.tipsy,
       
    62 										   ams.baseURL + 'ext/jquery-tipsy' + ams.devext + '.js',
       
    63 										   function() {
       
    64 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-tipsy' + ams.devext + '.css',
       
    65 														  'jquery-tipsy', function() {
       
    66 													   hints.each(function() {
       
    67 														   var hint = $(this);
       
    68 														   var data = hint.data();
       
    69 														   var dataOptions = {
       
    70 															   html: data.amsHintHtml === undefined ? (hint.attr('title') || '').startsWith('<') : data.amsHintHtml,
       
    71 															   title: ams.getFunctionByName(data.amsHintTitleGetter) || function() {
       
    72 																   var hint = $(this);
       
    73 																   var result = hint.attr('original-title') ||
       
    74 																	   hint.attr(data.amsHintTitleAttr || 'title') ||
       
    75 																	   (data.amsHintHtml ? hint.html() : hint.text());
       
    76 																   result = result.replace(/\?_="/, '?_=' + new Date().getTime() + '"');
       
    77 																   return result;
       
    78 															   },
       
    79 															   opacity: data.amsHintOpacity || 0.95,
       
    80 															   gravity: data.amsHintGravity || 'sw',
       
    81 															   offset: data.amsHintOffset || 0
       
    82 														   };
       
    83 														   var settings = $.extend({}, dataOptions, data.amsHintOptions);
       
    84 														   settings = ams.executeFunctionByName(data.amsHintInitCallback, hint, settings) || settings;
       
    85 														   var plugin = hint.tipsy(settings);
       
    86 														   ams.executeFunctionByName(data.amsHintAfterInitCallback, hint, plugin, settings);
       
    87 													   });
       
    88 												   });
       
    89 										   });
       
    90 			}
       
    91 		},
       
    92 
       
    93 		/**
       
    94 		 * Context menu plug-in
       
    95 		 */
       
    96 		contextMenu: function(element) {
       
    97 			var menus = $('.context-menu', element);
       
    98 			if (menus.length > 0) {
       
    99 				menus.each(function() {
       
   100 					var menu = $(this);
       
   101 					var data = menu.data();
       
   102 					var dataOptions = {
       
   103 						menuSelector: data.amsContextmenuSelector,
       
   104 						menuSelected: ams.helpers && ams.helpers.contextMenuHandler
       
   105 					};
       
   106 					var settings = $.extend({}, dataOptions, data.amsContextmenuOptions);
       
   107 					settings = ams.executeFunctionByName(data.amsContextmenuInitCallback, menu, settings) || settings;
       
   108 					var plugin = menu.contextMenu(settings);
       
   109 					ams.executeFunctionByName(data.amsContextmenuAfterInitCallback, menu, plugin, settings);
       
   110 				});
       
   111 			}
       
   112 		},
       
   113 
       
   114 		/**
       
   115 		 * Fieldset legend switcher
       
   116 		 */
       
   117 		switcher: function(element) {
       
   118 			$('LEGEND.switcher', element).each(function() {
       
   119 				var legend = $(this);
       
   120 				var fieldset = legend.parent('fieldset');
       
   121 				var data = legend.data();
       
   122 				if (!data.amsSwitcher) {
       
   123 					$('<i class="fa fa-fw"></i>')
       
   124 						.prependTo($(this))
       
   125 						.addClass(data.amsSwitcherState === 'open' ?
       
   126 									  (data.amsSwitcherMinusClass || 'fa-minus') :
       
   127 									  (data.amsSwitcherPlusClass || 'fa-plus'));
       
   128 					legend.on('click', function(e) {
       
   129 						e.preventDefault();
       
   130 						var veto = {};
       
   131 						legend.trigger('ams.switcher.before-switch', [legend, veto]);
       
   132 						if (veto.veto) {
       
   133 							return;
       
   134 						}
       
   135 						if (fieldset.hasClass('switched')) {
       
   136 							fieldset.removeClass('switched');
       
   137 							$('.fa', legend).removeClass(data.amsSwitcherPlusClass || 'fa-plus')
       
   138 								.addClass(data.amsSwitcherMinusClass || 'fa-minus');
       
   139 							legend.trigger('ams.switcher.opened', [legend]);
       
   140 							var id = legend.attr('id');
       
   141 							if (id) {
       
   142 								$('legend.switcher[data-ams-switcher-sync="' + id + '"]', fieldset).each(function() {
       
   143 									var switcher = $(this);
       
   144 									if (switcher.parents('fieldset').hasClass('switched')) {
       
   145 										switcher.click();
       
   146 									}
       
   147 								});
       
   148 							}
       
   149 						} else {
       
   150 							fieldset.addClass('switched');
       
   151 							$('.fa', legend).removeClass(data.amsSwitcherMinusClass || 'fa-minus')
       
   152 								.addClass(data.amsSwitcherPlusClass || 'fa-plus');
       
   153 							legend.trigger('ams.switcher.closed', [legend]);
       
   154 						}
       
   155 					});
       
   156 					if (data.amsSwitcherState !== 'open') {
       
   157 						fieldset.addClass('switched');
       
   158 					}
       
   159 					legend.data('ams-switcher', 'on');
       
   160 				}
       
   161 			});
       
   162 		},
       
   163 
       
   164 		/**
       
   165 		 * Fieldset legend checker
       
   166 		 */
       
   167 		checker: function(element) {
       
   168 			$('LEGEND.checker', element).each(function() {
       
   169 				var legend = $(this);
       
   170 				var fieldset = legend.parent('fieldset');
       
   171 				var data = legend.data();
       
   172 				if (!data.amsChecker) {
       
   173 					var checker = $('<label class="checkbox"></label>');
       
   174 					var fieldname = data.amsCheckerFieldname || ('checker_' + ams.generateId());
       
   175 					var checkboxId = fieldname.replace(/\./, '_');
       
   176 					var prefix = data.amsCheckerHiddenPrefix;
       
   177 					var hidden = null;
       
   178 					var checkedValue = data.amsCheckerHiddenValueOn || 'true';
       
   179 					var uncheckedValue = data.amsCheckerHiddenValueOff || 'false';
       
   180 					var marker = data.amsCheckerMarker || false;
       
   181 					if (prefix) {
       
   182 						hidden = $('<input type="hidden">').attr('name', prefix + fieldname)
       
   183 							.val(data.amsCheckerState === 'on' ? checkedValue : uncheckedValue)
       
   184 							.prependTo(legend);
       
   185 					} else if (marker) {
       
   186 						$('<input type="hidden">').attr('name', marker)
       
   187 							.attr('value', 1)
       
   188 							.prependTo(legend);
       
   189 					}
       
   190 					var input = $('<input type="checkbox">').attr('name', fieldname)
       
   191 						.attr('id', checkboxId)
       
   192 						.data('ams-checker-hidden-input', hidden)
       
   193 						.data('ams-checker-init', true)
       
   194 						.val(data.amsCheckerValue || true)
       
   195 						.attr('checked', data.amsCheckerState === 'on' ? 'checked' : null);
       
   196 					if (data.amsCheckerReadonly) {
       
   197 						input.attr('disabled', 'disabled');
       
   198 					} else {
       
   199 						input.on('change', function(e) {
       
   200 							e.preventDefault();
       
   201 							var veto = {};
       
   202 							var isChecked = $(this).is(':checked');
       
   203 							legend.trigger('ams.checker.before-switch', [legend, veto]);
       
   204 							if (veto.veto) {
       
   205 								// reset checked status because event is fired after change...
       
   206 								$(this).prop('checked', !isChecked);
       
   207 								return;
       
   208 							}
       
   209 							ams.executeFunctionByName(data.amsCheckerChangeHandler, legend, isChecked);
       
   210 							if (!data.amsCheckerCancelDefault) {
       
   211 								var hidden = input.data('ams-checker-hidden-input');
       
   212 								if (isChecked) {
       
   213 									if (data.amsCheckerMode === 'disable') {
       
   214 										fieldset.removeAttr('disabled');
       
   215 										$('.select2', fieldset).removeAttr('disabled');
       
   216 									} else {
       
   217 										fieldset.removeClass('switched');
       
   218 									}
       
   219 									if (hidden) {
       
   220 										hidden.val(checkedValue);
       
   221 									}
       
   222 									$('[data-required]', fieldset).attr('required', 'required');
       
   223 									legend.trigger('ams.checker.opened', [legend]);
       
   224 								} else {
       
   225 									if (data.amsCheckerMode === 'disable') {
       
   226 										fieldset.prop('disabled', 'disabled');
       
   227 										$('.select2', fieldset).attr('disabled', 'disabled');
       
   228 									} else {
       
   229 										fieldset.addClass('switched');
       
   230 									}
       
   231 									if (hidden) {
       
   232 										hidden.val(uncheckedValue);
       
   233 									}
       
   234 									$('[data-required]', fieldset).removeAttr('required');
       
   235 									legend.trigger('ams.checker.closed', [legend]);
       
   236 								}
       
   237 							}
       
   238 						});
       
   239 					}
       
   240 					input.appendTo(checker);
       
   241 					$('>label', legend).attr('for', input.attr('id'));
       
   242 					checker.append('<i></i>')
       
   243 						.prependTo(legend);
       
   244 					var required = $('[required]', fieldset);
       
   245 					required.attr('data-required', true);
       
   246 					if (data.amsCheckerState === 'on') {
       
   247 						input.attr('checked', true);
       
   248 					} else {
       
   249 						if (data.amsCheckerMode === 'disable') {
       
   250 							fieldset.attr('disabled', 'disabled');
       
   251 							$('.select2', fieldset).attr('disabled', 'disabled');
       
   252 						} else {
       
   253 							fieldset.addClass('switched');
       
   254 						}
       
   255 						required.removeAttr('required');
       
   256 					}
       
   257 					legend.data('ams-checker', 'on');
       
   258 				}
       
   259 			});
       
   260 		},
       
   261 
       
   262 		/**
       
   263 		 * Sliders
       
   264 		 */
       
   265 		slider: function(element) {
       
   266 			var sliders = $('.slider', element);
       
   267 			if (sliders.length > 0) {
       
   268 				ams.ajax && ams.ajax.check($.fn.slider,
       
   269 										   ams.baseURL + 'ext/bootstrap-slider-2.0.0' + ams.devext + '.js',
       
   270 										   function() {
       
   271 											   sliders.each(function() {
       
   272 												   var slider = $(this);
       
   273 												   var data = slider.data();
       
   274 												   var dataOptions = {};
       
   275 												   var settings = $.extend({}, dataOptions, slider.data.amsSliderOptions);
       
   276 												   settings = ams.executeFunctionByName(data.amsSliderInitCallback, slider, settings) || settings;
       
   277 												   var plugin = slider.slider(settings);
       
   278 												   ams.executeFunctionByName(data.amsSliderAfterInitCallback, slider, plugin, settings);
       
   279 											   });
       
   280 										   });
       
   281 			}
       
   282 		},
       
   283 
       
   284 		/**
       
   285 		 * Draggable plug-in
       
   286 		 */
       
   287 		draggable: function(element) {
       
   288 			var draggables = $('.draggable', element);
       
   289 			if (draggables.length > 0) {
       
   290 				draggables.each(function() {
       
   291 					var draggable = $(this);
       
   292 					var data = draggable.data();
       
   293 					var dataOptions = {
       
   294 						cursor: data.amsDraggableCursor || 'move',
       
   295 						containment: data.amsDraggableContainment,
       
   296 						handle: data.amsDraggableHandle,
       
   297 						connectToSortable: data.amsDraggableConnectSortable,
       
   298 						helper: ams.getFunctionByName(data.amsDraggableHelper) || data.amsDraggableHelper,
       
   299 						start: ams.getFunctionByName(data.amsDraggableStart),
       
   300 						stop: ams.getFunctionByName(data.amsDraggableStop)
       
   301 					};
       
   302 					var settings = $.extend({}, dataOptions, data.amsDraggableOptions);
       
   303 					settings = ams.executeFunctionByName(data.amsDraggableInitCallback, draggable, settings) || settings;
       
   304 					var plugin = draggable.draggable(settings);
       
   305 					draggable.disableSelection();
       
   306 					ams.executeFunctionByName(data.amsDraggableAfterInitCallback, draggable, plugin, settings);
       
   307 				});
       
   308 			}
       
   309 		},
       
   310 
       
   311 		/**
       
   312 		 * Droppable plug-in
       
   313 		 */
       
   314 		droppable: function(element) {
       
   315 			var droppables = $('.droppable', element);
       
   316 			if (droppables.length > 0) {
       
   317 				droppables.each(function() {
       
   318 					var droppable = $(this);
       
   319 					var data = droppable.data();
       
   320 					var dataOptions = {
       
   321 						accept: data.amsdroppableAccept,
       
   322 						drop: ams.getFunctionByName(data.amsDroppableDrop)
       
   323 					};
       
   324 					var settings = $.extend({}, dataOptions, data.amsDroppableOptions);
       
   325 					settings = ams.executeFunctionByName(data.amsDroppableInitCallback, droppable, settings) || settings;
       
   326 					var plugin = droppable.droppable(settings);
       
   327 					ams.executeFunctionByName(data.amsDroppableAfterInitCallback, droppable, plugin, settings);
       
   328 				});
       
   329 			}
       
   330 		},
       
   331 
       
   332 		/**
       
   333 		 * Sortable plug-in
       
   334 		 */
       
   335 		sortable: function(element) {
       
   336 			var sortables = $('.sortable', element);
       
   337 			if (sortables.length > 0) {
       
   338 				sortables.each(function() {
       
   339 					var sortable = $(this);
       
   340 					var data = sortable.data();
       
   341 					var dataOptions = {
       
   342 						items: data.amsSortableItems,
       
   343 						handle: data.amsSortableHandle,
       
   344 						helper: data.amsSortableHelper,
       
   345 						connectWith: data.amsSortableConnectwith,
       
   346 						start: ams.getFunctionByName(data.amsSortableStart),
       
   347 						over: ams.getFunctionByName(data.amsSortableOver),
       
   348 						containment: data.amsSortableContainment,
       
   349 						placeholder: data.amsSortablePlaceholder,
       
   350 						stop: ams.getFunctionByName(data.amsSortableStop)
       
   351 					};
       
   352 					var settings = $.extend({}, dataOptions, data.amsSortableOptions);
       
   353 					settings = ams.executeFunctionByName(data.amsSortableInitCallback, sortable, settings) || settings;
       
   354 					var plugin = sortable.sortable(settings);
       
   355 					sortable.disableSelection();
       
   356 					ams.executeFunctionByName(data.amsSortableAfterInitCallback, sortable, plugin, settings);
       
   357 				});
       
   358 			}
       
   359 		},
       
   360 
       
   361 		/**
       
   362 		 * Resizable plug-in
       
   363 		 */
       
   364 		resizable: function(element) {
       
   365 			var resizables = $('.resizable', element);
       
   366 			if (resizables.length > 0) {
       
   367 				resizables.each(function() {
       
   368 					var resizable = $(this);
       
   369 					var data = resizable.data();
       
   370 					var dataOptions = {
       
   371 						autoHide: data.amsResizableAutohide === false ? true : data.amsResizableAutohide,
       
   372 						containment: data.amsResizableContainment,
       
   373 						grid: data.amsResizableGrid,
       
   374 						handles: data.amsResizableHandles,
       
   375 						start: ams.getFunctionByName(data.amsResizableStart),
       
   376 						stop: ams.getFunctionByName(data.amsResizableStop)
       
   377 					};
       
   378 					var settings = $.extend({}, dataOptions, data.amsResizableOptions);
       
   379 					settings = ams.executeFunctionByName(data.amsResizableInitCallback, resizable, settings) || settings;
       
   380 					var plugin = resizable.resizable(settings);
       
   381 					resizable.disableSelection();
       
   382 					ams.executeFunctionByName(data.amsResizableAfterInitCallback, resizable, plugin, settings);
       
   383 				});
       
   384 			}
       
   385 		},
       
   386 
       
   387 		/**
       
   388 		 * JQuery typeahead plug-in
       
   389 		 */
       
   390 		typeahead: function(element) {
       
   391 			var typeaheads = $('.typeahead', element);
       
   392 			if (typeaheads.length > 0) {
       
   393 				ams.ajax && ams.ajax.check($.fn.typeahead,
       
   394 										   ams.baseURL + 'ext/jquery-typeahead' + ams.devext + '.js',
       
   395 										   function() {
       
   396 											   typeaheads.each(function() {
       
   397 												   var input = $(this);
       
   398 												   var data = input.data();
       
   399 												   var dataOptions = {};
       
   400 												   var settings = $.extend({}, dataOptions, data.amsTypeaheadOptions);
       
   401 												   settings = ams.executeFunctionByName(data.amsTypeaheadInitCallback, input, settings) || settings;
       
   402 												   var plugin = input.typeahead(settings);
       
   403 												   ams.executeFunctionByName(data.amsTypeaheadAfterInitCallback, input, plugin, settings);
       
   404 											   });
       
   405 										   });
       
   406 			}
       
   407 		},
       
   408 
       
   409 		/**
       
   410 		 * Treeview plug-in
       
   411 		 */
       
   412 		treeview: function(element) {
       
   413 			var treeviews = $('.treeview', element);
       
   414 			if (treeviews.length > 0) {
       
   415 				ams.ajax && ams.ajax.check($.fn.treview,
       
   416 										   ams.baseURL + 'ext/bootstrap-treeview' + ams.devext + '.js',
       
   417 										   function() {
       
   418 											   ams.getCSS(ams.baseURL + '../css/ext/bootstrap-treeview' + ams.devext + '.css',
       
   419 														  'bootstrap-treeview',
       
   420 														  function() {
       
   421 															  treeviews.each(function() {
       
   422 																  var treeview = $(this);
       
   423 																  var data = treeview.data();
       
   424 																  var dataOptions = {
       
   425 																	  data: data.amsTreeviewData,
       
   426 																	  levels: data.amsTreeviewLevels,
       
   427 																	  injectStyle: data.amsTreeviewInjectStyle,
       
   428 																	  expandIcon: data.amsTreeviewExpandIcon || 'fa fa-fw fa-plus-square-o',
       
   429 																	  collapseIcon: data.amsTreeviewCollaspeIcon || 'fa fa-fw fa-minus-square-o',
       
   430 																	  emptyIcon: data.amsTreeviewEmptyIcon || 'fa fa-fw',
       
   431 																	  nodeIcon: data.amsTreeviewNodeIcon,
       
   432 																	  selectedIcon: data.amsTreeviewSelectedIcon,
       
   433 																	  checkedIcon: data.amsTreeviewCheckedIcon || 'fa fa-fw fa-check-square-o',
       
   434 																	  uncheckedIcon: data.amsTreeviewUncheckedIcon || 'fa fa-fw fa-square-o',
       
   435 																	  color: data.amsTreeviewColor,
       
   436 																	  backColor: data.amsTreeviewBackColor,
       
   437 																	  borderColor: data.amsTreeviewBorderColor,
       
   438 																	  onHoverColor: data.amsTreeviewHoverColor,
       
   439 																	  selectedColor: data.amsTreeviewSelectedColor,
       
   440 																	  selectedBackColor: data.amsTreeviewSelectedBackColor,
       
   441 																	  unselectableColor: data.amsTreeviewUnselectableColor || 'rgba(1,1,1,0.25)',
       
   442 																	  unselectableBackColor: data.amsTreeviewUnselectableBackColor || 'rgba(1,1,1,0.25)',
       
   443 																	  enableLinks: data.amsTreeviewEnableLinks,
       
   444 																	  highlightSelected: data.amsTreeviewHighlightSelected,
       
   445 																	  highlightSearchResults: data.amsTreeviewhighlightSearchResults,
       
   446 																	  showBorder: data.amsTreeviewShowBorder,
       
   447 																	  showIcon: data.amsTreeviewShowIcon,
       
   448 																	  showCheckbox: data.amsTreeviewShowCheckbox,
       
   449 																	  showTags: data.amsTreeviewShowTags,
       
   450 																	  toggleUnselectable: data.amsTreeviewToggleUnselectable,
       
   451 																	  multiSelect: data.amsTreeviewMultiSelect,
       
   452 																	  onNodeChecked: ams.getFunctionByName(data.amsTreeviewNodeChecked),
       
   453 																	  onNodeCollapsed: ams.getFunctionByName(data.amsTreeviewNodeCollapsed),
       
   454 																	  onNodeDisabled: ams.getFunctionByName(data.amsTreeviewNodeDisabled),
       
   455 																	  onNodeEnabled: ams.getFunctionByName(data.amsTreeviewNodeEnabled),
       
   456 																	  onNodeExpanded: ams.getFunctionByName(data.amsTreeviewNodeExpanded),
       
   457 																	  onNodeSelected: ams.getFunctionByName(data.amsTreeviewNodeSelected),
       
   458 																	  onNodeUnchecked: ams.getFunctionByName(data.amsTreeviewNodeUnchecked),
       
   459 																	  onNodeUnselected: ams.getFunctionByName(data.amsTreeviewNodeUnselected),
       
   460 																	  onSearchComplete: ams.getFunctionByName(data.amsTreeviewSearchComplete),
       
   461 																	  onSearchCleared: ams.getFunctionByName(data.amsTreeviewSearchCleared)
       
   462 																  };
       
   463 																  var settings = $.extend({}, dataOptions, data.amsTreeviewOptions);
       
   464 																  settings = ams.executeFunctionByName(data.amsTreeviewInitcallback, treeview, settings) || settings;
       
   465 																  var plugin = treeview.treeview(settings);
       
   466 																  ams.executeFunctionByName(data.amsTreeviewAfterInitCallback, treeview, plugin, settings);
       
   467 															  });
       
   468 														  });
       
   469 										   });
       
   470 			}
       
   471 		},
       
   472 
       
   473 		/**
       
   474 		 * Select2 plug-in
       
   475 		 */
       
   476 		select2: function(element) {
       
   477 			var selects = $('.select2', element);
       
   478 			if (selects.length > 0) {
       
   479 				ams.ajax && ams.ajax.check($.fn.select2,
       
   480 										   ams.baseURL + 'ext/jquery-select2-3.5.4' + ams.devext + '.js',
       
   481 										   function() {
       
   482 											   selects.each(function() {
       
   483 												   var select = $(this);
       
   484 												   var data = select.data();
       
   485 												   if (data.select2) {
       
   486 													   // Already initialized
       
   487 													   return;
       
   488 												   }
       
   489 												   var dataOptions = {
       
   490 													   placeholder: data.amsSelect2Placeholder,
       
   491 													   multiple: data.amsSelect2Multiple,
       
   492 													   minimumInputLength: data.amsSelect2MinimumInputLength || 0,
       
   493 													   maximumSelectionSize: data.amsSelect2MaximumSelectionSize,
       
   494 													   openOnEnter: data.amsSelect2EnterOpen === undefined ? true : data.amsSelect2EnterOpen,
       
   495 													   allowClear: data.amsSelect2AllowClear === undefined ? true : data.amsSelect2AllowClear,
       
   496 													   width: data.amsSelect2Width || '100%',
       
   497 													   initSelection: ams.getFunctionByName(data.amsSelect2InitSelection),
       
   498 													   formatSelection: data.amsSelect2FormatSelection === undefined
       
   499 														   ? ams.helpers && ams.helpers.select2FormatSelection
       
   500 														   : ams.getFunctionByName(data.amsSelect2FormatSelection),
       
   501 													   formatResult: ams.getFunctionByName(data.amsSelect2FormatResult),
       
   502 													   formatMatches: data.amsSelect2FormatMatches === undefined ?
       
   503 														   function(matches) {
       
   504 															   if (matches === 1) {
       
   505 																   return ams.i18n.SELECT2_MATCH;
       
   506 															   } else {
       
   507 																   return matches + ams.i18n.SELECT2_MATCHES;
       
   508 															   }
       
   509 														   }
       
   510 														   : ams.getFunctionByName(data.amsSelect2FormatMatches),
       
   511 													   formatNoMatches: data.amsSelect2FormatResult === undefined ?
       
   512 														   function(term) {
       
   513 															   return ams.i18n.SELECT2_NOMATCHES;
       
   514 														   }
       
   515 														   : ams.getFunctionByName(data.amsSelect2FormatResult),
       
   516 													   formatInputTooShort: data.amsSelect2FormatInputTooShort === undefined ?
       
   517 														   function(input, min) {
       
   518 															   var n = min - input.length;
       
   519 															   return ams.i18n.SELECT2_INPUT_TOOSHORT
       
   520 																   .replace(/\{0\}/, n)
       
   521 																   .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
       
   522 														   }
       
   523 														   : ams.getFunctionByName(data.amsSelect2FormatInputTooShort),
       
   524 													   formatInputTooLong: data.amsSelect2FormatInputTooLong === undefined ?
       
   525 														   function(input, max) {
       
   526 															   var n = input.length - max;
       
   527 															   return ams.i18n.SELECT2_INPUT_TOOLONG
       
   528 																   .replace(/\{0\}/, n)
       
   529 																   .replace(/\{1\}/, n === 1 ? "" : ams.i18n.SELECT2_PLURAL);
       
   530 														   }
       
   531 														   : ams.getFunctionByName(data.amsSelect2FormatInputTooLong),
       
   532 													   formatSelectionTooBig: data.amsSelect2FormatSelectionTooBig === undefined ?
       
   533 														   function(limit) {
       
   534 															   return ams.i18n.SELECT2_SELECTION_TOOBIG
       
   535 																   .replace(/\{0\}/, limit)
       
   536 																   .replace(/\{1\}/, limit === 1 ? "" : ams.i18n.SELECT2_PLURAL);
       
   537 														   }
       
   538 														   : ams.getFunctionByName(data.amsSelect2FormatSelectionTooBig),
       
   539 													   formatLoadMore: data.amsSelect2FormatLoadMore === undefined ?
       
   540 														   function(pageNumber) {
       
   541 															   return ams.i18n.SELECT2_LOADMORE;
       
   542 														   }
       
   543 														   : ams.getFunctionByName(data.amsSelect2FormatLoadMore),
       
   544 													   formatSearching: data.amsSelect2FormatSearching === undefined ?
       
   545 														   function() {
       
   546 															   return ams.i18n.SELECT2_SEARCHING;
       
   547 														   }
       
   548 														   : ams.getFunctionByName(data.amsSelect2FormatSearching),
       
   549 													   separator: data.amsSelect2Separator || ',',
       
   550 													   tokenSeparators: data.amsSelect2TokensSeparators || [','],
       
   551 													   tokenizer: ams.getFunctionByName(data.amsSelect2Tokenizer)
       
   552 												   };
       
   553 
       
   554 												   switch (select.context.type) {
       
   555 													   case 'text':
       
   556 													   case 'hidden':
       
   557 														   if (!dataOptions.initSelection) {
       
   558 															   var valuesData = select.data('ams-select2-values');
       
   559 															   if (valuesData) {
       
   560 																   dataOptions.initSelection = function(element, callback) {
       
   561 																	   var data = [];
       
   562 																	   $(element.val().split(dataOptions.separator)).each(function() {
       
   563 																		   data.push({
       
   564 																						 id: this,
       
   565 																						 text: valuesData[this] || this
       
   566 																					 });
       
   567 																	   });
       
   568 																	   callback(data);
       
   569 																   };
       
   570 															   }
       
   571 														   }
       
   572 														   break;
       
   573 													   default:
       
   574 														   break;
       
   575 												   }
       
   576 
       
   577 												   if (select.attr('readonly')) {
       
   578 													   if (select.attr('type') === 'hidden') {
       
   579 														   dataOptions.query = function() {
       
   580 															   return [];
       
   581 														   };
       
   582 													   }
       
   583 												   } else if (data.amsSelect2Query) {
       
   584 													   // Custom query method
       
   585 													   dataOptions.query = ams.getFunctionByName(data.amsSelect2Query);
       
   586 													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
       
   587 												   } else if (data.amsSelect2QueryUrl) {
       
   588 													   // AJAX query
       
   589 													   dataOptions.ajax = {
       
   590 														   url: data.amsSelect2QueryUrl,
       
   591 														   quietMillis: data.amsSelect2QuietMillis || 200,
       
   592 														   type: data.amsSelect2QueryType || 'POST',
       
   593 														   dataType: data.amsSelect2QueryDatatype || 'json',
       
   594 														   data: function(term, page, context) {
       
   595 															   var options = {};
       
   596 															   options[data.amsSelect2QueryParamName || 'query'] = term;
       
   597 															   options[data.amsSelect2PageParamName || 'page'] = page;
       
   598 															   options[data.amsSelect2ContextParamName || 'context'] = context;
       
   599 															   return $.extend({}, options, data.amsSelect2QueryOptions);
       
   600 														   },
       
   601 														   results: ams.helpers && ams.helpers.select2QueryUrlResultsCallback
       
   602 													   };
       
   603 													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
       
   604 												   } else if (data.amsSelect2QueryMethod) {
       
   605 													   // JSON-RPC query
       
   606 													   dataOptions.query = function(options) {
       
   607 														   var settings = {
       
   608 															   id: new Date().getTime(),
       
   609 															   params: data.amsSelect2QueryParams || {},
       
   610 															   success: function(result) {
       
   611 																   return ams.helpers && ams.helpers.select2QueryMethodSuccessCallback.call(select, result, 'success', options);
       
   612 															   },
       
   613 															   error: ams.error && ams.error.show
       
   614 														   };
       
   615 														   settings.params[data.amsSelect2QueryParamName || 'query'] = options.term;
       
   616 														   settings.params[data.amsSelect2PageParamName || 'page'] = options.page;
       
   617 														   settings.params[data.amsSelect2ContextParamName || 'context'] = options.context;
       
   618 														   settings = $.extend({}, settings, data.amsSelect2QueryOptions);
       
   619 														   settings = ams.executeFunctionByName(data.amsSelect2QueryInitCallback, select, settings) || settings;
       
   620 														   ams.ajax && ams.ajax.check($.jsonRPC,
       
   621 																					  ams.baseURL + 'ext/jquery-jsonrpc' + ams.devext + '.js',
       
   622 																					  function() {
       
   623 																						  $.jsonRPC.withOptions({
       
   624 																													endPoint: data.amsSelect2MethodTarget || (ams.jsonrpc && ams.jsonrpc.getAddr()),
       
   625 																													namespace: data.amsSelect2MethodNamespace,
       
   626 																													cache: false
       
   627 																												}, function() {
       
   628 																							  $.jsonRPC.request(data.amsSelect2QueryMethod, settings);
       
   629 																						  });
       
   630 																					  });
       
   631 													   };
       
   632 													   dataOptions.minimumInputLength = data.amsSelect2MinimumInputLength || 1;
       
   633 												   } else if (data.amsSelect2Tags) {
       
   634 													   // Tags mode
       
   635 													   dataOptions.tags = data.amsSelect2Tags;
       
   636 												   } else if (data.amsSelect2Data) {
       
   637 													   // Provided data mode
       
   638 													   dataOptions.data = data.amsSelect2Data;
       
   639 												   }
       
   640 
       
   641 												   if (data.amsSelect2EnableFreeTags) {
       
   642 													   dataOptions.createSearchChoice = function(term) {
       
   643 														   return {
       
   644 															   id: term,
       
   645 															   text: (data.amsSelect2FreeTagsPrefix || ams.i18n.SELECT2_FREETAG_PREFIX) + term
       
   646 														   };
       
   647 													   };
       
   648 												   }
       
   649 
       
   650 												   var settings = $.extend({}, dataOptions, data.amsSelect2Options);
       
   651 												   settings = ams.executeFunctionByName(data.amsSelect2InitCallback, select, settings) || settings;
       
   652 												   var plugin = select.select2(settings);
       
   653 												   ams.executeFunctionByName(data.amsSelect2AfterInitCallback, select, plugin, settings);
       
   654 												   if (select.hasClass('ordered')) {
       
   655 													   ams.ajax && ams.ajax.check($.fn.select2Sortable,
       
   656 																				  ams.baseURL + 'ext/jquery-select2-sortable' + ams.devext + '.js',
       
   657 																				  function() {
       
   658 																					  select.select2Sortable({
       
   659 																												 bindOrder: 'sortableStop'
       
   660 																											 });
       
   661 																				  });
       
   662 												   }
       
   663 
       
   664 												   select.on('change', function() {
       
   665 													   var validator = $(select.get(0).form).data('validator');
       
   666 													   if (validator !== undefined) {
       
   667 														   $(select).valid();
       
   668 													   }
       
   669 												   });
       
   670 											   });
       
   671 										   });
       
   672 			}
       
   673 		},
       
   674 
       
   675 		/**
       
   676 		 * Edit mask plug-in
       
   677 		 */
       
   678 		maskedit: function(element) {
       
   679 			var masks = $('[data-mask]', element);
       
   680 			if (masks.length > 0) {
       
   681 				ams.ajax && ams.ajax.check($.fn.mask,
       
   682 										   ams.baseURL + 'ext/jquery-maskedinput-1.4.1' + ams.devext + '.js',
       
   683 										   function() {
       
   684 											   masks.each(function() {
       
   685 												   var mask = $(this);
       
   686 												   var data = mask.data();
       
   687 												   var dataOptions = {
       
   688 													   placeholder: data.amsMaskeditPlaceholder === undefined ? 'X' : data.amsMaskeditPlaceholder,
       
   689 													   complete: ams.getFunctionByName(data.amsMaskeditComplete)
       
   690 												   };
       
   691 												   var settings = $.extend({}, dataOptions, data.amsMaskeditOptions);
       
   692 												   settings = ams.executeFunctionByName(data.amsMaskeditInitCallback, mask, settings) || settings;
       
   693 												   var plugin = mask.mask(mask.attr('data-mask'), settings);
       
   694 												   ams.executeFunctionByName(data.amsMaskeditAfterInitCallback, mask, plugin, settings);
       
   695 											   });
       
   696 										   });
       
   697 			}
       
   698 		},
       
   699 
       
   700 		/**
       
   701 		 * JQuery input-mask plug-in
       
   702 		 *
       
   703 		 * Mask value can be set in a "data-input-mask" attribute defined:
       
   704 		 * - as a simple string containing mask
       
   705 		 * - as a JSON object defining all mask attributes, for example:
       
   706 		 *   data-input-mask='{"alias": "integer", "allowPlus": false, "allowMinus": false}'
       
   707 		 */
       
   708 		inputmask: function(element) {
       
   709 			var masks = $('input[data-input-mask]', element);
       
   710 			if (masks.length > 0) {
       
   711 				ams.ajax && ams.ajax.check($.fn.inputmask,
       
   712 										   ams.baseURL + 'ext/jquery-inputmask-bundle-3.2.8' + ams.devext + '.js',
       
   713 										   function() {
       
   714 											   masks.each(function() {
       
   715 												   var input = $(this);
       
   716 												   var data = input.data();
       
   717 												   var dataOptions;
       
   718 												   if (typeof (data.inputMask) === 'object') {
       
   719 													   dataOptions = data.inputMask;
       
   720 												   } else {
       
   721 													   dataOptions = {
       
   722 														   mask: data.inputMask.toString()
       
   723 													   };
       
   724 												   }
       
   725 												   var settings = $.extend({}, dataOptions, data.amsInputmaskOptions);
       
   726 												   settings = ams.executeFunctionByName(data.amsInputmaskInitCallback, input, settings) || settings;
       
   727 												   var plugin = input.inputmask(settings);
       
   728 												   ams.executeFunctionByName(data.amsInputmaskAfterInitCallback, input, plugin, settings);
       
   729 											   });
       
   730 										   });
       
   731 			}
       
   732 		},
       
   733 
       
   734 		/**
       
   735 		 * JQuery date picker
       
   736 		 */
       
   737 		datepicker: function(element) {
       
   738 			var datepickers = $('.datepicker', element);
       
   739 			if (datepickers.length > 0) {
       
   740 				ams.ajax && ams.ajax.check($.fn.datetimepicker,
       
   741 										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
       
   742 										   function(first_load) {
       
   743 											   if (first_load) {
       
   744 												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
       
   745 											   }
       
   746 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
       
   747 														  'jquery-datetimepicker',
       
   748 														  function() {
       
   749 															  datepickers.each(function() {
       
   750 																  var input = $(this);
       
   751 																  var data = input.data();
       
   752 																  var dataOptions = {
       
   753 																	  lang: data.amsDatetimepickerLang || ams.lang,
       
   754 																	  format: data.amsDatetimepickerFormat || 'd/m/y',
       
   755 																	  datepicker: true,
       
   756 																	  dayOfWeekStart: 1,
       
   757 																	  timepicker: false,
       
   758 																	  closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
       
   759 																	  weeks: data.amsDatetimepickerWeeks
       
   760 																  };
       
   761 																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
       
   762 																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
   763 																  var plugin = input.datetimepicker(settings);
       
   764 																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
   765 															  });
       
   766 														  });
       
   767 										   });
       
   768 			}
       
   769 		},
       
   770 
       
   771 		/**
       
   772 		 * JQuery datetime picker
       
   773 		 */
       
   774 		datetimepicker: function(element) {
       
   775 			var datetimepickers = $('.datetimepicker', element);
       
   776 			if (datetimepickers.length > 0) {
       
   777 				ams.ajax && ams.ajax.check($.fn.datetimepicker,
       
   778 										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
       
   779 										   function(first_load) {
       
   780 											   if (first_load) {
       
   781 												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
       
   782 											   }
       
   783 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
       
   784 														  'jquery-datetimepicker',
       
   785 														  function() {
       
   786 															  datetimepickers.each(function() {
       
   787 																  var input = $(this);
       
   788 																  var data = input.data();
       
   789 																  var dataOptions = {
       
   790 																	  lang: data.amsDatetimepickerLang || ams.lang,
       
   791 																	  format: data.amsDatetimepickerFormat || 'd/m/y H:i',
       
   792 																	  datepicker: true,
       
   793 																	  dayOfWeekStart: 1,
       
   794 																	  timepicker: true,
       
   795 																	  closeOnDateSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
       
   796 																	  closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect,
       
   797 																	  weeks: data.amsDatetimepickerWeeks
       
   798 																  };
       
   799 																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
       
   800 																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
   801 																  var plugin = input.datetimepicker(settings);
       
   802 																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
   803 															  });
       
   804 														  });
       
   805 										   });
       
   806 			}
       
   807 		},
       
   808 
       
   809 		/**
       
   810 		 * JQuery time picker
       
   811 		 */
       
   812 		timepicker: function(element) {
       
   813 			var timepickers = $('.timepicker', element);
       
   814 			if (timepickers.length > 0) {
       
   815 				ams.ajax && ams.ajax.check($.fn.datetimepicker,
       
   816 										   ams.baseURL + 'ext/jquery-datetimepicker' + ams.devext + '.js',
       
   817 										   function(first_load) {
       
   818 											   if (first_load) {
       
   819 												   ams.dialog && ams.dialog.registerHideCallback(ams.helpers && ams.helpers.datetimepickerDialogHiddenCallback);
       
   820 											   }
       
   821 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-datetimepicker' + ams.devext + '.css',
       
   822 														  'jquery-datetimepicker',
       
   823 														  function() {
       
   824 															  timepickers.each(function() {
       
   825 																  var input = $(this);
       
   826 																  var data = input.data();
       
   827 																  var dataOptions = {
       
   828 																	  lang: data.amsDatetimepickerLang || ams.lang,
       
   829 																	  format: data.amsDatetimepickerFormat || 'H:i',
       
   830 																	  datepicker: false,
       
   831 																	  timepicker: true,
       
   832 																	  closeOnTimeSelect: data.amsDatetimepickerCloseOnSelect === undefined ? true : data.amsDatetimepickerCloseOnSelect
       
   833 																  };
       
   834 																  var settings = $.extend({}, dataOptions, data.amsDatetimepickerOptions);
       
   835 																  settings = ams.executeFunctionByName(data.amsDatetimepickerInitCallback, input, settings) || settings;
       
   836 																  var plugin = input.datetimepicker(settings);
       
   837 																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
   838 															  });
       
   839 														  });
       
   840 										   });
       
   841 			}
       
   842 		},
       
   843 
       
   844 		/**
       
   845 		 * JQuery color picker
       
   846 		 */
       
   847 		colorpicker: function(element) {
       
   848 			var colorpickers = $('.colorpicker', element);
       
   849 			if (colorpickers.length > 0) {
       
   850 				ams.ajax && ams.ajax.check($.fn.minicolors,
       
   851 										   ams.baseURL + 'ext/jquery-minicolors' + ams.devext + '.js',
       
   852 										   function() {
       
   853 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-minicolors' + ams.devext + '.css',
       
   854 														  'jquery-minicolors',
       
   855 														  function() {
       
   856 															  colorpickers.each(function() {
       
   857 																  var input = $(this);
       
   858 																  var data = input.data();
       
   859 																  var dataOptions = {
       
   860 																	  position: data.amsColorpickerPosition || input.closest('.input').data('ams-colorpicker-position') || 'bottom left'
       
   861 																  };
       
   862 																  var settings = $.extend({}, dataOptions, data.amsColorpickerOptions);
       
   863 																  settings = ams.executeFunctionByName(data.amsColorpickerInitCallback, input, settings) || settings;
       
   864 																  var plugin = input.minicolors(settings);
       
   865 																  ams.executeFunctionByName(data.amsDatetimepickerAfterInitCallback, input, plugin, settings);
       
   866 															  });
       
   867 														  });
       
   868 										   });
       
   869 			}
       
   870 		},
       
   871 
       
   872 		/**
       
   873 		 * Drag & drop upload plug-in
       
   874 		 */
       
   875 		dndupload: function(element) {
       
   876 			var uploads = $('.dndupload', element);
       
   877 			if (uploads.length > 0) {
       
   878 				ams.ajax && ams.ajax.check($.fn.dndupload,
       
   879 										   ams.baseURL + 'ext/jquery-dndupload' + ams.devext + '.js',
       
   880 										   function() {
       
   881 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-dndupload' + ams.devext + '.css',
       
   882 														  'jquery-dndupload',
       
   883 														  function() {
       
   884 															  uploads.each(function() {
       
   885 																  var upload = $(this);
       
   886 																  var data = upload.data();
       
   887 																  var dataOptions = {
       
   888 																	  action: data.amsDnduploadAction || upload.attr('action') || 'upload-files',
       
   889 																	  fieldname: data.amsDnduploadFieldname || 'files',
       
   890 																	  autosubmit: data.amsDnduploadAutosubmit
       
   891 																  };
       
   892 																  var settings = $.extend({}, dataOptions, data.amsDnduploadOptions);
       
   893 																  settings = ams.executeFunctionByName(data.amsDnduploadInitCallback, upload, settings) || settings;
       
   894 																  var plugin = upload.dndupload(settings);
       
   895 																  ams.executeFunctionByName(data.amsDnduploadAfterInitcallback, upload, plugin, settings);
       
   896 															  });
       
   897 														  });
       
   898 										   });
       
   899 			}
       
   900 		},
       
   901 
       
   902 		/**
       
   903 		 * JQuery validation plug-in
       
   904 		 */
       
   905 		validate: function(element) {
       
   906 			var forms = $('FORM:not([novalidate])', element);
       
   907 			if (forms.length > 0) {
       
   908 				ams.ajax && ams.ajax.check($.fn.validate,
       
   909 										   ams.baseURL + 'ext/jquery-validate-1.17.0' + ams.devext + '.js',
       
   910 										   function(first_load) {
       
   911 											   if (first_load) {
       
   912 												   $.validator.setDefaults({
       
   913 																			   highlight: function(element) {
       
   914 																				   $(element).closest('.form-group, label:not(:parents(.form-group))')
       
   915 																							 .addClass('state-error');
       
   916 																			   },
       
   917 																			   unhighlight: function(element) {
       
   918 																				   $(element).closest('.form-group, label:not(:parents(.form-group))')
       
   919 																							 .removeClass('state-error');
       
   920 																			   },
       
   921 																			   errorElement: 'span',
       
   922 																			   errorClass: 'state-error',
       
   923 																			   errorPlacement: function(error, element) {
       
   924 																				   var label = element.parents('label, .input').first();
       
   925 																				   if (label.length) {
       
   926 																					   error.insertAfter(label);
       
   927 																				   } else {
       
   928 																					   error.insertAfter(element);
       
   929 																				   }
       
   930 																			   }
       
   931 																		   });
       
   932 												   if (ams.plugins && ams.plugins.i18n) {
       
   933 													   for (var key in ams.plugins.i18n.validate) {
       
   934 														   if (!ams.plugins.i18n.validate.hasOwnProperty(key)) {
       
   935 															   continue;
       
   936 														   }
       
   937 														   var message = ams.plugins.i18n.validate[key];
       
   938 														   if ((typeof (message) === 'string') &&
       
   939 															   (message.indexOf('{0}') > -1)) {
       
   940 															   ams.plugins.i18n.validate[key] = $.validator.format(message);
       
   941 														   }
       
   942 													   }
       
   943 													   $.extend($.validator.messages, ams.plugins.i18n.validate);
       
   944 												   }
       
   945 											   }
       
   946 											   forms.each(function() {
       
   947 												   var form = $(this);
       
   948 												   var data = form.data();
       
   949 												   var dataOptions = {
       
   950 													   ignore: null,
       
   951 													   submitHandler: form.attr('data-async') !== undefined ?
       
   952 														   data.amsFormSubmitHandler === undefined ?
       
   953 															   function() {
       
   954 																   // JQuery-form plug-in must be loaded synchronously!!
       
   955 																   // Otherwise, hidden input fields created by jquery-validate plug-in
       
   956 																   // and matching named buttons will be deleted (on first form submit)
       
   957 																   // before JQuery-form plug-in can get them when submitting the form...
       
   958 																   $('.state-error', form).removeClass('state-error');
       
   959 																   ams.ajax && ams.ajax.check($.fn.ajaxSubmit,
       
   960 																							  ams.baseURL + 'ext/jquery-form-3.49' + ams.devext + '.js');
       
   961 																   return ams.form && ams.form.submit(form);
       
   962 															   }
       
   963 															   : ams.getFunctionByName(data.amsFormSubmitHandler)
       
   964 														   : undefined,
       
   965 													   invalidHandler: data.amsFormInvalidHandler === undefined ?
       
   966 															   function(event, validator) {
       
   967 																   $('.state-error', form).removeClass('state-error');
       
   968 																   for (var index = 0; index < validator.errorList.length; index++) {
       
   969 																	   var error = validator.errorList[index];
       
   970 																	   var tabIndex = $(error.element).parents('.tab-pane').index() + 1;
       
   971 																	   if (tabIndex > 0) {
       
   972 																		   var navTabs = $('.nav-tabs', $(error.element).parents('.tabforms'));
       
   973 																		   $('li:nth-child(' + tabIndex + ')', navTabs)
       
   974 																			   .removeClassPrefix('state-')
       
   975 																			   .addClass('state-error');
       
   976 																		   $('li.state-error:first a', navTabs).click();
       
   977 																	   }
       
   978 																   }
       
   979 															   }
       
   980 															   : ams.getFunctionByName(data.amsFormInvalidHandler)
       
   981 												   };
       
   982 												   $('[data-ams-validate-rules]', form).each(function(index) {
       
   983 													   if (index === 0) {
       
   984 														   dataOptions.rules = {};
       
   985 													   }
       
   986 													   dataOptions.rules[$(this).attr('name')] = $(this).data('ams-validate-rules');
       
   987 												   });
       
   988 												   $('[data-ams-validate-messages]', form).each(function(index) {
       
   989 													   if (index === 0) {
       
   990 													   		dataOptions.messages = {};
       
   991 													   }
       
   992 													   dataOptions.messages[$(this).attr('name')] = $(this).data('ams-validate-messages');
       
   993 												   });
       
   994 												   var settings = $.extend({}, dataOptions, data.amsValidateOptions);
       
   995 												   settings = ams.executeFunctionByName(data.amsValidateInitCallback, form, settings) || settings;
       
   996 												   var plugin = form.validate(settings);
       
   997 												   ams.executeFunctionByName(data.amsValidateAfterInitCallback, form, plugin, settings);
       
   998 											   });
       
   999 										   });
       
  1000 			}
       
  1001 		},
       
  1002 
       
  1003 		/**
       
  1004 		 * JQuery dataTables
       
  1005 		 */
       
  1006 		datatable: function(element) {
       
  1007 			var tables = $('.datatable', element);
       
  1008 			if (tables.length > 0) {
       
  1009 				ams.ajax && ams.ajax.check($.fn.dataTable,
       
  1010 										   ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js',
       
  1011 										   function() {
       
  1012 											   ams.ajax.check($.fn.dataTableExt.oPagination.bootstrap_full,
       
  1013 															  ams.baseURL + 'myams-dataTables' + ams.devext + '.js',
       
  1014 															  function() {
       
  1015 																  $(tables).each(function() {
       
  1016 																	  var table = $(this);
       
  1017 																	  var data = table.data();
       
  1018 																	  var extensions = (data.amsDatatableExtensions || '').split(/\s+/);
       
  1019 																	  // Check DOM elements
       
  1020 																	  var sDom = data.amsDatatableSdom ||
       
  1021 																		  "W" +
       
  1022 																		  ((extensions.indexOf('colreorder') >= 0 ||
       
  1023 																			  extensions.indexOf('colreorderwithresize') >= 0) ? 'R' : '') +
       
  1024 																		  "<'dt-top-row'" +
       
  1025 																		  (extensions.indexOf('colvis') >= 0 ? 'C' : '') +
       
  1026 																		  ((data.amsDatatablePagination === false ||
       
  1027 																			  data.amsDatatablePaginationSize === false) ? '' : 'L') +
       
  1028 																		  (data.amsDatatableGlobalFilter === false ? '' : 'F') +
       
  1029 																		  ">r<'dt-wrapper't" +
       
  1030 																		  (extensions.indexOf('scroller') >= 0 ? 'S' : '') +
       
  1031 																		  "><'dt-row dt-bottom-row'<'row'<'col-sm-6'" +
       
  1032 																		  (data.amsDatatableInformation === false ? '' : 'i') +
       
  1033 																		  "><'col-sm-6 text-right'p>>";
       
  1034 
       
  1035 																	  var index;
       
  1036 																	  // Check initial sorting
       
  1037 																	  var sorting = data.amsDatatableSorting;
       
  1038 																	  if (typeof (sorting) === 'string') {
       
  1039 																		  var sortings = sorting.split(';');
       
  1040 																		  sorting = [];
       
  1041 																		  for (index = 0; index < sortings.length; index++) {
       
  1042 																			  var colSorting = sortings[index].split(',');
       
  1043 																			  colSorting[0] = parseInt(colSorting[0]);
       
  1044 																			  sorting.push(colSorting);
       
  1045 																		  }
       
  1046 																	  }
       
  1047 																	  // Check columns sortings
       
  1048 																	  var columns = [];
       
  1049 																	  var column;
       
  1050 																	  var sortables = $('th', table).listattr('data-ams-datatable-sortable');
       
  1051 																	  for (index = 0; index < sortables.length; index++) {
       
  1052 																		  var sortable = sortables[index];
       
  1053 																		  if (sortable !== undefined) {
       
  1054 																			  column = columns[index] || {};
       
  1055 																			  column.bSortable = typeof (sortable) === 'string' ? JSON.parse(sortable) : sortable;
       
  1056 																			  columns[index] = column;
       
  1057 																		  } else {
       
  1058 																			  columns[index] = columns[index] || {};
       
  1059 																		  }
       
  1060 																	  }
       
  1061 																	  // Check columns types
       
  1062 																	  var sortTypes = $('th', table).listattr('data-ams-datatable-stype');
       
  1063 																	  for (index = 0; index < sortTypes.length; index++) {
       
  1064 																		  var sortType = sortTypes[index];
       
  1065 																		  if (sortType) {
       
  1066 																			  column = columns[index] || {};
       
  1067 																			  column.sType = sortType;
       
  1068 																			  columns[index] = column;
       
  1069 																		  } else {
       
  1070 																			  columns[index] = columns[index] || {};
       
  1071 																		  }
       
  1072 																	  }
       
  1073 																	  // Set options
       
  1074 																	  var dataOptions = {
       
  1075 																		  bJQueryUI: false,
       
  1076 																		  bServerSide: data.amsDatatableServerSide || false,
       
  1077 																		  sAjaxSource: data.amsDatatableServerSide === true ? data.amsDatatableAjaxSource : undefined,
       
  1078 																		  sServerMethod: data.amsDatatableServerSide === true ? 'POST' : undefined,
       
  1079 																		  bFilter: data.amsDatatableGlobalFilter !== false || extensions.indexOf('columnfilter') >= 0,
       
  1080 																		  bPaginate: data.amsDatatablePagination !== false,
       
  1081 																		  bInfo: data.amsDatatableInfo !== false,
       
  1082 																		  bSort: data.amsDatatableSort !== false,
       
  1083 																		  aaSorting: sorting,
       
  1084 																		  aoColumns: columns.length > 0 ? columns : undefined,
       
  1085 																		  bDeferRender: true,
       
  1086 																		  bAutoWidth: false,
       
  1087 																		  iDisplayLength: data.amsDatatableDisplayLength || 25,
       
  1088 																		  sPaginationType: data.amsDatatablePaginationType || 'bootstrap_full',
       
  1089 																		  sDom: sDom,
       
  1090 																		  oLanguage: ams.plugins && ams.plugins.i18n.datatables,
       
  1091 																		  fnInitComplete: function(oSettings, json) {
       
  1092 																			  $('.ColVis_Button').addClass('btn btn-default btn-sm')
       
  1093 																				  .html(((ams.plugins && ams.plugins.i18n.datatables.sColumns) || "Columns") +
       
  1094 																							' <i class="fa fa-fw fa-caret-down"></i>');
       
  1095 																		  }
       
  1096 																	  };
       
  1097 																	  var settings = $.extend({}, dataOptions, data.amsDatatableOptions);
       
  1098 																	  var checkers = [];
       
  1099 																	  var sources = [];
       
  1100 																	  var callbacks = [];
       
  1101 																	  if (extensions.length > 0) {
       
  1102 																		  for (index = 0; index < extensions.length; index++) {
       
  1103 																			  switch (extensions[index]) {
       
  1104 																				  case 'autofill':
       
  1105 																					  checkers.push($.fn.dataTable.AutoFill);
       
  1106 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-autoFill' + ams.devext + '.js');
       
  1107 																					  break;
       
  1108 																				  case 'columnfilter':
       
  1109 																					  checkers.push($.fn.columnFilter);
       
  1110 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-columnFilter' + ams.devext + '.js');
       
  1111 																					  break;
       
  1112 																				  case 'colreorder':
       
  1113 																					  checkers.push($.fn.dataTable.ColReorder);
       
  1114 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorder' + ams.devext + '.js');
       
  1115 																					  break;
       
  1116 																				  case 'colreorderwithresize':
       
  1117 																					  checkers.push(window.ColReorder);
       
  1118 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colReorderWithResize' + ams.devext + '.js');
       
  1119 																					  break;
       
  1120 																				  case 'colvis':
       
  1121 																					  checkers.push($.fn.dataTable.ColVis);
       
  1122 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-colVis' + ams.devext + '.js');
       
  1123 																					  callbacks.push(function() {
       
  1124 																						  var cvDefault = {
       
  1125 																							  activate: 'click',
       
  1126 																							  sAlign: 'right'
       
  1127 																						  };
       
  1128 																						  settings.oColVis = $.extend({}, cvDefault, data.amsDatatableColvisOptions);
       
  1129 																					  });
       
  1130 																					  break;
       
  1131 																				  case 'editable':
       
  1132 																					  checkers.push($.fn.editable);
       
  1133 																					  sources.push(ams.baseURL + 'ext/jquery-jeditable' + ams.devext + '.js');
       
  1134 																					  checkers.push($.fn.makeEditable);
       
  1135 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-editable' + ams.devext + '.js');
       
  1136 																					  break;
       
  1137 																				  case 'fixedcolumns':
       
  1138 																					  checkers.push($.fn.dataTable.FixedColumns);
       
  1139 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedColumns' + ams.devext + '.js');
       
  1140 																					  break;
       
  1141 																				  case 'fixedheader':
       
  1142 																					  checkers.push($.fn.dataTable.Fixedheader);
       
  1143 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-fixedHeader' + ams.devext + '.js');
       
  1144 																					  break;
       
  1145 																				  case 'keytable':
       
  1146 																					  checkers.push(window.keyTable);
       
  1147 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-keyTable' + ams.devext + '.js');
       
  1148 																					  break;
       
  1149 																				  case 'rowgrouping':
       
  1150 																					  checkers.push($.fn.rowGrouping);
       
  1151 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-rowGrouping' + ams.devext + '.js');
       
  1152 																					  break;
       
  1153 																				  case 'rowreordering':
       
  1154 																					  checkers.push($.fn.rowReordering);
       
  1155 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-rowReordering' + ams.devext + '.js');
       
  1156 																					  break;
       
  1157 																				  case 'scroller':
       
  1158 																					  checkers.push($.fn.dataTable.Scroller);
       
  1159 																					  sources.push(ams.baseURL + 'ext/jquery-dataTables-scroller' + ams.devext + '.js');
       
  1160 																					  break;
       
  1161 																				  default:
       
  1162 																					  break;
       
  1163 																			  }
       
  1164 																		  }
       
  1165 																	  }
       
  1166 
       
  1167 																	  function initTable() {
       
  1168 																		  settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings;
       
  1169 																		  try {  // Some settings can easily generate DataTables exceptions...
       
  1170 																			  var plugin = table.dataTable(settings);
       
  1171 																			  ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings);
       
  1172 																			  if (extensions.length > 0) {
       
  1173 																				  for (index = 0; index < extensions.length; index++) {
       
  1174 																					  switch (extensions[index]) {
       
  1175 																						  case 'autofill':
       
  1176 																							  var afSettings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill);
       
  1177 																							  afSettings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, afSettings) || afSettings;
       
  1178 																							  table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined ?
       
  1179 																								  new $.fn.dataTable.AutoFill(table, afSettings)
       
  1180 																								  : ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, afSettings));
       
  1181 																							  break;
       
  1182 																						  case 'columnfilter':
       
  1183 																							  var cfDefault = {
       
  1184 																								  sPlaceHolder: 'head:after'
       
  1185 																							  };
       
  1186 																							  var cfSettings = $.extend({}, cfDefault, data.amsDatatableColumnfilterOptions, settings.columnfilter);
       
  1187 																							  cfSettings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cfSettings) || cfSettings;
       
  1188 																							  table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined ?
       
  1189 																								  plugin.columnFilter(cfSettings)
       
  1190 																								  : ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cfSettings));
       
  1191 																							  break;
       
  1192 																						  case 'editable':
       
  1193 																							  var edSettings = $.extend({}, data.amsDatatableEditableOptions, settings.editable);
       
  1194 																							  edSettings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, edSettings) || edSettings;
       
  1195 																							  table.data('ams-editable', data.amsDatatableEditableConstructor === undefined ?
       
  1196 																								  table.makeEditable(edSettings)
       
  1197 																								  : ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, edSettings));
       
  1198 																							  break;
       
  1199 																						  case 'fixedcolumns':
       
  1200 																							  var fcSettings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns);
       
  1201 																							  fcSettings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fcSettings) || fcSettings;
       
  1202 																							  table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined ?
       
  1203 																								  new $.fn.dataTable.FixedColumns(table, fcSettings)
       
  1204 																								  : ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fcSettings));
       
  1205 																							  break;
       
  1206 																						  case 'fixedheader':
       
  1207 																							  var fhSettings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader);
       
  1208 																							  fhSettings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fhSettings) || fhSettings;
       
  1209 																							  table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined ?
       
  1210 																								  new $.fn.dataTable.FixedHeader(table, fhSettings)
       
  1211 																								  : ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fhSettings));
       
  1212 																							  break;
       
  1213 																						  case 'keytable':
       
  1214 																							  var ktDefault = {
       
  1215 																								  table: table.get(0),
       
  1216 																								  datatable: plugin
       
  1217 																							  };
       
  1218 																							  var ktSettings = $.extend({}, ktDefault, data.amsDatatableKeytableOptions, settings.keytable);
       
  1219 																							  ktSettings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, ktSettings) || ktSettings;
       
  1220 																							  table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined ?
       
  1221 																								  new KeyTable(ktSettings)
       
  1222 																								  : ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, ktSettings));
       
  1223 																							  break;
       
  1224 																						  case 'rowgrouping':
       
  1225 																							  var rgSettings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping);
       
  1226 																							  rgSettings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rgSettings) || rgSettings;
       
  1227 																							  table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined ?
       
  1228 																								  table.rowGrouping(rgSettings)
       
  1229 																								  : ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rgSettings));
       
  1230 																							  break;
       
  1231 																						  case 'rowreordering':
       
  1232 																							  var rrSettings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering);
       
  1233 																							  rrSettings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rrSettings) || rrSettings;
       
  1234 																							  table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined ?
       
  1235 																								  table.rowReordering(rrSettings)
       
  1236 																								  : ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rrSettings));
       
  1237 																							  break;
       
  1238 																						  default:
       
  1239 																							  break;
       
  1240 																					  }
       
  1241 																				  }
       
  1242 																			  }
       
  1243 																			  if (data.amsDatatableFinalizeCallback) {
       
  1244 																				  var finalizers = data.amsDatatableFinalizeCallback.split(/\s+/);
       
  1245 																				  if (finalizers.length > 0) {
       
  1246 																					  for (index = 0; index < finalizers.length; index++) {
       
  1247 																						  ams.executeFunctionByName(finalizers[index], table, plugin, settings);
       
  1248 																					  }
       
  1249 																				  }
       
  1250 																			  }
       
  1251 																		  } catch (e) {
       
  1252 																		  }
       
  1253 																	  }
       
  1254 
       
  1255 																	  callbacks.push(initTable);
       
  1256 																	  ams.ajax && ams.ajax.check(checkers, sources, callbacks);
       
  1257 																  });
       
  1258 															  });
       
  1259 										   });
       
  1260 			}
       
  1261 		},
       
  1262 
       
  1263 		/**
       
  1264 		 * TableDND plug-in
       
  1265 		 */
       
  1266 		tablednd: function(element) {
       
  1267 			var tables = $('.table-dnd', element);
       
  1268 			if (tables.length > 0) {
       
  1269 				ams.ajax && ams.ajax.check($.fn.tableDnD,
       
  1270 										   ams.baseURL + 'ext/jquery-tablednd' + ams.devext + '.js',
       
  1271 										   function() {
       
  1272 											   tables.each(function() {
       
  1273 												   var table = $(this);
       
  1274 												   var data = table.data();
       
  1275 												   if (data.amsTabledndDragHandle) {
       
  1276 													   $('tr', table).addClass('no-drag-handle');
       
  1277 												   } else {
       
  1278 													   $(table).on('mouseover', 'tr', function() {
       
  1279 														   $(this.cells[0]).addClass('drag-handle');
       
  1280 													   }).on('mouseout', 'tr', function() {
       
  1281 														   $(this.cells[0]).removeClass('drag-handle');
       
  1282 													   });
       
  1283 												   }
       
  1284 												   var dataOptions = {
       
  1285 													   onDragClass: data.amsTabledndDragClass || 'dragging-row',
       
  1286 													   onDragStart: ams.getFunctionByName(data.amsTabledndDragStart),
       
  1287 													   dragHandle: data.amsTabledndDragHandle,
       
  1288 													   scrollAmount: data.amsTabledndScrollAmount,
       
  1289 													   onAllowDrop: data.amsTabledndAllowDrop,
       
  1290 													   onDrop: ams.getFunctionByName(data.amsTabledndDrop) || function(dnd_table, row) {
       
  1291 														   var target = data.amsTabledndDropTarget;
       
  1292 														   if (target) {
       
  1293 															   // Disable row click handler
       
  1294 															   $(row).data('ams-disabled-handlers', 'click');
       
  1295 															   try {
       
  1296 																   var rows = [];
       
  1297 																   $(dnd_table.rows).each(function() {
       
  1298 																	   var rowId = $(this).data('ams-element-name');
       
  1299 																	   if (rowId) {
       
  1300 																		   rows.push(rowId);
       
  1301 																	   }
       
  1302 																   });
       
  1303 																   var localTarget = ams.getFunctionByName(target);
       
  1304 																   if (typeof (localTarget) === 'function') {
       
  1305 																	   localTarget.call(table, dnd_table, rows);
       
  1306 																   } else {
       
  1307 																	   if (!target.startsWith(window.location.protocol)) {
       
  1308 																		   var location = data.amsLocation;
       
  1309 																		   if (location) {
       
  1310 																			   target = location + '/' + target;
       
  1311 																		   }
       
  1312 																	   }
       
  1313 																	   ams.ajax && ams.ajax.post(target, {names: JSON.stringify(rows)}, function(result, status) {
       
  1314 																		   if (result.status !== 'success') {
       
  1315 																			   ams.ajax.handleJSON(result);
       
  1316 																		   }
       
  1317 																	   });
       
  1318 																   }
       
  1319 															   } finally {
       
  1320 																   // Restore row click handler
       
  1321 																   setTimeout(function() {
       
  1322 																	   $(row).removeData('ams-disabled-handlers');
       
  1323 																   }, 50);
       
  1324 															   }
       
  1325 														   }
       
  1326 														   return false;
       
  1327 													   }
       
  1328 												   };
       
  1329 												   var settings = $.extend({}, dataOptions, data.amsTabledndOptions);
       
  1330 												   settings = ams.executeFunctionByName(data.amsTabledndInitCallback, table, settings) || settings;
       
  1331 												   var plugin = table.tableDnD(settings);
       
  1332 												   ams.executeFunctionByName(data.amsTabledndAfterInitCallback, table, plugin, settings);
       
  1333 											   });
       
  1334 										   });
       
  1335 			}
       
  1336 		},
       
  1337 
       
  1338 		/**
       
  1339 		 * Wizard plug-in
       
  1340 		 */
       
  1341 		wizard: function(element) {
       
  1342 			var wizards = $('.wizard', element);
       
  1343 			if (wizards.length > 0) {
       
  1344 				ams.ajax && ams.ajax.check($.fn.bootstrapWizard,
       
  1345 										   ams.baseURL + 'ext/bootstrap-wizard-1.4.2' + ams.devext + '.js',
       
  1346 										   function() {
       
  1347 											   wizards.each(function() {
       
  1348 												   var wizard = $(this);
       
  1349 												   var data = wizard.data();
       
  1350 												   var dataOptions = {
       
  1351 													   withVisible: data.amsWizardWithVisible === undefined ? true : data.amsWizardWithVisible,
       
  1352 													   tabClass: data.amsWizardTabClass,
       
  1353 													   firstSelector: data.amsWizardFirstSelector,
       
  1354 													   previousSelector: data.amsWizardPreviousSelector,
       
  1355 													   nextSelector: data.amsWizardNextSelector,
       
  1356 													   lastSelector: data.amsWizardLastSelector,
       
  1357 													   finishSelector: data.amsWizardFinishSelector,
       
  1358 													   backSelector: data.amsWizardBackSelector,
       
  1359 													   onInit: ams.getFunctionByName(data.amsWizardInit),
       
  1360 													   onShow: ams.getFunctionByName(data.amsWizardShow),
       
  1361 													   onNext: ams.getFunctionByName(data.amsWizardNext),
       
  1362 													   onPrevious: ams.getFunctionByName(data.amsWizardPrevious),
       
  1363 													   onFirst: ams.getFunctionByName(data.amsWizardFirst),
       
  1364 													   onLast: ams.getFunctionByName(data.amsWizardLast),
       
  1365 													   onBack: ams.getFunctionByName(data.amsWizardBack),
       
  1366 													   onFinish: ams.getFunctionByName(data.amsWizardFinish),
       
  1367 													   onTabChange: ams.getFunctionByName(data.amsWizardTabChange),
       
  1368 													   onTabClick: ams.getFunctionByName(data.amsWizardTabClick),
       
  1369 													   onTabShow: ams.getFunctionByName(data.amsWizardTabShow)
       
  1370 												   };
       
  1371 												   var settings = $.extend({}, dataOptions, data.amsWizardOptions);
       
  1372 												   settings = ams.executeFunctionByName(data.amsWizardInitCallback, wizard, settings) || settings;
       
  1373 												   var plugin = wizard.bootstrapWizard(settings);
       
  1374 												   ams.executeFunctionByName(data.amsWizardAfterInitCallback, wizard, plugin, settings);
       
  1375 											   });
       
  1376 										   });
       
  1377 			}
       
  1378 		},
       
  1379 
       
  1380 		/**
       
  1381 		 * TinyMCE plug-in
       
  1382 		 */
       
  1383 		tinymce: function(element) {
       
  1384 
       
  1385 			function cleanEditors() {
       
  1386 				$('.tinymce', $(this)).each(function() {
       
  1387 					var editor = tinymce.get($(this).attr('id'));
       
  1388 					if (editor) {
       
  1389 						editor.remove();
       
  1390 					}
       
  1391 				});
       
  1392 			}
       
  1393 
       
  1394 			var editors = $('.tinymce', element);
       
  1395 			if (editors.length > 0) {
       
  1396 				var baseURL = ams.baseURL + 'ext/tinymce' + (ams.devmode ? '/dev' : '');
       
  1397 				ams.ajax && ams.ajax.check(window.tinymce,
       
  1398 										   baseURL + '/tinymce' + ams.devext + '.js',
       
  1399 										   function(first_load) {
       
  1400 
       
  1401 											   function initEditors() {
       
  1402 												   editors.each(function() {
       
  1403 													   var editor = $(this);
       
  1404 													   var data = editor.data();
       
  1405 													   var dataOptions = {
       
  1406 														   theme: data.amsTinymceTheme || "modern",
       
  1407 														   language: ams.lang,
       
  1408 														   menubar: data.amsTinymceMenubar !== false,
       
  1409 														   statusbar: data.amsTinymceStatusbar !== false,
       
  1410 														   plugins: data.amsTinymcePlugins || [
       
  1411 															   "advlist autosave autolink lists link charmap print preview hr anchor pagebreak",
       
  1412 															   "searchreplace wordcount visualblocks visualchars code fullscreen",
       
  1413 															   "insertdatetime nonbreaking save table contextmenu directionality",
       
  1414 															   "emoticons paste textcolor colorpicker textpattern autoresize"
       
  1415 														   ],
       
  1416 														   toolbar: data.amsTinymceToolbar,
       
  1417 														   toolbar1: data.amsTinymceToolbar1 === false ? false : data.amsTinymceToolbar1 ||
       
  1418 															   "undo redo | pastetext | styleselect | bold italic | alignleft " +
       
  1419 															   "aligncenter alignright alignjustify | bullist numlist " +
       
  1420 															   "outdent indent",
       
  1421 														   toolbar2: data.amsTinymceToolbar2 === false ? false : data.amsTinymceToolbar2 ||
       
  1422 															   "forecolor backcolor emoticons | charmap link image media | " +
       
  1423 															   "fullscreen preview print | code",
       
  1424 														   content_css: data.amsTinymceContentCss,
       
  1425 														   formats: data.amsTinymceFormats,
       
  1426 														   style_formats: data.amsTinymceStyleFormats,
       
  1427 														   block_formats: data.amsTinymceBlockFormats,
       
  1428 														   valid_classes: data.amsTinymceValidClasses,
       
  1429 														   image_advtab: true,
       
  1430 														   image_list: ams.getFunctionByName(data.amsTinymceImageList) || data.amsTinymceImageList,
       
  1431 														   image_class_list: data.amsTinymceImageClassList,
       
  1432 														   link_list: ams.getFunctionByName(data.amsTinymceLinkList) || data.amsTinymceLinkList,
       
  1433 														   link_class_list: data.amsTinymceLinkClassList,
       
  1434 														   paste_as_text: data.amsTinymcePasteAsText === undefined ? true : data.amsTinymcePasteAsText,
       
  1435 														   paste_auto_cleanup_on_paste: data.amsTinymcePasteAutoCleanup === undefined ? true : data.amsTinymcePasteAutoCleanup,
       
  1436 														   paste_strip_class_attributes: data.amsTinymcePasteStripClassAttributes || 'all',
       
  1437 														   paste_remove_spans: data.amsTinymcePaseRemoveSpans === undefined ? true : data.amsTinymcePasteRemoveSpans,
       
  1438 														   paste_remove_styles: data.amsTinymcePasteRemoveStyles === undefined ? true : data.amsTinymcePasteRemoveStyles,
       
  1439 														   height: data.amsTinymceHeight || 50,
       
  1440 														   min_height: 50,
       
  1441 														   resize: true,
       
  1442 														   autoresize_min_height: 50,
       
  1443 														   autoresize_max_height: 500
       
  1444 													   };
       
  1445 													   if (data.amsTinymceExternalPlugins) {
       
  1446 														   var names = data.amsTinymceExternalPlugins.split(/\s+/);
       
  1447 														   for (var index in names) {
       
  1448 															   if (!names.hasOwnProperty(index)) {
       
  1449 																   continue;
       
  1450 															   }
       
  1451 															   var pluginSrc = editor.data('ams-tinymce-plugin-' + names[index]);
       
  1452 															   tinymce.PluginManager.load(names[index], ams.getSource(pluginSrc));
       
  1453 														   }
       
  1454 													   }
       
  1455 													   var settings = $.extend({}, dataOptions, data.amsTinymceOptions);
       
  1456 													   settings = ams.executeFunctionByName(data.amsTinymceInitCallback, editor, settings) || settings;
       
  1457 													   var plugin = editor.tinymce(settings);
       
  1458 													   ams.executeFunctionByName(data.amsTinymceAfterInitCallback, editor, plugin, settings);
       
  1459 												   });
       
  1460 											   }
       
  1461 
       
  1462 											   if (first_load) {
       
  1463 												   ams.getScript(baseURL + '/jquery.tinymce' + ams.devext + '.js', function() {
       
  1464 													   tinymce.baseURL = baseURL;
       
  1465 													   tinymce.suffix = ams.devext;
       
  1466 													   ams.skin && ams.skin.registerCleanCallback(cleanEditors);
       
  1467 													   initEditors();
       
  1468 												   });
       
  1469 											   } else {
       
  1470 												   initEditors();
       
  1471 											   }
       
  1472 										   });
       
  1473 			}
       
  1474 		},
       
  1475 
       
  1476 		/**
       
  1477 		 * HTML editor with syntax highlight
       
  1478 		 */
       
  1479 		editor: function(element) {
       
  1480 			var editors = $('.text-editor textarea', element);
       
  1481 			if (editors.length > 0) {
       
  1482 				ams.ajax && ams.ajax.check(globals.ace,
       
  1483 										   ams.baseURL + 'ext/ace/ace.js',
       
  1484 										   function(first_load) {
       
  1485 
       
  1486 												var initEditors = function() {
       
  1487 													globals.ace_loaded = true;
       
  1488 													editors.each(function() {
       
  1489 
       
  1490 														// Find textarea attributes
       
  1491 														var textarea = $(this),
       
  1492 															widget = textarea.parents('.text-editor'),
       
  1493 															data = widget.data(),
       
  1494 															modeList = ace.require('ace/ext/modelist'),
       
  1495 															mode = data.amsEditorMode || modeList.getModeForPath(data.amsEditorFilename || 'editor.txt').mode;
       
  1496 
       
  1497 														// Create editor DIV
       
  1498 														var textEditor = $('<div>', {
       
  1499 															position: 'absolute',
       
  1500 															width: textarea.width(),
       
  1501 															height: textarea.height(),
       
  1502 															'class': textarea.attr('class')
       
  1503 														}).insertBefore(textarea);
       
  1504 														textarea.css('display', 'none');
       
  1505 
       
  1506 														// Initialize editor
       
  1507 														var editor = ace.edit(textEditor[0]),
       
  1508 															dataOptions = {
       
  1509 																mode: mode,
       
  1510 																tabSize: 4,
       
  1511 																useSoftTabs: false,
       
  1512 																showGutter: true,
       
  1513 																showLineNumbers: true,
       
  1514 																printMargin: 132,
       
  1515 																showInvisibles: true
       
  1516 															},
       
  1517 															settings = $.extend({}, dataOptions, data.amsEditorOptions);
       
  1518 														settings = ams.executeFunctionByName(data.amsEditorInitCallback, textarea, settings) || settings;
       
  1519 														editor.setOptions(settings);
       
  1520 														editor.session.setValue(textarea.val());
       
  1521 														editor.session.on('change', function() {
       
  1522 															textarea.val(editor.session.getValue());
       
  1523 														});
       
  1524 														widget.data('editor', editor);
       
  1525 														ams.executeFunctionByName(data.amsEditorAfterInitCallback, textarea, editor, settings);
       
  1526 													});
       
  1527 												};
       
  1528 
       
  1529 												if (first_load) {
       
  1530 													ace.config.set('basePath', ams.baseURL + 'ext/ace');
       
  1531 													ams.ajax.check(globals.ace_loaded, [
       
  1532 														ams.baseURL + 'ext/ace/ext-modelist.js'
       
  1533 													], initEditors);
       
  1534 												} else {
       
  1535 													initEditors();
       
  1536 												}
       
  1537 										   });
       
  1538 			}
       
  1539 		},
       
  1540 
       
  1541 		/**
       
  1542 		 * Image area select plug-in
       
  1543 		 */
       
  1544 		imgareaselect: function(element) {
       
  1545 			var images = $('.imgareaselect', element);
       
  1546 			if (images.length > 0) {
       
  1547 				ams.ajax && ams.ajax.check($.fn.imgAreaSelect,
       
  1548 										   ams.baseURL + 'ext/jquery-imgareaselect-0.9.11-rc1' + ams.devext + '.js',
       
  1549 										   function() {
       
  1550 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-imgareaselect' + ams.devext + '.css',
       
  1551 														  'jquery-imgareaselect',
       
  1552 														  function() {
       
  1553 															  images.each(function() {
       
  1554 																  var image = $(this);
       
  1555 																  var data = image.data();
       
  1556 																  var parent = data.amsImgareaselectParent ? image.parents(data.amsImgareaselectParent) : 'body';
       
  1557 																  var dataOptions = {
       
  1558 																	  instance: true,
       
  1559 																	  handles: true,
       
  1560 																	  parent: parent,
       
  1561 																	  x1: data.amsImgareaselectX1 || 0,
       
  1562 																	  y1: data.amsImgareaselectY1 || 0,
       
  1563 																	  x2: data.amsImgareaselectX2 || data.amsImgareaselectImageWidth,
       
  1564 																	  y2: data.amsImgareaselectY2 || data.amsImgareaselectImageHeight,
       
  1565 																	  imageWidth: data.amsImgareaselectImageWidth,
       
  1566 																	  imageHeight: data.amsImgareaselectImageHeight,
       
  1567 																	  minWidth: 128,
       
  1568 																	  minHeight: 128,
       
  1569 																	  aspectRatio: data.amsImgareaselectRatio,
       
  1570 																	  onSelectEnd: ams.getFunctionByName(data.amsImgareaselectSelectEnd) || function(img, selection) {
       
  1571 																		  var target = data.amsImgareaselectTargetField || 'image_';
       
  1572 																		  $('input[name="' + target + 'x1"]', parent).val(selection.x1);
       
  1573 																		  $('input[name="' + target + 'y1"]', parent).val(selection.y1);
       
  1574 																		  $('input[name="' + target + 'x2"]', parent).val(selection.x2);
       
  1575 																		  $('input[name="' + target + 'y2"]', parent).val(selection.y2);
       
  1576 																	  }
       
  1577 																  };
       
  1578 																  var settings = $.extend({}, dataOptions, data.amsImgareaselectOptions);
       
  1579 																  settings = ams.executeFunctionByName(data.amsImgareaselectInitCallback, image, settings) || settings;
       
  1580 																  var plugin = image.imgAreaSelect(settings);
       
  1581 																  ams.executeFunctionByName(data.amsImgareaselectAfterInitCallback, image, plugin, settings);
       
  1582 																  // Add update timeout when plug-in is displayed into a modal dialog
       
  1583 																  setTimeout(function() {
       
  1584 																	  plugin.update();
       
  1585 																  }, 250);
       
  1586 															  });
       
  1587 														  });
       
  1588 										   });
       
  1589 			}
       
  1590 		},
       
  1591 
       
  1592 		/**
       
  1593 		 * FancyBox plug-in
       
  1594 		 */
       
  1595 		fancybox: function(element) {
       
  1596 			var fancyboxes = $('.fancybox', element);
       
  1597 			if (fancyboxes.length > 0) {
       
  1598 				ams.ajax && ams.ajax.check($.fn.fancybox,
       
  1599 										   ams.baseURL + 'ext/jquery-fancybox-2.1.5' + ams.devext + '.js',
       
  1600 										   function() {
       
  1601 											   ams.getCSS(ams.baseURL + '../css/ext/jquery-fancybox-2.1.5' + ams.devext + '.css',
       
  1602 														  'jquery-fancybox',
       
  1603 														  function() {
       
  1604 															  fancyboxes.each(function() {
       
  1605 																  var fancybox = $(this);
       
  1606 																  var data = fancybox.data();
       
  1607 																  var elements = fancybox;
       
  1608 																  var index,
       
  1609 																	  helper;
       
  1610 																  if (data.amsFancyboxElements) {
       
  1611 																	  elements = $(data.amsFancyboxElements, fancybox);
       
  1612 																  }
       
  1613 																  var helpers = (data.amsFancyboxHelpers || '').split(/\s+/);
       
  1614 																  if (helpers.length > 0) {
       
  1615 																	  for (index = 0; index < helpers.length; index++) {
       
  1616 																		  helper = helpers[index];
       
  1617 																		  switch (helper) {
       
  1618 																			  case 'buttons':
       
  1619 																				  ams.ajax && ams.ajax.check($.fancybox.helpers.buttons,
       
  1620 																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-buttons' + ams.devext + '.js');
       
  1621 																				  break;
       
  1622 																			  case 'thumbs':
       
  1623 																				  ams.ajax && ams.ajax.check($.fancybox.helpers.thumbs,
       
  1624 																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-thumbs' + ams.devext + '.js');
       
  1625 																				  break;
       
  1626 																			  case 'media':
       
  1627 																				  ams.ajax && ams.ajax.check($.fancybox.helpers.media,
       
  1628 																											 ams.baseURL + 'ext/fancybox-helpers/fancybox-media' + ams.devext + '.js');
       
  1629 																				  break;
       
  1630 																			  default:
       
  1631 																				  break;
       
  1632 																		  }
       
  1633 																	  }
       
  1634 																  }
       
  1635 																  var dataOptions = {
       
  1636 																	  type: data.amsFancyboxType,
       
  1637 																	  padding: data.amsFancyboxPadding || 10,
       
  1638 																	  margin: data.amsFancyboxMargin || 10,
       
  1639 																	  loop: data.amsFancyboxLoop,
       
  1640 																	  beforeLoad: ams.getFunctionByName(data.amsFancyboxBeforeLoad) || function() {
       
  1641 																		  var title;
       
  1642 																		  if (data.amsFancyboxTitleGetter) {
       
  1643 																			  title = ams.executeFunctionByName(data.amsFancyboxTitleGetter, this);
       
  1644 																		  }
       
  1645 																		  if (!title) {
       
  1646 																			  var content = $('*:first', this.element);
       
  1647 																			  title = content.attr('original-title') || content.attr('title');
       
  1648 																			  if (!title) {
       
  1649 																				  title = $(this.element).attr('original-title') || $(this.element).attr('title');
       
  1650 																			  }
       
  1651 																		  }
       
  1652 																		  this.title = title;
       
  1653 																	  },
       
  1654 																	  afterLoad: ams.getFunctionByName(data.amsFancyboxAfterLoad),
       
  1655 																	  helpers: {
       
  1656 																		  title: {
       
  1657 																			  type: 'inside'
       
  1658 																		  }
       
  1659 																	  }
       
  1660 																  };
       
  1661 																  if (helpers.length > 0) {
       
  1662 																	  for (index = 0; index < helpers.length; index++) {
       
  1663 																		  helper = helpers[index];
       
  1664 																		  switch (helper) {
       
  1665 																			  case 'buttons':
       
  1666 																				  dataOptions.helpers.buttons = {
       
  1667 																					  position: data.amsFancyboxButtonsPosition || 'top'
       
  1668 																				  };
       
  1669 																				  break;
       
  1670 																			  case 'thumbs':
       
  1671 																				  dataOptions.helpers.thumbs = {
       
  1672 																					  width: data.amsFancyboxThumbsWidth || 50,
       
  1673 																					  height: data.amsFancyboxThumbsHeight || 50
       
  1674 																				  };
       
  1675 																				  break;
       
  1676 																			  case 'media':
       
  1677 																				  dataOptions.helpers.media = true;
       
  1678 																				  break;
       
  1679 																		  }
       
  1680 																	  }
       
  1681 																  }
       
  1682 																  var settings = $.extend({}, dataOptions, data.amsFancyboxOptions);
       
  1683 																  settings = ams.executeFunctionByName(data.amsFancyboxInitCallback, fancybox, settings) || settings;
       
  1684 																  var plugin = elements.fancybox(settings);
       
  1685 																  ams.executeFunctionByName(data.amsFancyboxAfterInitCallback, fancybox, plugin, settings);
       
  1686 															  });
       
  1687 														  });
       
  1688 										   });
       
  1689 			}
       
  1690 		},
       
  1691 
       
  1692 		/**
       
  1693 		 * Flot charts
       
  1694 		 */
       
  1695 		chart: function(element) {
       
  1696 			var charts = $('.chart', element);
       
  1697 			if (charts.length > 0) {
       
  1698 				ams.ajax && ams.ajax.check([window.Flot, $.color],
       
  1699 					[ams.baseURL + 'ext/flot/jquery.canvaswrapper' + ams.devext + '.js',
       
  1700 					 ams.baseURL + 'ext/flot/jquery.colorhelpers' + ams.devext + '.js'],
       
  1701 					function () {
       
  1702 						ams.ajax.check($.fn.plot,
       
  1703 							ams.baseURL + 'ext/flot/jquery.flot' + ams.devext + '.js',
       
  1704 							function () {
       
  1705 								charts.each(function () {
       
  1706 
       
  1707 									var chart = $(this),
       
  1708 										data = chart.data(),
       
  1709 										dataOptions = {},
       
  1710 										plugin,
       
  1711 										flotPlugins = (data.amsChartPlugins || '').split(/\s+/);
       
  1712 
       
  1713 									function checkPlugin(plugin) {
       
  1714 										for (var index in $.plot.plugins) {
       
  1715 											if ($.plot.plugins.hasOwnProperty(index)) {
       
  1716 												var pluginInfo = $.plot.plugins[index];
       
  1717 												if (pluginInfo.name === plugin) {
       
  1718 													return pluginInfo;
       
  1719 												}
       
  1720 											}
       
  1721 										}
       
  1722 										return null;
       
  1723 									}
       
  1724 
       
  1725 									function initChart() {
       
  1726 										var settings = $.extend({}, dataOptions, data.amsChartOptions);
       
  1727 										settings = ams.executeFunctionByName(data.amsChartInitCallback, chart, settings) || settings;
       
  1728 										var chartData = data.amsChartData,
       
  1729 											chartDataLoader = data.amsChartDataLoader;
       
  1730 										if (chartDataLoader) {
       
  1731 											$.getJSON(chartDataLoader, chartData).done(function (data) {
       
  1732 												settings = $.extend({}, settings, data.settings);
       
  1733 												createChart(data.data, settings);
       
  1734 											});
       
  1735 										} else {
       
  1736 											createChart(data, settings);
       
  1737 										}
       
  1738 									}
       
  1739 
       
  1740 									function createChart(chartData, settings) {
       
  1741 										chartData = ams.executeFunctionByName(data.amsChartInitData, chart, chartData) || chartData;
       
  1742 										plugin = chart.plot(chartData, settings);
       
  1743 										ams.executeFunctionByName(data.amsChartAfterInitCallback, chart, plugin, settings);
       
  1744 									}
       
  1745 
       
  1746 									var deferred = [];
       
  1747 									if (flotPlugins.length > 0) {
       
  1748 										for (var index in flotPlugins) {
       
  1749 											if (flotPlugins.hasOwnProperty(index)) {
       
  1750 												var pluginName = flotPlugins[index];
       
  1751 												if (!checkPlugin(pluginName)) {
       
  1752 													deferred.push(ams.getScript(ams.baseURL + 'ext/flot/jquery.flot.' + pluginName + ams.devext + '.js'));
       
  1753 												}
       
  1754 											}
       
  1755 										}
       
  1756 									}
       
  1757 									if (deferred.length > 0) {
       
  1758 										$.when.apply($, deferred).then(function () {
       
  1759 											initChart();
       
  1760 										})
       
  1761 									} else {
       
  1762 										initChart();
       
  1763 									}
       
  1764 								});
       
  1765 							});
       
  1766 					});
       
  1767 			}
       
  1768 		},
       
  1769 
       
  1770 		/**
       
  1771 		 * Sparkline graphs
       
  1772 		 */
       
  1773 		graphs: function(element) {
       
  1774 			var graphs = $('.sparkline', element);
       
  1775 			if (graphs.length > 0) {
       
  1776 				ams.ajax && ams.ajax.check(ams.graphs,
       
  1777 										   ams.baseURL + 'myams-graphs' + ams.devext + '.js',
       
  1778 										   function() {
       
  1779 											   ams.graphs.init(graphs);
       
  1780 										   });
       
  1781 			}
       
  1782 		},
       
  1783 
       
  1784 		/**
       
  1785 		 * Custom scrollbars
       
  1786 		 */
       
  1787 		scrollbars: function(element) {
       
  1788 			var scrollbars = $('.scrollbar', element);
       
  1789 			if (scrollbars.length > 0) {
       
  1790 				ams.ajax && ams.ajax.check($.event.special.mousewheel,
       
  1791 										   ams.baseURL + 'ext/jquery-mousewheel.min.js',
       
  1792 										   function() {
       
  1793 											   ams.ajax.check($.fn.mCustomScrollbar,
       
  1794 															  ams.baseURL + 'ext/jquery-mCustomScrollbar' + ams.devext + '.js',
       
  1795 															  function() {
       
  1796 																  ams.getCSS(ams.baseURL + '../css/ext/jquery-mCustomScrollbar.css',
       
  1797 																			 'jquery-mCustomScrollbar',
       
  1798 																			 function() {
       
  1799 																				 scrollbars.each(function() {
       
  1800 																					 var scrollbar = $(this);
       
  1801 																					 var data = scrollbar.data();
       
  1802 																					 var dataOptions = {
       
  1803 																						 theme: data.amsScrollbarTheme || 'light'
       
  1804 																					 };
       
  1805 																					 var settings = $.extend({}, dataOptions, data.amsScrollbarOptions);
       
  1806 																					 settings = ams.executeFunctionByName(data.amsScrollbarInitCallback, scrollbar, settings) || settings;
       
  1807 																					 var plugin = scrollbar.mCustomScrollbar(settings);
       
  1808 																					 ams.executeFunctionByName(data.amsScrollbarAfterInitCallback, scrollbar, plugin, settings);
       
  1809 																				 });
       
  1810 																			 });
       
  1811 															  });
       
  1812 										   });
       
  1813 			}
       
  1814 		}
       
  1815 	});
       
  1816 
       
  1817 })(jQuery, this);