diff -r 448072405613 -r d1a43750fea2 src/ztfy/myams/resources/js/myams.js --- a/src/ztfy/myams/resources/js/myams.js Mon Mar 21 16:11:04 2016 +0100 +++ b/src/ztfy/myams/resources/js/myams.js Thu Sep 01 15:16:47 2016 +0200 @@ -463,8 +463,6 @@ /** * Generate a random ID - * - * @param length */ MyAMS.generateId = function() { function s4() { @@ -475,6 +473,20 @@ /** + * Generate a random UUID + */ + MyAMS.generateUUID = function () { + var d = new Date().getTime(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (d + Math.random() * 16) % 16 | 0; + d = Math.floor(d / 16); + return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); + }); + return uuid; + }; + + + /** * Get and execute a function given by name * Small piece of code by Jason Bunting */ @@ -522,13 +534,20 @@ }; MyAMS.getScript = function(url, callback, options) { + if (typeof(callback) === 'object') { + options = callback; + callback = null; + } + if (options === undefined) { + options = {}; + } var defaults = { dataType: 'script', url: ams.getSource(url), success: callback, error: ams.error.show, cache: !ams.devmode, - async: typeof(callback) === 'function' + async: options.async === undefined ? typeof(callback) === 'function' : options.async }; var settings = $.extend({}, defaults, options); return $.ajax(settings); @@ -887,6 +906,7 @@ break; case 'info': case 'success': + ams.form.resetChanged(form); if (result.close_form !== false) { ams.dialog.close(form); } @@ -897,6 +917,7 @@ case 'notify': case 'callback': case 'callbacks': + ams.form.resetChanged(form); if (result.close_form !== false) { ams.dialog.close(form); } @@ -905,6 +926,7 @@ ams.dialog.open(result.location); break; case 'reload': + ams.form.resetChanged(form); if (result.close_form !== false) { ams.dialog.close(form); } @@ -915,6 +937,7 @@ ams.skin.loadURL(url, result.target || target || '#content'); break; case 'redirect': + ams.form.resetChanged(form); if (result.close_form === true) { ams.dialog.close(form); } @@ -1242,12 +1265,12 @@ if (source.data('ams-ignore-change') !== true) { var event = source.data('ams-changed-event') || 'change'; source.on(event, function () { - $(this).parents('FORM').attr('data-ams-form-changed', true); + ams.form.setChanged($(this).parents('FORM')); }); } }); form.on('reset', function() { - $(this).removeAttr('data-ams-form-changed'); + ams.form.resetChanged($(this)); }); }); }, @@ -1290,28 +1313,50 @@ /** * Check for modified forms before loading new inner content */ - confirmChangedForm: function(element, callback) { + confirmChangedForm: function(element, callback, cancelCallback) { if (typeof(element) === 'function') { callback = element; element = undefined; } var forms = $('FORM[data-ams-form-changed="true"]', element); if (forms.exists()) { - ams.skin.bigBox({ - title: ams.i18n.WARNING, - content: '  ' + ams.i18n.FORM_CHANGED_WARNING, - buttons: ams.i18n.BTN_OK_CANCEL - }, function(button) { - if (button === ams.i18n.BTN_OK) { + if (cancelCallback) { + if (globals.confirm(ams.i18n.FORM_CHANGED_WARNING, ams.i18n.WARNING)) { callback.call(element); + } else { + cancelCallback.call(element); } - }); + } else { + ams.skin.bigBox({ + title: ams.i18n.WARNING, + content: '  ' + ams.i18n.FORM_CHANGED_WARNING, + buttons: ams.i18n.BTN_OK_CANCEL + }, function(button) { + if (button === ams.i18n.BTN_OK) { + callback.call(element); + } + }); + } } else { callback.call(element); } }, /** + * Update form "chenged" status flag + */ + setChanged: function(form) { + form.attr('data-ams-form-changed', true); + }, + + /** + * Reset form changed flag + */ + resetChanged: function(form) { + form.removeAttr('data-ams-form-changed'); + }, + + /** * Submit given form */ submit: function(form, handler, submit_options) { @@ -1354,12 +1399,56 @@ function _submitAjaxForm(form, options) { - var button; + var button, + button_data; var data = form.data(); var form_options = data.amsFormOptions; var form_data; var form_data_callback; + var progress_handler; + var progress_interval; + var progress_callback; + var progress_end_callback; + + // Inner progress status handler + function _getProgress(handler, progress_id) { + + var interval; + + function _clearProgressStatus() { + button.button('reset'); + clearInterval(interval); + ams.executeFunctionByName(progress_end_callback, form, button); + } + + function _getProgressStatus() { + ams.ajax.post(handler, + {progress_id: progress_id}, + {error: _clearProgressStatus}, + ams.getFunctionByName(progress_callback) || function(result, status) { + if (status == 'success') { + if (result.status === 'running') { + if (result.message) { + button.text(result.message); + } else { + button.text(button.data('ams-progress-text') + + ' ' + result.current + ' / ' + result.length); + } + } else if (result.status === 'finished') { + _clearProgressStatus(); + } + } else { + _clearProgressStatus(); + } + }); + } + + button.button('loading'); + interval = setInterval(_getProgressStatus, progress_interval); + } + + // Initialize form data if (submit_options) { form_data_callback = submit_options.formDataInitCallback; } @@ -1387,20 +1476,21 @@ form_data = data.amsFormData || {}; } + // Check submit button for custom action handler and target button = $(form.data('ams-submit-button')); - var buttonHandler, - buttonTarget; - if (button) { - buttonHandler = button.data('ams-form-handler'); - buttonTarget = button.data('ams-form-submit-target'); + if (button && button.exists()) { + button_data = button.data(); + } else { + button_data = {}; } + // Check action URL var url; - var form_handler = handler || buttonHandler || data.amsFormHandler || ''; + var form_handler = handler || button_data.amsFormHandler || data.amsFormHandler || ''; if (form_handler.startsWith(window.location.protocol)) { url = form_handler; } else { - var action = form.attr('action').replace(/#/, ''); + var action = button_data.amsFormAction || form.attr('action').replace(/#/, ''); if (action.startsWith(window.location.protocol)) { url = action; } else { @@ -1408,10 +1498,15 @@ } url += form_handler; } - + progress_handler = button_data.amsProgressHandler || data.amsProgressHandler || ''; + progress_interval = button_data.amsProgressInterval || data.amsProgressInterval || 1000; + progress_callback = button_data.amsProgressCallback || data.amsProgressCallback; + progress_end_callback = button_data.amsProgressEndCallback || data.amsProgressEndCallback; + + // Initialize submit target with AJAX indicator var target = null; if (submit_options && submit_options.initSubmitTarget) { - ams.executeFunctionByName(submit_options.initSubmitTarget); + ams.executeFunctionByName(submit_options.initSubmitTarget, form); } else { if (data.amsFormInitSubmitTarget) { target = $(buttonTarget || data.amsFormSubmitTarget || '#content'); @@ -1421,17 +1516,26 @@ } } - var hasUpload = typeof(options.uuid) !== 'undefined'; - if (hasUpload) { - if (url.indexOf('X-Progress-ID') < 0) { - url += "?X-Progress-ID=" + options.uuid; - } - delete options.uuid; - } - + // Complete form data if (submit_options) { form_data = $.extend({}, form_data, submit_options.form_data); } + + // Check progress handler + if (progress_handler) { + form_data.progress_id = ams.generateUUID(); + } else { + // Check progress meter via Apache progress module + var hasUpload = typeof(options.uuid) !== 'undefined'; + if (hasUpload) { + if (url.indexOf('X-Progress-ID') < 0) { + url += "?X-Progress-ID=" + options.uuid; + } + delete options.uuid; + } + } + + // Initialize default AJAX settings var defaults = { url: url, type: 'post', @@ -1462,13 +1566,15 @@ }, iframe: hasUpload }; + + // Initialize IFrame for custom download target var download_target = (submit_options && submit_options.downloadTarget) || data.amsFormDownloadTarget; if (download_target) { var iframe = $('iframe[name="' + download_target + '"]'); if (!iframe.exists()) { iframe = $('').hide() .attr('name', download_target) - .appendTo(form); + .appendTo($('body')); } defaults = $.extend({}, defaults, { iframe: true, @@ -1486,13 +1592,16 @@ if (!callback) { callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback; } - callback.call(form, result, status, request, form); - if (form.is(':visible') && button) { - button.button('reset'); + try { + callback.call(form, result, status, request, form); + } finally { + if (form.is(':visible') && button) { + button.button('reset'); + } + form.data('submitted', false); + form.removeData('ams-submit-button'); + ams.form.resetChanged(form); } - form.data('submitted', false); - form.removeData('ams-submit-button'); - form.removeAttr('data-ams-form-changed'); } } }); @@ -1521,37 +1630,52 @@ if (!callback) { callback = ams.getFunctionByName(data.amsFormSubmitCallback) || ams.form._submitCallback; } - callback.call(form, result, status, request, form); - if (form.is(':visible') && button) { - button.button('reset'); + try { + callback.call(form, result, status, request, form); + } finally { + if (form.is(':visible') && button) { + button.button('reset'); + } + form.data('submitted', false); + form.removeData('ams-submit-button'); + ams.form.resetChanged(form); } - form.data('submitted', false); - form.removeData('ams-submit-button'); - form.removeAttr('data-ams-form-changed'); }, iframe: hasUpload }); } var settings = $.extend({}, defaults, options, form_options, submit_options); + + // Initialize progress handler + if (progress_handler) { + _getProgress(progress_handler, form_data.progress_id); + } + + // Submit form $(form).ajaxSubmit(settings); + // If external download target is specified, reset form submit button and footer if (download_target) { var modal = $(form).parents('.modal-dialog'); - if (modal.exists()) { + var keep_modal = modal.exists() && button && button.data('ams-keep-modal'); + if (keep_modal !== true) { ams.dialog.close(form); } else { - ams.form.finalizeSubmitFooter.call(form); - if (button) { - button.button('reset'); - } - form.data('submitted', false); - form.removeData('ams-submit-button'); - form.removeAttr('data-ams-form-changed'); + setTimeout(function() { + ams.form.finalizeSubmitFooter.call(form); + if (button) { + button.button('reset'); + } + form.data('submitted', false); + form.removeData('ams-submit-button'); + ams.form.resetChanged(form); + }, button.data('ams-form-reset-timeout') || 2000); } } } - var hasUpload = $('INPUT[type="file"]', form).length > 0; + var hasUpload = (form.data('ams-form-ignore-uploads') !== true) && + ($('INPUT[type="file"]', form).length > 0); if (hasUpload) { // JQuery-progressbar plug-in must be loaded synchronously!! // Otherwise, hidden input fields created by jquery-validate plug-in @@ -2285,32 +2409,36 @@ var plugin; 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; + if (new_plugin.callback) { + plugin.callbacks.push(new_plugin.callback); + } + 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: new_plugin.callback ? [new_plugin.callback] : [], + 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() { - function registerPlugin(name, new_plugin) { - if (plugins.hasOwnProperty(name)) { - var plugin = plugins[name]; - plugin.css = plugin.css || new_plugin.css; - if (new_plugin.callback) { - plugin.callbacks.push(new_plugin.callback); - } - 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: new_plugin.callback ? [new_plugin.callback] : [], - register: new_plugin.register, - async: new_plugin.async - }; - } - } - var source = $(this); var ams_plugins = source.data('ams-plugins'); if (typeof(ams_plugins) === 'string') { @@ -2324,26 +2452,25 @@ register: source.data('ams-plugin-' + name + '-register'), async: source.data('ams-plugin-' + name + '-async') }; - registerPlugin(name, new_plugin); + _registerPlugin(name, new_plugin); } } else { for (name in ams_plugins) { if (!ams_plugins.hasOwnProperty(name)) { continue; } - registerPlugin(name, ams_plugins[name]); + _registerPlugin(name, ams_plugins[name]); } } }); - // Load new plug-ins and execute async ones for (name in plugins) { if (ams.plugins.enabled[name] === undefined) { plugin = plugins[name]; ams.getScript(plugin.src, function() { var index; var callbacks = plugin.callbacks; - if (callbacks) { + if (callbacks && callbacks.length) { for (index=0; index < callbacks.length; index++) { var called = ams.getFunctionByName(callbacks[index]); if (plugin.register !== false) { @@ -2360,15 +2487,11 @@ ams.plugins.enabled[name] = null; } } - var css = plugin.css; - if (css) { - ams.getCSS(css, name + '_css'); - } // If running in async mode, registered plug-ins are run // before callback is called so we call plug-in manually - if (callbacks && (plugin.async !== false)) { + if (callbacks && callbacks.length && (plugin.async !== false)) { for (index=0; index < callbacks.length; index++) { - callbacks[index](element); + ams.getFunctionByName(callbacks[index])(element); } } }, { @@ -2386,17 +2509,19 @@ continue; } var callbacks = ams.plugins.enabled[index]; - switch (typeof(callbacks)) { - case 'function': - callbacks(element); - break; - default: - for (var cb_index = 0; cb_index < callbacks.length; cb_index++) { - var callback = callbacks[cb_index]; - if (typeof(callback) === 'function') { - callback(element); + if (callbacks) { + switch (typeof(callbacks)) { + case 'function': + callbacks(element); + break; + default: + for (var cb_index = 0; cb_index < callbacks.length; cb_index++) { + var callback = callbacks[cb_index]; + if (typeof(callback) === 'function') { + callback(element); + } } - } + } } } }, @@ -2409,12 +2534,12 @@ */ initData: function(element) { $('[data-ams-data]', element).each(function() { - var handler = $(this); - var data = handler.data('ams-data'); + var data_element = $(this); + var data = data_element.data('ams-data'); if (data) { for (var name in data) { if (data.hasOwnProperty(name)) { - handler.attr('data-' + name, data[name]); + data_element.attr('data-' + name, data[name]); } } } @@ -3333,7 +3458,7 @@ // Set options var data_options = { bJQueryUI: false, - bFilter: data.amsDatatableGlobalFilter !== false, + bFilter: data.amsDatatableGlobalFilter !== false || extensions.indexOf('columnfilter') >= 0, bPaginate: data.amsDatatablePagination !== false, bInfo: data.amsDatatableInfo !== false, bSort: data.amsDatatableSort !== false, @@ -3415,7 +3540,7 @@ } } settings = ams.executeFunctionByName(data.amsDatatableInitCallback, table, settings) || settings; - try { // Some settings can easilly generate DataTables exceptions... + try { // Some settings can easily generate DataTables exceptions... var plugin = table.dataTable(settings); ams.executeFunctionByName(data.amsDatatableAfterInitCallback, table, plugin, settings); if (extensions.length > 0) { @@ -3989,6 +4114,15 @@ } }, + refreshNotificationsPanel: function(e) { + var button = $(this); + button.addClass('disabled'); + $('i', button).addClass('fa-spin'); + $('input[name="activity"]:checked', '#user-activity').change(); + $('i', button).removeClass('fa-spin'); + button.removeClass('disabled'); + }, + /** * Initialize desktop and mobile widgets */ @@ -4143,14 +4277,14 @@ * Initialize breadcrumbs based on active menu position */ _drawBreadCrumb: function() { - var crumb = $('#ribbon OL.breadcrumb'); + var crumb = $('OL.breadcrumb', '#ribbon'); $('li', crumb).not('.parent').remove(); if (!$('li', crumb).exists()) { crumb.append($('
  • ').append($('').text(ams.i18n.HOME) .addClass('padding-right-5') .attr('href', $('nav a[href!="#"]:first').attr('href')))); } - $('nav LI.active >A').each(function() { + $('LI.active >A', 'nav').each(function() { var menu = $(this); var body = $.trim(menu.clone() .children(".badge") @@ -4195,9 +4329,11 @@ updateActiveMenus(menu); } ams.skin.loadURL(url, container); - document.title = $('[data-ams-page-title]:first', container).data('ams-page-title') || - menu.attr('title') || - document.title; + var prefix = $('html head title').data('ams-title-prefix'); + document.title = (prefix ? prefix + ' > ' : '') + + ($('[data-ams-page-title]:first', container).data('ams-page-title') || + menu.attr('title') || + document.title); } else { var active_url = $('[data-ams-active-menu]').data('ams-active-menu'); if (active_url) { @@ -4234,6 +4370,17 @@ }, /** + * Remove given callback from registry + */ + unregisterCleanCallback: function(callback) { + var callbacks = ams.skin._clean_callbacks; + var index = callbacks.indexOf(callback); + if (index >= 0) { + callbacks.splice(index, 1); + } + }, + + /** * Call registered cleaning callbacks on given container */ cleanContainer: function(container) { @@ -4265,7 +4412,8 @@ container.html('

    Loading...

    '); if (container[0] === $('#content')[0]) { ams.skin._drawBreadCrumb(); - document.title = $('.breadcrumb LI:last-child').text(); + var prefix = $('html head title').data('ams-title-prefix'); + document.title = (prefix ? prefix + ' > ' : '') + $('.breadcrumb LI:last-child').text(); $('html, body').animate({scrollTop: 0}, 'fast'); } else { container.animate({scrollTop: 0}, 'fast'); @@ -4487,14 +4635,27 @@ } }); - $('input[name="activity"]').change(function() { - var url = $(this).data('ams-url'); - var container = $('.ajax-notifications'); - ams.skin.loadURL(url, container); + $('input[name="activity"]').change(function(e) { + var href = $(this).data('ams-url'); + if (href) { + e.preventDefault(); + e.stopPropagation(); + var href_getter = ams.getFunctionByName(href); + if (typeof(href_getter) === 'function') { + href = href_getter.call(this); + } + if (typeof(href) === 'function') { + // Javascript function call + href.call(this); + } else { + var container = $('.ajax-notifications'); + ams.skin.loadURL(href, container); + } + } }); // Logout button - $('#logout a').click(function(e) { + $('a', '#logout').click(function(e) { e.preventDefault(); e.stopPropagation(); //get the link @@ -4660,6 +4821,11 @@ $(button.get(0).form).data('ams-submit-button', button); }); + // Cancel clicks on readonly checkbox + $(document).on('click', 'input[type="checkbox"][readonly]', function() { + return false; + }); + // Initialize custom click handlers $(document).on('click', '[data-ams-click-handler]', function(e) { var source = $(this); @@ -4771,6 +4937,20 @@ } }); + // Check modal form dialogs on close + $(document).on('hide.bs.modal', function(e) { + var modal = $(e.target); + ams.form.confirmChangedForm(modal, function() { + // Confirm closing if OK + modal.data('modal').isShown = true; + return true; + }, function() { + // Prevent closing if cancelled + e.preventDefault(); + return false; + }); + }); + // Init page content ams.initContent(document); if (ams.ajax_nav && nav.exists()) {