diff -r 89a28618a327 -r c628592aa86e src/pyams_skin/resources/js/myams.js --- a/src/pyams_skin/resources/js/myams.js Wed Oct 07 18:04:42 2015 +0200 +++ b/src/pyams_skin/resources/js/myams.js Wed Oct 07 18:06:06 2015 +0200 @@ -113,7 +113,7 @@ * Get object if it supports given CSS class, * otherwise looks for parents */ - objectWithClass: function(klass) { + objectOrParentWithClass: function(klass) { if (this.hasClass(klass)) return this; else @@ -595,6 +595,14 @@ msg = 1; } return msg; + }, + + copyToClipboard: function() { + return function() { + var source = $(this); + source.parents('.btn-group').removeClass('open'); + window.prompt(MyAMS.i18n.CLIPBOARD_COPY, source.text()); + } } }; @@ -1237,7 +1245,7 @@ if (!ams.form._checkSubmitValidators(form)) return false; // Remove remaining status messages - $('.alert, SPAN.state-error', form).remove(); + $('.alert-danger, SPAN.state-error', form).remove(); $('.state-error', form).removeClassPrefix('state-'); // Check submit button var button = $(form.data('ams-submit-button')); @@ -1694,8 +1702,11 @@ * Register a callback which should be called when a dialog is shown */ registerShownCallback: function(callback, element) { - var dialog = element.objectWithClass('modal-dialog'); - if (dialog.exists()) { + var dialog; + if (element) { + dialog = element.objectOrParentWithClass('modal-dialog'); + } + if (dialog && dialog.exists()) { var callbacks = dialog.data('shown-callbacks'); if (callbacks === undefined) { callbacks = []; @@ -1717,8 +1728,11 @@ * Register a callback which should be called when a dialog is closed */ registerHideCallback: function(callback, element) { - var dialog = element.objectWithClass('modal-dialog'); - if (dialog.exists()) { + var dialog; + if (element) { + dialog = element.objectOrParentWithClass('modal-dialog'); + } + if (dialog && dialog.exists()) { var callbacks = dialog.data('hide-callbacks'); if (callbacks === undefined) { callbacks = []; @@ -1841,27 +1855,27 @@ var modal = e.target; var viewport = $('.modal-viewport', modal); - if (viewport.length == 0) - return; - var maxHeight = parseInt(viewport.css('max-height')); - var barWidth = $.scrollbarWidth(); - if (viewport.height() == maxHeight) { - $('
').addClass('scrollmarker') - .addClass('top') - .css('top', 0) - .css('width', viewport.width() - barWidth) - .hide() - .appendTo(viewport); - $('').addClass('scrollmarker') - .addClass('bottom') - .css('top', maxHeight - 20) - .css('width', viewport.width() - barWidth) - .appendTo(viewport); - viewport.scroll(resetViewport); - viewport.off('resize') + if (viewport.exists()) { + var maxHeight = parseInt(viewport.css('max-height')); + var barWidth = $.scrollbarWidth(); + if (viewport.height() == maxHeight) { + $('').addClass('scrollmarker') + .addClass('top') + .css('top', 0) + .css('width', viewport.width() - barWidth) + .hide() + .appendTo(viewport); + $('').addClass('scrollmarker') + .addClass('bottom') + .css('top', maxHeight - 20) + .css('width', viewport.width() - barWidth) + .appendTo(viewport); + viewport.scroll(resetViewport); + viewport.off('resize') .on('resize', resetViewport); - } else { - $('.scrollmarker', viewport).remove(); + } else { + $('.scrollmarker', viewport).remove(); + } } // Call shown callbacks registered for this dialog @@ -2967,28 +2981,13 @@ ams.ajax.check($.fn.dataTable, ams.baseURL + 'ext/jquery-dataTables-1.9.4' + ams.devext + '.js', function(first_load) { - if (first_load) { - $.fn.dataTableExt.oSort['numeric-comma-asc'] = function(a, b) { - var x = a.replace(/,/, ".").replace(/ /g, ''); - var y = b.replace(/,/, ".").replace(/ /g, ''); - x = parseFloat(x); - y = parseFloat(y); - return ((x < y) ? -1 : ((x > y) ? 1 : 0)); - }; - $.fn.dataTableExt.oSort['numeric-comma-desc'] = function(a, b) { - var x = a.replace(/,/, ".").replace(/ /g, ''); - var y = b.replace(/,/, ".").replace(/ /g, ''); - x = parseFloat(x); - y = parseFloat(y); - return ((x < y) ? 1 : ((x > y) ? -1 : 0)); - }; - } $(tables).each(function() { ams.ajax.check($.fn.dataTableExt.oPagination['bootstrap_full'], ams.baseURL + 'myams-dataTables' + ams.devext + '.js'); 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 || @@ -3003,13 +3002,38 @@ "><'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 in sortings) { + var col_sorting = sortings[index].split(','); + col_sorting[0] = parseInt(col_sorting[0]); + sorting.push(col_sorting); + } + } + // Check columns types + var columns = []; + var sort_types = $('th', table).listattr('data-ams-datatable-stype'); + for (index in sort_types) { + var sort_type = sort_types[index]; + if (sort_type) { + var column = columns[index] || {}; + column.sType = sort_type; + columns[index] = column; + } + } + // Set options var data_options = { bJQueryUI: false, bFilter: data.amsDatatableGlobalFilter !== false, bPaginate: data.amsDatatablePagination !== false, bInfo: data.amsDatatableInfo !== false, bSort: data.amsDatatableSort !== false, - aaSorting: data.amsDatatableSorting, + aaSorting: sorting, + aoColumns: columns.length > 0 ? columns : undefined, bDeferRender: true, bAutoWidth: false, iDisplayLength: data.amsDatatableDisplayLength || 25, @@ -3022,7 +3046,6 @@ } }; var settings = $.extend({}, data_options, data.amsDatatableOptions); - var index; if (extensions.length > 0) { for (index in extensions) { switch (extensions[index]) { @@ -3087,85 +3110,88 @@ } } settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings; - var plugin = table.dataTable(settings); - ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings); - if (extensions.length > 0) { - for (index in extensions) { - switch (extensions[index]) { - case 'autofill': - var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill); - af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings; - table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined - ? new $.fn.dataTable.AutoFill(table, af_settings) - : ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, af_settings)); - break; - case 'columnfilter': - var cf_default = { - sPlaceHolder: 'head:after' - }; - var cf_settings = $.extend({}, cf_default, data.amsDatatableColumnfilterOptions, settings.columnfilter); - cf_settings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cf_settings) || cf_settings; - table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined - ? plugin.columnFilter(cf_settings) - : ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cf_settings)); - break; - case 'editable': - var ed_settings = $.extend({}, data.amsDatatableEditableOptions, settings.editable); - ed_settings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, ed_settings) || ed_settings; - table.data('ams-editable', data.amsDatatableEditableConstructor === undefined - ? table.makeEditable(ed_settings) - : ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, ed_settings)); - break; - case 'fixedcolumns': - var fc_settings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns); - fc_settings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fc_settings) || fc_settings; - table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined - ? new $.fn.dataTable.FixedColumns(table, fc_settings) - : ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fc_settings)); - break; - case 'fixedheader': - var fh_settings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader); - fh_settings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fh_settings) || fh_settings; - table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined - ? new $.fn.dataTable.FixedHeader(table, fh_settings) - : ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fh_settings)); - break; - case 'keytable': - var kt_default = { - table: table.get(0), - datatable: plugin - }; - var kt_settings = $.extend({}, kt_default, data.amsDatatableKeytableOptions, settings.keytable); - kt_settings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, kt_settings) || kt_settings; - table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined - ? new KeyTable(kt_settings) - : ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, kt_settings)); - break; - case 'rowgrouping': - var rg_settings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping); - rg_settings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rg_settings) || rg_settings; - table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined - ? table.rowGrouping(rg_settings) - : ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rg_settings)); - break; - case 'rowreordering': - var rr_settings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering); - rr_settings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rr_settings) || rr_settings; - table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined - ? table.rowReordering(rr_settings) - : ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rr_settings)); - break; - default: - break; + try { // Some settings can easilly generate DataTables exceptions... + var plugin = table.dataTable(settings); + ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings); + if (extensions.length > 0) { + for (index in extensions) { + switch (extensions[index]) { + case 'autofill': + var af_settings = $.extend({}, data.amsDatatableAutofillOptions, settings.autofill); + af_settings = ams.executeFunctionByName(data.amsDatatableAutofillInitCallback, table, af_settings) || af_settings; + table.data('ams-autofill', data.amsDatatableAutofillConstructor === undefined + ? new $.fn.dataTable.AutoFill(table, af_settings) + : ams.executeFunctionByName(data.amsDatatableAutofillConstructor, table, plugin, af_settings)); + break; + case 'columnfilter': + var cf_default = { + sPlaceHolder: 'head:after' + }; + var cf_settings = $.extend({}, cf_default, data.amsDatatableColumnfilterOptions, settings.columnfilter); + cf_settings = ams.executeFunctionByName(data.amsDatatableColumnfilterInitCallback, table, cf_settings) || cf_settings; + table.data('ams-columnfilter', data.amsDatatableColumnfilterConstructor === undefined + ? plugin.columnFilter(cf_settings) + : ams.executeFunctionByName(data.amsDatatableColumnfilterConstructor, table, plugin, cf_settings)); + break; + case 'editable': + var ed_settings = $.extend({}, data.amsDatatableEditableOptions, settings.editable); + ed_settings = ams.executeFunctionByName(data.amsDatatableEditableInitCallback, table, ed_settings) || ed_settings; + table.data('ams-editable', data.amsDatatableEditableConstructor === undefined + ? table.makeEditable(ed_settings) + : ams.executeFunctionByName(data.amsDatatableEditableConstructor, table, plugin, ed_settings)); + break; + case 'fixedcolumns': + var fc_settings = $.extend({}, data.amsDatatableFixedcolumnsOptions, settings.fixedcolumns); + fc_settings = ams.executeFunctionByName(data.amsDatatableFixedcolumnsInitCallback, table, fc_settings) || fc_settings; + table.data('ams-fixedcolumns', data.amsDatatableFixedcolumnsConstructor === undefined + ? new $.fn.dataTable.FixedColumns(table, fc_settings) + : ams.executeFunctionByName(data.amsDatatableFixedcolumnsConstructor, table, plugin, fc_settings)); + break; + case 'fixedheader': + var fh_settings = $.extend({}, data.amsDatatableFixedheaderOptions, settings.fixedheader); + fh_settings = ams.executeFunctionByName(data.amsDatatableFixedheadeInitCallback, table, fh_settings) || fh_settings; + table.data('ams-fixedheader', data.amsDatatableFixedheaderConstructor === undefined + ? new $.fn.dataTable.FixedHeader(table, fh_settings) + : ams.executeFunctionByName(data.amsDatatableFixedheaderConstructor, table, plugin, fh_settings)); + break; + case 'keytable': + var kt_default = { + table: table.get(0), + datatable: plugin + }; + var kt_settings = $.extend({}, kt_default, data.amsDatatableKeytableOptions, settings.keytable); + kt_settings = ams.executeFunctionByName(data.amsDatatableKeytableInitCallback, table, kt_settings) || kt_settings; + table.data('ams-keytable', data.amsDatatableKeytableConstructor === undefined + ? new KeyTable(kt_settings) + : ams.executeFunctionByName(data.amsDatatableKeytableConstructor, table, plugin, kt_settings)); + break; + case 'rowgrouping': + var rg_settings = $.extend({}, data.amsDatatableRowgroupingOptions, settings.rowgrouping); + rg_settings = ams.executeFunctionByName(data.amsDatatableRowgroupingInitCallback, table, rg_settings) || rg_settings; + table.data('ams-rowgrouping', data.amsDatatableRowgroupingConstructor === undefined + ? table.rowGrouping(rg_settings) + : ams.executeFunctionByName(data.amsDatatableRowgroupingConstructor, table, plugin, rg_settings)); + break; + case 'rowreordering': + var rr_settings = $.extend({}, data.amsDatatableRowreorderingOptions, settings.rowreordering); + rr_settings = ams.executeFunctionByName(data.amsDatatableRowreorderingInitCallback, table, rr_settings) || rr_settings; + table.data('ams-rowreordering', data.amsDatatableRowreorderingConstructor === undefined + ? table.rowReordering(rr_settings) + : ams.executeFunctionByName(data.amsDatatableRowreorderingConstructor, table, plugin, rr_settings)); + break; + default: + break; + } + } + } + var finalizers = (data.amsDatatableFinalizeCallback || '').split(/\s+/); + if (finalizers.length > 0) { + for (index in finalizers) { + ams.executeFunctionByName(finalizers[index], table, plugin, settings); } } } - var finalizers = (data.amsDatatableFinalizeCallback || '').split(/\s+/); - if (finalizers.length > 0) { - for (index in finalizers) { - ams.executeFunctionByName(finalizers[index], table, plugin, settings); - } - } + catch (e) {} }); }); } @@ -3398,6 +3424,50 @@ }, /** + * 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) { + var plugin_info = $.plot.plugins[index]; + if (plugin_info.name == plugin) { + return plugin_info; + } + } + return null; + } + + var chart = $(this); + var data = chart.data(); + var data_options = {}; + var plugins = (data.amsChartPlugins || '').split(/\s+/); + if (plugins.length > 0) { + for (var index in plugins) { + var plugin_name = plugins[index]; + if (!checkPlugin(plugin_name)) { + ams.getScript(ams.baseURL + 'flot/jquery.flot.' + plugin_name + ams.devext + '.js'); + } + } + } + var settings = $.extend({}, data_options, data.amsChartOptions); + settings = ams.executeFunctionByName(data.amsChartInitCallback, chart, settings) || settings; + var chart_data = data.amsChartData; + chart_data = ams.executeFunctionByName(data.amsChartInitData, chart, chart_data) || chart_data; + var plugin = chart.plot(chart_data, settings); + ams.executeFunctionByName(data.amsChartAfterInitCallback, chart, plugin, settings); + }) + }); + } + }, + + /** * Sparkline graphs */ graphs: function(element) { @@ -4265,7 +4335,6 @@ if (target) { ams.form.confirmChangedForm(target, function () { ams.skin.loadURL(href, target, link.data('ams-link-options'), link.data('ams-link-callback')); - e.stopPropagation(); }); } else { ams.form.confirmChangedForm(function () { @@ -4401,15 +4470,21 @@ if (data.amsUrl) { if (data.amsTabLoaded) return; - ams.skin.loadURL(data.amsUrl, link.attr('href')); - if (data.amsTabLoadOnce) - link.data('ams-tab-loaded', true); + try { + link.append(''); + ams.skin.loadURL(data.amsUrl, link.attr('href')); + if (data.amsTabLoadOnce) + link.data('ams-tab-loaded', true); + } + finally { + $('i', link).remove(); + } } }); // Init page content ams.initContent(document); - if (ams.ajax_nav && ($('nav').length > 0)) + if (ams.ajax_nav && $('nav').exists()) ams.skin.checkURL(); // Add unload event listener to check for modified forms @@ -4485,6 +4560,8 @@ BTN_NO: "No", BTN_YES_NO: "[Yes][No]", + CLIPBOARD_COPY: "Copy to clipboard with Ctrl+C, and Enter", + FORM_CHANGED_WARNING: "Some changes were not saved. These updates will be lost if you leave this page.", DELETE_WARNING: "This change can't be undone. Are you sure that you want to delete this element?", NO_UPDATE: "No changes were applied.",