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