diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js b/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js index 9139034bef89a7e37d372b9b02c6948344c31b99..c60162cc329857fb2403311f8be2ca7870fbf801 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js @@ -16,252 +16,252 @@ * AjaxDataHandler - Javascript functions to work with AJAX and interacting with tce_db.php */ define(['jquery', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Severity' - ], function ($, Modal, Icons, Notification, Severity) { - 'use strict'; + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Severity' +], function($, Modal, Icons, Notification, Severity) { + 'use strict'; - /** - * - * @type {{identifier: {hide: string, delete: string, icon: string}}} - * @exports TYPO3/CMS/Backend/AjaxDataHandler - */ - var AjaxDataHandler = { - identifier: { - hide: '.t3js-record-hide', - delete: '.t3js-record-delete', - icon: '.t3js-icon' - } - }; + /** + * + * @type {{identifier: {hide: string, delete: string, icon: string}}} + * @exports TYPO3/CMS/Backend/AjaxDataHandler + */ + var AjaxDataHandler = { + identifier: { + hide: '.t3js-record-hide', + delete: '.t3js-record-delete', + icon: '.t3js-icon' + } + }; - /** - * generic function to call from the outside the script and validate directly showing errors - * - * @param {Object} parameters - * @return {Promise<Object>} a jQuery deferred object (promise) - */ - AjaxDataHandler.process = function(parameters) { - return AjaxDataHandler._call(parameters).done(function(result) { - if (result.hasErrors) { - AjaxDataHandler.handleErrors(result); - } - }); - }; + /** + * generic function to call from the outside the script and validate directly showing errors + * + * @param {Object} parameters + * @return {Promise<Object>} a jQuery deferred object (promise) + */ + AjaxDataHandler.process = function(parameters) { + return AjaxDataHandler._call(parameters).done(function(result) { + if (result.hasErrors) { + AjaxDataHandler.handleErrors(result); + } + }); + }; - /** - * - */ - AjaxDataHandler.initialize = function() { + /** + * + */ + AjaxDataHandler.initialize = function() { - // HIDE/UNHIDE: click events for all action icons to hide/unhide - $(document).on('click', AjaxDataHandler.identifier.hide, function(evt) { - evt.preventDefault(); - var $anchorElement = $(this); - var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); - var $rowElement = $anchorElement.closest('tr[data-uid]'); - var params = $anchorElement.data('params'); + // HIDE/UNHIDE: click events for all action icons to hide/unhide + $(document).on('click', AjaxDataHandler.identifier.hide, function(evt) { + evt.preventDefault(); + var $anchorElement = $(this); + var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); + var $rowElement = $anchorElement.closest('tr[data-uid]'); + var params = $anchorElement.data('params'); - // add a spinner - AjaxDataHandler._showSpinnerIcon($iconElement); + // add a spinner + AjaxDataHandler._showSpinnerIcon($iconElement); - // make the AJAX call to toggle the visibility - AjaxDataHandler._call(params).done(function(result) { - // print messages on errors - if (result.hasErrors) { - AjaxDataHandler.handleErrors(result); - } else { - // adjust overlay icon - AjaxDataHandler.toggleRow($rowElement); - } - }); - }); + // make the AJAX call to toggle the visibility + AjaxDataHandler._call(params).done(function(result) { + // print messages on errors + if (result.hasErrors) { + AjaxDataHandler.handleErrors(result); + } else { + // adjust overlay icon + AjaxDataHandler.toggleRow($rowElement); + } + }); + }); - // DELETE: click events for all action icons to delete - $(document).on('click', AjaxDataHandler.identifier.delete, function(evt) { - evt.preventDefault(); - var $anchorElement = $(this); - var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', - btnClass: 'btn-warning', - name: 'delete' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'cancel') { - Modal.dismiss(); - } else if (e.target.name === 'delete') { - Modal.dismiss(); - AjaxDataHandler.deleteRecord($anchorElement); - } - }); - }); - }; + // DELETE: click events for all action icons to delete + $(document).on('click', AjaxDataHandler.identifier.delete, function(evt) { + evt.preventDefault(); + var $anchorElement = $(this); + var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', + btnClass: 'btn-warning', + name: 'delete' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'cancel') { + Modal.dismiss(); + } else if (e.target.name === 'delete') { + Modal.dismiss(); + AjaxDataHandler.deleteRecord($anchorElement); + } + }); + }); + }; - /** - * Toggle row visibility after record has been changed - * - * @param {Object} $rowElement - */ - AjaxDataHandler.toggleRow = function($rowElement) { - var $anchorElement = $rowElement.find(AjaxDataHandler.identifier.hide); - var table = $anchorElement.closest('table[data-table]').data('table'); - var params = $anchorElement.data('params'); - var nextParams, nextState, iconName; + /** + * Toggle row visibility after record has been changed + * + * @param {Object} $rowElement + */ + AjaxDataHandler.toggleRow = function($rowElement) { + var $anchorElement = $rowElement.find(AjaxDataHandler.identifier.hide); + var table = $anchorElement.closest('table[data-table]').data('table'); + var params = $anchorElement.data('params'); + var nextParams, nextState, iconName; - if ($anchorElement.data('state') === 'hidden') { - nextState = 'visible'; - nextParams = params.replace('=0', '=1'); - iconName = 'actions-edit-hide'; - } else { - nextState = 'hidden'; - nextParams = params.replace('=1', '=0'); - iconName = 'actions-edit-unhide'; - } - $anchorElement.data('state', nextState).data('params', nextParams); + if ($anchorElement.data('state') === 'hidden') { + nextState = 'visible'; + nextParams = params.replace('=0', '=1'); + iconName = 'actions-edit-hide'; + } else { + nextState = 'hidden'; + nextParams = params.replace('=1', '=0'); + iconName = 'actions-edit-unhide'; + } + $anchorElement.data('state', nextState).data('params', nextParams); - // Update tooltip title - $anchorElement.tooltip('hide').one('hidden.bs.tooltip', function() { - var nextTitle = $anchorElement.data('toggleTitle'); - // Bootstrap Tooltip internally uses only .attr('data-original-title') - $anchorElement - .data('toggleTitle', $anchorElement.attr('data-original-title')) - .attr('data-original-title', nextTitle) - .tooltip('show'); - }); + // Update tooltip title + $anchorElement.tooltip('hide').one('hidden.bs.tooltip', function() { + var nextTitle = $anchorElement.data('toggleTitle'); + // Bootstrap Tooltip internally uses only .attr('data-original-title') + $anchorElement + .data('toggleTitle', $anchorElement.attr('data-original-title')) + .attr('data-original-title', nextTitle) + .tooltip('show'); + }); - var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); - Icons.getIcon(iconName, Icons.sizes.small).done(function(icon) { - $iconElement.replaceWith(icon); - }); + var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); + Icons.getIcon(iconName, Icons.sizes.small).done(function(icon) { + $iconElement.replaceWith(icon); + }); - // Set overlay for the record icon - var $recordIcon = $rowElement.find('.col-icon ' + AjaxDataHandler.identifier.icon); - if (nextState === 'hidden') { - Icons.getIcon('miscellaneous-placeholder', Icons.sizes.small, 'overlay-hidden').done(function(icon) { - $recordIcon.append($(icon).find('.icon-overlay')); - }); - } else { - $recordIcon.find('.icon-overlay').remove(); - } + // Set overlay for the record icon + var $recordIcon = $rowElement.find('.col-icon ' + AjaxDataHandler.identifier.icon); + if (nextState === 'hidden') { + Icons.getIcon('miscellaneous-placeholder', Icons.sizes.small, 'overlay-hidden').done(function(icon) { + $recordIcon.append($(icon).find('.icon-overlay')); + }); + } else { + $recordIcon.find('.icon-overlay').remove(); + } - $rowElement.fadeTo('fast', 0.4, function() { - $rowElement.fadeTo('fast', 1); - }); - if (table === 'pages') { - AjaxDataHandler.refreshPageTree(); - } - }; + $rowElement.fadeTo('fast', 0.4, function() { + $rowElement.fadeTo('fast', 1); + }); + if (table === 'pages') { + AjaxDataHandler.refreshPageTree(); + } + }; - /** - * delete record by given element (icon in table) - * don't call it directly! - * - * @param {HTMLElement} element - */ - AjaxDataHandler.deleteRecord = function(element) { - var $anchorElement = $(element); - var params = $anchorElement.data('params'); - var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); + /** + * delete record by given element (icon in table) + * don't call it directly! + * + * @param {HTMLElement} element + */ + AjaxDataHandler.deleteRecord = function(element) { + var $anchorElement = $(element); + var params = $anchorElement.data('params'); + var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); - // add a spinner - AjaxDataHandler._showSpinnerIcon($iconElement); + // add a spinner + AjaxDataHandler._showSpinnerIcon($iconElement); - // make the AJAX call to toggle the visibility - AjaxDataHandler._call(params).done(function(result) { - // revert to the old class - Icons.getIcon('actions-edit-delete', Icons.sizes.small).done(function(icon) { - $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); - $iconElement.replaceWith(icon); - }); - // print messages on errors - if (result.hasErrors) { - AjaxDataHandler.handleErrors(result); - } else { - var $table = $anchorElement.closest('table[data-table]'); - var $panel = $anchorElement.closest('.panel'); - var $panelHeading = $panel.find('.panel-heading'); - var table = $table.data('table'); - var $rowElements = $anchorElement.closest('tr[data-uid]'); - var uid = $rowElements.data('uid'); - var $translatedRowElements = $table.find('[data-l10nparent=' + uid + ']').closest('tr[data-uid]'); - $rowElements = $rowElements.add($translatedRowElements); + // make the AJAX call to toggle the visibility + AjaxDataHandler._call(params).done(function(result) { + // revert to the old class + Icons.getIcon('actions-edit-delete', Icons.sizes.small).done(function(icon) { + $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon); + $iconElement.replaceWith(icon); + }); + // print messages on errors + if (result.hasErrors) { + AjaxDataHandler.handleErrors(result); + } else { + var $table = $anchorElement.closest('table[data-table]'); + var $panel = $anchorElement.closest('.panel'); + var $panelHeading = $panel.find('.panel-heading'); + var table = $table.data('table'); + var $rowElements = $anchorElement.closest('tr[data-uid]'); + var uid = $rowElements.data('uid'); + var $translatedRowElements = $table.find('[data-l10nparent=' + uid + ']').closest('tr[data-uid]'); + $rowElements = $rowElements.add($translatedRowElements); - $rowElements.fadeTo('slow', 0.4, function() { - $rowElements.slideUp('slow', 0, function() { - $rowElements.remove(); - if ($table.find('tbody tr').length === 0) { - $panel.slideUp('slow'); - } - }); - }); - if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') { - var count = Number($panelHeading.find('.t3js-table-total-items').html()); - $panelHeading.find('.t3js-table-total-items').html(count-1); - } + $rowElements.fadeTo('slow', 0.4, function() { + $rowElements.slideUp('slow', 0, function() { + $rowElements.remove(); + if ($table.find('tbody tr').length === 0) { + $panel.slideUp('slow'); + } + }); + }); + if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') { + var count = Number($panelHeading.find('.t3js-table-total-items').html()); + $panelHeading.find('.t3js-table-total-items').html(count - 1); + } - if (table === 'pages') { - AjaxDataHandler.refreshPageTree(); - } - } - }); - }; + if (table === 'pages') { + AjaxDataHandler.refreshPageTree(); + } + } + }); + }; - /** - * handle the errors from result object - * - * @param {Object} result - * @private - */ - AjaxDataHandler.handleErrors = function(result) { - $.each(result.messages, function(position, message) { - Notification.error(message.title, message.message); - }); - }; + /** + * handle the errors from result object + * + * @param {Object} result + * @private + */ + AjaxDataHandler.handleErrors = function(result) { + $.each(result.messages, function(position, message) { + Notification.error(message.title, message.message); + }); + }; - /** - * refresh the page tree - * @private - */ - AjaxDataHandler.refreshPageTree = function() { - if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - }; + /** + * refresh the page tree + * @private + */ + AjaxDataHandler.refreshPageTree = function() { + if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } + }; - /** - * AJAX call to tce_db.php - * returns a jQuery Promise to work with - * - * @param {Object} params - * @returns {Object} - * @private - */ - AjaxDataHandler._call = function(params) { - return $.getJSON(TYPO3.settings.ajaxUrls['record_process'], params); - }; + /** + * AJAX call to tce_db.php + * returns a jQuery Promise to work with + * + * @param {Object} params + * @returns {Object} + * @private + */ + AjaxDataHandler._call = function(params) { + return $.getJSON(TYPO3.settings.ajaxUrls['record_process'], params); + }; - /** - * Replace the given icon with a spinner icon - * - * @param {Object} $iconElement - * @private - */ - AjaxDataHandler._showSpinnerIcon = function($iconElement) { - Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icon) { - $iconElement.replaceWith(icon); - }); - }; + /** + * Replace the given icon with a spinner icon + * + * @param {Object} $iconElement + * @private + */ + AjaxDataHandler._showSpinnerIcon = function($iconElement) { + Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icon) { + $iconElement.replaceWith(icon); + }); + }; - $(AjaxDataHandler.initialize); + $(AjaxDataHandler.initialize); - return AjaxDataHandler; + return AjaxDataHandler; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js index e1ca31e9511e35f353e72ca0bdb7ff1100b531c6..0b4dc8bfb06fb9d93500e9da224513be2140ac23 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js @@ -16,308 +16,308 @@ * Javascript container used to load the context menu via AJAX * to render the result in a layer next to the mouse cursor */ -define(['jquery', 'TYPO3/CMS/Backend/ContextMenuActions'], function ($, ContextMenuActions) { - - /** - * - * @type {{mousePos: {X: null, Y: null}, delayContextMenuHide: boolean}} - * @exports TYPO3/CMS/Backend/ContextMenu - */ - var ContextMenu = { - mousePos: { - X: null, - Y: null - }, - delayContextMenuHide: false, - record: { - uid: null, - table: null +define(['jquery', 'TYPO3/CMS/Backend/ContextMenuActions'], function($, ContextMenuActions) { + + /** + * + * @type {{mousePos: {X: null, Y: null}, delayContextMenuHide: boolean}} + * @exports TYPO3/CMS/Backend/ContextMenu + */ + var ContextMenu = { + mousePos: { + X: null, + Y: null + }, + delayContextMenuHide: false, + record: { + uid: null, + table: null + } + }; + + /** + * Initialize events + */ + ContextMenu.initializeEvents = function() { + $(document).on('click contextmenu', '.t3js-contextmenutrigger', function(event) { + // if there is an other "inline" onclick setting, context menu is not triggered + // usually this is the case for the foldertree + if ($(this).prop('onclick') && event.type === 'click') { + return; + } + event.preventDefault(); + ContextMenu.show( + $(this).data('table'), + $(this).data('uid'), + $(this).data('context'), + $(this).data('iteminfo'), + $(this).data('parameters') + ); + }); + + // register mouse movement inside the document + $(document).on('mousemove', ContextMenu.storeMousePositionEvent); + }; + + /** + * Main function, called from most context menu links + * + * @param {String} table Table from where info should be fetched + * @param {(String|Number)} uid The UID of the item + * @param {String} context Context of the item + * @param {String} enDisItems Items to disable / enable + * @param {String} addParams Additional params + * @return void + */ + ContextMenu.show = function(table, uid, context, enDisItems, addParams) { + ContextMenu.record = null; + ContextMenu.record = {table: table, uid: uid}; + + var parameters = ''; + + if (typeof table !== 'undefined') { + parameters += 'table=' + encodeURIComponent(table); + } + if (typeof uid !== 'undefined') { + parameters += (parameters.length > 0 ? '&' : '') + 'uid=' + uid; + } + if (typeof context !== 'undefined') { + parameters += (parameters.length > 0 ? '&' : '') + 'context=' + context; + } + if (typeof enDisItems !== 'undefined') { + parameters += (parameters.length > 0 ? '&' : '') + 'enDisItems=' + enDisItems; + } + if (typeof addParams !== 'undefined') { + parameters += (parameters.length > 0 ? '&' : '') + 'addParams=' + addParams; + } + this.fetch(parameters); + }; + + /** + * Make the AJAX request + * + * @param {array} parameters Parameters sent to the server + * @return void + */ + ContextMenu.fetch = function(parameters) { + var url = TYPO3.settings.ajaxUrls['contextmenu']; + if (parameters) { + url += ((url.indexOf('?') == -1) ? '?' : '&') + parameters; + } + $.ajax(url).done(function(response) { + if (typeof response !== "undefined" && Object.keys(response).length > 0) { + ContextMenu.populateData(response, 0); + } + }); + }; + + /** + * fills the context menu with content and displays it correctly + * depending on the mouse position + * + * @param {array} items The data that will be put in the menu + * @param {Number} level The depth of the context menu + */ + ContextMenu.populateData = function(items, level) { + this.initializeContextMenuContainer(); + + level = parseInt(level, 10) || 0; + var $obj = $('#contentMenu' + level); + + if ($obj.length && (level === 0 || $('#contentMenu' + (level - 1)).is(':visible'))) { + var elements = ContextMenu.drawMenu(items, level); + $obj.html('<div class="list-group">' + elements + '</div>'); + + $('a.list-group-item', $obj).click(function(event) { + event.preventDefault(); + + if ($(this).hasClass('list-group-item-submenu')) { + ContextMenu.openSubmenu(level, $(this)); + return; } - }; - - /** - * Initialize events - */ - ContextMenu.initializeEvents = function () { - $(document).on('click contextmenu', '.t3js-contextmenutrigger', function (event) { - // if there is an other "inline" onclick setting, context menu is not triggered - // usually this is the case for the foldertree - if ($(this).prop('onclick') && event.type === 'click') { - return; - } - event.preventDefault(); - ContextMenu.show( - $(this).data('table'), - $(this).data('uid'), - $(this).data('context'), - $(this).data('iteminfo'), - $(this).data('parameters') - ); - }); - - // register mouse movement inside the document - $(document).on('mousemove', ContextMenu.storeMousePositionEvent); - }; - - /** - * Main function, called from most context menu links - * - * @param {String} table Table from where info should be fetched - * @param {(String|Number)} uid The UID of the item - * @param {String} context Context of the item - * @param {String} enDisItems Items to disable / enable - * @param {String} addParams Additional params - * @return void - */ - ContextMenu.show = function (table, uid, context, enDisItems, addParams) { - ContextMenu.record = null; - ContextMenu.record = {table: table, uid: uid}; - - var parameters = ''; - - if (typeof table !== 'undefined') { - parameters += 'table=' + encodeURIComponent(table); - } - if (typeof uid !== 'undefined') { - parameters += (parameters.length > 0 ? '&' : '') + 'uid=' + uid; - } - if (typeof context !== 'undefined') { - parameters += (parameters.length > 0 ? '&' : '') + 'context=' + context; - } - if (typeof enDisItems !== 'undefined') { - parameters += (parameters.length > 0 ? '&' : '') + 'enDisItems=' + enDisItems; - } - if (typeof addParams !== 'undefined') { - parameters += (parameters.length > 0 ? '&' : '') + 'addParams=' + addParams; - } - this.fetch(parameters); - }; - /** - * Make the AJAX request - * - * @param {array} parameters Parameters sent to the server - * @return void - */ - ContextMenu.fetch = function (parameters) { - var url = TYPO3.settings.ajaxUrls['contextmenu']; - if (parameters) { - url += ((url.indexOf('?') == -1) ? '?' : '&') + parameters; + var callbackName = $(this).data('callback-action'); + var callbackModule = $(this).data('callback-module'); + var clickItem = $(this); + if (callbackModule) { + require([callbackModule], function(callbackModule) { + callbackModule[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid); + }); + } else if (ContextMenuActions && ContextMenuActions[callbackName]) { + ContextMenuActions[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid); + } else { + console.log('action: ' + callbackName + ' not found'); } - $.ajax(url).done(function (response) { - if (typeof response !== "undefined" && Object.keys(response).length > 0) { - ContextMenu.populateData(response, 0); - } - }); + ContextMenu.hideAll(); + }); + + $obj.css(ContextMenu.getPosition($obj)).show(); + } + }; + + ContextMenu.openSubmenu = function(level, $item) { + var $obj = $('#contentMenu' + (level + 1)).html(''); + $item.next().find('.list-group').clone(true).appendTo($obj); + $obj.css(ContextMenu.getPosition($obj)).show(); + }; + + ContextMenu.getPosition = function($obj) { + var x = this.mousePos.X; + var y = this.mousePos.Y; + var dimsWindow = { + width: $(window).width() - 20, // saving margin for scrollbars + height: $(window).height() }; - /** - * fills the context menu with content and displays it correctly - * depending on the mouse position - * - * @param {array} items The data that will be put in the menu - * @param {Number} level The depth of the context menu - */ - ContextMenu.populateData = function (items, level) { - this.initializeContextMenuContainer(); - - level = parseInt(level, 10) || 0; - var $obj = $('#contentMenu' + level); - - if ($obj.length && (level === 0 || $('#contentMenu' + (level - 1)).is(':visible'))) { - var elements = ContextMenu.drawMenu(items, level); - $obj.html('<div class="list-group">' + elements + '</div>'); - - $('a.list-group-item', $obj).click(function (event) { - event.preventDefault(); - - if ($(this).hasClass('list-group-item-submenu')) { - ContextMenu.openSubmenu(level, $(this)); - return; - } - - var callbackName = $(this).data('callback-action'); - var callbackModule = $(this).data('callback-module'); - var clickItem = $(this); - if (callbackModule) { - require([callbackModule], function (callbackModule) { - callbackModule[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid); - }); - } else if (ContextMenuActions && ContextMenuActions[callbackName]) { - ContextMenuActions[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid); - } else { - console.log('action: ' + callbackName + ' not found'); - } - ContextMenu.hideAll(); - }); - - $obj.css(ContextMenu.getPosition($obj)).show(); - } + // dimensions for the context menu + var dims = { + width: $obj.width(), + height: $obj.height() }; - ContextMenu.openSubmenu = function (level, $item) { - var $obj = $('#contentMenu' + (level + 1)).html(''); - $item.next().find('.list-group').clone(true).appendTo($obj); - $obj.css(ContextMenu.getPosition($obj)).show(); + var relative = { + X: this.mousePos.X - $(document).scrollLeft(), + Y: this.mousePos.Y - $(document).scrollTop() }; - ContextMenu.getPosition = function ($obj) { - var x = this.mousePos.X; - var y = this.mousePos.Y; - var dimsWindow = { - width: $(window).width() - 20, // saving margin for scrollbars - height: $(window).height() - }; - - // dimensions for the context menu - var dims = { - width: $obj.width(), - height: $obj.height() - }; - - var relative = { - X: this.mousePos.X - $(document).scrollLeft(), - Y: this.mousePos.Y - $(document).scrollTop() - }; - - // adjusting the Y position of the layer to fit it into the window frame - // if there is enough space above then put it upwards, - // otherwise adjust it to the bottom of the window - if (dimsWindow.height - dims.height < relative.Y) { - if (relative.Y > dims.height) { - y -= (dims.height - 10); - } else { - y += (dimsWindow.height - dims.height - relative.Y); - } - } - // adjusting the X position like Y above, but align it to the left side of the viewport if it does not fit completely - if (dimsWindow.width - dims.width < relative.X) { - if (relative.X > dims.width) { - x -= (dims.width - 10); - } else if ((dimsWindow.width - dims.width - relative.X) < $(document).scrollLeft()) { - x = $(document).scrollLeft(); - } else { - x += (dimsWindow.width - dims.width - relative.X); - } - } - return {left: x + 'px', top: y + 'px'}; - }; - - /** - * fills the context menu with content and displays it correctly - * depending on the mouse position - * - * @param {array} items The data that will be put in the menu - * @param {Number} level The depth of the context menu - */ - ContextMenu.drawMenu = function (items, level) { - var elements = ''; - $.each(items, function (key, value) { - if (value.type === 'item') { - elements += ContextMenu.drawActionItem(value); - } else if (value.type === 'divider') { - elements += '<a class="list-group-item list-group-item-divider"></a>'; - } else if (value.type === 'submenu' || value.childItems) { - elements += '<a class="list-group-item list-group-item-submenu"><span class="list-group-item-icon">' + value.icon + '</span> ' + value.label + ' <span class="fa fa-caret-right"></span></a>'; - var childElements = ContextMenu.drawMenu(value.childItems, 1); - elements += '<div class="context-menu contentMenu' + (level + 1) + '" style="display:none;"><div class="list-group">' + childElements + '</div></div>'; - - } - }); - return elements; - }; - - ContextMenu.drawActionItem = function (value) { - var attributes = value.additionalAttributes || []; - $attributesString = ''; - for (var attribute in attributes) { - $attributesString += ' ' + attribute + '="' + attributes[attribute] + '"'; - } - - return '<a class="list-group-item"' - + ' data-callback-action="' + value.callbackAction + '"' - + $attributesString + '><span class="list-group-item-icon">' + value.icon + '</span> ' + value.label + '</a>'; - }; - /** - * event handler function that saves the - * actual position of the mouse - * in the context menu object - * - * @param {Event} event The event object - */ - ContextMenu.storeMousePositionEvent = function (event) { - ContextMenu.mousePos.X = event.pageX; - ContextMenu.mousePos.Y = event.pageY; - ContextMenu.mouseOutFromMenu('#contentMenu0'); - ContextMenu.mouseOutFromMenu('#contentMenu1'); - }; - - /** - * hides a visible menu if the mouse has moved outside - * of the object - * - * @param {Object} obj The object to hide - */ - ContextMenu.mouseOutFromMenu = function (obj) { - var $element = $(obj); - - if ($element.length > 0 && $element.is(':visible') && !this.within($element, this.mousePos.X, this.mousePos.Y)) { - this.hide($element); - } else if ($element.length > 0 && $element.is(':visible')) { - this.delayContextMenuHide = true; - } - }; - - /** - * - * @param {Object} $element - * @param {Number} x - * @param {Number} y - * @returns {Boolean} - */ - ContextMenu.within = function ($element, x, y) { - var offset = $element.offset(); - return ( - y >= offset.top && - y < offset.top + $element.height() && - x >= offset.left && - x < offset.left + $element.width() - ); - }; - - /** - * hides a context menu - * - * @param {Object} obj The context menu object to hide - */ - ContextMenu.hide = function (obj) { - this.delayContextMenuHide = false; - window.setTimeout(function () { - if (!ContextMenu.delayContextMenuHide) { - $(obj).hide(); - } - }, 500); - }; - - /** - * hides all context menus - */ - ContextMenu.hideAll = function () { - this.hide('#contentMenu0'); - this.hide('#contentMenu1'); - }; - - /** - * manipulates the DOM to add the divs needed for context menu the bottom of the <body>-tag - */ - ContextMenu.initializeContextMenuContainer = function () { - if ($('#contentMenu0').length === 0) { - var code = '<div id="contentMenu0" class="context-menu"></div><div id="contentMenu1" class="context-menu" style="display: block;"></div>'; - $('body').append(code); - } - }; - - ContextMenu.initializeEvents(); - - return ContextMenu; + // adjusting the Y position of the layer to fit it into the window frame + // if there is enough space above then put it upwards, + // otherwise adjust it to the bottom of the window + if (dimsWindow.height - dims.height < relative.Y) { + if (relative.Y > dims.height) { + y -= (dims.height - 10); + } else { + y += (dimsWindow.height - dims.height - relative.Y); + } + } + // adjusting the X position like Y above, but align it to the left side of the viewport if it does not fit completely + if (dimsWindow.width - dims.width < relative.X) { + if (relative.X > dims.width) { + x -= (dims.width - 10); + } else if ((dimsWindow.width - dims.width - relative.X) < $(document).scrollLeft()) { + x = $(document).scrollLeft(); + } else { + x += (dimsWindow.width - dims.width - relative.X); + } + } + return {left: x + 'px', top: y + 'px'}; + }; + + /** + * fills the context menu with content and displays it correctly + * depending on the mouse position + * + * @param {array} items The data that will be put in the menu + * @param {Number} level The depth of the context menu + */ + ContextMenu.drawMenu = function(items, level) { + var elements = ''; + $.each(items, function(key, value) { + if (value.type === 'item') { + elements += ContextMenu.drawActionItem(value); + } else if (value.type === 'divider') { + elements += '<a class="list-group-item list-group-item-divider"></a>'; + } else if (value.type === 'submenu' || value.childItems) { + elements += '<a class="list-group-item list-group-item-submenu"><span class="list-group-item-icon">' + value.icon + '</span> ' + value.label + ' <span class="fa fa-caret-right"></span></a>'; + var childElements = ContextMenu.drawMenu(value.childItems, 1); + elements += '<div class="context-menu contentMenu' + (level + 1) + '" style="display:none;"><div class="list-group">' + childElements + '</div></div>'; + + } + }); + return elements; + }; + + ContextMenu.drawActionItem = function(value) { + var attributes = value.additionalAttributes || []; + $attributesString = ''; + for (var attribute in attributes) { + $attributesString += ' ' + attribute + '="' + attributes[attribute] + '"'; + } + + return '<a class="list-group-item"' + + ' data-callback-action="' + value.callbackAction + '"' + + $attributesString + '><span class="list-group-item-icon">' + value.icon + '</span> ' + value.label + '</a>'; + }; + /** + * event handler function that saves the + * actual position of the mouse + * in the context menu object + * + * @param {Event} event The event object + */ + ContextMenu.storeMousePositionEvent = function(event) { + ContextMenu.mousePos.X = event.pageX; + ContextMenu.mousePos.Y = event.pageY; + ContextMenu.mouseOutFromMenu('#contentMenu0'); + ContextMenu.mouseOutFromMenu('#contentMenu1'); + }; + + /** + * hides a visible menu if the mouse has moved outside + * of the object + * + * @param {Object} obj The object to hide + */ + ContextMenu.mouseOutFromMenu = function(obj) { + var $element = $(obj); + + if ($element.length > 0 && $element.is(':visible') && !this.within($element, this.mousePos.X, this.mousePos.Y)) { + this.hide($element); + } else if ($element.length > 0 && $element.is(':visible')) { + this.delayContextMenuHide = true; + } + }; + + /** + * + * @param {Object} $element + * @param {Number} x + * @param {Number} y + * @returns {Boolean} + */ + ContextMenu.within = function($element, x, y) { + var offset = $element.offset(); + return ( + y >= offset.top && + y < offset.top + $element.height() && + x >= offset.left && + x < offset.left + $element.width() + ); + }; + + /** + * hides a context menu + * + * @param {Object} obj The context menu object to hide + */ + ContextMenu.hide = function(obj) { + this.delayContextMenuHide = false; + window.setTimeout(function() { + if (!ContextMenu.delayContextMenuHide) { + $(obj).hide(); + } + }, 500); + }; + + /** + * hides all context menus + */ + ContextMenu.hideAll = function() { + this.hide('#contentMenu0'); + this.hide('#contentMenu1'); + }; + + /** + * manipulates the DOM to add the divs needed for context menu the bottom of the <body>-tag + */ + ContextMenu.initializeContextMenuContainer = function() { + if ($('#contentMenu0').length === 0) { + var code = '<div id="contentMenu0" class="context-menu"></div><div id="contentMenu1" class="context-menu" style="display: block;"></div>'; + $('body').append(code); + } + }; + + ContextMenu.initializeEvents(); + + return ContextMenu; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js index 4d45bf34ccb390a86e7b009c2538c69afd0c9005..236170632db38d87a51d234bbdd5046b95ff2adb 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js @@ -15,233 +15,233 @@ * Module: TYPO3/CMS/Backend/ContextMenuActions * Click menu actions for db records including tt_content and pages */ -define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) { - /** - * - * @exports TYPO3/CMS/Backend/ContextMenuActions - */ - var ContextMenuActions = {}; - - ContextMenuActions.getReturnUrl = function () { - return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search); - }; - - ContextMenuActions.editRecord = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][' + uid + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.viewRecord = function (table, uid) { - var $viewUrl = $(this).data('preview-url'); - if ($viewUrl) { - var previewWin = window.open($viewUrl, 'newTYPO3frontendWindow'); - previewWin.focus(); - } - }; - - ContextMenuActions.openInfoPopUp = function (table, uid) { - top.launchView(table, uid); - }; - - ContextMenuActions.mountAsTreeRoot = function (table, uid) { - if (table === 'pages') { - top.TYPO3.Backend.NavigationContainer.PageTree.setTemporaryMountPoint(uid); - } - }; - - ContextMenuActions.newPageWizard = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.NewRecord.moduleUrl + '&id=' + uid + '&pagesOnly=1&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.newContentWizard = function (table, uid) { - var $wizardUrl = $(this).data('new-wizard-url'); - if ($wizardUrl) { - $wizardUrl += '&returnUrl='+ ContextMenuActions.getReturnUrl(); - top.TYPO3.Backend.ContentContainer.setUrl($wizardUrl); +define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) { + /** + * + * @exports TYPO3/CMS/Backend/ContextMenuActions + */ + var ContextMenuActions = {}; + + ContextMenuActions.getReturnUrl = function() { + return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search); + }; + + ContextMenuActions.editRecord = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][' + uid + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.viewRecord = function(table, uid) { + var $viewUrl = $(this).data('preview-url'); + if ($viewUrl) { + var previewWin = window.open($viewUrl, 'newTYPO3frontendWindow'); + previewWin.focus(); + } + }; + + ContextMenuActions.openInfoPopUp = function(table, uid) { + top.launchView(table, uid); + }; + + ContextMenuActions.mountAsTreeRoot = function(table, uid) { + if (table === 'pages') { + top.TYPO3.Backend.NavigationContainer.PageTree.setTemporaryMountPoint(uid); + } + }; + + ContextMenuActions.newPageWizard = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.NewRecord.moduleUrl + '&id=' + uid + '&pagesOnly=1&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.newContentWizard = function(table, uid) { + var $wizardUrl = $(this).data('new-wizard-url'); + if ($wizardUrl) { + $wizardUrl += '&returnUrl=' + ContextMenuActions.getReturnUrl(); + top.TYPO3.Backend.ContentContainer.setUrl($wizardUrl); + } + }; + + ContextMenuActions.newRecord = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][-' + uid + ']=new&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.openHistoryPopUp = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.RecordHistory.moduleUrl + '&element=' + table + ':' + uid + '&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.openListModule = function(table, uid) { + var pageId = table === 'pages' ? uid : $(this).data('page-uid'); + top.TYPO3.ModuleMenu.App.showModule('web_list', 'id='.pageId); + }; + + ContextMenuActions.pagesSort = function(table, uid) { + var pagesSortUrl = $(this).data('pages-sort-url'); + if (pagesSortUrl) { + top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl); + } + }; + + ContextMenuActions.pagesNewMultiple = function(table, uid) { + var pagesSortUrl = $(this).data('pages-new-multiple-url'); + if (pagesSortUrl) { + top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl); + } + }; + + ContextMenuActions.disableRecord = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&redirect=' + ContextMenuActions.getReturnUrl() + ).done(function() { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + }); + }; + + ContextMenuActions.enableRecord = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=0&redirect=' + ContextMenuActions.getReturnUrl() + ).done(function() { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + }); + }; + + ContextMenuActions.deleteRecord = function(table, uid) { + var $anchorElement = $(this); + var $modal = Modal.confirm( + $anchorElement.data('title'), + $anchorElement.data('message'), + Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', + btnClass: 'btn-warning', + name: 'delete' } - }; - - ContextMenuActions.newRecord = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][-' + uid + ']=new&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; + ]); - ContextMenuActions.openHistoryPopUp = function (table, uid) { + $modal.on('button.clicked', function(e) { + if (e.target.name === 'delete') { top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.RecordHistory.moduleUrl + '&element=' + table + ':' + uid + '&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.openListModule = function (table, uid) { - var pageId = table === 'pages' ? uid : $(this).data('page-uid'); - top.TYPO3.ModuleMenu.App.showModule('web_list', 'id='.pageId); - }; - - ContextMenuActions.pagesSort = function (table, uid) { - var pagesSortUrl = $(this).data('pages-sort-url'); - if (pagesSortUrl) { - top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl); - } - }; - - ContextMenuActions.pagesNewMultiple = function (table, uid) { - var pagesSortUrl = $(this).data('pages-new-multiple-url'); - if (pagesSortUrl) { - top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl); - } - }; - - ContextMenuActions.disableRecord = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&redirect=' + ContextMenuActions.getReturnUrl() - ).done(function () { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + top.TYPO3.settings.RecordCommit.moduleUrl + '&redirect=' + ContextMenuActions.getReturnUrl() + '&cmd[' + table + '][' + uid + '][delete]=1' + ).done(function() { + if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } }); - }; - ContextMenuActions.enableRecord = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=0&redirect=' + ContextMenuActions.getReturnUrl() - ).done(function () { + } + Modal.dismiss(); + }); + }; + + ContextMenuActions.copy = function(table, uid) { + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][' + table + '%7C' + uid + ']=1' + '&CB[setCopyMode]=1'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.clipboardRelease = function(table, uid) { + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][' + table + '%7C' + uid + ']=0'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.cut = function(table, uid) { + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][' + table + '%7C' + uid + ']=1' + '&CB[setCopyMode]=0'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + /** + * Clear cache for given page uid + * + * @param {string} table pages table + * @param {int} uid of the page + */ + ContextMenuActions.clearCache = function(table, uid) { + var url = top.TYPO3.settings.WebLayout.moduleUrl; + url += '&id=' + uid + '&clear_cache=1'; + $.ajax(url); + }; + + /** + * Paste db record after another + * + * @param {string} table any db table except sys_file + * @param {int} uid of the record after which record from the cliboard will be pasted + */ + ContextMenuActions.pasteAfter = function(table, uid) { + ContextMenuActions.pasteInto.bind($(this))(table, -uid); + }; + + /** + * Paste page into another page + * + * @param {string} table any db table except sys_file + * @param {int} uid of the record after which record from the cliboard will be pasted + */ + ContextMenuActions.pasteInto = function(table, uid) { + var $anchorElement = $(this); + var title = $anchorElement.data('title'); + var performPaste = function() { + var url = '&CB[paste]=' + table + '%7C' + uid + + '&CB[pad]=normal' + + '&redirect=' + ContextMenuActions.getReturnUrl(); + + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.RecordCommit.moduleUrl + url + ).done(function() { + if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) { top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - }); - }; - - ContextMenuActions.deleteRecord = function (table, uid) { - var $anchorElement = $(this); - var $modal = Modal.confirm( - $anchorElement.data('title'), - $anchorElement.data('message'), - Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', - btnClass: 'btn-warning', - name: 'delete' - } - ]); - - $modal.on('button.clicked', function (e) { - if (e.target.name === 'delete') { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.RecordCommit.moduleUrl + '&redirect=' + ContextMenuActions.getReturnUrl() + '&cmd[' + table + '][' + uid + '][delete]=1' - ).done(function () { - if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - }); - - } - Modal.dismiss(); - }); - }; - - ContextMenuActions.copy = function (table, uid) { - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][' + table + '%7C' + uid + ']=1'+ '&CB[setCopyMode]=1'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.clipboardRelease = function (table, uid) { - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][' + table + '%7C' + uid + ']=0'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.cut = function (table, uid) { - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][' + table + '%7C' + uid + ']=1'+ '&CB[setCopyMode]=0'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - /** - * Clear cache for given page uid - * - * @param {string} table pages table - * @param {int} uid of the page - */ - ContextMenuActions.clearCache = function (table, uid) { - var url = top.TYPO3.settings.WebLayout.moduleUrl; - url += '&id=' + uid + '&clear_cache=1'; - $.ajax(url); - }; - - /** - * Paste db record after another - * - * @param {string} table any db table except sys_file - * @param {int} uid of the record after which record from the cliboard will be pasted - */ - ContextMenuActions.pasteAfter = function (table, uid) { - ContextMenuActions.pasteInto.bind($(this))(table, -uid); - }; - - /** - * Paste page into another page - * - * @param {string} table any db table except sys_file - * @param {int} uid of the record after which record from the cliboard will be pasted - */ - ContextMenuActions.pasteInto = function (table, uid) { - var $anchorElement = $(this); - var title = $anchorElement.data('title'); - var performPaste = function () { - var url = '&CB[paste]=' + table + '%7C' + uid - + '&CB[pad]=normal' - + '&redirect=' + ContextMenuActions.getReturnUrl(); - - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.RecordCommit.moduleUrl + url - ).done(function () { - if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - }); - }; - if (!$anchorElement.data('title')) { - performPaste(); - return; } - var $modal = Modal.confirm( - $anchorElement.data('title'), - $anchorElement.data('message'), - Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', - btnClass: 'btn-warning', - name: 'ok' - } - ]); - - $modal.on('button.clicked', function (e) { - if (e.target.name === 'ok') { - performPaste(); - } - Modal.dismiss(); - }); + }); + }; + if (!$anchorElement.data('title')) { + performPaste(); + return; + } + var $modal = Modal.confirm( + $anchorElement.data('title'), + $anchorElement.data('message'), + Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', + btnClass: 'btn-warning', + name: 'ok' + } + ]); - }; + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + performPaste(); + } + Modal.dismiss(); + }); + + }; - return ContextMenuActions; + return ContextMenuActions; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js index 656fc91981159dfcdcea078f84a4041e4340a9a6..f3f258bb809333616f7deeac42a0e8a30f1568ae 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js @@ -17,154 +17,154 @@ * and EXT:belog and EXT:scheduler */ define(['jquery'], function($) { - "use strict"; - - /** - * @type {{options: {fieldSelector: string, format: *}}} - * @exports TYPO3/CMS/Backend/DateTimePicker - */ - var DateTimePicker = { - options: { - fieldSelector: '.t3js-datetimepicker', - format: (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top).TYPO3.settings.DateTimePicker.DateFormat - } - }; - - /** - * initialize date fields to add a datepicker to each field - * note: this function can be called multiple times (e.g. after AJAX requests) because it only - * applies to fields which haven't been used yet. - */ - DateTimePicker.initialize = function() { - // fetch the date time fields that haven't been initialized yet - var $dateTimeFields = $(DateTimePicker.options.fieldSelector).filter(function() { - return $(this).data('DateTimePicker') === undefined; - }); - - if ($dateTimeFields.length > 0) { - require(['moment', 'TYPO3/CMS/Backend/Storage/Persistent', 'twbs/bootstrap-datetimepicker'], function(moment, PersistentStorage) { - var userLocale = PersistentStorage.get('lang'); - var setLocale = userLocale ? moment.locale(userLocale) : false; - - // initialize the datepicker on each selected element - $dateTimeFields.each(function() { - DateTimePicker.initializeField(moment, $(this), setLocale); - }); - - $dateTimeFields.on('blur', function() { - var $element = $(this); - var $hiddenField = $element.parent().parent().find('input[type=hidden]'); - - if ($element.val() === '') { - $hiddenField.val(''); - } else { - var type = $element.data('dateType'); - var format = $element.data('DateTimePicker').format(); - var date = moment.utc($element.val(), format); - if (date.isValid()) { - $hiddenField.val(DateTimePicker.formatDateForHiddenField(date, type)); - } else { - $element.val(DateTimePicker.formatDateForHiddenField(moment.utc($hiddenField.val()), type)); - } - } - }); - - // on datepicker change, write the selected date with the timezone offset to the hidden field - $dateTimeFields.on('dp.change', function(evt) { - var $element = $(this); - var $hiddenField = $element.parent().parent().find('input[type=hidden]'); - var type = $element.data('dateType'); - var value = ''; - - if ($element.val() !== '') { - value = DateTimePicker.formatDateForHiddenField(evt.date.utc(), type); - } - $hiddenField.val(value); - - $(document).trigger('formengine.dp.change', [$(this)]); - }); - }); - } - }; - - /** - * Initialize a single field - * - * @param {moment} moment - * @param {object} $element - * @param {string} locale - */ - DateTimePicker.initializeField = function(moment, $element, locale) { - var format = DateTimePicker.options.format; - var type = $element.data('dateType'); - var options = { - sideBySide: true, - showTodayButton: true, - toolbarPlacement: 'bottom', - icons: { - time: 'fa fa-clock-o', - date: 'fa fa-calendar', - up: 'fa fa-chevron-up', - down: 'fa fa-chevron-down', - previous: 'fa fa-chevron-left', - next: 'fa fa-chevron-right', - today: 'fa fa-calendar-o', - clear: 'fa fa-trash' - } - }; - - // set options based on type - switch (type) { - case 'datetime': - options.format = format[1]; - break; - case 'date': - options.format = format[0]; - break; - case 'time': - options.format = 'HH:mm'; - break; - case 'timesec': - options.format = 'HH:mm:ss'; - break; - case 'year': - options.format = 'YYYY'; - break; - } - - // datepicker expects the min and max dates to be formatted with options.format but unix timestamp given - if ($element.data('dateMindate')) { - $element.data('dateMindate', moment.unix($element.data('dateMindate')).format(options.format)); - } - if ($element.data('dateMaxdate')) { - $element.data('dateMaxdate', moment.unix($element.data('dateMaxdate')).format(options.format)); - } - - if (locale) { - options.locale = locale; - } - - // initialize the date time picker on this element - $element.datetimepicker(options); - }; - - /** - * Format a given date for the hidden FormEngine field - * - * Format the value for the hidden field that is passed on to the backend, i.e. most likely DataHandler. - * The format for that is the timestamp for time fields, and a full-blown ISO-8601 timestamp for all date-related fields. - * - * @param {moment} date - * @param {string} type Type of the date - * @returns {string} - */ - DateTimePicker.formatDateForHiddenField = function(date, type) { - if (type === 'time' || type === 'timesec') { - date.year(1970).month(0).date(1); - } - return date.format(); - }; - - $(DateTimePicker.initialize); - return DateTimePicker; + "use strict"; + + /** + * @type {{options: {fieldSelector: string, format: *}}} + * @exports TYPO3/CMS/Backend/DateTimePicker + */ + var DateTimePicker = { + options: { + fieldSelector: '.t3js-datetimepicker', + format: (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top).TYPO3.settings.DateTimePicker.DateFormat + } + }; + + /** + * initialize date fields to add a datepicker to each field + * note: this function can be called multiple times (e.g. after AJAX requests) because it only + * applies to fields which haven't been used yet. + */ + DateTimePicker.initialize = function() { + // fetch the date time fields that haven't been initialized yet + var $dateTimeFields = $(DateTimePicker.options.fieldSelector).filter(function() { + return $(this).data('DateTimePicker') === undefined; + }); + + if ($dateTimeFields.length > 0) { + require(['moment', 'TYPO3/CMS/Backend/Storage/Persistent', 'twbs/bootstrap-datetimepicker'], function(moment, PersistentStorage) { + var userLocale = PersistentStorage.get('lang'); + var setLocale = userLocale ? moment.locale(userLocale) : false; + + // initialize the datepicker on each selected element + $dateTimeFields.each(function() { + DateTimePicker.initializeField(moment, $(this), setLocale); + }); + + $dateTimeFields.on('blur', function() { + var $element = $(this); + var $hiddenField = $element.parent().parent().find('input[type=hidden]'); + + if ($element.val() === '') { + $hiddenField.val(''); + } else { + var type = $element.data('dateType'); + var format = $element.data('DateTimePicker').format(); + var date = moment.utc($element.val(), format); + if (date.isValid()) { + $hiddenField.val(DateTimePicker.formatDateForHiddenField(date, type)); + } else { + $element.val(DateTimePicker.formatDateForHiddenField(moment.utc($hiddenField.val()), type)); + } + } + }); + + // on datepicker change, write the selected date with the timezone offset to the hidden field + $dateTimeFields.on('dp.change', function(evt) { + var $element = $(this); + var $hiddenField = $element.parent().parent().find('input[type=hidden]'); + var type = $element.data('dateType'); + var value = ''; + + if ($element.val() !== '') { + value = DateTimePicker.formatDateForHiddenField(evt.date.utc(), type); + } + $hiddenField.val(value); + + $(document).trigger('formengine.dp.change', [$(this)]); + }); + }); + } + }; + + /** + * Initialize a single field + * + * @param {moment} moment + * @param {object} $element + * @param {string} locale + */ + DateTimePicker.initializeField = function(moment, $element, locale) { + var format = DateTimePicker.options.format; + var type = $element.data('dateType'); + var options = { + sideBySide: true, + showTodayButton: true, + toolbarPlacement: 'bottom', + icons: { + time: 'fa fa-clock-o', + date: 'fa fa-calendar', + up: 'fa fa-chevron-up', + down: 'fa fa-chevron-down', + previous: 'fa fa-chevron-left', + next: 'fa fa-chevron-right', + today: 'fa fa-calendar-o', + clear: 'fa fa-trash' + } + }; + + // set options based on type + switch (type) { + case 'datetime': + options.format = format[1]; + break; + case 'date': + options.format = format[0]; + break; + case 'time': + options.format = 'HH:mm'; + break; + case 'timesec': + options.format = 'HH:mm:ss'; + break; + case 'year': + options.format = 'YYYY'; + break; + } + + // datepicker expects the min and max dates to be formatted with options.format but unix timestamp given + if ($element.data('dateMindate')) { + $element.data('dateMindate', moment.unix($element.data('dateMindate')).format(options.format)); + } + if ($element.data('dateMaxdate')) { + $element.data('dateMaxdate', moment.unix($element.data('dateMaxdate')).format(options.format)); + } + + if (locale) { + options.locale = locale; + } + + // initialize the date time picker on this element + $element.datetimepicker(options); + }; + + /** + * Format a given date for the hidden FormEngine field + * + * Format the value for the hidden field that is passed on to the backend, i.e. most likely DataHandler. + * The format for that is the timestamp for time fields, and a full-blown ISO-8601 timestamp for all date-related fields. + * + * @param {moment} date + * @param {string} type Type of the date + * @returns {string} + */ + DateTimePicker.formatDateForHiddenField = function(date, type) { + if (type === 'time' || type === 'timesec') { + date.year(1970).month(0).date(1); + } + return date.format(); + }; + + $(DateTimePicker.initialize); + return DateTimePicker; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js b/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js index 0840d61ced10dff9eec88c8d9ec0849a672704d6..41eb529018932ae6d5cb9b6f99f8220a5cecc010 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js @@ -16,100 +16,100 @@ * Calculates the height of the docHeader and hides it upon scrolling */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - /** - * - * @type {{$documentHeader: null, $documentHeaderBars: null, $documentHeaderNavigationBar: null, $documentHeaderSearchBar: null, $moduleBody: null, direction: string, reactionRange: number, lastPosition: number, currentPosition: number, changedPosition: number, settings: {margin: number, offset: number, selectors: {moduleDocumentHeader: string, moduleDocheaderBar: string, moduleNavigationBar: string, moduleButtonBar: string, moduleSearchBar: string, moduleBody: string}}}} - * @exports TYPO3/CMS/Backend/DocumentHeader - */ - var DocumentHeader = { - $documentHeader: null, - $documentHeaderBars: null, - $documentHeaderNavigationBar: null, - $documentHeaderSearchBar: null, - $moduleBody: null, - direction: 'down', - reactionRange: 300, - lastPosition: 0, - currentPosition: 0, - changedPosition: 0, - settings: { - margin: 24, - offset: 100, - selectors: { - moduleDocumentHeader: '.t3js-module-docheader', - moduleDocheaderBar: '.t3js-module-docheader-bar', - moduleNavigationBar: '.t3js-module-docheader-bar-navigation', - moduleButtonBar: '.t3js-module-docheader-bar-buttons', - moduleSearchBar: '.t3js-module-docheader-bar-search', - moduleBody: '.t3js-module-body' + /** + * + * @type {{$documentHeader: null, $documentHeaderBars: null, $documentHeaderNavigationBar: null, $documentHeaderSearchBar: null, $moduleBody: null, direction: string, reactionRange: number, lastPosition: number, currentPosition: number, changedPosition: number, settings: {margin: number, offset: number, selectors: {moduleDocumentHeader: string, moduleDocheaderBar: string, moduleNavigationBar: string, moduleButtonBar: string, moduleSearchBar: string, moduleBody: string}}}} + * @exports TYPO3/CMS/Backend/DocumentHeader + */ + var DocumentHeader = { + $documentHeader: null, + $documentHeaderBars: null, + $documentHeaderNavigationBar: null, + $documentHeaderSearchBar: null, + $moduleBody: null, + direction: 'down', + reactionRange: 300, + lastPosition: 0, + currentPosition: 0, + changedPosition: 0, + settings: { + margin: 24, + offset: 100, + selectors: { + moduleDocumentHeader: '.t3js-module-docheader', + moduleDocheaderBar: '.t3js-module-docheader-bar', + moduleNavigationBar: '.t3js-module-docheader-bar-navigation', + moduleButtonBar: '.t3js-module-docheader-bar-buttons', + moduleSearchBar: '.t3js-module-docheader-bar-search', + moduleBody: '.t3js-module-body' - } - } - }; + } + } + }; - /** - * Reposition - */ - DocumentHeader.reposition = function() { - DocumentHeader.$documentHeader.css('height', 'auto'); - DocumentHeader.$documentHeaderBars.css('height', 'auto'); - DocumentHeader.$moduleBody.css('padding-top', DocumentHeader.$documentHeader.outerHeight() + DocumentHeader.settings.margin); - }; + /** + * Reposition + */ + DocumentHeader.reposition = function() { + DocumentHeader.$documentHeader.css('height', 'auto'); + DocumentHeader.$documentHeaderBars.css('height', 'auto'); + DocumentHeader.$moduleBody.css('padding-top', DocumentHeader.$documentHeader.outerHeight() + DocumentHeader.settings.margin); + }; - /** - * Scroll - */ - DocumentHeader.scroll = function() { - DocumentHeader.currentPosition = $(window).scrollTop(); - if (DocumentHeader.currentPosition > DocumentHeader.lastPosition) { - if (DocumentHeader.direction !== 'down') { - DocumentHeader.direction = 'down'; - DocumentHeader.changedPosition = DocumentHeader.currentPosition; - } - } else if (DocumentHeader.currentPosition < DocumentHeader.lastPosition) { - if (DocumentHeader.direction !== 'up') { - DocumentHeader.direction = 'up'; - DocumentHeader.changedPosition = DocumentHeader.currentPosition; - } - } - if (DocumentHeader.direction === 'up' && (DocumentHeader.changedPosition - DocumentHeader.reactionRange) < DocumentHeader.currentPosition) { - DocumentHeader.$documentHeader.css('margin-top', 0); - } - if (DocumentHeader.direction === 'down' && (DocumentHeader.changedPosition + DocumentHeader.reactionRange) < DocumentHeader.currentPosition) { - DocumentHeader.$documentHeader.css('margin-top', (DocumentHeader.$documentHeaderNavigationBar.outerHeight() + 4) * -1); - } - DocumentHeader.lastPosition = DocumentHeader.currentPosition; - }; + /** + * Scroll + */ + DocumentHeader.scroll = function() { + DocumentHeader.currentPosition = $(window).scrollTop(); + if (DocumentHeader.currentPosition > DocumentHeader.lastPosition) { + if (DocumentHeader.direction !== 'down') { + DocumentHeader.direction = 'down'; + DocumentHeader.changedPosition = DocumentHeader.currentPosition; + } + } else if (DocumentHeader.currentPosition < DocumentHeader.lastPosition) { + if (DocumentHeader.direction !== 'up') { + DocumentHeader.direction = 'up'; + DocumentHeader.changedPosition = DocumentHeader.currentPosition; + } + } + if (DocumentHeader.direction === 'up' && (DocumentHeader.changedPosition - DocumentHeader.reactionRange) < DocumentHeader.currentPosition) { + DocumentHeader.$documentHeader.css('margin-top', 0); + } + if (DocumentHeader.direction === 'down' && (DocumentHeader.changedPosition + DocumentHeader.reactionRange) < DocumentHeader.currentPosition) { + DocumentHeader.$documentHeader.css('margin-top', (DocumentHeader.$documentHeaderNavigationBar.outerHeight() + 4) * -1); + } + DocumentHeader.lastPosition = DocumentHeader.currentPosition; + }; - /** - * Start - */ - DocumentHeader.start = function() { - DocumentHeader.reposition(); - $(window).on('resize', DocumentHeader.reposition); - $(window).on('scroll', DocumentHeader.scroll); - }; + /** + * Start + */ + DocumentHeader.start = function() { + DocumentHeader.reposition(); + $(window).on('resize', DocumentHeader.reposition); + $(window).on('scroll', DocumentHeader.scroll); + }; - /** - * Initialize - */ - DocumentHeader.initialize = function() { - DocumentHeader.$documentHeader = $(DocumentHeader.settings.selectors.moduleDocumentHeader); - if (DocumentHeader.$documentHeader.length > 0) { - DocumentHeader.$documentHeaderBars = $(DocumentHeader.settings.selectors.moduleDocheaderBar); - DocumentHeader.$documentHeaderNavigationBar = $(DocumentHeader.settings.selectors.moduleNavigationBar); - DocumentHeader.$documentHeaderSearchBar = $(DocumentHeader.settings.selectors.moduleSearchBar).remove(); - if (DocumentHeader.$documentHeaderSearchBar.length > 0) { - DocumentHeader.$documentHeader.append(DocumentHeader.$documentHeaderSearchBar); - } - DocumentHeader.$moduleBody = $(DocumentHeader.settings.selectors.moduleBody); - DocumentHeader.start(); - } - }; + /** + * Initialize + */ + DocumentHeader.initialize = function() { + DocumentHeader.$documentHeader = $(DocumentHeader.settings.selectors.moduleDocumentHeader); + if (DocumentHeader.$documentHeader.length > 0) { + DocumentHeader.$documentHeaderBars = $(DocumentHeader.settings.selectors.moduleDocheaderBar); + DocumentHeader.$documentHeaderNavigationBar = $(DocumentHeader.settings.selectors.moduleNavigationBar); + DocumentHeader.$documentHeaderSearchBar = $(DocumentHeader.settings.selectors.moduleSearchBar).remove(); + if (DocumentHeader.$documentHeaderSearchBar.length > 0) { + DocumentHeader.$documentHeader.append(DocumentHeader.$documentHeaderSearchBar); + } + DocumentHeader.$moduleBody = $(DocumentHeader.settings.selectors.moduleBody); + DocumentHeader.start(); + } + }; - $(DocumentHeader.initialize); + $(DocumentHeader.initialize); - return DocumentHeader; + return DocumentHeader; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js index 267bf7d4277cda2d906f76d3fd2acd1293403462..8eb132cc6b16764fbc5af43edd339185904a7b4c 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js @@ -16,664 +16,662 @@ * */ define(['jquery', - 'moment', - 'nprogress', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Lang/Lang' - ], function($, moment, NProgress, Modal, Notification, Severity) { - - /** - * Array of files which are asked for being overridden - * - * @type {array} - */ - var askForOverride = [], - percentagePerFile = 1; - - /** - * File actions - */ - var actions = { - OVERRIDE: 'replace', - RENAME: 'rename', - SKIP: 'cancel', - USE_EXISTING: 'useExisting' - }; - - /* - * part 1: a generic jQuery plugin "$.dragUploader" - */ - - // register the constructor - /** - * - * @param {HTMLElement} element - * @constructor - * @exports TYPO3/CMS/Backend/DragUploader - */ - var DragUploaderPlugin = function(element) { - var me = this; - me.$body = $('body'); - me.$element = $(element); - me.$trigger = $(me.$element.data('dropzoneTrigger')); - me.$dropzone = $('<div />').addClass('dropzone').hide(); - me.irreObjectUid = me.$element.data('fileIrreObject'); - var dropZoneEscapedTarget = me.$element.data('dropzoneTarget'); - if (me.irreObjectUid && me.$element.nextAll(dropZoneEscapedTarget).length !== 0) { - me.dropZoneInsertBefore = true; - me.$dropzone.insertBefore(dropZoneEscapedTarget); - } else { - me.dropZoneInsertBefore = false; - me.$dropzone.insertAfter(dropZoneEscapedTarget); - } - me.$dropzoneMask = $('<div />').addClass('dropzone-mask').appendTo(me.$dropzone); - me.$fileInput = $('<input type="file" multiple name="files[]" />').addClass('upload-file-picker').appendTo(me.$body); - me.$fileList = $(me.$element.data('progress-container')); - me.fileListColumnCount = $('thead tr:first th', me.$fileList).length; - me.filesExtensionsAllowed = me.$element.data('file-allowed'); - me.fileDenyPattern = me.$element.data('file-deny-pattern') ? new RegExp(me.$element.data('file-deny-pattern'), 'i') : false; - me.maxFileSize = parseInt(me.$element.data('max-file-size')); - me.target = me.$element.data('target-folder'); - - me.browserCapabilities = { - fileReader: typeof FileReader !== 'undefined', - DnD: 'draggable' in document.createElement('span'), - FormData: !!window.FormData, - Progress: "upload" in new XMLHttpRequest - }; - - /** - * - */ - me.showDropzone = function() { - me.$dropzone.show(); - }; - - /** - * - * @param {Event} event - */ - me.hideDropzone = function(event) { - event.stopPropagation(); - event.preventDefault(); - me.$dropzone.hide(); - }; - - /** - * - * @param {Event} event - * @returns {Boolean} - */ - me.dragFileIntoDocument = function(event) { - event.stopPropagation(); - event.preventDefault(); - me.$body.addClass('drop-in-progress'); - me.showDropzone(); - return false; - }; - - /** - * - * @param {Event} event - * @returns {Boolean} - */ - me.dragAborted = function(event) { - event.stopPropagation(); - event.preventDefault(); - me.$body.removeClass('drop-in-progress'); - return false; - }; - - /** - * - * @param {Event} event - * @returns {Boolean} - */ - me.ignoreDrop = function(event) { - // stops the browser from redirecting. - event.stopPropagation(); - event.preventDefault(); - me.dragAborted(event); - return false; - }; - - /** - * - * @param {Event} event - */ - me.handleDrop = function(event) { - me.ignoreDrop(event); - me.processFiles(event.originalEvent.dataTransfer.files); - me.$dropzone.removeClass('drop-status-ok'); - }; - - /** - * - * @param {Array} files - */ - me.processFiles = function(files) { - me.queueLength = files.length; - - if (!me.$fileList.is(':visible')) { - me.$fileList.show(); - } - - NProgress.start(); - percentagePerFile = 1 / files.length; - - // Check for each file if is already exist before adding it to the queue - var ajaxCalls = []; - $.each(files, function(i, file) { - - ajaxCalls[i] = $.ajax({ - url: TYPO3.settings.ajaxUrls['file_exists'], - data: { - fileName: file.name, - fileTarget: me.target - }, - cache: false, - success: function(response) { - var fileExists = typeof response.uid !== 'undefined'; - if (fileExists) { - askForOverride.push({ - original: response, - uploaded: file, - action: me.irreObjectUid ? actions.USE_EXISTING : actions.SKIP - }); - NProgress.inc(percentagePerFile); - } else { - new FileQueueItem(me, file, 'cancel'); - } - } - }); - }); - - $.when.apply($, ajaxCalls).done(function () { - me.drawOverrideModal(); - NProgress.done(); - }); - - delete ajaxCalls; - me.$fileInput.val(''); - }; - - /** - * - * @param {Event} event - */ - me.fileInDropzone = function(event) { - me.$dropzone.addClass('drop-status-ok'); - }; - - /** - * - * @param {Event} event - */ - me.fileOutOfDropzone = function(event) { - me.$dropzone.removeClass('drop-status-ok'); - }; - - /** - * bind file picker to default upload button - * - * @param {Object} button - */ - me.bindUploadButton = function(button) { - button.click(function(event) { - event.preventDefault(); - me.$fileInput.click(); - me.showDropzone(); - }); - }; - - if (me.browserCapabilities.DnD) { - me.$body.on('dragover', me.dragFileIntoDocument); - me.$body.on('dragend', me.dragAborted); - me.$body.on('drop', me.ignoreDrop); - - me.$dropzone.on('dragenter', me.fileInDropzone); - me.$dropzoneMask.on('dragenter', me.fileInDropzone); - me.$dropzoneMask.on('dragleave', me.fileOutOfDropzone); - me.$dropzoneMask.on('drop', me.handleDrop); - - me.$dropzone.prepend( - '<div class="dropzone-hint">' + - '<div class="dropzone-hint-media">' + - '<div class="dropzone-hint-icon"></div>' + - '</div>' + - '<div class="dropzone-hint-body">' + - '<h3 class="dropzone-hint-title">' + - TYPO3.lang['file_upload.dropzonehint.title'] + - '</h3>' + - '<p class="dropzone-hint-message">' + - TYPO3.lang['file_upload.dropzonehint.message'] + - '</p>' + - '</div>' + - '</div>').click(function() { - me.$fileInput.click() - }); - $('<span />').addClass('dropzone-close').click(me.hideDropzone).appendTo(me.$dropzone); - - // no filelist then create own progress table - if (me.$fileList.length === 0) { - me.$fileList = $('<table />').attr('id', 'typo3-filelist').addClass('table table-striped table-hover upload-queue').html('<tbody></tbody>').hide(); - if (me.dropZoneInsertBefore) { - me.$fileList.insertAfter(me.$dropzone); - } else { - me.$fileList.insertBefore(me.$dropzone); - } - me.fileListColumnCount = 7; - } - - me.$fileInput.on('change', function() { - me.processFiles(this.files); - }); - - me.bindUploadButton(me.$trigger.length ? me.$trigger : me.$element); - } - - /** - * - */ - me.decrementQueueLength = function() { - if (me.queueLength > 0) { - me.queueLength--; - if (me.queueLength === 0) { - $.ajax({ - url: TYPO3.settings.ajaxUrls['flashmessages_render'], - cache: false, - success: function(data) { - $.each(data, function(index, flashMessage) { - Notification.showMessage(flashMessage.title, flashMessage.message, flashMessage.severity); - }); - } - }); - } - } - }; - - /** - * - */ - me.drawOverrideModal = function() { - var amountOfItems = Object.keys(askForOverride).length; - if (amountOfItems === 0) { - return; - } - var $modalContent = $('<div/>').append( - $('<p/>').text(TYPO3.lang['file_upload.existingfiles.description']), - $('<table/>', {class: 'table table-striped'}).append( - $('<tr />').append( - $('<th/>'), - $('<th/>').text(TYPO3.lang['file_upload.header.originalFile']), - $('<th/>').text(TYPO3.lang['file_upload.header.uploadedFile']), - $('<th/>').text(TYPO3.lang['file_upload.header.action']) - ) - ) - ); - - for (var i = 0; i < amountOfItems; ++i) { - var $record = $('<tr />').append( - $('<td />').append( - (askForOverride[i].original.thumbUrl !== '' - ? $('<img />', {src: askForOverride[i].original.thumbUrl, height: 40}) - : $(askForOverride[i].original.icon) - ) - ), - $('<td />').html( - askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].uploaded.size)) + ')' + - '<br>' + moment(askForOverride[i].uploaded.lastModified, 'x').format('YYYY-MM-DD HH:mm') - ), - $('<td />').html( - askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].original.size)) + ')' + - '<br>' + moment(askForOverride[i].original.mtime, 'X').format('YYYY-MM-DD HH:mm') - ), - $('<td />').append( - $('<select />', {class: 'form-control t3js-actions', 'data-override': i}).append( - (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.use_existing']) : ''), - $('<option />').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.skip']), - $('<option />').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.rename']), - $('<option />').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.override']) - ) - ) - ); - $modalContent.find('table').append($record); - } - - var $modal = Modal.confirm(TYPO3.lang['file_upload.existingfiles.title'], $modalContent, Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['file_upload.button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['file_upload.button.continue'] || 'Continue with selected actions', - btnClass: 'btn-warning', - name: 'continue' - } - ], ['modal-inner-scroll']); - $modal.find('.modal-dialog').addClass('modal-lg'); - - $modal.find('.modal-footer').prepend( - $('<span/>').addClass('form-inline pull-left').append( - $('<label/>').text(TYPO3.lang['file_upload.actions.all.label']), - $('<select/>', {class: 'form-control t3js-actions-all'}).append( - $('<option/>').val('').text(TYPO3.lang['file_upload.actions.all.empty']), - (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.all.use_existing']) : ''), - $('<option/>').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.all.skip']), - $('<option/>').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.all.rename']), - $('<option/>').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.all.override']) - ) - ) - ); - - $modal.on('change', '.t3js-actions-all', function() { - var $me = $(this), - value = $me.val(); - - if (value !== '') { - // mass action was selected, apply action to every file - $modal.find('.t3js-actions').each(function (i, select) { - var $select = $(select), - index = parseInt($select.data('override')); - $select.val(value).prop('disabled', 'disabled'); - askForOverride[index].action = $select.val(); - }); - } else { - $modal.find('.t3js-actions').removeProp('disabled'); - } - }).on('change', '.t3js-actions', function() { - var $me = $(this), - index = parseInt($me.data('override')); - askForOverride[index].action = $me.val(); - }).on('button.clicked', function(e) { - if (e.target.name === 'cancel') { - askForOverride = []; - Modal.dismiss(); - } else if (e.target.name === 'continue') { - $.each(askForOverride, function(key, fileInfo) { - if (fileInfo.action === actions.USE_EXISTING) { - DragUploader.addFileToIrre( - me.irreObjectUid, - fileInfo.original - ); - } else if (fileInfo.action !== actions.SKIP) { - new FileQueueItem(me, fileInfo.uploaded, fileInfo.action); - } - }); - askForOverride = []; - Modal.dismiss(); - } - }).on('hidden.bs.modal', function() { - askForOverride = []; - }); - } - }; - - var FileQueueItem = function(dragUploader, file, override) { - var me = this; - me.dragUploader = dragUploader; - me.file = file; - me.override = override; - - me.$row = $('<tr />').addClass('upload-queue-item uploading'); - me.$iconCol = $('<td />').addClass('col-icon').appendTo(me.$row); - me.$fileName = $('<td />').text(file.name).appendTo(me.$row); - me.$progress = $('<td />').attr('colspan', me.dragUploader.fileListColumnCount-2).appendTo(me.$row); - me.$progressContainer = $('<div />').addClass('upload-queue-progress').appendTo(me.$progress); - me.$progressBar = $('<div />').addClass('upload-queue-progress-bar').appendTo(me.$progressContainer); - me.$progressPercentage = $('<span />').addClass('upload-queue-progress-percentage').appendTo(me.$progressContainer); - me.$progressMessage = $('<span />').addClass('upload-queue-progress-message').appendTo(me.$progressContainer); - - me.updateMessage = function(message) { - me.$progressMessage.text(message); - }; - - me.removeProgress = function() { - if (me.$progress) { - me.$progress.remove(); - } - }; - - me.uploadStart = function() { - me.$progressPercentage.text('(0%)'); - me.$progressBar.width('1%'); - me.dragUploader.$trigger.trigger('uploadStart', [me]); - }; - - me.uploadError = function(response) { - me.updateMessage(TYPO3.lang['file_upload.uploadFailed'].replace(/\{0\}/g, me.file.name)); - var error = $(response.responseText); - if (error.is('t3err')) { - me.$progressPercentage.text(error.text()); - } else { - me.$progressPercentage.text('(' + response.statusText + ')'); - } - me.$row.addClass('error'); - me.dragUploader.decrementQueueLength(); - me.dragUploader.$trigger.trigger('uploadError', [me, response]); - }; - - me.updateProgress = function(event) { - var percentage = Math.round((event.loaded / event.total) * 100) + '%'; - me.$progressBar.outerWidth(percentage); - me.$progressPercentage.text(percentage); - me.dragUploader.$trigger.trigger('updateProgress', [me, percentage, event]); - }; - - me.uploadSuccess = function(data) { - if (data.upload) { - me.dragUploader.decrementQueueLength(); - me.$row.removeClass('uploading'); - me.$fileName.text(data.upload[0].name); - me.$progressPercentage.text(''); - me.$progressMessage.text('100%'); - me.$progressBar.outerWidth('100%'); - - // replace file icon - if (data.upload[0].icon) { - me.$iconCol.html('<a href="#" class="t3js-contextmenutrigger" data-uid="' + data.upload[0].id + '" data-table="sys_file">' + data.upload[0].icon + ' </span></a>'); - } - - if (me.dragUploader.irreObjectUid) { - DragUploader.addFileToIrre( - me.dragUploader.irreObjectUid, - data.upload[0] - ); - setTimeout(function() { - me.$row.remove(); - if ($('tr', me.dragUploader.$fileList).length === 0) { - me.dragUploader.$fileList.hide(); - me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]); - } - }, 3000); - } else { - setTimeout(function() { - me.showFileInfo(data.upload[0]); - me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]); - }, 3000); - } - } - }; - - me.showFileInfo = function(fileInfo) { - me.removeProgress(); - // add spacing cells when clibboard and/or extended view is enabled - for (i = 7; i < me.dragUploader.fileListColumnCount; i++) { - $('<td />').text('').appendTo(me.$row); - } - $('<td />').text(fileInfo.extension.toUpperCase()).appendTo(me.$row); - $('<td />').text(fileInfo.date).appendTo(me.$row); - $('<td />').text(DragUploader.fileSizeAsString(fileInfo.size)).appendTo(me.$row); - var permissions = ''; - if (fileInfo.permissions.read) { - permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.read'] + '</strong>'; - } - if (fileInfo.permissions.write) { - permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.write'] + '</strong>'; - } - $('<td />').html(permissions).appendTo(me.$row); - $('<td />').text('-').appendTo(me.$row); - }; - - me.checkAllowedExtensions = function() { - if (!me.dragUploader.filesExtensionsAllowed) { - return true; - } - var extension = me.file.name.split('.').pop(); - var allowed = me.dragUploader.filesExtensionsAllowed.split(','); - if ($.inArray(extension.toLowerCase(), allowed) !== -1) { - return true; - } - return false; - }; - - // position queue item in filelist - if ($('tbody tr.upload-queue-item', me.dragUploader.$fileList).length === 0) { - me.$row.prependTo($('tbody', me.dragUploader.$fileList)); - me.$row.addClass('last'); - } else { - me.$row.insertBefore($('tbody tr.upload-queue-item:first', me.dragUploader.$fileList)); - } - - // set dummy file icon - me.$iconCol.html('<span class="t3-icon t3-icon-mimetypes t3-icon-other-other"> </span>') - - // check file size - if (me.dragUploader.maxFileSize > 0 && me.file.size > me.dragUploader.maxFileSize) { - me.updateMessage(TYPO3.lang['file_upload.maxFileSizeExceeded'] - .replace(/\{0\}/g, me.file.name) - .replace(/\{1\}/g, DragUploader.fileSizeAsString(me.dragUploader.maxFileSize))); - me.$row.addClass('error'); - - // check filename/extension against deny pattern - } else if (me.dragUploader.fileDenyPattern && me.file.name.match(me.dragUploader.fileDenyPattern)) { - me.updateMessage(TYPO3.lang['file_upload.fileNotAllowed'].replace(/\{0\}/g, me.file.name)); - me.$row.addClass('error'); - - } else if (!me.checkAllowedExtensions()) { - me.updateMessage(TYPO3.lang['file_upload.fileExtensionExpected'] - .replace(/\{0\}/g, me.dragUploader.filesExtensionsAllowed) - ); - me.$row.addClass('error'); - } else { - me.updateMessage('- ' + DragUploader.fileSizeAsString(me.file.size)); - - var formData = new FormData(); - formData.append('data[upload][1][target]', me.dragUploader.target); - formData.append('data[upload][1][data]', '1'); - formData.append('overwriteExistingFiles', me.override); - formData.append('redirect', ''); - formData.append('upload_1', me.file); - - var s = $.extend(true, {}, $.ajaxSettings, { - url: TYPO3.settings.ajaxUrls['file_process'], - contentType: false, - processData: false, - data: formData, - cache: false, - type: 'POST', - success: me.uploadSuccess, - error: me.uploadError - }); - - s.xhr = function() { - var xhr = $.ajaxSettings.xhr(); - xhr.upload.addEventListener('progress', me.updateProgress); - return xhr; - }; - - // start upload - me.upload = $.ajax(s); - } - }; - - /** - * part 2: The main module of this file - * - initialize the DragUploader module and register - * the jQuery plugin in the jQuery global object - * when initializing the DragUploader module - */ - var DragUploader = {}; - - DragUploader.options = { - }; - - DragUploader.fileSizeAsString = function(size) { - var string = '', - sizeKB = size / 1024; - - if (parseInt(sizeKB) > 1024) { - var sizeMB = sizeKB / 1024; - string = sizeMB.toFixed(1) + ' MB'; - } else { - string = sizeKB.toFixed(1) + ' KB'; - } - return string; - }; - - DragUploader.addFileToIrre = function(irre_object, file) { - inline.delayedImportElement( - irre_object, - 'sys_file', - file.uid, - 'file' - ); - }; - - DragUploader.initialize = function() { - var me = this, - opts = me.options; - - // register the jQuery plugin "DragUploaderPlugin" - $.fn.dragUploader = function(option) { - return this.each(function() { - var $this = $(this), - data = $this.data('DragUploaderPlugin'); - if (!data) { - $this.data('DragUploaderPlugin', (data = new DragUploaderPlugin(this))); - } - if (typeof option === 'string') { - data[option](); - } - }); - }; - - $(function() { - $('.t3js-drag-uploader').dragUploader(); - }); - }; - - - - /** - * part 3: initialize the RequireJS module, require possible post-initialize hooks, - * and return the main object - */ - var initialize = function() { - - DragUploader.initialize(); - - // load required modules to hook in the post initialize function - if ( - 'undefined' !== typeof TYPO3.settings - && 'undefined' !== typeof TYPO3.settings.RequireJS - && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules - && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'] - ) { - $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'], function(pos, moduleName) { - require([moduleName]); - }); - } - - // return the object in the global space - return DragUploader; - }; - - // call the main initialize function and execute the hooks - return initialize(); + 'moment', + 'nprogress', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Lang/Lang' +], function($, moment, NProgress, Modal, Notification, Severity) { + + /** + * Array of files which are asked for being overridden + * + * @type {array} + */ + var askForOverride = [], + percentagePerFile = 1; + + /** + * File actions + */ + var actions = { + OVERRIDE: 'replace', + RENAME: 'rename', + SKIP: 'cancel', + USE_EXISTING: 'useExisting' + }; + + /* + * part 1: a generic jQuery plugin "$.dragUploader" + */ + + // register the constructor + /** + * + * @param {HTMLElement} element + * @constructor + * @exports TYPO3/CMS/Backend/DragUploader + */ + var DragUploaderPlugin = function(element) { + var me = this; + me.$body = $('body'); + me.$element = $(element); + me.$trigger = $(me.$element.data('dropzoneTrigger')); + me.$dropzone = $('<div />').addClass('dropzone').hide(); + me.irreObjectUid = me.$element.data('fileIrreObject'); + var dropZoneEscapedTarget = me.$element.data('dropzoneTarget'); + if (me.irreObjectUid && me.$element.nextAll(dropZoneEscapedTarget).length !== 0) { + me.dropZoneInsertBefore = true; + me.$dropzone.insertBefore(dropZoneEscapedTarget); + } else { + me.dropZoneInsertBefore = false; + me.$dropzone.insertAfter(dropZoneEscapedTarget); + } + me.$dropzoneMask = $('<div />').addClass('dropzone-mask').appendTo(me.$dropzone); + me.$fileInput = $('<input type="file" multiple name="files[]" />').addClass('upload-file-picker').appendTo(me.$body); + me.$fileList = $(me.$element.data('progress-container')); + me.fileListColumnCount = $('thead tr:first th', me.$fileList).length; + me.filesExtensionsAllowed = me.$element.data('file-allowed'); + me.fileDenyPattern = me.$element.data('file-deny-pattern') ? new RegExp(me.$element.data('file-deny-pattern'), 'i') : false; + me.maxFileSize = parseInt(me.$element.data('max-file-size')); + me.target = me.$element.data('target-folder'); + + me.browserCapabilities = { + fileReader: typeof FileReader !== 'undefined', + DnD: 'draggable' in document.createElement('span'), + FormData: !!window.FormData, + Progress: "upload" in new XMLHttpRequest + }; + + /** + * + */ + me.showDropzone = function() { + me.$dropzone.show(); + }; + + /** + * + * @param {Event} event + */ + me.hideDropzone = function(event) { + event.stopPropagation(); + event.preventDefault(); + me.$dropzone.hide(); + }; + + /** + * + * @param {Event} event + * @returns {Boolean} + */ + me.dragFileIntoDocument = function(event) { + event.stopPropagation(); + event.preventDefault(); + me.$body.addClass('drop-in-progress'); + me.showDropzone(); + return false; + }; + + /** + * + * @param {Event} event + * @returns {Boolean} + */ + me.dragAborted = function(event) { + event.stopPropagation(); + event.preventDefault(); + me.$body.removeClass('drop-in-progress'); + return false; + }; + + /** + * + * @param {Event} event + * @returns {Boolean} + */ + me.ignoreDrop = function(event) { + // stops the browser from redirecting. + event.stopPropagation(); + event.preventDefault(); + me.dragAborted(event); + return false; + }; + + /** + * + * @param {Event} event + */ + me.handleDrop = function(event) { + me.ignoreDrop(event); + me.processFiles(event.originalEvent.dataTransfer.files); + me.$dropzone.removeClass('drop-status-ok'); + }; + + /** + * + * @param {Array} files + */ + me.processFiles = function(files) { + me.queueLength = files.length; + + if (!me.$fileList.is(':visible')) { + me.$fileList.show(); + } + + NProgress.start(); + percentagePerFile = 1 / files.length; + + // Check for each file if is already exist before adding it to the queue + var ajaxCalls = []; + $.each(files, function(i, file) { + + ajaxCalls[i] = $.ajax({ + url: TYPO3.settings.ajaxUrls['file_exists'], + data: { + fileName: file.name, + fileTarget: me.target + }, + cache: false, + success: function(response) { + var fileExists = typeof response.uid !== 'undefined'; + if (fileExists) { + askForOverride.push({ + original: response, + uploaded: file, + action: me.irreObjectUid ? actions.USE_EXISTING : actions.SKIP + }); + NProgress.inc(percentagePerFile); + } else { + new FileQueueItem(me, file, 'cancel'); + } + } + }); + }); + + $.when.apply($, ajaxCalls).done(function() { + me.drawOverrideModal(); + NProgress.done(); + }); + + delete ajaxCalls; + me.$fileInput.val(''); + }; + + /** + * + * @param {Event} event + */ + me.fileInDropzone = function(event) { + me.$dropzone.addClass('drop-status-ok'); + }; + + /** + * + * @param {Event} event + */ + me.fileOutOfDropzone = function(event) { + me.$dropzone.removeClass('drop-status-ok'); + }; + + /** + * bind file picker to default upload button + * + * @param {Object} button + */ + me.bindUploadButton = function(button) { + button.click(function(event) { + event.preventDefault(); + me.$fileInput.click(); + me.showDropzone(); + }); + }; + + if (me.browserCapabilities.DnD) { + me.$body.on('dragover', me.dragFileIntoDocument); + me.$body.on('dragend', me.dragAborted); + me.$body.on('drop', me.ignoreDrop); + + me.$dropzone.on('dragenter', me.fileInDropzone); + me.$dropzoneMask.on('dragenter', me.fileInDropzone); + me.$dropzoneMask.on('dragleave', me.fileOutOfDropzone); + me.$dropzoneMask.on('drop', me.handleDrop); + + me.$dropzone.prepend( + '<div class="dropzone-hint">' + + '<div class="dropzone-hint-media">' + + '<div class="dropzone-hint-icon"></div>' + + '</div>' + + '<div class="dropzone-hint-body">' + + '<h3 class="dropzone-hint-title">' + + TYPO3.lang['file_upload.dropzonehint.title'] + + '</h3>' + + '<p class="dropzone-hint-message">' + + TYPO3.lang['file_upload.dropzonehint.message'] + + '</p>' + + '</div>' + + '</div>').click(function() { + me.$fileInput.click() + }); + $('<span />').addClass('dropzone-close').click(me.hideDropzone).appendTo(me.$dropzone); + + // no filelist then create own progress table + if (me.$fileList.length === 0) { + me.$fileList = $('<table />').attr('id', 'typo3-filelist').addClass('table table-striped table-hover upload-queue').html('<tbody></tbody>').hide(); + if (me.dropZoneInsertBefore) { + me.$fileList.insertAfter(me.$dropzone); + } else { + me.$fileList.insertBefore(me.$dropzone); + } + me.fileListColumnCount = 7; + } + + me.$fileInput.on('change', function() { + me.processFiles(this.files); + }); + + me.bindUploadButton(me.$trigger.length ? me.$trigger : me.$element); + } + + /** + * + */ + me.decrementQueueLength = function() { + if (me.queueLength > 0) { + me.queueLength--; + if (me.queueLength === 0) { + $.ajax({ + url: TYPO3.settings.ajaxUrls['flashmessages_render'], + cache: false, + success: function(data) { + $.each(data, function(index, flashMessage) { + Notification.showMessage(flashMessage.title, flashMessage.message, flashMessage.severity); + }); + } + }); + } + } + }; + + /** + * + */ + me.drawOverrideModal = function() { + var amountOfItems = Object.keys(askForOverride).length; + if (amountOfItems === 0) { + return; + } + var $modalContent = $('<div/>').append( + $('<p/>').text(TYPO3.lang['file_upload.existingfiles.description']), + $('<table/>', {class: 'table table-striped'}).append( + $('<tr />').append( + $('<th/>'), + $('<th/>').text(TYPO3.lang['file_upload.header.originalFile']), + $('<th/>').text(TYPO3.lang['file_upload.header.uploadedFile']), + $('<th/>').text(TYPO3.lang['file_upload.header.action']) + ) + ) + ); + + for (var i = 0; i < amountOfItems; ++i) { + var $record = $('<tr />').append( + $('<td />').append( + (askForOverride[i].original.thumbUrl !== '' + ? $('<img />', {src: askForOverride[i].original.thumbUrl, height: 40}) + : $(askForOverride[i].original.icon) + ) + ), + $('<td />').html( + askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].uploaded.size)) + ')' + + '<br>' + moment(askForOverride[i].uploaded.lastModified, 'x').format('YYYY-MM-DD HH:mm') + ), + $('<td />').html( + askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].original.size)) + ')' + + '<br>' + moment(askForOverride[i].original.mtime, 'X').format('YYYY-MM-DD HH:mm') + ), + $('<td />').append( + $('<select />', {class: 'form-control t3js-actions', 'data-override': i}).append( + (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.use_existing']) : ''), + $('<option />').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.skip']), + $('<option />').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.rename']), + $('<option />').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.override']) + ) + ) + ); + $modalContent.find('table').append($record); + } + + var $modal = Modal.confirm(TYPO3.lang['file_upload.existingfiles.title'], $modalContent, Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['file_upload.button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['file_upload.button.continue'] || 'Continue with selected actions', + btnClass: 'btn-warning', + name: 'continue' + } + ], ['modal-inner-scroll']); + $modal.find('.modal-dialog').addClass('modal-lg'); + + $modal.find('.modal-footer').prepend( + $('<span/>').addClass('form-inline pull-left').append( + $('<label/>').text(TYPO3.lang['file_upload.actions.all.label']), + $('<select/>', {class: 'form-control t3js-actions-all'}).append( + $('<option/>').val('').text(TYPO3.lang['file_upload.actions.all.empty']), + (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.all.use_existing']) : ''), + $('<option/>').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.all.skip']), + $('<option/>').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.all.rename']), + $('<option/>').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.all.override']) + ) + ) + ); + + $modal.on('change', '.t3js-actions-all', function() { + var $me = $(this), + value = $me.val(); + + if (value !== '') { + // mass action was selected, apply action to every file + $modal.find('.t3js-actions').each(function(i, select) { + var $select = $(select), + index = parseInt($select.data('override')); + $select.val(value).prop('disabled', 'disabled'); + askForOverride[index].action = $select.val(); + }); + } else { + $modal.find('.t3js-actions').removeProp('disabled'); + } + }).on('change', '.t3js-actions', function() { + var $me = $(this), + index = parseInt($me.data('override')); + askForOverride[index].action = $me.val(); + }).on('button.clicked', function(e) { + if (e.target.name === 'cancel') { + askForOverride = []; + Modal.dismiss(); + } else if (e.target.name === 'continue') { + $.each(askForOverride, function(key, fileInfo) { + if (fileInfo.action === actions.USE_EXISTING) { + DragUploader.addFileToIrre( + me.irreObjectUid, + fileInfo.original + ); + } else if (fileInfo.action !== actions.SKIP) { + new FileQueueItem(me, fileInfo.uploaded, fileInfo.action); + } + }); + askForOverride = []; + Modal.dismiss(); + } + }).on('hidden.bs.modal', function() { + askForOverride = []; + }); + } + }; + + var FileQueueItem = function(dragUploader, file, override) { + var me = this; + me.dragUploader = dragUploader; + me.file = file; + me.override = override; + + me.$row = $('<tr />').addClass('upload-queue-item uploading'); + me.$iconCol = $('<td />').addClass('col-icon').appendTo(me.$row); + me.$fileName = $('<td />').text(file.name).appendTo(me.$row); + me.$progress = $('<td />').attr('colspan', me.dragUploader.fileListColumnCount - 2).appendTo(me.$row); + me.$progressContainer = $('<div />').addClass('upload-queue-progress').appendTo(me.$progress); + me.$progressBar = $('<div />').addClass('upload-queue-progress-bar').appendTo(me.$progressContainer); + me.$progressPercentage = $('<span />').addClass('upload-queue-progress-percentage').appendTo(me.$progressContainer); + me.$progressMessage = $('<span />').addClass('upload-queue-progress-message').appendTo(me.$progressContainer); + + me.updateMessage = function(message) { + me.$progressMessage.text(message); + }; + + me.removeProgress = function() { + if (me.$progress) { + me.$progress.remove(); + } + }; + + me.uploadStart = function() { + me.$progressPercentage.text('(0%)'); + me.$progressBar.width('1%'); + me.dragUploader.$trigger.trigger('uploadStart', [me]); + }; + + me.uploadError = function(response) { + me.updateMessage(TYPO3.lang['file_upload.uploadFailed'].replace(/\{0\}/g, me.file.name)); + var error = $(response.responseText); + if (error.is('t3err')) { + me.$progressPercentage.text(error.text()); + } else { + me.$progressPercentage.text('(' + response.statusText + ')'); + } + me.$row.addClass('error'); + me.dragUploader.decrementQueueLength(); + me.dragUploader.$trigger.trigger('uploadError', [me, response]); + }; + + me.updateProgress = function(event) { + var percentage = Math.round((event.loaded / event.total) * 100) + '%'; + me.$progressBar.outerWidth(percentage); + me.$progressPercentage.text(percentage); + me.dragUploader.$trigger.trigger('updateProgress', [me, percentage, event]); + }; + + me.uploadSuccess = function(data) { + if (data.upload) { + me.dragUploader.decrementQueueLength(); + me.$row.removeClass('uploading'); + me.$fileName.text(data.upload[0].name); + me.$progressPercentage.text(''); + me.$progressMessage.text('100%'); + me.$progressBar.outerWidth('100%'); + + // replace file icon + if (data.upload[0].icon) { + me.$iconCol.html('<a href="#" class="t3js-contextmenutrigger" data-uid="' + data.upload[0].id + '" data-table="sys_file">' + data.upload[0].icon + ' </span></a>'); + } + + if (me.dragUploader.irreObjectUid) { + DragUploader.addFileToIrre( + me.dragUploader.irreObjectUid, + data.upload[0] + ); + setTimeout(function() { + me.$row.remove(); + if ($('tr', me.dragUploader.$fileList).length === 0) { + me.dragUploader.$fileList.hide(); + me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]); + } + }, 3000); + } else { + setTimeout(function() { + me.showFileInfo(data.upload[0]); + me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]); + }, 3000); + } + } + }; + + me.showFileInfo = function(fileInfo) { + me.removeProgress(); + // add spacing cells when clibboard and/or extended view is enabled + for (i = 7; i < me.dragUploader.fileListColumnCount; i++) { + $('<td />').text('').appendTo(me.$row); + } + $('<td />').text(fileInfo.extension.toUpperCase()).appendTo(me.$row); + $('<td />').text(fileInfo.date).appendTo(me.$row); + $('<td />').text(DragUploader.fileSizeAsString(fileInfo.size)).appendTo(me.$row); + var permissions = ''; + if (fileInfo.permissions.read) { + permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.read'] + '</strong>'; + } + if (fileInfo.permissions.write) { + permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.write'] + '</strong>'; + } + $('<td />').html(permissions).appendTo(me.$row); + $('<td />').text('-').appendTo(me.$row); + }; + + me.checkAllowedExtensions = function() { + if (!me.dragUploader.filesExtensionsAllowed) { + return true; + } + var extension = me.file.name.split('.').pop(); + var allowed = me.dragUploader.filesExtensionsAllowed.split(','); + if ($.inArray(extension.toLowerCase(), allowed) !== -1) { + return true; + } + return false; + }; + + // position queue item in filelist + if ($('tbody tr.upload-queue-item', me.dragUploader.$fileList).length === 0) { + me.$row.prependTo($('tbody', me.dragUploader.$fileList)); + me.$row.addClass('last'); + } else { + me.$row.insertBefore($('tbody tr.upload-queue-item:first', me.dragUploader.$fileList)); + } + + // set dummy file icon + me.$iconCol.html('<span class="t3-icon t3-icon-mimetypes t3-icon-other-other"> </span>') + + // check file size + if (me.dragUploader.maxFileSize > 0 && me.file.size > me.dragUploader.maxFileSize) { + me.updateMessage(TYPO3.lang['file_upload.maxFileSizeExceeded'] + .replace(/\{0\}/g, me.file.name) + .replace(/\{1\}/g, DragUploader.fileSizeAsString(me.dragUploader.maxFileSize))); + me.$row.addClass('error'); + + // check filename/extension against deny pattern + } else if (me.dragUploader.fileDenyPattern && me.file.name.match(me.dragUploader.fileDenyPattern)) { + me.updateMessage(TYPO3.lang['file_upload.fileNotAllowed'].replace(/\{0\}/g, me.file.name)); + me.$row.addClass('error'); + + } else if (!me.checkAllowedExtensions()) { + me.updateMessage(TYPO3.lang['file_upload.fileExtensionExpected'] + .replace(/\{0\}/g, me.dragUploader.filesExtensionsAllowed) + ); + me.$row.addClass('error'); + } else { + me.updateMessage('- ' + DragUploader.fileSizeAsString(me.file.size)); + + var formData = new FormData(); + formData.append('data[upload][1][target]', me.dragUploader.target); + formData.append('data[upload][1][data]', '1'); + formData.append('overwriteExistingFiles', me.override); + formData.append('redirect', ''); + formData.append('upload_1', me.file); + + var s = $.extend(true, {}, $.ajaxSettings, { + url: TYPO3.settings.ajaxUrls['file_process'], + contentType: false, + processData: false, + data: formData, + cache: false, + type: 'POST', + success: me.uploadSuccess, + error: me.uploadError + }); + + s.xhr = function() { + var xhr = $.ajaxSettings.xhr(); + xhr.upload.addEventListener('progress', me.updateProgress); + return xhr; + }; + + // start upload + me.upload = $.ajax(s); + } + }; + + /** + * part 2: The main module of this file + * - initialize the DragUploader module and register + * the jQuery plugin in the jQuery global object + * when initializing the DragUploader module + */ + var DragUploader = {}; + + DragUploader.options = {}; + + DragUploader.fileSizeAsString = function(size) { + var string = '', + sizeKB = size / 1024; + + if (parseInt(sizeKB) > 1024) { + var sizeMB = sizeKB / 1024; + string = sizeMB.toFixed(1) + ' MB'; + } else { + string = sizeKB.toFixed(1) + ' KB'; + } + return string; + }; + + DragUploader.addFileToIrre = function(irre_object, file) { + inline.delayedImportElement( + irre_object, + 'sys_file', + file.uid, + 'file' + ); + }; + + DragUploader.initialize = function() { + var me = this, + opts = me.options; + + // register the jQuery plugin "DragUploaderPlugin" + $.fn.dragUploader = function(option) { + return this.each(function() { + var $this = $(this), + data = $this.data('DragUploaderPlugin'); + if (!data) { + $this.data('DragUploaderPlugin', (data = new DragUploaderPlugin(this))); + } + if (typeof option === 'string') { + data[option](); + } + }); + }; + + $(function() { + $('.t3js-drag-uploader').dragUploader(); + }); + }; + + + /** + * part 3: initialize the RequireJS module, require possible post-initialize hooks, + * and return the main object + */ + var initialize = function() { + + DragUploader.initialize(); + + // load required modules to hook in the post initialize function + if ( + 'undefined' !== typeof TYPO3.settings + && 'undefined' !== typeof TYPO3.settings.RequireJS + && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules + && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'] + ) { + $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'], function(pos, moduleName) { + require([moduleName]); + }); + } + + // return the object in the global space + return DragUploader; + }; + + // call the main initialize function and execute the hooks + return initialize(); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js index 3b1257388c577130aca61bd5fe3b2b6dbf7f90cb..108e2f9a9058014085bf6fbb6910b8166174da38 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js @@ -22,1209 +22,1210 @@ // add legacy functions to be accessible in the global scope var setFormValueOpenBrowser, - setFormValueFromBrowseWin, - setHiddenFromList, - setFormValueManipulate, - setFormValue_getFObj; + setFormValueFromBrowseWin, + setHiddenFromList, + setFormValueManipulate, + setFormValue_getFObj; /** * Module: TYPO3/CMS/Backend/FormEngine */ define(['jquery', - 'TYPO3/CMS/Backend/FormEngineValidation', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/BackendException', - 'TYPO3/CMS/Backend/Event/InteractionRequestMap' - ], function ($, FormEngineValidation, Modal, Severity, BackendException, InteractionRequestMap) { - - /** - * @param {InteractionRequest} interactionRequest - * @param {boolean} response - */ - function handleConsumeResponse(interactionRequest, response) { - if (response) { - FormEngine.interactionRequestMap.resolveFor(interactionRequest); - } else { - FormEngine.interactionRequestMap.rejectFor(interactionRequest); - } - } - - /** - * @exports TYPO3/CMS/Backend/FormEngine - */ - var FormEngine = { - consumeTypes: ['typo3.setUrl', 'typo3.beforeSetUrl', 'typo3.refresh'], - Validation: FormEngineValidation, - interactionRequestMap: InteractionRequestMap, - formName: TYPO3.settings.FormEngine.formName, - openedPopupWindow: null, - legacyFieldChangedCb: function() { !$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb) || TYPO3.settings.FormEngine.legacyFieldChangedCb(); }, - browserUrl: '' - }; - - // functions to connect the db/file browser with this document and the formfields on it! - - /** - * Opens a popup window with the element browser (browser.php) - * - * @param {String} mode can be "db" or "file" - * @param {String} params additional params for the browser window - */ - FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params) { - Modal.advanced({ - type: Modal.types.iframe, - content: FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params, - size: Modal.sizes.large - }); - }; - - /** - * properly fills the select field from the popup window (element browser, link browser) - * or from a multi-select (two selects side-by-side) - * previously known as "setFormValueFromBrowseWin" - * - * @param {String} fieldName Formerly known as "fName" name of the field, like [tt_content][2387][header] - * @param {(String|Number)} value The value to fill in (could be an integer) - * @param {String} label The visible name in the selector - * @param {String} title The title when hovering over it - * @param {String} exclusiveValues If the select field has exclusive options that are not combine-able - * @param {$} $optionEl The jQuery object of the selected <option> tag - */ - FormEngine.setSelectOptionFromExternalSource = setFormValueFromBrowseWin = function(fieldName, value, label, title, exclusiveValues, $optionEl) { - exclusiveValues = String(exclusiveValues); - - var $fieldEl, - $originalFieldEl, - isMultiple = false, - isList = false; - - $originalFieldEl = $fieldEl = FormEngine.getFieldElement(fieldName); - - if ($originalFieldEl.length === 0 || value === '--div--') { - return; - } - - // Check if the form object has a "_list" element - // The "_list" element exists for multiple selection select types - var $listFieldEl = FormEngine.getFieldElement(fieldName, '_list', true); - if ($listFieldEl.length > 0) { - $fieldEl = $listFieldEl; - isMultiple = ($fieldEl.prop('multiple') && $fieldEl.prop('size') != '1'); - isList = true; - } - - // clear field before adding value, if configured so (maxitems==1) - // @todo: clean this code - if (typeof TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName] !== 'undefined') { - var clearSettings = TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName]; - $fieldEl.empty(); - - // Clear the upload field - // @todo: Investigate whether we either need to fix this code or we can drop it. - var filesContainer = document.getElementById(clearSettings.itemFormElID_file); - if (filesContainer) { - filesContainer.innerHTML = filesContainer.innerHTML; - } - } - - if (isMultiple || isList) { - // If multiple values are not allowed, clear anything that is in the control already - if (!isMultiple) { - $fieldEl.empty(); - } - - // Clear elements if exclusive values are found - if (exclusiveValues) { - var reenableOptions = false; - - var m = new RegExp('(^|,)' + value + '($|,)'); - // the new value is exclusive => remove all existing values - if (exclusiveValues.match(m)) { - $fieldEl.empty(); - reenableOptions = true; - } else if ($fieldEl.find('option').length == 1) { - // there is an old value and it was exclusive => it has to be removed - m = new RegExp("(^|,)" + $fieldEl.find('option').prop('value') + "($|,)"); - if (exclusiveValues.match(m)) { - $fieldEl.empty(); - reenableOptions = true; - } - } - - if (reenableOptions && typeof $optionEl !== 'undefined') { - $optionEl.closest('select').find('[disabled]').removeClass('hidden').prop('disabled', false) - } - } - - // Inserting the new element - var addNewValue = true; - - // check if there is a "_mul" field (a field on the right) and if the field was already added - var $multipleFieldEl = FormEngine.getFieldElement(fieldName, '_mul', true); - if ($multipleFieldEl.length == 0 || $multipleFieldEl.val() == 0) { - $fieldEl.find('option').each(function(k, optionEl) { - if ($(optionEl).prop('value') == value) { - addNewValue = false; - return false; - } - }); - - if (addNewValue && typeof $optionEl !== 'undefined') { - $optionEl.addClass('hidden').prop('disabled', true); - } - } - - // element can be added - if (addNewValue) { - // finally add the option - var $option = $('<option></option>'); - $option.attr({value: value, title: title}).text(label); - $option.appendTo($fieldEl); - - // set the hidden field - FormEngine.updateHiddenFieldValueFromSelect($fieldEl, $originalFieldEl); - - // execute the phpcode from $FormEngine->TBE_EDITOR_fieldChanged_func - FormEngine.legacyFieldChangedCb(); - } - - } else { - - // The incoming value consists of the table name, an underscore and the uid - // or just the uid - // For a single selection field we need only the uid, so we extract it - var pattern = /_(\\d+)$/ - ,result = value.toString().match(pattern); - - if (result != null) { - value = result[1]; - } - - // Change the selected value - $fieldEl.val(value); - } - if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') { - FormEngine.Validation.validate(); - } - }; - - /** - * sets the value of the hidden field, from the select list, always executed after the select field was updated - * previously known as global function setHiddenFromList() - * - * @param {HTMLElement} selectFieldEl the select field - * @param {HTMLElement} originalFieldEl the hidden form field - */ - FormEngine.updateHiddenFieldValueFromSelect = setHiddenFromList = function(selectFieldEl, originalFieldEl) { - var selectedValues = []; - $(selectFieldEl).find('option').each(function() { - selectedValues.push($(this).prop('value')); - }); - - // make a comma separated list, if it is a multi-select - // set the values to the final hidden field - $(originalFieldEl).val(selectedValues.join(',')); - }; - - /** - * legacy function, can be removed once this function is not in use anymore - * - * @param {String} fName - * @param {String} type - * @param {Number} maxLength - */ - setFormValueManipulate = function(fName, type, maxLength) { - var $formEl = FormEngine.getFormElement(fName); - if ($formEl.length > 0) { - var formObj = $formEl.get(0); - var localArray_V = []; - var localArray_L = []; - var localArray_S = []; - var localArray_T = []; - var fObjSel = formObj[fName + '_list']; - var l = fObjSel.length; - var c = 0; - var a; - - if (type === 'RemoveFirstIfFull') { - if (maxLength == 1) { - for (a = 1; a < l; a++) { - if (fObjSel.options[a].selected != 1) { - localArray_V[c] = fObjSel.options[a].value; - localArray_L[c] = fObjSel.options[a].text; - localArray_S[c] = 0; - localArray_T[c] = fObjSel.options[a].title; - c++; - } - } - } else { - return; - } - } - - if ((type === "Remove" && fObjSel.size > 1) || type === "Top" || type === "Bottom") { - if (type === "Top") { - for (a=0;a<l;a++) { - if (fObjSel.options[a].selected==1) { - localArray_V[c]=fObjSel.options[a].value; - localArray_L[c]=fObjSel.options[a].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[a].title; - c++; - } - } - } - for (a=0;a<l;a++) { - if (fObjSel.options[a].selected!=1) { - localArray_V[c]=fObjSel.options[a].value; - localArray_L[c]=fObjSel.options[a].text; - localArray_S[c]=0; - localArray_T[c] = fObjSel.options[a].title; - c++; - } - } - if (type === "Bottom") { - for (a=0;a<l;a++) { - if (fObjSel.options[a].selected==1) { - localArray_V[c]=fObjSel.options[a].value; - localArray_L[c]=fObjSel.options[a].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[a].title; - c++; - } - } - } - } - if (type === "Down") { - var tC = 0; - var tA = []; - var aa = 0; - - for (a=0;a<l;a++) { - if (fObjSel.options[a].selected!=1) { - // Add non-selected element: - localArray_V[c]=fObjSel.options[a].value; - localArray_L[c]=fObjSel.options[a].text; - localArray_S[c]=0; - localArray_T[c] = fObjSel.options[a].title; - c++; - - // Transfer any accumulated and reset: - if (tA.length > 0) { - for (aa=0;aa<tA.length;aa++) { - localArray_V[c]=fObjSel.options[tA[aa]].value; - localArray_L[c]=fObjSel.options[tA[aa]].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[tA[aa]].title; - c++; - } - - tC = 0; - tA = []; - } - } else { - tA[tC] = a; - tC++; - } - } - // Transfer any remaining: - if (tA.length > 0) { - for (aa=0;aa<tA.length;aa++) { - localArray_V[c]=fObjSel.options[tA[aa]].value; - localArray_L[c]=fObjSel.options[tA[aa]].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[tA[aa]].title; - c++; - } - } - } - if (type === "Up") { - var tC = 0; - var tA = []; - var aa = 0; - c = l-1; - - for (a=l-1;a>=0;a--) { - if (fObjSel.options[a].selected!=1) { - - // Add non-selected element: - localArray_V[c]=fObjSel.options[a].value; - localArray_L[c]=fObjSel.options[a].text; - localArray_S[c]=0; - localArray_T[c] = fObjSel.options[a].title; - c--; - - // Transfer any accumulated and reset: - if (tA.length > 0) { - for (aa=0;aa<tA.length;aa++) { - localArray_V[c]=fObjSel.options[tA[aa]].value; - localArray_L[c]=fObjSel.options[tA[aa]].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[tA[aa]].title; - c--; - } - - tC = 0; - tA = []; - } - } else { - tA[tC] = a; - tC++; - } - } - // Transfer any remaining: - if (tA.length > 0) { - for (aa=0;aa<tA.length;aa++) { - localArray_V[c]=fObjSel.options[tA[aa]].value; - localArray_L[c]=fObjSel.options[tA[aa]].text; - localArray_S[c]=1; - localArray_T[c] = fObjSel.options[tA[aa]].title; - c--; - } - } - c=l; // Restore length value in "c" - } - - // Transfer items in temporary storage to list object: - fObjSel.length = c; - for (a = 0; a < c; a++) { - fObjSel.options[a].value = localArray_V[a]; - fObjSel.options[a].text = localArray_L[a]; - fObjSel.options[a].selected = localArray_S[a]; - fObjSel.options[a].title = localArray_T[a]; - } - FormEngine.updateHiddenFieldValueFromSelect(fObjSel, formObj[fName]); - - FormEngine.legacyFieldChangedCb(); - } - }; - - - /** - * Legacy function - * returns the DOM object for the given form name of the current form, - * but only if the given field name is valid, legacy function, use "getFormElement" instead - * - * @param {String} fieldName the name of the field name - * @returns {*|HTMLElement} - */ - setFormValue_getFObj = function(fieldName) { - var $formEl = FormEngine.getFormElement(fieldName); - if ($formEl.length > 0) { - // return the DOM element of the form object - return $formEl.get(0); - } - return null; - }; - - /** - * returns a jQuery object for the given form name of the current form, - * if the parameter "fieldName" is given, then the form element is only returned if the field name is available - * the latter behaviour mirrors the one of the function "setFormValue_getFObj" - * - * @param {String} fieldName the field name to check for, optional - * @returns {*|HTMLElement} - */ - FormEngine.getFormElement = function(fieldName) { - var $formEl = $('form[name="' + FormEngine.formName + '"]:first'); - if (fieldName) { - var $fieldEl = FormEngine.getFieldElement(fieldName) - ,$listFieldEl = FormEngine.getFieldElement(fieldName, '_list'); - - // Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element - if ($fieldEl.length > 0 && - ( - ($fieldEl.prop('type') === 'select-one') || - ($listFieldEl.length > 0 && $listFieldEl.prop('type').match(/select-(one|multiple)/)) - ) - ) { - return $formEl; - } else { - console.error('Form fields missing: form: ' + FormEngine.formName + ', field name: ' + fieldName); - alert('Form field is invalid'); - } - } else { - return $formEl; - } - }; - - - /** - * Returns a jQuery object of the field DOM element of the current form, can also be used to - * request an alternative field like "_hr", "_list" or "_mul" - * - * @param {String} fieldName the name of the field (<input name="fieldName">) - * @param {String} appendix optional - * @param {Boolean} noFallback if set, then the appendix value is returned no matter if it exists or not - * @returns {*|HTMLElement} - */ - FormEngine.getFieldElement = function(fieldName, appendix, noFallback) { - var $formEl = FormEngine.getFormElement(); - - // if an appendix is set, return the field with the appendix (like _mul or _list) - if (appendix) { - var $fieldEl; - switch (appendix) { - case '_list': - $fieldEl = $(':input.tceforms-multiselect[data-formengine-input-name="' + fieldName + '"]', $formEl); - break; - case '_avail': - $fieldEl = $(':input[data-relatedfieldname="' + fieldName + '"]', $formEl); - break; - case '_mul': - case '_hr': - $fieldEl = $(':input[type=hidden][data-formengine-input-name="' + fieldName + '"]', $formEl); - break; - } - if (($fieldEl && $fieldEl.length > 0) || noFallback === true) { - return $fieldEl; - } - } - - return $(':input[name="' + fieldName + '"]', $formEl); - }; - - - - /************************************************** - * manipulate existing options in a select field - **************************************************/ - - /** - * Moves currently selected options from a select field to the very top, - * can be multiple entries as well - * - * @param {Object} $fieldEl a jQuery object, containing the select field - */ - FormEngine.moveOptionToTop = function($fieldEl) { - // remove the selected options - var selectedOptions = $fieldEl.find(':selected').detach(); - // and add them on first position again - $fieldEl.prepend(selectedOptions); - }; - - - /** - * moves currently selected options from a select field up by one position, - * can be multiple entries as well - * - * @param {Object} $fieldEl a jQuery object, containing the select field - */ - FormEngine.moveOptionUp = function($fieldEl) { - // remove the selected options and add it before the previous sibling - $.each($fieldEl.find(':selected'), function(k, optionEl) { - var $optionEl = $(optionEl) - ,$optionBefore = $optionEl.prev(); - - // stop if first option to move is already the first one - if (k == 0 && $optionBefore.length === 0) { - return false; - } - - $optionBefore.before($optionEl.detach()); - }); - }; - - - /** - * moves currently selected options from a select field down one position, - * can be multiple entries as well - * - * @param {Object} $fieldEl a jQuery object, containing the select field - */ - FormEngine.moveOptionDown = function($fieldEl) { - // remove the selected options and add it after the next sibling - // however, this time, we need to go from the last to the first - var selectedOptions = $fieldEl.find(':selected'); - selectedOptions = $.makeArray(selectedOptions); - selectedOptions.reverse(); - $.each(selectedOptions, function(k, optionEl) { - var $optionEl = $(optionEl) - ,$optionAfter = $optionEl.next(); - - // stop if first option to move is already the last one - if (k == 0 && $optionAfter.length === 0) { - return false; - } - - $optionAfter.after($optionEl.detach()); - }); - }; - - - /** - * moves currently selected options from a select field as the very last entries - * - * @param {Object} $fieldEl a jQuery object, containing the select field - */ - FormEngine.moveOptionToBottom = function($fieldEl) { - // remove the selected options - var selectedOptions = $fieldEl.find(':selected').detach(); - // and add them on last position again - $fieldEl.append(selectedOptions); - }; - - /** - * removes currently selected options from a select field - * - * @param {Object} $fieldEl a jQuery object, containing the select field - * @param {Object} $availableFieldEl a jQuery object, containing all available value - */ - FormEngine.removeOption = function($fieldEl, $availableFieldEl) { - var $selected = $fieldEl.find(':selected'); - - $selected.each(function() { - $availableFieldEl - .find('option[value="' + $.escapeSelector($(this).attr('value')) + '"]') - .removeClass('hidden') - .prop('disabled', false); - }); - - // remove the selected options - $selected.remove(); - }; - - - /** - * Initialize events for all form engine relevant tasks. - * This function only needs to be called once on page load, - * as it using deferrer methods only - */ - FormEngine.initializeEvents = function() { - if (top.TYPO3 && typeof top.TYPO3.Backend !== 'undefined') { - top.TYPO3.Backend.consumerScope.attach(FormEngine); - $(window).on('unload', function() { - top.TYPO3.Backend.consumerScope.detach(FormEngine); - }); - } - $(document).on('click', '.t3js-btn-moveoption-top, .t3js-btn-moveoption-up, .t3js-btn-moveoption-down, .t3js-btn-moveoption-bottom, .t3js-btn-removeoption', function(evt) { - evt.preventDefault(); - - // track the arrows "Up", "Down", "Clear" etc in multi-select boxes - var $el = $(this) - ,fieldName = $el.data('fieldname') - ,$listFieldEl = FormEngine.getFieldElement(fieldName, '_list'); - - if ($listFieldEl.length > 0) { - - if ($el.hasClass('t3js-btn-moveoption-top')) { - FormEngine.moveOptionToTop($listFieldEl); - } else if ($el.hasClass('t3js-btn-moveoption-up')) { - FormEngine.moveOptionUp($listFieldEl); - } else if ($el.hasClass('t3js-btn-moveoption-down')) { - FormEngine.moveOptionDown($listFieldEl); - } else if ($el.hasClass('t3js-btn-moveoption-bottom')) { - FormEngine.moveOptionToBottom($listFieldEl); - } else if ($el.hasClass('t3js-btn-removeoption')) { - var $availableFieldEl = FormEngine.getFieldElement(fieldName, '_avail'); - FormEngine.removeOption($listFieldEl, $availableFieldEl); - } - - // make sure to update the hidden field value when modifying the select value - FormEngine.updateHiddenFieldValueFromSelect($listFieldEl, FormEngine.getFieldElement(fieldName)); - FormEngine.legacyFieldChangedCb(); - if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') { - FormEngine.Validation.validate(); - } - } - }).on('click', '.t3js-formengine-select-itemstoselect', function(evt) { - // in multi-select environments with two (e.g. "Access"), on click the item from the right should go to the left - var $el = $(this) - ,fieldName = $el.data('relatedfieldname') - ,exclusiveValues = $el.data('exclusivevalues'); - - if (fieldName) { - // try to add each selected field to the "left" select field - $el.find(':selected').each(function() { - var $optionEl = $(this); - FormEngine.setSelectOptionFromExternalSource(fieldName, $optionEl.prop('value'), $optionEl.text(), $optionEl.prop('title'), exclusiveValues, $optionEl); - }); - } - }).on('click', '.t3js-editform-close', function(e) { - e.preventDefault(); - FormEngine.preventExitIfNotSaved( - FormEngine.preventExitIfNotSavedCallback - ); - }).on('click', '.t3js-editform-delete-record', function(e) { - e.preventDefault(); - var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?'; - var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?'; - var $anchorElement = $(this); - var $modal = Modal.confirm(title, content, Severity.warning, [ - { - text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'no' - }, - { - text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record', - btnClass: 'btn-warning', - name: 'yes' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'no') { - Modal.dismiss(); - } else if (e.target.name === 'yes') { - deleteRecord($anchorElement.data('table'), $anchorElement.data('uid'), $anchorElement.data('return-url')); - Modal.dismiss(); - } - }); - }).on('click', '.t3js-editform-delete-inline-record', function(e) { - e.preventDefault(); - var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?'; - var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?'; - var $anchorElement = $(this); - var $modal = Modal.confirm(title, content, Severity.warning, [ - { - text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'no' - }, - { - text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record', - btnClass: 'btn-warning', - name: 'yes' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'no') { - Modal.dismiss(); - } else if (e.target.name === 'yes') { - var objectId = $anchorElement.data('objectid'); - inline.deleteRecord(objectId); - Modal.dismiss(); - } - }); - }).on('click', '.t3js-editform-submitButton', function(event) { - // remember the clicked submit button. we need to know that in TBE_EDITOR.submitForm(); - var $me = $(this), - name = $me.data('name') || this.name, - $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', '1'); - - $me.parents('form').append($elem); - }).on('change', '.t3-form-field-eval-null-checkbox input[type="checkbox"]', function(e) { - // Null checkboxes without placeholder click event handler - $(this).closest('.t3js-formengine-field-item').toggleClass('disabled'); - }).on('change', '.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]', function(e) { - $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').toggle(); - $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').toggle(); - }).on('change', '.t3js-l10n-state-container input[type=radio]', function(event) { - // Change handler for "l10n_state" field changes - var $me = $(this); - var $input = $me.closest('.t3js-formengine-field-item').find('[data-formengine-input-name]'); - - if ($input.length > 0) { - var lastState = $input.data('last-l10n-state') || false, - currentState = $(this).val(); - - if (lastState && currentState === lastState) { - return; - } - - if (currentState === 'custom') { - if (lastState) { - $(this).attr('data-original-language-value', $input.val()); - } - $input.attr('disabled', false); - } else { - if (lastState === 'custom') { - $(this).closest('.t3js-l10n-state-container').find('.t3js-l10n-state-custom').attr('data-original-language-value', $input.val()); - } - $input.attr('disabled', 'disabled'); - } - - $input.val($(this).attr('data-original-language-value')).trigger('change'); - $input.data('last-l10n-state', $(this).val()); - } - }).on('formengine.dp.change', function(event, $field) { - FormEngine.Validation.validate(); - FormEngine.Validation.markFieldAsChanged($field); - }); - }; - - /** - * @param {InteractionRequest} interactionRequest - * @return {jQuery.Deferred} - */ - FormEngine.consume = function(interactionRequest) { - if (!interactionRequest) { - throw new BackendException('No interaction request given', 1496589980); - } - if (interactionRequest.concernsTypes(FormEngine.consumeTypes)) { - var outerMostRequest = interactionRequest.outerMostRequest; - var deferred = $.Deferred(); - - FormEngine.interactionRequestMap.attachFor( - outerMostRequest, - deferred - ); - // resolve or reject deferreds with previous user choice - if (outerMostRequest.isProcessed()) { - handleConsumeResponse( - outerMostRequest, - outerMostRequest.getProcessedData().response - ); - // show confirmation dialog - } else if (FormEngine.hasChange()) { - FormEngine.preventExitIfNotSaved(function(response) { - outerMostRequest.setProcessedData( - {response: response} - ); - handleConsumeResponse(outerMostRequest, response); - }); - // resolve directly - } else { - FormEngine.interactionRequestMap.resolveFor(outerMostRequest); - } - - return deferred; - } - }; - - /** - * Initializes the remaining character views based on the fields' maxlength attribute - */ - FormEngine.initializeRemainingCharacterViews = function() { - // all fields with a "maxlength" attribute - var $maxlengthElements = $('[maxlength]').not('.t3js-datetimepicker').not('.t3js-charcounter-initialized'); - $maxlengthElements.on('focus', function(e) { - var $field = $(this), - $parent = $field.parents('.t3js-formengine-field-item:first'), - maxlengthProperties = FormEngine.getCharacterCounterProperties($field); - - // append the counter only at focus to avoid cluttering the DOM - $parent.append($('<div />', {'class': 't3js-charcounter'}).append( - $('<span />', {'class': maxlengthProperties.labelClass}).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters)) - )); - }).on('blur', function() { - var $field = $(this), - $parent = $field.parents('.t3js-formengine-field-item:first'); - $parent.find('.t3js-charcounter').remove(); - }).on('keyup', function() { - var $field = $(this), - $parent = $field.parents('.t3js-formengine-field-item:first'), - maxlengthProperties = FormEngine.getCharacterCounterProperties($field); - - // change class and value - $parent.find('.t3js-charcounter span').removeClass().addClass(maxlengthProperties.labelClass).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters)) - }); - $maxlengthElements.addClass('t3js-charcounter-initialized'); - $(':password').on('focus', function() { - $(this).attr('type', 'text').select(); - }).on('blur', function() { - $(this).attr('type', 'password'); - }); - }; - - /** - * Initialize select checkbox element checkboxes - */ - FormEngine.initializeSelectCheckboxes = function() { - $('.t3js-toggle-checkboxes').each(function() { - var $checkbox = $(this); - var $table = $checkbox.closest('table'); - var $checkboxes = $table.find('.t3js-checkbox'); - var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length; - $checkbox.prop('checked', checkIt); - }); - $(document).on('change', '.t3js-toggle-checkboxes', function(e) { - e.preventDefault(); - var $checkbox = $(this); - var $table = $checkbox.closest('table'); - var $checkboxes = $table.find('.t3js-checkbox'); - var checkIt = $checkboxes.length !== $table.find('.t3js-checkbox:checked').length; - $checkboxes.prop('checked', checkIt); - $checkbox.prop('checked', checkIt); - }); - $(document).on('change', '.t3js-checkbox', function(e) { - FormEngine.updateCheckboxState(this); - }); - }; - - /** - * - * @param {HTMLElement} source - */ - FormEngine.updateCheckboxState = function(source) { - var $sourceElement = $(source); - var $table = $sourceElement.closest('table'); - var $checkboxes = $table.find('.t3js-checkbox'); - var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length; - $table.find('.t3js-toggle-checkboxes').prop('checked', checkIt); - }; - - /** - * Get the properties required for proper rendering of the character counter - * - * @param {Object} $field - * @returns {{remainingCharacters: number, labelClass: string}} - */ - FormEngine.getCharacterCounterProperties = function($field) { - var fieldText = $field.val(), - maxlength = $field.attr('maxlength'), - currentFieldLength = fieldText.length, - numberOfLineBreaks = (fieldText.match(/\n/g)||[]).length, // count line breaks - remainingCharacters = maxlength - currentFieldLength - numberOfLineBreaks, - threshold = 15, // hard limit of remaining characters when the label class changes - labelClass = ''; - - if (remainingCharacters < threshold) { - labelClass = 'label-danger'; - } else if(remainingCharacters < threshold * 2) { - labelClass = 'label-warning'; - } else { - labelClass = 'label-info'; - } - - return { - remainingCharacters: remainingCharacters, - labelClass: 'label ' + labelClass - }; - }; - - /** - * Select field filter functions, see TCA option "enableMultiSelectFilterTextfield" - * and "multiSelectFilterItems" - */ - FormEngine.SelectBoxFilter = { - options: { - fieldContainerSelector: '.t3js-formengine-field-group', - filterContainerSelector: '.t3js-formengine-multiselect-filter-container', - filterTextFieldSelector: '.t3js-formengine-multiselect-filter-textfield', - filterSelectFieldSelector: '.t3js-formengine-multiselect-filter-dropdown', - itemsToSelectElementSelector: '.t3js-formengine-select-itemstoselect' - } - }; - - /** - * Make sure that all selectors and input filters are recognized - * note: this also works on elements that are loaded asynchronously via AJAX, no need to call this method - * after an AJAX load. - */ - FormEngine.SelectBoxFilter.initializeEvents = function() { - $(document).on('keyup', FormEngine.SelectBoxFilter.options.filterTextFieldSelector, function() { - var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this)); - FormEngine.SelectBoxFilter.filter($selectElement, $(this).val()); - }).on('change', FormEngine.SelectBoxFilter.options.filterSelectFieldSelector, function() { - var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this)); - FormEngine.SelectBoxFilter.filter($selectElement, $(this).val()); - }); - }; - - /** - * Fetch the "itemstoselect" select element where a filter item is attached to - * - * @param {Object} $relativeElement - * @returns {*} - */ - FormEngine.SelectBoxFilter.getSelectElement = function($relativeElement) { - var $containerElement = $relativeElement.closest(FormEngine.SelectBoxFilter.options.fieldContainerSelector); - return $containerElement.find(FormEngine.SelectBoxFilter.options.itemsToSelectElementSelector); - }; - - /** - * Filter the actual items - * - * @param {Object} $selectElement - * @param {String} filterText - */ - FormEngine.SelectBoxFilter.filter = function($selectElement, filterText) { - var $allOptionElements; - if (!$selectElement.data('alloptions')) { - $allOptionElements = $selectElement.find('option').clone(); - $selectElement.data('alloptions', $allOptionElements); - } else { - $allOptionElements = $selectElement.data('alloptions'); - } - - if (filterText.length > 0) { - var matchFilter = new RegExp(filterText, 'i'); - $selectElement.html(''); - $allOptionElements.each(function() { - var $item = $(this); - if ($item.text().match(matchFilter)) { - $selectElement.append($item.clone()); - } - }); - } else { - $selectElement.html($allOptionElements); - } - }; - - /** - * convert all textareas so they grow when it is typed in. - */ - FormEngine.convertTextareasResizable = function() { - var $elements = $('.t3js-formengine-textarea'); - if (TYPO3.settings.Textarea && TYPO3.settings.Textarea.autosize && $elements.length) { - require(['autosize'], function(autosize) { - autosize($elements); - }); - } - }; - - /** - * convert all textareas to enable tab - */ - FormEngine.convertTextareasEnableTab = function() { - var $elements = $('.t3js-enable-tab'); - if ($elements.length) { - require(['taboverride'], function(taboverride) { - taboverride.set($elements); - }); - } - }; - - /** - * Initialize input / text field "null" checkbox CSS overlay if no placeholder is set. - */ - FormEngine.initializeNullNoPlaceholderCheckboxes = function() { - $('.t3-form-field-eval-null-checkbox').each(function() { - // Add disabled class to "t3js-formengine-field-item" if the null checkbox is NOT set, - // This activates a CSS overlay "disabling" the input field and everything around. - var $checkbox = $(this).find('input[type="checkbox"]'); - var $fieldItem = $(this).closest('.t3js-formengine-field-item'); - if (!$checkbox.attr('checked')) { - $fieldItem.addClass('disabled'); - } - }); - }; - - /** - * Initialize input / text field "null" checkbox placeholder / real field if placeholder is set. - */ - FormEngine.initializeNullWithPlaceholderCheckboxes = function() { - $('.t3js-form-field-eval-null-placeholder-checkbox').each(function() { - // Set initial state of both div's (one containing actual field, other containing placeholder field) - // depending on whether checkbox is checked or not - var $checkbox = $(this).find('input[type="checkbox"]'); - if ($checkbox.attr('checked')) { - $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').hide(); - } else { - $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').hide(); - } - }); - }; - - /** - * This is the main function that is called on page load, but also after elements are asynchronously - * called e.g. after inline elements are loaded, or a new flexform section is added. - * Use this function in your extension like this "TYPO3.FormEngine.initialize()" - * if you add new fields dynamically. - */ - FormEngine.reinitialize = function() { - // Apply "close" button to all input / datetime fields - if ($('.t3js-clearable').length) { - require(['TYPO3/CMS/Backend/jquery.clearable'], function() { - $('.t3js-clearable').clearable(); - }); - } - if ($('.t3-form-suggest').length) { - require(['TYPO3/CMS/Backend/FormEngineSuggest'], function(Suggest) { - Suggest($('.t3-form-suggest')); - }); - } - // Apply DatePicker to all date time fields - if ($('.t3js-datetimepicker').length) { - require(['TYPO3/CMS/Backend/DateTimePicker'], function(DateTimePicker) { - DateTimePicker.initialize(); - }); - } - - FormEngine.convertTextareasResizable(); - FormEngine.convertTextareasEnableTab(); - FormEngine.initializeNullNoPlaceholderCheckboxes(); - FormEngine.initializeNullWithPlaceholderCheckboxes(); - FormEngine.initializeInputLinkToggle(); - FormEngine.initializeLocalizationStateSelector(); - FormEngine.initializeRemainingCharacterViews(); - }; - - /** - * Disable the input field on load if localization state selector is set to "parent" or "source" - */ - FormEngine.initializeLocalizationStateSelector = function() { - $('.t3js-l10n-state-container').each(function() { - var $input = $(this).closest('.t3js-formengine-field-item').find('[data-formengine-input-name]'); - var currentState = $(this).find('input[type="radio"]:checked').val(); - if (currentState === 'parent' || currentState === 'source') { - $input.attr('disabled', 'disabled'); - } - }); - }; - - /** - * Toggle for input link explanation - */ - FormEngine.initializeInputLinkToggle = function() { - var toggleClass = '.t3js-form-field-inputlink-explanation-toggle', - inputFieldClass = '.t3js-form-field-inputlink-input', - explanationClass = '.t3js-form-field-inputlink-explanation'; - - // if empty, show input field - $(explanationClass).filter(function () { - return !$.trim($(this).val()); - }).each(function () { - var $group = $(this).closest('.t3js-form-field-inputlink'), - $inputField = $group.find(inputFieldClass), - $explanationField = $group.find(explanationClass); - $explanationField.toggleClass('hidden', true); - $inputField.toggleClass('hidden', false); - $group.find('.form-control-clearable button.close').toggleClass('hidden', false) - }); - - $(document).on('click', toggleClass, function (e) { - e.preventDefault(); - - var $group = $(this).closest('.t3js-form-field-inputlink'), - $inputField = $group.find(inputFieldClass), - $explanationField = $group.find(explanationClass), - explanationShown; - - explanationShown = !$explanationField.hasClass('hidden'); - $explanationField.toggleClass('hidden', explanationShown); - $inputField.toggleClass('hidden', !explanationShown); - $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown) - }); - - $(inputFieldClass).on('change', function () { - var $group = $(this).closest('.t3js-form-field-inputlink'), - $inputField = $group.find(inputFieldClass), - $explanationField = $group.find(explanationClass), - explanationShown; - - if (!$explanationField.hasClass('hidden')) { - - explanationShown = !$explanationField.hasClass('hidden'); - $explanationField.toggleClass('hidden', explanationShown); - $inputField.toggleClass('hidden', !explanationShown); - $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown) - } - }); - }; - - /** - * @return {boolean} - */ - FormEngine.hasChange = function() { - return $('form[name="' + FormEngine.formName + '"] .has-change').length > 0; - }; - - /** - * @param {boolean} response - */ - FormEngine.preventExitIfNotSavedCallback = function(response) { - if (response) { - FormEngine.closeDocument(); - } - }; - - /** - * Show modal to confirm closing the document without saving. - * - * @param {Function} callback - */ - FormEngine.preventExitIfNotSaved = function(callback) { - callback = callback || FormEngine.preventExitIfNotSavedCallback; - - if (FormEngine.hasChange()) { - var title = TYPO3.lang['label.confirm.close_without_save.title'] || 'Do you want to quit without saving?'; - var content = TYPO3.lang['label.confirm.close_without_save.content'] || 'You have currently unsaved changes. Are you sure that you want to discard all changes?'; - var $modal = Modal.confirm(title, content, Severity.warning, [ - { - text: TYPO3.lang['buttons.confirm.close_without_save.no'] || 'No, I will continue editing', - active: true, - btnClass: 'btn-default', - name: 'no' - }, - { - text: TYPO3.lang['buttons.confirm.close_without_save.yes'] || 'Yes, discard my changes', - btnClass: 'btn-warning', - name: 'yes' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'no') { - Modal.dismiss(); - callback.call(null, false); - } else if (e.target.name === 'yes') { - Modal.dismiss(); - callback.call(null, true); - } - }); - } else { - callback.call(null, true); - } - }; - - /** - * Show modal to confirm closing the document without saving - */ - FormEngine.preventSaveIfHasErrors = function() { - if ($('.has-error').length > 0) { - var title = TYPO3.lang['label.alert.save_with_error.title'] || 'You have errors in your form!'; - var content = TYPO3.lang['label.alert.save_with_error.content'] || 'Please check the form, there is at least one error in your form.'; - var $modal = Modal.confirm(title, content, Severity.error, [ - { - text: TYPO3.lang['buttons.alert.save_with_error.ok'] || 'OK', - btnClass: 'btn-danger', - name: 'ok' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'ok') { - Modal.dismiss(); - } - }); - return false; - } - return true; - }; - - /** - * Close current open document - */ - FormEngine.closeDocument = function() { - document.editform.closeDoc.value=1; - document.editform.submit(); - }; - - /** - * Main init function called from outside - * - * Sets some options and registers the DOMready handler to initialize further things - * - * @param {String} browserUrl - * @param {Number} mode - */ - FormEngine.initialize = function(browserUrl, mode) { - FormEngine.browserUrl = browserUrl; - FormEngine.Validation.setUsMode(mode); - - $(function() { - FormEngine.initializeEvents(); - FormEngine.SelectBoxFilter.initializeEvents(); - FormEngine.initializeSelectCheckboxes(); - FormEngine.Validation.initialize(); - FormEngine.reinitialize(); - $('#t3js-ui-block').remove(); - }); - }; - - // load required modules to hook in the post initialize function - if (undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine']) { - $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine'], function(pos, moduleName) { - require([moduleName]); - }); - } - - // make the form engine object publicly visible for other objects in the TYPO3 namespace - TYPO3.FormEngine = FormEngine; - - // return the object in the global space - return FormEngine; + 'TYPO3/CMS/Backend/FormEngineValidation', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/BackendException', + 'TYPO3/CMS/Backend/Event/InteractionRequestMap' +], function($, FormEngineValidation, Modal, Severity, BackendException, InteractionRequestMap) { + + /** + * @param {InteractionRequest} interactionRequest + * @param {boolean} response + */ + function handleConsumeResponse(interactionRequest, response) { + if (response) { + FormEngine.interactionRequestMap.resolveFor(interactionRequest); + } else { + FormEngine.interactionRequestMap.rejectFor(interactionRequest); + } + } + + /** + * @exports TYPO3/CMS/Backend/FormEngine + */ + var FormEngine = { + consumeTypes: ['typo3.setUrl', 'typo3.beforeSetUrl', 'typo3.refresh'], + Validation: FormEngineValidation, + interactionRequestMap: InteractionRequestMap, + formName: TYPO3.settings.FormEngine.formName, + openedPopupWindow: null, + legacyFieldChangedCb: function() { + !$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb) || TYPO3.settings.FormEngine.legacyFieldChangedCb(); + }, + browserUrl: '' + }; + + // functions to connect the db/file browser with this document and the formfields on it! + + /** + * Opens a popup window with the element browser (browser.php) + * + * @param {String} mode can be "db" or "file" + * @param {String} params additional params for the browser window + */ + FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params) { + Modal.advanced({ + type: Modal.types.iframe, + content: FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params, + size: Modal.sizes.large + }); + }; + + /** + * properly fills the select field from the popup window (element browser, link browser) + * or from a multi-select (two selects side-by-side) + * previously known as "setFormValueFromBrowseWin" + * + * @param {String} fieldName Formerly known as "fName" name of the field, like [tt_content][2387][header] + * @param {(String|Number)} value The value to fill in (could be an integer) + * @param {String} label The visible name in the selector + * @param {String} title The title when hovering over it + * @param {String} exclusiveValues If the select field has exclusive options that are not combine-able + * @param {$} $optionEl The jQuery object of the selected <option> tag + */ + FormEngine.setSelectOptionFromExternalSource = setFormValueFromBrowseWin = function(fieldName, value, label, title, exclusiveValues, $optionEl) { + exclusiveValues = String(exclusiveValues); + + var $fieldEl, + $originalFieldEl, + isMultiple = false, + isList = false; + + $originalFieldEl = $fieldEl = FormEngine.getFieldElement(fieldName); + + if ($originalFieldEl.length === 0 || value === '--div--') { + return; + } + + // Check if the form object has a "_list" element + // The "_list" element exists for multiple selection select types + var $listFieldEl = FormEngine.getFieldElement(fieldName, '_list', true); + if ($listFieldEl.length > 0) { + $fieldEl = $listFieldEl; + isMultiple = ($fieldEl.prop('multiple') && $fieldEl.prop('size') != '1'); + isList = true; + } + + // clear field before adding value, if configured so (maxitems==1) + // @todo: clean this code + if (typeof TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName] !== 'undefined') { + var clearSettings = TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName]; + $fieldEl.empty(); + + // Clear the upload field + // @todo: Investigate whether we either need to fix this code or we can drop it. + var filesContainer = document.getElementById(clearSettings.itemFormElID_file); + if (filesContainer) { + filesContainer.innerHTML = filesContainer.innerHTML; + } + } + + if (isMultiple || isList) { + // If multiple values are not allowed, clear anything that is in the control already + if (!isMultiple) { + $fieldEl.empty(); + } + + // Clear elements if exclusive values are found + if (exclusiveValues) { + var reenableOptions = false; + + var m = new RegExp('(^|,)' + value + '($|,)'); + // the new value is exclusive => remove all existing values + if (exclusiveValues.match(m)) { + $fieldEl.empty(); + reenableOptions = true; + } else if ($fieldEl.find('option').length == 1) { + // there is an old value and it was exclusive => it has to be removed + m = new RegExp("(^|,)" + $fieldEl.find('option').prop('value') + "($|,)"); + if (exclusiveValues.match(m)) { + $fieldEl.empty(); + reenableOptions = true; + } + } + + if (reenableOptions && typeof $optionEl !== 'undefined') { + $optionEl.closest('select').find('[disabled]').removeClass('hidden').prop('disabled', false) + } + } + + // Inserting the new element + var addNewValue = true; + + // check if there is a "_mul" field (a field on the right) and if the field was already added + var $multipleFieldEl = FormEngine.getFieldElement(fieldName, '_mul', true); + if ($multipleFieldEl.length == 0 || $multipleFieldEl.val() == 0) { + $fieldEl.find('option').each(function(k, optionEl) { + if ($(optionEl).prop('value') == value) { + addNewValue = false; + return false; + } + }); + + if (addNewValue && typeof $optionEl !== 'undefined') { + $optionEl.addClass('hidden').prop('disabled', true); + } + } + + // element can be added + if (addNewValue) { + // finally add the option + var $option = $('<option></option>'); + $option.attr({value: value, title: title}).text(label); + $option.appendTo($fieldEl); + + // set the hidden field + FormEngine.updateHiddenFieldValueFromSelect($fieldEl, $originalFieldEl); + + // execute the phpcode from $FormEngine->TBE_EDITOR_fieldChanged_func + FormEngine.legacyFieldChangedCb(); + } + + } else { + + // The incoming value consists of the table name, an underscore and the uid + // or just the uid + // For a single selection field we need only the uid, so we extract it + var pattern = /_(\\d+)$/ + , result = value.toString().match(pattern); + + if (result != null) { + value = result[1]; + } + + // Change the selected value + $fieldEl.val(value); + } + if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') { + FormEngine.Validation.validate(); + } + }; + + /** + * sets the value of the hidden field, from the select list, always executed after the select field was updated + * previously known as global function setHiddenFromList() + * + * @param {HTMLElement} selectFieldEl the select field + * @param {HTMLElement} originalFieldEl the hidden form field + */ + FormEngine.updateHiddenFieldValueFromSelect = setHiddenFromList = function(selectFieldEl, originalFieldEl) { + var selectedValues = []; + $(selectFieldEl).find('option').each(function() { + selectedValues.push($(this).prop('value')); + }); + + // make a comma separated list, if it is a multi-select + // set the values to the final hidden field + $(originalFieldEl).val(selectedValues.join(',')); + }; + + /** + * legacy function, can be removed once this function is not in use anymore + * + * @param {String} fName + * @param {String} type + * @param {Number} maxLength + */ + setFormValueManipulate = function(fName, type, maxLength) { + var $formEl = FormEngine.getFormElement(fName); + if ($formEl.length > 0) { + var formObj = $formEl.get(0); + var localArray_V = []; + var localArray_L = []; + var localArray_S = []; + var localArray_T = []; + var fObjSel = formObj[fName + '_list']; + var l = fObjSel.length; + var c = 0; + var a; + + if (type === 'RemoveFirstIfFull') { + if (maxLength == 1) { + for (a = 1; a < l; a++) { + if (fObjSel.options[a].selected != 1) { + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 0; + localArray_T[c] = fObjSel.options[a].title; + c++; + } + } + } else { + return; + } + } + + if ((type === "Remove" && fObjSel.size > 1) || type === "Top" || type === "Bottom") { + if (type === "Top") { + for (a = 0; a < l; a++) { + if (fObjSel.options[a].selected == 1) { + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[a].title; + c++; + } + } + } + for (a = 0; a < l; a++) { + if (fObjSel.options[a].selected != 1) { + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 0; + localArray_T[c] = fObjSel.options[a].title; + c++; + } + } + if (type === "Bottom") { + for (a = 0; a < l; a++) { + if (fObjSel.options[a].selected == 1) { + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[a].title; + c++; + } + } + } + } + if (type === "Down") { + var tC = 0; + var tA = []; + var aa = 0; + + for (a = 0; a < l; a++) { + if (fObjSel.options[a].selected != 1) { + // Add non-selected element: + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 0; + localArray_T[c] = fObjSel.options[a].title; + c++; + + // Transfer any accumulated and reset: + if (tA.length > 0) { + for (aa = 0; aa < tA.length; aa++) { + localArray_V[c] = fObjSel.options[tA[aa]].value; + localArray_L[c] = fObjSel.options[tA[aa]].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[tA[aa]].title; + c++; + } + + tC = 0; + tA = []; + } + } else { + tA[tC] = a; + tC++; + } + } + // Transfer any remaining: + if (tA.length > 0) { + for (aa = 0; aa < tA.length; aa++) { + localArray_V[c] = fObjSel.options[tA[aa]].value; + localArray_L[c] = fObjSel.options[tA[aa]].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[tA[aa]].title; + c++; + } + } + } + if (type === "Up") { + var tC = 0; + var tA = []; + var aa = 0; + c = l - 1; + + for (a = l - 1; a >= 0; a--) { + if (fObjSel.options[a].selected != 1) { + + // Add non-selected element: + localArray_V[c] = fObjSel.options[a].value; + localArray_L[c] = fObjSel.options[a].text; + localArray_S[c] = 0; + localArray_T[c] = fObjSel.options[a].title; + c--; + + // Transfer any accumulated and reset: + if (tA.length > 0) { + for (aa = 0; aa < tA.length; aa++) { + localArray_V[c] = fObjSel.options[tA[aa]].value; + localArray_L[c] = fObjSel.options[tA[aa]].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[tA[aa]].title; + c--; + } + + tC = 0; + tA = []; + } + } else { + tA[tC] = a; + tC++; + } + } + // Transfer any remaining: + if (tA.length > 0) { + for (aa = 0; aa < tA.length; aa++) { + localArray_V[c] = fObjSel.options[tA[aa]].value; + localArray_L[c] = fObjSel.options[tA[aa]].text; + localArray_S[c] = 1; + localArray_T[c] = fObjSel.options[tA[aa]].title; + c--; + } + } + c = l; // Restore length value in "c" + } + + // Transfer items in temporary storage to list object: + fObjSel.length = c; + for (a = 0; a < c; a++) { + fObjSel.options[a].value = localArray_V[a]; + fObjSel.options[a].text = localArray_L[a]; + fObjSel.options[a].selected = localArray_S[a]; + fObjSel.options[a].title = localArray_T[a]; + } + FormEngine.updateHiddenFieldValueFromSelect(fObjSel, formObj[fName]); + + FormEngine.legacyFieldChangedCb(); + } + }; + + + /** + * Legacy function + * returns the DOM object for the given form name of the current form, + * but only if the given field name is valid, legacy function, use "getFormElement" instead + * + * @param {String} fieldName the name of the field name + * @returns {*|HTMLElement} + */ + setFormValue_getFObj = function(fieldName) { + var $formEl = FormEngine.getFormElement(fieldName); + if ($formEl.length > 0) { + // return the DOM element of the form object + return $formEl.get(0); + } + return null; + }; + + /** + * returns a jQuery object for the given form name of the current form, + * if the parameter "fieldName" is given, then the form element is only returned if the field name is available + * the latter behaviour mirrors the one of the function "setFormValue_getFObj" + * + * @param {String} fieldName the field name to check for, optional + * @returns {*|HTMLElement} + */ + FormEngine.getFormElement = function(fieldName) { + var $formEl = $('form[name="' + FormEngine.formName + '"]:first'); + if (fieldName) { + var $fieldEl = FormEngine.getFieldElement(fieldName) + , $listFieldEl = FormEngine.getFieldElement(fieldName, '_list'); + + // Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element + if ($fieldEl.length > 0 && + ( + ($fieldEl.prop('type') === 'select-one') || + ($listFieldEl.length > 0 && $listFieldEl.prop('type').match(/select-(one|multiple)/)) + ) + ) { + return $formEl; + } else { + console.error('Form fields missing: form: ' + FormEngine.formName + ', field name: ' + fieldName); + alert('Form field is invalid'); + } + } else { + return $formEl; + } + }; + + + /** + * Returns a jQuery object of the field DOM element of the current form, can also be used to + * request an alternative field like "_hr", "_list" or "_mul" + * + * @param {String} fieldName the name of the field (<input name="fieldName">) + * @param {String} appendix optional + * @param {Boolean} noFallback if set, then the appendix value is returned no matter if it exists or not + * @returns {*|HTMLElement} + */ + FormEngine.getFieldElement = function(fieldName, appendix, noFallback) { + var $formEl = FormEngine.getFormElement(); + + // if an appendix is set, return the field with the appendix (like _mul or _list) + if (appendix) { + var $fieldEl; + switch (appendix) { + case '_list': + $fieldEl = $(':input.tceforms-multiselect[data-formengine-input-name="' + fieldName + '"]', $formEl); + break; + case '_avail': + $fieldEl = $(':input[data-relatedfieldname="' + fieldName + '"]', $formEl); + break; + case '_mul': + case '_hr': + $fieldEl = $(':input[type=hidden][data-formengine-input-name="' + fieldName + '"]', $formEl); + break; + } + if (($fieldEl && $fieldEl.length > 0) || noFallback === true) { + return $fieldEl; + } + } + + return $(':input[name="' + fieldName + '"]', $formEl); + }; + + + /************************************************** + * manipulate existing options in a select field + **************************************************/ + + /** + * Moves currently selected options from a select field to the very top, + * can be multiple entries as well + * + * @param {Object} $fieldEl a jQuery object, containing the select field + */ + FormEngine.moveOptionToTop = function($fieldEl) { + // remove the selected options + var selectedOptions = $fieldEl.find(':selected').detach(); + // and add them on first position again + $fieldEl.prepend(selectedOptions); + }; + + + /** + * moves currently selected options from a select field up by one position, + * can be multiple entries as well + * + * @param {Object} $fieldEl a jQuery object, containing the select field + */ + FormEngine.moveOptionUp = function($fieldEl) { + // remove the selected options and add it before the previous sibling + $.each($fieldEl.find(':selected'), function(k, optionEl) { + var $optionEl = $(optionEl) + , $optionBefore = $optionEl.prev(); + + // stop if first option to move is already the first one + if (k == 0 && $optionBefore.length === 0) { + return false; + } + + $optionBefore.before($optionEl.detach()); + }); + }; + + + /** + * moves currently selected options from a select field down one position, + * can be multiple entries as well + * + * @param {Object} $fieldEl a jQuery object, containing the select field + */ + FormEngine.moveOptionDown = function($fieldEl) { + // remove the selected options and add it after the next sibling + // however, this time, we need to go from the last to the first + var selectedOptions = $fieldEl.find(':selected'); + selectedOptions = $.makeArray(selectedOptions); + selectedOptions.reverse(); + $.each(selectedOptions, function(k, optionEl) { + var $optionEl = $(optionEl) + , $optionAfter = $optionEl.next(); + + // stop if first option to move is already the last one + if (k == 0 && $optionAfter.length === 0) { + return false; + } + + $optionAfter.after($optionEl.detach()); + }); + }; + + + /** + * moves currently selected options from a select field as the very last entries + * + * @param {Object} $fieldEl a jQuery object, containing the select field + */ + FormEngine.moveOptionToBottom = function($fieldEl) { + // remove the selected options + var selectedOptions = $fieldEl.find(':selected').detach(); + // and add them on last position again + $fieldEl.append(selectedOptions); + }; + + /** + * removes currently selected options from a select field + * + * @param {Object} $fieldEl a jQuery object, containing the select field + * @param {Object} $availableFieldEl a jQuery object, containing all available value + */ + FormEngine.removeOption = function($fieldEl, $availableFieldEl) { + var $selected = $fieldEl.find(':selected'); + + $selected.each(function() { + $availableFieldEl + .find('option[value="' + $.escapeSelector($(this).attr('value')) + '"]') + .removeClass('hidden') + .prop('disabled', false); + }); + + // remove the selected options + $selected.remove(); + }; + + + /** + * Initialize events for all form engine relevant tasks. + * This function only needs to be called once on page load, + * as it using deferrer methods only + */ + FormEngine.initializeEvents = function() { + if (top.TYPO3 && typeof top.TYPO3.Backend !== 'undefined') { + top.TYPO3.Backend.consumerScope.attach(FormEngine); + $(window).on('unload', function() { + top.TYPO3.Backend.consumerScope.detach(FormEngine); + }); + } + $(document).on('click', '.t3js-btn-moveoption-top, .t3js-btn-moveoption-up, .t3js-btn-moveoption-down, .t3js-btn-moveoption-bottom, .t3js-btn-removeoption', function(evt) { + evt.preventDefault(); + + // track the arrows "Up", "Down", "Clear" etc in multi-select boxes + var $el = $(this) + , fieldName = $el.data('fieldname') + , $listFieldEl = FormEngine.getFieldElement(fieldName, '_list'); + + if ($listFieldEl.length > 0) { + + if ($el.hasClass('t3js-btn-moveoption-top')) { + FormEngine.moveOptionToTop($listFieldEl); + } else if ($el.hasClass('t3js-btn-moveoption-up')) { + FormEngine.moveOptionUp($listFieldEl); + } else if ($el.hasClass('t3js-btn-moveoption-down')) { + FormEngine.moveOptionDown($listFieldEl); + } else if ($el.hasClass('t3js-btn-moveoption-bottom')) { + FormEngine.moveOptionToBottom($listFieldEl); + } else if ($el.hasClass('t3js-btn-removeoption')) { + var $availableFieldEl = FormEngine.getFieldElement(fieldName, '_avail'); + FormEngine.removeOption($listFieldEl, $availableFieldEl); + } + + // make sure to update the hidden field value when modifying the select value + FormEngine.updateHiddenFieldValueFromSelect($listFieldEl, FormEngine.getFieldElement(fieldName)); + FormEngine.legacyFieldChangedCb(); + if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') { + FormEngine.Validation.validate(); + } + } + }).on('click', '.t3js-formengine-select-itemstoselect', function(evt) { + // in multi-select environments with two (e.g. "Access"), on click the item from the right should go to the left + var $el = $(this) + , fieldName = $el.data('relatedfieldname') + , exclusiveValues = $el.data('exclusivevalues'); + + if (fieldName) { + // try to add each selected field to the "left" select field + $el.find(':selected').each(function() { + var $optionEl = $(this); + FormEngine.setSelectOptionFromExternalSource(fieldName, $optionEl.prop('value'), $optionEl.text(), $optionEl.prop('title'), exclusiveValues, $optionEl); + }); + } + }).on('click', '.t3js-editform-close', function(e) { + e.preventDefault(); + FormEngine.preventExitIfNotSaved( + FormEngine.preventExitIfNotSavedCallback + ); + }).on('click', '.t3js-editform-delete-record', function(e) { + e.preventDefault(); + var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?'; + var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?'; + var $anchorElement = $(this); + var $modal = Modal.confirm(title, content, Severity.warning, [ + { + text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'no' + }, + { + text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record', + btnClass: 'btn-warning', + name: 'yes' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'no') { + Modal.dismiss(); + } else if (e.target.name === 'yes') { + deleteRecord($anchorElement.data('table'), $anchorElement.data('uid'), $anchorElement.data('return-url')); + Modal.dismiss(); + } + }); + }).on('click', '.t3js-editform-delete-inline-record', function(e) { + e.preventDefault(); + var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?'; + var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?'; + var $anchorElement = $(this); + var $modal = Modal.confirm(title, content, Severity.warning, [ + { + text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'no' + }, + { + text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record', + btnClass: 'btn-warning', + name: 'yes' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'no') { + Modal.dismiss(); + } else if (e.target.name === 'yes') { + var objectId = $anchorElement.data('objectid'); + inline.deleteRecord(objectId); + Modal.dismiss(); + } + }); + }).on('click', '.t3js-editform-submitButton', function(event) { + // remember the clicked submit button. we need to know that in TBE_EDITOR.submitForm(); + var $me = $(this), + name = $me.data('name') || this.name, + $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', '1'); + + $me.parents('form').append($elem); + }).on('change', '.t3-form-field-eval-null-checkbox input[type="checkbox"]', function(e) { + // Null checkboxes without placeholder click event handler + $(this).closest('.t3js-formengine-field-item').toggleClass('disabled'); + }).on('change', '.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]', function(e) { + $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').toggle(); + $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').toggle(); + }).on('change', '.t3js-l10n-state-container input[type=radio]', function(event) { + // Change handler for "l10n_state" field changes + var $me = $(this); + var $input = $me.closest('.t3js-formengine-field-item').find('[data-formengine-input-name]'); + + if ($input.length > 0) { + var lastState = $input.data('last-l10n-state') || false, + currentState = $(this).val(); + + if (lastState && currentState === lastState) { + return; + } + + if (currentState === 'custom') { + if (lastState) { + $(this).attr('data-original-language-value', $input.val()); + } + $input.attr('disabled', false); + } else { + if (lastState === 'custom') { + $(this).closest('.t3js-l10n-state-container').find('.t3js-l10n-state-custom').attr('data-original-language-value', $input.val()); + } + $input.attr('disabled', 'disabled'); + } + + $input.val($(this).attr('data-original-language-value')).trigger('change'); + $input.data('last-l10n-state', $(this).val()); + } + }).on('formengine.dp.change', function(event, $field) { + FormEngine.Validation.validate(); + FormEngine.Validation.markFieldAsChanged($field); + }); + }; + + /** + * @param {InteractionRequest} interactionRequest + * @return {jQuery.Deferred} + */ + FormEngine.consume = function(interactionRequest) { + if (!interactionRequest) { + throw new BackendException('No interaction request given', 1496589980); + } + if (interactionRequest.concernsTypes(FormEngine.consumeTypes)) { + var outerMostRequest = interactionRequest.outerMostRequest; + var deferred = $.Deferred(); + + FormEngine.interactionRequestMap.attachFor( + outerMostRequest, + deferred + ); + // resolve or reject deferreds with previous user choice + if (outerMostRequest.isProcessed()) { + handleConsumeResponse( + outerMostRequest, + outerMostRequest.getProcessedData().response + ); + // show confirmation dialog + } else if (FormEngine.hasChange()) { + FormEngine.preventExitIfNotSaved(function(response) { + outerMostRequest.setProcessedData( + {response: response} + ); + handleConsumeResponse(outerMostRequest, response); + }); + // resolve directly + } else { + FormEngine.interactionRequestMap.resolveFor(outerMostRequest); + } + + return deferred; + } + }; + + /** + * Initializes the remaining character views based on the fields' maxlength attribute + */ + FormEngine.initializeRemainingCharacterViews = function() { + // all fields with a "maxlength" attribute + var $maxlengthElements = $('[maxlength]').not('.t3js-datetimepicker').not('.t3js-charcounter-initialized'); + $maxlengthElements.on('focus', function(e) { + var $field = $(this), + $parent = $field.parents('.t3js-formengine-field-item:first'), + maxlengthProperties = FormEngine.getCharacterCounterProperties($field); + + // append the counter only at focus to avoid cluttering the DOM + $parent.append($('<div />', {'class': 't3js-charcounter'}).append( + $('<span />', {'class': maxlengthProperties.labelClass}).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters)) + )); + }).on('blur', function() { + var $field = $(this), + $parent = $field.parents('.t3js-formengine-field-item:first'); + $parent.find('.t3js-charcounter').remove(); + }).on('keyup', function() { + var $field = $(this), + $parent = $field.parents('.t3js-formengine-field-item:first'), + maxlengthProperties = FormEngine.getCharacterCounterProperties($field); + + // change class and value + $parent.find('.t3js-charcounter span').removeClass().addClass(maxlengthProperties.labelClass).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters)) + }); + $maxlengthElements.addClass('t3js-charcounter-initialized'); + $(':password').on('focus', function() { + $(this).attr('type', 'text').select(); + }).on('blur', function() { + $(this).attr('type', 'password'); + }); + }; + + /** + * Initialize select checkbox element checkboxes + */ + FormEngine.initializeSelectCheckboxes = function() { + $('.t3js-toggle-checkboxes').each(function() { + var $checkbox = $(this); + var $table = $checkbox.closest('table'); + var $checkboxes = $table.find('.t3js-checkbox'); + var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length; + $checkbox.prop('checked', checkIt); + }); + $(document).on('change', '.t3js-toggle-checkboxes', function(e) { + e.preventDefault(); + var $checkbox = $(this); + var $table = $checkbox.closest('table'); + var $checkboxes = $table.find('.t3js-checkbox'); + var checkIt = $checkboxes.length !== $table.find('.t3js-checkbox:checked').length; + $checkboxes.prop('checked', checkIt); + $checkbox.prop('checked', checkIt); + }); + $(document).on('change', '.t3js-checkbox', function(e) { + FormEngine.updateCheckboxState(this); + }); + }; + + /** + * + * @param {HTMLElement} source + */ + FormEngine.updateCheckboxState = function(source) { + var $sourceElement = $(source); + var $table = $sourceElement.closest('table'); + var $checkboxes = $table.find('.t3js-checkbox'); + var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length; + $table.find('.t3js-toggle-checkboxes').prop('checked', checkIt); + }; + + /** + * Get the properties required for proper rendering of the character counter + * + * @param {Object} $field + * @returns {{remainingCharacters: number, labelClass: string}} + */ + FormEngine.getCharacterCounterProperties = function($field) { + var fieldText = $field.val(), + maxlength = $field.attr('maxlength'), + currentFieldLength = fieldText.length, + numberOfLineBreaks = (fieldText.match(/\n/g) || []).length, // count line breaks + remainingCharacters = maxlength - currentFieldLength - numberOfLineBreaks, + threshold = 15, // hard limit of remaining characters when the label class changes + labelClass = ''; + + if (remainingCharacters < threshold) { + labelClass = 'label-danger'; + } else if (remainingCharacters < threshold * 2) { + labelClass = 'label-warning'; + } else { + labelClass = 'label-info'; + } + + return { + remainingCharacters: remainingCharacters, + labelClass: 'label ' + labelClass + }; + }; + + /** + * Select field filter functions, see TCA option "enableMultiSelectFilterTextfield" + * and "multiSelectFilterItems" + */ + FormEngine.SelectBoxFilter = { + options: { + fieldContainerSelector: '.t3js-formengine-field-group', + filterContainerSelector: '.t3js-formengine-multiselect-filter-container', + filterTextFieldSelector: '.t3js-formengine-multiselect-filter-textfield', + filterSelectFieldSelector: '.t3js-formengine-multiselect-filter-dropdown', + itemsToSelectElementSelector: '.t3js-formengine-select-itemstoselect' + } + }; + + /** + * Make sure that all selectors and input filters are recognized + * note: this also works on elements that are loaded asynchronously via AJAX, no need to call this method + * after an AJAX load. + */ + FormEngine.SelectBoxFilter.initializeEvents = function() { + $(document).on('keyup', FormEngine.SelectBoxFilter.options.filterTextFieldSelector, function() { + var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this)); + FormEngine.SelectBoxFilter.filter($selectElement, $(this).val()); + }).on('change', FormEngine.SelectBoxFilter.options.filterSelectFieldSelector, function() { + var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this)); + FormEngine.SelectBoxFilter.filter($selectElement, $(this).val()); + }); + }; + + /** + * Fetch the "itemstoselect" select element where a filter item is attached to + * + * @param {Object} $relativeElement + * @returns {*} + */ + FormEngine.SelectBoxFilter.getSelectElement = function($relativeElement) { + var $containerElement = $relativeElement.closest(FormEngine.SelectBoxFilter.options.fieldContainerSelector); + return $containerElement.find(FormEngine.SelectBoxFilter.options.itemsToSelectElementSelector); + }; + + /** + * Filter the actual items + * + * @param {Object} $selectElement + * @param {String} filterText + */ + FormEngine.SelectBoxFilter.filter = function($selectElement, filterText) { + var $allOptionElements; + if (!$selectElement.data('alloptions')) { + $allOptionElements = $selectElement.find('option').clone(); + $selectElement.data('alloptions', $allOptionElements); + } else { + $allOptionElements = $selectElement.data('alloptions'); + } + + if (filterText.length > 0) { + var matchFilter = new RegExp(filterText, 'i'); + $selectElement.html(''); + $allOptionElements.each(function() { + var $item = $(this); + if ($item.text().match(matchFilter)) { + $selectElement.append($item.clone()); + } + }); + } else { + $selectElement.html($allOptionElements); + } + }; + + /** + * convert all textareas so they grow when it is typed in. + */ + FormEngine.convertTextareasResizable = function() { + var $elements = $('.t3js-formengine-textarea'); + if (TYPO3.settings.Textarea && TYPO3.settings.Textarea.autosize && $elements.length) { + require(['autosize'], function(autosize) { + autosize($elements); + }); + } + }; + + /** + * convert all textareas to enable tab + */ + FormEngine.convertTextareasEnableTab = function() { + var $elements = $('.t3js-enable-tab'); + if ($elements.length) { + require(['taboverride'], function(taboverride) { + taboverride.set($elements); + }); + } + }; + + /** + * Initialize input / text field "null" checkbox CSS overlay if no placeholder is set. + */ + FormEngine.initializeNullNoPlaceholderCheckboxes = function() { + $('.t3-form-field-eval-null-checkbox').each(function() { + // Add disabled class to "t3js-formengine-field-item" if the null checkbox is NOT set, + // This activates a CSS overlay "disabling" the input field and everything around. + var $checkbox = $(this).find('input[type="checkbox"]'); + var $fieldItem = $(this).closest('.t3js-formengine-field-item'); + if (!$checkbox.attr('checked')) { + $fieldItem.addClass('disabled'); + } + }); + }; + + /** + * Initialize input / text field "null" checkbox placeholder / real field if placeholder is set. + */ + FormEngine.initializeNullWithPlaceholderCheckboxes = function() { + $('.t3js-form-field-eval-null-placeholder-checkbox').each(function() { + // Set initial state of both div's (one containing actual field, other containing placeholder field) + // depending on whether checkbox is checked or not + var $checkbox = $(this).find('input[type="checkbox"]'); + if ($checkbox.attr('checked')) { + $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').hide(); + } else { + $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').hide(); + } + }); + }; + + /** + * This is the main function that is called on page load, but also after elements are asynchronously + * called e.g. after inline elements are loaded, or a new flexform section is added. + * Use this function in your extension like this "TYPO3.FormEngine.initialize()" + * if you add new fields dynamically. + */ + FormEngine.reinitialize = function() { + // Apply "close" button to all input / datetime fields + if ($('.t3js-clearable').length) { + require(['TYPO3/CMS/Backend/jquery.clearable'], function() { + $('.t3js-clearable').clearable(); + }); + } + if ($('.t3-form-suggest').length) { + require(['TYPO3/CMS/Backend/FormEngineSuggest'], function(Suggest) { + Suggest($('.t3-form-suggest')); + }); + } + // Apply DatePicker to all date time fields + if ($('.t3js-datetimepicker').length) { + require(['TYPO3/CMS/Backend/DateTimePicker'], function(DateTimePicker) { + DateTimePicker.initialize(); + }); + } + + FormEngine.convertTextareasResizable(); + FormEngine.convertTextareasEnableTab(); + FormEngine.initializeNullNoPlaceholderCheckboxes(); + FormEngine.initializeNullWithPlaceholderCheckboxes(); + FormEngine.initializeInputLinkToggle(); + FormEngine.initializeLocalizationStateSelector(); + FormEngine.initializeRemainingCharacterViews(); + }; + + /** + * Disable the input field on load if localization state selector is set to "parent" or "source" + */ + FormEngine.initializeLocalizationStateSelector = function() { + $('.t3js-l10n-state-container').each(function() { + var $input = $(this).closest('.t3js-formengine-field-item').find('[data-formengine-input-name]'); + var currentState = $(this).find('input[type="radio"]:checked').val(); + if (currentState === 'parent' || currentState === 'source') { + $input.attr('disabled', 'disabled'); + } + }); + }; + + /** + * Toggle for input link explanation + */ + FormEngine.initializeInputLinkToggle = function() { + var toggleClass = '.t3js-form-field-inputlink-explanation-toggle', + inputFieldClass = '.t3js-form-field-inputlink-input', + explanationClass = '.t3js-form-field-inputlink-explanation'; + + // if empty, show input field + $(explanationClass).filter(function() { + return !$.trim($(this).val()); + }).each(function() { + var $group = $(this).closest('.t3js-form-field-inputlink'), + $inputField = $group.find(inputFieldClass), + $explanationField = $group.find(explanationClass); + $explanationField.toggleClass('hidden', true); + $inputField.toggleClass('hidden', false); + $group.find('.form-control-clearable button.close').toggleClass('hidden', false) + }); + + $(document).on('click', toggleClass, function(e) { + e.preventDefault(); + + var $group = $(this).closest('.t3js-form-field-inputlink'), + $inputField = $group.find(inputFieldClass), + $explanationField = $group.find(explanationClass), + explanationShown; + + explanationShown = !$explanationField.hasClass('hidden'); + $explanationField.toggleClass('hidden', explanationShown); + $inputField.toggleClass('hidden', !explanationShown); + $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown) + }); + + $(inputFieldClass).on('change', function() { + var $group = $(this).closest('.t3js-form-field-inputlink'), + $inputField = $group.find(inputFieldClass), + $explanationField = $group.find(explanationClass), + explanationShown; + + if (!$explanationField.hasClass('hidden')) { + + explanationShown = !$explanationField.hasClass('hidden'); + $explanationField.toggleClass('hidden', explanationShown); + $inputField.toggleClass('hidden', !explanationShown); + $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown) + } + }); + }; + + /** + * @return {boolean} + */ + FormEngine.hasChange = function() { + return $('form[name="' + FormEngine.formName + '"] .has-change').length > 0; + }; + + /** + * @param {boolean} response + */ + FormEngine.preventExitIfNotSavedCallback = function(response) { + if (response) { + FormEngine.closeDocument(); + } + }; + + /** + * Show modal to confirm closing the document without saving. + * + * @param {Function} callback + */ + FormEngine.preventExitIfNotSaved = function(callback) { + callback = callback || FormEngine.preventExitIfNotSavedCallback; + + if (FormEngine.hasChange()) { + var title = TYPO3.lang['label.confirm.close_without_save.title'] || 'Do you want to quit without saving?'; + var content = TYPO3.lang['label.confirm.close_without_save.content'] || 'You have currently unsaved changes. Are you sure that you want to discard all changes?'; + var $modal = Modal.confirm(title, content, Severity.warning, [ + { + text: TYPO3.lang['buttons.confirm.close_without_save.no'] || 'No, I will continue editing', + active: true, + btnClass: 'btn-default', + name: 'no' + }, + { + text: TYPO3.lang['buttons.confirm.close_without_save.yes'] || 'Yes, discard my changes', + btnClass: 'btn-warning', + name: 'yes' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'no') { + Modal.dismiss(); + callback.call(null, false); + } else if (e.target.name === 'yes') { + Modal.dismiss(); + callback.call(null, true); + } + }); + } else { + callback.call(null, true); + } + }; + + /** + * Show modal to confirm closing the document without saving + */ + FormEngine.preventSaveIfHasErrors = function() { + if ($('.has-error').length > 0) { + var title = TYPO3.lang['label.alert.save_with_error.title'] || 'You have errors in your form!'; + var content = TYPO3.lang['label.alert.save_with_error.content'] || 'Please check the form, there is at least one error in your form.'; + var $modal = Modal.confirm(title, content, Severity.error, [ + { + text: TYPO3.lang['buttons.alert.save_with_error.ok'] || 'OK', + btnClass: 'btn-danger', + name: 'ok' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + Modal.dismiss(); + } + }); + return false; + } + return true; + }; + + /** + * Close current open document + */ + FormEngine.closeDocument = function() { + document.editform.closeDoc.value = 1; + document.editform.submit(); + }; + + /** + * Main init function called from outside + * + * Sets some options and registers the DOMready handler to initialize further things + * + * @param {String} browserUrl + * @param {Number} mode + */ + FormEngine.initialize = function(browserUrl, mode) { + FormEngine.browserUrl = browserUrl; + FormEngine.Validation.setUsMode(mode); + + $(function() { + FormEngine.initializeEvents(); + FormEngine.SelectBoxFilter.initializeEvents(); + FormEngine.initializeSelectCheckboxes(); + FormEngine.Validation.initialize(); + FormEngine.reinitialize(); + $('#t3js-ui-block').remove(); + }); + }; + + // load required modules to hook in the post initialize function + if (undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine']) { + $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine'], function(pos, moduleName) { + require([moduleName]); + }); + } + + // make the form engine object publicly visible for other objects in the TYPO3 namespace + TYPO3.FormEngine = FormEngine; + + // return the object in the global space + return FormEngine; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js index f40db4b0b2605338f1e4620ce0db08d984c0ff11..4fb7f682956bb7db434e8969b9acff1640b76c89 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js @@ -15,7 +15,7 @@ * Module: TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement * Logic for SelectSingleElement */ -define(['jquery'], function ($) { +define(['jquery'], function($) { /** * @@ -30,13 +30,13 @@ define(['jquery'], function ($) { * @param {String} selector * @param {Object} options */ - SelectSingleElement.initialize = function (selector, options) { + SelectSingleElement.initialize = function(selector, options) { var $selectElement = $(selector); var $groupIconContainer = $selectElement.prev('.input-group-icon'); var options = options || {}; - $selectElement.on('change', function () { + $selectElement.on('change', function() { // Update prepended select icon $groupIconContainer.html($selectElement.find(':selected').data('icon')); }); @@ -51,7 +51,7 @@ define(['jquery'], function ($) { $selectElement.on('focus', options.onFocus); } - $selectElement.closest('.form-control-wrap').find('.t3js-forms-select-single-icons').on('click', function (e) { + $selectElement.closest('.form-control-wrap').find('.t3js-forms-select-single-icons').on('click', function(e) { var $selectIcon = $(e.target).closest('[data-select-index]'); $selectElement diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js index 78953f3b1367ef7e3fb39c0a1d6271abf005fe7d..eb5b40a8be8a88503893ef2d2d46bc6a1f6f9320 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js @@ -19,14 +19,14 @@ * Extends TYPO3/CMS/Backend/SvgTree component. */ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], - function (d3, SvgTree) { + function(d3, SvgTree) { 'use strict'; /** * @constructor * @exports TYPO3/CMS/Backend/FormEngine/Element/SelectTree */ - var SelectTree = function () { + var SelectTree = function() { SvgTree.call(this); this.settings.showCheckboxes = true; }; @@ -40,7 +40,7 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * @param {String} selector * @param {Object} settings */ - SelectTree.prototype.initialize = function (selector, settings) { + SelectTree.prototype.initialize = function(selector, settings) { if (!_super_.initialize.call(this, selector, settings)) { return false; } @@ -58,11 +58,11 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * * @param {Selection} nodeSelection */ - SelectTree.prototype.updateNodes = function (nodeSelection) { + SelectTree.prototype.updateNodes = function(nodeSelection) { if (this.settings.showCheckboxes) { nodeSelection .selectAll('.tree-check use') - .attr('visibility', function (node) { + .attr('visibility', function(node) { var checked = Boolean(node.checked); if (d3.select(this).classed('icon-checked') && checked) { return 'visible'; @@ -82,20 +82,20 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * * @param {Selection} nodeSelection ENTER selection (only new DOM objects) */ - SelectTree.prototype.renderCheckbox = function (nodeSelection) { + SelectTree.prototype.renderCheckbox = function(nodeSelection) { var _this = this; if (this.settings.showCheckboxes) { this.textPosition = 50; // this can be simplified to single "use" element with changing href on click // when we drop IE11 on WIN7 support - var g = nodeSelection.filter(function (node) { + var g = nodeSelection.filter(function(node) { // do not render checkbox if node is not selectable return _this.isNodeSelectable(node) || Boolean(node.checked); }) .append('g') .attr('class', 'tree-check') - .on('click', function (d) { + .on('click', function(d) { _this.selectNode(d); }); @@ -125,12 +125,12 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * * @param {Node} node */ - SelectTree.prototype.updateAncestorsIndeterminateState = function (node) { + SelectTree.prototype.updateAncestorsIndeterminateState = function(node) { var _this = this; //foreach ancestor except node itself var indeterminate = false; - node.parents.forEach(function (index) { + node.parents.forEach(function(index) { var n = _this.nodes[index]; n.indeterminate = (node.checked || node.indeterminate || indeterminate); @@ -144,8 +144,8 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * It's done once after loading data. * Later indeterminate state is updated just for the subset of nodes */ - SelectTree.prototype.loadDataAfter = function () { - this.nodes.forEach(function (node) { + SelectTree.prototype.loadDataAfter = function() { + this.nodes.forEach(function(node) { node.indeterminate = false; }); @@ -164,10 +164,10 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * * @param {Array} nodes */ - SelectTree.prototype.calculateIndeterminate = function (nodes) { - nodes.forEach(function (node) { + SelectTree.prototype.calculateIndeterminate = function(nodes) { + nodes.forEach(function(node) { if ((node.checked || node.indeterminate) && node.parents && node.parents.length > 0) { - node.parents.forEach(function (parentNodeIndex) { + node.parents.forEach(function(parentNodeIndex) { nodes[parentNodeIndex].indeterminate = true; }); } @@ -179,7 +179,7 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], * * @param {Node} node */ - SelectTree.prototype.nodeSelectedAfter = function (node) { + SelectTree.prototype.nodeSelectedAfter = function(node) { this.updateAncestorsIndeterminateState(node); // check all nodes again, to ensure correct display of indeterminate state @@ -190,10 +190,10 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], /** * Sets a comma-separated list of selected nodes identifiers to configured input */ - SelectTree.prototype.saveCheckboxes = function () { + SelectTree.prototype.saveCheckboxes = function() { if (typeof this.settings.input !== 'undefined') { var selectedNodes = this.getSelectedNodes(); - this.settings.input.val(selectedNodes.map(function (d) { + this.settings.input.val(selectedNodes.map(function(d) { return d.identifier; })); } @@ -202,22 +202,22 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'], /** * Add icons imitating checkboxes */ - SelectTree.prototype.addIcons = function () { + SelectTree.prototype.addIcons = function() { this.data.icons = { check: { identifier: 'check', icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">' + - '<rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>', + '<rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>' }, checked: { identifier: 'checked', - icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>', + icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>' }, indeterminate: { identifier: 'indeterminate', - icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>', - }, + icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>' + } }; }; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js index d4009378a8e25bb5c354b9768e26f7dc90ab9a34..643336ffc1674611122a9785906ed64515032184 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js @@ -15,14 +15,14 @@ * Initialization of the selectTree js component used e.g. for category tree rendering */ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'], - function ($, SelectTree) { + function($, SelectTree) { 'use strict'; var SelectTreeElement = {}; - SelectTreeElement.initialize = function () { - $(document).ready(function () { - $('.typo3-tceforms-tree .treeRecord').each(function (i, element) { + SelectTreeElement.initialize = function() { + $(document).ready(function() { + $('.typo3-tceforms-tree .treeRecord').each(function(i, element) { /** * Hidden input field storing selected elements. @@ -43,7 +43,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'], flexFormContainerIdentifier: $treeInput.data('flexformcontaineridentifier'), flexFormContainerFieldName: $treeInput.data('flexformcontainerfieldname'), flexFormSectionContainerIsNew: $treeInput.data('flexformsectioncontainerisnew'), - command: $treeInput.data('command'), + command: $treeInput.data('command') }; var $wrapper = $treeInput.parent().siblings('.svg-tree-wrapper'); var dataUrl = TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(dataParams); @@ -56,7 +56,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'], input: $treeInput, exclusiveNodesIdentifiers: $treeInput.data('tree-exclusive-keys'), validation: $treeInput.data('formengine-validation-rules')[0], - expandUpToLevel: $treeInput.data('tree-expand-up-to-level'), + expandUpToLevel: $treeInput.data('tree-expand-up-to-level') }); if (!initialized) { return; @@ -65,7 +65,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'], tree.dispatch.on('nodeSelectedAfter.requestUpdate', window[$wrapper.attr('id')]); if ($treeInput.data('tree-show-toolbar')) { - require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function (TreeToolbar) { + require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function(TreeToolbar) { var selectTreeToolbar = new TreeToolbar(); selectTreeToolbar.initialize($wrapper); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js index b67145cf95cae1566e09ac5803faf1f9a2f5a535..abb34c49f562c32de8aeedb28a98b4d3ed5f5422 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js @@ -17,9 +17,9 @@ define(['jquery', 'TYPO3/CMS/Backend/Icons', 'TYPO3/CMS/Backend/Tooltip', - 'TYPO3/CMS/Backend/SvgTree', + 'TYPO3/CMS/Backend/SvgTree' ], - function ($, Icons) { + function($, Icons) { 'use strict'; /** @@ -28,13 +28,13 @@ define(['jquery', * @constructor * @exports TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar */ - var TreeToolbar = function () { + var TreeToolbar = function() { this.settings = { toolbarSelector: '.tree-toolbar', collapseAllBtn: '.collapse-all-btn', expandAllBtn: '.expand-all-btn', searchInput: '.search-input', - toggleHideUnchecked: '.hide-unchecked-btn', + toggleHideUnchecked: '.hide-unchecked-btn' }; /** @@ -66,15 +66,15 @@ define(['jquery', */ this.$template = $( '<div class="tree-toolbar btn-toolbar">' + - '<div class="input-group">' + - '<span class="input-group-addon input-group-icon filter"></span>' + - '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tcatree.findItem'] + '">' + - '</div>' + - '<div class="btn-group">' + - '<button type="button" data-toggle="tooltip" class="btn btn-default expand-all-btn" title="' + TYPO3.lang['tcatree.expandAll'] + '"></button>' + - '<button type="button" data-toggle="tooltip" class="btn btn-default collapse-all-btn" title="' + TYPO3.lang['tcatree.collapseAll'] + '"></button>' + - '<button type="button" data-toggle="tooltip" class="btn btn-default hide-unchecked-btn" title="' + TYPO3.lang['tcatree.toggleHideUnchecked'] + '"></button>' + - '</div>' + + '<div class="input-group">' + + '<span class="input-group-addon input-group-icon filter"></span>' + + '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tcatree.findItem'] + '">' + + '</div>' + + '<div class="btn-group">' + + '<button type="button" data-toggle="tooltip" class="btn btn-default expand-all-btn" title="' + TYPO3.lang['tcatree.expandAll'] + '"></button>' + + '<button type="button" data-toggle="tooltip" class="btn btn-default collapse-all-btn" title="' + TYPO3.lang['tcatree.collapseAll'] + '"></button>' + + '<button type="button" data-toggle="tooltip" class="btn btn-default hide-unchecked-btn" title="' + TYPO3.lang['tcatree.toggleHideUnchecked'] + '"></button>' + + '</div>' + '</div>' ); }; @@ -85,7 +85,7 @@ define(['jquery', * @param {String} treeSelector * @param {Object} settings */ - TreeToolbar.prototype.initialize = function (treeSelector, settings) { + TreeToolbar.prototype.initialize = function(treeSelector, settings) { this.$treeWrapper = $(treeSelector); if (!this.$treeWrapper.data('svgtree-initialized') || typeof this.$treeWrapper.data('svgtree') !== 'object') { @@ -103,30 +103,30 @@ define(['jquery', /** * Renders toolbar */ - TreeToolbar.prototype.render = function () { + TreeToolbar.prototype.render = function() { var _this = this; this.tree = this.$treeWrapper.data('svgtree'); var $toolbar = this.$template.clone().insertBefore(this.$treeWrapper); - Icons.getIcon('actions-filter', Icons.sizes.small).done(function (icon) { + Icons.getIcon('actions-filter', Icons.sizes.small).done(function(icon) { $toolbar.find('.filter').append(icon); }); - Icons.getIcon('apps-pagetree-category-expand-all', Icons.sizes.small).done(function (icon) { + Icons.getIcon('apps-pagetree-category-expand-all', Icons.sizes.small).done(function(icon) { $toolbar.find('.expand-all-btn').append(icon); }); - Icons.getIcon('apps-pagetree-category-collapse-all', Icons.sizes.small).done(function (icon) { + Icons.getIcon('apps-pagetree-category-collapse-all', Icons.sizes.small).done(function(icon) { $toolbar.find('.collapse-all-btn').append(icon); }); - Icons.getIcon('apps-pagetree-category-toggle-hide-checked', Icons.sizes.small).done(function (icon) { + Icons.getIcon('apps-pagetree-category-toggle-hide-checked', Icons.sizes.small).done(function(icon) { $toolbar.find('.hide-unchecked-btn').append(icon); }); $toolbar.find(this.settings.collapseAllBtn).on('click', this.collapseAll.bind(this)); $toolbar.find(this.settings.expandAllBtn).on('click', this.expandAll.bind(this)); - $toolbar.find(this.settings.searchInput).on('input', function () { + $toolbar.find(this.settings.searchInput).on('input', function() { _this.search.call(_this, this); }); @@ -137,14 +137,14 @@ define(['jquery', /** * Collapse children of root node */ - TreeToolbar.prototype.collapseAll = function () { + TreeToolbar.prototype.collapseAll = function() { this.tree.collapseAll(); }; /** * Expand all nodes */ - TreeToolbar.prototype.expandAll = function () { + TreeToolbar.prototype.expandAll = function() { this.tree.expandAll(); }; @@ -153,12 +153,12 @@ define(['jquery', * * @param {HTMLElement} input */ - TreeToolbar.prototype.search = function (input) { + TreeToolbar.prototype.search = function(input) { var _this = this; var name = $(input).val(); this.tree.nodes[0].open = false; - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { var regex = new RegExp(name, 'i'); if (regex.test(node.name)) { _this.showParents(node); @@ -177,13 +177,13 @@ define(['jquery', /** * Show only checked items */ - TreeToolbar.prototype.toggleHideUnchecked = function () { + TreeToolbar.prototype.toggleHideUnchecked = function() { var _this = this; this._hideUncheckedState = !this._hideUncheckedState; if (this._hideUncheckedState) { - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { if (node.checked) { _this.showParents(node); node.open = true; @@ -194,7 +194,7 @@ define(['jquery', } }); } else { - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { node.hidden = false; }); } @@ -209,7 +209,7 @@ define(['jquery', * @param {Node} node * @returns {Boolean} */ - TreeToolbar.prototype.showParents = function (node) { + TreeToolbar.prototype.showParents = function(node) { if (node.parents.length === 0) { return true; } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js index 458b3d1e5166c0de573939a89028b8b3476bc6b2..30fceb6917636012994cf806460d172785dab164 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js @@ -21,264 +21,264 @@ * which can contain one ore more sections */ define(['jquery', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/FormEngine' - ], function ($, Modal) { - - /** - * - * @param {HTMLElement} el - * @param {Object} options - * @constructor - * @exports TYPO3/CMS/Backend/FormEngineFlexForm - */ - TYPO3.FormEngine.FlexFormElement = function(el, options) { - var me = this; // avoid scope issues - var opts; // shorthand options notation - - // initialization function; private - me.initialize = function() { - // store DOM element and jQuery object for later use - me.el = el; - me.$el = $(el); - - // remove any existing backups - var old_me = me.$el.data('TYPO3.FormEngine.FlexFormElement'); - if (typeof old_me !== 'undefined') { - me.$el.removeData('TYPO3.FormEngine.FlexFormElement'); - } - - // add a reverse reference to the DOM element - me.$el.data('TYPO3.FormEngine.FlexFormElement', me); - - if (!options) { - options = {}; - } - - // set some values from existing properties - options.allowRestructure = me.$el.data('t3-flex-allow-restructure'); - options.flexformId = me.$el.attr('id'); - - // store options and merge with default options - opts = me.options = $.extend({}, TYPO3.FormEngine.FlexFormElement.defaults, options); - - // initialize events - me.initializeEvents(); - - // generate the preview text if a section is hidden on load - me.$el.find(opts.sectionSelector).each(function() { - me.generateSectionPreview($(this)); - }); - - return me; - }; - - /** - * init all events related to the flexform. As this method is called multiple times, - * some handlers need to be off'ed first to prevent event stacking. - */ - me.initializeEvents = function() { - // Toggling all sections on/off by clicking all toggle buttons of each section - me.$el.prev(opts.flexFormToggleAllSectionsSelector).off('click').on('click', function() { - me.$el.find(opts.sectionToggleButtonSelector).trigger('click'); - }); - - if (opts.allowRestructure) { - // create a sortable when dragging on the header of a section - me.createSortable(); - - // allow delete of a single section - me.$el.off('click').on('click', opts.deleteIconSelector, function(evt) { - evt.preventDefault(); - - var confirmTitle = TYPO3.lang['flexform.section.delete.title'] || 'Are you sure?'; - var confirmMessage = TYPO3.lang['flexform.section.delete.message'] || 'Are you sure you want to delete this section?'; - var $confirm = Modal.confirm(confirmTitle, confirmMessage); - $confirm.on('confirm.button.cancel', function() { - Modal.currentModal.trigger('modal-dismiss'); - }); - $confirm.on('confirm.button.ok', function(event) { - $(evt.target).closest(opts.sectionSelector).hide().addClass(opts.sectionDeletedClass); - me.setActionStatus(); - TYPO3.FormEngine.Validation.validate(); - Modal.currentModal.trigger('modal-dismiss'); - }); - }); - - // allow the toggle open/close of the main selection - me.$el.on('click', opts.sectionToggleButtonSelector, function(evt) { - evt.preventDefault(); - var $sectionEl = $(this).closest(opts.sectionSelector); - me.toggleSection($sectionEl); - }).on('click', opts.sectionToggleButtonSelector + ' .form-irre-header-control', function(evt) { - evt.stopPropagation(); - }); - } - - return me; - }; - - // initialize ourself - me.initialize(); - }; - - // setting some default values - TYPO3.FormEngine.FlexFormElement.defaults = { - 'deleteIconSelector': '.t3js-delete', - 'sectionSelector': '.t3js-flex-section', - 'sectionContentSelector': '.t3js-flex-section-content', - 'sectionHeaderSelector': '.t3js-flex-section-header', - 'sectionHeaderPreviewSelector': '.t3js-flex-section-header-preview', - 'sectionActionInputFieldSelector': '.t3js-flex-control-action', - 'sectionToggleInputFieldSelector': '.t3js-flex-control-toggle', - 'sectionToggleIconOpenSelector': '.t3js-flex-control-toggle-icon-open', - 'sectionToggleIconCloseSelector': '.t3js-flex-control-toggle-icon-close', - 'sectionToggleButtonSelector': '[data-toggle="formengine-flex"]', - 'flexFormToggleAllSectionsSelector': '.t3js-form-field-toggle-flexsection', - 'sectionDeletedClass': 't3js-flex-section-deleted', - 'allowRestructure': 0, // whether the form can be modified - 'flexformId': false - }; - - - /** - * Allow flexform sections to be sorted - */ - TYPO3.FormEngine.FlexFormElement.prototype.createSortable = function() { - var me = this; - - require(['jquery-ui/sortable'], function () { - me.$el.sortable({ - containment: 'parent', - handle: '.t3js-sortable-handle', - axis: 'y', - tolerance: 'pointer', - stop: function () { - me.setActionStatus(); - } - }); - }); - }; - - // Updates the "action"-status for a section. This is used to move and delete elements. - TYPO3.FormEngine.FlexFormElement.prototype.setActionStatus = function() { - var me = this; - - // Traverse and find how many sections are open or closed, and save the value accordingly - me.$el.find(me.options.sectionActionInputFieldSelector).each(function(index) { - var actionValue = ($(this).parents(me.options.sectionSelector).hasClass(me.options.sectionDeletedClass) ? 'DELETE' : index); - $(this).val(actionValue); - }); - }; - - // Toggling flexform elements on/off - // hides the flexform section and shows a preview text - // or shows the form parts - TYPO3.FormEngine.FlexFormElement.prototype.toggleSection = function($sectionEl) { - - var $contentEl = $sectionEl.find(this.options.sectionContentSelector); - - // display/hide the content of this flexform section - $contentEl.toggle(); - - if ($contentEl.is(':visible')) { - // show the open icon, and set the hidden field for toggling to "hidden" - $sectionEl.find(this.options.sectionToggleIconOpenSelector).show(); - $sectionEl.find(this.options.sectionToggleIconCloseSelector).hide(); - $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(0); - } else { - // show the close icon, and set the hidden field for toggling to "1" - $sectionEl.find(this.options.sectionToggleIconOpenSelector).hide(); - $sectionEl.find(this.options.sectionToggleIconCloseSelector).show(); - $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(1); - } - - // see if the preview content needs to be generated - this.generateSectionPreview($sectionEl); - }; - - // function to generate the section preview in the header - // if the section content is hidden - // called on load and when toggling an icon - TYPO3.FormEngine.FlexFormElement.prototype.generateSectionPreview = function($sectionEl) { - var $contentEl = $sectionEl.find(this.options.sectionContentSelector); - var previewContent = ''; - - if (!$contentEl.is(':visible')) { - $contentEl.find('input[type=text], textarea').each(function() { - var content = $($.parseHTML($(this).val())).text(); - if (content.length > 50) { - content = content.substring(0, 50) + '...'; - } - previewContent += (previewContent ? ' / ' : '') + content; - }); - } - - // create a preview container span element - if ($sectionEl.find(this.options.sectionHeaderPreviewSelector).length === 0) { - $sectionEl.find(this.options.sectionHeaderSelector).find('.t3js-record-title').parent() - .append('<span class="' + this.options.sectionHeaderPreviewSelector.replace(/\./, '') + '"></span>'); - } - - $sectionEl.find(this.options.sectionHeaderPreviewSelector).text(previewContent); - }; - - // register the flex functions as jQuery Plugin - $.fn.t3FormEngineFlexFormElement = function(options) { - // apply all util functions to ourself (for use in templates, etc.) - return this.each(function() { - (new TYPO3.FormEngine.FlexFormElement(this, options)); - }); - }; - - // Initialization Code - $(function() { - // run the flexform functions on all containers (which contains one or more sections) - $('.t3-flex-container').t3FormEngineFlexFormElement(); - - // Add handler to fetch container data on click on "add container" buttons - $('.t3js-flex-container-add').on('click', function(e) { - var me = $(this); - e.preventDefault(); - $.ajax({ - url: TYPO3.settings.ajaxUrls['record_flex_container_add'], - type: 'POST', - cache: false, - data: { - vanillaUid: me.data('vanillauid'), - databaseRowUid: me.data('databaserowuid'), - command: me.data('command'), - tableName: me.data('tablename'), - fieldName: me.data('fieldname'), - recordTypeValue: me.data('recordtypevalue'), - dataStructureIdentifier: me.data('datastructureidentifier'), - flexFormSheetName: me.data('flexformsheetname'), - flexFormFieldName: me.data('flexformfieldname'), - flexFormContainerName: me.data('flexformcontainername') - }, - success: function(response) { - me.closest('.t3-form-field-container').find('.t3-flex-container').append(response.html); - $('.t3-flex-container').t3FormEngineFlexFormElement(); - if (response.scriptCall && response.scriptCall.length > 0) { - $.each(response.scriptCall, function (index, value) { - eval(value); - }); - } - if (response.stylesheetFiles && response.stylesheetFiles.length > 0) { - $.each(response.stylesheetFiles, function (index, stylesheetFile) { - var element = document.createElement('link'); - element['rel'] = 'stylesheet'; - element['type'] = 'text/css'; - element['href'] = stylesheetFile; - document.head.appendChild(element); - }); - } - TYPO3.FormEngine.reinitialize(); - TYPO3.FormEngine.Validation.initializeInputFields(); - TYPO3.FormEngine.Validation.validate(); - } - }); - }); - - }); + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/FormEngine' +], function($, Modal) { + + /** + * + * @param {HTMLElement} el + * @param {Object} options + * @constructor + * @exports TYPO3/CMS/Backend/FormEngineFlexForm + */ + TYPO3.FormEngine.FlexFormElement = function(el, options) { + var me = this; // avoid scope issues + var opts; // shorthand options notation + + // initialization function; private + me.initialize = function() { + // store DOM element and jQuery object for later use + me.el = el; + me.$el = $(el); + + // remove any existing backups + var old_me = me.$el.data('TYPO3.FormEngine.FlexFormElement'); + if (typeof old_me !== 'undefined') { + me.$el.removeData('TYPO3.FormEngine.FlexFormElement'); + } + + // add a reverse reference to the DOM element + me.$el.data('TYPO3.FormEngine.FlexFormElement', me); + + if (!options) { + options = {}; + } + + // set some values from existing properties + options.allowRestructure = me.$el.data('t3-flex-allow-restructure'); + options.flexformId = me.$el.attr('id'); + + // store options and merge with default options + opts = me.options = $.extend({}, TYPO3.FormEngine.FlexFormElement.defaults, options); + + // initialize events + me.initializeEvents(); + + // generate the preview text if a section is hidden on load + me.$el.find(opts.sectionSelector).each(function() { + me.generateSectionPreview($(this)); + }); + + return me; + }; + + /** + * init all events related to the flexform. As this method is called multiple times, + * some handlers need to be off'ed first to prevent event stacking. + */ + me.initializeEvents = function() { + // Toggling all sections on/off by clicking all toggle buttons of each section + me.$el.prev(opts.flexFormToggleAllSectionsSelector).off('click').on('click', function() { + me.$el.find(opts.sectionToggleButtonSelector).trigger('click'); + }); + + if (opts.allowRestructure) { + // create a sortable when dragging on the header of a section + me.createSortable(); + + // allow delete of a single section + me.$el.off('click').on('click', opts.deleteIconSelector, function(evt) { + evt.preventDefault(); + + var confirmTitle = TYPO3.lang['flexform.section.delete.title'] || 'Are you sure?'; + var confirmMessage = TYPO3.lang['flexform.section.delete.message'] || 'Are you sure you want to delete this section?'; + var $confirm = Modal.confirm(confirmTitle, confirmMessage); + $confirm.on('confirm.button.cancel', function() { + Modal.currentModal.trigger('modal-dismiss'); + }); + $confirm.on('confirm.button.ok', function(event) { + $(evt.target).closest(opts.sectionSelector).hide().addClass(opts.sectionDeletedClass); + me.setActionStatus(); + TYPO3.FormEngine.Validation.validate(); + Modal.currentModal.trigger('modal-dismiss'); + }); + }); + + // allow the toggle open/close of the main selection + me.$el.on('click', opts.sectionToggleButtonSelector, function(evt) { + evt.preventDefault(); + var $sectionEl = $(this).closest(opts.sectionSelector); + me.toggleSection($sectionEl); + }).on('click', opts.sectionToggleButtonSelector + ' .form-irre-header-control', function(evt) { + evt.stopPropagation(); + }); + } + + return me; + }; + + // initialize ourself + me.initialize(); + }; + + // setting some default values + TYPO3.FormEngine.FlexFormElement.defaults = { + 'deleteIconSelector': '.t3js-delete', + 'sectionSelector': '.t3js-flex-section', + 'sectionContentSelector': '.t3js-flex-section-content', + 'sectionHeaderSelector': '.t3js-flex-section-header', + 'sectionHeaderPreviewSelector': '.t3js-flex-section-header-preview', + 'sectionActionInputFieldSelector': '.t3js-flex-control-action', + 'sectionToggleInputFieldSelector': '.t3js-flex-control-toggle', + 'sectionToggleIconOpenSelector': '.t3js-flex-control-toggle-icon-open', + 'sectionToggleIconCloseSelector': '.t3js-flex-control-toggle-icon-close', + 'sectionToggleButtonSelector': '[data-toggle="formengine-flex"]', + 'flexFormToggleAllSectionsSelector': '.t3js-form-field-toggle-flexsection', + 'sectionDeletedClass': 't3js-flex-section-deleted', + 'allowRestructure': 0, // whether the form can be modified + 'flexformId': false + }; + + + /** + * Allow flexform sections to be sorted + */ + TYPO3.FormEngine.FlexFormElement.prototype.createSortable = function() { + var me = this; + + require(['jquery-ui/sortable'], function() { + me.$el.sortable({ + containment: 'parent', + handle: '.t3js-sortable-handle', + axis: 'y', + tolerance: 'pointer', + stop: function() { + me.setActionStatus(); + } + }); + }); + }; + + // Updates the "action"-status for a section. This is used to move and delete elements. + TYPO3.FormEngine.FlexFormElement.prototype.setActionStatus = function() { + var me = this; + + // Traverse and find how many sections are open or closed, and save the value accordingly + me.$el.find(me.options.sectionActionInputFieldSelector).each(function(index) { + var actionValue = ($(this).parents(me.options.sectionSelector).hasClass(me.options.sectionDeletedClass) ? 'DELETE' : index); + $(this).val(actionValue); + }); + }; + + // Toggling flexform elements on/off + // hides the flexform section and shows a preview text + // or shows the form parts + TYPO3.FormEngine.FlexFormElement.prototype.toggleSection = function($sectionEl) { + + var $contentEl = $sectionEl.find(this.options.sectionContentSelector); + + // display/hide the content of this flexform section + $contentEl.toggle(); + + if ($contentEl.is(':visible')) { + // show the open icon, and set the hidden field for toggling to "hidden" + $sectionEl.find(this.options.sectionToggleIconOpenSelector).show(); + $sectionEl.find(this.options.sectionToggleIconCloseSelector).hide(); + $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(0); + } else { + // show the close icon, and set the hidden field for toggling to "1" + $sectionEl.find(this.options.sectionToggleIconOpenSelector).hide(); + $sectionEl.find(this.options.sectionToggleIconCloseSelector).show(); + $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(1); + } + + // see if the preview content needs to be generated + this.generateSectionPreview($sectionEl); + }; + + // function to generate the section preview in the header + // if the section content is hidden + // called on load and when toggling an icon + TYPO3.FormEngine.FlexFormElement.prototype.generateSectionPreview = function($sectionEl) { + var $contentEl = $sectionEl.find(this.options.sectionContentSelector); + var previewContent = ''; + + if (!$contentEl.is(':visible')) { + $contentEl.find('input[type=text], textarea').each(function() { + var content = $($.parseHTML($(this).val())).text(); + if (content.length > 50) { + content = content.substring(0, 50) + '...'; + } + previewContent += (previewContent ? ' / ' : '') + content; + }); + } + + // create a preview container span element + if ($sectionEl.find(this.options.sectionHeaderPreviewSelector).length === 0) { + $sectionEl.find(this.options.sectionHeaderSelector).find('.t3js-record-title').parent() + .append('<span class="' + this.options.sectionHeaderPreviewSelector.replace(/\./, '') + '"></span>'); + } + + $sectionEl.find(this.options.sectionHeaderPreviewSelector).text(previewContent); + }; + + // register the flex functions as jQuery Plugin + $.fn.t3FormEngineFlexFormElement = function(options) { + // apply all util functions to ourself (for use in templates, etc.) + return this.each(function() { + (new TYPO3.FormEngine.FlexFormElement(this, options)); + }); + }; + + // Initialization Code + $(function() { + // run the flexform functions on all containers (which contains one or more sections) + $('.t3-flex-container').t3FormEngineFlexFormElement(); + + // Add handler to fetch container data on click on "add container" buttons + $('.t3js-flex-container-add').on('click', function(e) { + var me = $(this); + e.preventDefault(); + $.ajax({ + url: TYPO3.settings.ajaxUrls['record_flex_container_add'], + type: 'POST', + cache: false, + data: { + vanillaUid: me.data('vanillauid'), + databaseRowUid: me.data('databaserowuid'), + command: me.data('command'), + tableName: me.data('tablename'), + fieldName: me.data('fieldname'), + recordTypeValue: me.data('recordtypevalue'), + dataStructureIdentifier: me.data('datastructureidentifier'), + flexFormSheetName: me.data('flexformsheetname'), + flexFormFieldName: me.data('flexformfieldname'), + flexFormContainerName: me.data('flexformcontainername') + }, + success: function(response) { + me.closest('.t3-form-field-container').find('.t3-flex-container').append(response.html); + $('.t3-flex-container').t3FormEngineFlexFormElement(); + if (response.scriptCall && response.scriptCall.length > 0) { + $.each(response.scriptCall, function(index, value) { + eval(value); + }); + } + if (response.stylesheetFiles && response.stylesheetFiles.length > 0) { + $.each(response.stylesheetFiles, function(index, stylesheetFile) { + var element = document.createElement('link'); + element['rel'] = 'stylesheet'; + element['type'] = 'text/css'; + element['href'] = stylesheetFile; + document.head.appendChild(element); + }); + } + TYPO3.FormEngine.reinitialize(); + TYPO3.FormEngine.Validation.initializeInputFields(); + TYPO3.FormEngine.Validation.validate(); + } + }); + }); + + }); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js index f350f1306d65883d8d8d6b906ee61e6e42056927..166de25f894a404b0c205a43123e682b5774d7cd 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js @@ -16,61 +16,61 @@ * LinkBrowser communication with parent window */ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) { - 'use strict'; + 'use strict'; - /** - * - * @type {{updateFunctions: null}} - * @exports TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter - */ - var FormEngineLinkBrowserAdapter = { - updateFunctions: null // those are set in the module initializer function in PHP - }; + /** + * + * @type {{updateFunctions: null}} + * @exports TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter + */ + var FormEngineLinkBrowserAdapter = { + updateFunctions: null // those are set in the module initializer function in PHP + }; - /** - * Return reference to parent's form element - * - * @returns {Element} - */ - FormEngineLinkBrowserAdapter.checkReference = function () { - var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]'; - if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) { - return window.opener.document.querySelector(selector); - } else { - close(); - } - }; + /** + * Return reference to parent's form element + * + * @returns {Element} + */ + FormEngineLinkBrowserAdapter.checkReference = function() { + var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]'; + if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) { + return window.opener.document.querySelector(selector); + } else { + close(); + } + }; - /** - * Save the current link back to the opener - * - * @param {String} input - */ - LinkBrowser.finalizeFunction = function(input) { - var field = FormEngineLinkBrowserAdapter.checkReference(); - if (field) { - var attributeValues = LinkBrowser.getLinkAttributeValues(); - // encode link on server - attributeValues.url = input; + /** + * Save the current link back to the opener + * + * @param {String} input + */ + LinkBrowser.finalizeFunction = function(input) { + var field = FormEngineLinkBrowserAdapter.checkReference(); + if (field) { + var attributeValues = LinkBrowser.getLinkAttributeValues(); + // encode link on server + attributeValues.url = input; - $.ajax({ - url: TYPO3.settings.ajaxUrls['link_browser_encodetypolink'], - data: attributeValues, - method: 'GET' - }).done(function(data) { - if (data.typoLink) { - $('#' + field.id, parent.opener.document).val(data.typoLink); - if (typeof field.onchange === 'function') { - field.onchange(); - } + $.ajax({ + url: TYPO3.settings.ajaxUrls['link_browser_encodetypolink'], + data: attributeValues, + method: 'GET' + }).done(function(data) { + if (data.typoLink) { + $('#' + field.id, parent.opener.document).val(data.typoLink); + if (typeof field.onchange === 'function') { + field.onchange(); + } - FormEngineLinkBrowserAdapter.updateFunctions(); + FormEngineLinkBrowserAdapter.updateFunctions(); - close(); - } - }); - } - }; + close(); + } + }); + } + }; - return FormEngineLinkBrowserAdapter; + return FormEngineLinkBrowserAdapter; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js index f43a8d9b80f56dda889f3a3145bd5e3b76ebbbb6..e54c8fcd786c59d910ace2b18c0b51b9afba919a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js @@ -15,114 +15,114 @@ * Module: TYPO3/CMS/Backend/FormEngineSuggest * Functionality to load suggest functionality */ -define(['jquery', 'jquery/autocomplete'], function ($) { - var initialize = function($searchField) { - var $containerElement = $searchField.closest('.t3-form-suggest-container'); - var tableName = $searchField.data('tablename'), - fieldName = $searchField.data('fieldname'), - formEl = $searchField.data('field'), - uid = $searchField.data('uid'), - pid = $searchField.data('pid'), - dataStructureIdentifier = $searchField.data('datastructureidentifier'), - flexFormSheetName = $searchField.data('flexformsheetname'), - flexFormFieldName = $searchField.data('flexformfieldname'), - flexFormContainerName = $searchField.data('flexformcontainername'), - flexFormContainerFieldName = $searchField.data('flexformcontainerfieldname'), - minimumCharacters = $searchField.data('minchars'), - url = TYPO3.settings.ajaxUrls['record_suggest'], - params = { - 'tableName': tableName, - 'fieldName': fieldName, - 'uid': uid, - 'pid': pid, - 'dataStructureIdentifier': dataStructureIdentifier, - 'flexFormSheetName': flexFormSheetName, - 'flexFormFieldName': flexFormFieldName, - 'flexFormContainerName': flexFormContainerName, - 'flexFormContainerFieldName': flexFormContainerFieldName - }, - insertValue = function(element) { - var insertData = ''; - if ($searchField.data('fieldtype') === 'select') { - insertData = $(element).data('uid'); - } else { - insertData = $(element).data('table') + '_' + $(element).data('uid'); - } - var labelEl = $('<div>').html($(element).data('label')); - var label = labelEl.text(); - var title = labelEl.find('span').attr('title') || label; - setFormValueFromBrowseWin(formEl, insertData, label, title); - TBE_EDITOR.fieldChanged(tableName, uid, fieldName, formEl); - }; +define(['jquery', 'jquery/autocomplete'], function($) { + var initialize = function($searchField) { + var $containerElement = $searchField.closest('.t3-form-suggest-container'); + var tableName = $searchField.data('tablename'), + fieldName = $searchField.data('fieldname'), + formEl = $searchField.data('field'), + uid = $searchField.data('uid'), + pid = $searchField.data('pid'), + dataStructureIdentifier = $searchField.data('datastructureidentifier'), + flexFormSheetName = $searchField.data('flexformsheetname'), + flexFormFieldName = $searchField.data('flexformfieldname'), + flexFormContainerName = $searchField.data('flexformcontainername'), + flexFormContainerFieldName = $searchField.data('flexformcontainerfieldname'), + minimumCharacters = $searchField.data('minchars'), + url = TYPO3.settings.ajaxUrls['record_suggest'], + params = { + 'tableName': tableName, + 'fieldName': fieldName, + 'uid': uid, + 'pid': pid, + 'dataStructureIdentifier': dataStructureIdentifier, + 'flexFormSheetName': flexFormSheetName, + 'flexFormFieldName': flexFormFieldName, + 'flexFormContainerName': flexFormContainerName, + 'flexFormContainerFieldName': flexFormContainerFieldName + }, + insertValue = function(element) { + var insertData = ''; + if ($searchField.data('fieldtype') === 'select') { + insertData = $(element).data('uid'); + } else { + insertData = $(element).data('table') + '_' + $(element).data('uid'); + } + var labelEl = $('<div>').html($(element).data('label')); + var label = labelEl.text(); + var title = labelEl.find('span').attr('title') || label; + setFormValueFromBrowseWin(formEl, insertData, label, title); + TBE_EDITOR.fieldChanged(tableName, uid, fieldName, formEl); + }; - $searchField.autocomplete({ - // ajax options - serviceUrl: url, - params: params, - type: 'POST', - paramName: 'value', - dataType: 'json', - minChars: minimumCharacters, - groupBy: 'typeLabel', - containerClass: 'autocomplete-results', - appendTo: $containerElement, - forceFixPosition: false, - preserveInput: true, - showNoSuggestionNotice: true, - noSuggestionNotice: '<div class="autocomplete-info">No results</div>', - minLength: minimumCharacters, - preventBadQueries: false, - // put the AJAX results in the right format - transformResult: function(response) { - return { - suggestions: $.map(response, function(dataItem) { - return { value: dataItem.text, data: dataItem }; - }) - }; - }, - // Rendering of each item - formatResult: function(suggestion, value) { - return $('<div>').append( - $('<a class="autocomplete-suggestion-link" href="#">' + - suggestion.data.sprite + suggestion.data.text + - '</a></div>').attr({ - 'data-label': suggestion.data.label, - 'data-table': suggestion.data.table, - 'data-uid': suggestion.data.uid - })).html(); - }, - onSearchComplete: function() { - $containerElement.addClass('open'); - }, - beforeRender: function(container) { - // Unset height, width and z-index again, should be fixed by the plugin at a later point - container.attr('style', ''); - $containerElement.addClass('open'); - }, - onHide: function() { - $containerElement.removeClass('open'); - }, - onSelect: function() { - insertValue($containerElement.find('.autocomplete-selected a')[0]); - } - }); + $searchField.autocomplete({ + // ajax options + serviceUrl: url, + params: params, + type: 'POST', + paramName: 'value', + dataType: 'json', + minChars: minimumCharacters, + groupBy: 'typeLabel', + containerClass: 'autocomplete-results', + appendTo: $containerElement, + forceFixPosition: false, + preserveInput: true, + showNoSuggestionNotice: true, + noSuggestionNotice: '<div class="autocomplete-info">No results</div>', + minLength: minimumCharacters, + preventBadQueries: false, + // put the AJAX results in the right format + transformResult: function(response) { + return { + suggestions: $.map(response, function(dataItem) { + return {value: dataItem.text, data: dataItem}; + }) + }; + }, + // Rendering of each item + formatResult: function(suggestion, value) { + return $('<div>').append( + $('<a class="autocomplete-suggestion-link" href="#">' + + suggestion.data.sprite + suggestion.data.text + + '</a></div>').attr({ + 'data-label': suggestion.data.label, + 'data-table': suggestion.data.table, + 'data-uid': suggestion.data.uid + })).html(); + }, + onSearchComplete: function() { + $containerElement.addClass('open'); + }, + beforeRender: function(container) { + // Unset height, width and z-index again, should be fixed by the plugin at a later point + container.attr('style', ''); + $containerElement.addClass('open'); + }, + onHide: function() { + $containerElement.removeClass('open'); + }, + onSelect: function() { + insertValue($containerElement.find('.autocomplete-selected a')[0]); + } + }); - // set up the events - $containerElement.on('click', '.autocomplete-suggestion-link', function(evt) { - evt.preventDefault(); - }); - }; + // set up the events + $containerElement.on('click', '.autocomplete-suggestion-link', function(evt) { + evt.preventDefault(); + }); + }; - /** - * Return a function that gets DOM elements that are checked if suggest is already initialized - * @exports TYPO3/CMS/Backend/FormEngineSuggest - */ - return function(selectorElements) { - $(selectorElements).each(function(key, el) { - if (!$(el).data('t3-suggest-initialized')) { - initialize($(el)); - $(el).data('t3-suggest-initialized', true); - } - }); - }; + /** + * Return a function that gets DOM elements that are checked if suggest is already initialized + * @exports TYPO3/CMS/Backend/FormEngineSuggest + */ + return function(selectorElements) { + $(selectorElements).each(function(key, el) { + if (!$(el).data('t3-suggest-initialized')) { + initialize($(el)); + $(el).data('t3-suggest-initialized', true); + } + }); + }; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js index d6523808697dd9cae49aa57244d64663cf49cf81..7c74acb9be0fd68aa7f277c22d3de9d4d14c21ee 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js @@ -16,1009 +16,1009 @@ * Contains all JS functions related to TYPO3 TCEforms/FormEngineValidation * @internal */ -define(['jquery', 'moment'], function ($, moment) { +define(['jquery', 'moment'], function($, moment) { - /** - * The main FormEngineValidation object - * - * @type {{rulesSelector: string, inputSelector: string, markerSelector: string, groupFieldHiddenElement: string, relatedFieldSelector: string, errorClass: string, lastYear: number, lastDate: number, lastTime: number, USmode: number, passwordDummy: string}} - * @exports TYPO3/CMS/Backend/FormEngineValidation - */ - var FormEngineValidation = { - rulesSelector: '[data-formengine-validation-rules]', - inputSelector: '[data-formengine-input-params]', - markerSelector: '.t3js-formengine-validation-marker', - groupFieldHiddenElement: '.t3js-formengine-field-group input[type=hidden]', - relatedFieldSelector: '[data-relatedfieldname]', - errorClass: 'has-error', - lastYear: 0, - lastDate: 0, - lastTime: 0, - USmode: 0, - passwordDummy: '********' - }; + /** + * The main FormEngineValidation object + * + * @type {{rulesSelector: string, inputSelector: string, markerSelector: string, groupFieldHiddenElement: string, relatedFieldSelector: string, errorClass: string, lastYear: number, lastDate: number, lastTime: number, USmode: number, passwordDummy: string}} + * @exports TYPO3/CMS/Backend/FormEngineValidation + */ + var FormEngineValidation = { + rulesSelector: '[data-formengine-validation-rules]', + inputSelector: '[data-formengine-input-params]', + markerSelector: '.t3js-formengine-validation-marker', + groupFieldHiddenElement: '.t3js-formengine-field-group input[type=hidden]', + relatedFieldSelector: '[data-relatedfieldname]', + errorClass: 'has-error', + lastYear: 0, + lastDate: 0, + lastTime: 0, + USmode: 0, + passwordDummy: '********' + }; - /** - * Initialize validation for the first time - */ - FormEngineValidation.initialize = function() { - $(document).find('.' + FormEngineValidation.errorClass).removeClass(FormEngineValidation.errorClass); + /** + * Initialize validation for the first time + */ + FormEngineValidation.initialize = function() { + $(document).find('.' + FormEngineValidation.errorClass).removeClass(FormEngineValidation.errorClass); - // Initialize input fields - FormEngineValidation.initializeInputFields().promise().done(function () { - // Bind to field changes - $(document).on('change', FormEngineValidation.rulesSelector, function() { - FormEngineValidation.validate(); - FormEngineValidation.markFieldAsChanged($(this)); - }); - }); + // Initialize input fields + FormEngineValidation.initializeInputFields().promise().done(function() { + // Bind to field changes + $(document).on('change', FormEngineValidation.rulesSelector, function() { + FormEngineValidation.validate(); + FormEngineValidation.markFieldAsChanged($(this)); + }); + }); - var today = new Date(); - FormEngineValidation.lastYear = FormEngineValidation.getYear(today); - FormEngineValidation.lastDate = FormEngineValidation.getDate(today); - FormEngineValidation.lastTime = 0; - FormEngineValidation.USmode = 0; - FormEngineValidation.validate(); - }; + var today = new Date(); + FormEngineValidation.lastYear = FormEngineValidation.getYear(today); + FormEngineValidation.lastDate = FormEngineValidation.getDate(today); + FormEngineValidation.lastTime = 0; + FormEngineValidation.USmode = 0; + FormEngineValidation.validate(); + }; - /** - * Initialize all input fields - * - * @returns {Object} - */ - FormEngineValidation.initializeInputFields = function() { - return $(document).find(FormEngineValidation.inputSelector).each(function() { - var config = $(this).data('formengine-input-params'); - var fieldName = config.field; - var $field = $('[name="' + fieldName + '"]'); + /** + * Initialize all input fields + * + * @returns {Object} + */ + FormEngineValidation.initializeInputFields = function() { + return $(document).find(FormEngineValidation.inputSelector).each(function() { + var config = $(this).data('formengine-input-params'); + var fieldName = config.field; + var $field = $('[name="' + fieldName + '"]'); - // ignore fields which already have been initialized - if ($field.data('main-field') === undefined) { - $field.data('main-field', fieldName); - $field.data('config', config); - FormEngineValidation.initializeInputField(fieldName); - } - }); - }; + // ignore fields which already have been initialized + if ($field.data('main-field') === undefined) { + $field.data('main-field', fieldName); + $field.data('config', config); + FormEngineValidation.initializeInputField(fieldName); + } + }); + }; - /** - * - * @param {Number} mode - */ - FormEngineValidation.setUsMode = function(mode) { - FormEngineValidation.USmode = mode; - }; + /** + * + * @param {Number} mode + */ + FormEngineValidation.setUsMode = function(mode) { + FormEngineValidation.USmode = mode; + }; - /** - * Initialize field by name - * - * @param {String} fieldName - */ - FormEngineValidation.initializeInputField = function(fieldName) { - var $field = $('[name="' + fieldName + '"]'); - var $humanReadableField = $('[data-formengine-input-name="' + fieldName + '"]'); - var $mainField = $('[name="' + $field.data('main-field') + '"]'); - if ($mainField.length === 0) { - $mainField = $field; - } + /** + * Initialize field by name + * + * @param {String} fieldName + */ + FormEngineValidation.initializeInputField = function(fieldName) { + var $field = $('[name="' + fieldName + '"]'); + var $humanReadableField = $('[data-formengine-input-name="' + fieldName + '"]'); + var $mainField = $('[name="' + $field.data('main-field') + '"]'); + if ($mainField.length === 0) { + $mainField = $field; + } - var config = $mainField.data('config'); - if (typeof config !== 'undefined') { - var evalList = FormEngineValidation.trimExplode(',', config.evalList); - var value = $field.val(); + var config = $mainField.data('config'); + if (typeof config !== 'undefined') { + var evalList = FormEngineValidation.trimExplode(',', config.evalList); + var value = $field.val(); - for (var i = 0; i < evalList.length; i++) { - value = FormEngineValidation.formatValue(evalList[i], value, config); - } - // Prevent password fields to be overwritten with original value - if (value.length && $humanReadableField.attr('type') !== 'password') { - $humanReadableField.val(value); - } - } - $humanReadableField.data('main-field', fieldName); - $humanReadableField.data('config', config); - $humanReadableField.on('change', function() { - FormEngineValidation.updateInputField($(this).attr('data-formengine-input-name')); - }); - $humanReadableField.on('keyup', FormEngineValidation.validate); + for (var i = 0; i < evalList.length; i++) { + value = FormEngineValidation.formatValue(evalList[i], value, config); + } + // Prevent password fields to be overwritten with original value + if (value.length && $humanReadableField.attr('type') !== 'password') { + $humanReadableField.val(value); + } + } + $humanReadableField.data('main-field', fieldName); + $humanReadableField.data('config', config); + $humanReadableField.on('change', function() { + FormEngineValidation.updateInputField($(this).attr('data-formengine-input-name')); + }); + $humanReadableField.on('keyup', FormEngineValidation.validate); - // add the attribute so that acceptance tests can know when the field initialization has completed - $humanReadableField.attr('data-formengine-input-initialized', 'true'); - }; + // add the attribute so that acceptance tests can know when the field initialization has completed + $humanReadableField.attr('data-formengine-input-initialized', 'true'); + }; - /** - * Format field value - * - * @param {String} type - * @param {String} value - * @param {Object} config - * @returns {String} - */ - FormEngineValidation.formatValue = function(type, value, config) { - var theString = ''; - var parsedInt, theTime; - switch (type) { - case 'date': - // poor man’s ISO-8601 detection: if we have a "-" in it, it apparently is not an integer. - if (value.toString().indexOf('-') > 0) { - var date = moment.utc(value); - if (FormEngineValidation.USmode) { - theString = date.format('MM-DD-YYYY'); - } else { - theString = date.format('DD-MM-YYYY'); - } - } else { - parsedInt = value * 1; - if (!parsedInt) { - return ''; - } - theTime = new Date(parsedInt * 1000); - if (FormEngineValidation.USmode) { - theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime); - } else { - theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime); - } - } - break; - case 'datetime': - if (value.toString().indexOf('-') <= 0 && !parseInt(value)) { - return ''; - } - theString = FormEngineValidation.formatValue('time', value, config) + ' ' + FormEngineValidation.formatValue('date', value, config); - break; - case 'time': - case 'timesec': - var dateValue; - if (value.toString().indexOf('-') > 0) { - dateValue = moment.utc(value); - } else { - parsedInt = parseInt(value); - if (!parsedInt && value.toString() !== '0') { - return ''; - } - dateValue = moment.unix(parsedInt).utc(); - } - if (type === 'timesec') { - theString = dateValue.format('HH:mm:ss'); - } else { - theString = dateValue.format('HH:mm'); - } - break; - case 'password': - theString = (value) ? FormEngineValidation.passwordDummy : ''; - break; - default: - theString = value; - } - return theString; - }; + /** + * Format field value + * + * @param {String} type + * @param {String} value + * @param {Object} config + * @returns {String} + */ + FormEngineValidation.formatValue = function(type, value, config) { + var theString = ''; + var parsedInt, theTime; + switch (type) { + case 'date': + // poor man’s ISO-8601 detection: if we have a "-" in it, it apparently is not an integer. + if (value.toString().indexOf('-') > 0) { + var date = moment.utc(value); + if (FormEngineValidation.USmode) { + theString = date.format('MM-DD-YYYY'); + } else { + theString = date.format('DD-MM-YYYY'); + } + } else { + parsedInt = value * 1; + if (!parsedInt) { + return ''; + } + theTime = new Date(parsedInt * 1000); + if (FormEngineValidation.USmode) { + theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime); + } else { + theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime); + } + } + break; + case 'datetime': + if (value.toString().indexOf('-') <= 0 && !parseInt(value)) { + return ''; + } + theString = FormEngineValidation.formatValue('time', value, config) + ' ' + FormEngineValidation.formatValue('date', value, config); + break; + case 'time': + case 'timesec': + var dateValue; + if (value.toString().indexOf('-') > 0) { + dateValue = moment.utc(value); + } else { + parsedInt = parseInt(value); + if (!parsedInt && value.toString() !== '0') { + return ''; + } + dateValue = moment.unix(parsedInt).utc(); + } + if (type === 'timesec') { + theString = dateValue.format('HH:mm:ss'); + } else { + theString = dateValue.format('HH:mm'); + } + break; + case 'password': + theString = (value) ? FormEngineValidation.passwordDummy : ''; + break; + default: + theString = value; + } + return theString; + }; - /** - * Update input field after change - * - * @param {String} fieldName - */ - FormEngineValidation.updateInputField = function(fieldName) { - var $field = $('[name="' + fieldName + '"]'); - var $mainField = $('[name="' + $field.data('main-field') + '"]'); - if ($mainField.length === 0) { - $mainField = $field; - } - var $humanReadableField = $('[data-formengine-input-name="' + $mainField.attr('name') + '"]'); + /** + * Update input field after change + * + * @param {String} fieldName + */ + FormEngineValidation.updateInputField = function(fieldName) { + var $field = $('[name="' + fieldName + '"]'); + var $mainField = $('[name="' + $field.data('main-field') + '"]'); + if ($mainField.length === 0) { + $mainField = $field; + } + var $humanReadableField = $('[data-formengine-input-name="' + $mainField.attr('name') + '"]'); - var config = $mainField.data('config'); - if (typeof config !== 'undefined') { - var evalList = FormEngineValidation.trimExplode(',', config.evalList); - var newValue = $humanReadableField.val(); - var i; + var config = $mainField.data('config'); + if (typeof config !== 'undefined') { + var evalList = FormEngineValidation.trimExplode(',', config.evalList); + var newValue = $humanReadableField.val(); + var i; - for (i = 0; i < evalList.length; i++) { - newValue = FormEngineValidation.processValue(evalList[i], newValue, config); - } + for (i = 0; i < evalList.length; i++) { + newValue = FormEngineValidation.processValue(evalList[i], newValue, config); + } - var formattedValue = newValue; - for (i = 0; i < evalList.length; i++) { - formattedValue = FormEngineValidation.formatValue(evalList[i], formattedValue, config); - } + var formattedValue = newValue; + for (i = 0; i < evalList.length; i++) { + formattedValue = FormEngineValidation.formatValue(evalList[i], formattedValue, config); + } - $mainField.val(newValue); - $humanReadableField.val(formattedValue); - } - }; + $mainField.val(newValue); + $humanReadableField.val(formattedValue); + } + }; - /** - * Run validation for field - * - * @param {Object} $field - * @param {String} [value=$field.val()] - * @returns {String} - */ - FormEngineValidation.validateField = function($field, value) { - value = value || $field.val() || ''; + /** + * Run validation for field + * + * @param {Object} $field + * @param {String} [value=$field.val()] + * @returns {String} + */ + FormEngineValidation.validateField = function($field, value) { + value = value || $field.val() || ''; - var rules = $field.data('formengine-validation-rules'); - var markParent = false; - var selected = 0; - // keep the original value, validateField should not alter it - var returnValue = value; - var $relatedField; - var minItems; - var maxItems; + var rules = $field.data('formengine-validation-rules'); + var markParent = false; + var selected = 0; + // keep the original value, validateField should not alter it + var returnValue = value; + var $relatedField; + var minItems; + var maxItems; - if (!$.isArray(value)) { - value = FormEngineValidation.ltrim(value); - } + if (!$.isArray(value)) { + value = FormEngineValidation.ltrim(value); + } - $.each(rules, function(k, rule) { - if (markParent) { - // abort any further validation as validating the field already failed - return false; - } - switch (rule.type) { - case 'required': - if (value === '') { - markParent = true; - $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass); - } - break; - case 'range': - if (value !== '') { - if (rule.minItems || rule.maxItems) { - $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]'); - if ($relatedField.length) { - selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length; - } else { - selected = $field.val(); - } - if (typeof rule.minItems !== 'undefined') { - minItems = rule.minItems * 1; - if (!isNaN(minItems) && selected < minItems) { - markParent = true; - } - } - if (typeof rule.maxItems !== 'undefined') { - maxItems = rule.maxItems * 1; - if (!isNaN(maxItems) && selected > maxItems) { - markParent = true; - } - } - } - if (typeof rule.lower !== 'undefined') { - var minValue = rule.lower * 1; - if (!isNaN(minValue) && value < minValue) { - markParent = true; - } - } - if (typeof rule.upper !== 'undefined') { - var maxValue = rule.upper * 1; - if (!isNaN(maxValue) && value > maxValue) { - markParent = true; - } - } - } - break; - case 'select': - if (rule.minItems || rule.maxItems) { - $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]'); - if ($relatedField.length) { - selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length; - } else { - selected = $field.find('option:selected').length; - } - if (typeof rule.minItems !== 'undefined') { - minItems = rule.minItems * 1; - if (!isNaN(minItems) && selected < minItems) { - markParent = true; - } - } - if (typeof rule.maxItems !== 'undefined') { - maxItems = rule.maxItems * 1; - if (!isNaN(maxItems) && selected > maxItems) { - markParent = true; - } - } - } - break; - case 'group': - if (rule.minItems || rule.maxItems) { - selected = $field.find('option').length; - if (typeof rule.minItems !== 'undefined') { - minItems = rule.minItems * 1; - if (!isNaN(minItems) && selected < minItems) { - markParent = true; - } - } - if (typeof rule.maxItems !== 'undefined') { - maxItems = rule.maxItems * 1; - if (!isNaN(maxItems) && selected > maxItems) { - markParent = true; - } - } - } - break; - case 'inline': - if (rule.minItems || rule.maxItems) { - selected = FormEngineValidation.trimExplode(',', $field.val()).length; - if (typeof rule.minItems !== 'undefined') { - minItems = rule.minItems * 1; - if (!isNaN(minItems) && selected < minItems) { - markParent = true; - } - } - if (typeof rule.maxItems !== 'undefined') { - maxItems = rule.maxItems * 1; - if (!isNaN(maxItems) && selected > maxItems) { - markParent = true; - } - } - } - break; - case 'null': - // unknown type null, we ignore it - break; - } - }); - if (markParent) { - // mark field - $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass); + $.each(rules, function(k, rule) { + if (markParent) { + // abort any further validation as validating the field already failed + return false; + } + switch (rule.type) { + case 'required': + if (value === '') { + markParent = true; + $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass); + } + break; + case 'range': + if (value !== '') { + if (rule.minItems || rule.maxItems) { + $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]'); + if ($relatedField.length) { + selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length; + } else { + selected = $field.val(); + } + if (typeof rule.minItems !== 'undefined') { + minItems = rule.minItems * 1; + if (!isNaN(minItems) && selected < minItems) { + markParent = true; + } + } + if (typeof rule.maxItems !== 'undefined') { + maxItems = rule.maxItems * 1; + if (!isNaN(maxItems) && selected > maxItems) { + markParent = true; + } + } + } + if (typeof rule.lower !== 'undefined') { + var minValue = rule.lower * 1; + if (!isNaN(minValue) && value < minValue) { + markParent = true; + } + } + if (typeof rule.upper !== 'undefined') { + var maxValue = rule.upper * 1; + if (!isNaN(maxValue) && value > maxValue) { + markParent = true; + } + } + } + break; + case 'select': + if (rule.minItems || rule.maxItems) { + $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]'); + if ($relatedField.length) { + selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length; + } else { + selected = $field.find('option:selected').length; + } + if (typeof rule.minItems !== 'undefined') { + minItems = rule.minItems * 1; + if (!isNaN(minItems) && selected < minItems) { + markParent = true; + } + } + if (typeof rule.maxItems !== 'undefined') { + maxItems = rule.maxItems * 1; + if (!isNaN(maxItems) && selected > maxItems) { + markParent = true; + } + } + } + break; + case 'group': + if (rule.minItems || rule.maxItems) { + selected = $field.find('option').length; + if (typeof rule.minItems !== 'undefined') { + minItems = rule.minItems * 1; + if (!isNaN(minItems) && selected < minItems) { + markParent = true; + } + } + if (typeof rule.maxItems !== 'undefined') { + maxItems = rule.maxItems * 1; + if (!isNaN(maxItems) && selected > maxItems) { + markParent = true; + } + } + } + break; + case 'inline': + if (rule.minItems || rule.maxItems) { + selected = FormEngineValidation.trimExplode(',', $field.val()).length; + if (typeof rule.minItems !== 'undefined') { + minItems = rule.minItems * 1; + if (!isNaN(minItems) && selected < minItems) { + markParent = true; + } + } + if (typeof rule.maxItems !== 'undefined') { + maxItems = rule.maxItems * 1; + if (!isNaN(maxItems) && selected > maxItems) { + markParent = true; + } + } + } + break; + case 'null': + // unknown type null, we ignore it + break; + } + }); + if (markParent) { + // mark field + $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass); - // check tabs - FormEngineValidation.markParentTab($field); - } - return returnValue; - }; + // check tabs + FormEngineValidation.markParentTab($field); + } + return returnValue; + }; - /** - * Process a value by given command and config - * - * @param {String} command - * @param {String} value - * @param {Array} config - * @returns {String} - */ - FormEngineValidation.processValue = function(command, value, config) { - var newString = ''; - var theValue = ''; - var theCmd = ''; - var a = 0; - var returnValue = value; - switch (command) { - case 'alpha': - case 'num': - case 'alphanum': - case 'alphanum_x': - newString = ''; - for (a = 0; a < value.length; a++) { - theChar = value.substr(a, 1); - var special = (theChar === '_' || theChar === '-'); - var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z'); - var num = (theChar >= '0' && theChar <= '9'); - switch (command) { - case 'alphanum': - special = 0; - break; - case 'alpha': - num = 0; - special = 0; - break; - case 'num': - alpha = 0; - special = 0; - break; - } - if (alpha || num || special) { - newString += theChar; - } - } - if (newString !== value) { - returnValue = newString; - } - break; - case 'is_in': - if (config.is_in) { - theValue = '' + value; - // Escape special characters, see https://stackoverflow.com/a/6969486/4828813 - config.is_in = config.is_in.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); - var re = new RegExp('[^' + config.is_in + ']+', 'g'); - newString = theValue.replace(re, ''); - } else { - newString = theValue; - } - returnValue = newString; - break; - case 'nospace': - returnValue = ('' + value).replace(/ /g, ''); - break; - case 'md5': - if (value !== '') { - returnValue = MD5(value); - } - break; - case 'upper': - returnValue = value.toUpperCase(); - break; - case 'lower': - returnValue = value.toLowerCase(); - break; - case 'int': - if (value !== '') { - returnValue = FormEngineValidation.parseInt(value); - } - break; - case 'double2': - if (value !== '') { - returnValue = FormEngineValidation.parseDouble(value); - } - break; - case 'trim': - returnValue = String(value).trim(); - break; - case 'datetime': - if (value !== '') { - theCmd = value.substr(0, 1); - returnValue = FormEngineValidation.parseDateTime(value, theCmd); - } - break; - case 'date': - if (value !== '') { - theCmd = value.substr(0, 1); - returnValue = FormEngineValidation.parseDate(value, theCmd); - } - break; - case 'time': - case 'timesec': - if (value !== '') { - theCmd = value.substr(0, 1); - returnValue = FormEngineValidation.parseTime(value, theCmd, command); - } - break; - case 'year': - if (value !== '') { - theCmd = value.substr(0, 1); - returnValue = FormEngineValidation.parseYear(value, theCmd); - } - break; - case 'null': - // unknown type null, we ignore it - break; - case 'password': - // password is only a display evaluation, we ignore it - break; - default: - if (typeof TBE_EDITOR.customEvalFunctions !== 'undefined' && typeof TBE_EDITOR.customEvalFunctions[command] === 'function') { - returnValue = TBE_EDITOR.customEvalFunctions[command](value); - } - } - return returnValue; - }; + /** + * Process a value by given command and config + * + * @param {String} command + * @param {String} value + * @param {Array} config + * @returns {String} + */ + FormEngineValidation.processValue = function(command, value, config) { + var newString = ''; + var theValue = ''; + var theCmd = ''; + var a = 0; + var returnValue = value; + switch (command) { + case 'alpha': + case 'num': + case 'alphanum': + case 'alphanum_x': + newString = ''; + for (a = 0; a < value.length; a++) { + theChar = value.substr(a, 1); + var special = (theChar === '_' || theChar === '-'); + var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z'); + var num = (theChar >= '0' && theChar <= '9'); + switch (command) { + case 'alphanum': + special = 0; + break; + case 'alpha': + num = 0; + special = 0; + break; + case 'num': + alpha = 0; + special = 0; + break; + } + if (alpha || num || special) { + newString += theChar; + } + } + if (newString !== value) { + returnValue = newString; + } + break; + case 'is_in': + if (config.is_in) { + theValue = '' + value; + // Escape special characters, see https://stackoverflow.com/a/6969486/4828813 + config.is_in = config.is_in.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + var re = new RegExp('[^' + config.is_in + ']+', 'g'); + newString = theValue.replace(re, ''); + } else { + newString = theValue; + } + returnValue = newString; + break; + case 'nospace': + returnValue = ('' + value).replace(/ /g, ''); + break; + case 'md5': + if (value !== '') { + returnValue = MD5(value); + } + break; + case 'upper': + returnValue = value.toUpperCase(); + break; + case 'lower': + returnValue = value.toLowerCase(); + break; + case 'int': + if (value !== '') { + returnValue = FormEngineValidation.parseInt(value); + } + break; + case 'double2': + if (value !== '') { + returnValue = FormEngineValidation.parseDouble(value); + } + break; + case 'trim': + returnValue = String(value).trim(); + break; + case 'datetime': + if (value !== '') { + theCmd = value.substr(0, 1); + returnValue = FormEngineValidation.parseDateTime(value, theCmd); + } + break; + case 'date': + if (value !== '') { + theCmd = value.substr(0, 1); + returnValue = FormEngineValidation.parseDate(value, theCmd); + } + break; + case 'time': + case 'timesec': + if (value !== '') { + theCmd = value.substr(0, 1); + returnValue = FormEngineValidation.parseTime(value, theCmd, command); + } + break; + case 'year': + if (value !== '') { + theCmd = value.substr(0, 1); + returnValue = FormEngineValidation.parseYear(value, theCmd); + } + break; + case 'null': + // unknown type null, we ignore it + break; + case 'password': + // password is only a display evaluation, we ignore it + break; + default: + if (typeof TBE_EDITOR.customEvalFunctions !== 'undefined' && typeof TBE_EDITOR.customEvalFunctions[command] === 'function') { + returnValue = TBE_EDITOR.customEvalFunctions[command](value); + } + } + return returnValue; + }; - /** - * Validate the complete form - */ - FormEngineValidation.validate = function() { - $(document).find(FormEngineValidation.markerSelector + ', .t3js-tabmenu-item') - .removeClass(FormEngineValidation.errorClass) - .removeClass('has-validation-error'); + /** + * Validate the complete form + */ + FormEngineValidation.validate = function() { + $(document).find(FormEngineValidation.markerSelector + ', .t3js-tabmenu-item') + .removeClass(FormEngineValidation.errorClass) + .removeClass('has-validation-error'); - $(FormEngineValidation.rulesSelector).each(function() { - var $field = $(this); - if (!$field.closest('.t3js-flex-section-deleted, .t3js-inline-record-deleted').length) { - var modified = false; - var currentValue = $field.val(); - var newValue = FormEngineValidation.validateField($field, currentValue); - if ($.isArray(newValue) && $.isArray(currentValue)) { - // handling for multi-selects - if (newValue.length !== currentValue.length) { - modified = true; - } else { - for (var i = 0; i < newValue.length; i++) { - if (newValue[i] !== currentValue[i]) { - modified = true; - break; - } - } - } - } else if (newValue.length && currentValue !== newValue) { - modified = true; - } - if (modified) { - $field.val(newValue); - } - } - }); - $(document).trigger('t3-formengine-postfieldvalidation'); - }; + $(FormEngineValidation.rulesSelector).each(function() { + var $field = $(this); + if (!$field.closest('.t3js-flex-section-deleted, .t3js-inline-record-deleted').length) { + var modified = false; + var currentValue = $field.val(); + var newValue = FormEngineValidation.validateField($field, currentValue); + if ($.isArray(newValue) && $.isArray(currentValue)) { + // handling for multi-selects + if (newValue.length !== currentValue.length) { + modified = true; + } else { + for (var i = 0; i < newValue.length; i++) { + if (newValue[i] !== currentValue[i]) { + modified = true; + break; + } + } + } + } else if (newValue.length && currentValue !== newValue) { + modified = true; + } + if (modified) { + $field.val(newValue); + } + } + }); + $(document).trigger('t3-formengine-postfieldvalidation'); + }; - /** - * Helper function to mark a field as changed. - * - * @param {Object} $field - */ - FormEngineValidation.markFieldAsChanged = function($field) { - var $paletteField = $field.closest('.t3js-formengine-palette-field'); - $paletteField.addClass('has-change'); - }; + /** + * Helper function to mark a field as changed. + * + * @param {Object} $field + */ + FormEngineValidation.markFieldAsChanged = function($field) { + var $paletteField = $field.closest('.t3js-formengine-palette-field'); + $paletteField.addClass('has-change'); + }; - /** - * Helper function to get clean trimmed array from comma list - * - * @param {String} delimiter - * @param {String} string - * @returns {Array} - */ - FormEngineValidation.trimExplode = function(delimiter, string) { - var result = []; - var items = string.split(delimiter); - for (var i=0; i<items.length; i++) { - var item = items[i].trim(); - if (item.length > 0) { - result.push(item); - } - } - return result; - }; + /** + * Helper function to get clean trimmed array from comma list + * + * @param {String} delimiter + * @param {String} string + * @returns {Array} + */ + FormEngineValidation.trimExplode = function(delimiter, string) { + var result = []; + var items = string.split(delimiter); + for (var i = 0; i < items.length; i++) { + var item = items[i].trim(); + if (item.length > 0) { + result.push(item); + } + } + return result; + }; - /** - * Parse value to integer - * - * @param {(Number|String)} value - * @returns {Number} - */ - FormEngineValidation.parseInt = function(value) { - var theVal = '' + value, - returnValue; + /** + * Parse value to integer + * + * @param {(Number|String)} value + * @returns {Number} + */ + FormEngineValidation.parseInt = function(value) { + var theVal = '' + value, + returnValue; - if (!value) { - return 0; - } + if (!value) { + return 0; + } - returnValue = parseInt(theVal, 10); - if (isNaN(returnValue)) { - return 0; - } - return returnValue; - }; + returnValue = parseInt(theVal, 10); + if (isNaN(returnValue)) { + return 0; + } + return returnValue; + }; - /** - * Parse value to double - * - * @param {String} value - * @returns {String} - */ - FormEngineValidation.parseDouble = function(value) { - var theVal = '' + value; - theVal = theVal.replace(/[^0-9,\.-]/g, ''); - var negative = theVal.substring(0, 1) === '-'; - theVal = theVal.replace(/-/g, ''); - theVal = theVal.replace(/,/g, '.'); - if (theVal.indexOf('.') === -1) { - theVal += '.0'; - } - var parts = theVal.split('.'); - var dec = parts.pop(); - theVal = Number(parts.join('') + '.' + dec); - if (negative) { - theVal *= -1; - } - theVal = theVal.toFixed(2); + /** + * Parse value to double + * + * @param {String} value + * @returns {String} + */ + FormEngineValidation.parseDouble = function(value) { + var theVal = '' + value; + theVal = theVal.replace(/[^0-9,\.-]/g, ''); + var negative = theVal.substring(0, 1) === '-'; + theVal = theVal.replace(/-/g, ''); + theVal = theVal.replace(/,/g, '.'); + if (theVal.indexOf('.') === -1) { + theVal += '.0'; + } + var parts = theVal.split('.'); + var dec = parts.pop(); + theVal = Number(parts.join('') + '.' + dec); + if (negative) { + theVal *= -1; + } + theVal = theVal.toFixed(2); - return theVal; - }; + return theVal; + }; - /** - * Trims leading whitespace characters - * - * @param {String} value - * @returns {String} - */ - FormEngineValidation.ltrim = function(value) { - var theVal = '' + value; - if (!value) { - return ''; - } - return theVal.replace(/^\s+/, ''); - }; + /** + * Trims leading whitespace characters + * + * @param {String} value + * @returns {String} + */ + FormEngineValidation.ltrim = function(value) { + var theVal = '' + value; + if (!value) { + return ''; + } + return theVal.replace(/^\s+/, ''); + }; - /** - * Trims trailing whitespace characters - * - * @param {String} value - * @returns {String} - */ - FormEngineValidation.btrim = function(value) { - var theVal = '' + value; - if (!value) { - return ''; - } - return theVal.replace(/\s+$/, ''); - }; + /** + * Trims trailing whitespace characters + * + * @param {String} value + * @returns {String} + */ + FormEngineValidation.btrim = function(value) { + var theVal = '' + value; + if (!value) { + return ''; + } + return theVal.replace(/\s+$/, ''); + }; - /** - * Parse datetime value - * - * @param {String} value - * @param {String} command - * @returns {*} - */ - FormEngineValidation.parseDateTime = function(value, command) { - var today = new Date(); - var values = FormEngineValidation.split(value); - var add = 0; - switch (command) { - case 'd': - case 't': - case 'n': - FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0); - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - case '+': - case '-': - if (FormEngineValidation.lastTime === 0) { - FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0); - } - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - default: - var index = value.indexOf(' '); - if (index !== -1) { - var dateVal = FormEngineValidation.parseDate(value.substr(index, value.length), value.substr(0, 1)); - FormEngineValidation.lastTime = dateVal + FormEngineValidation.parseTime(value.substr(0, index), value.substr(0, 1), 'time'); - } else { - // only date, no time - FormEngineValidation.lastTime = FormEngineValidation.parseDate(value, value.substr(0, 1)); - } - } - FormEngineValidation.lastTime += add * 24 * 60 * 60; - return FormEngineValidation.lastTime; - }; + /** + * Parse datetime value + * + * @param {String} value + * @param {String} command + * @returns {*} + */ + FormEngineValidation.parseDateTime = function(value, command) { + var today = new Date(); + var values = FormEngineValidation.split(value); + var add = 0; + switch (command) { + case 'd': + case 't': + case 'n': + FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0); + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + case '+': + case '-': + if (FormEngineValidation.lastTime === 0) { + FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0); + } + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + default: + var index = value.indexOf(' '); + if (index !== -1) { + var dateVal = FormEngineValidation.parseDate(value.substr(index, value.length), value.substr(0, 1)); + FormEngineValidation.lastTime = dateVal + FormEngineValidation.parseTime(value.substr(0, index), value.substr(0, 1), 'time'); + } else { + // only date, no time + FormEngineValidation.lastTime = FormEngineValidation.parseDate(value, value.substr(0, 1)); + } + } + FormEngineValidation.lastTime += add * 24 * 60 * 60; + return FormEngineValidation.lastTime; + }; - /** - * Parse date value - * - * @param {String} value - * @param {String} command - * @returns {*} - */ - FormEngineValidation.parseDate = function(value, command) { - var today = new Date(); - var values = FormEngineValidation.split(value); - var add = 0; - switch (command) { - case 'd': - case 't': - case 'n': - FormEngineValidation.lastDate = FormEngineValidation.getTimestamp(today); - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - case '+': - case '-': - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - default: - var index = 4; - if (values.valPol[index]) { - add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index])); - } - if (values.values[1] && values.values[1].length > 2) { - if (values.valPol[2]) { - add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); - } - var temp = values.values[1]; - values = FormEngineValidation.splitSingle(temp); - } + /** + * Parse date value + * + * @param {String} value + * @param {String} command + * @returns {*} + */ + FormEngineValidation.parseDate = function(value, command) { + var today = new Date(); + var values = FormEngineValidation.split(value); + var add = 0; + switch (command) { + case 'd': + case 't': + case 'n': + FormEngineValidation.lastDate = FormEngineValidation.getTimestamp(today); + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + case '+': + case '-': + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + default: + var index = 4; + if (values.valPol[index]) { + add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index])); + } + if (values.values[1] && values.values[1].length > 2) { + if (values.valPol[2]) { + add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); + } + var temp = values.values[1]; + values = FormEngineValidation.splitSingle(temp); + } - var year = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : FormEngineValidation.getYear(today); - var usMode = FormEngineValidation.USmode ? 1 : 2; - var month = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCMonth() + 1; - usMode = FormEngineValidation.USmode ? 2 : 1; - var day = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCDate(); + var year = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : FormEngineValidation.getYear(today); + var usMode = FormEngineValidation.USmode ? 1 : 2; + var month = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCMonth() + 1; + usMode = FormEngineValidation.USmode ? 2 : 1; + var day = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCDate(); - var theTime = moment.utc(); - theTime.year(parseInt(year)).month(parseInt(month)-1).date(parseInt(day)).hour(0).minute(0).second(0); - FormEngineValidation.lastDate = theTime.unix(); - } - FormEngineValidation.lastDate += add * 24 * 60 * 60; - return FormEngineValidation.lastDate; - }; + var theTime = moment.utc(); + theTime.year(parseInt(year)).month(parseInt(month) - 1).date(parseInt(day)).hour(0).minute(0).second(0); + FormEngineValidation.lastDate = theTime.unix(); + } + FormEngineValidation.lastDate += add * 24 * 60 * 60; + return FormEngineValidation.lastDate; + }; - /** - * Parse time value - * - * @param {String} value - * @param {String} command - * @param {String} type - * @returns {*} - */ - FormEngineValidation.parseTime = function(value, command, type) { - var today = new Date(); - var values = FormEngineValidation.split(value); - var add = 0; - switch (command) { - case 'd': - case 't': - case 'n': - FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today); - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - case '+': - case '-': - if (FormEngineValidation.lastTime == 0) { - FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today); - } - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - default: - var index = (type === 'timesec') ? 4 : 3; - if (values.valPol[index]) { - add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index])); - } - if (values.values[1] && values.values[1].length > 2) { - if (values.valPol[2]) { - add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); - } - var temp = values.values[1]; - values = FormEngineValidation.splitSingle(temp); - } - var sec = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : today.getUTCSeconds(); - if (sec > 59) { - sec = 59; - } - var min = (values.values[2]) ? FormEngineValidation.parseInt(values.values[2]) : today.getUTCMinutes(); - if (min > 59) { - min = 59; - } - var hour = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : today.getUTCHours(); - if (hour >= 24) { - hour = 0; - } + /** + * Parse time value + * + * @param {String} value + * @param {String} command + * @param {String} type + * @returns {*} + */ + FormEngineValidation.parseTime = function(value, command, type) { + var today = new Date(); + var values = FormEngineValidation.split(value); + var add = 0; + switch (command) { + case 'd': + case 't': + case 'n': + FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today); + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + case '+': + case '-': + if (FormEngineValidation.lastTime == 0) { + FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today); + } + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + default: + var index = (type === 'timesec') ? 4 : 3; + if (values.valPol[index]) { + add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index])); + } + if (values.values[1] && values.values[1].length > 2) { + if (values.valPol[2]) { + add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); + } + var temp = values.values[1]; + values = FormEngineValidation.splitSingle(temp); + } + var sec = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : today.getUTCSeconds(); + if (sec > 59) { + sec = 59; + } + var min = (values.values[2]) ? FormEngineValidation.parseInt(values.values[2]) : today.getUTCMinutes(); + if (min > 59) { + min = 59; + } + var hour = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : today.getUTCHours(); + if (hour >= 24) { + hour = 0; + } - var theTime = moment.utc(); - theTime.year(1970).month(0).date(1).hour(hour).minute(min).second(type === 'timesec' ? sec : 0); + var theTime = moment.utc(); + theTime.year(1970).month(0).date(1).hour(hour).minute(min).second(type === 'timesec' ? sec : 0); - FormEngineValidation.lastTime = theTime.unix(); - } - FormEngineValidation.lastTime += add * 60; - if (FormEngineValidation.lastTime < 0) { - FormEngineValidation.lastTime += 24 * 60 * 60; - } - return FormEngineValidation.lastTime; - }; + FormEngineValidation.lastTime = theTime.unix(); + } + FormEngineValidation.lastTime += add * 60; + if (FormEngineValidation.lastTime < 0) { + FormEngineValidation.lastTime += 24 * 60 * 60; + } + return FormEngineValidation.lastTime; + }; - /** - * Parse year value - * - * @param {String} value - * @param {String} command - * @returns {*} - */ - FormEngineValidation.parseYear = function(value, command) { - var today = new Date(); - var values = FormEngineValidation.split(value); - var add = 0; - switch (command) { - case 'd': - case 't': - case 'n': - FormEngineValidation.lastYear = FormEngineValidation.getYear(today); - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - case '+': - case '-': - if (values.valPol[1]) { - add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); - } - break; - default: - if (values.valPol[2]) { - add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); - } - var year = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : FormEngineValidation.getYear(today); - FormEngineValidation.lastYear = year; - } - FormEngineValidation.lastYear += add; - return FormEngineValidation.lastYear; - }; + /** + * Parse year value + * + * @param {String} value + * @param {String} command + * @returns {*} + */ + FormEngineValidation.parseYear = function(value, command) { + var today = new Date(); + var values = FormEngineValidation.split(value); + var add = 0; + switch (command) { + case 'd': + case 't': + case 'n': + FormEngineValidation.lastYear = FormEngineValidation.getYear(today); + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + case '+': + case '-': + if (values.valPol[1]) { + add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1])); + } + break; + default: + if (values.valPol[2]) { + add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2])); + } + var year = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : FormEngineValidation.getYear(today); + FormEngineValidation.lastYear = year; + } + FormEngineValidation.lastYear += add; + return FormEngineValidation.lastYear; + }; - /** - * Get year from date object - * - * @param {Date} timeObj - * @returns {?number} - */ - FormEngineValidation.getYear = function(timeObj) { - if (timeObj === null) { - return null; - } - return timeObj.getUTCFullYear(); - }; + /** + * Get year from date object + * + * @param {Date} timeObj + * @returns {?number} + */ + FormEngineValidation.getYear = function(timeObj) { + if (timeObj === null) { + return null; + } + return timeObj.getUTCFullYear(); + }; - /** - * Get date as timestamp from Date object - * - * @param {Date} timeObj - * @returns {Number} - */ - FormEngineValidation.getDate = function(timeObj) { - var theTime = new Date(FormEngineValidation.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate()); - return FormEngineValidation.getTimestamp(theTime); - }; + /** + * Get date as timestamp from Date object + * + * @param {Date} timeObj + * @returns {Number} + */ + FormEngineValidation.getDate = function(timeObj) { + var theTime = new Date(FormEngineValidation.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate()); + return FormEngineValidation.getTimestamp(theTime); + }; - /** - * - * @param {String} foreign - * @param {String} value - * @returns {Object} - */ - FormEngineValidation.pol = function(foreign, value) { - return eval(((foreign == '-') ? '-' : '') + value); - }; + /** + * + * @param {String} foreign + * @param {String} value + * @returns {Object} + */ + FormEngineValidation.pol = function(foreign, value) { + return eval(((foreign == '-') ? '-' : '') + value); + }; - /** - * Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server - * - * @param {Number} timestamp - * @param {Number} timeonly - * @returns {*} - */ - FormEngineValidation.convertClientTimestampToUTC = function(timestamp, timeonly) { - var timeObj = new Date(timestamp*1000); - timeObj.setTime((timestamp - timeObj.getTimezoneOffset()*60)*1000); - if (timeonly) { - // only seconds since midnight - return FormEngineValidation.getTime(timeObj); - } else { - // seconds since the "unix-epoch" - return FormEngineValidation.getTimestamp(timeObj); - } - }; + /** + * Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server + * + * @param {Number} timestamp + * @param {Number} timeonly + * @returns {*} + */ + FormEngineValidation.convertClientTimestampToUTC = function(timestamp, timeonly) { + var timeObj = new Date(timestamp * 1000); + timeObj.setTime((timestamp - timeObj.getTimezoneOffset() * 60) * 1000); + if (timeonly) { + // only seconds since midnight + return FormEngineValidation.getTime(timeObj); + } else { + // seconds since the "unix-epoch" + return FormEngineValidation.getTimestamp(timeObj); + } + }; - /** - * Parse date string or object and return unix timestamp - * - * @param {(String|Date)} timeObj - * @returns {Number} - */ - FormEngineValidation.getTimestamp = function(timeObj) { - return Date.parse(timeObj)/1000; - }; + /** + * Parse date string or object and return unix timestamp + * + * @param {(String|Date)} timeObj + * @returns {Number} + */ + FormEngineValidation.getTimestamp = function(timeObj) { + return Date.parse(timeObj) / 1000; + }; - /** - * Seconds since midnight - * - * @param timeObj - * @returns {*} - */ - FormEngineValidation.getTime = function(timeObj) { - return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + FormEngineValidation.getSecs(timeObj); - }; + /** + * Seconds since midnight + * + * @param timeObj + * @returns {*} + */ + FormEngineValidation.getTime = function(timeObj) { + return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + FormEngineValidation.getSecs(timeObj); + }; - /** - * - * @param timeObj - * @returns {Number} - */ - FormEngineValidation.getSecs = function(timeObj) { - return timeObj.getUTCSeconds(); - }; + /** + * + * @param timeObj + * @returns {Number} + */ + FormEngineValidation.getSecs = function(timeObj) { + return timeObj.getUTCSeconds(); + }; - /** - * - * @param timeObj - * @returns {Number} - */ - FormEngineValidation.getTimeSecs = function(timeObj) { - return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds(); - }; + /** + * + * @param timeObj + * @returns {Number} + */ + FormEngineValidation.getTimeSecs = function(timeObj) { + return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds(); + }; - /** - * Find tab by field and mark it as has-validation-error - * - * @param {Object} $element - */ - FormEngineValidation.markParentTab = function($element) { - var $panes = $element.parents('.tab-pane'); - $panes.each(function() { - var $pane = $(this); - var id = $pane.attr('id'); - $(document) - .find('a[href="#' + id + '"]') - .closest('.t3js-tabmenu-item') - .addClass('has-validation-error'); - }); - }; + /** + * Find tab by field and mark it as has-validation-error + * + * @param {Object} $element + */ + FormEngineValidation.markParentTab = function($element) { + var $panes = $element.parents('.tab-pane'); + $panes.each(function() { + var $pane = $(this); + var id = $pane.attr('id'); + $(document) + .find('a[href="#' + id + '"]') + .closest('.t3js-tabmenu-item') + .addClass('has-validation-error'); + }); + }; - /** - * - * @param value - * @returns {{values: Array, pointer: number}} - */ - FormEngineValidation.splitSingle = function(value) { - var theVal = '' + value; - var result = { - values: [], - pointer: 3 - }; - result.values[1] = theVal.substr(0,2); - result.values[2] = theVal.substr(2,2); - result.values[3] = theVal.substr(4,10); - return result; - }; + /** + * + * @param value + * @returns {{values: Array, pointer: number}} + */ + FormEngineValidation.splitSingle = function(value) { + var theVal = '' + value; + var result = { + values: [], + pointer: 3 + }; + result.values[1] = theVal.substr(0, 2); + result.values[2] = theVal.substr(2, 2); + result.values[3] = theVal.substr(4, 10); + return result; + }; - /** - * - * @param theStr1 - * @param delim - * @param index - * @returns {*} - */ - FormEngineValidation.splitStr = function(theStr1, delim, index) { - var theStr = '' + theStr1; - var lengthOfDelim = delim.length; - var sPos = -lengthOfDelim; - if (index < 1) { - index = 1; - } - for (var a = 1; a < index; a++) { - sPos = theStr.indexOf(delim, sPos + lengthOfDelim); - if (sPos == -1) { - return null; - } - } - var ePos = theStr.indexOf(delim, sPos + lengthOfDelim); - if (ePos == -1) { - ePos = theStr.length; - } - return (theStr.substring(sPos + lengthOfDelim, ePos)); - }; + /** + * + * @param theStr1 + * @param delim + * @param index + * @returns {*} + */ + FormEngineValidation.splitStr = function(theStr1, delim, index) { + var theStr = '' + theStr1; + var lengthOfDelim = delim.length; + var sPos = -lengthOfDelim; + if (index < 1) { + index = 1; + } + for (var a = 1; a < index; a++) { + sPos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (sPos == -1) { + return null; + } + } + var ePos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (ePos == -1) { + ePos = theStr.length; + } + return (theStr.substring(sPos + lengthOfDelim, ePos)); + }; - /** - * - * @param value - * @returns {{values: Array, valPol: Array, pointer: number, numberMode: number, theVal: string}} - */ - FormEngineValidation.split = function(value) { - var result = { - values: [], - valPol: [], - pointer: 0, - numberMode: 0, - theVal: '' - }; - value += ' '; - for (var a=0; a < value.length; a++) { - var theChar = value.substr(a, 1); - if (theChar < '0' || theChar > '9') { - if (result.numberMode) { - result.pointer++; - result.values[result.pointer] = result.theVal; - result.theVal = ''; - result.numberMode = 0; - } - if (theChar == '+' || theChar == '-') { - result.valPol[result.pointer + 1] = theChar; - } - } else { - result.theVal += theChar; - result.numberMode = 1; - } - } - return result; - }; + /** + * + * @param value + * @returns {{values: Array, valPol: Array, pointer: number, numberMode: number, theVal: string}} + */ + FormEngineValidation.split = function(value) { + var result = { + values: [], + valPol: [], + pointer: 0, + numberMode: 0, + theVal: '' + }; + value += ' '; + for (var a = 0; a < value.length; a++) { + var theChar = value.substr(a, 1); + if (theChar < '0' || theChar > '9') { + if (result.numberMode) { + result.pointer++; + result.values[result.pointer] = result.theVal; + result.theVal = ''; + result.numberMode = 0; + } + if (theChar == '+' || theChar == '-') { + result.valPol[result.pointer + 1] = theChar; + } + } else { + result.theVal += theChar; + result.numberMode = 1; + } + } + return result; + }; - return FormEngineValidation; + return FormEngineValidation; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js b/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js index 0ba0541471e1a7b37bfba7cd0fb5195e596a2c91..5df4ef5b271c6631828b07ee5ad34860246f900e 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js @@ -16,145 +16,145 @@ * Uses the icon API of the core to fetch icons via AJAX. */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - try { - // fetch from opening window - if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Icons) { - return window.opener.TYPO3.Icons; - } + try { + // fetch from opening window + if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Icons) { + return window.opener.TYPO3.Icons; + } - // fetch from parent - if (parent && parent.window.TYPO3 && parent.window.TYPO3.Icons) { - return parent.window.TYPO3.Icons; - } + // fetch from parent + if (parent && parent.window.TYPO3 && parent.window.TYPO3.Icons) { + return parent.window.TYPO3.Icons; + } - // fetch object from outer frame - if (top && top.TYPO3.Icons) { - return top.TYPO3.Icons; - } - } catch (e) { - // This only happens if the opener, parent or top is some other url (eg a local file) - // which loaded the current window. Then the browser's cross domain policy jumps in - // and raises an exception. - // For this case we are safe and we can create our global object below. - } + // fetch object from outer frame + if (top && top.TYPO3.Icons) { + return top.TYPO3.Icons; + } + } catch (e) { + // This only happens if the opener, parent or top is some other url (eg a local file) + // which loaded the current window. Then the browser's cross domain policy jumps in + // and raises an exception. + // For this case we are safe and we can create our global object below. + } - /** - * - * @type {{cache: {}, sizes: {small: string, default: string, large: string, overlay: string}, states: {default: string, disabled: string}}} - * @exports TYPO3/CMS/Backend/Icons - */ - var Icons = { - cache: {}, - sizes: { - small: 'small', - default: 'default', - large: 'large', - overlay: 'overlay' - }, - states: { - default: 'default', - disabled: 'disabled' - }, - markupIdentifiers: { - default: 'default', - inline: 'inline' - } - }; + /** + * + * @type {{cache: {}, sizes: {small: string, default: string, large: string, overlay: string}, states: {default: string, disabled: string}}} + * @exports TYPO3/CMS/Backend/Icons + */ + var Icons = { + cache: {}, + sizes: { + small: 'small', + default: 'default', + large: 'large', + overlay: 'overlay' + }, + states: { + default: 'default', + disabled: 'disabled' + }, + markupIdentifiers: { + default: 'default', + inline: 'inline' + } + }; - /** - * Get the icon by its identifier. - * - * @param {String} identifier - * @param {String} size - * @param {String} overlayIdentifier - * @param {String} state - * @param {String} markupIdentifier - * @return {Promise<Array>} - */ - Icons.getIcon = function(identifier, size, overlayIdentifier, state, markupIdentifier) { - return $.when(Icons.fetch(identifier, size, overlayIdentifier, state, markupIdentifier)); - }; + /** + * Get the icon by its identifier. + * + * @param {String} identifier + * @param {String} size + * @param {String} overlayIdentifier + * @param {String} state + * @param {String} markupIdentifier + * @return {Promise<Array>} + */ + Icons.getIcon = function(identifier, size, overlayIdentifier, state, markupIdentifier) { + return $.when(Icons.fetch(identifier, size, overlayIdentifier, state, markupIdentifier)); + }; - /** - * Performs the AJAX request to fetch the icon. - * - * @param {string} identifier - * @param {string} size - * @param {string} overlayIdentifier - * @param {string} state - * @param {string} markupIdentifier - * @return {String|Promise} - * @private - */ - Icons.fetch = function(identifier, size, overlayIdentifier, state, markupIdentifier) { - /** - * Icon keys: - * - * 0: identifier - * 1: size - * 2: overlayIdentifier - * 3: state - * 4: markupIdentifier - */ - size = size || Icons.sizes.default; - state = state || Icons.states.default; - markupIdentifier = markupIdentifier || Icons.markupIdentifiers.default; + /** + * Performs the AJAX request to fetch the icon. + * + * @param {string} identifier + * @param {string} size + * @param {string} overlayIdentifier + * @param {string} state + * @param {string} markupIdentifier + * @return {String|Promise} + * @private + */ + Icons.fetch = function(identifier, size, overlayIdentifier, state, markupIdentifier) { + /** + * Icon keys: + * + * 0: identifier + * 1: size + * 2: overlayIdentifier + * 3: state + * 4: markupIdentifier + */ + size = size || Icons.sizes.default; + state = state || Icons.states.default; + markupIdentifier = markupIdentifier || Icons.markupIdentifiers.default; - var icon = [identifier, size, overlayIdentifier, state, markupIdentifier], - cacheIdentifier = icon.join('_'); + var icon = [identifier, size, overlayIdentifier, state, markupIdentifier], + cacheIdentifier = icon.join('_'); - if (!Icons.isCached(cacheIdentifier)) { - Icons.putInCache(cacheIdentifier, $.ajax({ - url: TYPO3.settings.ajaxUrls['icons'], - dataType: 'html', - data: { - icon: JSON.stringify(icon) - }, - success: function(markup) { - return markup; - } - }).promise()); - } - return Icons.getFromCache(cacheIdentifier).done(); - }; + if (!Icons.isCached(cacheIdentifier)) { + Icons.putInCache(cacheIdentifier, $.ajax({ + url: TYPO3.settings.ajaxUrls['icons'], + dataType: 'html', + data: { + icon: JSON.stringify(icon) + }, + success: function(markup) { + return markup; + } + }).promise()); + } + return Icons.getFromCache(cacheIdentifier).done(); + }; - /** - * Check whether icon was fetched already - * - * @param {String} cacheIdentifier - * @returns {Boolean} - * @private - */ - Icons.isCached = function(cacheIdentifier) { - return typeof Icons.cache[cacheIdentifier] !== 'undefined'; - }; + /** + * Check whether icon was fetched already + * + * @param {String} cacheIdentifier + * @returns {Boolean} + * @private + */ + Icons.isCached = function(cacheIdentifier) { + return typeof Icons.cache[cacheIdentifier] !== 'undefined'; + }; - /** - * Get icon from cache - * - * @param {String} cacheIdentifier - * @returns {String} - * @private - */ - Icons.getFromCache = function(cacheIdentifier) { - return Icons.cache[cacheIdentifier]; - }; + /** + * Get icon from cache + * + * @param {String} cacheIdentifier + * @returns {String} + * @private + */ + Icons.getFromCache = function(cacheIdentifier) { + return Icons.cache[cacheIdentifier]; + }; - /** - * Put icon into cache - * - * @param {String} cacheIdentifier - * @param {Object} markup - * @private - */ - Icons.putInCache = function(cacheIdentifier, markup) { - Icons.cache[cacheIdentifier] = markup; - }; + /** + * Put icon into cache + * + * @param {String} cacheIdentifier + * @param {Object} markup + * @private + */ + Icons.putInCache = function(cacheIdentifier, markup) { + Icons.cache[cacheIdentifier] = markup; + }; - // attach to global frame - TYPO3.Icons = Icons; + // attach to global frame + TYPO3.Icons = Icons; - return Icons; + return Icons; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js index 90036f2bb9ed1d091ab2836fb1b5eb5f4f41082f..2094cb36f99413f41287b3ed485d0c1bd0c0331b 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js @@ -16,251 +16,251 @@ * this JS code does the drag+drop logic for the Layout module (Web => Page) * based on jQuery UI */ -define(['jquery', 'jquery-ui/droppable'], function ($) { - 'use strict'; +define(['jquery', 'jquery-ui/droppable'], function($) { + 'use strict'; - /** - * - * @type {{contentIdentifier: string, dragIdentifier: string, dragHeaderIdentifier: string, dropZoneIdentifier: string, columnIdentifier: string, validDropZoneClass: string, dropPossibleHoverClass: string, addContentIdentifier: string, originalStyles: string}} - * @exports TYPO3/CMS/Backend/LayoutModule/DragDrop - */ - var DragDrop = { - contentIdentifier: '.t3js-page-ce', - dragIdentifier: '.t3-page-ce-dragitem', - dragHeaderIdentifier: '.t3js-page-ce-draghandle', - dropZoneIdentifier: '.t3js-page-ce-dropzone-available', - columnIdentifier: '.t3js-page-column', - validDropZoneClass: 'active', - dropPossibleHoverClass: 't3-page-ce-dropzone-possible', - addContentIdentifier: '.t3js-page-new-ce', - clone: true, - originalStyles: '' - }; + /** + * + * @type {{contentIdentifier: string, dragIdentifier: string, dragHeaderIdentifier: string, dropZoneIdentifier: string, columnIdentifier: string, validDropZoneClass: string, dropPossibleHoverClass: string, addContentIdentifier: string, originalStyles: string}} + * @exports TYPO3/CMS/Backend/LayoutModule/DragDrop + */ + var DragDrop = { + contentIdentifier: '.t3js-page-ce', + dragIdentifier: '.t3-page-ce-dragitem', + dragHeaderIdentifier: '.t3js-page-ce-draghandle', + dropZoneIdentifier: '.t3js-page-ce-dropzone-available', + columnIdentifier: '.t3js-page-column', + validDropZoneClass: 'active', + dropPossibleHoverClass: 't3-page-ce-dropzone-possible', + addContentIdentifier: '.t3js-page-new-ce', + clone: true, + originalStyles: '' + }; - /** - * initializes Drag+Drop for all content elements on the page - */ - DragDrop.initialize = function () { - $(DragDrop.contentIdentifier).draggable({ - handle: DragDrop.dragHeaderIdentifier, - scope: 'tt_content', - cursor: 'move', - distance: 20, - addClasses: 'active-drag', - revert: 'invalid', - zIndex: 100, - start: function (evt, ui) { - DragDrop.onDragStart($(this)); - }, - stop: function (evt, ui) { - DragDrop.onDragStop($(this)); - } - }); + /** + * initializes Drag+Drop for all content elements on the page + */ + DragDrop.initialize = function() { + $(DragDrop.contentIdentifier).draggable({ + handle: DragDrop.dragHeaderIdentifier, + scope: 'tt_content', + cursor: 'move', + distance: 20, + addClasses: 'active-drag', + revert: 'invalid', + zIndex: 100, + start: function(evt, ui) { + DragDrop.onDragStart($(this)); + }, + stop: function(evt, ui) { + DragDrop.onDragStop($(this)); + } + }); - $(DragDrop.dropZoneIdentifier).droppable({ - accept: this.contentIdentifier, - scope: 'tt_content', - tolerance: 'pointer', - over: function (evt, ui) { - DragDrop.onDropHoverOver($(ui.draggable), $(this)); - }, - out: function (evt, ui) { - DragDrop.onDropHoverOut($(ui.draggable), $(this)); - }, - drop: function (evt, ui) { - DragDrop.onDrop($(ui.draggable), $(this), evt); - } - }); - }; + $(DragDrop.dropZoneIdentifier).droppable({ + accept: this.contentIdentifier, + scope: 'tt_content', + tolerance: 'pointer', + over: function(evt, ui) { + DragDrop.onDropHoverOver($(ui.draggable), $(this)); + }, + out: function(evt, ui) { + DragDrop.onDropHoverOut($(ui.draggable), $(this)); + }, + drop: function(evt, ui) { + DragDrop.onDrop($(ui.draggable), $(this), evt); + } + }); + }; - /** - * called when a draggable is selected to be moved - * @param $element a jQuery object for the draggable - * @private - */ - DragDrop.onDragStart = function ($element) { - // Add css class for the drag shadow - DragDrop.originalStyles = $element.get(0).style.cssText; - $element.children(DragDrop.dragIdentifier).addClass('dragitem-shadow'); - $element.append('<div class="ui-draggable-copy-message">' + TYPO3.lang['dragdrop.copy.message'] + '</div>'); - // Hide create new element button - $element.children(DragDrop.dropZoneIdentifier).addClass('drag-start'); - $element.closest(DragDrop.columnIdentifier).removeClass('active'); + /** + * called when a draggable is selected to be moved + * @param $element a jQuery object for the draggable + * @private + */ + DragDrop.onDragStart = function($element) { + // Add css class for the drag shadow + DragDrop.originalStyles = $element.get(0).style.cssText; + $element.children(DragDrop.dragIdentifier).addClass('dragitem-shadow'); + $element.append('<div class="ui-draggable-copy-message">' + TYPO3.lang['dragdrop.copy.message'] + '</div>'); + // Hide create new element button + $element.children(DragDrop.dropZoneIdentifier).addClass('drag-start'); + $element.closest(DragDrop.columnIdentifier).removeClass('active'); - $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).hide(); - $element.find(DragDrop.dropZoneIdentifier).hide(); + $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).hide(); + $element.find(DragDrop.dropZoneIdentifier).hide(); - $(DragDrop.dropZoneIdentifier).each(function () { - var $me = $(this); - if ($me.parent().find('.icon-actions-add').length) { - $me.addClass(DragDrop.validDropZoneClass); - } else { - $me.closest(DragDrop.contentIdentifier).find('> ' + DragDrop.addContentIdentifier + ', > > ' + DragDrop.addContentIdentifier).show(); - } - }); - }; + $(DragDrop.dropZoneIdentifier).each(function() { + var $me = $(this); + if ($me.parent().find('.icon-actions-add').length) { + $me.addClass(DragDrop.validDropZoneClass); + } else { + $me.closest(DragDrop.contentIdentifier).find('> ' + DragDrop.addContentIdentifier + ', > > ' + DragDrop.addContentIdentifier).show(); + } + }); + }; - /** - * called when a draggable is released - * @param $element a jQuery object for the draggable - * @private - */ - DragDrop.onDragStop = function ($element) { - // Remove css class for the drag shadow - $element.children(DragDrop.dragIdentifier).removeClass('dragitem-shadow'); - // Show create new element button - $element.children(DragDrop.dropZoneIdentifier).removeClass('drag-start'); - $element.closest(DragDrop.columnIdentifier).addClass('active'); - $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).show(); - $element.find(DragDrop.dropZoneIdentifier).show(); - $element.find('.ui-draggable-copy-message').remove(); + /** + * called when a draggable is released + * @param $element a jQuery object for the draggable + * @private + */ + DragDrop.onDragStop = function($element) { + // Remove css class for the drag shadow + $element.children(DragDrop.dragIdentifier).removeClass('dragitem-shadow'); + // Show create new element button + $element.children(DragDrop.dropZoneIdentifier).removeClass('drag-start'); + $element.closest(DragDrop.columnIdentifier).addClass('active'); + $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).show(); + $element.find(DragDrop.dropZoneIdentifier).show(); + $element.find('.ui-draggable-copy-message').remove(); - // Reset inline style - $element.get(0).style.cssText = DragDrop.originalStyles; + // Reset inline style + $element.get(0).style.cssText = DragDrop.originalStyles; - $(DragDrop.dropZoneIdentifier + '.' + DragDrop.validDropZoneClass).removeClass(DragDrop.validDropZoneClass); - }; + $(DragDrop.dropZoneIdentifier + '.' + DragDrop.validDropZoneClass).removeClass(DragDrop.validDropZoneClass); + }; - /** - * adds CSS classes when hovering over a dropzone - * @param $draggableElement - * @param $droppableElement - * @private - */ - DragDrop.onDropHoverOver = function ($draggableElement, $droppableElement) { - if ($droppableElement.hasClass(DragDrop.validDropZoneClass)) { - $droppableElement.addClass(DragDrop.dropPossibleHoverClass); - } - }; + /** + * adds CSS classes when hovering over a dropzone + * @param $draggableElement + * @param $droppableElement + * @private + */ + DragDrop.onDropHoverOver = function($draggableElement, $droppableElement) { + if ($droppableElement.hasClass(DragDrop.validDropZoneClass)) { + $droppableElement.addClass(DragDrop.dropPossibleHoverClass); + } + }; - /** - * removes the CSS classes after hovering out of a dropzone again - * @param $draggableElement - * @param $droppableElement - * @private - */ - DragDrop.onDropHoverOut = function ($draggableElement, $droppableElement) { - $droppableElement.removeClass(DragDrop.dropPossibleHoverClass); - }; + /** + * removes the CSS classes after hovering out of a dropzone again + * @param $draggableElement + * @param $droppableElement + * @private + */ + DragDrop.onDropHoverOut = function($draggableElement, $droppableElement) { + $droppableElement.removeClass(DragDrop.dropPossibleHoverClass); + }; - /** - * this method does the whole logic when a draggable is dropped on to a dropzone - * sending out the request and afterwards move the HTML element in the right place. - * - * @param $draggableElement - * @param $droppableElement - * @param {Event} evt the event - * @private - */ - DragDrop.onDrop = function ($draggableElement, $droppableElement, evt) { - var newColumn = DragDrop.getColumnPositionForElement($droppableElement); + /** + * this method does the whole logic when a draggable is dropped on to a dropzone + * sending out the request and afterwards move the HTML element in the right place. + * + * @param $draggableElement + * @param $droppableElement + * @param {Event} evt the event + * @private + */ + DragDrop.onDrop = function($draggableElement, $droppableElement, evt) { + var newColumn = DragDrop.getColumnPositionForElement($droppableElement); - $droppableElement.removeClass(DragDrop.dropPossibleHoverClass); - var $pasteAction = typeof $draggableElement === 'number'; + $droppableElement.removeClass(DragDrop.dropPossibleHoverClass); + var $pasteAction = typeof $draggableElement === 'number'; - // send an AJAX requst via the AjaxDataHandler - var contentElementUid = $pasteAction ? $draggableElement : parseInt($draggableElement.data('uid')); - if (contentElementUid > 0) { - var parameters = {}; - // add the information about a possible column position change - var targetFound = $droppableElement.closest(DragDrop.contentIdentifier).data('uid'); - // the item was moved to the top of the colPos, so the page ID is used here - var targetPid = 0; - if (typeof targetFound === 'undefined') { - // the actual page is needed - targetPid = $('[data-page]').first().data('page'); - } else { - // the negative value of the content element after where it should be moved - targetPid = 0 - parseInt(targetFound); - } - var language = parseInt($droppableElement.closest('[data-language-uid]').data('language-uid')); - var colPos = 0; - if (targetPid !== 0) { - colPos = newColumn; - } - parameters['cmd'] = {tt_content: {}}; - parameters['data'] = {tt_content: {}}; - var copyAction = (evt && evt.originalEvent.ctrlKey || $droppableElement.hasClass('t3js-paste-copy')); - if (copyAction) { - parameters['cmd']['tt_content'][contentElementUid] = { - copy: { - action: 'paste', - target: targetPid, - update: { - colPos: colPos, - sys_language_uid: language - } - } - }; - DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction); - } else { - parameters['data']['tt_content'][contentElementUid] = { - colPos: colPos, - sys_language_uid: language - }; - if ($pasteAction) { - parameters = { - CB: { - paste: 'tt_content|' + targetPid, - update: { - colPos: colPos, - sys_language_uid: language - } - } - }; - } else { - parameters['cmd']['tt_content'][contentElementUid] = {move: targetPid}; - } - // fire the request, and show a message if it has failed - DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction); - } - } - }; + // send an AJAX requst via the AjaxDataHandler + var contentElementUid = $pasteAction ? $draggableElement : parseInt($draggableElement.data('uid')); + if (contentElementUid > 0) { + var parameters = {}; + // add the information about a possible column position change + var targetFound = $droppableElement.closest(DragDrop.contentIdentifier).data('uid'); + // the item was moved to the top of the colPos, so the page ID is used here + var targetPid = 0; + if (typeof targetFound === 'undefined') { + // the actual page is needed + targetPid = $('[data-page]').first().data('page'); + } else { + // the negative value of the content element after where it should be moved + targetPid = 0 - parseInt(targetFound); + } + var language = parseInt($droppableElement.closest('[data-language-uid]').data('language-uid')); + var colPos = 0; + if (targetPid !== 0) { + colPos = newColumn; + } + parameters['cmd'] = {tt_content: {}}; + parameters['data'] = {tt_content: {}}; + var copyAction = (evt && evt.originalEvent.ctrlKey || $droppableElement.hasClass('t3js-paste-copy')); + if (copyAction) { + parameters['cmd']['tt_content'][contentElementUid] = { + copy: { + action: 'paste', + target: targetPid, + update: { + colPos: colPos, + sys_language_uid: language + } + } + }; + DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction); + } else { + parameters['data']['tt_content'][contentElementUid] = { + colPos: colPos, + sys_language_uid: language + }; + if ($pasteAction) { + parameters = { + CB: { + paste: 'tt_content|' + targetPid, + update: { + colPos: colPos, + sys_language_uid: language + } + } + }; + } else { + parameters['cmd']['tt_content'][contentElementUid] = {move: targetPid}; + } + // fire the request, and show a message if it has failed + DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction); + } + } + }; - /** - * this method does the actual AJAX request for both, the move and the copy action. - * - * @param $droppableElement - * @param $draggableElement - * @param parameters - * @param $copyAction - * @param $pasteAction - * @private - */ - DragDrop.ajaxAction = function ($droppableElement, $draggableElement, parameters, $copyAction, $pasteAction) { - require(['TYPO3/CMS/Backend/AjaxDataHandler'], function (DataHandler) { - DataHandler.process(parameters).done(function (result) { - if (!result.hasErrors) { - // insert draggable on the new position - if (!$pasteAction) { - if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) { - $draggableElement.detach().css({top: 0, left: 0}) - .insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier)); - } else { - $draggableElement.detach().css({top: 0, left: 0}) - .insertAfter($droppableElement.closest(DragDrop.contentIdentifier)); - } - } - self.location.reload(true); - } - }); - }); - }; + /** + * this method does the actual AJAX request for both, the move and the copy action. + * + * @param $droppableElement + * @param $draggableElement + * @param parameters + * @param $copyAction + * @param $pasteAction + * @private + */ + DragDrop.ajaxAction = function($droppableElement, $draggableElement, parameters, $copyAction, $pasteAction) { + require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) { + DataHandler.process(parameters).done(function(result) { + if (!result.hasErrors) { + // insert draggable on the new position + if (!$pasteAction) { + if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) { + $draggableElement.detach().css({top: 0, left: 0}) + .insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier)); + } else { + $draggableElement.detach().css({top: 0, left: 0}) + .insertAfter($droppableElement.closest(DragDrop.contentIdentifier)); + } + } + self.location.reload(true); + } + }); + }); + }; - /** - * returns the next "upper" container colPos parameter inside the code - * @param $element - * @return int|null the colPos - */ - DragDrop.getColumnPositionForElement = function ($element) { - var $columnContainer = $element.closest('[data-colpos]'); - if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') { - return $columnContainer.data('colpos'); - } else { - return false; - } - }; + /** + * returns the next "upper" container colPos parameter inside the code + * @param $element + * @return int|null the colPos + */ + DragDrop.getColumnPositionForElement = function($element) { + var $columnContainer = $element.closest('[data-colpos]'); + if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') { + return $columnContainer.data('colpos'); + } else { + return false; + } + }; - $(DragDrop.initialize); - return DragDrop; + $(DragDrop.initialize); + return DragDrop; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js index d433572939ffed3f5928375ea77623841b9d9b17..7cbccd3eff05904d04501e5d65dcbef55606fdfa 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js @@ -17,112 +17,112 @@ * based on jQuery UI */ define(['jquery', - 'TYPO3/CMS/Backend/LayoutModule/DragDrop', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity' - ], function ($, DragDrop, Modal, Severity) { - 'use strict'; + 'TYPO3/CMS/Backend/LayoutModule/DragDrop', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity' +], function($, DragDrop, Modal, Severity) { + 'use strict'; - /** - * - * @type {{}} - * @exports TYPO3/CMS/Backend/LayoutModule/Paste - */ - var Paste = { - openedPopupWindow: [] - }; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Backend/LayoutModule/Paste + */ + var Paste = { + openedPopupWindow: [] + }; - /** - * initializes paste icons for all content elements on the page - */ - Paste.initialize = function () { - if ($('.t3js-page-columns').length) { - Paste.activatePasteIcons(); - } - }; + /** + * initializes paste icons for all content elements on the page + */ + Paste.initialize = function() { + if ($('.t3js-page-columns').length) { + Paste.activatePasteIcons(); + } + }; - /** - * activates the paste into / paste after icons outside of the context menus - */ - Paste.activatePasteIcons = function () { - $('.t3-page-ce-wrapper-new-ce').each(function () { - if (!$(this).find('.icon-actions-add').length) { - return true; - } - $('.t3js-page-lang-column .t3-page-ce > .t3-page-ce').removeClass('t3js-page-ce'); - if (top.pasteAfterLinkTemplate && top.pasteIntoLinkTemplate) { - var parent = $(this).parent(); - if (parent.data('page')) { - $(this).append(top.pasteIntoLinkTemplate); - } else { - $(this).append(top.pasteAfterLinkTemplate); - } - $(this).find('.t3js-paste').on('click', function (evt) { - evt.preventDefault(); - Paste.activatePasteModal($(this)); - }); - } - }); - } + /** + * activates the paste into / paste after icons outside of the context menus + */ + Paste.activatePasteIcons = function() { + $('.t3-page-ce-wrapper-new-ce').each(function() { + if (!$(this).find('.icon-actions-add').length) { + return true; + } + $('.t3js-page-lang-column .t3-page-ce > .t3-page-ce').removeClass('t3js-page-ce'); + if (top.pasteAfterLinkTemplate && top.pasteIntoLinkTemplate) { + var parent = $(this).parent(); + if (parent.data('page')) { + $(this).append(top.pasteIntoLinkTemplate); + } else { + $(this).append(top.pasteAfterLinkTemplate); + } + $(this).find('.t3js-paste').on('click', function(evt) { + evt.preventDefault(); + Paste.activatePasteModal($(this)); + }); + } + }); + } - /** - * generates the paste into / paste after modal - */ - Paste.activatePasteModal = function (element) { - var $element = $(element); - var url = $element.data('url') || null; - var title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + $element.data('title') + '"'; - var severity = (typeof top.TYPO3.Severity[$element.data('severity')] !== 'undefined') ? top.TYPO3.Severity[$element.data('severity')] : top.TYPO3.Severity.info; - if ($element.hasClass('t3js-paste-copy')) { - var content = TYPO3.lang['paste.modal.pastecopy'] || 'Do you want to copy the record to this position?'; - var buttons = [ - { - text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }, - { - text: TYPO3.lang['paste.modal.button.pastecopy'] || 'Copy', - btnClass: 'btn-' + Severity.getCssClass(severity), - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - DragDrop.onDrop($element.data('content'), $element, null); - } - } - ]; - } else { - var content = TYPO3.lang['paste.modal.paste'] || 'Do you want to move the record to this position?'; - var buttons = [ - { - text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }, - { - text: TYPO3.lang['paste.modal.button.paste'] || 'Move', - btnClass: 'btn-' + Severity.getCssClass(severity), - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - DragDrop.onDrop($element.data('content'), $element, null); - } - } - ]; - } - if (url !== null) { - var separator = (url.indexOf('?') > -1) ? '&' : '?'; - var params = $.param({data: $element.data()}); - Modal.loadUrl(title, severity, buttons, url + separator + params); - } else { - Modal.show(title, content, severity, buttons); - } - } + /** + * generates the paste into / paste after modal + */ + Paste.activatePasteModal = function(element) { + var $element = $(element); + var url = $element.data('url') || null; + var title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + $element.data('title') + '"'; + var severity = (typeof top.TYPO3.Severity[$element.data('severity')] !== 'undefined') ? top.TYPO3.Severity[$element.data('severity')] : top.TYPO3.Severity.info; + if ($element.hasClass('t3js-paste-copy')) { + var content = TYPO3.lang['paste.modal.pastecopy'] || 'Do you want to copy the record to this position?'; + var buttons = [ + { + text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }, + { + text: TYPO3.lang['paste.modal.button.pastecopy'] || 'Copy', + btnClass: 'btn-' + Severity.getCssClass(severity), + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + DragDrop.onDrop($element.data('content'), $element, null); + } + } + ]; + } else { + var content = TYPO3.lang['paste.modal.paste'] || 'Do you want to move the record to this position?'; + var buttons = [ + { + text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }, + { + text: TYPO3.lang['paste.modal.button.paste'] || 'Move', + btnClass: 'btn-' + Severity.getCssClass(severity), + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + DragDrop.onDrop($element.data('content'), $element, null); + } + } + ]; + } + if (url !== null) { + var separator = (url.indexOf('?') > -1) ? '&' : '?'; + var params = $.param({data: $element.data()}); + Modal.loadUrl(title, severity, buttons, url + separator + params); + } else { + Modal.show(title, content, severity, buttons); + } + } - $(Paste.initialize); - return Paste; + $(Paste.initialize); + return Paste; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js index 2f1db7452ba5b93dd82491a2b41c55c4ad13e76b..693ef5cbc4fe7ebcd91e2de1488611fee9581c59 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js @@ -24,186 +24,186 @@ var Tree, DragDrop; */ define(['jquery'], function($) { - DragDrop = { - dragID: null, - table: null // can be "pages" or "folders", needed for doing the changes when dropping - }; - - DragDrop.dragElement = function(event, $element) { - event.preventDefault(); - var $container = $element.parent().parent(); - var elementID = $container.prop('id'); - elementID = elementID.substring(elementID.indexOf('_') + 1); - DragDrop.dragID = DragDrop.getIdFromEvent(event); - - if (!DragDrop.dragID) { - return false; - } - - if (!elementID) { - elementID = DragDrop.dragID; - } - - if ($('#dragIcon').length === 0) { - $('body').append('<div id="dragIcon" style="display: none;"> </div>'); - } - - $('#dragIcon').html($container.find('.dragIcon').html() + $container.find('.dragTitle').children(':first').text()); - - document.onmouseup = function(event) { - DragDrop.cancelDragEvent(event); - }; - - document.onmousemove = function(event) { - DragDrop.mouseMoveEvent(event); - }; - }; - - DragDrop.dropElement = function(event) { - var dropID = DragDrop.getIdFromEvent(event); - if ((DragDrop.dragID) && (DragDrop.dragID !== dropID)) { - var dragID = DragDrop.dragID; - var table = DragDrop.table; - var parameters = 'table=' + table + '-drag' + - '&uid=' + dragID + - '&dragDrop=' + table + - '&srcId=' + dragID + - '&dstId=' + dropID; - require(['TYPO3/CMS/Backend/ContextMenu'], function (ContextMenu) { - ContextMenu.record = {table: decodeURIComponent(table), uid: decodeURIComponent(dragID)}; - ContextMenu.fetch(parameters); - }); - } - DragDrop.cancelDragEvent(); - return false; - }; - - DragDrop.cancelDragEvent = function(event) { - DragDrop.dragID = null; - if ($('#dragIcon').length && $('#dragIcon').is(':visible')) { - $('#dragIcon').hide(); - } - - document.onmouseup = null; - document.onmousemove = null; - }; - - DragDrop.mouseMoveEvent = function(event) { - if (!event) { - event = window.event; - } - $('#dragIcon').css({ - left: (event.x + 5) + 'px', - top: (event.y - 5) + 'px' - }).show(); - }; - - DragDrop.getIdFromEvent = function(event) { - var obj = event.currentTarget; - while (obj.id == false && obj.parentNode) { - obj = obj.parentNode; - } - return obj.id.substring(obj.id.indexOf('_') + 1); - }; - - Tree = { - ajaxRoute: 'sc_alt_file_navframe_expandtoggle', - frameSetModule: null, - activateDragDrop: true, - highlightClass: 'active', - pageID: 0, - - // reloads a part of the page tree (useful when "expand" / "collapse") - load: function(params, isExpand, obj, scopeData, scopeHash) { - var $obj = $(obj); - var $parentNode = $(obj).parent().parent(); - - // immediately collapse the subtree and change the plus to a minus when collapsing - // without waiting for the response - if (!isExpand) { - $parentNode.find('ul:first').remove(); - var $pm = $obj.parent().find('.pm:first'); - if ($pm.length) { - $pm.get().onclick = null; - var src = $pm.children(':first').prop('src'); - src = src.replace(/minus/, 'plus'); - $pm.children('first').prop('src', src); - } - } else { - $obj.css({cursor: 'wait'}); - } - $.ajax({ - url: TYPO3.settings.ajaxUrls[this.ajaxRoute], - data: { - PM: params, - scopeData: scopeData, - scopeHash: scopeHash - } - }).done(function(data) { - // the parent node needs to be overwritten, not the object - $parentNode.replaceWith(data); - Tree.reSelectActiveItem(); - }); - }, - - // does the complete page refresh (previously known as "_refresh_nav()") - refresh: function() { - var r = new Date(); - // randNum is useful so pagetree does not get cached in browser cache when refreshing - var loc = window.location.href.replace(/&randNum=\d+|#.*/g, ''); - var addSign = loc.indexOf('?') > 0 ? '&' : '?'; - window.location = loc + addSign + 'randNum=' + r.getTime(); - }, - - // attaches the events to the elements needed for the drag and drop (for the titles and the icons) - registerDragDropHandlers: function() { - if (!Tree.activateDragDrop) { - return; - } - - $('.list-tree-root').on('mousedown', '.dragTitle, .dragIcon', function(evt) { - DragDrop.dragElement(evt, $(this)); - }).on('mouseup', '.dragTitle, .dragIcon', function(evt) { - DragDrop.dropElement(evt, $(this)); - }); - }, - - // selects the activated item again, in case it collapsed and got expanded again - reSelectActiveItem: function() { - if (!top.fsMod) { - return; - } - var $activeItem = $('#' + top.fsMod.navFrameHighlightedID[this.frameSetModule]); - if ($activeItem.length) { - $activeItem.addClass(Tree.highlightClass); - Tree.extractPageIdFromTreeItem($activeItem.prop('id')); - } - }, - - // highlights an active list item in the page tree and registers it to the top-frame - // used when loading the page for the first time - highlightActiveItem: function(frameSetModule, highlightID) { - Tree.frameSetModule = frameSetModule; - Tree.extractPageIdFromTreeItem(highlightID); - - // Remove all items that are already highlighted - var $obj = $('#' + top.fsMod.navFrameHighlightedID[frameSetModule]); - if ($obj.length) { - $obj.removeClass(Tree.highlightClass); - } - - // Set the new item - top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID; - $('#' + highlightID).addClass(Tree.highlightClass); - }, - - //extract pageID from the given id (pagesxxx_y_z where xxx is the ID) - extractPageIdFromTreeItem: function(highlightID) { - if (highlightID) { - Tree.pageID = highlightID.split('_')[0].substring(5); - } - } - }; - - return Tree; + DragDrop = { + dragID: null, + table: null // can be "pages" or "folders", needed for doing the changes when dropping + }; + + DragDrop.dragElement = function(event, $element) { + event.preventDefault(); + var $container = $element.parent().parent(); + var elementID = $container.prop('id'); + elementID = elementID.substring(elementID.indexOf('_') + 1); + DragDrop.dragID = DragDrop.getIdFromEvent(event); + + if (!DragDrop.dragID) { + return false; + } + + if (!elementID) { + elementID = DragDrop.dragID; + } + + if ($('#dragIcon').length === 0) { + $('body').append('<div id="dragIcon" style="display: none;"> </div>'); + } + + $('#dragIcon').html($container.find('.dragIcon').html() + $container.find('.dragTitle').children(':first').text()); + + document.onmouseup = function(event) { + DragDrop.cancelDragEvent(event); + }; + + document.onmousemove = function(event) { + DragDrop.mouseMoveEvent(event); + }; + }; + + DragDrop.dropElement = function(event) { + var dropID = DragDrop.getIdFromEvent(event); + if ((DragDrop.dragID) && (DragDrop.dragID !== dropID)) { + var dragID = DragDrop.dragID; + var table = DragDrop.table; + var parameters = 'table=' + table + '-drag' + + '&uid=' + dragID + + '&dragDrop=' + table + + '&srcId=' + dragID + + '&dstId=' + dropID; + require(['TYPO3/CMS/Backend/ContextMenu'], function(ContextMenu) { + ContextMenu.record = {table: decodeURIComponent(table), uid: decodeURIComponent(dragID)}; + ContextMenu.fetch(parameters); + }); + } + DragDrop.cancelDragEvent(); + return false; + }; + + DragDrop.cancelDragEvent = function(event) { + DragDrop.dragID = null; + if ($('#dragIcon').length && $('#dragIcon').is(':visible')) { + $('#dragIcon').hide(); + } + + document.onmouseup = null; + document.onmousemove = null; + }; + + DragDrop.mouseMoveEvent = function(event) { + if (!event) { + event = window.event; + } + $('#dragIcon').css({ + left: (event.x + 5) + 'px', + top: (event.y - 5) + 'px' + }).show(); + }; + + DragDrop.getIdFromEvent = function(event) { + var obj = event.currentTarget; + while (obj.id == false && obj.parentNode) { + obj = obj.parentNode; + } + return obj.id.substring(obj.id.indexOf('_') + 1); + }; + + Tree = { + ajaxRoute: 'sc_alt_file_navframe_expandtoggle', + frameSetModule: null, + activateDragDrop: true, + highlightClass: 'active', + pageID: 0, + + // reloads a part of the page tree (useful when "expand" / "collapse") + load: function(params, isExpand, obj, scopeData, scopeHash) { + var $obj = $(obj); + var $parentNode = $(obj).parent().parent(); + + // immediately collapse the subtree and change the plus to a minus when collapsing + // without waiting for the response + if (!isExpand) { + $parentNode.find('ul:first').remove(); + var $pm = $obj.parent().find('.pm:first'); + if ($pm.length) { + $pm.get().onclick = null; + var src = $pm.children(':first').prop('src'); + src = src.replace(/minus/, 'plus'); + $pm.children('first').prop('src', src); + } + } else { + $obj.css({cursor: 'wait'}); + } + $.ajax({ + url: TYPO3.settings.ajaxUrls[this.ajaxRoute], + data: { + PM: params, + scopeData: scopeData, + scopeHash: scopeHash + } + }).done(function(data) { + // the parent node needs to be overwritten, not the object + $parentNode.replaceWith(data); + Tree.reSelectActiveItem(); + }); + }, + + // does the complete page refresh (previously known as "_refresh_nav()") + refresh: function() { + var r = new Date(); + // randNum is useful so pagetree does not get cached in browser cache when refreshing + var loc = window.location.href.replace(/&randNum=\d+|#.*/g, ''); + var addSign = loc.indexOf('?') > 0 ? '&' : '?'; + window.location = loc + addSign + 'randNum=' + r.getTime(); + }, + + // attaches the events to the elements needed for the drag and drop (for the titles and the icons) + registerDragDropHandlers: function() { + if (!Tree.activateDragDrop) { + return; + } + + $('.list-tree-root').on('mousedown', '.dragTitle, .dragIcon', function(evt) { + DragDrop.dragElement(evt, $(this)); + }).on('mouseup', '.dragTitle, .dragIcon', function(evt) { + DragDrop.dropElement(evt, $(this)); + }); + }, + + // selects the activated item again, in case it collapsed and got expanded again + reSelectActiveItem: function() { + if (!top.fsMod) { + return; + } + var $activeItem = $('#' + top.fsMod.navFrameHighlightedID[this.frameSetModule]); + if ($activeItem.length) { + $activeItem.addClass(Tree.highlightClass); + Tree.extractPageIdFromTreeItem($activeItem.prop('id')); + } + }, + + // highlights an active list item in the page tree and registers it to the top-frame + // used when loading the page for the first time + highlightActiveItem: function(frameSetModule, highlightID) { + Tree.frameSetModule = frameSetModule; + Tree.extractPageIdFromTreeItem(highlightID); + + // Remove all items that are already highlighted + var $obj = $('#' + top.fsMod.navFrameHighlightedID[frameSetModule]); + if ($obj.length) { + $obj.removeClass(Tree.highlightClass); + } + + // Set the new item + top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID; + $('#' + highlightID).addClass(Tree.highlightClass); + }, + + //extract pageID from the given id (pagesxxx_y_z where xxx is the ID) + extractPageIdFromTreeItem: function(highlightID) { + if (highlightID) { + Tree.pageID = highlightID.split('_')[0].substring(5); + } + } + }; + + return Tree; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js b/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js index 43ae4bae382f29d3ae2f42578f17725e9e8f9194..343cc2200cc9cee6f7780ccb642f2d68824a47b8 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js @@ -17,139 +17,139 @@ * @exports TYPO3/CMS/Backend/LiveSearch */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Viewport', - 'TYPO3/CMS/Backend/Icons', - 'jquery/autocomplete', - 'TYPO3/CMS/Backend/jquery.clearable' -], function ($, Viewport, Icons) { - 'use strict'; + 'jquery', + 'TYPO3/CMS/Backend/Viewport', + 'TYPO3/CMS/Backend/Icons', + 'jquery/autocomplete', + 'TYPO3/CMS/Backend/jquery.clearable' +], function($, Viewport, Icons) { + 'use strict'; - var containerSelector = '#typo3-cms-backend-backend-toolbaritems-livesearchtoolbaritem'; - var toolbarItem = '.t3js-toolbar-item-search'; - var dropdownToggle = '.t3js-toolbar-search-dropdowntoggle'; - var searchFieldSelector = '.t3js-topbar-navigation-search-field'; - var formSelector = '.t3js-topbar-navigation-search'; - var url = TYPO3.settings.ajaxUrls['livesearch']; + var containerSelector = '#typo3-cms-backend-backend-toolbaritems-livesearchtoolbaritem'; + var toolbarItem = '.t3js-toolbar-item-search'; + var dropdownToggle = '.t3js-toolbar-search-dropdowntoggle'; + var searchFieldSelector = '.t3js-topbar-navigation-search-field'; + var formSelector = '.t3js-topbar-navigation-search'; + var url = TYPO3.settings.ajaxUrls['livesearch']; - Viewport.Topbar.Toolbar.registerEvent(function() { - $(searchFieldSelector).autocomplete({ - // ajax options - serviceUrl: url, - paramName: 'q', - dataType: 'json', - minChars: 2, - width: '100%', - groupBy: 'typeLabel', - containerClass: toolbarItem.substr(1, toolbarItem.length), - appendTo: containerSelector + ' .dropdown-menu', - forceFixPosition: false, - preserveInput: true, - showNoSuggestionNotice: true, - triggerSelectOnValidInput: false, - preventBadQueries: false, - noSuggestionNotice: '<h3 class="dropdown-headline">' + TYPO3.lang['liveSearch_listEmptyText'] + '</h3>' - + '<p>' + TYPO3.lang['liveSearch_helpTitle'] + '</p>' - + '<hr>' - + '<p>' + TYPO3.lang['liveSearch_helpDescription'] + '<br>' + TYPO3.lang['liveSearch_helpDescriptionPages'] + '</p>', - // put the AJAX results in the right format - transformResult: function(response) { - return { - suggestions: $.map(response, function(dataItem) { - return { value: dataItem.title, data: dataItem }; - }) - }; - }, - formatGroup: function(suggestion, category, i) { - var html = ''; - // add a divider if it's not the first group - if (i > 0) { - html = '<hr>'; - } - return html + '<h3 class="dropdown-headline">' + category + '</h3>'; - }, - // Rendering of each item - formatResult: function(suggestion, value, i) { - return '' - + '<div class="dropdown-table">' - + '<div class="dropdown-table-row">' - + '<div class="dropdown-table-column dropdown-table-icon">' + suggestion.data.iconHTML + '</div>' - + '<div class="dropdown-table-column dropdown-table-title">' - + '<a class="dropdown-table-title-ellipsis dropdown-list-link" href="#" data-pageid="' + suggestion.data.pageId + '" data-target="' + suggestion.data.editLink + '">' - + suggestion.data.title - + '</a>' - + '</div>' - + '</div>' - + '</div>' - + ''; - }, - onSearchStart: function () { - if(!$(toolbarItem).hasClass('loading')) { - $(toolbarItem).addClass('loading'); - Icons.getIcon('spinner-circle-light', Icons.sizes.small, '', 'default', 'inline').done(function (markup) { - $(toolbarItem).find('.icon-apps-toolbar-menu-search').replaceWith(markup) - }); - } - }, - onSearchComplete: function(query, suggestions) { - if (!$(toolbarItem).hasClass('open') && $(searchFieldSelector).val().length > 1) { - $(dropdownToggle).dropdown('toggle'); - $(searchFieldSelector).focus(); - } - if ($(toolbarItem).hasClass('loading')) { - $(toolbarItem).removeClass('loading'); - Icons.getIcon('apps-toolbar-menu-search', Icons.sizes.small, '', 'default', 'inline').done(function (markup) { - $(toolbarItem).find('.icon-spinner-circle-light').replaceWith(markup) - }); - } - }, - beforeRender: function(container) { - container.append('<hr><div>' + - '<a href="#" class="btn btn-primary pull-right t3js-live-search-show-all">' + - TYPO3.lang['liveSearch_showAllResults'] + - '</a>' + - '</div>'); - if (!$(toolbarItem).hasClass('open')) { - $(dropdownToggle).dropdown('toggle'); - $(searchFieldSelector).focus(); - } - }, - onHide: function() { - if ($(toolbarItem).hasClass('open')) { - $(dropdownToggle).dropdown('toggle'); - } - } - }); + Viewport.Topbar.Toolbar.registerEvent(function() { + $(searchFieldSelector).autocomplete({ + // ajax options + serviceUrl: url, + paramName: 'q', + dataType: 'json', + minChars: 2, + width: '100%', + groupBy: 'typeLabel', + containerClass: toolbarItem.substr(1, toolbarItem.length), + appendTo: containerSelector + ' .dropdown-menu', + forceFixPosition: false, + preserveInput: true, + showNoSuggestionNotice: true, + triggerSelectOnValidInput: false, + preventBadQueries: false, + noSuggestionNotice: '<h3 class="dropdown-headline">' + TYPO3.lang['liveSearch_listEmptyText'] + '</h3>' + + '<p>' + TYPO3.lang['liveSearch_helpTitle'] + '</p>' + + '<hr>' + + '<p>' + TYPO3.lang['liveSearch_helpDescription'] + '<br>' + TYPO3.lang['liveSearch_helpDescriptionPages'] + '</p>', + // put the AJAX results in the right format + transformResult: function(response) { + return { + suggestions: $.map(response, function(dataItem) { + return {value: dataItem.title, data: dataItem}; + }) + }; + }, + formatGroup: function(suggestion, category, i) { + var html = ''; + // add a divider if it's not the first group + if (i > 0) { + html = '<hr>'; + } + return html + '<h3 class="dropdown-headline">' + category + '</h3>'; + }, + // Rendering of each item + formatResult: function(suggestion, value, i) { + return '' + + '<div class="dropdown-table">' + + '<div class="dropdown-table-row">' + + '<div class="dropdown-table-column dropdown-table-icon">' + suggestion.data.iconHTML + '</div>' + + '<div class="dropdown-table-column dropdown-table-title">' + + '<a class="dropdown-table-title-ellipsis dropdown-list-link" href="#" data-pageid="' + suggestion.data.pageId + '" data-target="' + suggestion.data.editLink + '">' + + suggestion.data.title + + '</a>' + + '</div>' + + '</div>' + + '</div>' + + ''; + }, + onSearchStart: function() { + if (!$(toolbarItem).hasClass('loading')) { + $(toolbarItem).addClass('loading'); + Icons.getIcon('spinner-circle-light', Icons.sizes.small, '', 'default', 'inline').done(function(markup) { + $(toolbarItem).find('.icon-apps-toolbar-menu-search').replaceWith(markup) + }); + } + }, + onSearchComplete: function(query, suggestions) { + if (!$(toolbarItem).hasClass('open') && $(searchFieldSelector).val().length > 1) { + $(dropdownToggle).dropdown('toggle'); + $(searchFieldSelector).focus(); + } + if ($(toolbarItem).hasClass('loading')) { + $(toolbarItem).removeClass('loading'); + Icons.getIcon('apps-toolbar-menu-search', Icons.sizes.small, '', 'default', 'inline').done(function(markup) { + $(toolbarItem).find('.icon-spinner-circle-light').replaceWith(markup) + }); + } + }, + beforeRender: function(container) { + container.append('<hr><div>' + + '<a href="#" class="btn btn-primary pull-right t3js-live-search-show-all">' + + TYPO3.lang['liveSearch_showAllResults'] + + '</a>' + + '</div>'); + if (!$(toolbarItem).hasClass('open')) { + $(dropdownToggle).dropdown('toggle'); + $(searchFieldSelector).focus(); + } + }, + onHide: function() { + if ($(toolbarItem).hasClass('open')) { + $(dropdownToggle).dropdown('toggle'); + } + } + }); - // set up the events - $(containerSelector).on('click', '.t3js-live-search-show-all', function(evt) { - evt.preventDefault(); - TYPO3.ModuleMenu.App.showModule('web_list', 'id=0&search_levels=-1&search_field=' + encodeURIComponent($(searchFieldSelector).val())); - $(searchFieldSelector).val('').trigger('change'); - }); - if ($(searchFieldSelector).length) { - $('.' + $(searchFieldSelector).autocomplete().options.containerClass).on('click.autocomplete', '.dropdown-list-link', function (evt) { - evt.preventDefault(); - jump($(this).data('target'), 'web_list', 'web', $(this).data('pageid')); - $(searchFieldSelector).val('').trigger('change'); - }); - } + // set up the events + $(containerSelector).on('click', '.t3js-live-search-show-all', function(evt) { + evt.preventDefault(); + TYPO3.ModuleMenu.App.showModule('web_list', 'id=0&search_levels=-1&search_field=' + encodeURIComponent($(searchFieldSelector).val())); + $(searchFieldSelector).val('').trigger('change'); + }); + if ($(searchFieldSelector).length) { + $('.' + $(searchFieldSelector).autocomplete().options.containerClass).on('click.autocomplete', '.dropdown-list-link', function(evt) { + evt.preventDefault(); + jump($(this).data('target'), 'web_list', 'web', $(this).data('pageid')); + $(searchFieldSelector).val('').trigger('change'); + }); + } - // Unset height, width and z-index - $(toolbarItem).removeAttr('style'); + // Unset height, width and z-index + $(toolbarItem).removeAttr('style'); - $(searchFieldSelector).clearable({ - onClear: function() { - if ($(toolbarItem).hasClass('open')) { - $(dropdownToggle).dropdown('toggle'); - } - } - }); + $(searchFieldSelector).clearable({ + onClear: function() { + if ($(toolbarItem).hasClass('open')) { + $(dropdownToggle).dropdown('toggle'); + } + } + }); - // Prevent submitting the search form - $(formSelector).submit(function(evt) { - evt.preventDefault(); - }); - }); + // Prevent submitting the search form + $(formSelector).submit(function(evt) { + evt.preventDefault(); + }); + }); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js b/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js index e561b0ed372d4420cad467f9be9dfbdd25452629..7314d770bd17b280c359e00a5d3e563cf11b9d94 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js @@ -16,280 +16,289 @@ * UI for localization workflow. */ define([ - 'jquery', - 'TYPO3/CMS/Backend/AjaxDataHandler', - 'TYPO3/CMS/Backend/Wizard', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Severity', - 'bootstrap' + 'jquery', + 'TYPO3/CMS/Backend/AjaxDataHandler', + 'TYPO3/CMS/Backend/Wizard', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Severity', + 'bootstrap' ], function($, DataHandler, Wizard, Icons, Severity) { - 'use strict'; + 'use strict'; - /** - * @type {{identifier: {triggerButton: string}, actions: {translate: $, copy: $}, settings: {}, records: []}} - * @exports TYPO3/CMS/Backend/Localization - */ - var Localization = { - identifier: { - triggerButton: '.t3js-localize' - }, - actions: { - translate: $('<label />', { - class: 'btn btn-block btn-default t3js-option', - 'data-helptext': '.t3js-helptext-translate' - }).html('<br>Translate').prepend( - $('<input />', { - type: 'radio', - name: 'mode', - id: 'mode_translate', - value: 'localize', - style: 'display: none' - }) - ), - copy: $('<label />', { - class: 'btn btn-block btn-default t3js-option', - 'data-helptext': '.t3js-helptext-copy' - }).html('<br>Copy').prepend( - $('<input />', { - type: 'radio', - name: 'mode', - id: 'mode_copy', - value: 'copyFromLanguage', - style: 'display: none' - }) - ) - }, - settings: {}, - records: [] - }; + /** + * @type {{identifier: {triggerButton: string}, actions: {translate: $, copy: $}, settings: {}, records: []}} + * @exports TYPO3/CMS/Backend/Localization + */ + var Localization = { + identifier: { + triggerButton: '.t3js-localize' + }, + actions: { + translate: $('<label />', { + class: 'btn btn-block btn-default t3js-option', + 'data-helptext': '.t3js-helptext-translate' + }).html('<br>Translate').prepend( + $('<input />', { + type: 'radio', + name: 'mode', + id: 'mode_translate', + value: 'localize', + style: 'display: none' + }) + ), + copy: $('<label />', { + class: 'btn btn-block btn-default t3js-option', + 'data-helptext': '.t3js-helptext-copy' + }).html('<br>Copy').prepend( + $('<input />', { + type: 'radio', + name: 'mode', + id: 'mode_copy', + value: 'copyFromLanguage', + style: 'display: none' + }) + ) + }, + settings: {}, + records: [] + }; - Localization.initialize = function() { - Icons.getIcon('actions-localize', Icons.sizes.large).done(function(localizeIconMarkup) { - Icons.getIcon('actions-edit-copy', Icons.sizes.large).done(function(copyIconMarkup) { - Localization.actions.translate.prepend(localizeIconMarkup); - Localization.actions.copy.prepend(copyIconMarkup); - $(Localization.identifier.triggerButton).prop('disabled', false); - }); - }); + Localization.initialize = function() { + Icons.getIcon('actions-localize', Icons.sizes.large).done(function(localizeIconMarkup) { + Icons.getIcon('actions-edit-copy', Icons.sizes.large).done(function(copyIconMarkup) { + Localization.actions.translate.prepend(localizeIconMarkup); + Localization.actions.copy.prepend(copyIconMarkup); + $(Localization.identifier.triggerButton).prop('disabled', false); + }); + }); - $(document).on('click', Localization.identifier.triggerButton, function() { - var $triggerButton = $(this), - actions = [], - slideStep1 = ''; + $(document).on('click', Localization.identifier.triggerButton, function() { + var $triggerButton = $(this), + actions = [], + slideStep1 = ''; - if ($triggerButton.data('allowTranslate')) { - actions.push( - '<div class="row">' - + '<div class="btn-group col-sm-3">' + Localization.actions.translate[0].outerHTML + '</div>' - + '<div class="col-sm-9">' - + '<p class="t3js-helptext t3js-helptext-translate text-muted">' + TYPO3.lang['localize.educate.translate'] + '</p>' - + '</div>' - + '</div>' - ); - } + if ($triggerButton.data('allowTranslate')) { + actions.push( + '<div class="row">' + + '<div class="btn-group col-sm-3">' + Localization.actions.translate[0].outerHTML + '</div>' + + '<div class="col-sm-9">' + + '<p class="t3js-helptext t3js-helptext-translate text-muted">' + TYPO3.lang['localize.educate.translate'] + '</p>' + + '</div>' + + '</div>' + ); + } - if ($triggerButton.data('allowCopy')) { - actions.push( - '<div class="row">' - + '<div class="col-sm-3 btn-group">' + Localization.actions.copy[0].outerHTML + '</div>' - + '<div class="col-sm-9">' - + '<p class="t3js-helptext t3js-helptext-copy text-muted">' + TYPO3.lang['localize.educate.copy'] + '</p>' - + '</div>' - + '</div>' - ); - } + if ($triggerButton.data('allowCopy')) { + actions.push( + '<div class="row">' + + '<div class="col-sm-3 btn-group">' + Localization.actions.copy[0].outerHTML + '</div>' + + '<div class="col-sm-9">' + + '<p class="t3js-helptext t3js-helptext-copy text-muted">' + TYPO3.lang['localize.educate.copy'] + '</p>' + + '</div>' + + '</div>' + ); + } - slideStep1 += '<div data-toggle="buttons">' + actions.join('<hr>') + '</div>'; + slideStep1 += '<div data-toggle="buttons">' + actions.join('<hr>') + '</div>'; - Wizard.addSlide('localize-choose-action', TYPO3.lang['localize.wizard.header'].replace('{0}', $triggerButton.data('colposName')).replace('{1}', $triggerButton.data('languageName')), slideStep1, Severity.info); - Wizard.addSlide('localize-choose-language', TYPO3.lang['localize.view.chooseLanguage'], '', Severity.info, function($slide) { - Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) { - $slide.html( - $('<div />', {class: 'text-center'}).append(markup) - ); - Localization.loadAvailableLanguages( - $triggerButton.data('pageId'), - $triggerButton.data('colposId'), - $triggerButton.data('languageId') - ).done(function(result) { - if (result.length === 1) { - // We only have one result, auto select the record and continue - Localization.settings.language = result[0].uid + ''; // we need a string - Wizard.unlockNextStep().trigger('click'); - return; - } + Wizard.addSlide('localize-choose-action', TYPO3.lang['localize.wizard.header'].replace('{0}', $triggerButton.data('colposName')).replace('{1}', $triggerButton.data('languageName')), slideStep1, Severity.info); + Wizard.addSlide('localize-choose-language', TYPO3.lang['localize.view.chooseLanguage'], '', Severity.info, function($slide) { + Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) { + $slide.html( + $('<div />', {class: 'text-center'}).append(markup) + ); + Localization.loadAvailableLanguages( + $triggerButton.data('pageId'), + $triggerButton.data('colposId'), + $triggerButton.data('languageId') + ).done(function(result) { + if (result.length === 1) { + // We only have one result, auto select the record and continue + Localization.settings.language = result[0].uid + ''; // we need a string + Wizard.unlockNextStep().trigger('click'); + return; + } - var $languageButtons = $('<div />', {class: 'row', 'data-toggle': 'buttons'}); + var $languageButtons = $('<div />', {class: 'row', 'data-toggle': 'buttons'}); - $.each(result, function(_, languageObject) { - $languageButtons.append( - $('<div />', {class: 'col-sm-4'}).append( - $('<label />', {class: 'btn btn-default btn-block t3js-option option'}).text(' ' + languageObject.title).prepend( - languageObject.flagIcon - ).prepend( - $('<input />', { - type: 'radio', - name: 'language', - id: 'language' + languageObject.uid, - value: languageObject.uid, - style: 'display: none;' - }) - ) - ) - ); - }); - $slide.html($languageButtons); - }); - }); - }); - Wizard.addSlide('localize-summary', TYPO3.lang['localize.view.summary'], '', Severity.info, function($slide) { - Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) { - $slide.html( - $('<div />', {class: 'text-center'}).append(markup) - ); + $.each(result, function(_, languageObject) { + $languageButtons.append( + $('<div />', {class: 'col-sm-4'}).append( + $('<label />', {class: 'btn btn-default btn-block t3js-option option'}).text(' ' + languageObject.title).prepend( + languageObject.flagIcon + ).prepend( + $('<input />', { + type: 'radio', + name: 'language', + id: 'language' + languageObject.uid, + value: languageObject.uid, + style: 'display: none;' + }) + ) + ) + ); + }); + $slide.html($languageButtons); + }); + }); + }); + Wizard.addSlide('localize-summary', TYPO3.lang['localize.view.summary'], '', Severity.info, function($slide) { + Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) { + $slide.html( + $('<div />', {class: 'text-center'}).append(markup) + ); - Localization.getSummary( - $triggerButton.data('pageId'), - $triggerButton.data('colposId'), - $triggerButton.data('languageId') - ).done(function(result) { - var $summary = $('<div />', {class: 'row'}); - Localization.records = []; + Localization.getSummary( + $triggerButton.data('pageId'), + $triggerButton.data('colposId'), + $triggerButton.data('languageId') + ).done(function(result) { + var $summary = $('<div />', {class: 'row'}); + Localization.records = []; - $.each(result, function(_, record) { - var label = ' (' + record.uid + ') ' + record.title; - Localization.records.push(record.uid); + $.each(result, function(_, record) { + var label = ' (' + record.uid + ') ' + record.title; + Localization.records.push(record.uid); - $summary.append( - $('<div />', {'class': 'col-sm-6'}).append( - $('<div />', {'class': 'input-group'}).append( - $('<span />', {'class': 'input-group-addon'}).append( - $('<input />', {type: 'checkbox', id: 'record-uid-' + record.uid, checked: 'checked', 'data-uid': record.uid, 'aria-label': label}) - ), - $('<label />', {'class': 'form-control', for: 'record-uid-' + record.uid}).text(label).prepend(record.icon) - ) - ) - ); - }); - $slide.html($summary); - Wizard.unlockNextStep(); + $summary.append( + $('<div />', {'class': 'col-sm-6'}).append( + $('<div />', {'class': 'input-group'}).append( + $('<span />', {'class': 'input-group-addon'}).append( + $('<input />', { + type: 'checkbox', + id: 'record-uid-' + record.uid, + checked: 'checked', + 'data-uid': record.uid, + 'aria-label': label + }) + ), + $('<label />', { + 'class': 'form-control', + for: 'record-uid-' + record.uid + }).text(label).prepend(record.icon) + ) + ) + ); + }); + $slide.html($summary); + Wizard.unlockNextStep(); - Wizard.getComponent().on('change', 'input[type="checkbox"]', function() { - var $me = $(this), - uid = $me.data('uid'); + Wizard.getComponent().on('change', 'input[type="checkbox"]', function() { + var $me = $(this), + uid = $me.data('uid'); - if ($me.is(':checked')) { - Localization.records.push(uid); - } else { - var index = Localization.records.indexOf(uid); - if (index > -1) { - Localization.records.splice(index, 1); - } - } + if ($me.is(':checked')) { + Localization.records.push(uid); + } else { + var index = Localization.records.indexOf(uid); + if (index > -1) { + Localization.records.splice(index, 1); + } + } - if (Localization.records.length > 0) { - Wizard.unlockNextStep(); - } else { - Wizard.lockNextStep(); - } - }); - }); - }); - }); - Wizard.addFinalProcessingSlide(function() { - Localization.localizeRecords( - $triggerButton.data('pageId'), - $triggerButton.data('colposId'), - $triggerButton.data('languageId'), - Localization.records - ).done(function() { - Wizard.dismiss(); - document.location.reload(); - }); - }).done(function() { - Wizard.show(); + if (Localization.records.length > 0) { + Wizard.unlockNextStep(); + } else { + Wizard.lockNextStep(); + } + }); + }); + }); + }); + Wizard.addFinalProcessingSlide(function() { + Localization.localizeRecords( + $triggerButton.data('pageId'), + $triggerButton.data('colposId'), + $triggerButton.data('languageId'), + Localization.records + ).done(function() { + Wizard.dismiss(); + document.location.reload(); + }); + }).done(function() { + Wizard.show(); - Wizard.getComponent().on('click', '.t3js-option', function(e) { - var $me = $(this), - $radio = $me.find('input[type="radio"]'); + Wizard.getComponent().on('click', '.t3js-option', function(e) { + var $me = $(this), + $radio = $me.find('input[type="radio"]'); - if ($me.data('helptext')) { - var $container = $(e.delegateTarget); - $container.find('.t3js-helptext').addClass('text-muted'); - $container.find($me.data('helptext')).removeClass('text-muted'); - } - if ($radio.length > 0) { - Localization.settings[$radio.attr('name')] = $radio.val(); - } - Wizard.unlockNextStep(); - }); - }); - }); + if ($me.data('helptext')) { + var $container = $(e.delegateTarget); + $container.find('.t3js-helptext').addClass('text-muted'); + $container.find($me.data('helptext')).removeClass('text-muted'); + } + if ($radio.length > 0) { + Localization.settings[$radio.attr('name')] = $radio.val(); + } + Wizard.unlockNextStep(); + }); + }); + }); - /** - * Load available languages from page and colPos - * - * @param {Integer} pageId - * @param {Integer} colPos - * @param {Integer} languageId - * @return {Promise} - */ - Localization.loadAvailableLanguages = function(pageId, colPos, languageId) { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['languages_page_colpos'], - data: { - pageId: pageId, - colPos: colPos, - languageId: languageId - } - }); - }; + /** + * Load available languages from page and colPos + * + * @param {Integer} pageId + * @param {Integer} colPos + * @param {Integer} languageId + * @return {Promise} + */ + Localization.loadAvailableLanguages = function(pageId, colPos, languageId) { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['languages_page_colpos'], + data: { + pageId: pageId, + colPos: colPos, + languageId: languageId + } + }); + }; - /** - * Get summary for record processing - * - * @param {Integer} pageId - * @param {Integer} colPos - * @param {Integer} languageId - * @return {Promise} - */ - Localization.getSummary = function(pageId, colPos, languageId) { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['records_localize_summary'], - data: { - pageId: pageId, - colPos: colPos, - destLanguageId: languageId, - languageId: Localization.settings.language - } - }); - }; + /** + * Get summary for record processing + * + * @param {Integer} pageId + * @param {Integer} colPos + * @param {Integer} languageId + * @return {Promise} + */ + Localization.getSummary = function(pageId, colPos, languageId) { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['records_localize_summary'], + data: { + pageId: pageId, + colPos: colPos, + destLanguageId: languageId, + languageId: Localization.settings.language + } + }); + }; - /** - * Localize records - * - * @param {Integer} pageId - * @param {Integer} colPos - * @param {Integer} languageId - * @param {Array} uidList - * @return {Promise} - */ - Localization.localizeRecords = function(pageId, colPos, languageId, uidList) { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['records_localize'], - data: { - pageId: pageId, - colPos: colPos, - srcLanguageId: Localization.settings.language, - destLanguageId: languageId, - action: Localization.settings.mode, - uidList: uidList - } - }); - }; - }; + /** + * Localize records + * + * @param {Integer} pageId + * @param {Integer} colPos + * @param {Integer} languageId + * @param {Array} uidList + * @return {Promise} + */ + Localization.localizeRecords = function(pageId, colPos, languageId, uidList) { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['records_localize'], + data: { + pageId: pageId, + colPos: colPos, + srcLanguageId: Localization.settings.language, + destLanguageId: languageId, + action: Localization.settings.mode, + uidList: uidList + } + }); + }; + }; - $(Localization.initialize); + $(Localization.initialize); - return Localization; + return Localization; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js index da64e7f6b7cf87a5f266c20a17d29fd9943b743b..4f0817b7b1f0b7e734b3de6c1fb5b6f14be53a56 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js @@ -17,465 +17,488 @@ * displays a proper dialog to the user. */ define(['jquery', 'TYPO3/CMS/Backend/Notification', 'bootstrap'], function($, Typo3Notification) { - 'use strict'; - - /** - * - * @type {{identifier: {loginrefresh: string, lockedModal: string, loginFormModal: string}, options: {modalConfig: {backdrop: string}}, webNotification: null, intervalTime: integer, intervalId: null, backendIsLocked: boolean, isTimingOut: boolean, $timeoutModal: string, $backendLockedModal: string, $loginForm: string, loginFramesetUrl: string, logoutUrl: string}} - * @exports TYPO3/CMS/Backend/LoginRefresh - */ - var LoginRefresh = { - identifier: { - loginrefresh: 't3js-modal-loginrefresh', - lockedModal: 't3js-modal-backendlocked', - loginFormModal: 't3js-modal-backendloginform' - }, - options: { - modalConfig: { - backdrop: 'static' - } - }, - webNotification: null, - intervalTime: 60, - intervalId: null, - backendIsLocked: false, - isTimingOut: false, - $timeoutModal: '', - $backendLockedModal: '', - $loginForm: '', - loginFramesetUrl: '', - logoutUrl: '' - }; - - /** - * Starts the session check task (if not running already) - */ - LoginRefresh.startTask = function() { - if (LoginRefresh.intervalId !== null) { - return; - } - - // set interval to 60 seconds - var interval = 1000 * LoginRefresh.intervalTime; - LoginRefresh.intervalId = setInterval(LoginRefresh.checkActiveSession, interval); - }; - - /** - * Stops the session check task - */ - LoginRefresh.stopTask = function() { - clearInterval(LoginRefresh.intervalId); - LoginRefresh.intervalId = null; - }; - - /** - * Generates a modal dialog as template. - * - * @param {String} identifier - * @returns {Object} - */ - LoginRefresh.generateModal = function(identifier) { - return $('<div />', {id: identifier, class: 't3js-modal ' + identifier + ' modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade'}).append( - $('<div />', {class: 'modal-dialog'}).append( - $('<div />', {class: 'modal-content'}).append( - $('<div />', {class: 'modal-header'}).append( - $('<h4 />', {class: 'modal-title'}) - ), - $('<div />', {class: 'modal-body'}), - $('<div />', {class: 'modal-footer'}) - ) - ) - ); - }; - - /** - * Set interval time - * - * @param {integer} intervalTime - */ - LoginRefresh.setIntervalTime = function(intervalTime) { - // To avoid the integer overflow in setInterval, we limit the interval time to be one request per day - LoginRefresh.intervalTime = Math.min(intervalTime, 86400); - }; - - /** - * Set logout url - * - * @param {String} logoutUrl - */ - LoginRefresh.setLogoutUrl = function(logoutUrl) { - LoginRefresh.logoutUrl = logoutUrl; - }; - - /** - * Generates the modal displayed on near session time outs - */ - LoginRefresh.initializeTimeoutModal = function() { - LoginRefresh.$timeoutModal = LoginRefresh.generateModal(LoginRefresh.identifier.loginrefresh); - LoginRefresh.$timeoutModal.addClass('modal-severity-notice'); - LoginRefresh.$timeoutModal.find('.modal-header h4').text(TYPO3.lang['mess.login_about_to_expire_title']); - LoginRefresh.$timeoutModal.find('.modal-body').append( - $('<p />').text(TYPO3.lang['mess.login_about_to_expire']), - $('<div />', {class: 'progress'}).append( - $('<div />', { - class: 'progress-bar progress-bar-warning progress-bar-striped active', - role: 'progressbar', - 'aria-valuemin': '0', - 'aria-valuemax': '100' - }).append( - $('<span />', {class: 'sr-only'}) - ) - ) - ); - LoginRefresh.$timeoutModal.find('.modal-footer').append( - $('<button />', {class: 'btn btn-default', 'data-action': 'logout'}).text(TYPO3.lang['mess.refresh_login_logout_button']).on('click', function() { - top.location.href = LoginRefresh.logoutUrl; - }), - $('<button />', {class: 'btn btn-primary t3js-active', 'data-action': 'refreshSession'}).text(TYPO3.lang['mess.refresh_login_refresh_button']).on('click', function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['login_timedout'], - method: 'GET', - success: function() { - LoginRefresh.hideTimeoutModal(); - } - }); - }) - ); - LoginRefresh.registerDefaultModalEvents(LoginRefresh.$timeoutModal); - - $('body').append(LoginRefresh.$timeoutModal); - }; - - /** - * Shows the timeout dialog. If the backend is not focused, a Web Notification - * is displayed, too. - */ - LoginRefresh.showTimeoutModal = function() { - LoginRefresh.isTimingOut = true; - LoginRefresh.$timeoutModal.modal(LoginRefresh.options.modalConfig); - LoginRefresh.fillProgressbar(LoginRefresh.$timeoutModal); - - if (typeof Notification !== 'undefined' && Notification.permission === 'granted' && !LoginRefresh.isPageActive()) { - LoginRefresh.webNotification = new Notification(TYPO3.lang['mess.login_about_to_expire_title'], { - body: TYPO3.lang['mess.login_about_to_expire'], - icon: '/typo3/sysext/backend/Resources/Public/Images/Logo.png' - }); - LoginRefresh.webNotification.onclick = function() { - window.focus(); - }; - } - }; - - /** - * Hides the timeout dialog. If a Web Notification is displayed, close it too. - */ - LoginRefresh.hideTimeoutModal = function() { - LoginRefresh.isTimingOut = false; - LoginRefresh.$timeoutModal.modal('hide'); - - if (typeof Notification !== 'undefined' && LoginRefresh.webNotification !== null) { - LoginRefresh.webNotification.close(); - } - }; - - /** - * Generates the modal displayed if the backend is locked. - */ - LoginRefresh.initializeBackendLockedModal = function() { - LoginRefresh.$backendLockedModal = LoginRefresh.generateModal(LoginRefresh.identifier.lockedModal); - LoginRefresh.$backendLockedModal.find('.modal-header h4').text(TYPO3.lang['mess.please_wait']); - LoginRefresh.$backendLockedModal.find('.modal-body').append( - $('<p />').text(TYPO3.lang['mess.be_locked']) - ); - LoginRefresh.$backendLockedModal.find('.modal-footer').remove(); - - $('body').append(LoginRefresh.$backendLockedModal); - }; - - /** - * Shows the "backend locked" dialog. - */ - LoginRefresh.showBackendLockedModal = function() { - LoginRefresh.$backendLockedModal.modal(LoginRefresh.options.modalConfig); - }; - - /** - * Hides the "backend locked" dialog. - */ - LoginRefresh.hideBackendLockedModal = function() { - LoginRefresh.$backendLockedModal.modal('hide'); - }; - - /** - * Generates the login form displayed if the session has timed out. - */ - LoginRefresh.initializeLoginForm = function() { - if (TYPO3.configuration.showRefreshLoginPopup) { - // dialog is not required if "showRefreshLoginPopup" is enabled - return; - } - - LoginRefresh.$loginForm = LoginRefresh.generateModal(LoginRefresh.identifier.loginFormModal); - LoginRefresh.$loginForm.addClass('modal-notice'); - var refresh_login_title = String(TYPO3.lang['mess.refresh_login_title']).replace('%s', TYPO3.configuration.username); - LoginRefresh.$loginForm.find('.modal-header h4').text(refresh_login_title); - LoginRefresh.$loginForm.find('.modal-body').append( - $('<p />').text(TYPO3.lang['mess.login_expired']), - $('<form />', {id: 'beLoginRefresh', method: 'POST', action: TYPO3.settings.ajaxUrls['login']}).append( - $('<div />', {class: 'form-group'}).append( - $('<input />', {type: 'password', name: 'p_field', autofocus: 'autofocus', class: 'form-control', placeholder: TYPO3.lang['mess.refresh_login_password'], 'data-rsa-encryption': 't3-loginrefres-userident'}) - ), - $('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}), - $('<input />', {type: 'hidden', name: 'userident', id: 't3-loginrefres-userident'}) - ) - ); - LoginRefresh.$loginForm.find('.modal-footer').append( - $('<a />', {href: LoginRefresh.logoutUrl, class: 'btn btn-default'}).text(TYPO3.lang['mess.refresh_exit_button']), - $('<button />', {type: 'button', class: 'btn btn-primary', 'data-action': 'refreshSession'}) - .text(TYPO3.lang['mess.refresh_login_button']) - .on('click', function(e) { - LoginRefresh.$loginForm.find('form').submit(); - }) - ); - LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.submitForm); - $('body').append(LoginRefresh.$loginForm); - if (require.specified('TYPO3/CMS/Rsaauth/RsaEncryptionModule')) { - require(['TYPO3/CMS/Rsaauth/RsaEncryptionModule'], function(RsaEncryption) { - RsaEncryption.registerForm($('#beLoginRefresh').get(0)); - }); - } - }; - - /** - * Shows the login form. - */ - LoginRefresh.showLoginForm = function() { - // log off for sure - $.ajax({ - url: TYPO3.settings.ajaxUrls['logout'], - method: 'GET', - success: function() { - if (TYPO3.configuration.showRefreshLoginPopup) { - LoginRefresh.showLoginPopup(); - } else { - LoginRefresh.$loginForm.modal(LoginRefresh.options.modalConfig); - } - }, - failure: function() { - alert('something went wrong'); - } - }); - }; - - /** - * Set login frameset url - */ - LoginRefresh.setLoginFramesetUrl = function(loginFramesetUrl) { - LoginRefresh.loginFramesetUrl = loginFramesetUrl; - }; - - /** - * Opens the login form in a new window. - */ - LoginRefresh.showLoginPopup = function() { - var vHWin = window.open(LoginRefresh.loginFramesetUrl, 'relogin_' + Math.random().toString(16).slice(2), 'height=450,width=700,status=0,menubar=0,location=1'); - if (vHWin) { - vHWin.focus(); - } - }; - - /** - * Hides the login form. - */ - LoginRefresh.hideLoginForm = function() { - LoginRefresh.$loginForm.modal('hide'); - }; - - /** - * Fills the progressbar attached to the given modal. - */ - LoginRefresh.fillProgressbar = function($activeModal) { - if (!LoginRefresh.isTimingOut) { - return; - } - - var max = 100, - current = 0, - $progressBar = $activeModal.find('.progress-bar'), - $srText = $progressBar.children('.sr-only'); - - var progress = setInterval(function() { - var isOverdue = (current >= max); - - if (!LoginRefresh.isTimingOut || isOverdue) { - clearInterval(progress); - - if (isOverdue) { - // show login form - LoginRefresh.hideTimeoutModal(); - LoginRefresh.showLoginForm(); - } - - // reset current - current = 0; - } else { - current += 1; - } - - var percentText = (current) + '%'; - $progressBar.css('width', percentText); - $srText.text(percentText); - }, 300); - }; - - /** - * Creates additional data based on the security level and "submits" the form - * via an AJAX request. - * - * @param {Event} event - */ - LoginRefresh.submitForm = function(event) { - event.preventDefault(); - - var $form = LoginRefresh.$loginForm.find('form'), - $passwordField = $form.find('input[name=p_field]'), - $useridentField = $form.find('input[name=userident]'), - passwordFieldValue = $passwordField.val(); - - if (passwordFieldValue === '' && $useridentField.val() === '') { - Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']); - $passwordField.focus(); - return; - } - - if (passwordFieldValue) { - $useridentField.val(passwordFieldValue); - $passwordField.val(''); - } - - var postData = { - login_status: 'login' - }; - $.each($form.serializeArray(), function(i, field) { - postData[field.name] = field.value; - }); - $.ajax({ - url: $form.attr('action'), - method: 'POST', - data: postData, - success: function(response) { - var result = response.login; - if (result.success) { - // User is logged in - LoginRefresh.hideLoginForm(); - } else { - Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']); - $passwordField.focus(); - } - } - }); - }; - - /** - * Registers the (shown|hidden).bs.modal events. - * If a modal is shown, the interval check is stopped. If the modal hides, - * the interval check starts again. - * This method is not invoked for the backend locked modal, because we still - * need to check if the backend gets unlocked again. - * - * @param {Object} $modal - * @returns {Object} - */ - LoginRefresh.registerDefaultModalEvents = function($modal) { - $modal.on('hidden.bs.modal', function() { - LoginRefresh.startTask(); - }).on('shown.bs.modal', function() { - LoginRefresh.stopTask(); - // focus the button which was configured as active button - LoginRefresh.$timeoutModal.find('.modal-footer .t3js-active').first().focus(); - }); - - return $modal; - }; - - /** - * Checks if the user is in focus of the backend. - * Thanks to http://stackoverflow.com/a/19519701 - */ - LoginRefresh.isPageActive = function() { - var stateKey, eventKey, keys = { - hidden: 'visibilitychange', - webkitHidden: 'webkitvisibilitychange', - mozHidden: 'mozvisibilitychange', - msHidden: 'msvisibilitychange' - }; - - for (stateKey in keys) { - if (stateKey in document) { - eventKey = keys[stateKey]; - break; - } - } - return function(c) { - if (c) { - document.addEventListener(eventKey, c); - } - return !document[stateKey]; - }(); - }; - - /** - * Periodically called task that checks if - * - * - the user's backend session is about to expire - * - the user's backend session has expired - * - the backend got locked - * - * and opens a dialog. - */ - LoginRefresh.checkActiveSession = function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['login_timedout'], - success: function(response) { - if (response.login.locked) { - if (!LoginRefresh.backendIsLocked) { - LoginRefresh.backendIsLocked = true; - LoginRefresh.showBackendLockedModal(); - } - } else { - if (LoginRefresh.backendIsLocked) { - LoginRefresh.backendIsLocked = false; - LoginRefresh.hideBackendLockedModal(); - } - } - - if (!LoginRefresh.backendIsLocked) { - if (response.login.timed_out || response.login.will_time_out) { - if (response.login.timed_out) { - LoginRefresh.showLoginForm(); - } else { - LoginRefresh.showTimeoutModal(); - } - } - } - } - }); - }; - - LoginRefresh.initialize = function() { - LoginRefresh.initializeTimeoutModal(); - LoginRefresh.initializeBackendLockedModal(); - LoginRefresh.initializeLoginForm(); - - LoginRefresh.startTask(); - - if (typeof Notification !== 'undefined' && Notification.permission !== 'granted') { - Notification.requestPermission(); - } - }; - - // expose to global - TYPO3.LoginRefresh = LoginRefresh; - - return LoginRefresh; + 'use strict'; + + /** + * + * @type {{identifier: {loginrefresh: string, lockedModal: string, loginFormModal: string}, options: {modalConfig: {backdrop: string}}, webNotification: null, intervalTime: integer, intervalId: null, backendIsLocked: boolean, isTimingOut: boolean, $timeoutModal: string, $backendLockedModal: string, $loginForm: string, loginFramesetUrl: string, logoutUrl: string}} + * @exports TYPO3/CMS/Backend/LoginRefresh + */ + var LoginRefresh = { + identifier: { + loginrefresh: 't3js-modal-loginrefresh', + lockedModal: 't3js-modal-backendlocked', + loginFormModal: 't3js-modal-backendloginform' + }, + options: { + modalConfig: { + backdrop: 'static' + } + }, + webNotification: null, + intervalTime: 60, + intervalId: null, + backendIsLocked: false, + isTimingOut: false, + $timeoutModal: '', + $backendLockedModal: '', + $loginForm: '', + loginFramesetUrl: '', + logoutUrl: '' + }; + + /** + * Starts the session check task (if not running already) + */ + LoginRefresh.startTask = function() { + if (LoginRefresh.intervalId !== null) { + return; + } + + // set interval to 60 seconds + var interval = 1000 * LoginRefresh.intervalTime; + LoginRefresh.intervalId = setInterval(LoginRefresh.checkActiveSession, interval); + }; + + /** + * Stops the session check task + */ + LoginRefresh.stopTask = function() { + clearInterval(LoginRefresh.intervalId); + LoginRefresh.intervalId = null; + }; + + /** + * Generates a modal dialog as template. + * + * @param {String} identifier + * @returns {Object} + */ + LoginRefresh.generateModal = function(identifier) { + return $('<div />', { + id: identifier, + class: 't3js-modal ' + identifier + ' modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade' + }).append( + $('<div />', {class: 'modal-dialog'}).append( + $('<div />', {class: 'modal-content'}).append( + $('<div />', {class: 'modal-header'}).append( + $('<h4 />', {class: 'modal-title'}) + ), + $('<div />', {class: 'modal-body'}), + $('<div />', {class: 'modal-footer'}) + ) + ) + ); + }; + + /** + * Set interval time + * + * @param {integer} intervalTime + */ + LoginRefresh.setIntervalTime = function(intervalTime) { + // To avoid the integer overflow in setInterval, we limit the interval time to be one request per day + LoginRefresh.intervalTime = Math.min(intervalTime, 86400); + }; + + /** + * Set logout url + * + * @param {String} logoutUrl + */ + LoginRefresh.setLogoutUrl = function(logoutUrl) { + LoginRefresh.logoutUrl = logoutUrl; + }; + + /** + * Generates the modal displayed on near session time outs + */ + LoginRefresh.initializeTimeoutModal = function() { + LoginRefresh.$timeoutModal = LoginRefresh.generateModal(LoginRefresh.identifier.loginrefresh); + LoginRefresh.$timeoutModal.addClass('modal-severity-notice'); + LoginRefresh.$timeoutModal.find('.modal-header h4').text(TYPO3.lang['mess.login_about_to_expire_title']); + LoginRefresh.$timeoutModal.find('.modal-body').append( + $('<p />').text(TYPO3.lang['mess.login_about_to_expire']), + $('<div />', {class: 'progress'}).append( + $('<div />', { + class: 'progress-bar progress-bar-warning progress-bar-striped active', + role: 'progressbar', + 'aria-valuemin': '0', + 'aria-valuemax': '100' + }).append( + $('<span />', {class: 'sr-only'}) + ) + ) + ); + LoginRefresh.$timeoutModal.find('.modal-footer').append( + $('<button />', { + class: 'btn btn-default', + 'data-action': 'logout' + }).text(TYPO3.lang['mess.refresh_login_logout_button']).on('click', function() { + top.location.href = LoginRefresh.logoutUrl; + }), + $('<button />', { + class: 'btn btn-primary t3js-active', + 'data-action': 'refreshSession' + }).text(TYPO3.lang['mess.refresh_login_refresh_button']).on('click', function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['login_timedout'], + method: 'GET', + success: function() { + LoginRefresh.hideTimeoutModal(); + } + }); + }) + ); + LoginRefresh.registerDefaultModalEvents(LoginRefresh.$timeoutModal); + + $('body').append(LoginRefresh.$timeoutModal); + }; + + /** + * Shows the timeout dialog. If the backend is not focused, a Web Notification + * is displayed, too. + */ + LoginRefresh.showTimeoutModal = function() { + LoginRefresh.isTimingOut = true; + LoginRefresh.$timeoutModal.modal(LoginRefresh.options.modalConfig); + LoginRefresh.fillProgressbar(LoginRefresh.$timeoutModal); + + if (typeof Notification !== 'undefined' && Notification.permission === 'granted' && !LoginRefresh.isPageActive()) { + LoginRefresh.webNotification = new Notification(TYPO3.lang['mess.login_about_to_expire_title'], { + body: TYPO3.lang['mess.login_about_to_expire'], + icon: '/typo3/sysext/backend/Resources/Public/Images/Logo.png' + }); + LoginRefresh.webNotification.onclick = function() { + window.focus(); + }; + } + }; + + /** + * Hides the timeout dialog. If a Web Notification is displayed, close it too. + */ + LoginRefresh.hideTimeoutModal = function() { + LoginRefresh.isTimingOut = false; + LoginRefresh.$timeoutModal.modal('hide'); + + if (typeof Notification !== 'undefined' && LoginRefresh.webNotification !== null) { + LoginRefresh.webNotification.close(); + } + }; + + /** + * Generates the modal displayed if the backend is locked. + */ + LoginRefresh.initializeBackendLockedModal = function() { + LoginRefresh.$backendLockedModal = LoginRefresh.generateModal(LoginRefresh.identifier.lockedModal); + LoginRefresh.$backendLockedModal.find('.modal-header h4').text(TYPO3.lang['mess.please_wait']); + LoginRefresh.$backendLockedModal.find('.modal-body').append( + $('<p />').text(TYPO3.lang['mess.be_locked']) + ); + LoginRefresh.$backendLockedModal.find('.modal-footer').remove(); + + $('body').append(LoginRefresh.$backendLockedModal); + }; + + /** + * Shows the "backend locked" dialog. + */ + LoginRefresh.showBackendLockedModal = function() { + LoginRefresh.$backendLockedModal.modal(LoginRefresh.options.modalConfig); + }; + + /** + * Hides the "backend locked" dialog. + */ + LoginRefresh.hideBackendLockedModal = function() { + LoginRefresh.$backendLockedModal.modal('hide'); + }; + + /** + * Generates the login form displayed if the session has timed out. + */ + LoginRefresh.initializeLoginForm = function() { + if (TYPO3.configuration.showRefreshLoginPopup) { + // dialog is not required if "showRefreshLoginPopup" is enabled + return; + } + + LoginRefresh.$loginForm = LoginRefresh.generateModal(LoginRefresh.identifier.loginFormModal); + LoginRefresh.$loginForm.addClass('modal-notice'); + var refresh_login_title = String(TYPO3.lang['mess.refresh_login_title']).replace('%s', TYPO3.configuration.username); + LoginRefresh.$loginForm.find('.modal-header h4').text(refresh_login_title); + LoginRefresh.$loginForm.find('.modal-body').append( + $('<p />').text(TYPO3.lang['mess.login_expired']), + $('<form />', { + id: 'beLoginRefresh', + method: 'POST', + action: TYPO3.settings.ajaxUrls['login'] + }).append( + $('<div />', {class: 'form-group'}).append( + $('<input />', { + type: 'password', + name: 'p_field', + autofocus: 'autofocus', + class: 'form-control', + placeholder: TYPO3.lang['mess.refresh_login_password'], + 'data-rsa-encryption': 't3-loginrefres-userident' + }) + ), + $('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}), + $('<input />', {type: 'hidden', name: 'userident', id: 't3-loginrefres-userident'}) + ) + ); + LoginRefresh.$loginForm.find('.modal-footer').append( + $('<a />', { + href: LoginRefresh.logoutUrl, + class: 'btn btn-default' + }).text(TYPO3.lang['mess.refresh_exit_button']), + $('<button />', {type: 'button', class: 'btn btn-primary', 'data-action': 'refreshSession'}) + .text(TYPO3.lang['mess.refresh_login_button']) + .on('click', function(e) { + LoginRefresh.$loginForm.find('form').submit(); + }) + ); + LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.submitForm); + $('body').append(LoginRefresh.$loginForm); + if (require.specified('TYPO3/CMS/Rsaauth/RsaEncryptionModule')) { + require(['TYPO3/CMS/Rsaauth/RsaEncryptionModule'], function(RsaEncryption) { + RsaEncryption.registerForm($('#beLoginRefresh').get(0)); + }); + } + }; + + /** + * Shows the login form. + */ + LoginRefresh.showLoginForm = function() { + // log off for sure + $.ajax({ + url: TYPO3.settings.ajaxUrls['logout'], + method: 'GET', + success: function() { + if (TYPO3.configuration.showRefreshLoginPopup) { + LoginRefresh.showLoginPopup(); + } else { + LoginRefresh.$loginForm.modal(LoginRefresh.options.modalConfig); + } + }, + failure: function() { + alert('something went wrong'); + } + }); + }; + + /** + * Set login frameset url + */ + LoginRefresh.setLoginFramesetUrl = function(loginFramesetUrl) { + LoginRefresh.loginFramesetUrl = loginFramesetUrl; + }; + + /** + * Opens the login form in a new window. + */ + LoginRefresh.showLoginPopup = function() { + var vHWin = window.open(LoginRefresh.loginFramesetUrl, 'relogin_' + Math.random().toString(16).slice(2), 'height=450,width=700,status=0,menubar=0,location=1'); + if (vHWin) { + vHWin.focus(); + } + }; + + /** + * Hides the login form. + */ + LoginRefresh.hideLoginForm = function() { + LoginRefresh.$loginForm.modal('hide'); + }; + + /** + * Fills the progressbar attached to the given modal. + */ + LoginRefresh.fillProgressbar = function($activeModal) { + if (!LoginRefresh.isTimingOut) { + return; + } + + var max = 100, + current = 0, + $progressBar = $activeModal.find('.progress-bar'), + $srText = $progressBar.children('.sr-only'); + + var progress = setInterval(function() { + var isOverdue = (current >= max); + + if (!LoginRefresh.isTimingOut || isOverdue) { + clearInterval(progress); + + if (isOverdue) { + // show login form + LoginRefresh.hideTimeoutModal(); + LoginRefresh.showLoginForm(); + } + + // reset current + current = 0; + } else { + current += 1; + } + + var percentText = (current) + '%'; + $progressBar.css('width', percentText); + $srText.text(percentText); + }, 300); + }; + + /** + * Creates additional data based on the security level and "submits" the form + * via an AJAX request. + * + * @param {Event} event + */ + LoginRefresh.submitForm = function(event) { + event.preventDefault(); + + var $form = LoginRefresh.$loginForm.find('form'), + $passwordField = $form.find('input[name=p_field]'), + $useridentField = $form.find('input[name=userident]'), + passwordFieldValue = $passwordField.val(); + + if (passwordFieldValue === '' && $useridentField.val() === '') { + Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']); + $passwordField.focus(); + return; + } + + if (passwordFieldValue) { + $useridentField.val(passwordFieldValue); + $passwordField.val(''); + } + + var postData = { + login_status: 'login' + }; + $.each($form.serializeArray(), function(i, field) { + postData[field.name] = field.value; + }); + $.ajax({ + url: $form.attr('action'), + method: 'POST', + data: postData, + success: function(response) { + var result = response.login; + if (result.success) { + // User is logged in + LoginRefresh.hideLoginForm(); + } else { + Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']); + $passwordField.focus(); + } + } + }); + }; + + /** + * Registers the (shown|hidden).bs.modal events. + * If a modal is shown, the interval check is stopped. If the modal hides, + * the interval check starts again. + * This method is not invoked for the backend locked modal, because we still + * need to check if the backend gets unlocked again. + * + * @param {Object} $modal + * @returns {Object} + */ + LoginRefresh.registerDefaultModalEvents = function($modal) { + $modal.on('hidden.bs.modal', function() { + LoginRefresh.startTask(); + }).on('shown.bs.modal', function() { + LoginRefresh.stopTask(); + // focus the button which was configured as active button + LoginRefresh.$timeoutModal.find('.modal-footer .t3js-active').first().focus(); + }); + + return $modal; + }; + + /** + * Checks if the user is in focus of the backend. + * Thanks to http://stackoverflow.com/a/19519701 + */ + LoginRefresh.isPageActive = function() { + var stateKey, eventKey, keys = { + hidden: 'visibilitychange', + webkitHidden: 'webkitvisibilitychange', + mozHidden: 'mozvisibilitychange', + msHidden: 'msvisibilitychange' + }; + + for (stateKey in keys) { + if (stateKey in document) { + eventKey = keys[stateKey]; + break; + } + } + return function(c) { + if (c) { + document.addEventListener(eventKey, c); + } + return !document[stateKey]; + }(); + }; + + /** + * Periodically called task that checks if + * + * - the user's backend session is about to expire + * - the user's backend session has expired + * - the backend got locked + * + * and opens a dialog. + */ + LoginRefresh.checkActiveSession = function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['login_timedout'], + success: function(response) { + if (response.login.locked) { + if (!LoginRefresh.backendIsLocked) { + LoginRefresh.backendIsLocked = true; + LoginRefresh.showBackendLockedModal(); + } + } else { + if (LoginRefresh.backendIsLocked) { + LoginRefresh.backendIsLocked = false; + LoginRefresh.hideBackendLockedModal(); + } + } + + if (!LoginRefresh.backendIsLocked) { + if (response.login.timed_out || response.login.will_time_out) { + if (response.login.timed_out) { + LoginRefresh.showLoginForm(); + } else { + LoginRefresh.showTimeoutModal(); + } + } + } + } + }); + }; + + LoginRefresh.initialize = function() { + LoginRefresh.initializeTimeoutModal(); + LoginRefresh.initializeBackendLockedModal(); + LoginRefresh.initializeLoginForm(); + + LoginRefresh.startTask(); + + if (typeof Notification !== 'undefined' && Notification.permission !== 'granted') { + Notification.requestPermission(); + } + }; + + // expose to global + TYPO3.LoginRefresh = LoginRefresh; + + return LoginRefresh; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js index 03648fbc1d2cb659cac374bf51557765deb50321..ba37686c98f060f96b1bf1c2c6cf30911bd32d3a 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js @@ -16,445 +16,451 @@ * API for modal windows powered by Twitter Bootstrap. */ define(['jquery', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Icons', - 'bootstrap' - ], function($, Severity, Icons) { - 'use strict'; + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Icons', + 'bootstrap' +], function($, Severity, Icons) { + 'use strict'; - try { - // fetch from parent - if (parent && parent.window.TYPO3 && parent.window.TYPO3.Modal) { - // we need to trigger the event capturing again, in order to make sure this works inside iframes - parent.window.TYPO3.Modal.initializeMarkupTrigger(document); - return parent.window.TYPO3.Modal; - } + try { + // fetch from parent + if (parent && parent.window.TYPO3 && parent.window.TYPO3.Modal) { + // we need to trigger the event capturing again, in order to make sure this works inside iframes + parent.window.TYPO3.Modal.initializeMarkupTrigger(document); + return parent.window.TYPO3.Modal; + } - // fetch object from outer frame - if (top && top.TYPO3.Modal) { - // we need to trigger the event capturing again, in order to make sure this works inside iframes - top.TYPO3.Modal.initializeMarkupTrigger(document); - return top.TYPO3.Modal; - } - } catch (e) { - // This only happens if the opener, parent or top is some other url (eg a local file) - // which loaded the current window. Then the browser's cross domain policy jumps in - // and raises an exception. - // For this case we are safe and we can create our global object below. - } + // fetch object from outer frame + if (top && top.TYPO3.Modal) { + // we need to trigger the event capturing again, in order to make sure this works inside iframes + top.TYPO3.Modal.initializeMarkupTrigger(document); + return top.TYPO3.Modal; + } + } catch (e) { + // This only happens if the opener, parent or top is some other url (eg a local file) + // which loaded the current window. Then the browser's cross domain policy jumps in + // and raises an exception. + // For this case we are safe and we can create our global object below. + } - /** - * The main object of the modal API - * - * @type {{instances: Array, currentModal: null, template: (*), identifiers: {modal: string, content: string, title: string, close: string, body: string, footer: string, iframe: string, iconPlaceholder: string}, sizes: {small: string, default: string, large: string, full: string}, styles: {default: string, light: string, dark: string}, types: {default: string, ajax: string, iframe: string}, defaultConfiguration: {type: string, title: string, content: string, severity: number, buttons: Array, style: string, size: string, additionalCssClasses: Array, callback: Modal.defaultConfiguration.callback, ajaxCallback: Modal.defaultConfiguration.ajaxCallback, ajaxTarget: null}}} - * @exports TYPO3/CMS/Backend/Modal - */ - var Modal = { - instances: [], - currentModal: null, - template: $( - '<div class="t3js-modal modal fade">' + - '<div class="modal-dialog">' + - '<div class="t3js-modal-content modal-content">' + - '<div class="modal-header">' + - '<button class="t3js-modal-close close">' + - '<span aria-hidden="true">' + - '<span class="t3js-modal-icon-placeholder" data-icon="actions-close"></span>' + - '</span>' + - '<span class="sr-only"></span>' + - '</button>' + - '<h4 class="t3js-modal-title modal-title"></h4>' + - '</div>' + - '<div class="t3js-modal-body modal-body"></div>' + - '<div class="t3js-modal-footer modal-footer"></div>' + - '</div>' + - '</div>' + - '</div>' - ), - identifiers: { - modal: '.t3js-modal', - content: '.t3js-modal-content', - title: '.t3js-modal-title', - close: '.t3js-modal-close', - body: '.t3js-modal-body', - footer: '.t3js-modal-footer', - iframe: '.t3js-modal-iframe', - iconPlaceholder: '.t3js-modal-icon-placeholder' - }, - sizes: { - small: 'small', - default: 'default', - medium: 'medium', - large: 'large', - full: 'full' - }, - styles: { - default: 'light', - light: 'light', - dark: 'dark' - }, - types: { - default: 'default', - ajax: 'ajax', - iframe: 'iframe' - }, - defaultConfiguration: { - type: 'default', - title: 'Information', - content: 'No content provided, please check your <code>Modal</code> configuration.', - severity: Severity.notice, - buttons: [], - style: 'default', - size: 'default', - additionalCssClasses: [], - callback: function(){ }, - ajaxCallback: function(){ }, - ajaxTarget: null - } - }; + /** + * The main object of the modal API + * + * @type {{instances: Array, currentModal: null, template: (*), identifiers: {modal: string, content: string, title: string, close: string, body: string, footer: string, iframe: string, iconPlaceholder: string}, sizes: {small: string, default: string, large: string, full: string}, styles: {default: string, light: string, dark: string}, types: {default: string, ajax: string, iframe: string}, defaultConfiguration: {type: string, title: string, content: string, severity: number, buttons: Array, style: string, size: string, additionalCssClasses: Array, callback: Modal.defaultConfiguration.callback, ajaxCallback: Modal.defaultConfiguration.ajaxCallback, ajaxTarget: null}}} + * @exports TYPO3/CMS/Backend/Modal + */ + var Modal = { + instances: [], + currentModal: null, + template: $( + '<div class="t3js-modal modal fade">' + + '<div class="modal-dialog">' + + '<div class="t3js-modal-content modal-content">' + + '<div class="modal-header">' + + '<button class="t3js-modal-close close">' + + '<span aria-hidden="true">' + + '<span class="t3js-modal-icon-placeholder" data-icon="actions-close"></span>' + + '</span>' + + '<span class="sr-only"></span>' + + '</button>' + + '<h4 class="t3js-modal-title modal-title"></h4>' + + '</div>' + + '<div class="t3js-modal-body modal-body"></div>' + + '<div class="t3js-modal-footer modal-footer"></div>' + + '</div>' + + '</div>' + + '</div>' + ), + identifiers: { + modal: '.t3js-modal', + content: '.t3js-modal-content', + title: '.t3js-modal-title', + close: '.t3js-modal-close', + body: '.t3js-modal-body', + footer: '.t3js-modal-footer', + iframe: '.t3js-modal-iframe', + iconPlaceholder: '.t3js-modal-icon-placeholder' + }, + sizes: { + small: 'small', + default: 'default', + medium: 'medium', + large: 'large', + full: 'full' + }, + styles: { + default: 'light', + light: 'light', + dark: 'dark' + }, + types: { + default: 'default', + ajax: 'ajax', + iframe: 'iframe' + }, + defaultConfiguration: { + type: 'default', + title: 'Information', + content: 'No content provided, please check your <code>Modal</code> configuration.', + severity: Severity.notice, + buttons: [], + style: 'default', + size: 'default', + additionalCssClasses: [], + callback: function() { + }, + ajaxCallback: function() { + }, + ajaxTarget: null + } + }; - /** - * Shows a confirmation dialog - * Events: - * - button.clicked - * - confirm.button.cancel - * - confirm.button.ok - * - * @param {String} title the title for the confirm modal - * @param {*} content the content for the conform modal, e.g. the main question - * @param {int} [severity=Severity.warning] severity default Severity.warning - * @param {array} [buttons] an array with buttons, default no buttons - * @param {array} [additionalCssClasses=''] additional css classes to add to the modal - */ - Modal.confirm = function(title, content, severity, buttons, additionalCssClasses) { - severity = typeof severity !== 'undefined' ? severity : Severity.warning; + /** + * Shows a confirmation dialog + * Events: + * - button.clicked + * - confirm.button.cancel + * - confirm.button.ok + * + * @param {String} title the title for the confirm modal + * @param {*} content the content for the conform modal, e.g. the main question + * @param {int} [severity=Severity.warning] severity default Severity.warning + * @param {array} [buttons] an array with buttons, default no buttons + * @param {array} [additionalCssClasses=''] additional css classes to add to the modal + */ + Modal.confirm = function(title, content, severity, buttons, additionalCssClasses) { + severity = typeof severity !== 'undefined' ? severity : Severity.warning; - return Modal.advanced( - { - title: title, - content: content, - severity: severity, - buttons: buttons || [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', - btnClass: 'btn-' + Severity.getCssClass(severity), - name: 'ok' - } - ], - additionalCssClasses: additionalCssClasses || [], - callback: function(currentModal) { - currentModal.on('button.clicked', function(e) { - if (e.target.name === 'cancel') { - $(this).trigger('confirm.button.cancel'); - } else if (e.target.name === 'ok') { - $(this).trigger('confirm.button.ok'); - } - }); - } - } - ); - }; + return Modal.advanced( + { + title: title, + content: content, + severity: severity, + buttons: buttons || [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', + btnClass: 'btn-' + Severity.getCssClass(severity), + name: 'ok' + } + ], + additionalCssClasses: additionalCssClasses || [], + callback: function(currentModal) { + currentModal.on('button.clicked', function(e) { + if (e.target.name === 'cancel') { + $(this).trigger('confirm.button.cancel'); + } else if (e.target.name === 'ok') { + $(this).trigger('confirm.button.ok'); + } + }); + } + } + ); + }; - /** - * load URL with AJAX, append the content to the modal-body - * and trigger the callback - * - * @param {String} title - * @param {int} severity - * @param {array} buttons - * @param {String} url - * @param {function} callback - * @param {String} target - */ - Modal.loadUrl = function(title, severity, buttons, url, callback, target) { - return Modal.advanced({ - type: Modal.types.ajax, - title: title, - content: url, - severity: typeof severity !== 'undefined' ? severity : Severity.info, - buttons: buttons, - ajaxCallback: callback, - ajaxTarget: target - }); - }; + /** + * load URL with AJAX, append the content to the modal-body + * and trigger the callback + * + * @param {String} title + * @param {int} severity + * @param {array} buttons + * @param {String} url + * @param {function} callback + * @param {String} target + */ + Modal.loadUrl = function(title, severity, buttons, url, callback, target) { + return Modal.advanced({ + type: Modal.types.ajax, + title: title, + content: url, + severity: typeof severity !== 'undefined' ? severity : Severity.info, + buttons: buttons, + ajaxCallback: callback, + ajaxTarget: target + }); + }; - /** - * Shows a dialog - * - * @param {String} title the title for the modal - * @param {*} content the content for the modal, e.g. the main question - * @param {int} severity default Severity.info - * @param {array} buttons an array with buttons, default no buttons - * @param {array} additionalCssClasses additional css classes to add to the modal - */ - Modal.show = function(title, content, severity, buttons, additionalCssClasses) { - return Modal.advanced({ - type: Modal.types.default, - title: title, - content: content, - severity: typeof severity !== 'undefined' ? severity : Severity.info, - buttons: buttons, - additionalCssClasses: additionalCssClasses - }); - }; + /** + * Shows a dialog + * + * @param {String} title the title for the modal + * @param {*} content the content for the modal, e.g. the main question + * @param {int} severity default Severity.info + * @param {array} buttons an array with buttons, default no buttons + * @param {array} additionalCssClasses additional css classes to add to the modal + */ + Modal.show = function(title, content, severity, buttons, additionalCssClasses) { + return Modal.advanced({ + type: Modal.types.default, + title: title, + content: content, + severity: typeof severity !== 'undefined' ? severity : Severity.info, + buttons: buttons, + additionalCssClasses: additionalCssClasses + }); + }; - /** - * Loads modal by configuration - * - * @param {object} configuration configuration for the modal - */ - Modal.advanced = function(configuration) { - if (typeof configuration !== 'object') { - configuration = {}; - } + /** + * Loads modal by configuration + * + * @param {object} configuration configuration for the modal + */ + Modal.advanced = function(configuration) { + if (typeof configuration !== 'object') { + configuration = {}; + } - // Validation of configuration - configuration.type = typeof configuration.type === 'string' && configuration.type in Modal.types ? configuration.type : Modal.defaultConfiguration.type; - configuration.title = typeof configuration.title === 'string' ? configuration.title : Modal.defaultConfiguration.title; - configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object' ? configuration.content : Modal.defaultConfiguration.content; - configuration.severity = typeof configuration.severity !== 'undefined' ? configuration.severity : Modal.defaultConfiguration.severity; - configuration.buttons = configuration.buttons || Modal.defaultConfiguration.buttons; - configuration.size = typeof configuration.size === 'string' && configuration.size in Modal.sizes ? configuration.size : Modal.defaultConfiguration.size; - configuration.style = typeof configuration.style === 'string' && configuration.style in Modal.styles ? configuration.style : Modal.defaultConfiguration.style; - configuration.additionalCssClasses = configuration.additionalCssClasses || Modal.defaultConfiguration.additionalCssClasses; - configuration.callback = typeof configuration.callback === 'function' ? configuration.callback : Modal.defaultConfiguration.callback; - configuration.ajaxCallback = typeof configuration.ajaxCallback === 'function' ? configuration.ajaxCallback : Modal.defaultConfiguration.ajaxCallback; - configuration.ajaxTarget = typeof configuration.ajaxTarget === 'string' ? configuration.ajaxTarget : Modal.defaultConfiguration.ajaxTarget; + // Validation of configuration + configuration.type = typeof configuration.type === 'string' && configuration.type in Modal.types ? configuration.type : Modal.defaultConfiguration.type; + configuration.title = typeof configuration.title === 'string' ? configuration.title : Modal.defaultConfiguration.title; + configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object' ? configuration.content : Modal.defaultConfiguration.content; + configuration.severity = typeof configuration.severity !== 'undefined' ? configuration.severity : Modal.defaultConfiguration.severity; + configuration.buttons = configuration.buttons || Modal.defaultConfiguration.buttons; + configuration.size = typeof configuration.size === 'string' && configuration.size in Modal.sizes ? configuration.size : Modal.defaultConfiguration.size; + configuration.style = typeof configuration.style === 'string' && configuration.style in Modal.styles ? configuration.style : Modal.defaultConfiguration.style; + configuration.additionalCssClasses = configuration.additionalCssClasses || Modal.defaultConfiguration.additionalCssClasses; + configuration.callback = typeof configuration.callback === 'function' ? configuration.callback : Modal.defaultConfiguration.callback; + configuration.ajaxCallback = typeof configuration.ajaxCallback === 'function' ? configuration.ajaxCallback : Modal.defaultConfiguration.ajaxCallback; + configuration.ajaxTarget = typeof configuration.ajaxTarget === 'string' ? configuration.ajaxTarget : Modal.defaultConfiguration.ajaxTarget; - return Modal._generate( - configuration.type, - configuration.title, - configuration.content, - configuration.severity, - configuration.buttons, - configuration.style, - configuration.size, - configuration.additionalCssClasses, - configuration.callback, - configuration.ajaxCallback, - configuration.ajaxTarget - ); - }; + return Modal._generate( + configuration.type, + configuration.title, + configuration.content, + configuration.severity, + configuration.buttons, + configuration.style, + configuration.size, + configuration.additionalCssClasses, + configuration.callback, + configuration.ajaxCallback, + configuration.ajaxTarget + ); + }; - /** - * Generate the modal window - * Events: - * - button.clicked - * - * @param {String} type the type of the modal - * @param {String} title the title for the modal - * @param {*} content the content for the modal, e.g. the main question - * @param {int} severity default Severity.info - * @param {array} buttons an array with buttons, default no buttons - * @param {String} style the style of the modal window - * @param {String} size the size of the modal window - * @param {array} additionalCssClasses additional css classes to add to the modal - * @param {function} callback - * @param {function} ajaxCallback - * @param {String} ajaxTarget - * @private - */ - Modal._generate = function(type, title, content, severity, buttons, style, size, additionalCssClasses, callback, ajaxCallback, ajaxTarget) { - var currentModal = Modal.template.clone(); - if (additionalCssClasses.length) { - for (var i = 0; i < additionalCssClasses.length; i++) { - currentModal.addClass(additionalCssClasses[i]); - } - } - currentModal.addClass('modal-type-' + Modal.types[type]); - currentModal.addClass('modal-severity-' + Severity.getCssClass(severity)); - currentModal.addClass('modal-style-' + Modal.styles[style]); - currentModal.addClass('modal-size-' + Modal.sizes[size]); - currentModal.attr('tabindex', '-1'); - currentModal.find(Modal.identifiers.title).text(title); - currentModal.find(Modal.identifiers.close).on('click', function() { - currentModal.modal('hide'); - }); + /** + * Generate the modal window + * Events: + * - button.clicked + * + * @param {String} type the type of the modal + * @param {String} title the title for the modal + * @param {*} content the content for the modal, e.g. the main question + * @param {int} severity default Severity.info + * @param {array} buttons an array with buttons, default no buttons + * @param {String} style the style of the modal window + * @param {String} size the size of the modal window + * @param {array} additionalCssClasses additional css classes to add to the modal + * @param {function} callback + * @param {function} ajaxCallback + * @param {String} ajaxTarget + * @private + */ + Modal._generate = function(type, title, content, severity, buttons, style, size, additionalCssClasses, callback, ajaxCallback, ajaxTarget) { + var currentModal = Modal.template.clone(); + if (additionalCssClasses.length) { + for (var i = 0; i < additionalCssClasses.length; i++) { + currentModal.addClass(additionalCssClasses[i]); + } + } + currentModal.addClass('modal-type-' + Modal.types[type]); + currentModal.addClass('modal-severity-' + Severity.getCssClass(severity)); + currentModal.addClass('modal-style-' + Modal.styles[style]); + currentModal.addClass('modal-size-' + Modal.sizes[size]); + currentModal.attr('tabindex', '-1'); + currentModal.find(Modal.identifiers.title).text(title); + currentModal.find(Modal.identifiers.close).on('click', function() { + currentModal.modal('hide'); + }); - // Add content - if (type === 'ajax') { - $.get(content, function(response) { - Modal.currentModal.find(ajaxTarget ? ajaxTarget : Modal.identifiers.body).empty().append(response); - if (ajaxCallback) { - ajaxCallback(); - } - Modal.currentModal.trigger('modal-loaded'); - }, 'html'); - Icons.getIcon('spinner-circle', Icons.sizes.default, null, null, Icons.markupIdentifiers.inline).done(function(icon) { - currentModal.find(Modal.identifiers.body).html('<div class="modal-loading">' + icon + '</div>'); - }); - } else if (type === 'iframe') { - currentModal.find(Modal.identifiers.body).append( - $('<iframe />', { src: content, 'name': 'modal_frame', 'class': 'modal-iframe t3js-modal-iframe' }) - ); - currentModal.find(Modal.identifiers.iframe).on('load',function() { - currentModal.find(Modal.identifiers.title).text( - currentModal.find(Modal.identifiers.iframe).get(0).contentDocument.title - ); - }); - } else { - if (typeof content === 'object') { - currentModal.find(Modal.identifiers.body).append(content); - } else { - // we need html, check if we have to wrap content in <p> - if (!/^<[a-z][\s\S]*>/i.test(content)) { - content = $('<p />').html(content); - } - currentModal.find(Modal.identifiers.body).html(content); - } - } + // Add content + if (type === 'ajax') { + $.get(content, function(response) { + Modal.currentModal.find(ajaxTarget ? ajaxTarget : Modal.identifiers.body).empty().append(response); + if (ajaxCallback) { + ajaxCallback(); + } + Modal.currentModal.trigger('modal-loaded'); + }, 'html'); + Icons.getIcon('spinner-circle', Icons.sizes.default, null, null, Icons.markupIdentifiers.inline).done(function(icon) { + currentModal.find(Modal.identifiers.body).html('<div class="modal-loading">' + icon + '</div>'); + }); + } else if (type === 'iframe') { + currentModal.find(Modal.identifiers.body).append( + $('<iframe />', { + src: content, + 'name': 'modal_frame', + 'class': 'modal-iframe t3js-modal-iframe' + }) + ); + currentModal.find(Modal.identifiers.iframe).on('load', function() { + currentModal.find(Modal.identifiers.title).text( + currentModal.find(Modal.identifiers.iframe).get(0).contentDocument.title + ); + }); + } else { + if (typeof content === 'object') { + currentModal.find(Modal.identifiers.body).append(content); + } else { + // we need html, check if we have to wrap content in <p> + if (!/^<[a-z][\s\S]*>/i.test(content)) { + content = $('<p />').html(content); + } + currentModal.find(Modal.identifiers.body).html(content); + } + } - // Add buttons - if (buttons.length > 0) { - for (i = 0; i<buttons.length; i++) { - var button = buttons[i]; - var $button = $('<button />', {class: 'btn'}); - $button.html('<span>' + button.text + '</span>'); - if (button.active) { - $button.addClass('t3js-active'); - } - if (button.btnClass) { - $button.addClass(button.btnClass); - } - if (button.name) { - $button.attr('name', button.name); - } - if (button.trigger) { - $button.on('click', button.trigger); - } - if (button.dataAttributes) { - if (Object.keys(button.dataAttributes).length > 0) { - Object.keys(button.dataAttributes).map(function(key, index) { - $button.attr('data-' + key, button.dataAttributes[key]); - }); - } - } - if (button.icon) { - $button.prepend('<span class="t3js-modal-icon-placeholder" data-icon="' + button.icon + '"></span>'); - } - currentModal.find(Modal.identifiers.footer).append($button); - } - currentModal - .find(Modal.identifiers.footer).find('button') - .on('click', function() { - $(this).trigger('button.clicked'); - }); + // Add buttons + if (buttons.length > 0) { + for (i = 0; i < buttons.length; i++) { + var button = buttons[i]; + var $button = $('<button />', {class: 'btn'}); + $button.html('<span>' + button.text + '</span>'); + if (button.active) { + $button.addClass('t3js-active'); + } + if (button.btnClass) { + $button.addClass(button.btnClass); + } + if (button.name) { + $button.attr('name', button.name); + } + if (button.trigger) { + $button.on('click', button.trigger); + } + if (button.dataAttributes) { + if (Object.keys(button.dataAttributes).length > 0) { + Object.keys(button.dataAttributes).map(function(key, index) { + $button.attr('data-' + key, button.dataAttributes[key]); + }); + } + } + if (button.icon) { + $button.prepend('<span class="t3js-modal-icon-placeholder" data-icon="' + button.icon + '"></span>'); + } + currentModal.find(Modal.identifiers.footer).append($button); + } + currentModal + .find(Modal.identifiers.footer).find('button') + .on('click', function() { + $(this).trigger('button.clicked'); + }); - } else { - currentModal.find(Modal.identifiers.footer).remove(); - } + } else { + currentModal.find(Modal.identifiers.footer).remove(); + } - currentModal.on('shown.bs.modal', function() { - // focus the button which was configured as active button - $(this).find(Modal.identifiers.footer).find('.t3js-active').first().focus(); - // Get Icons - $(this).find(Modal.identifiers.iconPlaceholder).each(function() { - Icons.getIcon($(this).data('icon'), Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) { - Modal.currentModal.find(Modal.identifiers.iconPlaceholder + '[data-icon=' + $(icon).data('identifier') + ']').replaceWith(icon); - }); - }); - }); + currentModal.on('shown.bs.modal', function() { + // focus the button which was configured as active button + $(this).find(Modal.identifiers.footer).find('.t3js-active').first().focus(); + // Get Icons + $(this).find(Modal.identifiers.iconPlaceholder).each(function() { + Icons.getIcon($(this).data('icon'), Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) { + Modal.currentModal.find(Modal.identifiers.iconPlaceholder + '[data-icon=' + $(icon).data('identifier') + ']').replaceWith(icon); + }); + }); + }); - // Remove modal from Modal.instances when hidden - currentModal.on('hidden.bs.modal', function() { - if (Modal.instances.length > 0) { - var lastIndex = Modal.instances.length-1; - Modal.instances.splice(lastIndex, 1); - Modal.currentModal = Modal.instances[lastIndex-1]; - } - currentModal.trigger('modal-destroyed'); - $(this).remove(); - // Keep class modal-open on body tag as long as open modals exist - if (Modal.instances.length > 0) { - $('body').addClass('modal-open'); - } - }); + // Remove modal from Modal.instances when hidden + currentModal.on('hidden.bs.modal', function() { + if (Modal.instances.length > 0) { + var lastIndex = Modal.instances.length - 1; + Modal.instances.splice(lastIndex, 1); + Modal.currentModal = Modal.instances[lastIndex - 1]; + } + currentModal.trigger('modal-destroyed'); + $(this).remove(); + // Keep class modal-open on body tag as long as open modals exist + if (Modal.instances.length > 0) { + $('body').addClass('modal-open'); + } + }); - // When modal is opened/shown add it to Modal.instances and make it Modal.currentModal - currentModal.on('show.bs.modal', function() { - Modal.currentModal = $(this); - Modal.instances.push(Modal.currentModal); - }); - currentModal.on('modal-dismiss', function() { - // Hide modal, the bs.modal events will clean up Modal.instances - $(this).modal('hide'); - }); + // When modal is opened/shown add it to Modal.instances and make it Modal.currentModal + currentModal.on('show.bs.modal', function() { + Modal.currentModal = $(this); + Modal.instances.push(Modal.currentModal); + }); + currentModal.on('modal-dismiss', function() { + // Hide modal, the bs.modal events will clean up Modal.instances + $(this).modal('hide'); + }); - if (callback) { - callback(currentModal); - } + if (callback) { + callback(currentModal); + } - return currentModal.modal(); - }; + return currentModal.modal(); + }; - /** - * Close the current open modal - */ - Modal.dismiss = function() { - if (Modal.currentModal) { - Modal.currentModal.modal('hide'); - } - }; + /** + * Close the current open modal + */ + Modal.dismiss = function() { + if (Modal.currentModal) { + Modal.currentModal.modal('hide'); + } + }; - /** - * Initialize markup with data attributes - * - * @param {object} theDocument - */ - Modal.initializeMarkupTrigger = function(theDocument) { - $(theDocument).on('click', '.t3js-modal-trigger', function(evt) { - evt.preventDefault(); - var $element = $(this); - var url = $element.data('url') || null; - var content = $element.data('content') || 'Are you sure?'; - var severity = typeof Severity[$element.data('severity')] !== 'undefined' ? Severity[$element.data('severity')] : Severity.info; - if (url !== null) { - var separator = (url.indexOf('?') > -1) ? '&' : '?'; - var params = $.param({data: $element.data()}); - url = url + separator + params; - } - Modal.advanced({ - type: url !== null ? Modal.types.ajax : Modal.types.default, - title: $element.data('title') || 'Alert', - content: url !== null ? url : content, - severity: severity, - buttons: [ - { - text: $element.data('button-close-text') || 'Close', - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.currentModal.trigger('modal-dismiss'); - } - }, - { - text: $element.data('button-ok-text') || 'OK', - btnClass: 'btn-' + Severity.getCssClass(severity), - trigger: function() { - Modal.currentModal.trigger('modal-dismiss'); - evt.target.ownerDocument.location.href = $element.data('href') || $element.attr('href'); - } - } - ] - }); - }); - }; + /** + * Initialize markup with data attributes + * + * @param {object} theDocument + */ + Modal.initializeMarkupTrigger = function(theDocument) { + $(theDocument).on('click', '.t3js-modal-trigger', function(evt) { + evt.preventDefault(); + var $element = $(this); + var url = $element.data('url') || null; + var content = $element.data('content') || 'Are you sure?'; + var severity = typeof Severity[$element.data('severity')] !== 'undefined' ? Severity[$element.data('severity')] : Severity.info; + if (url !== null) { + var separator = (url.indexOf('?') > -1) ? '&' : '?'; + var params = $.param({data: $element.data()}); + url = url + separator + params; + } + Modal.advanced({ + type: url !== null ? Modal.types.ajax : Modal.types.default, + title: $element.data('title') || 'Alert', + content: url !== null ? url : content, + severity: severity, + buttons: [ + { + text: $element.data('button-close-text') || 'Close', + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }, + { + text: $element.data('button-ok-text') || 'OK', + btnClass: 'btn-' + Severity.getCssClass(severity), + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + evt.target.ownerDocument.location.href = $element.data('href') || $element.attr('href'); + } + } + ] + }); + }); + }; - /** - * Custom event, fired if modal gets closed - */ - $(document).on('modal-dismiss', Modal.dismiss); + /** + * Custom event, fired if modal gets closed + */ + $(document).on('modal-dismiss', Modal.dismiss); - Modal.initializeMarkupTrigger(document); + Modal.initializeMarkupTrigger(document); - // expose as global object - TYPO3.Modal = Modal; + // expose as global object + TYPO3.Modal = Modal; - return Modal; + return Modal; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js index 90e2371d250a77dcf3ed91ca96fdb2faf0609689..94e94a2f369cf039f180e8e91782b31c0476fa36 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js @@ -16,413 +16,413 @@ * Class to render the module menu and handle the BE navigation */ require( - [ - 'jquery', - 'TYPO3/CMS/Backend/Storage/Persistent', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Viewport', - 'TYPO3/CMS/Backend/Event/ClientRequest', - 'TYPO3/CMS/Backend/Event/TriggerRequest' - ], - function ($, PersistentStorage, Icons, Viewport, ClientRequest, TriggerRequest) { - if (typeof TYPO3.ModuleMenu !== 'undefined') { - return TYPO3.ModuleMenu.App; - } - - TYPO3.ModuleMenu = {}; - TYPO3.ModuleMenu.App = { - loadedModule: null, - loadedNavigationComponentId: '', - - initialize: function () { - var me = this; - - var deferred = $.Deferred(); - deferred.resolve(); - - // load the start module - if (top.startInModule && top.startInModule[0] && $('#' + top.startInModule[0]).length > 0) { - deferred = me.showModule( - top.startInModule[0], - top.startInModule[1] - ); - } else { - // fetch first module - if ($('.t3js-mainmodule:first').attr('id')) { - deferred = me.showModule( - $('.t3js-mainmodule:first').attr('id') - ); - } - // else case: the main module has no entries, this is probably a backend - // user with very little access rights, maybe only the logout button and - // a user settings module in topbar. - } - - deferred.then(function() { - // check if module menu should be collapsed or not - var state = PersistentStorage.get('BackendComponents.States.typo3-module-menu'); - if (state && state.collapsed) { - TYPO3.ModuleMenu.App.toggleMenu(state.collapsed === 'true'); - } - - // check if there are collapsed items in the users' configuration - var collapsedMainMenuItems = me.getCollapsedMainMenuItems(); - $.each(collapsedMainMenuItems, function (key, itm) { - if (itm !== true) { - return; - } - var $group = $('#' + key); - if ($group.length > 0) { - var $groupContainer = $group.find('.modulemenu-group-container'); - $group.addClass('collapsed').removeClass('expanded'); - TYPO3.Backend.NavigationContainer.cleanup(); - $groupContainer.hide().promise().done(function () { - TYPO3.Backend.doLayout(); - }); - } - }); - me.initializeEvents(); - }); - }, - - initializeEvents: function () { - var me = this; - $(document).on('click', '.modulemenu-group .modulemenu-group-header', function () { - var $group = $(this).parent('.modulemenu-group'); - var $groupContainer = $group.find('.modulemenu-group-container'); - - TYPO3.Backend.NavigationContainer.cleanup(); - if ($group.hasClass('expanded')) { - me.addCollapsedMainMenuItem($group.attr('id')); - $group.addClass('collapsed').removeClass('expanded'); - $groupContainer.stop().slideUp().promise().done(function () { - TYPO3.Backend.doLayout(); - }); - } else { - me.removeCollapseMainMenuItem($group.attr('id')); - $group.addClass('expanded').removeClass('collapsed'); - $groupContainer.stop().slideDown().promise().done(function () { - TYPO3.Backend.doLayout(); - }); - } - - }); - // register clicking on sub modules - $(document).on('click', '.modulemenu-item,.t3-menuitem-submodule', function (evt) { - evt.preventDefault(); - me.showModule( - $(this).attr('id'), - '', - evt - ); - }); - $(document).on('click', '.t3js-topbar-button-modulemenu', - function (evt) { - evt.preventDefault(); - TYPO3.ModuleMenu.App.toggleMenu(); - } - ); - $(document).on('click', '.t3js-scaffold-content-overlay', - function (evt) { - evt.preventDefault(); - TYPO3.ModuleMenu.App.toggleMenu(true); - } - ); - $(document).on('click', '.t3js-topbar-button-navigationcomponent', - function (evt) { - evt.preventDefault(); - TYPO3.Backend.NavigationContainer.toggle(); - } - ); - }, - - /** - * @param {Boolean} collapse - */ - toggleMenu: function (collapse) { - TYPO3.Backend.NavigationContainer.cleanup(); - - var $mainContainer = $('.t3js-scaffold'); - var expandedClass = 'scaffold-modulemenu-expanded'; - - if (typeof collapse === 'undefined') { - collapse = $mainContainer.hasClass(expandedClass); - } - $mainContainer.toggleClass(expandedClass, !collapse); - if (!collapse) { - $('.scaffold') - .removeClass('scaffold-search-expanded') - .removeClass('scaffold-toolbar-expanded'); - } - - // Persist collapsed state in the UC of the current user - PersistentStorage.set( - 'BackendComponents.States.typo3-module-menu', - { - collapsed: collapse - } - ); - - TYPO3.Backend.doLayout(); - }, - - /** - * Gets the module properties from module menu markup (data attributes) - * - * @param {string} name module name e.g. web_list - * @return {Object} - */ - getRecordFromName: function (name) { - var $subModuleElement = $('#' + name); - return { - name: name, - navigationComponentId: $subModuleElement.data('navigationcomponentid'), - navigationFrameScript: $subModuleElement.data('navigationframescript'), - navigationFrameScriptParam: $subModuleElement.data('navigationframescriptparameters'), - link: $subModuleElement.find('a').data('link') - }; - }, - - /** - * Event handler called after clicking on the module menu item - * - * @param {string} name module name e.g. web_layout - * @param {string} params - * @param {Event} [event] - * @return {jQuery.Deferred} - */ - showModule: function (name, params, event) { - params = params || ''; - var moduleData = this.getRecordFromName(name); - return this.loadModuleComponents( - moduleData, - params, - new ClientRequest('typo3.showModule', event) - ); - }, - - ensurePageInTreeSelected: function () { - if (this.loadedNavigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement' - && this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].isInitialized() - ) { - this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].selectRequestedPageId(); - } - }, - - /** - * Shows requested module (e.g. list/page) - * - * @param {Object} moduleData - * @param {string} params - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - loadModuleComponents: function (moduleData, params, interactionRequest) { - var moduleName = moduleData.name; - - // Allow other components e.g. Formengine to cancel switching between modules - // (e.g. you have unsaved changes in the form) - var deferred = TYPO3.Backend.ContentContainer.beforeSetUrl(interactionRequest); - deferred.then( - $.proxy(function() { - if (moduleData.navigationComponentId) { - this.loadNavigationComponent(moduleData.navigationComponentId); - } else if (moduleData.navigationFrameScript) { - TYPO3.Backend.NavigationContainer.show('typo3-navigationIframe'); - this.openInNavFrame( - moduleData.navigationFrameScript, - moduleData.navigationFrameScriptParam, - new TriggerRequest( - 'typo3.loadModuleComponents', - interactionRequest - ) - ); - } else { - TYPO3.Backend.NavigationContainer.hide(); - } - - this.highlightModuleMenuItem(moduleName); - this.loadedModule = moduleName; - params = this.includeId(moduleData, params); - this.openInContentFrame( - moduleData.link, - params, - new TriggerRequest( - 'typo3.loadModuleComponents', - interactionRequest - ) - ); - - // compatibility - top.currentSubScript = moduleData.link; - top.currentModuleLoaded = moduleName; - - TYPO3.Backend.doLayout(); - this.ensurePageInTreeSelected(); - }, this - )); - - return deferred; - }, - - /** - * Prepends previously saved record id to the url params - * - * @param {Object} moduleData - * @param {string} params query string parameters for module url - * @return {string} - */ - includeId: function (moduleData, params) { - if (!moduleData.navigationComponentId && !moduleData.navigationFrameScript) { - return params; - } - //get id - var section = ''; - if (moduleData.navigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement') { - section = 'web'; - } else { - section = moduleData.name.split('_')[0]; - } - if (top.fsMod.recentIds[section]) { - params = 'id=' + top.fsMod.recentIds[section] + '&' + params; - } - - return params; - }, - - /** - * Renders registered (non-iframe) navigation component e.g. a page tree - * - * @param {string} navigationComponentId - */ - loadNavigationComponent: function (navigationComponentId) { - TYPO3.Backend.NavigationContainer.show(navigationComponentId); - if (navigationComponentId === this.loadedNavigationComponentId) { - return; - } - var componentCssName = navigationComponentId.replace(/[/]/g, '_'); - if (this.loadedNavigationComponentId !== '') { - $('#navigationComponent-' + this.loadedNavigationComponentId.replace(/[/]/g, '_')).hide(); - } - if ($('.t3js-scaffold-content-navigation [data-component="' + navigationComponentId + '"]').length < 1) { - $('.t3js-scaffold-content-navigation') - .append('<div class="scaffold-content-navigation-component" data-component="' + navigationComponentId + '" id="navigationComponent-' + componentCssName + '"></div>'); - } - - require([navigationComponentId], function (NavigationComponent) { - NavigationComponent.initialize('#navigationComponent-' + componentCssName); - TYPO3.Backend.NavigationContainer.show(navigationComponentId); - self.loadedNavigationComponentId = navigationComponentId; - }); - }, - - /** - * @param {string} url - * @param {string} params - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - openInNavFrame: function (url, params, interactionRequest) { - var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : ''); - var currentUrl = TYPO3.Backend.NavigationContainer.getUrl(); - var deferred = TYPO3.Backend.NavigationContainer.setUrl( - url, - new TriggerRequest('typo3.openInNavFrame', interactionRequest) - ); - if (currentUrl !== navUrl) { - // if deferred is already resolved, execute directly - if (deferred.state() === 'resolved') { - TYPO3.Backend.NavigationContainer.refresh(); - // otherwise hand in future callback - } else { - deferred.then(TYPO3.Backend.NavigationContainer.refresh); - } - } - return deferred; - }, - - /** - * @param {string} url - * @param {string} params - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - openInContentFrame: function (url, params, interactionRequest) { - var deferred; - - if (top.nextLoadModuleUrl) { - deferred = TYPO3.Backend.ContentContainer.setUrl( - top.nextLoadModuleUrl, - new TriggerRequest('typo3.openInContentFrame', interactionRequest) - ); - top.nextLoadModuleUrl = ''; - } else { - var urlToLoad = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : ''); - deferred = TYPO3.Backend.ContentContainer.setUrl( - urlToLoad, - new TriggerRequest('typo3.openInContentFrame', interactionRequest) - ); - } - - return deferred; - }, - - highlightModuleMenuItem: function (module, mainModule) { - $('.modulemenu-item.active').removeClass('active'); - $('#' + module).addClass('active'); - }, - - // refresh the HTML by fetching the menu again - refreshMenu: function () { - $.ajax(TYPO3.settings.ajaxUrls['modulemenu']).done(function (result) { - $('#menu').replaceWith(result.menu); - if (top.currentModuleLoaded) { - TYPO3.ModuleMenu.App.highlightModuleMenuItem(top.currentModuleLoaded); - } - TYPO3.Backend.doLayout(); - }); - }, - - reloadFrames: function () { - TYPO3.Backend.NavigationContainer.refresh(); - TYPO3.Backend.ContentContainer.refresh(); - }, - - /** - * fetches all module menu elements in the local storage that should be collapsed - * @returns {*} - */ - getCollapsedMainMenuItems: function () { - if (PersistentStorage.isset('modulemenu')) { - return JSON.parse(PersistentStorage.get('modulemenu')); - } else { - return {}; - } - }, - - /** - * adds a module menu item to the local storage - * @param item - */ - addCollapsedMainMenuItem: function (item) { - var existingItems = this.getCollapsedMainMenuItems(); - existingItems[item] = true; - PersistentStorage.set('modulemenu', JSON.stringify(existingItems)); - }, - - /** - * removes a module menu item from the local storage - * @param item - */ - removeCollapseMainMenuItem: function (item) { - var existingItems = this.getCollapsedMainMenuItems(); - delete existingItems[item]; - PersistentStorage.set('modulemenu', JSON.stringify(existingItems)); - } - - }; - // start the module menu app - TYPO3.ModuleMenu.App.initialize(); - return TYPO3.ModuleMenu; - } + [ + 'jquery', + 'TYPO3/CMS/Backend/Storage/Persistent', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Viewport', + 'TYPO3/CMS/Backend/Event/ClientRequest', + 'TYPO3/CMS/Backend/Event/TriggerRequest' + ], + function($, PersistentStorage, Icons, Viewport, ClientRequest, TriggerRequest) { + if (typeof TYPO3.ModuleMenu !== 'undefined') { + return TYPO3.ModuleMenu.App; + } + + TYPO3.ModuleMenu = {}; + TYPO3.ModuleMenu.App = { + loadedModule: null, + loadedNavigationComponentId: '', + + initialize: function() { + var me = this; + + var deferred = $.Deferred(); + deferred.resolve(); + + // load the start module + if (top.startInModule && top.startInModule[0] && $('#' + top.startInModule[0]).length > 0) { + deferred = me.showModule( + top.startInModule[0], + top.startInModule[1] + ); + } else { + // fetch first module + if ($('.t3js-mainmodule:first').attr('id')) { + deferred = me.showModule( + $('.t3js-mainmodule:first').attr('id') + ); + } + // else case: the main module has no entries, this is probably a backend + // user with very little access rights, maybe only the logout button and + // a user settings module in topbar. + } + + deferred.then(function() { + // check if module menu should be collapsed or not + var state = PersistentStorage.get('BackendComponents.States.typo3-module-menu'); + if (state && state.collapsed) { + TYPO3.ModuleMenu.App.toggleMenu(state.collapsed === 'true'); + } + + // check if there are collapsed items in the users' configuration + var collapsedMainMenuItems = me.getCollapsedMainMenuItems(); + $.each(collapsedMainMenuItems, function(key, itm) { + if (itm !== true) { + return; + } + var $group = $('#' + key); + if ($group.length > 0) { + var $groupContainer = $group.find('.modulemenu-group-container'); + $group.addClass('collapsed').removeClass('expanded'); + TYPO3.Backend.NavigationContainer.cleanup(); + $groupContainer.hide().promise().done(function() { + TYPO3.Backend.doLayout(); + }); + } + }); + me.initializeEvents(); + }); + }, + + initializeEvents: function() { + var me = this; + $(document).on('click', '.modulemenu-group .modulemenu-group-header', function() { + var $group = $(this).parent('.modulemenu-group'); + var $groupContainer = $group.find('.modulemenu-group-container'); + + TYPO3.Backend.NavigationContainer.cleanup(); + if ($group.hasClass('expanded')) { + me.addCollapsedMainMenuItem($group.attr('id')); + $group.addClass('collapsed').removeClass('expanded'); + $groupContainer.stop().slideUp().promise().done(function() { + TYPO3.Backend.doLayout(); + }); + } else { + me.removeCollapseMainMenuItem($group.attr('id')); + $group.addClass('expanded').removeClass('collapsed'); + $groupContainer.stop().slideDown().promise().done(function() { + TYPO3.Backend.doLayout(); + }); + } + + }); + // register clicking on sub modules + $(document).on('click', '.modulemenu-item,.t3-menuitem-submodule', function(evt) { + evt.preventDefault(); + me.showModule( + $(this).attr('id'), + '', + evt + ); + }); + $(document).on('click', '.t3js-topbar-button-modulemenu', + function(evt) { + evt.preventDefault(); + TYPO3.ModuleMenu.App.toggleMenu(); + } + ); + $(document).on('click', '.t3js-scaffold-content-overlay', + function(evt) { + evt.preventDefault(); + TYPO3.ModuleMenu.App.toggleMenu(true); + } + ); + $(document).on('click', '.t3js-topbar-button-navigationcomponent', + function(evt) { + evt.preventDefault(); + TYPO3.Backend.NavigationContainer.toggle(); + } + ); + }, + + /** + * @param {Boolean} collapse + */ + toggleMenu: function(collapse) { + TYPO3.Backend.NavigationContainer.cleanup(); + + var $mainContainer = $('.t3js-scaffold'); + var expandedClass = 'scaffold-modulemenu-expanded'; + + if (typeof collapse === 'undefined') { + collapse = $mainContainer.hasClass(expandedClass); + } + $mainContainer.toggleClass(expandedClass, !collapse); + if (!collapse) { + $('.scaffold') + .removeClass('scaffold-search-expanded') + .removeClass('scaffold-toolbar-expanded'); + } + + // Persist collapsed state in the UC of the current user + PersistentStorage.set( + 'BackendComponents.States.typo3-module-menu', + { + collapsed: collapse + } + ); + + TYPO3.Backend.doLayout(); + }, + + /** + * Gets the module properties from module menu markup (data attributes) + * + * @param {string} name module name e.g. web_list + * @return {Object} + */ + getRecordFromName: function(name) { + var $subModuleElement = $('#' + name); + return { + name: name, + navigationComponentId: $subModuleElement.data('navigationcomponentid'), + navigationFrameScript: $subModuleElement.data('navigationframescript'), + navigationFrameScriptParam: $subModuleElement.data('navigationframescriptparameters'), + link: $subModuleElement.find('a').data('link') + }; + }, + + /** + * Event handler called after clicking on the module menu item + * + * @param {string} name module name e.g. web_layout + * @param {string} params + * @param {Event} [event] + * @return {jQuery.Deferred} + */ + showModule: function(name, params, event) { + params = params || ''; + var moduleData = this.getRecordFromName(name); + return this.loadModuleComponents( + moduleData, + params, + new ClientRequest('typo3.showModule', event) + ); + }, + + ensurePageInTreeSelected: function() { + if (this.loadedNavigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement' + && this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].isInitialized() + ) { + this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].selectRequestedPageId(); + } + }, + + /** + * Shows requested module (e.g. list/page) + * + * @param {Object} moduleData + * @param {string} params + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + loadModuleComponents: function(moduleData, params, interactionRequest) { + var moduleName = moduleData.name; + + // Allow other components e.g. Formengine to cancel switching between modules + // (e.g. you have unsaved changes in the form) + var deferred = TYPO3.Backend.ContentContainer.beforeSetUrl(interactionRequest); + deferred.then( + $.proxy(function() { + if (moduleData.navigationComponentId) { + this.loadNavigationComponent(moduleData.navigationComponentId); + } else if (moduleData.navigationFrameScript) { + TYPO3.Backend.NavigationContainer.show('typo3-navigationIframe'); + this.openInNavFrame( + moduleData.navigationFrameScript, + moduleData.navigationFrameScriptParam, + new TriggerRequest( + 'typo3.loadModuleComponents', + interactionRequest + ) + ); + } else { + TYPO3.Backend.NavigationContainer.hide(); + } + + this.highlightModuleMenuItem(moduleName); + this.loadedModule = moduleName; + params = this.includeId(moduleData, params); + this.openInContentFrame( + moduleData.link, + params, + new TriggerRequest( + 'typo3.loadModuleComponents', + interactionRequest + ) + ); + + // compatibility + top.currentSubScript = moduleData.link; + top.currentModuleLoaded = moduleName; + + TYPO3.Backend.doLayout(); + this.ensurePageInTreeSelected(); + }, this + )); + + return deferred; + }, + + /** + * Prepends previously saved record id to the url params + * + * @param {Object} moduleData + * @param {string} params query string parameters for module url + * @return {string} + */ + includeId: function(moduleData, params) { + if (!moduleData.navigationComponentId && !moduleData.navigationFrameScript) { + return params; + } + //get id + var section = ''; + if (moduleData.navigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement') { + section = 'web'; + } else { + section = moduleData.name.split('_')[0]; + } + if (top.fsMod.recentIds[section]) { + params = 'id=' + top.fsMod.recentIds[section] + '&' + params; + } + + return params; + }, + + /** + * Renders registered (non-iframe) navigation component e.g. a page tree + * + * @param {string} navigationComponentId + */ + loadNavigationComponent: function(navigationComponentId) { + TYPO3.Backend.NavigationContainer.show(navigationComponentId); + if (navigationComponentId === this.loadedNavigationComponentId) { + return; + } + var componentCssName = navigationComponentId.replace(/[/]/g, '_'); + if (this.loadedNavigationComponentId !== '') { + $('#navigationComponent-' + this.loadedNavigationComponentId.replace(/[/]/g, '_')).hide(); + } + if ($('.t3js-scaffold-content-navigation [data-component="' + navigationComponentId + '"]').length < 1) { + $('.t3js-scaffold-content-navigation') + .append('<div class="scaffold-content-navigation-component" data-component="' + navigationComponentId + '" id="navigationComponent-' + componentCssName + '"></div>'); + } + + require([navigationComponentId], function(NavigationComponent) { + NavigationComponent.initialize('#navigationComponent-' + componentCssName); + TYPO3.Backend.NavigationContainer.show(navigationComponentId); + self.loadedNavigationComponentId = navigationComponentId; + }); + }, + + /** + * @param {string} url + * @param {string} params + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + openInNavFrame: function(url, params, interactionRequest) { + var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : ''); + var currentUrl = TYPO3.Backend.NavigationContainer.getUrl(); + var deferred = TYPO3.Backend.NavigationContainer.setUrl( + url, + new TriggerRequest('typo3.openInNavFrame', interactionRequest) + ); + if (currentUrl !== navUrl) { + // if deferred is already resolved, execute directly + if (deferred.state() === 'resolved') { + TYPO3.Backend.NavigationContainer.refresh(); + // otherwise hand in future callback + } else { + deferred.then(TYPO3.Backend.NavigationContainer.refresh); + } + } + return deferred; + }, + + /** + * @param {string} url + * @param {string} params + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + openInContentFrame: function(url, params, interactionRequest) { + var deferred; + + if (top.nextLoadModuleUrl) { + deferred = TYPO3.Backend.ContentContainer.setUrl( + top.nextLoadModuleUrl, + new TriggerRequest('typo3.openInContentFrame', interactionRequest) + ); + top.nextLoadModuleUrl = ''; + } else { + var urlToLoad = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : ''); + deferred = TYPO3.Backend.ContentContainer.setUrl( + urlToLoad, + new TriggerRequest('typo3.openInContentFrame', interactionRequest) + ); + } + + return deferred; + }, + + highlightModuleMenuItem: function(module, mainModule) { + $('.modulemenu-item.active').removeClass('active'); + $('#' + module).addClass('active'); + }, + + // refresh the HTML by fetching the menu again + refreshMenu: function() { + $.ajax(TYPO3.settings.ajaxUrls['modulemenu']).done(function(result) { + $('#menu').replaceWith(result.menu); + if (top.currentModuleLoaded) { + TYPO3.ModuleMenu.App.highlightModuleMenuItem(top.currentModuleLoaded); + } + TYPO3.Backend.doLayout(); + }); + }, + + reloadFrames: function() { + TYPO3.Backend.NavigationContainer.refresh(); + TYPO3.Backend.ContentContainer.refresh(); + }, + + /** + * fetches all module menu elements in the local storage that should be collapsed + * @returns {*} + */ + getCollapsedMainMenuItems: function() { + if (PersistentStorage.isset('modulemenu')) { + return JSON.parse(PersistentStorage.get('modulemenu')); + } else { + return {}; + } + }, + + /** + * adds a module menu item to the local storage + * @param item + */ + addCollapsedMainMenuItem: function(item) { + var existingItems = this.getCollapsedMainMenuItems(); + existingItems[item] = true; + PersistentStorage.set('modulemenu', JSON.stringify(existingItems)); + }, + + /** + * removes a module menu item from the local storage + * @param item + */ + removeCollapseMainMenuItem: function(item) { + var existingItems = this.getCollapsedMainMenuItems(); + delete existingItems[item]; + PersistentStorage.set('modulemenu', JSON.stringify(existingItems)); + } + + }; + // start the module menu app + TYPO3.ModuleMenu.App.initialize(); + return TYPO3.ModuleMenu; + } ); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js b/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js index 7de0e7deaebd6706b820ac7e7e03b65e7fded9c8..5af8fb1859bd2b46f7bd0f33f63bfa8d163e6db2 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js @@ -16,57 +16,57 @@ * JavaScript functions for creating multiple pages */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - /** - * @type {{lineCounter: number, containerSelector: string, addMoreFieldsButtonSelector: string, doktypeSelector: string}} - * @exports TYPO3/CMS/Backend/NewMultiplePages - */ - var NewMultiplePages = { - lineCounter: 5, - containerSelector: '.t3js-newmultiplepages-container', - addMoreFieldsButtonSelector: '.t3js-newmultiplepages-createnewfields', - doktypeSelector: '.t3js-newmultiplepages-select-doktype', - templateRow: '.t3js-newmultiplepages-newlinetemplate' - }; + /** + * @type {{lineCounter: number, containerSelector: string, addMoreFieldsButtonSelector: string, doktypeSelector: string}} + * @exports TYPO3/CMS/Backend/NewMultiplePages + */ + var NewMultiplePages = { + lineCounter: 5, + containerSelector: '.t3js-newmultiplepages-container', + addMoreFieldsButtonSelector: '.t3js-newmultiplepages-createnewfields', + doktypeSelector: '.t3js-newmultiplepages-select-doktype', + templateRow: '.t3js-newmultiplepages-newlinetemplate' + }; - /** - * Add further input rows - */ - NewMultiplePages.createNewFormFields = function() { - for (var i = 0; i < 5; i++) { - var label = NewMultiplePages.lineCounter + i + 1; - var line = $(NewMultiplePages.templateRow).html() - .replace(/\[0\]/g, (NewMultiplePages.lineCounter + i)) - .replace(/\[1\]/g, label); - $(line).appendTo(NewMultiplePages.containerSelector); - } - NewMultiplePages.lineCounter += 5; - }; + /** + * Add further input rows + */ + NewMultiplePages.createNewFormFields = function() { + for (var i = 0; i < 5; i++) { + var label = NewMultiplePages.lineCounter + i + 1; + var line = $(NewMultiplePages.templateRow).html() + .replace(/\[0\]/g, (NewMultiplePages.lineCounter + i)) + .replace(/\[1\]/g, label); + $(line).appendTo(NewMultiplePages.containerSelector); + } + NewMultiplePages.lineCounter += 5; + }; - /** - * @param {Object} $selectElement - */ - NewMultiplePages.actOnTypeSelectChange = function($selectElement) { - var $optionElement = $selectElement.find(':selected'); - var $target = $($selectElement.data('target')); - $target.html($optionElement.data('icon')); - }; + /** + * @param {Object} $selectElement + */ + NewMultiplePages.actOnTypeSelectChange = function($selectElement) { + var $optionElement = $selectElement.find(':selected'); + var $target = $($selectElement.data('target')); + $target.html($optionElement.data('icon')); + }; - /** - * Register listeners - */ - NewMultiplePages.initializeEvents = function() { - $(NewMultiplePages.addMoreFieldsButtonSelector).on('click', function() { - NewMultiplePages.createNewFormFields(); - }); + /** + * Register listeners + */ + NewMultiplePages.initializeEvents = function() { + $(NewMultiplePages.addMoreFieldsButtonSelector).on('click', function() { + NewMultiplePages.createNewFormFields(); + }); - $(document).on('change', NewMultiplePages.doktypeSelector, function() { - NewMultiplePages.actOnTypeSelectChange($(this)); - }); - }; + $(document).on('change', NewMultiplePages.doktypeSelector, function() { + NewMultiplePages.actOnTypeSelectChange($(this)); + }); + }; - $(NewMultiplePages.initializeEvents); + $(NewMultiplePages.initializeEvents); - return NewMultiplePages; + return NewMultiplePages; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js b/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js index 22b39834ddd2b72cb7648640ac9499c020270f52..845cd07dbae3e0d74d567292ec22d3076b97a935 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js @@ -18,208 +18,207 @@ * @deprecation: Severity got its own AMD module, it is required here only for * backwards compatibility reasons */ -define(['jquery', 'TYPO3/CMS/Backend/Severity'], function ($) { - 'use strict'; - - try { - // fetch from parent - if (parent && parent.window.TYPO3 && parent.window.TYPO3.Notification) { - return parent.window.TYPO3.Notification; - } - - // fetch object from outer frame - if (top && top.TYPO3.Notification) { - return top.TYPO3.Notification; - } - } catch (e) { - // This only happens if the opener, parent or top is some other url (eg a local file) - // which loaded the current window. Then the browser's cross domain policy jumps in - // and raises an exception. - // For this case we are safe and we can create our global object below. - } - - /** - * The main Notification object - * - * @type {{NOTICE: number, INFO: number, OK: number, WARNING: number, ERROR: number, messageContainer: null, duration: number}} - * @exports TYPO3/CMS/Backend/Notification - */ - var Notification = { - NOTICE: -2, - INFO: -1, - OK: 0, - WARNING: 1, - ERROR: 2, - messageContainer: null, - duration: 5 - }; - - /** - * Show a notice notification - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky - * - * @public - */ - Notification.notice = function(title, message, duration) { - Notification.showMessage(title, message, Notification.NOTICE, duration); - }; - - /** - * Show an info notification - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky - * - * @public - */ - Notification.info = function(title, message, duration) { - Notification.showMessage(title, message, Notification.INFO, duration); - }; - - /** - * Show an ok notification - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky - * - * @public - */ - Notification.success = function(title, message, duration) { - Notification.showMessage(title, message, Notification.OK, duration); - }; - - /** - * Show a warning notification - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky - * - * @public - */ - Notification.warning = function(title, message, duration) { - Notification.showMessage(title, message, Notification.WARNING, duration); - }; - - /** - * Show an error notification - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {float} duration Time in seconds to show notification before it disappears, default 0, 0 = sticky - * - * @public - */ - Notification.error = function(title, message, duration) { - duration = duration || 0; - Notification.showMessage(title, message, Notification.ERROR, duration); - }; - - /** - * Show message - * - * @param {String} title The title for the notification - * @param {String} message The message for the notification - * @param {int} severity See constants in this object - * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky - * - * @private - */ - Notification.showMessage = function(title, message, severity, duration) { - var className = ''; - var icon = ''; - switch (severity) { - case Notification.NOTICE: - className = 'notice'; - icon = 'lightbulb-o'; - break; - case Notification.INFO: - className = 'info'; - icon = 'info'; - break; - case Notification.OK: - className = 'success'; - icon = 'check'; - break; - case Notification.WARNING: - className = 'warning'; - icon = 'exclamation'; - break; - case Notification.ERROR: - className = 'danger'; - icon = 'times'; - break; - default: - className = 'info'; - icon = 'info'; - } - - duration = (typeof duration === 'undefined') ? Notification.duration : parseFloat(duration); - - if (Notification.messageContainer === null) { - Notification.messageContainer = $('<div id="alert-container"></div>').appendTo('body'); - } - var $box = $( - '<div class="alert alert-' + className + ' alert-dismissible fade" role="alert">' + - '<button type="button" class="close" data-dismiss="alert">' + - '<span aria-hidden="true"><i class="fa fa-times-circle"></i></span>' + - '<span class="sr-only">Close</span>' + - '</button>' + - '<div class="media">' + - '<div class="media-left">' + - '<span class="fa-stack fa-lg">' + - '<i class="fa fa-circle fa-stack-2x"></i>' + - '<i class="fa fa-' + icon + ' fa-stack-1x"></i>' + - '</span>' + - '</div>' + - '<div class="media-body">' + - '<h4 class="alert-title"></h4>' + - '<p class="alert-message text-pre-wrap"></p>' + - '</div>' + - '</div>' + - '</div>' - ); - $box.find('.alert-title').text(title); - $box.find('.alert-message').text(message); - $box.on('close.bs.alert', function(e) { - e.preventDefault(); - $(this) - .clearQueue() - .queue(function(next) { - $(this).removeClass('in'); - next(); - }) - .slideUp(function () { - $(this).remove(); - }); - }); - $box.appendTo(Notification.messageContainer); - $box.delay('fast') - .queue(function(next) { - $(this).addClass('in'); - next(); - }); - // if duration > 0 dismiss alert - if (duration > 0) { - $box.delay(duration * 1000) - .queue(function(next) { - $(this).alert('close'); - next(); - }); - } - }; - - - - // attach to global frame - if (typeof TYPO3 !== 'undefined') { - TYPO3.Notification = Notification; - } - - return Notification; +define(['jquery', 'TYPO3/CMS/Backend/Severity'], function($) { + 'use strict'; + + try { + // fetch from parent + if (parent && parent.window.TYPO3 && parent.window.TYPO3.Notification) { + return parent.window.TYPO3.Notification; + } + + // fetch object from outer frame + if (top && top.TYPO3.Notification) { + return top.TYPO3.Notification; + } + } catch (e) { + // This only happens if the opener, parent or top is some other url (eg a local file) + // which loaded the current window. Then the browser's cross domain policy jumps in + // and raises an exception. + // For this case we are safe and we can create our global object below. + } + + /** + * The main Notification object + * + * @type {{NOTICE: number, INFO: number, OK: number, WARNING: number, ERROR: number, messageContainer: null, duration: number}} + * @exports TYPO3/CMS/Backend/Notification + */ + var Notification = { + NOTICE: -2, + INFO: -1, + OK: 0, + WARNING: 1, + ERROR: 2, + messageContainer: null, + duration: 5 + }; + + /** + * Show a notice notification + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky + * + * @public + */ + Notification.notice = function(title, message, duration) { + Notification.showMessage(title, message, Notification.NOTICE, duration); + }; + + /** + * Show an info notification + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky + * + * @public + */ + Notification.info = function(title, message, duration) { + Notification.showMessage(title, message, Notification.INFO, duration); + }; + + /** + * Show an ok notification + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky + * + * @public + */ + Notification.success = function(title, message, duration) { + Notification.showMessage(title, message, Notification.OK, duration); + }; + + /** + * Show a warning notification + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky + * + * @public + */ + Notification.warning = function(title, message, duration) { + Notification.showMessage(title, message, Notification.WARNING, duration); + }; + + /** + * Show an error notification + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {float} duration Time in seconds to show notification before it disappears, default 0, 0 = sticky + * + * @public + */ + Notification.error = function(title, message, duration) { + duration = duration || 0; + Notification.showMessage(title, message, Notification.ERROR, duration); + }; + + /** + * Show message + * + * @param {String} title The title for the notification + * @param {String} message The message for the notification + * @param {int} severity See constants in this object + * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky + * + * @private + */ + Notification.showMessage = function(title, message, severity, duration) { + var className = ''; + var icon = ''; + switch (severity) { + case Notification.NOTICE: + className = 'notice'; + icon = 'lightbulb-o'; + break; + case Notification.INFO: + className = 'info'; + icon = 'info'; + break; + case Notification.OK: + className = 'success'; + icon = 'check'; + break; + case Notification.WARNING: + className = 'warning'; + icon = 'exclamation'; + break; + case Notification.ERROR: + className = 'danger'; + icon = 'times'; + break; + default: + className = 'info'; + icon = 'info'; + } + + duration = (typeof duration === 'undefined') ? Notification.duration : parseFloat(duration); + + if (Notification.messageContainer === null) { + Notification.messageContainer = $('<div id="alert-container"></div>').appendTo('body'); + } + var $box = $( + '<div class="alert alert-' + className + ' alert-dismissible fade" role="alert">' + + '<button type="button" class="close" data-dismiss="alert">' + + '<span aria-hidden="true"><i class="fa fa-times-circle"></i></span>' + + '<span class="sr-only">Close</span>' + + '</button>' + + '<div class="media">' + + '<div class="media-left">' + + '<span class="fa-stack fa-lg">' + + '<i class="fa fa-circle fa-stack-2x"></i>' + + '<i class="fa fa-' + icon + ' fa-stack-1x"></i>' + + '</span>' + + '</div>' + + '<div class="media-body">' + + '<h4 class="alert-title"></h4>' + + '<p class="alert-message text-pre-wrap"></p>' + + '</div>' + + '</div>' + + '</div>' + ); + $box.find('.alert-title').text(title); + $box.find('.alert-message').text(message); + $box.on('close.bs.alert', function(e) { + e.preventDefault(); + $(this) + .clearQueue() + .queue(function(next) { + $(this).removeClass('in'); + next(); + }) + .slideUp(function() { + $(this).remove(); + }); + }); + $box.appendTo(Notification.messageContainer); + $box.delay('fast') + .queue(function(next) { + $(this).addClass('in'); + next(); + }); + // if duration > 0 dismiss alert + if (duration > 0) { + $box.delay(duration * 1000) + .queue(function(next) { + $(this).alert('close'); + next(); + }); + } + }; + + + // attach to global frame + if (typeof TYPO3 !== 'undefined') { + TYPO3.Notification = Notification; + } + + return Notification; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js b/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js index 314726ff407ad9ce98d4918ceeeb9ef72ac52f56..c9d305139116e3abb1dc6153b5bfb98ca8dda4d4 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js @@ -16,117 +16,117 @@ * Javascript for show the online media dialog */ define(['jquery', - 'nprogress', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Lang/Lang' - ], function($, NProgress, Modal, Severity) { - 'use strict'; + 'nprogress', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Lang/Lang' +], function($, NProgress, Modal, Severity) { + 'use strict'; - /** - * - * @param element - * @constructor - * @exports TYPO3/CMS/Backend/OnlineMedia - */ - var OnlineMediaPlugin = function(element) { - var me = this; - me.$btn = $(element); - me.target = me.$btn.data('target-folder'); - me.irreObjectUid = me.$btn.data('file-irre-object'); - me.allowed = me.$btn.data('online-media-allowed'); - me.allowedHelpText = me.$btn.data('online-media-allowed-help-text') || 'Allow to embed from sources:'; - me.btnSubmit = me.$btn.data('data-btn-submit') || 'Add'; - me.placeholder = me.$btn.data('placeholder') || 'Paste media url here...'; + /** + * + * @param element + * @constructor + * @exports TYPO3/CMS/Backend/OnlineMedia + */ + var OnlineMediaPlugin = function(element) { + var me = this; + me.$btn = $(element); + me.target = me.$btn.data('target-folder'); + me.irreObjectUid = me.$btn.data('file-irre-object'); + me.allowed = me.$btn.data('online-media-allowed'); + me.allowedHelpText = me.$btn.data('online-media-allowed-help-text') || 'Allow to embed from sources:'; + me.btnSubmit = me.$btn.data('data-btn-submit') || 'Add'; + me.placeholder = me.$btn.data('placeholder') || 'Paste media url here...'; - /** - * - * @param {String} url - */ - me.addOnlineMedia = function(url) { - NProgress.start(); - $.post(TYPO3.settings.ajaxUrls['online_media_create'], - { - url: url, - targetFolder: me.target, - allowed: me.allowed - }, - function(data) { - if (data.file) { - inline.delayedImportElement( - me.irreObjectUid, - 'sys_file', - data.file, - 'file' - ); - } else { - var $confirm = Modal.confirm( - 'ERROR', - data.error, - Severity.error, - [{ - text: TYPO3.lang['button.ok'] || 'OK', - btnClass: 'btn-' + Severity.getCssClass(Severity.error), - name: 'ok', - active: true - }] - ).on('confirm.button.ok', function() { - $confirm.modal('hide'); - }); - } - NProgress.done(); - } - ); - }; + /** + * + * @param {String} url + */ + me.addOnlineMedia = function(url) { + NProgress.start(); + $.post(TYPO3.settings.ajaxUrls['online_media_create'], + { + url: url, + targetFolder: me.target, + allowed: me.allowed + }, + function(data) { + if (data.file) { + inline.delayedImportElement( + me.irreObjectUid, + 'sys_file', + data.file, + 'file' + ); + } else { + var $confirm = Modal.confirm( + 'ERROR', + data.error, + Severity.error, + [{ + text: TYPO3.lang['button.ok'] || 'OK', + btnClass: 'btn-' + Severity.getCssClass(Severity.error), + name: 'ok', + active: true + }] + ).on('confirm.button.ok', function() { + $confirm.modal('hide'); + }); + } + NProgress.done(); + } + ); + }; - /** - * Trigger the modal - */ - me.triggerModal = function() { - var allowedExtMarkup = $.map(me.allowed.split(','), function(ext) { - return '<span class="label label-success">' + ext.toUpperCase() + '</span>'; - }); - var $modal = Modal.show( - me.$btn.attr('title'), - '<div class="form-control-wrap">' + - '<input type="text" class="form-control online-media-url" placeholder="' + me.placeholder + '" />' + - '</div><div class="help-block">' + me.allowedHelpText + '<br>' + allowedExtMarkup.join(' ') + '</div>', - Severity.notice, - [{ - text: me.btnSubmit, - btnClass: 'btn', - name: 'ok', - trigger: function() { - var url = $modal.find('input.online-media-url').val(); - if (url) { - $modal.modal('hide'); - me.addOnlineMedia(url); - } - } - }] - ); + /** + * Trigger the modal + */ + me.triggerModal = function() { + var allowedExtMarkup = $.map(me.allowed.split(','), function(ext) { + return '<span class="label label-success">' + ext.toUpperCase() + '</span>'; + }); + var $modal = Modal.show( + me.$btn.attr('title'), + '<div class="form-control-wrap">' + + '<input type="text" class="form-control online-media-url" placeholder="' + me.placeholder + '" />' + + '</div><div class="help-block">' + me.allowedHelpText + '<br>' + allowedExtMarkup.join(' ') + '</div>', + Severity.notice, + [{ + text: me.btnSubmit, + btnClass: 'btn', + name: 'ok', + trigger: function() { + var url = $modal.find('input.online-media-url').val(); + if (url) { + $modal.modal('hide'); + me.addOnlineMedia(url); + } + } + }] + ); - $modal.on('shown.bs.modal', function() { - // focus the input field - $(this).find('input.online-media-url').first().focus().on('keydown', function(e) { - if (e.keyCode === 13) { - $modal.find('button[name="ok"]').trigger('click'); - } - }); - }); - }; + $modal.on('shown.bs.modal', function() { + // focus the input field + $(this).find('input.online-media-url').first().focus().on('keydown', function(e) { + if (e.keyCode === 13) { + $modal.find('button[name="ok"]').trigger('click'); + } + }); + }); + }; - return {triggerModal: me.triggerModal}; - }; + return {triggerModal: me.triggerModal}; + }; - $(document).on('click', '.t3js-online-media-add-btn', function(evt) { - evt.preventDefault(); - var $this = $(this), - onlineMediaPlugin = $this.data('OnlineMediaPlugin'); - if (!onlineMediaPlugin) { - $this.data('OnlineMediaPlugin', (onlineMediaPlugin = new OnlineMediaPlugin(this))); - } - onlineMediaPlugin.triggerModal(); - }); + $(document).on('click', '.t3js-online-media-add-btn', function(evt) { + evt.preventDefault(); + var $this = $(this), + onlineMediaPlugin = $this.data('OnlineMediaPlugin'); + if (!onlineMediaPlugin) { + $this.data('OnlineMediaPlugin', (onlineMediaPlugin = new OnlineMediaPlugin(this))); + } + onlineMediaPlugin.triggerModal(); + }); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js index 2fa442d9dc9762a3aeb9f1ea0d353836fc4833e4..d89a014c954dd05366bdd74eb5c562fb26955d95 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js @@ -16,222 +16,226 @@ * JavaScript implementations for page actions */ define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent', 'TYPO3/CMS/Backend/Wizard/NewContentElement'], function($, PersistentStorage, NewContentElement) { - 'use strict'; - - /** - * - * @type {{settings: {pageId: number, language: {pageOverlayId: number}}, identifier: {pageTitle: string, hiddenElements: string}, elements: {$pageTitle: null, $showHiddenElementsCheckbox: null}, documentIsReady: boolean}} - * @exports TYPO3/CMS/Backend/PageActions - */ - var PageActions = { - settings: { - pageId: 0, - language: { - pageOverlayId: 0 - } - }, - identifier: { - pageTitle: '.t3js-title-inlineedit', - hiddenElements: '.t3js-hidden-record', - newButton: '.t3js-toggle-new-content-element-wizard' - }, - elements: { - $pageTitle: null, - $showHiddenElementsCheckbox: null - }, - documentIsReady: false - }; - - /** - * Initialize page title renaming - */ - PageActions.initializePageTitleRenaming = function() { - if (!PageActions.documentIsReady) { - $(function() { - PageActions.initializePageTitleRenaming(); - }); - return; - } - if (PageActions.settings.pageId <= 0) { - return; - } - - var $editActionLink = $('<a class="hidden" href="#" data-action="edit"><span class="t3-icon fa fa-pencil"></span></a>'); - $editActionLink.on('click', function(e) { - e.preventDefault(); - PageActions.editPageTitle(); - }); - PageActions.elements.$pageTitle - .on('dblclick', PageActions.editPageTitle) - .on('mouseover', function() { $editActionLink.removeClass('hidden'); }) - .on('mouseout', function() { $editActionLink.addClass('hidden'); }) - .append($editActionLink); - }; - - /** - * Initialize elements - */ - PageActions.initializeElements = function() { - PageActions.elements.$pageTitle = $(PageActions.identifier.pageTitle + ':first'); - PageActions.elements.$showHiddenElementsCheckbox = $('#checkTt_content_showHidden'); - }; - - /** - * Initialize events - */ - PageActions.initializeEvents = function() { - PageActions.elements.$showHiddenElementsCheckbox.on('change', PageActions.toggleContentElementVisibility); - }; - - /** - * Toggles the "Show hidden content elements" checkbox - */ - PageActions.toggleContentElementVisibility = function() { - var $me = $(this), - $hiddenElements = $(PageActions.identifier.hiddenElements); - - // show a spinner to show activity - var $spinner = $('<span />', {class: 'checkbox-spinner fa fa-circle-o-notch fa-spin'}); - $me.hide().after($spinner); - - if ($me.prop('checked')) { - $hiddenElements.slideDown(); - } else { - $hiddenElements.slideUp(); - } - - PersistentStorage.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() { - $spinner.remove(); - $me.show(); - }); - }; - - /** - * Changes the h1 to an edit form - */ - PageActions.editPageTitle = function() { - var $inputFieldWrap = $( - '<form>' + - '<div class="form-group">' + - '<div class="input-group input-group-lg">' + - '<input class="form-control">' + - '<span class="input-group-btn">' + - '<button class="btn btn-default" type="button" data-action="submit"><span class="t3-icon fa fa-floppy-o"></span></button> ' + - '</span>' + - '<span class="input-group-btn">' + - '<button class="btn btn-default" type="button" data-action="cancel"><span class="t3-icon fa fa-times"></span></button> ' + - '</span>' + - '</div>' + - '</div>' + - '</form>' - ), - $inputField = $inputFieldWrap.find('input'); - - $inputFieldWrap.find('[data-action=cancel]').on('click', function() { - $inputFieldWrap.replaceWith(PageActions.elements.$pageTitle); - PageActions.initializePageTitleRenaming(); - }); - - $inputFieldWrap.find('[data-action=submit]').on('click', function() { - var newPageTitle = $.trim($inputField.val()); - if (newPageTitle !== '' && PageActions.elements.$pageTitle.text() !== newPageTitle) { - PageActions.saveChanges($inputField); - } else { - $inputFieldWrap.find('[data-action=cancel]').trigger('click'); - } - }); - - // the form stuff is a wacky workaround to prevent the submission of the docheader form - $inputField.parents('form').on('submit', function(e) { - e.preventDefault(); - return false; - }); - - var $h1 = PageActions.elements.$pageTitle; - $h1.children().last().remove(); - $h1.replaceWith($inputFieldWrap); - $inputField.val($h1.text()).focus(); - - $inputField.on('keyup', function(e) { - switch (e.which) { - case 13: // enter - $inputFieldWrap.find('[data-action=submit]').trigger('click'); - break; - case 27: // escape - $inputFieldWrap.find('[data-action=cancel]').trigger('click'); - break; - } - }); - }; - - /** - * Set the page id (used in the RequireJS callback) - * - * @param {Number} pageId - */ - PageActions.setPageId = function(pageId) { - PageActions.settings.pageId = pageId; - }; - - /** - * Set the overlay id - * - * @param {Number} overlayId - */ - PageActions.setLanguageOverlayId = function(overlayId) { - PageActions.settings.language.pageOverlayId = overlayId; - }; - - /** - * Activate New Content Element Wizard - */ - PageActions.initializeNewContentElementWizard = function() { - $(PageActions.identifier.newButton).click(function() { - NewContentElement.wizard($(this).data('url'), $(this).data('title')); - }); - }; - - /** - * Save the changes and reload the page tree - * - * @param {Object} $field - */ - PageActions.saveChanges = function($field) { - var $inputFieldWrap = $field.parents('form'); - $inputFieldWrap.find('button').addClass('disabled'); - $field.attr('disabled', 'disabled'); - - var parameters = {}, - recordUid; - - if (PageActions.settings.language.pageOverlayId === 0) { - recordUid = PageActions.settings.pageId; - } else { - recordUid = PageActions.settings.language.pageOverlayId; - } - - parameters.data = {}; - parameters.data['pages'] = {}; - parameters.data['pages'][recordUid] = {title: $field.val()}; - - require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) { - DataHandler.process(parameters).done(function() { - $inputFieldWrap.find('[data-action=cancel]').trigger('click'); - PageActions.elements.$pageTitle.text($field.val()); - PageActions.initializePageTitleRenaming(); - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - }).fail(function() { - $inputFieldWrap.find('[data-action=cancel]').trigger('click'); - }); - }); - }; - - $(function() { - PageActions.initializeElements(); - PageActions.initializeEvents(); - PageActions.initializeNewContentElementWizard(); - PageActions.documentIsReady = true; - }); - - return PageActions; + 'use strict'; + + /** + * + * @type {{settings: {pageId: number, language: {pageOverlayId: number}}, identifier: {pageTitle: string, hiddenElements: string}, elements: {$pageTitle: null, $showHiddenElementsCheckbox: null}, documentIsReady: boolean}} + * @exports TYPO3/CMS/Backend/PageActions + */ + var PageActions = { + settings: { + pageId: 0, + language: { + pageOverlayId: 0 + } + }, + identifier: { + pageTitle: '.t3js-title-inlineedit', + hiddenElements: '.t3js-hidden-record', + newButton: '.t3js-toggle-new-content-element-wizard' + }, + elements: { + $pageTitle: null, + $showHiddenElementsCheckbox: null + }, + documentIsReady: false + }; + + /** + * Initialize page title renaming + */ + PageActions.initializePageTitleRenaming = function() { + if (!PageActions.documentIsReady) { + $(function() { + PageActions.initializePageTitleRenaming(); + }); + return; + } + if (PageActions.settings.pageId <= 0) { + return; + } + + var $editActionLink = $('<a class="hidden" href="#" data-action="edit"><span class="t3-icon fa fa-pencil"></span></a>'); + $editActionLink.on('click', function(e) { + e.preventDefault(); + PageActions.editPageTitle(); + }); + PageActions.elements.$pageTitle + .on('dblclick', PageActions.editPageTitle) + .on('mouseover', function() { + $editActionLink.removeClass('hidden'); + }) + .on('mouseout', function() { + $editActionLink.addClass('hidden'); + }) + .append($editActionLink); + }; + + /** + * Initialize elements + */ + PageActions.initializeElements = function() { + PageActions.elements.$pageTitle = $(PageActions.identifier.pageTitle + ':first'); + PageActions.elements.$showHiddenElementsCheckbox = $('#checkTt_content_showHidden'); + }; + + /** + * Initialize events + */ + PageActions.initializeEvents = function() { + PageActions.elements.$showHiddenElementsCheckbox.on('change', PageActions.toggleContentElementVisibility); + }; + + /** + * Toggles the "Show hidden content elements" checkbox + */ + PageActions.toggleContentElementVisibility = function() { + var $me = $(this), + $hiddenElements = $(PageActions.identifier.hiddenElements); + + // show a spinner to show activity + var $spinner = $('<span />', {class: 'checkbox-spinner fa fa-circle-o-notch fa-spin'}); + $me.hide().after($spinner); + + if ($me.prop('checked')) { + $hiddenElements.slideDown(); + } else { + $hiddenElements.slideUp(); + } + + PersistentStorage.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() { + $spinner.remove(); + $me.show(); + }); + }; + + /** + * Changes the h1 to an edit form + */ + PageActions.editPageTitle = function() { + var $inputFieldWrap = $( + '<form>' + + '<div class="form-group">' + + '<div class="input-group input-group-lg">' + + '<input class="form-control">' + + '<span class="input-group-btn">' + + '<button class="btn btn-default" type="button" data-action="submit"><span class="t3-icon fa fa-floppy-o"></span></button> ' + + '</span>' + + '<span class="input-group-btn">' + + '<button class="btn btn-default" type="button" data-action="cancel"><span class="t3-icon fa fa-times"></span></button> ' + + '</span>' + + '</div>' + + '</div>' + + '</form>' + ), + $inputField = $inputFieldWrap.find('input'); + + $inputFieldWrap.find('[data-action=cancel]').on('click', function() { + $inputFieldWrap.replaceWith(PageActions.elements.$pageTitle); + PageActions.initializePageTitleRenaming(); + }); + + $inputFieldWrap.find('[data-action=submit]').on('click', function() { + var newPageTitle = $.trim($inputField.val()); + if (newPageTitle !== '' && PageActions.elements.$pageTitle.text() !== newPageTitle) { + PageActions.saveChanges($inputField); + } else { + $inputFieldWrap.find('[data-action=cancel]').trigger('click'); + } + }); + + // the form stuff is a wacky workaround to prevent the submission of the docheader form + $inputField.parents('form').on('submit', function(e) { + e.preventDefault(); + return false; + }); + + var $h1 = PageActions.elements.$pageTitle; + $h1.children().last().remove(); + $h1.replaceWith($inputFieldWrap); + $inputField.val($h1.text()).focus(); + + $inputField.on('keyup', function(e) { + switch (e.which) { + case 13: // enter + $inputFieldWrap.find('[data-action=submit]').trigger('click'); + break; + case 27: // escape + $inputFieldWrap.find('[data-action=cancel]').trigger('click'); + break; + } + }); + }; + + /** + * Set the page id (used in the RequireJS callback) + * + * @param {Number} pageId + */ + PageActions.setPageId = function(pageId) { + PageActions.settings.pageId = pageId; + }; + + /** + * Set the overlay id + * + * @param {Number} overlayId + */ + PageActions.setLanguageOverlayId = function(overlayId) { + PageActions.settings.language.pageOverlayId = overlayId; + }; + + /** + * Activate New Content Element Wizard + */ + PageActions.initializeNewContentElementWizard = function() { + $(PageActions.identifier.newButton).click(function() { + NewContentElement.wizard($(this).data('url'), $(this).data('title')); + }); + }; + + /** + * Save the changes and reload the page tree + * + * @param {Object} $field + */ + PageActions.saveChanges = function($field) { + var $inputFieldWrap = $field.parents('form'); + $inputFieldWrap.find('button').addClass('disabled'); + $field.attr('disabled', 'disabled'); + + var parameters = {}, + recordUid; + + if (PageActions.settings.language.pageOverlayId === 0) { + recordUid = PageActions.settings.pageId; + } else { + recordUid = PageActions.settings.language.pageOverlayId; + } + + parameters.data = {}; + parameters.data['pages'] = {}; + parameters.data['pages'][recordUid] = {title: $field.val()}; + + require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) { + DataHandler.process(parameters).done(function() { + $inputFieldWrap.find('[data-action=cancel]').trigger('click'); + PageActions.elements.$pageTitle.text($field.val()); + PageActions.initializePageTitleRenaming(); + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + }).fail(function() { + $inputFieldWrap.find('[data-action=cancel]').trigger('click'); + }); + }); + }; + + $(function() { + PageActions.initializeElements(); + PageActions.initializeEvents(); + PageActions.initializeNewContentElementWizard(); + PageActions.documentIsReady = true; + }); + + return PageActions; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js index 23259dc54a34dfa7f683ed170e7925fd4d3a288f..403c08429af43b8699f11d68f343adf90a95ce2c 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js @@ -21,16 +21,16 @@ define(['jquery', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/ContextMenu', 'TYPO3/CMS/Backend/Storage/Persistent', - 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Notification' ], - function ($, d3, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) { + function($, d3, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) { 'use strict'; /** * @constructor * @exports TYPO3/CMS/Backend/PageTree/PageTree */ - var PageTree = function () { + var PageTree = function() { SvgTree.call(this); }; @@ -43,7 +43,7 @@ define(['jquery', * @param {String} selector * @param {Object} settings */ - PageTree.prototype.initialize = function (selector, settings) { + PageTree.prototype.initialize = function(selector, settings) { var _this = this; if (!_super_.initialize.call(_this, selector, settings)) { @@ -68,7 +68,7 @@ define(['jquery', /** * Add mount point */ - PageTree.prototype.addMountPoint = function (breadcrumb) { + PageTree.prototype.addMountPoint = function(breadcrumb) { var _this = this; if (_this.wrapper.parent().find('.node-mount-point').length) { @@ -77,24 +77,24 @@ define(['jquery', _this.mountPoint = _this.wrapper.before( '<div class="node-mount-point">' + - '<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' + - '<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' + - '<div class="node-mount-point__icon" data-tree-icon="actions-close" title="' + TYPO3.lang['labels.temporaryDBmount'] + '"></div>' + + '<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' + + '<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' + + '<div class="node-mount-point__icon" data-tree-icon="actions-close" title="' + TYPO3.lang['labels.temporaryDBmount'] + '"></div>' + '</div>' ); _this.wrapper.parent() .find('[data-tree-icon=actions-close]') - .on('click', function () { + .on('click', function() { top.TYPO3.Backend.NavigationContainer.PageTree.unsetTemporaryMountPoint(); _this.wrapper.parent().find('.node-mount-point').remove(); }); //get icons - _this.wrapper.parent().find('.node-mount-point [data-tree-icon]').each(function () { + _this.wrapper.parent().find('.node-mount-point [data-tree-icon]').each(function() { var $this = $(this); - Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small, null, null, 'inline').done(function (icon) { + Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small, null, null, 'inline').done(function(icon) { $this.append(icon); }); }); @@ -105,19 +105,19 @@ define(['jquery', * * @param error */ - PageTree.prototype.errorNotification = function (error) { + PageTree.prototype.errorNotification = function(error) { var title = TYPO3.lang.pagetree_networkErrorTitle; var desc = TYPO3.lang.pagetree_networkErrorDesc; if (error && error.target && (error.target.status || error.target.statusText)) { - title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || ''); + title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || ''); } Notification.error(title, desc); this.loadData(); }; - PageTree.prototype.sendChangeCommand = function (data) { + PageTree.prototype.sendChangeCommand = function(data) { var _this = this; var params = ''; @@ -148,17 +148,17 @@ define(['jquery', d3.request(top.TYPO3.settings.ajaxUrls.record_process) .header('X-Requested-With', 'XMLHttpRequest') .header('Content-Type', 'application/x-www-form-urlencoded') - .on('error', function (error) { + .on('error', function(error) { _this.errorNotification(error); throw error; }) - .post(params, function (data) { + .post(params, function(data) { if (data) { var response = JSON.parse(data.response); if (response && response.hasErrors) { if (response.messages) { - $.each(response.messages, function (id, message) { + $.each(response.messages, function(id, message) { Notification.error( message.title, message.message @@ -185,7 +185,7 @@ define(['jquery', * * @param {Node} node */ - PageTree.prototype.nodeSelectedAfter = function (node) { + PageTree.prototype.nodeSelectedAfter = function(node) { var separator = '?'; if (currentSubScript.indexOf('?') !== -1) { separator = '&'; @@ -197,7 +197,7 @@ define(['jquery', ); }; - PageTree.prototype.nodeRightClick = function (node) { + PageTree.prototype.nodeRightClick = function(node) { d3.event.preventDefault(); var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']'); @@ -212,7 +212,7 @@ define(['jquery', } }; - PageTree.prototype.contextmenu = function (node) { + PageTree.prototype.contextmenu = function(node) { var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']'); if ($node.length) { @@ -226,27 +226,27 @@ define(['jquery', } }; - PageTree.prototype.updateSvg = function (nodeEnter) { + PageTree.prototype.updateSvg = function(nodeEnter) { nodeEnter .select('use') .attr('data-table', 'pages'); }; - PageTree.prototype.hideChildren = function (node) { + PageTree.prototype.hideChildren = function(node) { _super_.hideChildren(node); Persistent.set('BackendComponents.States.Pagetree.stateHash.' + node.stateIdentifier, 0); }; - PageTree.prototype.showChildren = function (node) { + PageTree.prototype.showChildren = function(node) { _super_.showChildren(node); Persistent.set('BackendComponents.States.Pagetree.stateHash.' + node.stateIdentifier, 1); }; - PageTree.prototype.updateNodeBgClass = function (nodeBg) { + PageTree.prototype.updateNodeBgClass = function(nodeBg) { return _super_.updateNodeBgClass.call(this, nodeBg).call(this.dragDrop.drag()); }; - PageTree.prototype.nodesUpdate = function (nodes) { + PageTree.prototype.nodesUpdate = function(nodes) { var _this = this; nodes = _super_.nodesUpdate.call(this, nodes) @@ -258,10 +258,10 @@ define(['jquery', .attr('class', 'node-stop') .attr('dx', 30) .attr('dy', 5) - .attr('visibility', function (node) { + .attr('visibility', function(node) { return (node.stopPageTree && (node.depth !== 0)) ? 'visible' : 'hidden'; }) - .on('click', function (node) { + .on('click', function(node) { _this.setTemporaryMountPoint(node.identifier); }); @@ -274,24 +274,24 @@ define(['jquery', * * @param {Node} node */ - PageTree.prototype.appendTextElement = function (node) { + PageTree.prototype.appendTextElement = function(node) { var _this = this; var clicks = 0; _super_.appendTextElement.call(this, node) - .attr('dx', function (node) { + .attr('dx', function(node) { if (node.stopPageTree && node.depth !== 0) { return _this.textPosition + 15; } return _this.textPosition; }) - .on('click', function (node) { + .on('click', function(node) { if (node.identifier !== 0) { clicks++; if (clicks === 1) { - setTimeout(function () { + setTimeout(function() { if (clicks === 1) { _this.clickOnLabel(node, this); _this.nodeBgEvents().click(node, this); @@ -311,24 +311,24 @@ define(['jquery', }); }; - PageTree.prototype.setTemporaryMountPoint = function (pid) { + PageTree.prototype.setTemporaryMountPoint = function(pid) { var params = 'pid=' + pid; var _this = this; d3.request(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point) .header('X-Requested-With', 'XMLHttpRequest') .header('Content-Type', 'application/x-www-form-urlencoded') - .on('error', function (error) { + .on('error', function(error) { _this.errorNotification(error); throw error; }) - .post(params, function (data) { + .post(params, function(data) { if (data) { var response = JSON.parse(data.response); if (response && response.hasErrors) { if (response.messages) { - $.each(response.messages, function (id, message) { + $.each(response.messages, function(id, message) { Notification.error( message.title, message.message @@ -349,14 +349,14 @@ define(['jquery', }); }; - PageTree.prototype.unsetTemporaryMountPoint = function () { + PageTree.prototype.unsetTemporaryMountPoint = function() { var _this = this; - Persistent.unset('pageTree_temporaryMountPoint').then(function () { + Persistent.unset('pageTree_temporaryMountPoint').then(function() { _this.refreshTree(); }); }; - PageTree.prototype.sendEditNodeLabelCommand = function (node) { + PageTree.prototype.sendEditNodeLabelCommand = function(node) { var _this = this; var params = '&data[pages][' + node.identifier + '][' + node.nameSourceField + ']=' + node.newName; @@ -367,17 +367,17 @@ define(['jquery', d3.request(top.TYPO3.settings.ajaxUrls.record_process) .header('X-Requested-With', 'XMLHttpRequest') .header('Content-Type', 'application/x-www-form-urlencoded') - .on('error', function (error) { + .on('error', function(error) { _this.errorNotification(error); throw error; }) - .post(params, function (data) { + .post(params, function(data) { if (data) { var response = JSON.parse(data.response); if (response && response.hasErrors) { if (response.messages) { - $.each(response.messages, function (id, message) { + $.each(response.messages, function(id, message) { Notification.error( message.title, message.message @@ -402,7 +402,7 @@ define(['jquery', }); }; - PageTree.prototype.editNodeLabel = function (node) { + PageTree.prototype.editNodeLabel = function(node) { var _this = this; _this.removeEditedText(); @@ -411,7 +411,7 @@ define(['jquery', d3.select(_this.svg.node().parentNode) .append('input') .attr('class', 'node-edit') - .style('top', function () { + .style('top', function() { var top = node.y + _this.settings.marginTop; return top + 'px'; }) @@ -420,7 +420,7 @@ define(['jquery', .style('height', _this.settings.nodeHeight + 'px') .attr('type', 'text') .attr('value', node.name) - .on('keydown', function () { + .on('keydown', function() { var code = d3.event.keyCode; if (code === 13 || code === 9) { //enter || tab @@ -441,7 +441,7 @@ define(['jquery', _this.removeEditedText(); } }) - .on('blur', function () { + .on('blur', function() { if (_this.nodeIsEdit) { var newName = this.value.trim(); @@ -459,7 +459,7 @@ define(['jquery', .select(); }; - PageTree.prototype.removeEditedText = function () { + PageTree.prototype.removeEditedText = function() { var _this = this; var inputWrapper = d3.selectAll('.node-edit'); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js index 31e4a10f4c109398ab7d6a035bca990004e7fc8b..25d69c9b3ef9a21ef658a22d2d6707a5d11a0881 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js @@ -17,11 +17,11 @@ * Provides drag&drop related functionality for the SVG page tree */ define([ - 'jquery', - 'd3', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - ], function ($, d3, Modal, Severity) { + 'jquery', + 'd3', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity' +], function($, d3, Modal, Severity) { 'use strict'; /** @@ -40,7 +40,7 @@ define([ */ dropZoneDelete: null, - init: function (svgTree) { + init: function(svgTree) { this.tree = svgTree; }, @@ -49,7 +49,7 @@ define([ * * Returns initialized d3.drag() function */ - drag: function () { + drag: function() { var self = {}; var _this = this; var tree = _this.tree; @@ -60,7 +60,7 @@ define([ * @param node * @returns {string} */ - self.getDropZoneOpenTransform = function (node) { + self.getDropZoneOpenTransform = function(node) { var svgWidth = parseFloat(tree.svg.style('width')) || 300; return 'translate(' + (svgWidth - 58 - node.x) + ', -10)'; @@ -72,13 +72,13 @@ define([ * @param node * @returns {string} */ - self.getDropZoneCloseTransform = function (node) { + self.getDropZoneCloseTransform = function(node) { var svgWidth = parseFloat(tree.svg.style('width')) || 300; return 'translate(' + (svgWidth - node.x) + ', -10)'; }; - self.dragStart = function (node) { + self.dragStart = function(node) { if (tree.settings.isDragAnDrop !== true || node.depth === 0) { return false; } @@ -103,10 +103,10 @@ define([ .attr('width', '50px') .attr('x', 0) .attr('y', 0) - .on('mouseover', function () { + .on('mouseover', function() { tree.nodeIsOverDelete = true; }) - .on('mouseout', function () { + .on('mouseout', function() { tree.nodeIsOverDelete = false; }); @@ -122,7 +122,7 @@ define([ $.extend(self, _this.setDragStart()); }; - self.dragDragged = function (node) { + self.dragDragged = function(node) { if (_this.isDragNodeDistanceMore(self, 10)) { self.startDrag = true; } else { @@ -168,7 +168,7 @@ define([ $(document).find('.node-dd').css({ left: left, top: top, - display: 'block', + display: 'block' }); tree.settings.nodeDragPosition = false; @@ -179,7 +179,7 @@ define([ || (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsStateIdentifier.indexOf(node.stateIdentifier) !== -1) || !tree.isOverSvg) { - _this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop' }); + _this.addNodeDdClass({$nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop'}); if (!tree.isOverSvg) { _this.tree.nodesBgContainer @@ -194,7 +194,7 @@ define([ .attr('data-open', 'true'); } } else if (!tree.settings.nodeOver.node) { - _this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop' }); + _this.addNodeDdClass({$nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop'}); _this.tree.nodesBgContainer .selectAll('.node-bg__border') .style('display', 'none'); @@ -210,7 +210,7 @@ define([ } }; - self.dragEnd = function (node) { + self.dragEnd = function(node) { _this.setDragEnd(); if (!self.startDrag || tree.settings.isDragAnDrop !== true || node.depth === 0) { @@ -234,7 +234,7 @@ define([ $nodesWrap: $svg.find('.nodes-wrapper'), className: '', rmClass: 'dragging', - setCanNodeDrag: false, + setCanNodeDrag: false }); $nodesBg @@ -257,7 +257,7 @@ define([ || !tree.isOverSvg ) ) { - var options = _this.changeNodePosition({ droppedNode: droppedNode }); + var options = _this.changeNodePosition({droppedNode: droppedNode}); var modalText = options.position === 'in' ? TYPO3.lang['mess.move_into'] : TYPO3.lang['mess.move_after']; modalText = modalText.replace('%s', options.node.name).replace('%s', options.target.name); @@ -270,20 +270,20 @@ define([ text: $(this).data('button-close-text') || TYPO3.lang['labels.cancel'] || 'Cancel', active: true, btnClass: 'btn-default', - name: 'cancel', + name: 'cancel' }, { text: $(this).data('button-ok-text') || TYPO3.lang['cm.copy'] || 'Copy', btnClass: 'btn-warning', - name: 'copy', + name: 'copy' }, { text: $(this).data('button-ok-text') || TYPO3.lang['button.move'] || 'Move', btnClass: 'btn-warning', - name: 'move', - }, + name: 'move' + } ]) - .on('button.clicked', function (e) { + .on('button.clicked', function(e) { if (e.target.name === 'move') { options.command = 'move'; tree.sendChangeCommand(options); @@ -295,7 +295,7 @@ define([ Modal.dismiss(); }); } else if (tree.nodeIsOverDelete) { - var options = _this.changeNodePosition({ droppedNode: droppedNode, command: 'delete' }); + var options = _this.changeNodePosition({droppedNode: droppedNode, command: 'delete'}); if (tree.settings.displayDeleteConfirmation) { var $modal = Modal.confirm( TYPO3.lang.deleteItem, @@ -305,16 +305,16 @@ define([ text: $(this).data('button-close-text') || TYPO3.lang['labels.cancel'] || 'Cancel', active: true, btnClass: 'btn-default', - name: 'cancel', + name: 'cancel' }, { text: $(this).data('button-ok-text') || TYPO3.lang['cm.delete'] || 'Delete', btnClass: 'btn-warning', - name: 'delete', - }, + name: 'delete' + } ]); - $modal.on('button.clicked', function (e) { + $modal.on('button.clicked', function(e) { if (e.target.name === 'delete') { tree.sendChangeCommand(options); @@ -337,7 +337,7 @@ define([ /** * Open node with children while holding the node/element over this node for one second */ - openNodeTimeout: function () { + openNodeTimeout: function() { var _this = this; if (!_this.timeout) { @@ -348,7 +348,7 @@ define([ if (_this.timeout.node != _this.tree.settings.nodeOver.node) { _this.timeout.node = _this.tree.settings.nodeOver; clearTimeout(_this.timeout.time); - _this.timeout.time = setTimeout(function () { + _this.timeout.time = setTimeout(function() { if (_this.tree.settings.nodeOver.node) { _this.tree.showChildren(_this.tree.settings.nodeOver.node); _this.tree.prepareDataForVisibleNodes(); @@ -361,7 +361,7 @@ define([ } }, - changeNodeClasses: function () { + changeNodeClasses: function() { var elementNodeBg = this.tree.svg.select('.node-over'); var $svg = $(this.tree.svg.node()); var $nodesWrap = $svg.find('.nodes-wrapper'); @@ -390,19 +390,19 @@ define([ this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'nodrop', + className: 'nodrop' }); } else if (this.tree.settings.nodeOver.node.firstChild) { this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-above', + className: 'ok-above' }); } else { this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-between', + className: 'ok-between' }); } @@ -415,7 +415,7 @@ define([ this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-append', + className: 'ok-append' }); this.tree.settings.nodeDragPosition = 'in'; } else { @@ -427,14 +427,14 @@ define([ this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-below', + className: 'ok-below' }); } else { this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-between', + className: 'ok-between' }); } @@ -447,7 +447,7 @@ define([ this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'ok-append', + className: 'ok-append' }); this.tree.settings.nodeDragPosition = 'in'; } @@ -459,12 +459,12 @@ define([ this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, - className: 'nodrop', + className: 'nodrop' }); } }, - addNodeDdClass: function (options) { + addNodeDdClass: function(options) { var clearClass = ' #prefix#--nodrop #prefix#--ok-append #prefix#--ok-below #prefix#--ok-between #prefix#--ok-above'; var rmClass = ''; var addClass = ''; @@ -499,9 +499,9 @@ define([ * @param {Integer} distance * @returns {boolean} */ - isDragNodeDistanceMore: function (data, distance) { + isDragNodeDistanceMore: function(data, distance) { return (data.startDrag || - (((data.startPageX - distance) > d3.event.sourceEvent.pageX) || + (((data.startPageX - distance) > d3.event.sourceEvent.pageX) || ((data.startPageX + distance) < d3.event.sourceEvent.pageX) || ((data.startPageY - distance) > d3.event.sourceEvent.pageY) || ((data.startPageY + distance) < d3.event.sourceEvent.pageY))); @@ -512,21 +512,21 @@ define([ * * @returns {{startPageX, startPageY, startDrag: boolean}} */ - setDragStart: function () { - $('body iframe').css({ 'pointer-events': 'none' }); + setDragStart: function() { + $('body iframe').css({'pointer-events': 'none'}); return { startPageX: d3.event.sourceEvent.pageX, startPageY: d3.event.sourceEvent.pageY, - startDrag: false, + startDrag: false }; }, /** * Sets the same parameters on end for method drag() and dragToolbar() */ - setDragEnd: function () { - $('body iframe').css({ 'pointer-events': '' }); + setDragEnd: function() { + $('body iframe').css({'pointer-events': ''}); }, /** @@ -534,12 +534,12 @@ define([ * * Returns method from d3js */ - dragToolbar: function () { + dragToolbar: function() { var self = {}; var _this = this; var tree = _this.tree; - self.dragStart = function () { + self.dragStart = function() { self.id = $(this).data('node-type'); self.name = $(this).attr('title'); self.tooltip = $(this).attr('tooltip'); @@ -548,7 +548,7 @@ define([ $.extend(self, _this.setDragStart()); }; - self.dragDragged = function () { + self.dragDragged = function() { if (_this.isDragNodeDistanceMore(self, 10)) { self.startDrag = true; } else { @@ -584,13 +584,13 @@ define([ $(document).find('.node-dd').css({ left: left, top: top, - display: 'block', + display: 'block' }); _this.changeNodeClasses(); }; - self.dragEnd = function () { + self.dragEnd = function() { _this.setDragEnd(); if (!self.startDrag) { @@ -614,7 +614,7 @@ define([ $nodesWrap: $svg.find('.nodes-wrapper'), className: '', rmClass: 'dragging', - setCanNodeDrag: false, + setCanNodeDrag: false }); $nodesBg @@ -643,7 +643,7 @@ define([ icon: self.icon, position: _this.tree.settings.nodeDragPosition, command: 'new', - target: _this.tree.settings.nodeOver.node, + target: _this.tree.settings.nodeOver.node }; _this.addNewNode(data); @@ -656,7 +656,7 @@ define([ .on('end', self.dragEnd); }, - changeNodePosition: function (options) { + changeNodePosition: function(options) { var _this = this; var tree = _this.tree; var nodes = tree.nodes; @@ -686,7 +686,7 @@ define([ uid: uid, // dragged node id target: target, // hovered node position: position, // before, in, after - command: options.command, // element is copied or moved + command: options.command // element is copied or moved }; $.extend(data, options); @@ -701,7 +701,7 @@ define([ * @param {Integer} index * @returns {Array} [position, target] */ - setNodePositionAndTarget: function (nodeDepth, index) { + setNodePositionAndTarget: function(nodeDepth, index) { if (index > 0) { index--; } @@ -728,12 +728,12 @@ define([ * * @type {Object} options */ - addNewNode: function (options) { + addNewNode: function(options) { var _this = this; var target = options.target; var index = _this.tree.nodes.indexOf(target); var newNode = {}; - var removeNode = function (newNode) { + var removeNode = function(newNode) { var index = _this.tree.nodes.indexOf(newNode); // if newNode is only one child @@ -755,8 +755,8 @@ define([ newNode.target = target; newNode.parents = target.parents; newNode.parentsStateIdentifier = target.parentsStateIdentifier; - newNode.depth = target.depth; - newNode.position = options.position; + newNode.depth = target.depth; + newNode.position = options.position; newNode.name = (typeof options.title !== 'undefined') ? options.title : TYPO3.lang['tree.defaultPageTitle']; newNode.y = newNode.y || newNode.target.y; newNode.x = newNode.x || newNode.target.x; @@ -799,7 +799,7 @@ define([ .style('height', _this.tree.settings.nodeHeight + 'px') .attr('text', 'text') .attr('value', newNode.name) - .on('keydown', function () { + .on('keydown', function() { var code = d3.event.keyCode; if (code === 13 || code === 9) { // enter || tab @@ -818,7 +818,7 @@ define([ removeNode(newNode); } }) - .on('blur', function () { + .on('blur', function() { if (_this.tree.nodeIsEdit && (_this.tree.nodes.indexOf(newNode) > -1)) { var newName = this.value.trim(); @@ -840,18 +840,18 @@ define([ * * @returns {String} */ - template: function (icon, name) { + template: function(icon, name) { return '<div class="node-dd node-dd--nodrop">' + - '<div class="node-dd__ctrl-icon">' + - '</div>' + - '<div class="node-dd__text">' + - '<span class="node-dd__icon">' + - '<svg aria-hidden="true" width="16px" height="16px"><use xlink:href="' + icon + '"/></svg>' + - '</span>' + - '<span class="node-dd__name">' + name + '</span>' + - '</div>' + + '<div class="node-dd__ctrl-icon">' + + '</div>' + + '<div class="node-dd__text">' + + '<span class="node-dd__icon">' + + '<svg aria-hidden="true" width="16px" height="16px"><use xlink:href="' + icon + '"/></svg>' + + '</span>' + + '<span class="node-dd__name">' + name + '</span>' + + '</div>' + '</div>'; - }, + } }; return PageTreeDragDrop; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js index a39725abb4b13365981ba6f3f97c8998f7960cf2..400106a0e14aee89405db8b1a8be6ce4a7a3d138 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js @@ -20,24 +20,24 @@ define(['jquery', 'TYPO3/CMS/Backend/PageTree/PageTree', 'TYPO3/CMS/Backend/PageTree/PageTreeToolbar', 'TYPO3/CMS/Backend/Viewport', - 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Icons' ], - function ($, PageTree, PageTreeToolbar, Viewport, Icons) { + function($, PageTree, PageTreeToolbar, Viewport, Icons) { 'use strict'; var PageTreeElement = { template: - '<div id="typo3-pagetree" class="svg-tree">' + - '<div>' + - '<div id="svg-toolbar" class="svg-toolbar"></div>' + - '<div id="typo3-pagetree-treeContainer">' + - '<div id="typo3-pagetree-tree" class="svg-tree-wrapper" style="height:1000px;">' + - '<div class="node-loader"></div>' + - '</div>' + - '</div>' + - '</div>' + - '<div class="svg-tree-loader"></div>' + - '</div>', + '<div id="typo3-pagetree" class="svg-tree">' + + '<div>' + + '<div id="svg-toolbar" class="svg-toolbar"></div>' + + '<div id="typo3-pagetree-treeContainer">' + + '<div id="typo3-pagetree-tree" class="svg-tree-wrapper" style="height:1000px;">' + + '<div class="node-loader"></div>' + + '</div>' + + '</div>' + + '</div>' + + '<div class="svg-tree-loader"></div>' + + '</div>' }; /** @@ -45,8 +45,8 @@ define(['jquery', * * @param {String} selector */ - PageTreeElement.initialize = function (selector) { - $(function () { + PageTreeElement.initialize = function(selector) { + $(function() { var $element = $(selector); if ($element.html().trim().length !== 0) { @@ -56,21 +56,21 @@ define(['jquery', var tree = new PageTree(); $element.append(PageTreeElement.template); - Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function (spinner) { + Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { $('.node-loader').append(spinner); }); - Icons.getIcon('spinner-circle-light', Icons.sizes.large).done(function (spinner) { + Icons.getIcon('spinner-circle-light', Icons.sizes.large).done(function(spinner) { $('.svg-tree-loader').append(spinner); }); var dataUrl = top.TYPO3.settings.ajaxUrls.page_tree_data; var configurationUrl = top.TYPO3.settings.ajaxUrls.page_tree_configuration; - $.ajax({ url: configurationUrl }).done(function (configuration) { + $.ajax({url: configurationUrl}).done(function(configuration) { tree.initialize($element.find('#typo3-pagetree-tree'), $.extend(configuration, { dataUrl: dataUrl, - showIcons: true, + showIcons: true })); Viewport.NavigationContainer.setComponentInstance(tree); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js index 7769ee0c6a3c31286918fee963c8b08662d695cd..6bde7aa1503aa88c6853273456d82455c3021200 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js @@ -20,9 +20,9 @@ define(['jquery', 'TYPO3/CMS/Backend/PageTree/PageTreeDragDrop', 'TYPO3/CMS/Backend/Tooltip', 'TYPO3/CMS/Backend/SvgTree', - 'TYPO3/CMS/Lang/Lang', + 'TYPO3/CMS/Lang/Lang' ], - function ($, Icons, d3, PageTreeDragDrop) { + function($, Icons, d3, PageTreeDragDrop) { 'use strict'; /** @@ -31,11 +31,11 @@ define(['jquery', * @constructor * @exports TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar */ - var TreeToolbar = function () { + var TreeToolbar = function() { this.settings = { toolbarSelector: 'tree-toolbar', searchInput: '.search-input', - target: '.svg-toolbar', + target: '.svg-toolbar' }; /** @@ -74,7 +74,7 @@ define(['jquery', * @param {String} treeSelector * @param {Object} settings */ - TreeToolbar.prototype.initialize = function (treeSelector, settings) { + TreeToolbar.prototype.initialize = function(treeSelector, settings) { var _this = this; _this.$treeWrapper = $(treeSelector); @@ -95,37 +95,37 @@ define(['jquery', /** * Create toolbar template */ - TreeToolbar.prototype.createTemplate = function () { + TreeToolbar.prototype.createTemplate = function() { var _this = this; var $template = $( '<div class="' + _this.settings.toolbarSelector + '">' + - '<div class="svg-toolbar__menu">' + - '<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter">' + - '<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="' + TYPO3.lang['tree.buttonFilter'] + '"></button>' + - '</div>' + - '<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh">' + - '<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="' + TYPO3.lang['labels.refresh'] + '"></button>' + - '</div>' + + '<div class="svg-toolbar__menu">' + + '<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter">' + + '<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="' + TYPO3.lang['tree.buttonFilter'] + '"></button>' + + '</div>' + + '<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh">' + + '<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="' + TYPO3.lang['labels.refresh'] + '"></button>' + + '</div>' + '</div>' + '<div class="svg-toolbar__submenu">' + - '<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">' + - '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tree.searchTermInfo'] + '">' + - '</div>' + - '<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">' + - '</div>' + - '</div>' + + '<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">' + + '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tree.searchTermInfo'] + '">' + + '</div>' + + '<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">' + + '</div>' + + '</div>' + '</div>' ); if (this.tree.settings.doktypes && this.tree.settings.doktypes.length) { var $buttons = $template.find('[data-tree-submenu=page-new]'); $template.find('.svg-toolbar__menu').prepend('<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="page-new">' + - '<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="' + TYPO3.lang['tree.buttonNewNode'] +'"></button>' + + '<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="' + TYPO3.lang['tree.buttonNewNode'] + '"></button>' + '</div>' ); - $.each(this.tree.settings.doktypes, function (id, e) { + $.each(this.tree.settings.doktypes, function(id, e) { _this.tree.fetchIcon(e.icon, false); $buttons.append('<div class="svg-toolbar__drag-node" data-tree-icon="' + e.icon + '" data-node-type="' + e.nodeType + '" title="' + e.title + '" tooltip="' + e.tooltip + '"></div>'); }); @@ -137,7 +137,7 @@ define(['jquery', /** * Renders toolbar */ - TreeToolbar.prototype.render = function () { + TreeToolbar.prototype.render = function() { var _this = this; this.tree = this.$treeWrapper.data('svgtree'); @@ -147,18 +147,18 @@ define(['jquery', var $toolbar = $(this.settings.target).append(this.template); //get icons - $toolbar.find('[data-tree-icon]').each(function () { + $toolbar.find('[data-tree-icon]').each(function() { var $this = $(this); - Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small).done(function (icon) { + Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small).done(function(icon) { $this.append(icon); }); }); //toggle toolbar submenu - $toolbar.find('[data-tree-show-submenu]').each(function () { + $toolbar.find('[data-tree-show-submenu]').each(function() { var _this = this; - $(this).click(function () { + $(this).click(function() { var $this = $(this); var name = $this.attr('data-tree-show-submenu'); var $submenu = $toolbar.find('[data-tree-submenu=' + name + ']'); @@ -176,13 +176,13 @@ define(['jquery', var d3Toolbar = d3.select('.svg-toolbar'); - $.each(this.tree.settings.doktypes, function (id, e) { + $.each(this.tree.settings.doktypes, function(id, e) { d3Toolbar .selectAll('[data-tree-icon=' + e.icon + ']') .call(_this.dragDrop.dragToolbar()); }); - $toolbar.find(this.settings.searchInput).on('input', function () { + $toolbar.find(this.settings.searchInput).on('input', function() { _this.search.call(_this, this); }); @@ -192,7 +192,7 @@ define(['jquery', /** * Refresh tree */ - TreeToolbar.prototype.refreshTree = function () { + TreeToolbar.prototype.refreshTree = function() { this.tree.refreshTree(); }; @@ -201,12 +201,12 @@ define(['jquery', * * @param {HTMLElement} input */ - TreeToolbar.prototype.search = function (input) { + TreeToolbar.prototype.search = function(input) { var _this = this; var name = $(input).val().trim(); this.tree.nodes[0].expanded = false; - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { var regex = new RegExp(name, 'i'); if (node.identifier.toString() === name || regex.test(node.name) || regex.test(node.alias)) { _this.showParents(node); @@ -227,13 +227,13 @@ define(['jquery', * * @param {HTMLElement} input */ - TreeToolbar.prototype.toggleHideUnchecked = function (input) { + TreeToolbar.prototype.toggleHideUnchecked = function(input) { var _this = this; this._hideUncheckedState = !this._hideUncheckedState; if (this._hideUncheckedState) { - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { if (node.checked) { _this.showParents(node); node.expanded = true; @@ -244,7 +244,7 @@ define(['jquery', } }); } else { - this.tree.nodes.forEach(function (node) { + this.tree.nodes.forEach(function(node) { node.hidden = false; }); } @@ -259,7 +259,7 @@ define(['jquery', * @param {Node} node * @returns {Boolean} */ - TreeToolbar.prototype.showParents = function (node) { + TreeToolbar.prototype.showParents = function(node) { if (node.parents.length === 0) { return true; } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js b/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js index fc7f4615b69387a3f2cfebf0b35120f088d316be..cf5288ce51eb574239541858fe4a1577c8394b6b 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js @@ -15,77 +15,77 @@ * Module: TYPO3/CMS/Backend/Severity * Severity for the TYPO3 backend */ -define(function () { - 'use strict'; +define(function() { + 'use strict'; - try { - // fetch from opening window - if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Severity) { - return window.opener.TYPO3.Severity; - } + try { + // fetch from opening window + if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Severity) { + return window.opener.TYPO3.Severity; + } - // fetch from parent - if (parent && parent.window.TYPO3 && parent.window.TYPO3.Severity) { - return parent.window.TYPO3.Severity; - } + // fetch from parent + if (parent && parent.window.TYPO3 && parent.window.TYPO3.Severity) { + return parent.window.TYPO3.Severity; + } - // fetch object from outer frame - if (top && top.TYPO3 && top.TYPO3.Severity) { - return top.TYPO3.Severity; - } - } catch (e) { - // This only happens if the opener, parent or top is some other url (eg a local file) - // which loaded the current window. Then the browser's cross domain policy jumps in - // and raises an exception. - // For this case we are safe and we can create our global object below. - } + // fetch object from outer frame + if (top && top.TYPO3 && top.TYPO3.Severity) { + return top.TYPO3.Severity; + } + } catch (e) { + // This only happens if the opener, parent or top is some other url (eg a local file) + // which loaded the current window. Then the browser's cross domain policy jumps in + // and raises an exception. + // For this case we are safe and we can create our global object below. + } - /** - * Severity object - * - * @type {{notice: number, information: number, info: number, ok: number, warning: number, error: number}} - * @exports TYPO3/CMS/Backend/Severity - */ - var Severity = { - notice: -2, - info: -1, - ok: 0, - warning: 1, - error: 2 - }; + /** + * Severity object + * + * @type {{notice: number, information: number, info: number, ok: number, warning: number, error: number}} + * @exports TYPO3/CMS/Backend/Severity + */ + var Severity = { + notice: -2, + info: -1, + ok: 0, + warning: 1, + error: 2 + }; - /** - * Gets the CSS class for the severity - * - * @param {Number} severity - * @returns {String} - */ - Severity.getCssClass = function(severity) { - var severityClass; - switch (severity) { - case Severity.notice: - severityClass = 'notice'; - break; - case Severity.ok: - severityClass = 'success'; - break; - case Severity.warning: - severityClass = 'warning'; - break; - case Severity.error: - severityClass = 'danger'; - break; - case Severity.info: - default: - severityClass = 'info'; - } - return severityClass; - }; + /** + * Gets the CSS class for the severity + * + * @param {Number} severity + * @returns {String} + */ + Severity.getCssClass = function(severity) { + var severityClass; + switch (severity) { + case Severity.notice: + severityClass = 'notice'; + break; + case Severity.ok: + severityClass = 'success'; + break; + case Severity.warning: + severityClass = 'warning'; + break; + case Severity.error: + severityClass = 'danger'; + break; + case Severity.info: + default: + severityClass = 'info'; + } + return severityClass; + }; - // attach to global frame - if (typeof TYPO3 !== 'undefined') { - TYPO3.Severity = Severity; - } + // attach to global frame + if (typeof TYPO3 !== 'undefined') { + TYPO3.Severity = Severity; + } - return Severity; + return Severity; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js b/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js index 57cc99fc611bf2c1a9678b376cab8009c504032c..702be26a9e0b99f7f106264f754448d02f1fd6fb 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js @@ -16,100 +16,100 @@ * Initializes global handling of split buttons. */ define(['jquery', 'TYPO3/CMS/Backend/Icons'], function($, Icons) { - 'use strict'; + 'use strict'; - /** - * - * @type {{preSubmitCallbacks: Array}} - * @exports TYPO3/CMS/Backend/SplitButtons - */ - var SplitButtons = { - preSubmitCallbacks: [] - }; + /** + * + * @type {{preSubmitCallbacks: Array}} + * @exports TYPO3/CMS/Backend/SplitButtons + */ + var SplitButtons = { + preSubmitCallbacks: [] + }; - /** - * Initializes the save handling - */ - SplitButtons.initializeSaveHandling = function() { - var preventExec = false; - var elements = [ - 'button[form]', - 'button[name^="_save"]', - 'a[data-name^="_save"]', - 'button[name="CMD"][value^="save"]', - 'a[data-name="CMD"][data-value^="save"]', - 'button[name^="_translation_save"]', - 'a[data-name^="_translation_save"]', - 'button[name="CMD"][value^="_translation_save"]', - 'a[data-name="CMD"][data-value^="_translation_save"]' - ].join(','); - $('.t3js-module-docheader').on('click', elements, function(e) { - // prevent doubleclick double submission bug in chrome, - // see https://forge.typo3.org/issues/77942 - if (!preventExec) { - preventExec = true; - var $me = $(this), - linkedForm = $me.attr('form') || $me.attr('data-form') || null, - $form = linkedForm ? $('#' + linkedForm) : $me.closest('form'), - name = $me.data('name') || this.name, - value = $me.data('value') || this.value, - $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', value); + /** + * Initializes the save handling + */ + SplitButtons.initializeSaveHandling = function() { + var preventExec = false; + var elements = [ + 'button[form]', + 'button[name^="_save"]', + 'a[data-name^="_save"]', + 'button[name="CMD"][value^="save"]', + 'a[data-name="CMD"][data-value^="save"]', + 'button[name^="_translation_save"]', + 'a[data-name^="_translation_save"]', + 'button[name="CMD"][value^="_translation_save"]', + 'a[data-name="CMD"][data-value^="_translation_save"]' + ].join(','); + $('.t3js-module-docheader').on('click', elements, function(e) { + // prevent doubleclick double submission bug in chrome, + // see https://forge.typo3.org/issues/77942 + if (!preventExec) { + preventExec = true; + var $me = $(this), + linkedForm = $me.attr('form') || $me.attr('data-form') || null, + $form = linkedForm ? $('#' + linkedForm) : $me.closest('form'), + name = $me.data('name') || this.name, + value = $me.data('value') || this.value, + $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', value); - // Run any preSubmit callbacks - for (var i = 0; i < SplitButtons.preSubmitCallbacks.length; ++i) { - SplitButtons.preSubmitCallbacks[i](e); + // Run any preSubmit callbacks + for (var i = 0; i < SplitButtons.preSubmitCallbacks.length; ++i) { + SplitButtons.preSubmitCallbacks[i](e); - if (e.isPropagationStopped()) { - preventExec = false; - return false; - } - } - $form.append($elem); - // Disable submit buttons - $form.on('submit', function() { - if ($form.find('.has-error').length > 0) { - preventExec = false; - return false; - } + if (e.isPropagationStopped()) { + preventExec = false; + return false; + } + } + $form.append($elem); + // Disable submit buttons + $form.on('submit', function() { + if ($form.find('.has-error').length > 0) { + preventExec = false; + return false; + } - var $affectedButton, - $splitButton = $me.closest('.t3js-splitbutton'); + var $affectedButton, + $splitButton = $me.closest('.t3js-splitbutton'); - if ($splitButton.length > 0) { - $splitButton.find('button').prop('disabled', true); - $affectedButton = $splitButton.children().first(); - } else { - $me.prop('disabled', true); - $affectedButton = $me; - } + if ($splitButton.length > 0) { + $splitButton.find('button').prop('disabled', true); + $affectedButton = $splitButton.children().first(); + } else { + $me.prop('disabled', true); + $affectedButton = $me; + } - Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(markup) { - $affectedButton.find('.t3js-icon').replaceWith(markup); - }); - }); + Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(markup) { + $affectedButton.find('.t3js-icon').replaceWith(markup); + }); + }); - if ((e.currentTarget.tagName === 'A' || $me.attr('form')) && !e.isDefaultPrevented()) { - $form.submit(); - e.preventDefault(); - } - } - }); - }; + if ((e.currentTarget.tagName === 'A' || $me.attr('form')) && !e.isDefaultPrevented()) { + $form.submit(); + e.preventDefault(); + } + } + }); + }; - /** - * Adds a callback being executed before submit - * - * @param {function} callback - */ - SplitButtons.addPreSubmitCallback = function(callback) { - if (typeof callback !== 'function') { - throw 'callback must be a function.'; - } + /** + * Adds a callback being executed before submit + * + * @param {function} callback + */ + SplitButtons.addPreSubmitCallback = function(callback) { + if (typeof callback !== 'function') { + throw 'callback must be a function.'; + } - SplitButtons.preSubmitCallbacks.push(callback); - }; + SplitButtons.preSubmitCallbacks.push(callback); + }; - $(SplitButtons.initializeSaveHandling); + $(SplitButtons.initializeSaveHandling); - return SplitButtons; + return SplitButtons; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js index e6f6fb24098c7a24d7e910a4db8028072d565e83..eb8b99e69f6711d559bd47afe4e37194f2dee5a4 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js @@ -23,16 +23,16 @@ define( 'TYPO3/CMS/Backend/Severity', 'TYPO3/CMS/Backend/Notification', 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Lang/Lang', + 'TYPO3/CMS/Lang/Lang' ], - function ($, d3, ContextMenu, Modal, Severity, Notification, Icons) { + function($, d3, ContextMenu, Modal, Severity, Notification, Icons) { 'use strict'; /** * @constructor * @exports SvgTree */ - var SvgTree = function () { + var SvgTree = function() { this.settings = { showCheckboxes: false, showIcons: false, @@ -45,7 +45,7 @@ define( dataUrl: '', nodeOver: {}, validation: { - maxItems: Number.MAX_VALUE, + maxItems: Number.MAX_VALUE }, unselectableElements: [], expandUpToLevel: null, @@ -53,7 +53,7 @@ define( /** * List node identifiers which can not be selected together with any other node */ - exclusiveNodesIdentifiers: '', + exclusiveNodesIdentifiers: '' }; /** @@ -154,7 +154,7 @@ define( * @param {String} selector * @param {Object} settings */ - initialize: function (selector, settings) { + initialize: function(selector, settings) { var $wrapper = $(selector); // Do nothing if already initialized @@ -191,10 +191,10 @@ define( this.svg = this.d3wrapper.append('svg') .attr('version', '1.1') .attr('width', '100%') - .on('mouseover', function () { + .on('mouseover', function() { _this.isOverSvg = true; }) - .on('mouseout', function () { + .on('mouseout', function() { _this.isOverSvg = false; }); @@ -216,7 +216,7 @@ define( this.updateScrollPosition(); this.loadData(); - this.wrapper.on('resize scroll', function () { + this.wrapper.on('resize scroll', function() { _this.updateScrollPosition(); _this.update(); }); @@ -232,10 +232,10 @@ define( /** * Update svg tree after changed window height */ - resize: function () { + resize: function() { var _this = this; - $(window).resize(function () { + $(window).resize(function() { _this.setWrapperHeight(); _this.updateScrollPosition(); _this.update(); @@ -245,7 +245,7 @@ define( /** * Set svg wrapper height */ - setWrapperHeight: function () { + setWrapperHeight: function() { var treeWrapperHeight = ($('#typo3-pagetree').height() - $('#svg-toolbar').height()); $('#typo3-pagetree-tree').height(treeWrapperHeight); }, @@ -253,7 +253,7 @@ define( /** * Updates variables used for visible nodes calculation */ - updateScrollPosition: function () { + updateScrollPosition: function() { this.viewportHeight = this.wrapper.height(); this.scrollTop = this.wrapper.scrollTop(); this.scrollBottom = this.scrollTop + this.viewportHeight + (this.viewportHeight / 2); @@ -262,17 +262,17 @@ define( /** * Loads tree data (json) from configured url */ - loadData: function () { + loadData: function() { var _this = this; _this.nodesAddPlaceholder(); - d3.json(this.settings.dataUrl, function (error, json) { + d3.json(this.settings.dataUrl, function(error, json) { if (error) { var title = TYPO3.lang.pagetree_networkErrorTitle; var desc = TYPO3.lang.pagetree_networkErrorDesc; if (error && error.target && (error.target.status || error.target.statusText)) { - title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || ''); + title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || ''); } Notification.error( @@ -294,7 +294,7 @@ define( * * @param {Node[]} nodes */ - replaceData: function (nodes) { + replaceData: function(nodes) { var _this = this; _this.setParametersNode(nodes); @@ -311,11 +311,11 @@ define( * * @param {Node[]} nodes */ - setParametersNode: function (nodes) { + setParametersNode: function(nodes) { var _this = this; nodes = nodes || this.nodes; - nodes = nodes.map(function (node, index) { + nodes = nodes.map(function(node, index) { node.expanded = (_this.settings.expandUpToLevel !== null) ? node.depth < _this.settings.expandUpToLevel : Boolean(node.expanded); node.parents = []; node.parentsStateIdentifier = []; @@ -353,14 +353,14 @@ define( _this.nodes = nodes; }, - nodesRemovePlaceholder: function () { + nodesRemovePlaceholder: function() { $('.svg-tree').find('.node-loader').hide(); $('.svg-tree').find('.svg-tree-loader').hide(); }, - nodesAddPlaceholder: function (node) { + nodesAddPlaceholder: function(node) { if (node) { - $('.svg-tree').find('.node-loader').css({ top: node.y + this.settings.marginTop }).show(); + $('.svg-tree').find('.node-loader').css({top: node.y + this.settings.marginTop}).show(); } else { $('.svg-tree').find('.svg-tree-loader').show(); } @@ -371,18 +371,18 @@ define( * and enriches dataset with additional properties * Visible dataset is stored in this.data */ - prepareDataForVisibleNodes: function () { + prepareDataForVisibleNodes: function() { var _this = this; var blacklist = {}; - this.nodes.map(function (node, index) { + this.nodes.map(function(node, index) { if (!node.expanded) { blacklist[index] = true; } }); - this.data.nodes = this.nodes.filter(function (node) { - return node.hidden !== true && !node.parents.some(function (index) { + this.data.nodes = this.nodes.filter(function(node) { + return node.hidden !== true && !node.parents.some(function(index) { return Boolean(blacklist[index]); }); }); @@ -390,7 +390,7 @@ define( this.data.links = []; var pathAboveMounts = 0; - this.data.nodes.forEach(function (n, i) { + this.data.nodes.forEach(function(n, i) { // delete n.children; n.x = n.depth * _this.settings.indentWidth; @@ -402,7 +402,7 @@ define( if (n.parents[0] !== undefined) { _this.data.links.push({ source: _this.nodes[n.parents[0]], - target: n, + target: n }); } @@ -421,7 +421,7 @@ define( * @param {String} iconName * @param {Boolean} update */ - fetchIcon: function (iconName, update) { + fetchIcon: function(iconName, update) { if (!iconName) { return; } @@ -434,9 +434,9 @@ define( if (!(iconName in this.data.icons)) { this.data.icons[iconName] = { identifier: iconName, - icon: '', + icon: '' }; - Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function (icon) { + Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) { var result = icon.match(/<svg[\s\S]*<\/svg>/i); // Check if the icon is from the Bitmap Icon Provider (see PHP class for the inline rendering) @@ -458,17 +458,17 @@ define( /** * Renders the subset of the tree nodes fitting the viewport (adding, modifying and removing SVG nodes) */ - update: function () { + update: function() { var _this = this; var visibleRows = Math.ceil(_this.viewportHeight / _this.settings.nodeHeight + 1); var position = Math.floor(Math.max(_this.scrollTop, 0) / _this.settings.nodeHeight); var visibleNodes = this.data.nodes.slice(position, position + visibleRows); - var nodes = this.nodesContainer.selectAll('.node').data(visibleNodes, function (d) { + var nodes = this.nodesContainer.selectAll('.node').data(visibleNodes, function(d) { return d.stateIdentifier; }); - var nodesBg = this.nodesBgContainer.selectAll('.node-bg').data(visibleNodes, function (d) { + var nodesBg = this.nodesBgContainer.selectAll('.node-bg').data(visibleNodes, function(d) { return d.stateIdentifier; }); @@ -486,10 +486,10 @@ define( var nodeBgClass = this.updateNodeBgClass(nodesBg); nodeBgClass - .attr('class', function (node, i) { + .attr('class', function(node, i) { return _this.getNodeBgClass(node, i, nodeBgClass); }) - .attr('style', function (node) { + .attr('style', function(node) { return node.backgroundColor ? 'fill: ' + node.backgroundColor + ';' : ''; }); @@ -529,7 +529,7 @@ define( * @param {Node} nodesBg * @returns {Node} nodesBg */ - updateNodeBgClass: function (nodesBg) { + updateNodeBgClass: function(nodesBg) { var _this = this; return nodesBg.enter() @@ -539,17 +539,17 @@ define( .attr('height', this.settings.nodeHeight) .attr('data-state-id', this.getNodeStateIdentifier) .attr('transform', this.getNodeBgTransform) - .on('mouseover', function (node) { + .on('mouseover', function(node) { _this.nodeBgEvents().mouseOver(node, this); }) - .on('mouseout', function (node) { + .on('mouseout', function(node) { _this.nodeBgEvents().mouseOut(node, this); }) - .on('click', function (node) { + .on('click', function(node) { _this.nodeBgEvents().click(node, this); _this.selectNode(node); }) - .on('contextmenu', function (node) { + .on('contextmenu', function(node) { _this.dispatch.call('nodeRightClick', node, this); }); }, @@ -558,11 +558,11 @@ define( * node background events * */ - nodeBgEvents: function () { + nodeBgEvents: function() { var _this = this; var self = {}; - self.mouseOver = function (node, element) { + self.mouseOver = function(node, element) { var elementNodeBg = _this.svg.select('.nodes-bg .node-bg[data-state-id="' + node.stateIdentifier + '"]'); node.isOver = true; @@ -576,7 +576,7 @@ define( } }; - self.mouseOut = function (node, element) { + self.mouseOut = function(node, element) { var elementNodeBg = _this.svg.select('.nodes-bg .node-bg[data-state-id="' + node.stateIdentifier + '"]'); node.isOver = false; @@ -590,10 +590,10 @@ define( } }; - self.click = function (node, element) { + self.click = function(node, element) { var $nodeBg = $(element).closest('svg').find('.nodes-bg .node-bg[data-state-id=' + node.stateIdentifier + ']'); - _this.nodes.forEach(function (node) { + _this.nodes.forEach(function(node) { if (node.selected === true) { node.selected = false; } @@ -615,9 +615,9 @@ define( /** * Renders links(lines) between parent and child nodes */ - updateLinks: function () { + updateLinks: function() { var _this = this; - var visibleLinks = this.data.links.filter(function (linkData) { + var visibleLinks = this.data.links.filter(function(linkData) { return linkData.source.y <= _this.scrollBottom && linkData.target.y >= _this.scrollTop; }); @@ -646,18 +646,18 @@ define( * @param {Selection} nodes * @returns {Selection} */ - enterSvgElements: function (nodes) { + enterSvgElements: function(nodes) { var _this = this; this.textPosition = 10; if (this.settings.showIcons) { - var iconsArray = $.map(this.data.icons, function (value) { + var iconsArray = $.map(this.data.icons, function(value) { if (value.icon !== '') return value; }); var icons = this.iconsContainer .selectAll('.icon-def') - .data(iconsArray, function (i) { + .data(iconsArray, function(i) { return i.stateIdentifier; }); @@ -665,10 +665,10 @@ define( .enter() .append('g') .attr('class', 'icon-def') - .attr('id', function (i) { + .attr('id', function(i) { return 'icon-' + i.identifier; }) - .append(function (i) { + .append(function(i) { // workaround for IE11 where you can't simply call .html(content) on svg var parser = new DOMParser(); var markupText = i.icon.replace('<svg', '<g').replace('/svg>', '/g>'); @@ -687,7 +687,7 @@ define( .attr('class', 'toggle') .attr('visibility', this.getToggleVisibility) .attr('transform', 'translate(-8, -8)') - .on('click', function (node) { + .on('click', function(node) { _this.chevronClick(node); }); @@ -710,7 +710,7 @@ define( .attr('y', -8) .attr('class', 'node-icon') .attr('data-uid', this.getNodeIdentifier) - .on('click', function (node) { + .on('click', function(node) { _this.clickOnIcon(node, this); }); @@ -719,7 +719,7 @@ define( .attr('x', 8) .attr('y', -3) .attr('class', 'node-icon-overlay') - .on('click', function (node) { + .on('click', function(node) { _this.clickOnIcon(node, this); }); } @@ -741,7 +741,7 @@ define( * @param {Node} node * @returns {Node} node */ - appendTextElement: function (node) { + appendTextElement: function(node) { var _this = this; return node @@ -749,7 +749,7 @@ define( .attr('dx', this.textPosition) .attr('dy', 5) .attr('class', 'node-name') - .on('click', function (node) { + .on('click', function(node) { _this.clickOnLabel(node, this); _this.nodeBgEvents().click(node, this); _this.selectNode(node); @@ -760,7 +760,7 @@ define( * @param {Node} nodes * @returns {Node} nodes */ - nodesUpdate: function (nodes) { + nodesUpdate: function(nodes) { var _this = this; nodes = nodes @@ -771,25 +771,25 @@ define( .attr('data-table', 'pages') .attr('data-state-id', this.getNodeStateIdentifier) .attr('title', this.getNodeTitle) - .on('mouseover', function (node) { + .on('mouseover', function(node) { _this.nodeBgEvents().mouseOver(node, this); }) - .on('mouseout', function (node) { + .on('mouseout', function(node) { _this.nodeBgEvents().mouseOut(node, this); }) - .on('contextmenu', function (node) { + .on('contextmenu', function(node) { _this.dispatch.call('nodeRightClick', node, this); }); var nodeStop = nodes .append('text') - .text(function (node) { + .text(function(node) { return node.readableRootline; }) .attr('class', 'node-rootline') .attr('dx', 0) .attr('dy', -15) - .attr('visibility', function (node) { + .attr('visibility', function(node) { return node.readableRootline ? 'visible' : 'hidden'; }); @@ -802,7 +802,7 @@ define( * @param {Node} node * @returns {String} */ - getNodeIdentifier: function (node) { + getNodeIdentifier: function(node) { return node.identifier; }, @@ -812,7 +812,7 @@ define( * @param {Node} node * @returns {String} */ - getNodeStateIdentifier: function (node) { + getNodeStateIdentifier: function(node) { return node.stateIdentifier; }, @@ -822,7 +822,7 @@ define( * @param {Node} node * @returns {String} */ - getNodeLabel: function (node) { + getNodeLabel: function(node) { return (node.prefix || '') + node.name + (node.suffix || ''); }, @@ -832,7 +832,7 @@ define( * @param {Node} node * @returns {String} */ - getNodeClass: function (node) { + getNodeClass: function(node) { return 'node identifier-' + node.stateIdentifier; }, @@ -844,7 +844,7 @@ define( * @param {Object} nodeBgClass * @returns {String} */ - getNodeBgClass: function (node, i, nodeBgClass) { + getNodeBgClass: function(node, i, nodeBgClass) { var bgClass = 'node-bg'; var prevNode = false; var nextNode = false; @@ -881,7 +881,7 @@ define( * @param {Node} node * @returns {String} */ - getNodeTitle: function (node) { + getNodeTitle: function(node) { return node.tip ? node.tip : 'uid=' + node.identifier; }, @@ -891,7 +891,7 @@ define( * @param {Node} node * @returns {String} */ - getChevronTransform: function (node) { + getChevronTransform: function(node) { return node.expanded ? 'translate(16,0) rotate(90)' : ' rotate(0)'; }, @@ -901,7 +901,7 @@ define( * @param {Node} node * @returns {String} */ - getChevronColor: function (node) { + getChevronColor: function(node) { return node.expanded ? '#000' : '#8e8e8e'; }, @@ -911,7 +911,7 @@ define( * @param {Node} node * @returns {String} */ - getToggleVisibility: function (node) { + getToggleVisibility: function(node) { return node.hasChildren ? 'visible' : 'hidden'; }, @@ -921,7 +921,7 @@ define( * @param {Node} node * @returns {String} */ - getChevronClass: function (node) { + getChevronClass: function(node) { return 'chevron ' + (node.expanded ? 'expanded' : 'collapsed'); }, @@ -931,7 +931,7 @@ define( * @param {Node} node * @returns {String} */ - getIconId: function (node) { + getIconId: function(node) { return '#icon-' + node.icon; }, @@ -941,7 +941,7 @@ define( * @param {Node} node * @returns {String} */ - getIconOverlayId: function (node) { + getIconOverlayId: function(node) { return '#icon-' + node.overlayIcon; }, @@ -951,10 +951,10 @@ define( * @param {Object} link * @returns {String} */ - getLinkPath: function (link) { + getLinkPath: function(link) { var target = { x: link.target._isDragged ? link.target._x : link.target.x, - y: link.target._isDragged ? link.target._y : link.target.y, + y: link.target._isDragged ? link.target._y : link.target.y }; var path = []; path.push('M' + link.source.x + ' ' + link.source.y); @@ -973,7 +973,7 @@ define( * * @param {Node} node */ - getNodeTransform: function (node) { + getNodeTransform: function(node) { return 'translate(' + (node.x || 0) + ',' + (node.y || 0) + ')'; }, @@ -982,7 +982,7 @@ define( * * @param {Node} node */ - getNodeBgTransform: function (node) { + getNodeBgTransform: function(node) { return 'translate(-8, ' + ((node.y || 0) - 10) + ')'; }, @@ -991,7 +991,7 @@ define( * * @param {Node} node */ - selectNode: function (node) { + selectNode: function(node) { if (!this.isNodeSelectable(node)) { return; } @@ -1019,14 +1019,14 @@ define( * * @param {Node} node */ - handleExclusiveNodeSelection: function (node) { + handleExclusiveNodeSelection: function(node) { var exclusiveKeys = this.settings.exclusiveNodesIdentifiers.split(','); var _this = this; if (this.settings.exclusiveNodesIdentifiers.length && node.checked === false) { if (exclusiveKeys.indexOf('' + node.identifier) > -1) { // this key is exclusive, so uncheck all others - this.nodes.forEach(function (node) { + this.nodes.forEach(function(node) { if (node.checked === true) { node.checked = false; _this.dispatch.call('nodeSelectedAfter', _this, node); @@ -1052,7 +1052,7 @@ define( * @param {Node} node * @returns {Boolean} */ - isNodeSelectable: function (node) { + isNodeSelectable: function(node) { return !this.settings.readOnlyMode && this.settings.unselectableElements.indexOf(node.identifier) === -1; }, @@ -1061,8 +1061,8 @@ define( * * @returns {Node[]} */ - getSelectedNodes: function () { - return this.nodes.filter(function (node) { + getSelectedNodes: function() { + return this.nodes.filter(function(node) { return node.checked; }); }, @@ -1073,7 +1073,7 @@ define( * @param {Node} node * @param {HTMLElement} element */ - clickOnIcon: function (node, element) { + clickOnIcon: function(node, element) { this.dispatch.call('contextmenu', node, element); }, @@ -1083,7 +1083,7 @@ define( * @param {Node} node * @param {HTMLElement} element */ - clickOnLabel: function (node, element) { + clickOnLabel: function(node, element) { this.selectNode(node); this.nodeBgEvents().click(node, element); }, @@ -1093,7 +1093,7 @@ define( * * @param {Node} node */ - chevronClick: function (node) { + chevronClick: function(node) { if (node.expanded) { this.hideChildren(node); } else { @@ -1109,7 +1109,7 @@ define( * * @param {Node} node */ - hideChildren: function (node) { + hideChildren: function(node) { node.expanded = false; }, @@ -1118,21 +1118,21 @@ define( * * @param {Node} node */ - showChildren: function (node) { + showChildren: function(node) { node.expanded = true; }, /** * Refresh view with new data */ - refreshTree: function () { + refreshTree: function() { this.loadData(); }, /** * Expand all nodes and refresh view */ - expandAll: function () { + expandAll: function() { this.nodes.forEach(this.showChildren.bind(this)); this.prepareDataForVisibleNodes(); this.update(); @@ -1141,11 +1141,11 @@ define( /** * Collapse all nodes recursively and refresh view */ - collapseAll: function () { + collapseAll: function() { this.nodes.forEach(this.hideChildren.bind(this)); this.prepareDataForVisibleNodes(); this.update(); - }, + } }; return SvgTree; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js b/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js index f5ce43154e05cc364b50c2849ff1948bc46f4347..79cb7dba09d3ee3d2fa61f69d27ce7a2329150a6 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js @@ -17,28 +17,28 @@ * @exports TYPO3/CMS/Backend/ToggleSearchToolbox */ define(['jquery', 'TYPO3/CMS/Backend/DocumentHeader', 'TYPO3/CMS/Backend/jquery.clearable'], function($, DocumentHeader) { - 'use strict'; + 'use strict'; - $(function() { - var $toolbar = $('#db_list-searchbox-toolbar'); - $('.t3js-toggle-search-toolbox').on('click', function() { - $toolbar.toggle(); - DocumentHeader.reposition(); - if ($toolbar.is(':visible')) { - $('#search_field').focus(); - } - }); + $(function() { + var $toolbar = $('#db_list-searchbox-toolbar'); + $('.t3js-toggle-search-toolbox').on('click', function() { + $toolbar.toggle(); + DocumentHeader.reposition(); + if ($toolbar.is(':visible')) { + $('#search_field').focus(); + } + }); - var $searchFields = $('#search_field'); - var searchResultShown = ('' !== $searchFields.val()); + var $searchFields = $('#search_field'); + var searchResultShown = ('' !== $searchFields.val()); - // make search field clearable - $searchFields.clearable({ - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - }); - }); + // make search field clearable + $searchFields.clearable({ + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } + } + }); + }); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js index 723dc915233575f288825fc4975b9174de101d5d..886731b62394f5826271700f39dd0261b553dc5f 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js @@ -17,44 +17,44 @@ * @exports TYPO3/CMS/Backend/Toolbar */ require( - [ - 'jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/ModuleMenu' - ], - function ($) { + [ + 'jquery', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/ModuleMenu' + ], + function($) { - TYPO3.Toolbar = {}; - TYPO3.Toolbar.App = { - initialize: function () { - this.initializeEvents(); - }, - initializeEvents: function () { - $('.t3js-toolbar-item').parent().on('hidden.bs.dropdown', function () { - $('.scaffold') - .removeClass('scaffold-toolbar-expanded') - .removeClass('scaffold-search-expanded'); - }); - $(document).on('click', '.toolbar-item [data-modulename]', function (evt) { - var moduleName = $(this).data('modulename'); - TYPO3.ModuleMenu.App.showModule(moduleName); - evt.preventDefault(); - }); - $(document).on('click', '.t3js-topbar-button-toolbar', function () { - $('.scaffold') - .removeClass('scaffold-modulemenu-expanded') - .removeClass('scaffold-search-expanded') - .toggleClass('scaffold-toolbar-expanded'); - }); - $(document).on('click', '.t3js-topbar-button-search', function () { - $('.scaffold') - .removeClass('scaffold-modulemenu-expanded') - .removeClass('scaffold-toolbar-expanded') - .toggleClass('scaffold-search-expanded'); - }); - } - }; - // start the module menu app - TYPO3.Toolbar.App.initialize(); - } + TYPO3.Toolbar = {}; + TYPO3.Toolbar.App = { + initialize: function() { + this.initializeEvents(); + }, + initializeEvents: function() { + $('.t3js-toolbar-item').parent().on('hidden.bs.dropdown', function() { + $('.scaffold') + .removeClass('scaffold-toolbar-expanded') + .removeClass('scaffold-search-expanded'); + }); + $(document).on('click', '.toolbar-item [data-modulename]', function(evt) { + var moduleName = $(this).data('modulename'); + TYPO3.ModuleMenu.App.showModule(moduleName); + evt.preventDefault(); + }); + $(document).on('click', '.t3js-topbar-button-toolbar', function() { + $('.scaffold') + .removeClass('scaffold-modulemenu-expanded') + .removeClass('scaffold-search-expanded') + .toggleClass('scaffold-toolbar-expanded'); + }); + $(document).on('click', '.t3js-topbar-button-search', function() { + $('.scaffold') + .removeClass('scaffold-modulemenu-expanded') + .removeClass('scaffold-toolbar-expanded') + .toggleClass('scaffold-search-expanded'); + }); + } + }; + // start the module menu app + TYPO3.Toolbar.App.initialize(); + } ); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js index 66041556d73fdb8d89f8903d8450d629e9a34cdb..88a00a236dc8f7489e31c05f15bf43324f000d85 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js @@ -17,71 +17,71 @@ * reloading the clear cache icon */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Viewport' + 'jquery', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Viewport' ], function($, Icons, Notification, Viewport) { - 'use strict'; + 'use strict'; - /** - * - * @type {{options: {containerSelector: string, menuItemSelector: string, toolbarIconSelector: string}}} - * @exports TYPO3/CMS/Backend/Toolbar/ClearCacheMenu - */ - var ClearCacheMenu = { - options: { - containerSelector: '#typo3-cms-backend-backend-toolbaritems-clearcachetoolbaritem', - menuItemSelector: 'a.toolbar-cache-flush-action', - toolbarIconSelector: '.toolbar-item-icon .t3js-icon', - } - }; + /** + * + * @type {{options: {containerSelector: string, menuItemSelector: string, toolbarIconSelector: string}}} + * @exports TYPO3/CMS/Backend/Toolbar/ClearCacheMenu + */ + var ClearCacheMenu = { + options: { + containerSelector: '#typo3-cms-backend-backend-toolbaritems-clearcachetoolbaritem', + menuItemSelector: 'a.toolbar-cache-flush-action', + toolbarIconSelector: '.toolbar-item-icon .t3js-icon' + } + }; - /** - * Registers listeners for the icons inside the dropdown to trigger - * the clear cache call - */ - ClearCacheMenu.initializeEvents = function() { - $(ClearCacheMenu.options.containerSelector).on('click', ClearCacheMenu.options.menuItemSelector, function(evt) { - evt.preventDefault(); - var ajaxUrl = $(this).attr('href'); - if (ajaxUrl) { - ClearCacheMenu.clearCache(ajaxUrl); - } - }); - }; + /** + * Registers listeners for the icons inside the dropdown to trigger + * the clear cache call + */ + ClearCacheMenu.initializeEvents = function() { + $(ClearCacheMenu.options.containerSelector).on('click', ClearCacheMenu.options.menuItemSelector, function(evt) { + evt.preventDefault(); + var ajaxUrl = $(this).attr('href'); + if (ajaxUrl) { + ClearCacheMenu.clearCache(ajaxUrl); + } + }); + }; - /** - * calls TYPO3 to clear a cache, then changes the topbar icon - * to a spinner. Restores the original topbar icon when the request completed. - * - * @param {String} ajaxUrl the URL to load - */ - ClearCacheMenu.clearCache = function(ajaxUrl) { - // Close clear cache menu - $(ClearCacheMenu.options.containerSelector).removeClass('open'); + /** + * calls TYPO3 to clear a cache, then changes the topbar icon + * to a spinner. Restores the original topbar icon when the request completed. + * + * @param {String} ajaxUrl the URL to load + */ + ClearCacheMenu.clearCache = function(ajaxUrl) { + // Close clear cache menu + $(ClearCacheMenu.options.containerSelector).removeClass('open'); - var $toolbarItemIcon = $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector), - $existingIcon = $toolbarItemIcon.clone(); + var $toolbarItemIcon = $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector), + $existingIcon = $toolbarItemIcon.clone(); - Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { - $toolbarItemIcon.replaceWith(spinner); - }); + Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { + $toolbarItemIcon.replaceWith(spinner); + }); - $.ajax({ - url: ajaxUrl, - type: 'post', - cache: false, - complete: function(jqXHRObject, status) { - $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector).replaceWith($existingIcon); - if (status !== 'success' || jqXHRObject.responseText !== '') { - Notification.error('An error occurs', 'An error occurred while clearing the cache. It is likely not all caches were cleared as expected.', 0); - } - } - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + cache: false, + complete: function(jqXHRObject, status) { + $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector).replaceWith($existingIcon); + if (status !== 'success' || jqXHRObject.responseText !== '') { + Notification.error('An error occurs', 'An error occurred while clearing the cache. It is likely not all caches were cleared as expected.', 0); + } + } + }); + }; - Viewport.Topbar.Toolbar.registerEvent(ClearCacheMenu.initializeEvents); + Viewport.Topbar.Toolbar.registerEvent(ClearCacheMenu.initializeEvents); - return ClearCacheMenu; + return ClearCacheMenu; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js index a9da605d7ec497101f711e090a9a9b2b5b68ffd6..3eca32db27c92ad4b97855e7c3227e7c85873178 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js @@ -17,204 +17,204 @@ * and edit a shortcut */ define(['jquery', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Viewport' - ], function($, Modal, Icons, Notification, Viewport) { - 'use strict'; - - /** - * - * @type {{options: {containerSelector: string, toolbarIconSelector: string, toolbarMenuSelector: string, shortcutItemSelector: string, shortcutDeleteSelector: string, shortcutEditSelector: string, shortcutFormTitleSelector: string, shortcutFormGroupSelector: string, shortcutFormSaveSelector: string, shortcutFormCancelSelector: string}}} - * @exports TYPO3/CMS/Backend/Toolbar/ShortcutMenu - */ - var ShortcutMenu = { - options: { - containerSelector: '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem', - toolbarIconSelector: '.dropdown-toggle span.icon', - toolbarMenuSelector: '.dropdown-menu', - - shortcutItemSelector: '.t3js-topbar-shortcut', - shortcutDeleteSelector: '.t3js-shortcut-delete', - shortcutEditSelector: '.t3js-shortcut-edit', - - shortcutFormTitleSelector: 'input[name="shortcut-title"]', - shortcutFormGroupSelector: 'select[name="shortcut-group"]', - shortcutFormSaveSelector: '.shortcut-form-save', - shortcutFormCancelSelector: '.shortcut-form-cancel', - shortcutFormSelector: '.shortcut-form' - } - }; - - /** - * build the in-place-editor for a shortcut - * - * @param {Object} $shortcutRecord - */ - ShortcutMenu.editShortcut = function($shortcutRecord) { - // load the form - $.ajax({ - url: TYPO3.settings.ajaxUrls['shortcut_editform'], - data: { - shortcutId: $shortcutRecord.data('shortcutid'), - shortcutGroup: $shortcutRecord.data('shortcutgroup') - }, - cache: false - }).done(function(data) { - $(ShortcutMenu.options.containerSelector).find(ShortcutMenu.options.toolbarMenuSelector).html(data); - }); - }; - - /** - * Save the data from the in-place-editor for a shortcut - * - * @param {Object} $shortcutForm - */ - ShortcutMenu.saveShortcutForm = function($shortcutForm) { - $.ajax({ - url: TYPO3.settings.ajaxUrls['shortcut_saveform'], - data: { - shortcutId: $shortcutForm.data('shortcutid'), - shortcutTitle: $shortcutForm.find(ShortcutMenu.options.shortcutFormTitleSelector).val(), - shortcutGroup: $shortcutForm.find(ShortcutMenu.options.shortcutFormGroupSelector).val() - }, - type: 'post', - cache: false - }).done(function(data) { - Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']); - ShortcutMenu.refreshMenu(); - }); - }; - - /** - * removes an existing short by sending an AJAX call - * - * @param {Object} $shortcutRecord - */ - ShortcutMenu.deleteShortcut = function($shortcutRecord) { - Modal.confirm(TYPO3.lang['bookmark.delete'], TYPO3.lang['bookmark.confirmDelete']) - .on('confirm.button.ok', function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['shortcut_remove'], - data: { - shortcutId: $shortcutRecord.data('shortcutid') - }, - type: 'post', - cache: false - }).done(function() { - // a reload is used in order to restore the original behaviour - // e.g. remove groups that are now empty because the last one in the group - // was removed - ShortcutMenu.refreshMenu(); - }); - $(this).trigger('modal-dismiss'); - }) - .on('confirm.button.cancel', function() { - $(this).trigger('modal-dismiss'); - }); - }; - - /** - * makes a call to the backend class to create a new shortcut, - * when finished it reloads the menu - * - * @param {String} moduleName - * @param {String} url - * @param {String} confirmationText - * @param {String} motherModule - * @param {Object} shortcutButton - * @param {String} displayName - */ - ShortcutMenu.createShortcut = function(moduleName, url, confirmationText, motherModule, shortcutButton, displayName) { - if (typeof confirmationText !== 'undefined') { - Modal.confirm(TYPO3.lang['bookmark.create'], confirmationText) - .on('confirm.button.ok', function() { - var $toolbarItemIcon = $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector), - $existingIcon = $toolbarItemIcon.clone(); - - Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { - $toolbarItemIcon.replaceWith(spinner); - }); - - $.ajax({ - url: TYPO3.settings.ajaxUrls['shortcut_create'], - type: 'post', - data: { - module: moduleName, - url: url, - motherModName: motherModule, - displayName: displayName - }, - cache: false - }).done(function() { - ShortcutMenu.refreshMenu(); - $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector).replaceWith($existingIcon); - if (typeof shortcutButton === 'object') { - Icons.getIcon('actions-system-shortcut-active', Icons.sizes.small).done(function(icons) { - $(shortcutButton).html(icons['actions-system-shortcut-active']); - }); - $(shortcutButton).addClass('active'); - $(shortcutButton).attr('title', null); - $(shortcutButton).attr('onclick', null); - } - }); - $(this).trigger('modal-dismiss'); - }) - .on('confirm.button.cancel', function() { - $(this).trigger('modal-dismiss'); - }); - } - - }; - - /** - * reloads the menu after an update - */ - ShortcutMenu.refreshMenu = function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['shortcut_list'], - type: 'get', - cache: false - }).done(function(data) { - $(ShortcutMenu.options.toolbarMenuSelector, ShortcutMenu.options.containerSelector).html(data); - }); - }; - - /** - * Registers listeners - */ - ShortcutMenu.initializeEvents = function() { - $(ShortcutMenu.options.containerSelector).on('click', ShortcutMenu.options.shortcutDeleteSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - ShortcutMenu.deleteShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector)); - }).on('click', ShortcutMenu.options.shortcutFormGroupSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - }).on('click', ShortcutMenu.options.shortcutEditSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - ShortcutMenu.editShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector)); - }).on('click', ShortcutMenu.options.shortcutFormSaveSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector)); - }).on('submit', ShortcutMenu.options.shortcutFormSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector)); - }).on('click', ShortcutMenu.options.shortcutFormCancelSelector, function(evt) { - evt.preventDefault(); - evt.stopImmediatePropagation(); - ShortcutMenu.refreshMenu(); - }); - }; - - Viewport.Topbar.Toolbar.registerEvent(ShortcutMenu.initializeEvents); - - // expose as global object - TYPO3.ShortcutMenu = ShortcutMenu; - - return ShortcutMenu; + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Viewport' +], function($, Modal, Icons, Notification, Viewport) { + 'use strict'; + + /** + * + * @type {{options: {containerSelector: string, toolbarIconSelector: string, toolbarMenuSelector: string, shortcutItemSelector: string, shortcutDeleteSelector: string, shortcutEditSelector: string, shortcutFormTitleSelector: string, shortcutFormGroupSelector: string, shortcutFormSaveSelector: string, shortcutFormCancelSelector: string}}} + * @exports TYPO3/CMS/Backend/Toolbar/ShortcutMenu + */ + var ShortcutMenu = { + options: { + containerSelector: '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem', + toolbarIconSelector: '.dropdown-toggle span.icon', + toolbarMenuSelector: '.dropdown-menu', + + shortcutItemSelector: '.t3js-topbar-shortcut', + shortcutDeleteSelector: '.t3js-shortcut-delete', + shortcutEditSelector: '.t3js-shortcut-edit', + + shortcutFormTitleSelector: 'input[name="shortcut-title"]', + shortcutFormGroupSelector: 'select[name="shortcut-group"]', + shortcutFormSaveSelector: '.shortcut-form-save', + shortcutFormCancelSelector: '.shortcut-form-cancel', + shortcutFormSelector: '.shortcut-form' + } + }; + + /** + * build the in-place-editor for a shortcut + * + * @param {Object} $shortcutRecord + */ + ShortcutMenu.editShortcut = function($shortcutRecord) { + // load the form + $.ajax({ + url: TYPO3.settings.ajaxUrls['shortcut_editform'], + data: { + shortcutId: $shortcutRecord.data('shortcutid'), + shortcutGroup: $shortcutRecord.data('shortcutgroup') + }, + cache: false + }).done(function(data) { + $(ShortcutMenu.options.containerSelector).find(ShortcutMenu.options.toolbarMenuSelector).html(data); + }); + }; + + /** + * Save the data from the in-place-editor for a shortcut + * + * @param {Object} $shortcutForm + */ + ShortcutMenu.saveShortcutForm = function($shortcutForm) { + $.ajax({ + url: TYPO3.settings.ajaxUrls['shortcut_saveform'], + data: { + shortcutId: $shortcutForm.data('shortcutid'), + shortcutTitle: $shortcutForm.find(ShortcutMenu.options.shortcutFormTitleSelector).val(), + shortcutGroup: $shortcutForm.find(ShortcutMenu.options.shortcutFormGroupSelector).val() + }, + type: 'post', + cache: false + }).done(function(data) { + Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']); + ShortcutMenu.refreshMenu(); + }); + }; + + /** + * removes an existing short by sending an AJAX call + * + * @param {Object} $shortcutRecord + */ + ShortcutMenu.deleteShortcut = function($shortcutRecord) { + Modal.confirm(TYPO3.lang['bookmark.delete'], TYPO3.lang['bookmark.confirmDelete']) + .on('confirm.button.ok', function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['shortcut_remove'], + data: { + shortcutId: $shortcutRecord.data('shortcutid') + }, + type: 'post', + cache: false + }).done(function() { + // a reload is used in order to restore the original behaviour + // e.g. remove groups that are now empty because the last one in the group + // was removed + ShortcutMenu.refreshMenu(); + }); + $(this).trigger('modal-dismiss'); + }) + .on('confirm.button.cancel', function() { + $(this).trigger('modal-dismiss'); + }); + }; + + /** + * makes a call to the backend class to create a new shortcut, + * when finished it reloads the menu + * + * @param {String} moduleName + * @param {String} url + * @param {String} confirmationText + * @param {String} motherModule + * @param {Object} shortcutButton + * @param {String} displayName + */ + ShortcutMenu.createShortcut = function(moduleName, url, confirmationText, motherModule, shortcutButton, displayName) { + if (typeof confirmationText !== 'undefined') { + Modal.confirm(TYPO3.lang['bookmark.create'], confirmationText) + .on('confirm.button.ok', function() { + var $toolbarItemIcon = $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector), + $existingIcon = $toolbarItemIcon.clone(); + + Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { + $toolbarItemIcon.replaceWith(spinner); + }); + + $.ajax({ + url: TYPO3.settings.ajaxUrls['shortcut_create'], + type: 'post', + data: { + module: moduleName, + url: url, + motherModName: motherModule, + displayName: displayName + }, + cache: false + }).done(function() { + ShortcutMenu.refreshMenu(); + $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector).replaceWith($existingIcon); + if (typeof shortcutButton === 'object') { + Icons.getIcon('actions-system-shortcut-active', Icons.sizes.small).done(function(icons) { + $(shortcutButton).html(icons['actions-system-shortcut-active']); + }); + $(shortcutButton).addClass('active'); + $(shortcutButton).attr('title', null); + $(shortcutButton).attr('onclick', null); + } + }); + $(this).trigger('modal-dismiss'); + }) + .on('confirm.button.cancel', function() { + $(this).trigger('modal-dismiss'); + }); + } + + }; + + /** + * reloads the menu after an update + */ + ShortcutMenu.refreshMenu = function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['shortcut_list'], + type: 'get', + cache: false + }).done(function(data) { + $(ShortcutMenu.options.toolbarMenuSelector, ShortcutMenu.options.containerSelector).html(data); + }); + }; + + /** + * Registers listeners + */ + ShortcutMenu.initializeEvents = function() { + $(ShortcutMenu.options.containerSelector).on('click', ShortcutMenu.options.shortcutDeleteSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + ShortcutMenu.deleteShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector)); + }).on('click', ShortcutMenu.options.shortcutFormGroupSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + }).on('click', ShortcutMenu.options.shortcutEditSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + ShortcutMenu.editShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector)); + }).on('click', ShortcutMenu.options.shortcutFormSaveSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector)); + }).on('submit', ShortcutMenu.options.shortcutFormSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector)); + }).on('click', ShortcutMenu.options.shortcutFormCancelSelector, function(evt) { + evt.preventDefault(); + evt.stopImmediatePropagation(); + ShortcutMenu.refreshMenu(); + }); + }; + + Viewport.Topbar.Toolbar.registerEvent(ShortcutMenu.initializeEvents); + + // expose as global object + TYPO3.ShortcutMenu = ShortcutMenu; + + return ShortcutMenu; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js index 47ca331caf5e6d7d66a084d4233f72b899b7fa23..4349d0c5ee18e0fe32254dbe78761ba8bacdf489 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js @@ -16,130 +16,130 @@ * System information menu handler */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Storage/Persistent', - 'TYPO3/CMS/Backend/Viewport' + 'jquery', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Storage/Persistent', + 'TYPO3/CMS/Backend/Viewport' ], function($, Icons, PersistentStorage, Viewport) { - 'use strict'; - - /** - * - * @type {{identifier: {containerSelector: string, toolbarIconSelector: string, menuContainerSelector: string, moduleLinks: string}, elements: {$counter: (*|jQuery|HTMLElement)}}} - * @exports TYPO3/CMS/Backend/Toolbar/SystemInformationMenu - */ - var SystemInformationMenu = { - identifier: { - containerSelector: '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem', - toolbarIconSelector: '.toolbar-item-icon .t3js-icon', - menuContainerSelector: '.dropdown-menu', - moduleLinks: '.t3js-systeminformation-module', - counter: '.t3js-systeminformation-counter' - } - }; - - /** - * Initialize the events - */ - SystemInformationMenu.initialize = function() { - $(SystemInformationMenu.identifier.moduleLinks).on('click', SystemInformationMenu.openModule); - }; - - /** - * Timer for auto reloading the SystemInformation - */ - SystemInformationMenu.timer = null; - - /** - * Updates the menu - */ - SystemInformationMenu.updateMenu = function() { - var $toolbarItemIcon = $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector), - $existingIcon = $toolbarItemIcon.clone(), - $menuContainer = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector); - - if (SystemInformationMenu.timer !== null) { - clearTimeout(SystemInformationMenu.timer); - SystemInformationMenu.timer = null; - } - - Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { - $toolbarItemIcon.replaceWith(spinner); - }); - - $.ajax({ - url: TYPO3.settings.ajaxUrls['systeminformation_render'], - type: 'post', - cache: false, - success: function(data) { - $menuContainer.html(data); - SystemInformationMenu.updateCounter(); - - SystemInformationMenu.initialize(); - }, - complete: function() { - $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector).replaceWith($existingIcon); - } - }).done(function(){ - // reload error data every five minutes - SystemInformationMenu.timer = setTimeout( - SystemInformationMenu.updateMenu, - 1000 * 300 - ); - }); - }; - - /** - * Updates the counter - */ - SystemInformationMenu.updateCounter = function() { - var $container = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector).find('.t3js-systeminformation-container'), - $counter = $(SystemInformationMenu.identifier.counter), - count = $container.data('count'), - badgeClass = $container.data('severityclass'); - - $counter.text(count).toggle(parseInt(count) > 0); - - // ensure all default classes are available and previous - // (at this time in processing unknown) class is removed - $counter.removeClass(); - $counter.addClass('t3js-systeminformation-counter toolbar-item-badge badge'); - // badgeClass e.g. could be 'badge-info', 'badge-danger', ... - if (badgeClass !== '') { - $counter.addClass(badgeClass); - } - }; - - /** - * Updates the UC and opens the linked module - * - * @param {Event} e - */ - SystemInformationMenu.openModule = function(e) { - e.preventDefault(); - e.stopPropagation(); - - var storedSystemInformationSettings = {}, - moduleStorageObject = {}, - requestedModule = $(e.currentTarget).data('modulename'), - moduleParams = $(e.currentTarget).data('moduleparams'), - timestamp = Math.floor((new Date()).getTime() / 1000); - - if (PersistentStorage.isset('systeminformation')) { - storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation')); - } - - moduleStorageObject[requestedModule] = {lastAccess: timestamp}; - $.extend(true, storedSystemInformationSettings, moduleStorageObject); - var $ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings)); - $ajax.done(function() { - // finally, open the module now - TYPO3.ModuleMenu.App.showModule(requestedModule, moduleParams); - Viewport.Topbar.refresh(); - }); - }; - - Viewport.Topbar.Toolbar.registerEvent(SystemInformationMenu.updateMenu); - - return SystemInformationMenu; + 'use strict'; + + /** + * + * @type {{identifier: {containerSelector: string, toolbarIconSelector: string, menuContainerSelector: string, moduleLinks: string}, elements: {$counter: (*|jQuery|HTMLElement)}}} + * @exports TYPO3/CMS/Backend/Toolbar/SystemInformationMenu + */ + var SystemInformationMenu = { + identifier: { + containerSelector: '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem', + toolbarIconSelector: '.toolbar-item-icon .t3js-icon', + menuContainerSelector: '.dropdown-menu', + moduleLinks: '.t3js-systeminformation-module', + counter: '.t3js-systeminformation-counter' + } + }; + + /** + * Initialize the events + */ + SystemInformationMenu.initialize = function() { + $(SystemInformationMenu.identifier.moduleLinks).on('click', SystemInformationMenu.openModule); + }; + + /** + * Timer for auto reloading the SystemInformation + */ + SystemInformationMenu.timer = null; + + /** + * Updates the menu + */ + SystemInformationMenu.updateMenu = function() { + var $toolbarItemIcon = $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector), + $existingIcon = $toolbarItemIcon.clone(), + $menuContainer = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector); + + if (SystemInformationMenu.timer !== null) { + clearTimeout(SystemInformationMenu.timer); + SystemInformationMenu.timer = null; + } + + Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { + $toolbarItemIcon.replaceWith(spinner); + }); + + $.ajax({ + url: TYPO3.settings.ajaxUrls['systeminformation_render'], + type: 'post', + cache: false, + success: function(data) { + $menuContainer.html(data); + SystemInformationMenu.updateCounter(); + + SystemInformationMenu.initialize(); + }, + complete: function() { + $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector).replaceWith($existingIcon); + } + }).done(function() { + // reload error data every five minutes + SystemInformationMenu.timer = setTimeout( + SystemInformationMenu.updateMenu, + 1000 * 300 + ); + }); + }; + + /** + * Updates the counter + */ + SystemInformationMenu.updateCounter = function() { + var $container = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector).find('.t3js-systeminformation-container'), + $counter = $(SystemInformationMenu.identifier.counter), + count = $container.data('count'), + badgeClass = $container.data('severityclass'); + + $counter.text(count).toggle(parseInt(count) > 0); + + // ensure all default classes are available and previous + // (at this time in processing unknown) class is removed + $counter.removeClass(); + $counter.addClass('t3js-systeminformation-counter toolbar-item-badge badge'); + // badgeClass e.g. could be 'badge-info', 'badge-danger', ... + if (badgeClass !== '') { + $counter.addClass(badgeClass); + } + }; + + /** + * Updates the UC and opens the linked module + * + * @param {Event} e + */ + SystemInformationMenu.openModule = function(e) { + e.preventDefault(); + e.stopPropagation(); + + var storedSystemInformationSettings = {}, + moduleStorageObject = {}, + requestedModule = $(e.currentTarget).data('modulename'), + moduleParams = $(e.currentTarget).data('moduleparams'), + timestamp = Math.floor((new Date()).getTime() / 1000); + + if (PersistentStorage.isset('systeminformation')) { + storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation')); + } + + moduleStorageObject[requestedModule] = {lastAccess: timestamp}; + $.extend(true, storedSystemInformationSettings, moduleStorageObject); + var $ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings)); + $ajax.done(function() { + // finally, open the module now + TYPO3.ModuleMenu.App.showModule(requestedModule, moduleParams); + Viewport.Topbar.refresh(); + }); + }; + + Viewport.Topbar.Toolbar.registerEvent(SystemInformationMenu.updateMenu); + + return SystemInformationMenu; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js index 2b2fb55993ad47c8109e44d637ec19cc1d13afe3..23c82e4e660e4582390096080f12ac28646bec85 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js @@ -16,53 +16,52 @@ * API for tooltip windows powered by Twitter Bootstrap. */ define(['jquery', 'bootstrap'], function($) { - 'use strict'; + 'use strict'; - /** - * The main tooltip object - * - * @type {{}} - * @exports TYPO3/CMS/Backend/Tooltip - */ - var Tooltip = { - }; + /** + * The main tooltip object + * + * @type {{}} + * @exports TYPO3/CMS/Backend/Tooltip + */ + var Tooltip = {}; - /** - * Initialize - */ - Tooltip.initialize = function(selector, options) { - options = options || {}; - $(selector).tooltip(options); - }; + /** + * Initialize + */ + Tooltip.initialize = function(selector, options) { + options = options || {}; + $(selector).tooltip(options); + }; - /** - * Show tooltip on $element - * - * @param {Object} $element - * @param {String} title - */ - Tooltip.show = function($element, title) { - $element - .attr('data-placement', 'auto') - .attr('data-title', title) - .tooltip('show'); - }; + /** + * Show tooltip on $element + * + * @param {Object} $element + * @param {String} title + */ + Tooltip.show = function($element, title) { + $element + .attr('data-placement', 'auto') + .attr('data-title', title) + .tooltip('show'); + }; - /** - * Hide tooltip on $element - * - * @param {Object} $element - */ - Tooltip.hide = function($element) { - $element.tooltip('hide'); - }; + /** + * Hide tooltip on $element + * + * @param {Object} $element + */ + Tooltip.hide = function($element) { + $element.tooltip('hide'); + }; - $(function () { - Tooltip.initialize('[data-toggle="tooltip"]'); - }); + $(function() { + Tooltip.initialize('[data-toggle="tooltip"]'); + }); - // expose as global object - TYPO3.Tooltip = Tooltip; + // expose as global object + TYPO3.Tooltip = Tooltip; - return Tooltip; + return Tooltip; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js b/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js index 7a4d93f0da73a22633e7977c40c38501a9e80b89..992382392c3152035514b8faac73c4c92262930f 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js @@ -17,69 +17,69 @@ * Module: TYPO3/CMS/Backend/ValueSlider */ define(['jquery', 'twbs/bootstrap-slider'], function($) { - /** - * ValueSlider object - * - * @type {{selector: string}} - * @exports TYPO3/CMS/Backend/ValueSlider - */ - var ValueSlider = { - selector: '[data-slider-id]' - }; + /** + * ValueSlider object + * + * @type {{selector: string}} + * @exports TYPO3/CMS/Backend/ValueSlider + */ + var ValueSlider = { + selector: '[data-slider-id]' + }; - /** - * Initialize all slider elements - */ - ValueSlider.initializeSlider = function() { - var $sliders = $(ValueSlider.selector); - if ($sliders.length > 0) { - $sliders.slider({ - formatter: ValueSlider.renderTooltipValue - }); - $sliders.on('change', ValueSlider.updateValue); - } - }; + /** + * Initialize all slider elements + */ + ValueSlider.initializeSlider = function() { + var $sliders = $(ValueSlider.selector); + if ($sliders.length > 0) { + $sliders.slider({ + formatter: ValueSlider.renderTooltipValue + }); + $sliders.on('change', ValueSlider.updateValue); + } + }; - /** - * Update value of slider element - * - * @param {Event} e - */ - ValueSlider.updateValue = function(e) { - var $slider = $(e.currentTarget), - $foreignField = $('[data-formengine-input-name="' + $slider.data('sliderItemName') + '"]'), - sliderField = $slider.data('sliderField'), - sliderCallbackParams = $slider.data('sliderCallbackParams'); + /** + * Update value of slider element + * + * @param {Event} e + */ + ValueSlider.updateValue = function(e) { + var $slider = $(e.currentTarget), + $foreignField = $('[data-formengine-input-name="' + $slider.data('sliderItemName') + '"]'), + sliderField = $slider.data('sliderField'), + sliderCallbackParams = $slider.data('sliderCallbackParams'); - $foreignField.val(e.value.newValue); - TBE_EDITOR.fieldChanged.apply(TBE_EDITOR, sliderCallbackParams); - }; + $foreignField.val(e.value.newValue); + TBE_EDITOR.fieldChanged.apply(TBE_EDITOR, sliderCallbackParams); + }; - /** - * - * @param {Number} value - * @returns {*} - */ - ValueSlider.renderTooltipValue = function(value) { - var renderedValue, - $slider = $('[data-slider-id="' + this.id + '"]'), - data = $slider.data(); - switch (data.sliderValueType) { - case 'double': - renderedValue = parseFloat(value).toFixed(2); - break; - case 'int': - default: - renderedValue = parseInt(value); - } + /** + * + * @param {Number} value + * @returns {*} + */ + ValueSlider.renderTooltipValue = function(value) { + var renderedValue, + $slider = $('[data-slider-id="' + this.id + '"]'), + data = $slider.data(); + switch (data.sliderValueType) { + case 'double': + renderedValue = parseFloat(value).toFixed(2); + break; + case 'int': + default: + renderedValue = parseInt(value); + } - return renderedValue; - }; + return renderedValue; + }; - // init if document is ready - $(document).ready(function() { - ValueSlider.initializeSlider(); - }); + // init if document is ready + $(document).ready(function() { + ValueSlider.initializeSlider(); + }); - return ValueSlider; + return ValueSlider; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js b/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js index 0498a4c3bf7f17fb93b053635c82a4a5bfe50f72..d1338fb4a44df2ae8b1091aae774d4ae01a6520b 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js @@ -17,251 +17,251 @@ * @exports TYPO3/CMS/Backend/Viewport */ define( - 'TYPO3/CMS/Backend/Viewport', - [ - 'jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Utility', - 'TYPO3/CMS/Backend/Event/ConsumerScope', - 'TYPO3/CMS/Backend/Event/TriggerRequest' - ], - function ($, Icons, Utility, ConsumerScope, TriggerRequest) { - 'use strict'; + 'TYPO3/CMS/Backend/Viewport', + [ + 'jquery', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Utility', + 'TYPO3/CMS/Backend/Event/ConsumerScope', + 'TYPO3/CMS/Backend/Event/TriggerRequest' + ], + function($, Icons, Utility, ConsumerScope, TriggerRequest) { + 'use strict'; - function resolveIFrameElement() { - var $iFrame = $('.t3js-scaffold-content-module-iframe:first'); - if ($iFrame.length === 0) { - return null; - } - return $iFrame.get(0); - } + function resolveIFrameElement() { + var $iFrame = $('.t3js-scaffold-content-module-iframe:first'); + if ($iFrame.length === 0) { + return null; + } + return $iFrame.get(0); + } - TYPO3.Backend = { - /** - * @type {ConsumerScope} - */ - consumerScope: ConsumerScope, + TYPO3.Backend = { + /** + * @type {ConsumerScope} + */ + consumerScope: ConsumerScope, - initialize: function() { - TYPO3.Backend.doLayout(); - $(window).on('resize', TYPO3.Backend.doLayout); - }, - /** - * This function is triggered whenever a re-layouting of component is needed - */ - doLayout: function () { - TYPO3.Backend.NavigationContainer.cleanup(); - TYPO3.Backend.NavigationContainer.calculateScrollbar(); - $('.t3js-topbar-header').css('padding-right', $('.t3js-scaffold-toolbar').outerWidth()); - }, - Loader: { - start: function() { - require(['nprogress'], function(NProgress) { - NProgress.configure({parent: '.t3js-scaffold-content-module', showSpinner: false}); - NProgress.start(); - }); - }, - finish: function() { - require(['nprogress'], function(NProgress) { - NProgress.done(); - }); - } - }, - NavigationContainer: { - instance: null, + initialize: function() { + TYPO3.Backend.doLayout(); + $(window).on('resize', TYPO3.Backend.doLayout); + }, + /** + * This function is triggered whenever a re-layouting of component is needed + */ + doLayout: function() { + TYPO3.Backend.NavigationContainer.cleanup(); + TYPO3.Backend.NavigationContainer.calculateScrollbar(); + $('.t3js-topbar-header').css('padding-right', $('.t3js-scaffold-toolbar').outerWidth()); + }, + Loader: { + start: function() { + require(['nprogress'], function(NProgress) { + NProgress.configure({parent: '.t3js-scaffold-content-module', showSpinner: false}); + NProgress.start(); + }); + }, + finish: function() { + require(['nprogress'], function(NProgress) { + NProgress.done(); + }); + } + }, + NavigationContainer: { + instance: null, - PageTree: { - refreshTree: function() { - if (TYPO3.Backend.NavigationContainer.instance !== null) { - TYPO3.Backend.NavigationContainer.instance.refreshTree(); - } - }, - setTemporaryMountPoint: function (pid) { - if (TYPO3.Backend.NavigationContainer.instance !== null) { - TYPO3.Backend.NavigationContainer.instance.setTemporaryMountPoint(pid); - } - }, - unsetTemporaryMountPoint: function () { - if (TYPO3.Backend.NavigationContainer.instance !== null) { - TYPO3.Backend.NavigationContainer.instance.unsetTemporaryMountPoint(); - } - } - }, - toggle: function () { - $('.t3js-scaffold').toggleClass('scaffold-content-navigation-expanded') - }, - cleanup: function() { - $('.t3js-scaffold-modulemenu').removeAttr('style'); - $('t3js-scaffold-content').removeAttr('style'); - }, - hide: function () { - $('.t3js-topbar-button-navigationcomponent').attr('disabled', true); - Icons.getIcon('actions-pagetree', Icons.sizes.small, 'overlay-readonly', null, Icons.markupIdentifiers.inline).done(function(icon) { - $('.t3js-topbar-button-navigationcomponent').html(icon); - }); - $('.t3js-scaffold').removeClass('scaffold-content-navigation-expanded'); - $('.t3js-scaffold-content-module').removeAttr('style'); - }, - show: function (component) { - $('.t3js-topbar-button-navigationcomponent').attr('disabled', false); - Icons.getIcon('actions-pagetree', Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) { - $('.t3js-topbar-button-navigationcomponent').html(icon); - }); - if(component !== undefined) { - $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded'); - } - $('.t3js-scaffold-content-navigation [data-component]').hide(); - $('.t3js-scaffold-content-navigation [data-component="' + component + '"]').show(); - }, - /** - * @param {string} urlToLoad - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - setUrl: function(urlToLoad, interactionRequest) { - var deferred = TYPO3.Backend.consumerScope.invoke( - new TriggerRequest('typo3.setUrl', interactionRequest) - ); - deferred.then(function() { - $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded'); - $('.t3js-scaffold-content-navigation-iframe').attr('src', urlToLoad); - }); - return deferred; - }, - getUrl: function() { - return $('.t3js-scaffold-content-navigation-iframe').attr('src'); - }, - /** - * @param {boolean} forceGet - */ - refresh: function(forceGet) { - $('.t3js-scaffold-content-navigation-iframe')[0].contentWindow.location.reload(forceGet); - }, - calculateScrollbar: function (){ - TYPO3.Backend.NavigationContainer.cleanup(); - var $scaffold = $('.t3js-scaffold'); - var $moduleMenuContainer = $('.t3js-scaffold-modulemenu'); - var $contentContainer = $('.t3js-scaffold-content'); - var $moduleMenu = $('.t3js-modulemenu'); - $moduleMenuContainer.css('overflow', 'auto'); - var moduleMenuContainerWidth = $moduleMenuContainer.outerWidth(); - var moduleMenuWidth = $moduleMenu.outerWidth(); - $moduleMenuContainer.removeAttr('style').css('overflow', 'hidden'); - if ($scaffold.hasClass('scaffold-modulemenu-expanded') === false) { - $moduleMenuContainer.width(moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth)); - $contentContainer.css('left', moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth)) - } else { - $moduleMenuContainer.removeAttr('style'); - $contentContainer.removeAttr('style'); - } - $moduleMenuContainer.css('overflow', 'auto'); - }, + PageTree: { + refreshTree: function() { + if (TYPO3.Backend.NavigationContainer.instance !== null) { + TYPO3.Backend.NavigationContainer.instance.refreshTree(); + } + }, + setTemporaryMountPoint: function(pid) { + if (TYPO3.Backend.NavigationContainer.instance !== null) { + TYPO3.Backend.NavigationContainer.instance.setTemporaryMountPoint(pid); + } + }, + unsetTemporaryMountPoint: function() { + if (TYPO3.Backend.NavigationContainer.instance !== null) { + TYPO3.Backend.NavigationContainer.instance.unsetTemporaryMountPoint(); + } + } + }, + toggle: function() { + $('.t3js-scaffold').toggleClass('scaffold-content-navigation-expanded') + }, + cleanup: function() { + $('.t3js-scaffold-modulemenu').removeAttr('style'); + $('t3js-scaffold-content').removeAttr('style'); + }, + hide: function() { + $('.t3js-topbar-button-navigationcomponent').attr('disabled', true); + Icons.getIcon('actions-pagetree', Icons.sizes.small, 'overlay-readonly', null, Icons.markupIdentifiers.inline).done(function(icon) { + $('.t3js-topbar-button-navigationcomponent').html(icon); + }); + $('.t3js-scaffold').removeClass('scaffold-content-navigation-expanded'); + $('.t3js-scaffold-content-module').removeAttr('style'); + }, + show: function(component) { + $('.t3js-topbar-button-navigationcomponent').attr('disabled', false); + Icons.getIcon('actions-pagetree', Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) { + $('.t3js-topbar-button-navigationcomponent').html(icon); + }); + if (component !== undefined) { + $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded'); + } + $('.t3js-scaffold-content-navigation [data-component]').hide(); + $('.t3js-scaffold-content-navigation [data-component="' + component + '"]').show(); + }, + /** + * @param {string} urlToLoad + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + setUrl: function(urlToLoad, interactionRequest) { + var deferred = TYPO3.Backend.consumerScope.invoke( + new TriggerRequest('typo3.setUrl', interactionRequest) + ); + deferred.then(function() { + $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded'); + $('.t3js-scaffold-content-navigation-iframe').attr('src', urlToLoad); + }); + return deferred; + }, + getUrl: function() { + return $('.t3js-scaffold-content-navigation-iframe').attr('src'); + }, + /** + * @param {boolean} forceGet + */ + refresh: function(forceGet) { + $('.t3js-scaffold-content-navigation-iframe')[0].contentWindow.location.reload(forceGet); + }, + calculateScrollbar: function() { + TYPO3.Backend.NavigationContainer.cleanup(); + var $scaffold = $('.t3js-scaffold'); + var $moduleMenuContainer = $('.t3js-scaffold-modulemenu'); + var $contentContainer = $('.t3js-scaffold-content'); + var $moduleMenu = $('.t3js-modulemenu'); + $moduleMenuContainer.css('overflow', 'auto'); + var moduleMenuContainerWidth = $moduleMenuContainer.outerWidth(); + var moduleMenuWidth = $moduleMenu.outerWidth(); + $moduleMenuContainer.removeAttr('style').css('overflow', 'hidden'); + if ($scaffold.hasClass('scaffold-modulemenu-expanded') === false) { + $moduleMenuContainer.width(moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth)); + $contentContainer.css('left', moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth)) + } else { + $moduleMenuContainer.removeAttr('style'); + $contentContainer.removeAttr('style'); + } + $moduleMenuContainer.css('overflow', 'auto'); + }, - /** - * Public method used by Naviagtion components to register themselves. - * See TYPO3/CMS/Backend/PageTree/PageTreeElement->initialize - * - * @param {Object} component - */ - setComponentInstance: function (component) { - TYPO3.Backend.NavigationContainer.instance = component; + /** + * Public method used by Naviagtion components to register themselves. + * See TYPO3/CMS/Backend/PageTree/PageTreeElement->initialize + * + * @param {Object} component + */ + setComponentInstance: function(component) { + TYPO3.Backend.NavigationContainer.instance = component; + } + }, + /** + * Content container manages the right site of the viewport (showing module specific content) + */ + ContentContainer: { + get: function() { + return $('.t3js-scaffold-content-module-iframe')[0].contentWindow; + }, + /** + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + beforeSetUrl: function(interactionRequest) { + return TYPO3.Backend.consumerScope.invoke( + new TriggerRequest('typo3.beforeSetUrl', interactionRequest) + ); + }, + /** + * @param {String} urlToLoad + * @param {InteractionRequest} [interactionRequest] + * @return {jQuery.Deferred} + */ + setUrl: function(urlToLoad, interactionRequest) { + var deferred; + var iFrame = resolveIFrameElement(); + // abort, if no IFRAME can be found + if (iFrame === null) { + deferred = $.Deferred(); + deferred.reject(); + return deferred; + } + deferred = TYPO3.Backend.consumerScope.invoke( + new TriggerRequest('typo3.setUrl', interactionRequest) + ); + deferred.then(function() { + TYPO3.Backend.Loader.start(); + $('.t3js-scaffold-content-module-iframe') + .attr('src', urlToLoad) + .one('load', function() { + TYPO3.Backend.Loader.finish(); + }); + }); + return deferred; + }, + getUrl: function() { + return $('.t3js-scaffold-content-module-iframe').attr('src'); + }, + /** + * @param {boolean} forceGet + * @param {InteractionRequest} interactionRequest + * @return {jQuery.Deferred} + */ + refresh: function(forceGet, interactionRequest) { + var deferred; + var iFrame = resolveIFrameElement(); + // abort, if no IFRAME can be found + if (iFrame === null) { + deferred = $.Deferred(); + deferred.reject(); + return deferred; + } + deferred = TYPO3.Backend.consumerScope.invoke( + new TriggerRequest('typo3.refresh', interactionRequest) + ); + deferred.then(function() { + iFrame.contentWindow.location.reload(forceGet); + }); + return deferred; + }, + getIdFromUrl: function() { + if (this.getUrl) { + return Utility.getParameterFromUrl(this.getUrl, 'id'); + } else { + return 0; + } + } + }, + Topbar: { + topbarSelector: '.t3js-scaffold-header', + refresh: function() { + $.ajax(TYPO3.settings.ajaxUrls['topbar']).done(function(data) { + $(TYPO3.Backend.Topbar.topbarSelector).html(data.topbar); + $(TYPO3.Backend.Topbar.topbarSelector).trigger('t3-topbar-update'); + }); + }, + Toolbar: { + registerEvent: function(callback) { + $(callback); + $(TYPO3.Backend.Topbar.topbarSelector).on('t3-topbar-update', callback); + } } - }, - /** - * Content container manages the right site of the viewport (showing module specific content) - */ - ContentContainer: { - get: function() { - return $('.t3js-scaffold-content-module-iframe')[0].contentWindow; - }, - /** - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - beforeSetUrl: function(interactionRequest) { - return TYPO3.Backend.consumerScope.invoke( - new TriggerRequest('typo3.beforeSetUrl', interactionRequest) - ); - }, - /** - * @param {String} urlToLoad - * @param {InteractionRequest} [interactionRequest] - * @return {jQuery.Deferred} - */ - setUrl: function (urlToLoad, interactionRequest) { - var deferred; - var iFrame = resolveIFrameElement(); - // abort, if no IFRAME can be found - if (iFrame === null) { - deferred = $.Deferred(); - deferred.reject(); - return deferred; - } - deferred = TYPO3.Backend.consumerScope.invoke( - new TriggerRequest('typo3.setUrl', interactionRequest) - ); - deferred.then(function() { - TYPO3.Backend.Loader.start(); - $('.t3js-scaffold-content-module-iframe') - .attr('src', urlToLoad) - .one('load', function() { - TYPO3.Backend.Loader.finish(); - }); - }); - return deferred; - }, - getUrl: function() { - return $('.t3js-scaffold-content-module-iframe').attr('src'); - }, - /** - * @param {boolean} forceGet - * @param {InteractionRequest} interactionRequest - * @return {jQuery.Deferred} - */ - refresh: function(forceGet, interactionRequest) { - var deferred; - var iFrame = resolveIFrameElement(); - // abort, if no IFRAME can be found - if (iFrame === null) { - deferred = $.Deferred(); - deferred.reject(); - return deferred; - } - deferred = TYPO3.Backend.consumerScope.invoke( - new TriggerRequest('typo3.refresh', interactionRequest) - ); - deferred.then(function() { - iFrame.contentWindow.location.reload(forceGet); - }); - return deferred; - }, - getIdFromUrl: function() { - if(this.getUrl) { - return Utility.getParameterFromUrl(this.getUrl, 'id'); - } else { - return 0; - } - } - }, - Topbar: { - topbarSelector: '.t3js-scaffold-header', - refresh: function() { - $.ajax(TYPO3.settings.ajaxUrls['topbar']).done(function(data) { - $(TYPO3.Backend.Topbar.topbarSelector).html(data.topbar); - $(TYPO3.Backend.Topbar.topbarSelector).trigger('t3-topbar-update'); - }); - }, - Toolbar: { - registerEvent: function (callback) { - $(callback); - $(TYPO3.Backend.Topbar.topbarSelector).on('t3-topbar-update', callback); - } - } - } - }; + } + }; - // start the module menu app - TYPO3.Backend.initialize(); - return TYPO3.Backend; - } + // start the module menu app + TYPO3.Backend.initialize(); + return TYPO3.Backend; + } ); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js index 79d12b29d5996fb329cfd5d3792aee697e7ba48e..bbb7fc5eeca1f886ee9bf5fc241fa77da9a57463 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js @@ -16,345 +16,345 @@ * API for wizard windows. */ define(['jquery', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Icons', - 'bootstrap' + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Icons', + 'bootstrap' ], function($, Modal, Severity, Icons) { - 'use strict'; - - try { - // fetch from parent - if (parent && parent.window.TYPO3 && parent.window.TYPO3.Wizard) { - return parent.window.TYPO3.Wizard; - } - - // fetch object from outer frame - if (top && top.TYPO3 && top.TYPO3.Wizard) { - return top.TYPO3.Wizard; - } - } catch (e) { - // This only happens if the opener, parent or top is some other url (eg a local file) - // which loaded the current window. Then the browser's cross domain policy jumps in - // and raises an exception. - // For this case we are safe and we can create our global object below. - } - - /** - * @type {{setup: {slides: Array, settings: {}, forceSelection: boolean, $carousel: null}, originalSetup: {}}} - * @exports TYPO3/CMS/Backend/Wizard - */ - var Wizard = { - setup: { - slides: [], - settings: {}, - forceSelection: true, - $carousel: null - }, - originalSetup: {} - }; - - /** - * Initializes the events after building the wizards - * - * @private - */ - Wizard.initializeEvents = function() { - var $modal = Wizard.setup.$carousel.closest('.modal'), - $modalTitle = $modal.find('.modal-title'), - $modalFooter = $modal.find('.modal-footer'), - $nextButton = $modalFooter.find('button[name="next"]'); - - $nextButton.on('click', function() { - Wizard.setup.$carousel.carousel('next'); - }); - - Wizard.setup.$carousel.on('slide.bs.carousel', function() { - var nextSlideNumber = Wizard.setup.$carousel.data('currentSlide') + 1, - currentIndex = Wizard.setup.$carousel.data('currentIndex') + 1; - - $modalTitle.text(Wizard.setup.slides[currentIndex].title); - - Wizard.setup.$carousel.data('currentSlide', nextSlideNumber); - Wizard.setup.$carousel.data('currentIndex', currentIndex); - - if (nextSlideNumber >= Wizard.setup.$carousel.data('realSlideCount')) { - // Point of no return - hide modal footer disable any closing ability - $modal.find('.modal-header .close').remove(); - $modalFooter.slideUp(); - } else { - $modalFooter.find('.progress-bar') - .width(Wizard.setup.$carousel.data('initialStep') * nextSlideNumber + '%') - .text(top.TYPO3.lang['wizard.progress'] - .replace('{0}', nextSlideNumber) - .replace('{1}', Wizard.setup.$carousel.data('slideCount'))); - } - - $nextButton - .removeClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex -1].severity)) - .addClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity)); - - $modal - .removeClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex -1].severity)) - .addClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity)); - }).on('slid.bs.carousel', function(e) { - var currentIndex = Wizard.setup.$carousel.data('currentIndex'), - slide = Wizard.setup.slides[currentIndex]; - - Wizard.runSlideCallback(slide, $(e.relatedTarget)); - - if (Wizard.setup.forceSelection) { - Wizard.lockNextStep(); - } - }); - - /** - * Custom event, closes the wizard - */ - var cmp = Wizard.getComponent(); - cmp.on('wizard-dismiss', Wizard.dismiss); - - Modal.currentModal.on('hidden.bs.modal', function() { - cmp.trigger('wizard-dismissed'); - }).on('shown.bs.modal', function() { - cmp.trigger('wizard-visible'); - }); - }; - - /** - * @param {String} key - * @param {*} value - * @returns {Object} - */ - Wizard.set = function(key, value) { - Wizard.setup.settings[key] = value; - return Wizard; - }; - - /** - * Adds a new slide to the wizard - * - * @param {String} identifier - * @param {String} title - * @param {String} content - * @param {String} severity - * @param {Function} callback - * @returns {Object} - */ - Wizard.addSlide = function(identifier, title, content, severity, callback) { - Wizard.setup.slides.push({ - identifier: identifier, - title: title, - content: content || '', - severity: (typeof severity !== 'undefined' ? severity : Severity.info), - callback: callback - }); - - return Wizard; - }; - - /** - * Adds a final processing slide - * - * @param {Function} callback - * @returns {Object} - */ - Wizard.addFinalProcessingSlide = function(callback) { - if (typeof callback !== 'function') { - callback = function() { - Wizard.dismiss(); - } - } - - return Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { - var $processingSlide = $('<div />', {class: 'text-center'}).append(markup); - Wizard.addSlide( - 'final-processing-slide', top.TYPO3.lang['wizard.processing.title'], - $processingSlide[0].outerHTML, - Severity.info, - callback - ); - }); - }; - - /** - * Processes the footer of the modal - * - * @private - */ - Wizard.addProgressBar = function() { - var realSlideCount = Wizard.setup.$carousel.find('.item').length, - slideCount = Math.max(1, realSlideCount), - initialStep, - $modal = Wizard.setup.$carousel.closest('.modal'), - $modalFooter = $modal.find('.modal-footer'); - - initialStep = Math.round(100 / slideCount); - - Wizard.setup.$carousel - .data('initialStep', initialStep) - .data('slideCount', slideCount) - .data('realSlideCount', realSlideCount) - .data('currentIndex', 0) - .data('currentSlide', 1); - - // Append progress bar to modal footer - if (slideCount > 1) { - $modalFooter.prepend( - $('<div />', {class: 'progress'}).append( - $('<div />', { - role: 'progressbar', - class: 'progress-bar', - 'aria-valuemin': 0, - 'aria-valuenow': initialStep, - 'aria-valuemax': 100 - }).width(initialStep + '%').text( - top.TYPO3.lang['wizard.progress'] - .replace('{0}', '1') - .replace('{1}', slideCount) - ) - ) - ); - } - }; - - /** - * Generates the markup of slides added by addSlide() - * - * @returns {$} - * @private - */ - Wizard.generateSlides = function() { - // Check whether the slides were already generated - if (Wizard.setup.$carousel !== null) { - return Wizard.setup.$carousel; - } - - var slides = - '<div class="carousel slide" data-ride="carousel" data-interval="false">' - + '<div class="carousel-inner" role="listbox">'; - - for (var i = 0; i < Wizard.setup.slides.length; ++i) { - var currentSlide = Wizard.setup.slides[i], - slideContent = currentSlide.content; - - if (typeof slideContent === 'object') { - slideContent = slideContent.html(); - } - slides += '<div class="item" data-slide="' + currentSlide.identifier + '">' + slideContent + '</div>'; - } - - slides += '</div></div>'; - - Wizard.setup.$carousel = $(slides); - Wizard.setup.$carousel.find('.item').first().addClass('active'); - - return Wizard.setup.$carousel; - }; - - /** - * Renders the wizard - * - * @returns {$} - */ - Wizard.show = function() { - var $slides = Wizard.generateSlides(), - firstSlide = Wizard.setup.slides[0]; - - var $modal = Modal.confirm( - firstSlide.title, - $slides, - firstSlide.severity, - [{ - text: top.TYPO3.lang['wizard.button.cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function() { - Wizard.getComponent().trigger('wizard-dismiss'); - } - }, { - text: top.TYPO3.lang['wizard.button.next'], - btnClass: 'btn-' + Severity.getCssClass(firstSlide.severity), - name: 'next' - }] - ); - - if (Wizard.setup.forceSelection) { - Wizard.lockNextStep(); - } - - Wizard.addProgressBar($modal); - Wizard.initializeEvents(); - - Wizard.getComponent().on('wizard-visible', function() { - Wizard.runSlideCallback(firstSlide, Wizard.setup.$carousel.find('.item').first()); - }).on('wizard-dismissed', function() { - Wizard.setup = $.extend(true, {}, Wizard.originalSetup); - }); - }; - - /** - * Runs the callback for the given slide - * - * @param {Object} slide - * @param {$} $slide - * @private - */ - Wizard.runSlideCallback = function(slide, $slide) { - if (typeof slide.callback === 'function') { - slide.callback($slide, Wizard.setup.settings, slide.identifier); - } - }; - - /** - * Get the wizard component - * - * @returns {$} - */ - Wizard.getComponent = function() { - if (Wizard.setup.$carousel === null) { - Wizard.generateSlides(); - } - return Wizard.setup.$carousel; - }; - - /** - * Closes the wizard window - */ - Wizard.dismiss = function() { - Modal.dismiss(); - }; - - /** - * Locks the button for continuing to the next step - * - * @returns {$} - */ - Wizard.lockNextStep = function() { - var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]'); - $button.prop('disabled', true); - - return $button; - }; - - /** - * Unlocks the button for continuing to the next step - * - * @returns {$} - */ - Wizard.unlockNextStep = function() { - var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]'); - $button.prop('disabled', false); - - return $button; - }; - - // Store the initial setup - Wizard.originalSetup = $.extend(true, {}, Wizard.setup); - - // expose as global object - TYPO3.Wizard = Wizard; - - return Wizard; + 'use strict'; + + try { + // fetch from parent + if (parent && parent.window.TYPO3 && parent.window.TYPO3.Wizard) { + return parent.window.TYPO3.Wizard; + } + + // fetch object from outer frame + if (top && top.TYPO3 && top.TYPO3.Wizard) { + return top.TYPO3.Wizard; + } + } catch (e) { + // This only happens if the opener, parent or top is some other url (eg a local file) + // which loaded the current window. Then the browser's cross domain policy jumps in + // and raises an exception. + // For this case we are safe and we can create our global object below. + } + + /** + * @type {{setup: {slides: Array, settings: {}, forceSelection: boolean, $carousel: null}, originalSetup: {}}} + * @exports TYPO3/CMS/Backend/Wizard + */ + var Wizard = { + setup: { + slides: [], + settings: {}, + forceSelection: true, + $carousel: null + }, + originalSetup: {} + }; + + /** + * Initializes the events after building the wizards + * + * @private + */ + Wizard.initializeEvents = function() { + var $modal = Wizard.setup.$carousel.closest('.modal'), + $modalTitle = $modal.find('.modal-title'), + $modalFooter = $modal.find('.modal-footer'), + $nextButton = $modalFooter.find('button[name="next"]'); + + $nextButton.on('click', function() { + Wizard.setup.$carousel.carousel('next'); + }); + + Wizard.setup.$carousel.on('slide.bs.carousel', function() { + var nextSlideNumber = Wizard.setup.$carousel.data('currentSlide') + 1, + currentIndex = Wizard.setup.$carousel.data('currentIndex') + 1; + + $modalTitle.text(Wizard.setup.slides[currentIndex].title); + + Wizard.setup.$carousel.data('currentSlide', nextSlideNumber); + Wizard.setup.$carousel.data('currentIndex', currentIndex); + + if (nextSlideNumber >= Wizard.setup.$carousel.data('realSlideCount')) { + // Point of no return - hide modal footer disable any closing ability + $modal.find('.modal-header .close').remove(); + $modalFooter.slideUp(); + } else { + $modalFooter.find('.progress-bar') + .width(Wizard.setup.$carousel.data('initialStep') * nextSlideNumber + '%') + .text(top.TYPO3.lang['wizard.progress'] + .replace('{0}', nextSlideNumber) + .replace('{1}', Wizard.setup.$carousel.data('slideCount'))); + } + + $nextButton + .removeClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex - 1].severity)) + .addClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity)); + + $modal + .removeClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex - 1].severity)) + .addClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity)); + }).on('slid.bs.carousel', function(e) { + var currentIndex = Wizard.setup.$carousel.data('currentIndex'), + slide = Wizard.setup.slides[currentIndex]; + + Wizard.runSlideCallback(slide, $(e.relatedTarget)); + + if (Wizard.setup.forceSelection) { + Wizard.lockNextStep(); + } + }); + + /** + * Custom event, closes the wizard + */ + var cmp = Wizard.getComponent(); + cmp.on('wizard-dismiss', Wizard.dismiss); + + Modal.currentModal.on('hidden.bs.modal', function() { + cmp.trigger('wizard-dismissed'); + }).on('shown.bs.modal', function() { + cmp.trigger('wizard-visible'); + }); + }; + + /** + * @param {String} key + * @param {*} value + * @returns {Object} + */ + Wizard.set = function(key, value) { + Wizard.setup.settings[key] = value; + return Wizard; + }; + + /** + * Adds a new slide to the wizard + * + * @param {String} identifier + * @param {String} title + * @param {String} content + * @param {String} severity + * @param {Function} callback + * @returns {Object} + */ + Wizard.addSlide = function(identifier, title, content, severity, callback) { + Wizard.setup.slides.push({ + identifier: identifier, + title: title, + content: content || '', + severity: (typeof severity !== 'undefined' ? severity : Severity.info), + callback: callback + }); + + return Wizard; + }; + + /** + * Adds a final processing slide + * + * @param {Function} callback + * @returns {Object} + */ + Wizard.addFinalProcessingSlide = function(callback) { + if (typeof callback !== 'function') { + callback = function() { + Wizard.dismiss(); + } + } + + return Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { + var $processingSlide = $('<div />', {class: 'text-center'}).append(markup); + Wizard.addSlide( + 'final-processing-slide', top.TYPO3.lang['wizard.processing.title'], + $processingSlide[0].outerHTML, + Severity.info, + callback + ); + }); + }; + + /** + * Processes the footer of the modal + * + * @private + */ + Wizard.addProgressBar = function() { + var realSlideCount = Wizard.setup.$carousel.find('.item').length, + slideCount = Math.max(1, realSlideCount), + initialStep, + $modal = Wizard.setup.$carousel.closest('.modal'), + $modalFooter = $modal.find('.modal-footer'); + + initialStep = Math.round(100 / slideCount); + + Wizard.setup.$carousel + .data('initialStep', initialStep) + .data('slideCount', slideCount) + .data('realSlideCount', realSlideCount) + .data('currentIndex', 0) + .data('currentSlide', 1); + + // Append progress bar to modal footer + if (slideCount > 1) { + $modalFooter.prepend( + $('<div />', {class: 'progress'}).append( + $('<div />', { + role: 'progressbar', + class: 'progress-bar', + 'aria-valuemin': 0, + 'aria-valuenow': initialStep, + 'aria-valuemax': 100 + }).width(initialStep + '%').text( + top.TYPO3.lang['wizard.progress'] + .replace('{0}', '1') + .replace('{1}', slideCount) + ) + ) + ); + } + }; + + /** + * Generates the markup of slides added by addSlide() + * + * @returns {$} + * @private + */ + Wizard.generateSlides = function() { + // Check whether the slides were already generated + if (Wizard.setup.$carousel !== null) { + return Wizard.setup.$carousel; + } + + var slides = + '<div class="carousel slide" data-ride="carousel" data-interval="false">' + + '<div class="carousel-inner" role="listbox">'; + + for (var i = 0; i < Wizard.setup.slides.length; ++i) { + var currentSlide = Wizard.setup.slides[i], + slideContent = currentSlide.content; + + if (typeof slideContent === 'object') { + slideContent = slideContent.html(); + } + slides += '<div class="item" data-slide="' + currentSlide.identifier + '">' + slideContent + '</div>'; + } + + slides += '</div></div>'; + + Wizard.setup.$carousel = $(slides); + Wizard.setup.$carousel.find('.item').first().addClass('active'); + + return Wizard.setup.$carousel; + }; + + /** + * Renders the wizard + * + * @returns {$} + */ + Wizard.show = function() { + var $slides = Wizard.generateSlides(), + firstSlide = Wizard.setup.slides[0]; + + var $modal = Modal.confirm( + firstSlide.title, + $slides, + firstSlide.severity, + [{ + text: top.TYPO3.lang['wizard.button.cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + Wizard.getComponent().trigger('wizard-dismiss'); + } + }, { + text: top.TYPO3.lang['wizard.button.next'], + btnClass: 'btn-' + Severity.getCssClass(firstSlide.severity), + name: 'next' + }] + ); + + if (Wizard.setup.forceSelection) { + Wizard.lockNextStep(); + } + + Wizard.addProgressBar($modal); + Wizard.initializeEvents(); + + Wizard.getComponent().on('wizard-visible', function() { + Wizard.runSlideCallback(firstSlide, Wizard.setup.$carousel.find('.item').first()); + }).on('wizard-dismissed', function() { + Wizard.setup = $.extend(true, {}, Wizard.originalSetup); + }); + }; + + /** + * Runs the callback for the given slide + * + * @param {Object} slide + * @param {$} $slide + * @private + */ + Wizard.runSlideCallback = function(slide, $slide) { + if (typeof slide.callback === 'function') { + slide.callback($slide, Wizard.setup.settings, slide.identifier); + } + }; + + /** + * Get the wizard component + * + * @returns {$} + */ + Wizard.getComponent = function() { + if (Wizard.setup.$carousel === null) { + Wizard.generateSlides(); + } + return Wizard.setup.$carousel; + }; + + /** + * Closes the wizard window + */ + Wizard.dismiss = function() { + Modal.dismiss(); + }; + + /** + * Locks the button for continuing to the next step + * + * @returns {$} + */ + Wizard.lockNextStep = function() { + var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]'); + $button.prop('disabled', true); + + return $button; + }; + + /** + * Unlocks the button for continuing to the next step + * + * @returns {$} + */ + Wizard.unlockNextStep = function() { + var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]'); + $button.prop('disabled', false); + + return $button; + }; + + // Store the initial setup + Wizard.originalSetup = $.extend(true, {}, Wizard.setup); + + // expose as global object + TYPO3.Wizard = Wizard; + + return Wizard; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js index f8e8171948c941ec499283f11b4334d88b4a4f47..8cc79e735da0586df66cf5f55b7ad5bd608a1b28 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js @@ -15,61 +15,61 @@ * Module: TYPO3/CMS/Backend/Wizard/Colorpicker * Colorpicker JavaScript */ -define(['jquery'], function ($) { - 'use strict'; +define(['jquery'], function($) { + 'use strict'; - /** - * - * @type {{options: {}}} - * @exports TYPO3/CMS/Backend/Wizard/Colorpicker - */ - var Colorpicker = { - options: {} - }; + /** + * + * @type {{options: {}}} + * @exports TYPO3/CMS/Backend/Wizard/Colorpicker + */ + var Colorpicker = { + options: {} + }; - /** - * - * @param {Object} options - */ - Colorpicker.setFieldChangeFunctions = function(options) { - Colorpicker.options = options; - }; + /** + * + * @param {Object} options + */ + Colorpicker.setFieldChangeFunctions = function(options) { + Colorpicker.options = options; + }; - /** - * - */ - Colorpicker.initializeEvents = function() { - // Set color value - $('.t3js-colorpicker-value').on('click', function(e) { - e.preventDefault(); - $('#colorValue').val($(this).data('color-value')); - $(this).closest('form').submit(); - }); + /** + * + */ + Colorpicker.initializeEvents = function() { + // Set color value + $('.t3js-colorpicker-value').on('click', function(e) { + e.preventDefault(); + $('#colorValue').val($(this).data('color-value')); + $(this).closest('form').submit(); + }); - // Handle the change of the color selector - $('.t3js-colorpicker-selector').on('change', function(e) { - e.preventDefault(); - $('#colorValue').val($(this).val()); - $(this).closest('form').submit(); - }); + // Handle the change of the color selector + $('.t3js-colorpicker-selector').on('change', function(e) { + e.preventDefault(); + $('#colorValue').val($(this).val()); + $(this).closest('form').submit(); + }); - // Handle the transfer of the color value and closing of popup - $('#colorpicker-saveclose').on('click', function(e) { - e.preventDefault(); - var theField = $('[data-formengine-input-name="' + $('[name="fieldName"]').val() + '"]').get(0); - if (theField) { - theField.value = $('#colorValue').val(); + // Handle the transfer of the color value and closing of popup + $('#colorpicker-saveclose').on('click', function(e) { + e.preventDefault(); + var theField = $('[data-formengine-input-name="' + $('[name="fieldName"]').val() + '"]').get(0); + if (theField) { + theField.value = $('#colorValue').val(); - if (typeof Colorpicker.options.fieldChangeFunctions === 'function') { - Colorpicker.options.fieldChangeFunctions(); - } - } - parent.close(); - return false; - }); - }; + if (typeof Colorpicker.options.fieldChangeFunctions === 'function') { + Colorpicker.options.fieldChangeFunctions(); + } + } + parent.close(); + return false; + }); + }; - $(Colorpicker.initializeEvents); + $(Colorpicker.initializeEvents); - return Colorpicker; + return Colorpicker; }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/backend.js b/typo3/sysext/backend/Resources/Public/JavaScript/backend.js index 42e9417e25c147bc6fd16580ec7214d4f5196bab..f991de31c81cc6c49cfb27c565f4d64acead1d2f 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/backend.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/backend.js @@ -21,104 +21,106 @@ var TYPO3 = TYPO3 || {}; * jump the backend to a module */ function jump(url, modName, mainModName, pageId) { - if (isNaN(pageId)) { - pageId = -2; - } - // clear information about which entry in nav. tree that might have been highlighted. - top.fsMod.navFrameHighlightedID = []; - top.fsMod.recentIds['web'] = pageId; + if (isNaN(pageId)) { + pageId = -2; + } + // clear information about which entry in nav. tree that might have been highlighted. + top.fsMod.navFrameHighlightedID = []; + top.fsMod.recentIds['web'] = pageId; - top.nextLoadModuleUrl = url; - top.TYPO3.ModuleMenu.App.showModule(modName); + top.nextLoadModuleUrl = url; + top.TYPO3.ModuleMenu.App.showModule(modName); } /** * Function similar to PHPs rawurlencode(); */ function rawurlencode(str) { - var output = encodeURIComponent(str); - output = str_replace("*","%2A", output); - output = str_replace("+","%2B", output); - output = str_replace("/","%2F", output); - output = str_replace("@","%40", output); - return output; + var output = encodeURIComponent(str); + output = str_replace("*", "%2A", output); + output = str_replace("+", "%2B", output); + output = str_replace("/", "%2F", output); + output = str_replace("@", "%40", output); + return output; } /** * String-replace function */ -function str_replace(match,replace,string) { // - var input = ""+string; - var matchStr = ""+match; - if (!matchStr) {return string;} - var output = ""; - var pointer=0; - var pos = input.indexOf(matchStr); - while (pos !== -1) { - output+=""+input.substr(pointer, pos-pointer)+replace; - pointer=pos+matchStr.length; - pos = input.indexOf(match,pos+1); - } - output+=""+input.substr(pointer); - return output; +function str_replace(match, replace, string) { // + var input = "" + string; + var matchStr = "" + match; + if (!matchStr) { + return string; + } + var output = ""; + var pointer = 0; + var pos = input.indexOf(matchStr); + while (pos !== -1) { + output += "" + input.substr(pointer, pos - pointer) + replace; + pointer = pos + matchStr.length; + pos = input.indexOf(match, pos + 1); + } + output += "" + input.substr(pointer); + return output; } - /** * Launcing information window for records/files (fileref as "table" argument) */ function launchView(table, uid) { - var thePreviewWindow = window.open(TYPO3.settings.ShowItem.moduleUrl + '&table=' + encodeURIComponent(table) + "&uid=" + encodeURIComponent(uid), - "ShowItem" + Math.random().toString(16).slice(2), - "width=650,height=600,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0"); - if (thePreviewWindow && thePreviewWindow.focus) { - thePreviewWindow.focus(); - } + var thePreviewWindow = window.open(TYPO3.settings.ShowItem.moduleUrl + '&table=' + encodeURIComponent(table) + "&uid=" + encodeURIComponent(uid), + "ShowItem" + Math.random().toString(16).slice(2), + "width=650,height=600,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0"); + if (thePreviewWindow && thePreviewWindow.focus) { + thePreviewWindow.focus(); + } } /** * Opens plain window with url */ -function openUrlInWindow(url,windowName) { // - regularWindow = window.open( - url, - windowName, - "status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1"); - regularWindow.focus(); - return false; +function openUrlInWindow(url, windowName) { // + regularWindow = window.open( + url, + windowName, + "status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1"); + regularWindow.focus(); + return false; } /** * Loads a page id for editing in the page edit module: */ -function loadEditId(id,addGetVars) { // - top.fsMod.recentIds.web = id; - top.fsMod.navFrameHighlightedID.web = "pages" + id + "_0"; // For highlighting +function loadEditId(id, addGetVars) { // + top.fsMod.recentIds.web = id; + top.fsMod.navFrameHighlightedID.web = "pages" + id + "_0"; // For highlighting - if (top.nav_frame && top.nav_frame.refresh_nav) { - top.nav_frame.refresh_nav(); - } - if (TYPO3.configuration.pageModule) { - top.goToModule(TYPO3.configuration.pageModule, 0, addGetVars?addGetVars:""); - } + if (top.nav_frame && top.nav_frame.refresh_nav) { + top.nav_frame.refresh_nav(); + } + if (TYPO3.configuration.pageModule) { + top.goToModule(TYPO3.configuration.pageModule, 0, addGetVars ? addGetVars : ""); + } } /** * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared) * Used by the shortcut frame to set a "intermediate URL" */ -var nextLoadModuleUrl=""; -function getModuleUrl(inUrl) { // - var nMU; - if (top.nextLoadModuleUrl) { - nMU=top.nextLoadModuleUrl; - top.nextLoadModuleUrl=""; - return nMU; - } else { - return inUrl; - } +var nextLoadModuleUrl = ""; + +function getModuleUrl(inUrl) { // + var nMU; + if (top.nextLoadModuleUrl) { + nMU = top.nextLoadModuleUrl; + top.nextLoadModuleUrl = ""; + return nMU; + } else { + return inUrl; + } } // Used by Frameset Modules diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js index 7faccd830d0c9c82d0929f7d8b7602dbd6b0f807..691dffbaa144f2a3d565ae9e3fbf2d6d2a5276c9 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js @@ -16,109 +16,110 @@ * These fields show a "clear"-button when someone hovers over them and * they are not empty. * Options: - * * 'onClear': Function that is called after clearing. Takes no arguments, - * 'this' is set to the clearable input element. Defaults to an - * empty function. + * * 'onClear': Function that is called after clearing. Takes no arguments, + * 'this' is set to the clearable input element. Defaults to an + * empty function. */ (function(factory) { - if (typeof define === "function" && define.amd) { - // AMD. Register as an anonymous module. - define([ "jquery" ], factory); - } else { - // Browser globals - factory(jQuery); - } + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define(["jquery"], factory); + } else { + // Browser globals + factory(jQuery); + } }(function($) { - $.fn.clearable = function(options) { + $.fn.clearable = function(options) { - var defaults = { - 'onClear': function() {} - }; + var defaults = { + 'onClear': function() { + } + }; - // The inlined markup represent the current generated markup from the - // icon api for the icon actions-close that can be found in the official - // icon repository and is registered in the backend icon api. - // - // It´s not possible to use/open the backend icon api without opening - // new possible vectors for attackers to sniff system informations. - // - // When the icon definition of actions-close changes also the inlined - // icon should be updated. - // - // https://github.com/typo3/typo3.icons - var closeIcon = '<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">' + - '<span class="icon-markup">' + - '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0 .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7 0l.7.7c.2.2.2.5 0 .7z" class="icon-color"/></svg>' + - '</span>' + - '</span>'; + // The inlined markup represent the current generated markup from the + // icon api for the icon actions-close that can be found in the official + // icon repository and is registered in the backend icon api. + // + // It´s not possible to use/open the backend icon api without opening + // new possible vectors for attackers to sniff system informations. + // + // When the icon definition of actions-close changes also the inlined + // icon should be updated. + // + // https://github.com/typo3/typo3.icons + var closeIcon = '<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">' + + '<span class="icon-markup">' + + '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0 .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7 0l.7.7c.2.2.2.5 0 .7z" class="icon-color"/></svg>' + + '</span>' + + '</span>'; - // Merge defaults and given options. Given options have higher priority - // because they are the last argument. - var settings = $.extend({}, defaults, options); + // Merge defaults and given options. Given options have higher priority + // because they are the last argument. + var settings = $.extend({}, defaults, options); - // Iterate over the list of inputs and make each clearable. Return - // the list to allow chaining. - return this.each(function() { + // Iterate over the list of inputs and make each clearable. Return + // the list to allow chaining. + return this.each(function() { - // The input element to make clearable. - var $input = $(this); + // The input element to make clearable. + var $input = $(this); - // make sure the input field is not used twice for a clearable - // or the input field is a colorpicker, because it breaks the colorpicker. - if (!$input.data('clearable') && !$input.hasClass('t3js-color-picker')) { - $input.data('clearable', 'loaded'); - var hiddenClass = $input.hasClass('hidden') ? ' hidden' : ''; + // make sure the input field is not used twice for a clearable + // or the input field is a colorpicker, because it breaks the colorpicker. + if (!$input.data('clearable') && !$input.hasClass('t3js-color-picker')) { + $input.data('clearable', 'loaded'); + var hiddenClass = $input.hasClass('hidden') ? ' hidden' : ''; - // Wrap it with a div and add a span that is the trigger for - // clearing. - $input.wrap('<div class="form-control-clearable" />'); - $input.after('<button type="button" class="close' + hiddenClass + '" tabindex="-1" aria-hidden="true">' + closeIcon + '</button>'); - $input.addClass('t3js-clearable'); + // Wrap it with a div and add a span that is the trigger for + // clearing. + $input.wrap('<div class="form-control-clearable" />'); + $input.after('<button type="button" class="close' + hiddenClass + '" tabindex="-1" aria-hidden="true">' + closeIcon + '</button>'); + $input.addClass('t3js-clearable'); - var $clearer = $input.next(); + var $clearer = $input.next(); - // Register a listener the various events triggering the clearer to - // be shown or hidden. - var handler = function() { - var $element = $(this); - if ($element.next('input[type=hidden]').length) { - $element = $element.next('input[type=hidden]'); - } - var value = $element.val(); - var hasEmptyValue = (value.length === 0); - if (value === "0" && $element.closest('.t3js-datetimepicker').length) { - hasEmptyValue = true; - } + // Register a listener the various events triggering the clearer to + // be shown or hidden. + var handler = function() { + var $element = $(this); + if ($element.next('input[type=hidden]').length) { + $element = $element.next('input[type=hidden]'); + } + var value = $element.val(); + var hasEmptyValue = (value.length === 0); + if (value === "0" && $element.closest('.t3js-datetimepicker').length) { + hasEmptyValue = true; + } - // only show the clearing button if the value is set, or if the value is not "0" on a datetime field - if (!hasEmptyValue) { - $clearer.show(); - } else { - $clearer.hide(); - } - }; - $input.on('keyup', handler); - $input.on('mouseenter', handler); - $input.on('change', handler); - $input.on('initialize', handler); + // only show the clearing button if the value is set, or if the value is not "0" on a datetime field + if (!hasEmptyValue) { + $clearer.show(); + } else { + $clearer.hide(); + } + }; + $input.on('keyup', handler); + $input.on('mouseenter', handler); + $input.on('change', handler); + $input.on('initialize', handler); - // The actual clearing action. Focus the input element afterwards, - // the user probably wants to type into it after clearing. - $clearer.click(function(e) { - e.preventDefault(); - $input.val('').change(); - if (!$input.hasClass("t3js-datetimepicker")) { - $input.focus(); - } - $input.trigger('keyup'); + // The actual clearing action. Focus the input element afterwards, + // the user probably wants to type into it after clearing. + $clearer.click(function(e) { + e.preventDefault(); + $input.val('').change(); + if (!$input.hasClass("t3js-datetimepicker")) { + $input.focus(); + } + $input.trigger('keyup'); - if ('function' === typeof(settings.onClear)) { - settings.onClear.call($input.get()); - } - }); + if ('function' === typeof(settings.onClear)) { + settings.onClear.call($input.get()); + } + }); - $input.trigger('initialize'); - } - }); - }; + $input.trigger('initialize'); + } + }); + }; })); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js index d34384ebddaf53634632d94849bb94382f1d9dc9..313b34634a210f7d756f62fc62448d67a78814ec 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js @@ -16,505 +16,557 @@ */ function evalFunc() { - this.input = evalFunc_input; - this.output = evalFunc_output; - this.parseInt = evalFunc_parseInt; - this.getNumChars = evalFunc_getNumChars; - this.parseDouble = evalFunc_parseDouble; - this.noSpace = evalFunc_noSpace; - this.getSecs = evalFunc_getSecs; - this.getYear = evalFunc_getYear; - this.getTimeSecs = evalFunc_getTimeSecs; - this.getTime = evalFunc_getTime; - this.getDate = evalFunc_getDate; - this.getTimestamp = evalFunc_getTimestamp; - this.caseSwitch = evalFunc_caseSwitch; - this.evalObjValue = evalFunc_evalObjValue; - this.outputObjValue = evalFunc_outputObjValue; - this.split = evalFunc_splitStr; - this.pol = evalFunc_pol; - this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC; - - this.ltrim = evalFunc_ltrim; - this.btrim = evalFunc_btrim; - var today = new Date(); - this.lastYear = this.getYear(today); - this.lastDate = this.getDate(today); - this.lastTime = 0; - this.refDate = today; - this.isInString = ''; - this.USmode = 0; + this.input = evalFunc_input; + this.output = evalFunc_output; + this.parseInt = evalFunc_parseInt; + this.getNumChars = evalFunc_getNumChars; + this.parseDouble = evalFunc_parseDouble; + this.noSpace = evalFunc_noSpace; + this.getSecs = evalFunc_getSecs; + this.getYear = evalFunc_getYear; + this.getTimeSecs = evalFunc_getTimeSecs; + this.getTime = evalFunc_getTime; + this.getDate = evalFunc_getDate; + this.getTimestamp = evalFunc_getTimestamp; + this.caseSwitch = evalFunc_caseSwitch; + this.evalObjValue = evalFunc_evalObjValue; + this.outputObjValue = evalFunc_outputObjValue; + this.split = evalFunc_splitStr; + this.pol = evalFunc_pol; + this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC; + + this.ltrim = evalFunc_ltrim; + this.btrim = evalFunc_btrim; + var today = new Date(); + this.lastYear = this.getYear(today); + this.lastDate = this.getDate(today); + this.lastTime = 0; + this.refDate = today; + this.isInString = ''; + this.USmode = 0; } + function evalFunc_pol(foreign, value) { - return eval (((foreign=="-")?'-':'')+value); + return eval(((foreign == "-") ? '-' : '') + value); } -function evalFunc_evalObjValue(FObj,value) { - var evallist = FObj.evallist; - this.isInString = (FObj.is_in) ? ''+FObj.is_in : ''; - var index=1; - var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false; - var newValue=value; - while (theEvalType) { - if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') { - newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue); - } else { - newValue = evalFunc.input(theEvalType, newValue); - } - index++; - theEvalType = this.split(evallist, ",", index); - } - return newValue; + +function evalFunc_evalObjValue(FObj, value) { + var evallist = FObj.evallist; + this.isInString = (FObj.is_in) ? '' + FObj.is_in : ''; + var index = 1; + var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false; + var newValue = value; + while (theEvalType) { + if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') { + newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue); + } else { + newValue = evalFunc.input(theEvalType, newValue); + } + index++; + theEvalType = this.split(evallist, ",", index); + } + return newValue; } -function evalFunc_outputObjValue(FObj,value) { - var evallist = FObj.evallist; - var index=1; - var theEvalType = this.split(evallist, ",", index); - var newValue=value; - while (theEvalType) { - if (theEvalType != 'required') { - newValue = evalFunc.output(theEvalType, value, FObj); - } - index++; - theEvalType = this.split(evallist, ",", index); - } - return newValue; + +function evalFunc_outputObjValue(FObj, value) { + var evallist = FObj.evallist; + var index = 1; + var theEvalType = this.split(evallist, ",", index); + var newValue = value; + while (theEvalType) { + if (theEvalType != 'required') { + newValue = evalFunc.output(theEvalType, value, FObj); + } + index++; + theEvalType = this.split(evallist, ",", index); + } + return newValue; } -function evalFunc_caseSwitch(type,inVal) { - var theVal = ''+inVal; - var newString = ''; - switch (type) { - case "alpha": - case "num": - case "alphanum": - case "alphanum_x": - for (var a=0;a<theVal.length;a++) { - var theChar = theVal.substr(a,1); - var special = (theChar == '_' || theChar == '-'); - var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z'); - var num = (theChar>='0' && theChar<='9'); - switch(type) { - case "alphanum": special=0; break; - case "alpha": num=0; special=0; break; - case "num": alpha=0; special=0; break; - } - if (alpha || num || special) { - newString+=theChar; - } - } - break; - case "is_in": - if (this.isInString) { - for (var a=0;a<theVal.length;a++) { - var theChar = theVal.substr(a,1); - if (this.isInString.indexOf(theChar)!=-1) { - newString+=theChar; - } - } - } else {newString = theVal;} - break; - case "nospace": - newString = this.noSpace(theVal); - break; - case "upper": - newString = theVal.toUpperCase(); - break; - case "lower": - newString = theVal.toLowerCase(); - break; - default: - return inVal; - } - return newString; + +function evalFunc_caseSwitch(type, inVal) { + var theVal = '' + inVal; + var newString = ''; + switch (type) { + case "alpha": + case "num": + case "alphanum": + case "alphanum_x": + for (var a = 0; a < theVal.length; a++) { + var theChar = theVal.substr(a, 1); + var special = (theChar == '_' || theChar == '-'); + var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z'); + var num = (theChar >= '0' && theChar <= '9'); + switch (type) { + case "alphanum": + special = 0; + break; + case "alpha": + num = 0; + special = 0; + break; + case "num": + alpha = 0; + special = 0; + break; + } + if (alpha || num || special) { + newString += theChar; + } + } + break; + case "is_in": + if (this.isInString) { + for (var a = 0; a < theVal.length; a++) { + var theChar = theVal.substr(a, 1); + if (this.isInString.indexOf(theChar) != -1) { + newString += theChar; + } + } + } else { + newString = theVal; + } + break; + case "nospace": + newString = this.noSpace(theVal); + break; + case "upper": + newString = theVal.toUpperCase(); + break; + case "lower": + newString = theVal.toLowerCase(); + break; + default: + return inVal; + } + return newString; } + function evalFunc_parseInt(value) { - var theVal = ''+value; - if (!value) { - return 0; - } - for (var a = 0; a < theVal.length; a++) { - if (theVal.substr(a,1)!='0') { - return parseInt(theVal.substr(a,theVal.length)) || 0; - } - } - return 0; + var theVal = '' + value; + if (!value) { + return 0; + } + for (var a = 0; a < theVal.length; a++) { + if (theVal.substr(a, 1) != '0') { + return parseInt(theVal.substr(a, theVal.length)) || 0; + } + } + return 0; } + function evalFunc_getNumChars(value) { - var theVal = ''+value; - if (!value) { - return 0; - } - var outVal=""; - for (var a = 0; a < theVal.length; a++) { - if (theVal.substr(a,1)==parseInt(theVal.substr(a,1))) { - outVal+=theVal.substr(a,1); - } - } - return outVal; + var theVal = '' + value; + if (!value) { + return 0; + } + var outVal = ""; + for (var a = 0; a < theVal.length; a++) { + if (theVal.substr(a, 1) == parseInt(theVal.substr(a, 1))) { + outVal += theVal.substr(a, 1); + } + } + return outVal; } + function evalFunc_parseDouble(value) { - var theVal = "" + value; - theVal = theVal.replace(/[^0-9,\.-]/g, ""); - var negative = theVal.substring(0, 1) === '-'; - theVal = theVal.replace(/-/g, ""); - theVal = theVal.replace(/,/g, "."); - if (theVal.indexOf(".") == -1) { - theVal += ".0"; - } - var parts = theVal.split("."); - var dec = parts.pop(); - theVal = Number(parts.join("") + "." + dec); - if (negative) { - theVal *= -1; - } - theVal = theVal.toFixed(2); - - return theVal; + var theVal = "" + value; + theVal = theVal.replace(/[^0-9,\.-]/g, ""); + var negative = theVal.substring(0, 1) === '-'; + theVal = theVal.replace(/-/g, ""); + theVal = theVal.replace(/,/g, "."); + if (theVal.indexOf(".") == -1) { + theVal += ".0"; + } + var parts = theVal.split("."); + var dec = parts.pop(); + theVal = Number(parts.join("") + "." + dec); + if (negative) { + theVal *= -1; + } + theVal = theVal.toFixed(2); + + return theVal; } + function evalFunc_noSpace(value) { - var theVal = ''+value; - var newString=""; - for (var a=0;a<theVal.length;a++) { - var theChar = theVal.substr(a,1); - if (theChar!=' ') { - newString+=theChar; - } - } - return newString; + var theVal = '' + value; + var newString = ""; + for (var a = 0; a < theVal.length; a++) { + var theChar = theVal.substr(a, 1); + if (theChar != ' ') { + newString += theChar; + } + } + return newString; } + function evalFunc_ltrim(value) { - var theVal = ''+value; - if (!value) { - return ''; - } - for (var a = 0; a < theVal.length; a++) { - if (theVal.substr(a,1)!=' ') { - return theVal.substr(a,theVal.length); - } - } - return ''; + var theVal = '' + value; + if (!value) { + return ''; + } + for (var a = 0; a < theVal.length; a++) { + if (theVal.substr(a, 1) != ' ') { + return theVal.substr(a, theVal.length); + } + } + return ''; } + function evalFunc_btrim(value) { - var theVal = ''+value; - if (!value) { - return ''; - } - for (var a = theVal.length; a > 0; a--) { - if (theVal.substr(a-1,1)!=' ') { - return theVal.substr(0,a); - } - } - return ''; + var theVal = '' + value; + if (!value) { + return ''; + } + for (var a = theVal.length; a > 0; a--) { + if (theVal.substr(a - 1, 1) != ' ') { + return theVal.substr(0, a); + } + } + return ''; } + function evalFunc_splitSingle(value) { - var theVal = ''+value; - this.values = new Array(); - this.pointer = 3; - this.values[1]=theVal.substr(0,2); - this.values[2]=theVal.substr(2,2); - this.values[3]=theVal.substr(4,10); + var theVal = '' + value; + this.values = new Array(); + this.pointer = 3; + this.values[1] = theVal.substr(0, 2); + this.values[2] = theVal.substr(2, 2); + this.values[3] = theVal.substr(4, 10); } + function evalFunc_split(value) { - this.values = new Array(); - this.valPol = new Array(); - this.pointer = 0; - var numberMode = 0; - var theVal = ""; - value+=" "; - for (var a=0;a<value.length;a++) { - var theChar = value.substr(a,1); - if (theChar<"0" || theChar>"9") { - if (numberMode) { - this.pointer++; - this.values[this.pointer]=theVal; - theVal = ""; - numberMode=0; - } - if (theChar=="+" || theChar=="-") { - this.valPol[this.pointer+1] = theChar; - } - } else { - theVal+=theChar; - numberMode=1; - } - } + this.values = new Array(); + this.valPol = new Array(); + this.pointer = 0; + var numberMode = 0; + var theVal = ""; + value += " "; + for (var a = 0; a < value.length; a++) { + var theChar = value.substr(a, 1); + if (theChar < "0" || theChar > "9") { + if (numberMode) { + this.pointer++; + this.values[this.pointer] = theVal; + theVal = ""; + numberMode = 0; + } + if (theChar == "+" || theChar == "-") { + this.valPol[this.pointer + 1] = theChar; + } + } else { + theVal += theChar; + numberMode = 1; + } + } } -function evalFunc_input(type,inVal) { - if (type=="md5") { - return MD5(inVal); - } - if (type=="trim") { - return this.ltrim(this.btrim(inVal)); - } - if (type=="int") { - return this.parseInt(inVal); - } - if (type=="double2") { - return this.parseDouble(inVal); - } - - var today = new Date(); - var add=0; - var value = this.ltrim(inVal); - var values = new evalFunc_split(value); - var theCmd = value.substr(0,1); - value = this.caseSwitch(type,value); - if (value=="") { - return ""; - } - switch (type) { - case "datetime": - switch (theCmd) { - case "d": - case "t": - case "n": - this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0); - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - case "+": - case "-": - if (this.lastTime == 0) { - this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0); - } - if (values.valPol[1]) { - add = this.pol(values.valPol[1], this.parseInt(values.values[1])); - } - break; - default: - var index = value.indexOf(' '); - if (index!=-1) { - var dateVal = this.input("date", value.substr(index,value.length)); - // set refDate so that evalFunc_input on time will work with correct DST information - this.refDate = new Date(dateVal*1000); - this.lastTime = dateVal + this.input("time", value.substr(0,index)); - } else { - // only date, no time - this.lastTime = this.input("date", value); - } - } - this.lastTime+=add*24*60*60; - return this.lastTime; - break; - case "year": - switch (theCmd) { - case "d": - case "t": - case "n": - this.lastYear = this.getYear(today); - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - case "+": - case "-": - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - default: - if (values.valPol[2]) { - add = this.pol(values.valPol[2],this.parseInt(values.values[2])); - } - var year = (values.values[1])?this.parseInt(values.values[1]):this.getYear(today); - if ((year >= 0 && year < 38) || (year >= 70 && year<100) || (year >= 1902 && year < 2038)) { - if (year<100) { - year = (year<38) ? year+=2000 : year+=1900; - } - } else { - year = this.getYear(today); - } - this.lastYear = year; - } - this.lastYear+=add; - return this.lastYear; - break; - case "date": - switch (theCmd) { - case "d": - case "t": - case "n": - this.lastDate = this.getTimestamp(today); - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - case "+": - case "-": - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - default: - var index = 4; - if (values.valPol[index]) { - add = this.pol(values.valPol[index],this.parseInt(values.values[index])); - } - if (values.values[1] && values.values[1].length>2) { - if (values.valPol[2]) { - add = this.pol(values.valPol[2],this.parseInt(values.values[2])); - } - var temp = values.values[1]; - values = new evalFunc_splitSingle(temp); - } - - var year = (values.values[3])?this.parseInt(values.values[3]):this.getYear(today); - if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year<2038)) { - if (year<100) { - year = (year<38) ? year+=2000 : year+=1900; - } - } else { - year = this.getYear(today); - } - var month = (values.values[this.USmode?1:2])?this.parseInt(values.values[this.USmode?1:2]):today.getUTCMonth()+1; - var day = (values.values[this.USmode?2:1])?this.parseInt(values.values[this.USmode?2:1]):today.getUTCDate(); - - var theTime = new Date(parseInt(year), parseInt(month)-1, parseInt(day)); - - // Substract timezone offset from client - this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0); - } - this.lastDate+=add*24*60*60; - return this.lastDate; - break; - case "time": - case "timesec": - switch (theCmd) { - case "d": - case "t": - case "n": - this.lastTime = this.getTimeSecs(today); - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - case "+": - case "-": - if (this.lastTime == 0) { - this.lastTime = this.getTimeSecs(today); - } - if (values.valPol[1]) { - add = this.pol(values.valPol[1],this.parseInt(values.values[1])); - } - break; - default: - var index = (type=="timesec")?4:3; - if (values.valPol[index]) { - add = this.pol(values.valPol[index],this.parseInt(values.values[index])); - } - if (values.values[1] && values.values[1].length>2) { - if (values.valPol[2]) { - add = this.pol(values.valPol[2],this.parseInt(values.values[2])); - } - var temp = values.values[1]; - values = new evalFunc_splitSingle(temp); - } - var sec = (values.values[3])?this.parseInt(values.values[3]):today.getUTCSeconds(); - if (sec > 59) {sec=59;} - var min = (values.values[2])?this.parseInt(values.values[2]):today.getUTCMinutes(); - if (min > 59) {min=59;} - var hour = (values.values[1])?this.parseInt(values.values[1]):today.getUTCHours(); - if (hour >= 24) {hour=0;} - - var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type=="timesec")?sec:0)); - - // Substract timezone offset from client - this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1); - } - this.lastTime+=add*60; - if (this.lastTime<0) {this.lastTime+=24*60*60;} - return this.lastTime; - break; - default: - return value; - } + +function evalFunc_input(type, inVal) { + if (type == "md5") { + return MD5(inVal); + } + if (type == "trim") { + return this.ltrim(this.btrim(inVal)); + } + if (type == "int") { + return this.parseInt(inVal); + } + if (type == "double2") { + return this.parseDouble(inVal); + } + + var today = new Date(); + var add = 0; + var value = this.ltrim(inVal); + var values = new evalFunc_split(value); + var theCmd = value.substr(0, 1); + value = this.caseSwitch(type, value); + if (value == "") { + return ""; + } + switch (type) { + case "datetime": + switch (theCmd) { + case "d": + case "t": + case "n": + this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0); + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + case "+": + case "-": + if (this.lastTime == 0) { + this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0); + } + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + default: + var index = value.indexOf(' '); + if (index != -1) { + var dateVal = this.input("date", value.substr(index, value.length)); + // set refDate so that evalFunc_input on time will work with correct DST information + this.refDate = new Date(dateVal * 1000); + this.lastTime = dateVal + this.input("time", value.substr(0, index)); + } else { + // only date, no time + this.lastTime = this.input("date", value); + } + } + this.lastTime += add * 24 * 60 * 60; + return this.lastTime; + break; + case "year": + switch (theCmd) { + case "d": + case "t": + case "n": + this.lastYear = this.getYear(today); + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + case "+": + case "-": + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + default: + if (values.valPol[2]) { + add = this.pol(values.valPol[2], this.parseInt(values.values[2])); + } + var year = (values.values[1]) ? this.parseInt(values.values[1]) : this.getYear(today); + if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year < 2038)) { + if (year < 100) { + year = (year < 38) ? year += 2000 : year += 1900; + } + } else { + year = this.getYear(today); + } + this.lastYear = year; + } + this.lastYear += add; + return this.lastYear; + break; + case "date": + switch (theCmd) { + case "d": + case "t": + case "n": + this.lastDate = this.getTimestamp(today); + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + case "+": + case "-": + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + default: + var index = 4; + if (values.valPol[index]) { + add = this.pol(values.valPol[index], this.parseInt(values.values[index])); + } + if (values.values[1] && values.values[1].length > 2) { + if (values.valPol[2]) { + add = this.pol(values.valPol[2], this.parseInt(values.values[2])); + } + var temp = values.values[1]; + values = new evalFunc_splitSingle(temp); + } + + var year = (values.values[3]) ? this.parseInt(values.values[3]) : this.getYear(today); + if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year < 2038)) { + if (year < 100) { + year = (year < 38) ? year += 2000 : year += 1900; + } + } else { + year = this.getYear(today); + } + var month = (values.values[this.USmode ? 1 : 2]) ? this.parseInt(values.values[this.USmode ? 1 : 2]) : today.getUTCMonth() + 1; + var day = (values.values[this.USmode ? 2 : 1]) ? this.parseInt(values.values[this.USmode ? 2 : 1]) : today.getUTCDate(); + + var theTime = new Date(parseInt(year), parseInt(month) - 1, parseInt(day)); + + // Substract timezone offset from client + this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0); + } + this.lastDate += add * 24 * 60 * 60; + return this.lastDate; + break; + case "time": + case "timesec": + switch (theCmd) { + case "d": + case "t": + case "n": + this.lastTime = this.getTimeSecs(today); + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + case "+": + case "-": + if (this.lastTime == 0) { + this.lastTime = this.getTimeSecs(today); + } + if (values.valPol[1]) { + add = this.pol(values.valPol[1], this.parseInt(values.values[1])); + } + break; + default: + var index = (type == "timesec") ? 4 : 3; + if (values.valPol[index]) { + add = this.pol(values.valPol[index], this.parseInt(values.values[index])); + } + if (values.values[1] && values.values[1].length > 2) { + if (values.valPol[2]) { + add = this.pol(values.valPol[2], this.parseInt(values.values[2])); + } + var temp = values.values[1]; + values = new evalFunc_splitSingle(temp); + } + var sec = (values.values[3]) ? this.parseInt(values.values[3]) : today.getUTCSeconds(); + if (sec > 59) { + sec = 59; + } + var min = (values.values[2]) ? this.parseInt(values.values[2]) : today.getUTCMinutes(); + if (min > 59) { + min = 59; + } + var hour = (values.values[1]) ? this.parseInt(values.values[1]) : today.getUTCHours(); + if (hour >= 24) { + hour = 0; + } + + var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type == "timesec") ? sec : 0)); + + // Substract timezone offset from client + this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1); + } + this.lastTime += add * 60; + if (this.lastTime < 0) { + this.lastTime += 24 * 60 * 60; + } + return this.lastTime; + break; + default: + return value; + } } -function evalFunc_output(type,value,FObj) { - var theString = ""; - switch (type) { - case "date": - if (!parseInt(value)) {return '';} - var theTime = new Date(parseInt(value) * 1000); - if (this.USmode) { - theString = (theTime.getUTCMonth()+1)+'-'+theTime.getUTCDate()+'-'+this.getYear(theTime); - } else { - theString = theTime.getUTCDate()+'-'+(theTime.getUTCMonth()+1)+'-'+this.getYear(theTime); - } - break; - case "datetime": - if (!parseInt(value)) {return '';} - theString = this.output("time",value)+' '+this.output("date",value); - break; - case "time": - case "timesec": - if (!parseInt(value)) {return '';} - var theTime = new Date(parseInt(value) * 1000); - var h = theTime.getUTCHours(); - var m = theTime.getUTCMinutes(); - var s = theTime.getUTCSeconds(); - theString = h+':'+((m<10)?'0':'')+m + ((type=="timesec")?':'+((s<10)?'0':'')+s:''); - break; - case "password": - theString = (value) ? "********" : ""; - break; - case "int": - theString = (FObj.checkbox && value==FObj.checkboxValue)?'':value; - break; - default: - theString = value; - } - return theString; + +function evalFunc_output(type, value, FObj) { + var theString = ""; + switch (type) { + case "date": + if (!parseInt(value)) { + return ''; + } + var theTime = new Date(parseInt(value) * 1000); + if (this.USmode) { + theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime); + } else { + theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime); + } + break; + case "datetime": + if (!parseInt(value)) { + return ''; + } + theString = this.output("time", value) + ' ' + this.output("date", value); + break; + case "time": + case "timesec": + if (!parseInt(value)) { + return ''; + } + var theTime = new Date(parseInt(value) * 1000); + var h = theTime.getUTCHours(); + var m = theTime.getUTCMinutes(); + var s = theTime.getUTCSeconds(); + theString = h + ':' + ((m < 10) ? '0' : '') + m + ((type == "timesec") ? ':' + ((s < 10) ? '0' : '') + s : ''); + break; + case "password": + theString = (value) ? "********" : ""; + break; + case "int": + theString = (FObj.checkbox && value == FObj.checkboxValue) ? '' : value; + break; + default: + theString = value; + } + return theString; } + function evalFunc_getSecs(timeObj) { - return timeObj.getUTCSeconds(); + return timeObj.getUTCSeconds(); } + // Seconds since midnight: function evalFunc_getTime(timeObj) { - return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj); + return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj); } + function evalFunc_getYear(timeObj) { - return timeObj.getUTCFullYear(); + return timeObj.getUTCFullYear(); } + // Seconds since midnight with client timezone offset: function evalFunc_getTimeSecs(timeObj) { - return timeObj.getHours()*60*60+timeObj.getMinutes()*60+timeObj.getSeconds(); + return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds(); } + function evalFunc_getDate(timeObj) { - var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate()); - return this.getTimestamp(theTime); + var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate()); + return this.getTimestamp(theTime); } -function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) { - this.evallist = evallist; - this.is_in = is_in; - this.checkboxValue = checkboxValue; - this.checkbox = checkbox; + +function evalFunc_dummy(evallist, is_in, checkbox, checkboxValue) { + this.evallist = evallist; + this.is_in = is_in; + this.checkboxValue = checkboxValue; + this.checkbox = checkbox; } + function evalFunc_splitStr(theStr1, delim, index) { - var theStr = ''+theStr1; - var lengthOfDelim = delim.length; - sPos = -lengthOfDelim; - if (index<1) {index=1;} - for (a=1; a<index; a++) { - sPos = theStr.indexOf(delim, sPos+lengthOfDelim); - if (sPos==-1) {return null;} - } - ePos = theStr.indexOf(delim, sPos+lengthOfDelim); - if(ePos == -1) {ePos = theStr.length;} - return (theStr.substring(sPos+lengthOfDelim,ePos)); + var theStr = '' + theStr1; + var lengthOfDelim = delim.length; + sPos = -lengthOfDelim; + if (index < 1) { + index = 1; + } + for (a = 1; a < index; a++) { + sPos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (sPos == -1) { + return null; + } + } + ePos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (ePos == -1) { + ePos = theStr.length; + } + return (theStr.substring(sPos + lengthOfDelim, ePos)); } + function evalFunc_getTimestamp(timeObj) { - return Date.parse(timeObj)/1000; + return Date.parse(timeObj) / 1000; } // Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server function evalFunc_convertClientTimestampToUTC(timestamp, timeonly) { - var timeObj = new Date(timestamp*1000); - timeObj.setTime((timestamp - timeObj.getTimezoneOffset()*60)*1000); - if (timeonly) { - // only seconds since midnight - return this.getTime(timeObj); - } else { - // seconds since the "unix-epoch" - return this.getTimestamp(timeObj); - } + var timeObj = new Date(timestamp * 1000); + timeObj.setTime((timestamp - timeObj.getTimezoneOffset() * 60) * 1000); + if (timeonly) { + // only seconds since midnight + return this.getTime(timeObj); + } else { + // seconds since the "unix-epoch" + return this.getTimestamp(timeObj); + } } diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js index cbf9c07eb4436e00c8fb5cb4147b100df026d1bc..72ec8b48f4ba6d82e515a4a627b698f18b3d57ea 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js @@ -18,1235 +18,1235 @@ */ var inline = { - classVisible: 'panel-visible', - classCollapsed: 'panel-collapsed', - structureSeparator: '-', - flexFormSeparator: '---', - flexFormSubstitute: ':', - noTitleString: (TYPO3.lang ? TYPO3.lang['FormEngine.noRecordTitle'] : '[No title]'), - lockedAjaxMethod: {}, - sourcesLoaded: {}, - data: {}, - isLoading: false, - - addToDataArray: function (object) { - $.each(object, function (key, value) { - if (!inline.data[key]) { - inline.data[key] = {}; - } - $.extend(inline.data[key], value); - }); - }, - toggleEvent: function (event) { - var $triggerElement = $(event.target); - if ($triggerElement.parents('.t3js-formengine-irre-control').length == 1) { - return; - } - - var $recordHeader = $triggerElement.closest('.panel-heading'); - inline.expandCollapseRecord( - $recordHeader.attr('id').replace(/_header$/, ''), - $recordHeader.attr('data-expandSingle') - ); - }, - expandCollapseRecord: function (objectId, expandSingle) { - var currentUid = this.parseObjectId('none', objectId, 1); - var objectPrefix = this.parseObjectId('full', objectId, 0, 1); - var escapedObjectId = this.escapeObjectId(objectId); - - var $currentObject = $('#' + escapedObjectId + '_div'); - // if content is not loaded yet, get it now from server - if (inline.isLoading) { - return false; - } else if ($('#' + escapedObjectId + '_fields').length > 0 && $('#' + escapedObjectId + '_fields').html().substr(0, 16) === '<!--notloaded-->') { - inline.isLoading = true; - var headerIdentifier = '#' + escapedObjectId + '_header'; - // add loading-indicator - require(['nprogress'], function (NProgress) { - inline.progress = NProgress; - inline.progress.configure({parent: headerIdentifier, showSpinner: false}); - inline.progress.start(); - }); - return this.getRecordDetails(objectId); - } - - var isCollapsed = $currentObject.hasClass(this.classCollapsed); - var collapse = []; - var expand = []; - - // if only a single record should be visibly for that set of records - // and the record clicked itself is no visible, collapse all others - if (expandSingle && $currentObject.hasClass(this.classCollapsed)) { - collapse = this.collapseAllRecords(objectId, objectPrefix, currentUid); - } - - inline.toggleElement(objectId); - - if (this.isNewRecord(objectId)) { - this.updateExpandedCollapsedStateLocally(objectId, isCollapsed); - } else if (isCollapsed) { - expand.push(currentUid); - } else if (!isCollapsed) { - collapse.push(currentUid); - } - - this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(',')); - - return false; - }, - - toggleElement: function (objectId) { - var escapedObjectId = this.escapeObjectId(objectId); - var $jQueryObject = $('#' + escapedObjectId + '_div'); - - if ($jQueryObject.hasClass(this.classCollapsed)) { - $jQueryObject.removeClass(this.classCollapsed).addClass(this.classVisible); - $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-collapsed').removeClass('t3-icon-irre-collapsed').addClass('t3-icon-irre-expanded'); - } else { - $jQueryObject.removeClass(this.classVisible).addClass(this.classCollapsed); - $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-expanded').addClass('t3-icon-irre-collapsed').removeClass('t3-icon-irre-expanded'); - } - }, - collapseAllRecords: function (objectId, objectPrefix, callingUid) { - // get the form field, where all records are stored - var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true); - var formObj = document.getElementsByName(objectName); - var collapse = []; - - if (formObj.length) { - // the uid of the calling object (last part in objectId) - var recObjectId = '', escapedRecordObjectId; - - var records = this.trimExplode(',', formObj[0].value); - for (var i = 0; i < records.length; i++) { - recObjectId = objectPrefix + this.structureSeparator + records[i]; - escapedRecordObjectId = this.escapeObjectId(recObjectId); - - var $recordEntry = $('#' + escapedRecordObjectId + '_div'); - if (records[i] != callingUid && $recordEntry.hasClass(this.classVisible)) { - $recordEntry.removeClass(this.classVisible).addClass(this.classCollapsed); - if (this.isNewRecord(recObjectId)) { - this.updateExpandedCollapsedStateLocally(recObjectId, 0); - } else { - collapse.push(records[i]); - } - } - } - } - - return collapse; - }, - - updateExpandedCollapsedStateLocally: function (objectId, value) { - var ucName = 'uc[inlineView]' + this.parseObjectId('parts', objectId, 3, 2, true); - var ucFormObj = document.getElementsByName(ucName); - if (ucFormObj.length) { - ucFormObj[0].value = value; - } - }, - - getRecordDetails: function (objectId) { - var context = this.getContext(this.parseObjectId('full', objectId, 0, 1)); - inline.makeAjaxCall('details', [objectId], true, context); - return false; - }, - - createNewRecord: function (objectId, recordUid) { - if (this.isBelowMax(objectId)) { - var context = this.getContext(objectId); - if (recordUid) { - objectId += this.structureSeparator + recordUid; - } - this.makeAjaxCall('create', [objectId], true, context); - } else { - var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectId].max); - var matches = objectId.match(/^(data-\d+-.*?-\d+-.*?)-(.*?)$/); - var title = ''; - if (matches) { - title = $('#' + matches[1] + '_records').data('title'); - } - top.TYPO3.Notification.error(title, message, 5); - } - return false; - }, - - synchronizeLocalizeRecords: function (objectId, type) { - var context = this.getContext(objectId); - this.makeAjaxCall('synchronizelocalize', [objectId, type], true, context); - return false; - }, - - setExpandedCollapsedState: function (objectId, expand, collapse) { - var context = this.getContext(objectId); - this.makeAjaxCall('expandcollapse', [objectId, expand, collapse], false, context); - }, - - makeAjaxCall: function (method, params, lock, context) { - var url = '', urlParams = '', options = {}; - if (method && params && params.length && this.lockAjaxMethod(method, lock)) { - url = TYPO3.settings.ajaxUrls['record_inline_' + method]; - urlParams = ''; - for (var i = 0; i < params.length; i++) { - urlParams += '&ajax[' + i + ']=' + encodeURIComponent(params[i]); - } - if (context) { - urlParams += '&ajax[context]=' + encodeURIComponent(JSON.stringify(context)); - } - options = { - type: 'POST', - data: urlParams, - success: function (data, message, jqXHR) { - inline.isLoading = false; - inline.processAjaxResponse(method, jqXHR); - if (inline.progress) { - inline.progress.done(); - } - }, - error: function (jqXHR) { - inline.isLoading = false; - inline.showAjaxFailure(method, jqXHR); - if (inline.progress) { - inline.progress.done(); - } - } - }; - - $.ajax(url, options); - } - }, - - lockAjaxMethod: function (method, lock) { - if (!lock || !inline.lockedAjaxMethod[method]) { - inline.lockedAjaxMethod[method] = true; - return true; - } else { - return false; - } - }, - - unlockAjaxMethod: function (method) { - inline.lockedAjaxMethod[method] = false; - }, - - processAjaxResponse: function (method, xhr, json) { - var processedCount = 0, sourcesWaiting = []; - if (!json && xhr) { - json = xhr.responseJSON; - } - if (json.hasErrors) { - $.each(json.messages, function(position, message) { - top.TYPO3.Notification.error(message.title, message.message); - }); - } - // If there are elements the should be added to the <HEAD> tag (e.g. for RTEhtmlarea): - if (json.stylesheetFiles) { - $.each(json.stylesheetFiles, function (index, stylesheetFile) { - if (!stylesheetFile) { - return; - } - var element = document.createElement('link'); - element['rel'] = 'stylesheet'; - element['type'] = 'text/css'; - element['href'] = stylesheetFile; - $('head').get(0).appendChild(element); - processedCount++; - delete(json.stylesheetFiles[index]); - }); - } - if (processedCount) { - window.setTimeout(function () { - inline.reprocessAjaxResponse(method, json, sourcesWaiting); - }, 40); - } else { - if (method) { - inline.unlockAjaxMethod(method); - } - if (json.scriptCall && json.scriptCall.length > 0) { - $.each(json.scriptCall, function (index, value) { - eval(value); - }); - } - TYPO3.FormEngine.reinitialize(); - TYPO3.FormEngine.Validation.initializeInputFields(); - TYPO3.FormEngine.Validation.validate(); - } - }, - - // Check if dynamically added scripts are loaded and restart inline.processAjaxResponse(): - reprocessAjaxResponse: function (method, json, sourcesWaiting) { - var sourcesLoaded = true; - if (sourcesWaiting && sourcesWaiting.length) { - $.each(sourcesWaiting, function (index, source) { - if (!inline.sourcesLoaded[source]) { - sourcesLoaded = false; - return false; - } - }); - } - if (sourcesLoaded) { - $.each(sourcesWaiting, function (index, source) { - delete(inline.sourcesLoaded[source]); - }); - window.setTimeout(function () { - inline.processAjaxResponse(method, null, json); - }, 80); - } else { - window.setTimeout(function () { - inline.reprocessAjaxResponse(method, json, sourcesWaiting); - }, 40); - } - }, - - sourceLoadedHandler: function (element) { - if (element && element.src) { - inline.sourcesLoaded[element.src] = true; - } - }, - - showAjaxFailure: function (method, xhr) { - inline.unlockAjaxMethod(method); - top.TYPO3.Notification.error('Error ' + xhr.status, xhr.statusText, 0); - }, - - // foreign_selector: used by selector box (type='select') - importNewRecord: function (objectId) { - var $selector = $('#' + this.escapeObjectId(objectId) + '_selector'); - var selectedIndex = $selector.prop('selectedIndex'); - if (selectedIndex != -1) { - var context = this.getContext(objectId); - var selectedValue = $selector.val(); - if (!this.data.unique || !this.data.unique[objectId]) { - $selector.find('option').eq(selectedIndex).prop('selected', false); - } - this.makeAjaxCall('create', [objectId, selectedValue], true, context); - } - return false; - }, - - // foreign_selector: used by element browser (type='group/db') - importElement: function (objectId, table, uid) { - var context = this.getContext(objectId); - inline.makeAjaxCall('create', [objectId, uid], true, context); - }, - - importElementMultiple: function (objectId, table, uidArray, type) { - $.each(uidArray, function (index, uid) { - inline.delayedImportElement(objectId, table, uid, type); - }); - }, - delayedImportElement: function (objectId, table, uid, type) { - if (inline.lockedAjaxMethod['create'] == true) { - window.setTimeout("inline.delayedImportElement('" + objectId + "','" + table + "'," + uid + ", null );", - 300); - } else { - inline.importElement(objectId, table, uid, type); - } - }, - // Check uniqueness for element browser: - checkUniqueElement: function (objectId, table, uid) { - if (this.checkUniqueUsed(objectId, uid, table)) { - return {passed: false, message: 'There is already a relation to the selected element!'}; - } else { - return {passed: true}; - } - }, - - // Checks if a record was used and should be unique: - checkUniqueUsed: function (objectId, uid, table) { - if (!this.data.unique || !this.data.unique[objectId]) { - return false; - } - - var unique = this.data.unique[objectId]; - var values = this.getValuesFromHashMap(unique.used); - - // for select: only the uid is stored - if (unique['type'] == 'select') { - if (values.indexOf(uid) != -1) { - return true; - } - - // for group/db: table and uid is stored in an assoc array - } else if (unique.type == 'groupdb') { - for (var i = values.length - 1; i >= 0; i--) { - // if the pair table:uid is already used: - if (values[i].table == table && values[i].uid == uid) { - return true; - } - } - } - - return false; - }, - - setUniqueElement: function (objectId, table, uid, type, elName) { - var recordUid = this.parseFormElementName('none', elName, 1, 1); - this.setUnique(objectId, recordUid, uid); - }, - - getValuesFromHashMap: function (hashMap) { - return $.map(hashMap, function (value, key) { - return value; - }); - }, - - // Remove all select items already used - // from a newly retrieved/expanded record - removeUsed: function (objectId, recordUid) { - if (!this.data.unique || !this.data.unique[objectId]) { - return; - } - - var unique = this.data.unique[objectId]; - if (unique.type != 'select') { - return; - } - - var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']'); - var values = this.getValuesFromHashMap(unique.used); - if (recordObj.length) { - if (recordObj[0].hasOwnProperty('options')) { - var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value; - for (var i = 0; i < values.length; i++) { - if (values[i] != selectedValue) { - var $recordObject = $(recordObj[0]); - this.removeSelectOption($recordObject, values[i]); - } - } - } - } - }, - // this function is applied to a newly inserted record by AJAX - // it removes the used select items, that should be unique - setUnique: function (objectId, recordUid, selectedValue) { - if (!this.data.unique || !this.data.unique[objectId]) { - return; - } - var $selector = $('#' + this.escapeObjectId(objectId) + '_selector'); - - var unique = this.data.unique[objectId]; - if (unique.type == 'select') { - if (!(unique.selector && unique.max == -1)) { - var formName = 'data' + this.parseObjectId('parts', objectId, 3, 1, true); - var formObj = document.getElementsByName(formName); - var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']'); - var values = this.getValuesFromHashMap(unique.used); - if ($selector.length) { - // remove all items from the new select-item which are already used in other children - if (recordObj.length) { - var $recordObject = $(recordObj[0]); - for (var i = 0; i < values.length; i++) { - this.removeSelectOption($recordObject, values[i]); - } - // set the selected item automatically to the first of the remaining items if no selector is used - if (!unique.selector) { - selectedValue = recordObj[0].options[0].value; - recordObj[0].options[0].selected = true; - this.updateUnique(recordObj[0], objectId, formName, recordUid); - this.handleChangedField(recordObj[0], objectId + '[' + recordUid + ']'); - } - } - for (var i = 0; i < values.length; i++) { - this.removeSelectOption($selector, values[i]); - } - if (typeof this.data.unique[objectId].used.length != 'undefined') { - this.data.unique[objectId].used = {}; - } - this.data.unique[objectId].used[recordUid] = selectedValue; - } - // remove the newly used item from each select-field of the child records - if (formObj.length && selectedValue) { - var records = this.trimExplode(',', formObj[0].value); - for (var i = 0; i < records.length; i++) { - recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); - if (recordObj.length && records[i] != recordUid) { - var $recordObject = $(recordObj[0]); - this.removeSelectOption($recordObject, selectedValue); - } - } - } - } - } else if (unique.type == 'groupdb') { - // add the new record to the used items: - this.data.unique[objectId].used[recordUid] = {'table': unique.elTable, 'uid': selectedValue}; - } - - // remove used items from a selector-box - if (unique.selector == 'select' && selectedValue) { - this.removeSelectOption($selector, selectedValue); - this.data.unique[objectId]['used'][recordUid] = selectedValue; - } - }, - - domAddNewRecord: function (method, insertObjectId, objectPrefix, htmlData) { - var $insertObject = $('#' + this.escapeObjectId(insertObjectId)); - if (this.isBelowMax(objectPrefix)) { - if (method == 'bottom') { - $insertObject.append(htmlData); - } else if (method == 'after') { - $insertObject.after(htmlData); - } - } else { - var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectPrefix].max); - var title = $insertObject.data('title'); - top.TYPO3.Notification.error(title, message); - } - }, - - domAddRecordDetails: function (objectId, objectPrefix, expandSingle, htmlData) { - var hiddenValue, formObj, valueObj; - var escapeObjectId = this.escapeObjectId(objectId); - var $objectDiv = $('#' + escapeObjectId + '_fields'); - if ($objectDiv.length == 0 || $objectDiv.html().substr(0, 16) !== '<!--notloaded-->') { - return; - } - - var elName = this.parseObjectId('full', objectId, 2, 0, true); - - var $formObj = $('[data-formengine-input-name="' + elName + '[hidden]"]'); - var $valueObj = $('[name="' + elName + '[hidden]"]'); - - // It might be the case that a child record - // cannot be hidden at all (no hidden field) - if ($formObj.length && $valueObj.length) { - hiddenValue = $formObj[0].checked; - $formObj.first().remove(); - $valueObj.first().remove(); - } - - // Update DOM - $objectDiv.html(htmlData); - - formObj = document.querySelector('[data-formengine-input-name="' + elName + '[hidden]"]'); - valueObj = document.getElementsByName(elName + '[hidden]'); - - // Set the hidden value again - if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) { - valueObj[0].value = hiddenValue ? 1 : 0; - formObj.checked = hiddenValue; - } - - // now that the content is loaded, set the expandState - this.expandCollapseRecord(objectId, expandSingle); - }, - - changeSorting: function (objectId, direction) { - var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true); - var objectPrefix = this.parseObjectId('full', objectId, 0, 1); - var formObj = document.getElementsByName(objectName); - - if (!formObj.length) { - return false; - } - - // the uid of the calling object (last part in objectId) - var callingUid = this.parseObjectId('none', objectId, 1); - var records = this.trimExplode(',', formObj[0].value); - var current = records.indexOf(callingUid); - var changed = false; - - // move up - if (direction > 0 && current > 0) { - records[current] = records[current - 1]; - records[current - 1] = callingUid; - changed = true; - - // move down - } else if (direction < 0 && current < records.length - 1) { - records[current] = records[current + 1]; - records[current + 1] = callingUid; - changed = true; - } - - if (changed) { - formObj[0].value = records.join(','); - var cAdj = direction > 0 ? 1 : 0; // adjustment - var objectIdPrefix = '#' + this.escapeObjectId(objectPrefix) + this.structureSeparator; - $(objectIdPrefix + records[current - cAdj] + '_div').insertBefore( - $(objectIdPrefix + records[current + 1 - cAdj] + '_div') - ); - this.redrawSortingButtons(objectPrefix, records); - } - - return false; - }, - - dragAndDropSorting: function (element) { - var objectId = element.getAttribute('id').replace(/_records$/, ''); - var objectName = 'data' + inline.parseObjectId('parts', objectId, 3, 0, true); - var formObj = document.getElementsByName(objectName); - var $element = $(element); - - if (!formObj.length) { - return; - } - - var checked = []; - var order = []; - $element.find('.sortableHandle').each(function (i, e) { - order.push($(e).data('id').toString()); - }); - var records = this.trimExplode(',', formObj[0].value); - - // check if ordered uid is really part of the records - // virtually deleted items might still be there but ordering shouldn't saved at all on them - for (var i = 0; i < order.length; i++) { - if (records.indexOf(order[i]) != -1) { - checked.push(order[i]); - } - } - - formObj[0].value = checked.join(','); - - if (inline.data.config && inline.data.config[objectId]) { - var table = inline.data.config[objectId].table; - inline.redrawSortingButtons(objectId + inline.structureSeparator + table, checked); - } - }, - - createDragAndDropSorting: function (objectId) { - require(['jquery', 'jquery-ui/sortable'], function ($) { - var $sortingContainer = $('#' + inline.escapeObjectId(objectId)); - - if ($sortingContainer.hasClass('ui-sortable')) { - $sortingContainer.sortable('enable'); - return; - } - - $sortingContainer.sortable({ - containment: 'parent', - handle: '.sortableHandle', - zIndex: '4000', - axis: 'y', - tolerance: 'pointer', - stop: function () { - inline.dragAndDropSorting($sortingContainer[0]); - } - }); - }); - }, - - destroyDragAndDropSorting: function (objectId) { - require(['jquery', 'jquery-ui/sortable'], function ($) { - var $sortingContainer = $('#' + inline.escapeObjectId(objectId)); - if (!$sortingContainer.hasClass('ui-sortable')) { - return; - } - $sortingContainer.sortable('disable'); - }); - }, - - redrawSortingButtons: function (objectPrefix, records) { - var i, $headerObj, sortUp, sortDown, partOfHeaderObj, iconIdentifier; - - // if no records were passed, fetch them from form field - if (typeof records == 'undefined') { - records = []; - var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); - var formObj = document.getElementsByName(objectName); - if (formObj.length) { - records = this.trimExplode(',', formObj[0].value); - } - } - partOfHeaderObj = this.escapeObjectId(objectPrefix) + this.structureSeparator; - require(['TYPO3/CMS/Backend/Icons'], function(Icons) { - for (i = 0; i < records.length; i++) { - if (!records[i].length) { - continue; - } - $headerObj = $('#' + partOfHeaderObj + records[i] + '_header'); - sortUp = $headerObj.find('.sortingUp'); - iconIdentifier = 'actions-move-up'; - if (sortUp) { - if (i == 0) { - sortUp.addClass('disabled'); - iconIdentifier = 'empty-empty'; - } else { - sortUp.removeClass('disabled'); - } - Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) { - sortUp.find('.t3js-icon').replaceWith(markup); - }); - } - sortDown = $headerObj.find('.sortingDown'); - iconIdentifier = 'actions-move-down'; - if (sortDown) { - if (i == records.length - 1) { - sortDown.addClass('disabled'); - iconIdentifier = 'empty-empty'; - } else { - sortDown.removeClass('disabled'); - } - Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) { - sortDown.find('.t3js-icon').replaceWith(markup); - }); - } - } - }); - }, - - memorizeAddRecord: function (objectPrefix, newUid, afterUid, selectedValue) { - if (this.isBelowMax(objectPrefix)) { - var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); - var formObj = document.getElementsByName(objectName); - - if (formObj.length) { - var records = []; - if (formObj[0].value.length) { - records = this.trimExplode(',', formObj[0].value); - } - - if (afterUid) { - var newRecords = []; - for (var i = 0; i < records.length; i++) { - if (records[i].length) { - newRecords.push(records[i]); - } - if (afterUid == records[i]) { - newRecords.push(newUid); - } - } - records = newRecords; - } else { - records.push(newUid); - } - formObj[0].value = records.join(','); - } - - this.redrawSortingButtons(objectPrefix, records); - - if (this.data.unique && this.data.unique[objectPrefix]) { - this.setUnique(objectPrefix, newUid, selectedValue); - } - } - - // if we reached the maximum of possible records after this action, hide the new buttons - if (!this.isBelowMax(objectPrefix)) { - var objectParent = this.parseObjectId('full', objectPrefix, 0, 1); - var md5 = this.getObjectMD5(objectParent); - this.hideElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent); - this.hideElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent); - this.hideElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent); - this.hideElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent); - this.hideElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item'); - } - - if (TBE_EDITOR) { - TBE_EDITOR.fieldChanged_fName(objectName, formObj); - } - }, - - memorizeRemoveRecord: function (objectName, removeUid) { - var formObj = document.getElementsByName(objectName); - if (formObj.length) { - var parts = [], - indexOfRemoveUid = -1; - if (formObj[0].value.length) { - parts = this.trimExplode(',', formObj[0].value); - indexOfRemoveUid = parts.indexOf(removeUid); - if (indexOfRemoveUid !== -1) { - delete parts[indexOfRemoveUid]; - } - formObj[0].value = parts.join(','); - if (TBE_EDITOR) { - TBE_EDITOR.fieldChanged_fName(objectName, formObj); - } - return parts.length; - } - } - return false; - }, - - updateUnique: function (srcElement, objectPrefix, formName, recordUid) { - if (!this.data.unique || !this.data.unique[objectPrefix]) { - return; - } - - var unique = this.data.unique[objectPrefix]; - var oldValue = unique.used[recordUid]; - - if (unique.selector == 'select') { - var selector = $(objectPrefix + '_selector'); - this.removeSelectOption(selector, srcElement.value); - if (typeof oldValue != 'undefined') { - this.readdSelectOption(selector, oldValue, unique); - } - } - - if (unique.selector && unique.max == -1) { - return; - } - - var formObj = document.getElementsByName(formName); - if (!unique || !formObj.length) { - return; - } - - var records = this.trimExplode(',', formObj[0].value); - var recordObj; - for (var i = 0; i < records.length; i++) { - recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); - if (recordObj.length && recordObj[0] != srcElement) { - var $recordObject = $(recordObj[0]); - this.removeSelectOption($recordObject, srcElement.value); - if (typeof oldValue != 'undefined') { - this.readdSelectOption($recordObject, oldValue, unique); - } - } - } - this.data.unique[objectPrefix].used[recordUid] = srcElement.value; - }, - - revertUnique: function (objectPrefix, elName, recordUid) { - if (!this.data.unique || !this.data.unique[objectPrefix]) { - return; - } - - var unique = this.data.unique[objectPrefix]; - var fieldObj = elName ? document.getElementsByName(elName + '[' + unique.field + ']') : null; - - if (unique.type == 'select') { - if (!fieldObj || !fieldObj.length) { - return; - } - - delete(this.data.unique[objectPrefix].used[recordUid]); - - if (unique.selector == 'select') { - if (!isNaN(fieldObj[0].value)) { - var $selector = $('#' + this.escapeObjectId(objectPrefix) + '_selector'); - this.readdSelectOption($selector, fieldObj[0].value, unique); - } - } - - if (unique.selector && unique.max == -1) { - return; - } - - var formName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); - var formObj = document.getElementsByName(formName); - if (!formObj.length) { - return; - } - - var records = this.trimExplode(',', formObj[0].value); - var recordObj; - // walk through all inline records on that level and get the select field - for (var i = 0; i < records.length; i++) { - recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); - if (recordObj.length) { - var $recordObject = $(recordObj[0]); - this.readdSelectOption($recordObject, fieldObj[0].value, unique); - } - } - } else if (unique.type == 'groupdb') { - delete(this.data.unique[objectPrefix].used[recordUid]) - } - }, - - enableDisableRecord: function (objectIdentifier, fieldName) { - var elName = this.parseObjectId('full', objectIdentifier, 2, 0, true) + '[' + fieldName + ']'; - var formObj = document.querySelector('[data-formengine-input-name="' + elName + '"]'); - var valueObj = document.getElementsByName(elName); - var escapedObjectIdentifier = this.escapeObjectId(objectIdentifier); - var $container = $('#' + escapedObjectIdentifier + '_div'); - var $icon = $container.find('.t3js-' + escapedObjectIdentifier + '_disabled .t3js-icon'); - - // It might be the case that there's no hidden field - if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) { - formObj.click(); - valueObj[0].value = formObj.checked ? 1 : 0; - TBE_EDITOR.fieldChanged_fName(elName, elName); - } - - if ($icon.length) { - require(['TYPO3/CMS/Backend/Icons'], function(Icons) { - var hiddenClass = 't3-form-field-container-inline-hidden', - isHidden = $container.hasClass(hiddenClass), - toggleIcon; - - if (isHidden) { - toggleIcon = 'actions-edit-hide'; - $container.removeClass(hiddenClass); - } else { - toggleIcon = 'actions-edit-unhide'; - $container.addClass(hiddenClass); - } - - Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(markup) { - $icon.replaceWith(markup); - }); - }); - } - - return false; - }, - - deleteRecord: function (objectId, options) { - var i, j, inlineRecords, records, childObjectId, childTable; - var objectPrefix = this.parseObjectId('full', objectId, 0, 1); - var elName = this.parseObjectId('full', objectId, 2, 0, true); - var shortName = this.parseObjectId('parts', objectId, 2, 0, true); - var recordUid = this.parseObjectId('none', objectId, 1); - var beforeDeleteIsBelowMax = this.isBelowMax(objectPrefix); - - // revert the unique settings if available - this.revertUnique(objectPrefix, elName, recordUid); - - // Remove from TBE_EDITOR (required fields, required range, etc.): - if (TBE_EDITOR && TBE_EDITOR.removeElement) { - var removeStack = []; - // Iterate over all child records: - inlineRecords = $('.inlineRecord', '#' + objectId + '_div'); - // Remove nested child records from TBE_EDITOR required/range checks: - for (i = inlineRecords.length - 1; i >= 0; i--) { - if (inlineRecords.get(i).value.length) { - records = this.trimExplode(',', inlineRecords.get(i).value); - childObjectId = this.data.map[inlineRecords.get(i).name]; - childTable = this.data.config[childObjectId].table; - for (j = records.length - 1; j >= 0; j--) { - removeStack.push('data[' + childTable + '][' + records[j] + ']'); - } - } - } - removeStack.push('data' + shortName); - TBE_EDITOR.removeElementArray(removeStack); - } - - // Mark this container as deleted - $('#' + this.escapeObjectId(objectId) + '_div') - .addClass('inlineIsDeletedRecord') - .addClass('t3js-inline-record-deleted'); - - // If the record is new and was never saved before, just remove it from DOM: - if (this.isNewRecord(objectId) || options && options.forceDirectRemoval) { - this.fadeAndRemove(objectId + '_div'); - // If the record already exists in storage, mark it to be deleted on clicking the save button: - } else { - document.getElementsByName('cmd' + shortName + '[delete]')[0].disabled = false; - $('#' + this.escapeObjectId(objectId) + '_div').fadeOut(200); - } - - var recordCount = this.memorizeRemoveRecord( - 'data' + this.parseObjectId('parts', objectId, 3, 2, true), - recordUid - ); - - if (recordCount <= 1) { - this.destroyDragAndDropSorting(this.parseObjectId('full', objectId, 0, 2) + '_records'); - } - this.redrawSortingButtons(objectPrefix); - - // if the NEW-button was hidden and now we can add again new children, show the button - if (!beforeDeleteIsBelowMax && this.isBelowMax(objectPrefix)) { - var objectParent = this.parseObjectId('full', objectPrefix, 0, 1); - var md5 = this.getObjectMD5(objectParent); - this.showElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent); - this.showElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent); - this.showElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent); - this.showElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent); - this.showElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item'); - } - TYPO3.FormEngine.Validation.validate(); - return false; - }, - - parseFormElementName: function (wrap, formElementName, rightCount, skipRight) { - var idParts = this.splitFormElementName(formElementName); - - if (!wrap) { - wrap = 'full'; - } - if (!skipRight) { - skipRight = 0; - } - - var elParts = []; - for (var i = 0; i < skipRight; i++) { - idParts.pop(); - } - - if (rightCount > 0) { - for (var i = 0; i < rightCount; i++) { - elParts.unshift(idParts.pop()); - } - } else { - for (var i = 0; i < -rightCount; i++) { - idParts.shift(); - } - elParts = idParts; - } - - return this.constructFormElementName(wrap, elParts); - }, - - splitFormElementName: function (formElementName) { - // remove left and right side "data[...|...]" -> '...|...' - formElementName = formElementName.substr(0, formElementName.lastIndexOf(']')).substr(formElementName.indexOf('[') + 1); - return formElementName.split(']['); - }, - - splitObjectId: function (objectId) { - objectId = objectId.substr(objectId.indexOf(this.structureSeparator) + 1); - objectId = objectId.split(this.flexFormSeparator).join(this.flexFormSubstitute); - return objectId.split(this.structureSeparator); - }, - - constructFormElementName: function (wrap, parts) { - var elReturn; - - if (wrap == 'full') { - elReturn = 'data[' + parts.join('][') + ']'; - elReturn = elReturn.split(this.flexFormSubstitute).join(']['); - } else if (wrap == 'parts') { - elReturn = '[' + parts.join('][') + ']'; - elReturn = elReturn.split(this.flexFormSubstitute).join(']['); - } else if (wrap == 'none') { - elReturn = parts.length > 1 ? parts : parts.join(''); - } - - return elReturn; - }, - - constructObjectId: function (wrap, parts) { - var elReturn; - - if (wrap == 'full') { - elReturn = 'data' + this.structureSeparator + parts.join(this.structureSeparator); - elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator); - } else if (wrap == 'parts') { - elReturn = this.structureSeparator + parts.join(this.structureSeparator); - elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator); - } else if (wrap == 'none') { - elReturn = parts.length > 1 ? parts : parts.join(''); - } - - return elReturn; - }, - - parseObjectId: function (wrap, objectId, rightCount, skipRight, returnAsFormElementName) { - var idParts = this.splitObjectId(objectId); - - if (!wrap) { - wrap = 'full'; - } - if (!skipRight) { - skipRight = 0; - } - - var elParts = []; - for (var i = 0; i < skipRight; i++) { - idParts.pop(); - } - - if (rightCount > 0) { - for (var i = 0; i < rightCount; i++) { - elParts.unshift(idParts.pop()); - } - } else { - for (var i = 0; i < -rightCount; i++) { - idParts.shift(); - } - elParts = idParts; - } - - return returnAsFormElementName - ? this.constructFormElementName(wrap, elParts) - : this.constructObjectId(wrap, elParts); - }, - - handleChangedField: function (formField, objectId) { - var formObj; - if (typeof formField == 'object') { - formObj = formField; - } else { - formObj = document.getElementsByName(formField); - if (formObj.length) { - formObj = formObj[0]; - } - } - - if (formObj != undefined) { - var value; - if (formObj.nodeName == 'SELECT') { - value = formObj.options[formObj.selectedIndex].text; - } else { - value = formObj.value; - } - $('#' + this.escapeObjectId(objectId) + '_label').text(value.length ? value : this.noTitleString); - } - return true; - }, - - arrayAssocCount: function (object) { - var count = 0; - if (typeof object.length != 'undefined') { - count = object.length; - } else { - for (var i in object) { - count++; - } - } - return count; - }, - - isBelowMax: function (objectPrefix) { - var isBelowMax = true; - var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); - var formObj = document.getElementsByName(objectName); - - if (this.data.config && this.data.config[objectPrefix] && formObj.length) { - var recordCount = formObj[0].value ? this.trimExplode(',', formObj[0].value).length : 0; - if (recordCount >= this.data.config[objectPrefix].max) { - isBelowMax = false; - } - } - if (isBelowMax && this.data.unique && this.data.unique[objectPrefix]) { - var unique = this.data.unique[objectPrefix]; - if (this.arrayAssocCount(unique.used) >= unique.max && unique.max >= 0) { - isBelowMax = false; - } - } - return isBelowMax; - }, - - getOptionsHash: function ($selectObj) { - var optionsHash = {}; - $selectObj.find('option').each(function (i, option) { - optionsHash[option.value] = i; - }); - return optionsHash; - }, - - removeSelectOption: function ($selectObj, value) { - var optionsHash = this.getOptionsHash($selectObj); - if (optionsHash[value] != undefined) { - $selectObj.find('option').eq(optionsHash[value]).remove(); - } - }, - - readdSelectOption: function ($selectObj, value, unique) { - if (!$selectObj.length) { - return; - } - - var index = null; - var optionsHash = this.getOptionsHash($selectObj); - - for (var possibleValue in unique.possible) { - if (possibleValue == value) { - break; - } - if (optionsHash[possibleValue] != undefined) { - index = optionsHash[possibleValue]; - } - } - - if (index == null) { - index = 0; - } else if (index < $selectObj.find('option').length) { - index++; - } - // recreate the <option> tag - var readdOption = document.createElement('option'); - readdOption.text = unique.possible[value]; - readdOption.value = value; - // add the <option> at the right position - // I didn't find a possibility to add an option to a predefined position - // with help of an index in jQuery. So we realized it the "old" style - var selectObj = $selectObj.get(0); - selectObj.add(readdOption, document.all ? index : selectObj.options[index]); - }, - - hideElementsWithClassName: function (selector, parentElement) { - $('#' + this.escapeObjectId(parentElement)).find(selector).fadeOut(200); - }, - - showElementsWithClassName: function (selector, parentElement) { - $('#' + this.escapeObjectId(parentElement)).find(selector).fadeIn(200); - }, - - // sets the opacity to 0.2 and then fades in to opacity 1 - fadeOutFadeIn: function (objectId) { - $('#' + this.escapeObjectId(objectId)).css({opacity: 0.2}).fadeTo(200, 1, 'linear'); - }, - - isNewRecord: function (objectId) { - var $selector = $('#' + this.escapeObjectId(objectId) + '_div'); - return $selector.length && $selector.hasClass('inlineIsNewRecord'); - }, - - // Find and fix nested of inline and tab levels if a new element was created dynamically (it doesn't know about its nesting): - findContinuedNestedLevel: function (nested, objectId) { - if (this.data.nested && this.data.nested[objectId]) { - // Remove the first element from the new nested stack, it's just a hint: - nested.shift(); - nested = this.data.nested[objectId].concat(nested); - } - return nested; - }, - - getObjectMD5: function (objectPrefix) { - var md5 = false; - if (this.data.config && this.data.config[objectPrefix] && this.data.config[objectPrefix].md5) { - md5 = this.data.config[objectPrefix].md5; - } - return md5 - }, - - fadeAndRemove: function (element) { - $('#' + this.escapeObjectId(element)).fadeOut(200, function () { - $(this).remove(); - TYPO3.FormEngine.Validation.validate(); - }); - }, - - getContext: function (objectId) { - var result = null; - - if (objectId !== '' && typeof this.data.config[objectId] !== 'undefined' && typeof this.data.config[objectId].context !== 'undefined') { - result = this.data.config[objectId].context; - } - - return result; - }, - - /** - * Escapes object identifiers to be used in jQuery. - * - * @param {String} objectId - * @return string - */ - escapeObjectId: function (objectId) { - var escapedObjectId; - escapedObjectId = objectId.replace(/:/g, '\\:'); - escapedObjectId = escapedObjectId.replace(/\./g, '\\.'); - return escapedObjectId; - }, - - /** - * Helper function to get clean trimmed array from comma list - * - * @param {String} delimiter - * @param {String} string - * @returns {Array} - */ - trimExplode: function(delimiter, string) { - var result = []; - var items = string.split(delimiter); - for (var i=0; i<items.length; i++) { - var item = items[i].trim(); - if (item.length > 0) { - result.push(item); - } - } - return result; - } + classVisible: 'panel-visible', + classCollapsed: 'panel-collapsed', + structureSeparator: '-', + flexFormSeparator: '---', + flexFormSubstitute: ':', + noTitleString: (TYPO3.lang ? TYPO3.lang['FormEngine.noRecordTitle'] : '[No title]'), + lockedAjaxMethod: {}, + sourcesLoaded: {}, + data: {}, + isLoading: false, + + addToDataArray: function(object) { + $.each(object, function(key, value) { + if (!inline.data[key]) { + inline.data[key] = {}; + } + $.extend(inline.data[key], value); + }); + }, + toggleEvent: function(event) { + var $triggerElement = $(event.target); + if ($triggerElement.parents('.t3js-formengine-irre-control').length == 1) { + return; + } + + var $recordHeader = $triggerElement.closest('.panel-heading'); + inline.expandCollapseRecord( + $recordHeader.attr('id').replace(/_header$/, ''), + $recordHeader.attr('data-expandSingle') + ); + }, + expandCollapseRecord: function(objectId, expandSingle) { + var currentUid = this.parseObjectId('none', objectId, 1); + var objectPrefix = this.parseObjectId('full', objectId, 0, 1); + var escapedObjectId = this.escapeObjectId(objectId); + + var $currentObject = $('#' + escapedObjectId + '_div'); + // if content is not loaded yet, get it now from server + if (inline.isLoading) { + return false; + } else if ($('#' + escapedObjectId + '_fields').length > 0 && $('#' + escapedObjectId + '_fields').html().substr(0, 16) === '<!--notloaded-->') { + inline.isLoading = true; + var headerIdentifier = '#' + escapedObjectId + '_header'; + // add loading-indicator + require(['nprogress'], function(NProgress) { + inline.progress = NProgress; + inline.progress.configure({parent: headerIdentifier, showSpinner: false}); + inline.progress.start(); + }); + return this.getRecordDetails(objectId); + } + + var isCollapsed = $currentObject.hasClass(this.classCollapsed); + var collapse = []; + var expand = []; + + // if only a single record should be visibly for that set of records + // and the record clicked itself is no visible, collapse all others + if (expandSingle && $currentObject.hasClass(this.classCollapsed)) { + collapse = this.collapseAllRecords(objectId, objectPrefix, currentUid); + } + + inline.toggleElement(objectId); + + if (this.isNewRecord(objectId)) { + this.updateExpandedCollapsedStateLocally(objectId, isCollapsed); + } else if (isCollapsed) { + expand.push(currentUid); + } else if (!isCollapsed) { + collapse.push(currentUid); + } + + this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(',')); + + return false; + }, + + toggleElement: function(objectId) { + var escapedObjectId = this.escapeObjectId(objectId); + var $jQueryObject = $('#' + escapedObjectId + '_div'); + + if ($jQueryObject.hasClass(this.classCollapsed)) { + $jQueryObject.removeClass(this.classCollapsed).addClass(this.classVisible); + $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-collapsed').removeClass('t3-icon-irre-collapsed').addClass('t3-icon-irre-expanded'); + } else { + $jQueryObject.removeClass(this.classVisible).addClass(this.classCollapsed); + $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-expanded').addClass('t3-icon-irre-collapsed').removeClass('t3-icon-irre-expanded'); + } + }, + collapseAllRecords: function(objectId, objectPrefix, callingUid) { + // get the form field, where all records are stored + var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true); + var formObj = document.getElementsByName(objectName); + var collapse = []; + + if (formObj.length) { + // the uid of the calling object (last part in objectId) + var recObjectId = '', escapedRecordObjectId; + + var records = this.trimExplode(',', formObj[0].value); + for (var i = 0; i < records.length; i++) { + recObjectId = objectPrefix + this.structureSeparator + records[i]; + escapedRecordObjectId = this.escapeObjectId(recObjectId); + + var $recordEntry = $('#' + escapedRecordObjectId + '_div'); + if (records[i] != callingUid && $recordEntry.hasClass(this.classVisible)) { + $recordEntry.removeClass(this.classVisible).addClass(this.classCollapsed); + if (this.isNewRecord(recObjectId)) { + this.updateExpandedCollapsedStateLocally(recObjectId, 0); + } else { + collapse.push(records[i]); + } + } + } + } + + return collapse; + }, + + updateExpandedCollapsedStateLocally: function(objectId, value) { + var ucName = 'uc[inlineView]' + this.parseObjectId('parts', objectId, 3, 2, true); + var ucFormObj = document.getElementsByName(ucName); + if (ucFormObj.length) { + ucFormObj[0].value = value; + } + }, + + getRecordDetails: function(objectId) { + var context = this.getContext(this.parseObjectId('full', objectId, 0, 1)); + inline.makeAjaxCall('details', [objectId], true, context); + return false; + }, + + createNewRecord: function(objectId, recordUid) { + if (this.isBelowMax(objectId)) { + var context = this.getContext(objectId); + if (recordUid) { + objectId += this.structureSeparator + recordUid; + } + this.makeAjaxCall('create', [objectId], true, context); + } else { + var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectId].max); + var matches = objectId.match(/^(data-\d+-.*?-\d+-.*?)-(.*?)$/); + var title = ''; + if (matches) { + title = $('#' + matches[1] + '_records').data('title'); + } + top.TYPO3.Notification.error(title, message, 5); + } + return false; + }, + + synchronizeLocalizeRecords: function(objectId, type) { + var context = this.getContext(objectId); + this.makeAjaxCall('synchronizelocalize', [objectId, type], true, context); + return false; + }, + + setExpandedCollapsedState: function(objectId, expand, collapse) { + var context = this.getContext(objectId); + this.makeAjaxCall('expandcollapse', [objectId, expand, collapse], false, context); + }, + + makeAjaxCall: function(method, params, lock, context) { + var url = '', urlParams = '', options = {}; + if (method && params && params.length && this.lockAjaxMethod(method, lock)) { + url = TYPO3.settings.ajaxUrls['record_inline_' + method]; + urlParams = ''; + for (var i = 0; i < params.length; i++) { + urlParams += '&ajax[' + i + ']=' + encodeURIComponent(params[i]); + } + if (context) { + urlParams += '&ajax[context]=' + encodeURIComponent(JSON.stringify(context)); + } + options = { + type: 'POST', + data: urlParams, + success: function(data, message, jqXHR) { + inline.isLoading = false; + inline.processAjaxResponse(method, jqXHR); + if (inline.progress) { + inline.progress.done(); + } + }, + error: function(jqXHR) { + inline.isLoading = false; + inline.showAjaxFailure(method, jqXHR); + if (inline.progress) { + inline.progress.done(); + } + } + }; + + $.ajax(url, options); + } + }, + + lockAjaxMethod: function(method, lock) { + if (!lock || !inline.lockedAjaxMethod[method]) { + inline.lockedAjaxMethod[method] = true; + return true; + } else { + return false; + } + }, + + unlockAjaxMethod: function(method) { + inline.lockedAjaxMethod[method] = false; + }, + + processAjaxResponse: function(method, xhr, json) { + var processedCount = 0, sourcesWaiting = []; + if (!json && xhr) { + json = xhr.responseJSON; + } + if (json.hasErrors) { + $.each(json.messages, function(position, message) { + top.TYPO3.Notification.error(message.title, message.message); + }); + } + // If there are elements the should be added to the <HEAD> tag (e.g. for RTEhtmlarea): + if (json.stylesheetFiles) { + $.each(json.stylesheetFiles, function(index, stylesheetFile) { + if (!stylesheetFile) { + return; + } + var element = document.createElement('link'); + element['rel'] = 'stylesheet'; + element['type'] = 'text/css'; + element['href'] = stylesheetFile; + $('head').get(0).appendChild(element); + processedCount++; + delete(json.stylesheetFiles[index]); + }); + } + if (processedCount) { + window.setTimeout(function() { + inline.reprocessAjaxResponse(method, json, sourcesWaiting); + }, 40); + } else { + if (method) { + inline.unlockAjaxMethod(method); + } + if (json.scriptCall && json.scriptCall.length > 0) { + $.each(json.scriptCall, function(index, value) { + eval(value); + }); + } + TYPO3.FormEngine.reinitialize(); + TYPO3.FormEngine.Validation.initializeInputFields(); + TYPO3.FormEngine.Validation.validate(); + } + }, + + // Check if dynamically added scripts are loaded and restart inline.processAjaxResponse(): + reprocessAjaxResponse: function(method, json, sourcesWaiting) { + var sourcesLoaded = true; + if (sourcesWaiting && sourcesWaiting.length) { + $.each(sourcesWaiting, function(index, source) { + if (!inline.sourcesLoaded[source]) { + sourcesLoaded = false; + return false; + } + }); + } + if (sourcesLoaded) { + $.each(sourcesWaiting, function(index, source) { + delete(inline.sourcesLoaded[source]); + }); + window.setTimeout(function() { + inline.processAjaxResponse(method, null, json); + }, 80); + } else { + window.setTimeout(function() { + inline.reprocessAjaxResponse(method, json, sourcesWaiting); + }, 40); + } + }, + + sourceLoadedHandler: function(element) { + if (element && element.src) { + inline.sourcesLoaded[element.src] = true; + } + }, + + showAjaxFailure: function(method, xhr) { + inline.unlockAjaxMethod(method); + top.TYPO3.Notification.error('Error ' + xhr.status, xhr.statusText, 0); + }, + + // foreign_selector: used by selector box (type='select') + importNewRecord: function(objectId) { + var $selector = $('#' + this.escapeObjectId(objectId) + '_selector'); + var selectedIndex = $selector.prop('selectedIndex'); + if (selectedIndex != -1) { + var context = this.getContext(objectId); + var selectedValue = $selector.val(); + if (!this.data.unique || !this.data.unique[objectId]) { + $selector.find('option').eq(selectedIndex).prop('selected', false); + } + this.makeAjaxCall('create', [objectId, selectedValue], true, context); + } + return false; + }, + + // foreign_selector: used by element browser (type='group/db') + importElement: function(objectId, table, uid) { + var context = this.getContext(objectId); + inline.makeAjaxCall('create', [objectId, uid], true, context); + }, + + importElementMultiple: function(objectId, table, uidArray, type) { + $.each(uidArray, function(index, uid) { + inline.delayedImportElement(objectId, table, uid, type); + }); + }, + delayedImportElement: function(objectId, table, uid, type) { + if (inline.lockedAjaxMethod['create'] == true) { + window.setTimeout("inline.delayedImportElement('" + objectId + "','" + table + "'," + uid + ", null );", + 300); + } else { + inline.importElement(objectId, table, uid, type); + } + }, + // Check uniqueness for element browser: + checkUniqueElement: function(objectId, table, uid) { + if (this.checkUniqueUsed(objectId, uid, table)) { + return {passed: false, message: 'There is already a relation to the selected element!'}; + } else { + return {passed: true}; + } + }, + + // Checks if a record was used and should be unique: + checkUniqueUsed: function(objectId, uid, table) { + if (!this.data.unique || !this.data.unique[objectId]) { + return false; + } + + var unique = this.data.unique[objectId]; + var values = this.getValuesFromHashMap(unique.used); + + // for select: only the uid is stored + if (unique['type'] == 'select') { + if (values.indexOf(uid) != -1) { + return true; + } + + // for group/db: table and uid is stored in an assoc array + } else if (unique.type == 'groupdb') { + for (var i = values.length - 1; i >= 0; i--) { + // if the pair table:uid is already used: + if (values[i].table == table && values[i].uid == uid) { + return true; + } + } + } + + return false; + }, + + setUniqueElement: function(objectId, table, uid, type, elName) { + var recordUid = this.parseFormElementName('none', elName, 1, 1); + this.setUnique(objectId, recordUid, uid); + }, + + getValuesFromHashMap: function(hashMap) { + return $.map(hashMap, function(value, key) { + return value; + }); + }, + + // Remove all select items already used + // from a newly retrieved/expanded record + removeUsed: function(objectId, recordUid) { + if (!this.data.unique || !this.data.unique[objectId]) { + return; + } + + var unique = this.data.unique[objectId]; + if (unique.type != 'select') { + return; + } + + var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']'); + var values = this.getValuesFromHashMap(unique.used); + if (recordObj.length) { + if (recordObj[0].hasOwnProperty('options')) { + var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value; + for (var i = 0; i < values.length; i++) { + if (values[i] != selectedValue) { + var $recordObject = $(recordObj[0]); + this.removeSelectOption($recordObject, values[i]); + } + } + } + } + }, + // this function is applied to a newly inserted record by AJAX + // it removes the used select items, that should be unique + setUnique: function(objectId, recordUid, selectedValue) { + if (!this.data.unique || !this.data.unique[objectId]) { + return; + } + var $selector = $('#' + this.escapeObjectId(objectId) + '_selector'); + + var unique = this.data.unique[objectId]; + if (unique.type == 'select') { + if (!(unique.selector && unique.max == -1)) { + var formName = 'data' + this.parseObjectId('parts', objectId, 3, 1, true); + var formObj = document.getElementsByName(formName); + var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']'); + var values = this.getValuesFromHashMap(unique.used); + if ($selector.length) { + // remove all items from the new select-item which are already used in other children + if (recordObj.length) { + var $recordObject = $(recordObj[0]); + for (var i = 0; i < values.length; i++) { + this.removeSelectOption($recordObject, values[i]); + } + // set the selected item automatically to the first of the remaining items if no selector is used + if (!unique.selector) { + selectedValue = recordObj[0].options[0].value; + recordObj[0].options[0].selected = true; + this.updateUnique(recordObj[0], objectId, formName, recordUid); + this.handleChangedField(recordObj[0], objectId + '[' + recordUid + ']'); + } + } + for (var i = 0; i < values.length; i++) { + this.removeSelectOption($selector, values[i]); + } + if (typeof this.data.unique[objectId].used.length != 'undefined') { + this.data.unique[objectId].used = {}; + } + this.data.unique[objectId].used[recordUid] = selectedValue; + } + // remove the newly used item from each select-field of the child records + if (formObj.length && selectedValue) { + var records = this.trimExplode(',', formObj[0].value); + for (var i = 0; i < records.length; i++) { + recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); + if (recordObj.length && records[i] != recordUid) { + var $recordObject = $(recordObj[0]); + this.removeSelectOption($recordObject, selectedValue); + } + } + } + } + } else if (unique.type == 'groupdb') { + // add the new record to the used items: + this.data.unique[objectId].used[recordUid] = {'table': unique.elTable, 'uid': selectedValue}; + } + + // remove used items from a selector-box + if (unique.selector == 'select' && selectedValue) { + this.removeSelectOption($selector, selectedValue); + this.data.unique[objectId]['used'][recordUid] = selectedValue; + } + }, + + domAddNewRecord: function(method, insertObjectId, objectPrefix, htmlData) { + var $insertObject = $('#' + this.escapeObjectId(insertObjectId)); + if (this.isBelowMax(objectPrefix)) { + if (method == 'bottom') { + $insertObject.append(htmlData); + } else if (method == 'after') { + $insertObject.after(htmlData); + } + } else { + var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectPrefix].max); + var title = $insertObject.data('title'); + top.TYPO3.Notification.error(title, message); + } + }, + + domAddRecordDetails: function(objectId, objectPrefix, expandSingle, htmlData) { + var hiddenValue, formObj, valueObj; + var escapeObjectId = this.escapeObjectId(objectId); + var $objectDiv = $('#' + escapeObjectId + '_fields'); + if ($objectDiv.length == 0 || $objectDiv.html().substr(0, 16) !== '<!--notloaded-->') { + return; + } + + var elName = this.parseObjectId('full', objectId, 2, 0, true); + + var $formObj = $('[data-formengine-input-name="' + elName + '[hidden]"]'); + var $valueObj = $('[name="' + elName + '[hidden]"]'); + + // It might be the case that a child record + // cannot be hidden at all (no hidden field) + if ($formObj.length && $valueObj.length) { + hiddenValue = $formObj[0].checked; + $formObj.first().remove(); + $valueObj.first().remove(); + } + + // Update DOM + $objectDiv.html(htmlData); + + formObj = document.querySelector('[data-formengine-input-name="' + elName + '[hidden]"]'); + valueObj = document.getElementsByName(elName + '[hidden]'); + + // Set the hidden value again + if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) { + valueObj[0].value = hiddenValue ? 1 : 0; + formObj.checked = hiddenValue; + } + + // now that the content is loaded, set the expandState + this.expandCollapseRecord(objectId, expandSingle); + }, + + changeSorting: function(objectId, direction) { + var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true); + var objectPrefix = this.parseObjectId('full', objectId, 0, 1); + var formObj = document.getElementsByName(objectName); + + if (!formObj.length) { + return false; + } + + // the uid of the calling object (last part in objectId) + var callingUid = this.parseObjectId('none', objectId, 1); + var records = this.trimExplode(',', formObj[0].value); + var current = records.indexOf(callingUid); + var changed = false; + + // move up + if (direction > 0 && current > 0) { + records[current] = records[current - 1]; + records[current - 1] = callingUid; + changed = true; + + // move down + } else if (direction < 0 && current < records.length - 1) { + records[current] = records[current + 1]; + records[current + 1] = callingUid; + changed = true; + } + + if (changed) { + formObj[0].value = records.join(','); + var cAdj = direction > 0 ? 1 : 0; // adjustment + var objectIdPrefix = '#' + this.escapeObjectId(objectPrefix) + this.structureSeparator; + $(objectIdPrefix + records[current - cAdj] + '_div').insertBefore( + $(objectIdPrefix + records[current + 1 - cAdj] + '_div') + ); + this.redrawSortingButtons(objectPrefix, records); + } + + return false; + }, + + dragAndDropSorting: function(element) { + var objectId = element.getAttribute('id').replace(/_records$/, ''); + var objectName = 'data' + inline.parseObjectId('parts', objectId, 3, 0, true); + var formObj = document.getElementsByName(objectName); + var $element = $(element); + + if (!formObj.length) { + return; + } + + var checked = []; + var order = []; + $element.find('.sortableHandle').each(function(i, e) { + order.push($(e).data('id').toString()); + }); + var records = this.trimExplode(',', formObj[0].value); + + // check if ordered uid is really part of the records + // virtually deleted items might still be there but ordering shouldn't saved at all on them + for (var i = 0; i < order.length; i++) { + if (records.indexOf(order[i]) != -1) { + checked.push(order[i]); + } + } + + formObj[0].value = checked.join(','); + + if (inline.data.config && inline.data.config[objectId]) { + var table = inline.data.config[objectId].table; + inline.redrawSortingButtons(objectId + inline.structureSeparator + table, checked); + } + }, + + createDragAndDropSorting: function(objectId) { + require(['jquery', 'jquery-ui/sortable'], function($) { + var $sortingContainer = $('#' + inline.escapeObjectId(objectId)); + + if ($sortingContainer.hasClass('ui-sortable')) { + $sortingContainer.sortable('enable'); + return; + } + + $sortingContainer.sortable({ + containment: 'parent', + handle: '.sortableHandle', + zIndex: '4000', + axis: 'y', + tolerance: 'pointer', + stop: function() { + inline.dragAndDropSorting($sortingContainer[0]); + } + }); + }); + }, + + destroyDragAndDropSorting: function(objectId) { + require(['jquery', 'jquery-ui/sortable'], function($) { + var $sortingContainer = $('#' + inline.escapeObjectId(objectId)); + if (!$sortingContainer.hasClass('ui-sortable')) { + return; + } + $sortingContainer.sortable('disable'); + }); + }, + + redrawSortingButtons: function(objectPrefix, records) { + var i, $headerObj, sortUp, sortDown, partOfHeaderObj, iconIdentifier; + + // if no records were passed, fetch them from form field + if (typeof records == 'undefined') { + records = []; + var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); + var formObj = document.getElementsByName(objectName); + if (formObj.length) { + records = this.trimExplode(',', formObj[0].value); + } + } + partOfHeaderObj = this.escapeObjectId(objectPrefix) + this.structureSeparator; + require(['TYPO3/CMS/Backend/Icons'], function(Icons) { + for (i = 0; i < records.length; i++) { + if (!records[i].length) { + continue; + } + $headerObj = $('#' + partOfHeaderObj + records[i] + '_header'); + sortUp = $headerObj.find('.sortingUp'); + iconIdentifier = 'actions-move-up'; + if (sortUp) { + if (i == 0) { + sortUp.addClass('disabled'); + iconIdentifier = 'empty-empty'; + } else { + sortUp.removeClass('disabled'); + } + Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) { + sortUp.find('.t3js-icon').replaceWith(markup); + }); + } + sortDown = $headerObj.find('.sortingDown'); + iconIdentifier = 'actions-move-down'; + if (sortDown) { + if (i == records.length - 1) { + sortDown.addClass('disabled'); + iconIdentifier = 'empty-empty'; + } else { + sortDown.removeClass('disabled'); + } + Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) { + sortDown.find('.t3js-icon').replaceWith(markup); + }); + } + } + }); + }, + + memorizeAddRecord: function(objectPrefix, newUid, afterUid, selectedValue) { + if (this.isBelowMax(objectPrefix)) { + var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); + var formObj = document.getElementsByName(objectName); + + if (formObj.length) { + var records = []; + if (formObj[0].value.length) { + records = this.trimExplode(',', formObj[0].value); + } + + if (afterUid) { + var newRecords = []; + for (var i = 0; i < records.length; i++) { + if (records[i].length) { + newRecords.push(records[i]); + } + if (afterUid == records[i]) { + newRecords.push(newUid); + } + } + records = newRecords; + } else { + records.push(newUid); + } + formObj[0].value = records.join(','); + } + + this.redrawSortingButtons(objectPrefix, records); + + if (this.data.unique && this.data.unique[objectPrefix]) { + this.setUnique(objectPrefix, newUid, selectedValue); + } + } + + // if we reached the maximum of possible records after this action, hide the new buttons + if (!this.isBelowMax(objectPrefix)) { + var objectParent = this.parseObjectId('full', objectPrefix, 0, 1); + var md5 = this.getObjectMD5(objectParent); + this.hideElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent); + this.hideElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent); + this.hideElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent); + this.hideElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent); + this.hideElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item'); + } + + if (TBE_EDITOR) { + TBE_EDITOR.fieldChanged_fName(objectName, formObj); + } + }, + + memorizeRemoveRecord: function(objectName, removeUid) { + var formObj = document.getElementsByName(objectName); + if (formObj.length) { + var parts = [], + indexOfRemoveUid = -1; + if (formObj[0].value.length) { + parts = this.trimExplode(',', formObj[0].value); + indexOfRemoveUid = parts.indexOf(removeUid); + if (indexOfRemoveUid !== -1) { + delete parts[indexOfRemoveUid]; + } + formObj[0].value = parts.join(','); + if (TBE_EDITOR) { + TBE_EDITOR.fieldChanged_fName(objectName, formObj); + } + return parts.length; + } + } + return false; + }, + + updateUnique: function(srcElement, objectPrefix, formName, recordUid) { + if (!this.data.unique || !this.data.unique[objectPrefix]) { + return; + } + + var unique = this.data.unique[objectPrefix]; + var oldValue = unique.used[recordUid]; + + if (unique.selector == 'select') { + var selector = $(objectPrefix + '_selector'); + this.removeSelectOption(selector, srcElement.value); + if (typeof oldValue != 'undefined') { + this.readdSelectOption(selector, oldValue, unique); + } + } + + if (unique.selector && unique.max == -1) { + return; + } + + var formObj = document.getElementsByName(formName); + if (!unique || !formObj.length) { + return; + } + + var records = this.trimExplode(',', formObj[0].value); + var recordObj; + for (var i = 0; i < records.length; i++) { + recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); + if (recordObj.length && recordObj[0] != srcElement) { + var $recordObject = $(recordObj[0]); + this.removeSelectOption($recordObject, srcElement.value); + if (typeof oldValue != 'undefined') { + this.readdSelectOption($recordObject, oldValue, unique); + } + } + } + this.data.unique[objectPrefix].used[recordUid] = srcElement.value; + }, + + revertUnique: function(objectPrefix, elName, recordUid) { + if (!this.data.unique || !this.data.unique[objectPrefix]) { + return; + } + + var unique = this.data.unique[objectPrefix]; + var fieldObj = elName ? document.getElementsByName(elName + '[' + unique.field + ']') : null; + + if (unique.type == 'select') { + if (!fieldObj || !fieldObj.length) { + return; + } + + delete(this.data.unique[objectPrefix].used[recordUid]); + + if (unique.selector == 'select') { + if (!isNaN(fieldObj[0].value)) { + var $selector = $('#' + this.escapeObjectId(objectPrefix) + '_selector'); + this.readdSelectOption($selector, fieldObj[0].value, unique); + } + } + + if (unique.selector && unique.max == -1) { + return; + } + + var formName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); + var formObj = document.getElementsByName(formName); + if (!formObj.length) { + return; + } + + var records = this.trimExplode(',', formObj[0].value); + var recordObj; + // walk through all inline records on that level and get the select field + for (var i = 0; i < records.length; i++) { + recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']'); + if (recordObj.length) { + var $recordObject = $(recordObj[0]); + this.readdSelectOption($recordObject, fieldObj[0].value, unique); + } + } + } else if (unique.type == 'groupdb') { + delete(this.data.unique[objectPrefix].used[recordUid]) + } + }, + + enableDisableRecord: function(objectIdentifier, fieldName) { + var elName = this.parseObjectId('full', objectIdentifier, 2, 0, true) + '[' + fieldName + ']'; + var formObj = document.querySelector('[data-formengine-input-name="' + elName + '"]'); + var valueObj = document.getElementsByName(elName); + var escapedObjectIdentifier = this.escapeObjectId(objectIdentifier); + var $container = $('#' + escapedObjectIdentifier + '_div'); + var $icon = $container.find('.t3js-' + escapedObjectIdentifier + '_disabled .t3js-icon'); + + // It might be the case that there's no hidden field + if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) { + formObj.click(); + valueObj[0].value = formObj.checked ? 1 : 0; + TBE_EDITOR.fieldChanged_fName(elName, elName); + } + + if ($icon.length) { + require(['TYPO3/CMS/Backend/Icons'], function(Icons) { + var hiddenClass = 't3-form-field-container-inline-hidden', + isHidden = $container.hasClass(hiddenClass), + toggleIcon; + + if (isHidden) { + toggleIcon = 'actions-edit-hide'; + $container.removeClass(hiddenClass); + } else { + toggleIcon = 'actions-edit-unhide'; + $container.addClass(hiddenClass); + } + + Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(markup) { + $icon.replaceWith(markup); + }); + }); + } + + return false; + }, + + deleteRecord: function(objectId, options) { + var i, j, inlineRecords, records, childObjectId, childTable; + var objectPrefix = this.parseObjectId('full', objectId, 0, 1); + var elName = this.parseObjectId('full', objectId, 2, 0, true); + var shortName = this.parseObjectId('parts', objectId, 2, 0, true); + var recordUid = this.parseObjectId('none', objectId, 1); + var beforeDeleteIsBelowMax = this.isBelowMax(objectPrefix); + + // revert the unique settings if available + this.revertUnique(objectPrefix, elName, recordUid); + + // Remove from TBE_EDITOR (required fields, required range, etc.): + if (TBE_EDITOR && TBE_EDITOR.removeElement) { + var removeStack = []; + // Iterate over all child records: + inlineRecords = $('.inlineRecord', '#' + objectId + '_div'); + // Remove nested child records from TBE_EDITOR required/range checks: + for (i = inlineRecords.length - 1; i >= 0; i--) { + if (inlineRecords.get(i).value.length) { + records = this.trimExplode(',', inlineRecords.get(i).value); + childObjectId = this.data.map[inlineRecords.get(i).name]; + childTable = this.data.config[childObjectId].table; + for (j = records.length - 1; j >= 0; j--) { + removeStack.push('data[' + childTable + '][' + records[j] + ']'); + } + } + } + removeStack.push('data' + shortName); + TBE_EDITOR.removeElementArray(removeStack); + } + + // Mark this container as deleted + $('#' + this.escapeObjectId(objectId) + '_div') + .addClass('inlineIsDeletedRecord') + .addClass('t3js-inline-record-deleted'); + + // If the record is new and was never saved before, just remove it from DOM: + if (this.isNewRecord(objectId) || options && options.forceDirectRemoval) { + this.fadeAndRemove(objectId + '_div'); + // If the record already exists in storage, mark it to be deleted on clicking the save button: + } else { + document.getElementsByName('cmd' + shortName + '[delete]')[0].disabled = false; + $('#' + this.escapeObjectId(objectId) + '_div').fadeOut(200); + } + + var recordCount = this.memorizeRemoveRecord( + 'data' + this.parseObjectId('parts', objectId, 3, 2, true), + recordUid + ); + + if (recordCount <= 1) { + this.destroyDragAndDropSorting(this.parseObjectId('full', objectId, 0, 2) + '_records'); + } + this.redrawSortingButtons(objectPrefix); + + // if the NEW-button was hidden and now we can add again new children, show the button + if (!beforeDeleteIsBelowMax && this.isBelowMax(objectPrefix)) { + var objectParent = this.parseObjectId('full', objectPrefix, 0, 1); + var md5 = this.getObjectMD5(objectParent); + this.showElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent); + this.showElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent); + this.showElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent); + this.showElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent); + this.showElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item'); + } + TYPO3.FormEngine.Validation.validate(); + return false; + }, + + parseFormElementName: function(wrap, formElementName, rightCount, skipRight) { + var idParts = this.splitFormElementName(formElementName); + + if (!wrap) { + wrap = 'full'; + } + if (!skipRight) { + skipRight = 0; + } + + var elParts = []; + for (var i = 0; i < skipRight; i++) { + idParts.pop(); + } + + if (rightCount > 0) { + for (var i = 0; i < rightCount; i++) { + elParts.unshift(idParts.pop()); + } + } else { + for (var i = 0; i < -rightCount; i++) { + idParts.shift(); + } + elParts = idParts; + } + + return this.constructFormElementName(wrap, elParts); + }, + + splitFormElementName: function(formElementName) { + // remove left and right side "data[...|...]" -> '...|...' + formElementName = formElementName.substr(0, formElementName.lastIndexOf(']')).substr(formElementName.indexOf('[') + 1); + return formElementName.split(']['); + }, + + splitObjectId: function(objectId) { + objectId = objectId.substr(objectId.indexOf(this.structureSeparator) + 1); + objectId = objectId.split(this.flexFormSeparator).join(this.flexFormSubstitute); + return objectId.split(this.structureSeparator); + }, + + constructFormElementName: function(wrap, parts) { + var elReturn; + + if (wrap == 'full') { + elReturn = 'data[' + parts.join('][') + ']'; + elReturn = elReturn.split(this.flexFormSubstitute).join(']['); + } else if (wrap == 'parts') { + elReturn = '[' + parts.join('][') + ']'; + elReturn = elReturn.split(this.flexFormSubstitute).join(']['); + } else if (wrap == 'none') { + elReturn = parts.length > 1 ? parts : parts.join(''); + } + + return elReturn; + }, + + constructObjectId: function(wrap, parts) { + var elReturn; + + if (wrap == 'full') { + elReturn = 'data' + this.structureSeparator + parts.join(this.structureSeparator); + elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator); + } else if (wrap == 'parts') { + elReturn = this.structureSeparator + parts.join(this.structureSeparator); + elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator); + } else if (wrap == 'none') { + elReturn = parts.length > 1 ? parts : parts.join(''); + } + + return elReturn; + }, + + parseObjectId: function(wrap, objectId, rightCount, skipRight, returnAsFormElementName) { + var idParts = this.splitObjectId(objectId); + + if (!wrap) { + wrap = 'full'; + } + if (!skipRight) { + skipRight = 0; + } + + var elParts = []; + for (var i = 0; i < skipRight; i++) { + idParts.pop(); + } + + if (rightCount > 0) { + for (var i = 0; i < rightCount; i++) { + elParts.unshift(idParts.pop()); + } + } else { + for (var i = 0; i < -rightCount; i++) { + idParts.shift(); + } + elParts = idParts; + } + + return returnAsFormElementName + ? this.constructFormElementName(wrap, elParts) + : this.constructObjectId(wrap, elParts); + }, + + handleChangedField: function(formField, objectId) { + var formObj; + if (typeof formField == 'object') { + formObj = formField; + } else { + formObj = document.getElementsByName(formField); + if (formObj.length) { + formObj = formObj[0]; + } + } + + if (formObj != undefined) { + var value; + if (formObj.nodeName == 'SELECT') { + value = formObj.options[formObj.selectedIndex].text; + } else { + value = formObj.value; + } + $('#' + this.escapeObjectId(objectId) + '_label').text(value.length ? value : this.noTitleString); + } + return true; + }, + + arrayAssocCount: function(object) { + var count = 0; + if (typeof object.length != 'undefined') { + count = object.length; + } else { + for (var i in object) { + count++; + } + } + return count; + }, + + isBelowMax: function(objectPrefix) { + var isBelowMax = true; + var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true); + var formObj = document.getElementsByName(objectName); + + if (this.data.config && this.data.config[objectPrefix] && formObj.length) { + var recordCount = formObj[0].value ? this.trimExplode(',', formObj[0].value).length : 0; + if (recordCount >= this.data.config[objectPrefix].max) { + isBelowMax = false; + } + } + if (isBelowMax && this.data.unique && this.data.unique[objectPrefix]) { + var unique = this.data.unique[objectPrefix]; + if (this.arrayAssocCount(unique.used) >= unique.max && unique.max >= 0) { + isBelowMax = false; + } + } + return isBelowMax; + }, + + getOptionsHash: function($selectObj) { + var optionsHash = {}; + $selectObj.find('option').each(function(i, option) { + optionsHash[option.value] = i; + }); + return optionsHash; + }, + + removeSelectOption: function($selectObj, value) { + var optionsHash = this.getOptionsHash($selectObj); + if (optionsHash[value] != undefined) { + $selectObj.find('option').eq(optionsHash[value]).remove(); + } + }, + + readdSelectOption: function($selectObj, value, unique) { + if (!$selectObj.length) { + return; + } + + var index = null; + var optionsHash = this.getOptionsHash($selectObj); + + for (var possibleValue in unique.possible) { + if (possibleValue == value) { + break; + } + if (optionsHash[possibleValue] != undefined) { + index = optionsHash[possibleValue]; + } + } + + if (index == null) { + index = 0; + } else if (index < $selectObj.find('option').length) { + index++; + } + // recreate the <option> tag + var readdOption = document.createElement('option'); + readdOption.text = unique.possible[value]; + readdOption.value = value; + // add the <option> at the right position + // I didn't find a possibility to add an option to a predefined position + // with help of an index in jQuery. So we realized it the "old" style + var selectObj = $selectObj.get(0); + selectObj.add(readdOption, document.all ? index : selectObj.options[index]); + }, + + hideElementsWithClassName: function(selector, parentElement) { + $('#' + this.escapeObjectId(parentElement)).find(selector).fadeOut(200); + }, + + showElementsWithClassName: function(selector, parentElement) { + $('#' + this.escapeObjectId(parentElement)).find(selector).fadeIn(200); + }, + + // sets the opacity to 0.2 and then fades in to opacity 1 + fadeOutFadeIn: function(objectId) { + $('#' + this.escapeObjectId(objectId)).css({opacity: 0.2}).fadeTo(200, 1, 'linear'); + }, + + isNewRecord: function(objectId) { + var $selector = $('#' + this.escapeObjectId(objectId) + '_div'); + return $selector.length && $selector.hasClass('inlineIsNewRecord'); + }, + + // Find and fix nested of inline and tab levels if a new element was created dynamically (it doesn't know about its nesting): + findContinuedNestedLevel: function(nested, objectId) { + if (this.data.nested && this.data.nested[objectId]) { + // Remove the first element from the new nested stack, it's just a hint: + nested.shift(); + nested = this.data.nested[objectId].concat(nested); + } + return nested; + }, + + getObjectMD5: function(objectPrefix) { + var md5 = false; + if (this.data.config && this.data.config[objectPrefix] && this.data.config[objectPrefix].md5) { + md5 = this.data.config[objectPrefix].md5; + } + return md5 + }, + + fadeAndRemove: function(element) { + $('#' + this.escapeObjectId(element)).fadeOut(200, function() { + $(this).remove(); + TYPO3.FormEngine.Validation.validate(); + }); + }, + + getContext: function(objectId) { + var result = null; + + if (objectId !== '' && typeof this.data.config[objectId] !== 'undefined' && typeof this.data.config[objectId].context !== 'undefined') { + result = this.data.config[objectId].context; + } + + return result; + }, + + /** + * Escapes object identifiers to be used in jQuery. + * + * @param {String} objectId + * @return string + */ + escapeObjectId: function(objectId) { + var escapedObjectId; + escapedObjectId = objectId.replace(/:/g, '\\:'); + escapedObjectId = escapedObjectId.replace(/\./g, '\\.'); + return escapedObjectId; + }, + + /** + * Helper function to get clean trimmed array from comma list + * + * @param {String} delimiter + * @param {String} string + * @returns {Array} + */ + trimExplode: function(delimiter, string) { + var result = []; + var items = string.split(delimiter); + for (var i = 0; i < items.length; i++) { + var item = items[i].trim(); + if (item.length > 0) { + result.push(item); + } + } + return result; + } }; /*]]>*/ -$(function () { - $(document).on('click', '[data-toggle="formengine-inline"]', function(event) { - inline.toggleEvent(event); - }); +$(function() { + $(document).on('click', '[data-toggle="formengine-inline"]', function(event) { + inline.toggleEvent(event); + }); }); diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js index 2de9c5eb3be119b6925301531c63039e3adda578..9a138b1311da8ffa1e1da51cd87c2b4c26a823b7 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js @@ -16,229 +16,240 @@ */ var TBE_EDITOR = { - /* Example: - elements: { - 'data-parentPid-table-uid': { - 'field': { - 'range': [0, 100], - 'rangeImg': '', - 'required': true, - 'requiredImg': '' - } - } - }, - */ + /* Example: + elements: { + 'data-parentPid-table-uid': { + 'field': { + 'range': [0, 100], + 'rangeImg': '', + 'required': true, + 'requiredImg': '' + } + } + }, + */ - elements: {}, - nested: {'field':{}, 'level':{}}, - ignoreElements: [], - actionChecks: { submit: [] }, - customEvalFunctions: {}, + elements: {}, + nested: {'field': {}, 'level': {}}, + ignoreElements: [], + actionChecks: {submit: []}, + customEvalFunctions: {}, - formname: 'editform', - isChanged: 0, + formname: 'editform', + isChanged: 0, - doSaveFieldName: 0, + doSaveFieldName: 0, - labels: {}, + labels: {}, - clearBeforeSettingFormValueFromBrowseWin: [], + clearBeforeSettingFormValueFromBrowseWin: [], - // Handling of data structures: - removeElement: function(record) { - if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) { - delete(TBE_EDITOR.elements[record]); - } - }, - removeElementArray: function(removeStack) { - if (removeStack && removeStack.length) { - TBE_EDITOR.ignoreElements = removeStack; - for (var i=removeStack.length; i>=0; i--) { - TBE_EDITOR.removeElement(removeStack[i]); - } - TBE_EDITOR.ignoreElements = []; - } - }, - getElement: function(record, field, type) { - var result = null; - var element; + // Handling of data structures: + removeElement: function(record) { + if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) { + delete(TBE_EDITOR.elements[record]); + } + }, + removeElementArray: function(removeStack) { + if (removeStack && removeStack.length) { + TBE_EDITOR.ignoreElements = removeStack; + for (var i = removeStack.length; i >= 0; i--) { + TBE_EDITOR.removeElement(removeStack[i]); + } + TBE_EDITOR.ignoreElements = []; + } + }, + getElement: function(record, field, type) { + var result = null; + var element; - if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) { - element = TBE_EDITOR.elements[record][field]; - if (type) { - if (element[type]) result = element; - } else { - result = element; - } - } + if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) { + element = TBE_EDITOR.elements[record][field]; + if (type) { + if (element[type]) result = element; + } else { + result = element; + } + } - return result; - }, - checkElements: function() { - return (document.getElementsByClassName('has-error').length == 0); - }, - addActionChecks: function(type, checks) { - TBE_EDITOR.actionChecks[type].push(checks); - }, + return result; + }, + checkElements: function() { + return (document.getElementsByClassName('has-error').length == 0); + }, + addActionChecks: function(type, checks) { + TBE_EDITOR.actionChecks[type].push(checks); + }, - fieldChanged_fName: function(fName,el) { - var idx=2; - var table = TBE_EDITOR.split(fName, "[", idx); - var uid = TBE_EDITOR.split(fName, "[", idx+1); - var field = TBE_EDITOR.split(fName, "[", idx+2); + fieldChanged_fName: function(fName, el) { + var idx = 2; + var table = TBE_EDITOR.split(fName, "[", idx); + var uid = TBE_EDITOR.split(fName, "[", idx + 1); + var field = TBE_EDITOR.split(fName, "[", idx + 2); - table = table.substr(0,table.length-1); - uid = uid.substr(0,uid.length-1); - field = field.substr(0,field.length-1); - TBE_EDITOR.fieldChanged(table,uid,field,el); - }, - fieldChanged: function(table,uid,field,el) { - var theField = 'data['+table+']['+uid+']['+field+']'; - TBE_EDITOR.isChanged = 1; + table = table.substr(0, table.length - 1); + uid = uid.substr(0, uid.length - 1); + field = field.substr(0, field.length - 1); + TBE_EDITOR.fieldChanged(table, uid, field, el); + }, + fieldChanged: function(table, uid, field, el) { + var theField = 'data[' + table + '][' + uid + '][' + field + ']'; + TBE_EDITOR.isChanged = 1; - // modify the "field has changed" info by adding a class to the container element (based on palette or main field) - var $formField = $('[name="' + el + '"]'); - var $humanReadableField = $('[data-formengine-input-name="' + el + '"]'); - if (!$formField.is($humanReadableField)) { - $humanReadableField.triggerHandler('change'); - } - // add class to palette field - $formField.closest('.t3js-formengine-palette-field').addClass('has-change'); + // modify the "field has changed" info by adding a class to the container element (based on palette or main field) + var $formField = $('[name="' + el + '"]'); + var $humanReadableField = $('[data-formengine-input-name="' + el + '"]'); + if (!$formField.is($humanReadableField)) { + $humanReadableField.triggerHandler('change'); + } + // add class to palette field + $formField.closest('.t3js-formengine-palette-field').addClass('has-change'); - if (TYPO3.FormEngine && TYPO3.FormEngine.Validation) { - TYPO3.FormEngine.Validation.updateInputField(theField); - TYPO3.FormEngine.Validation.validate(); - } - }, - isFormChanged: function(noAlert) { - if (TBE_EDITOR.isChanged && !noAlert && confirm(TYPO3.lang['FormEngine.fieldsChanged'])) { - return 0; - } - return TBE_EDITOR.isChanged; - }, - checkAndDoSubmit: function(sendAlert) { - if (TBE_EDITOR.checkSubmit(sendAlert)) { TBE_EDITOR.submitForm(); } - }, - /** - * Checks if the form can be submitted according to any possible restrains like required values, item numbers etc. - * Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1) - * If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will). - * If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...) - */ - checkSubmit: function(sendAlert) { - var funcIndex, funcMax, funcRes; - var OK = 1; - var STOP = 0; + if (TYPO3.FormEngine && TYPO3.FormEngine.Validation) { + TYPO3.FormEngine.Validation.updateInputField(theField); + TYPO3.FormEngine.Validation.validate(); + } + }, + isFormChanged: function(noAlert) { + if (TBE_EDITOR.isChanged && !noAlert && confirm(TYPO3.lang['FormEngine.fieldsChanged'])) { + return 0; + } + return TBE_EDITOR.isChanged; + }, + checkAndDoSubmit: function(sendAlert) { + if (TBE_EDITOR.checkSubmit(sendAlert)) { + TBE_EDITOR.submitForm(); + } + }, + /** + * Checks if the form can be submitted according to any possible restrains like required values, item numbers etc. + * Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1) + * If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will). + * If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...) + */ + checkSubmit: function(sendAlert) { + var funcIndex, funcMax, funcRes; + var OK = 1; + var STOP = 0; - // $this->additionalJS_submit: - if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) { - for (funcIndex=0, funcMax=TBE_EDITOR.actionChecks.submit.length; funcIndex<funcMax; funcIndex++) { - try { - eval(TBE_EDITOR.actionChecks.submit[funcIndex]); - } catch(error) {} - } - } + // $this->additionalJS_submit: + if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) { + for (funcIndex = 0, funcMax = TBE_EDITOR.actionChecks.submit.length; funcIndex < funcMax; funcIndex++) { + try { + eval(TBE_EDITOR.actionChecks.submit[funcIndex]); + } catch (error) { + } + } + } - if (STOP) { - // return false immediately, if the code in additionalJS_submit set STOP variable. - return false; - } + if (STOP) { + // return false immediately, if the code in additionalJS_submit set STOP variable. + return false; + } - if (!OK) { - if (!confirm(unescape("SYSTEM ERROR: One or more Rich Text Editors on the page could not be contacted. This IS an error, although it should not be regular.\nYou can save the form now by pressing OK, but you will loose the Rich Text Editor content if you do.\n\nPlease report the error to your administrator if it persists."))) { - return false; - } else { - OK = 1; - } - } - if (!TBE_EDITOR.checkElements()) { - OK = 0; - } + if (!OK) { + if (!confirm(unescape("SYSTEM ERROR: One or more Rich Text Editors on the page could not be contacted. This IS an error, although it should not be regular.\nYou can save the form now by pressing OK, but you will loose the Rich Text Editor content if you do.\n\nPlease report the error to your administrator if it persists."))) { + return false; + } else { + OK = 1; + } + } + if (!TBE_EDITOR.checkElements()) { + OK = 0; + } - if (OK || sendAlert==-1) { - return true; - } else { - if (sendAlert) { - var t = (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top); - t.TYPO3.Modal.confirm( - t.TYPO3.lang['alert'] || 'Alert', - TYPO3.lang['FormEngine.fieldsMissing'], - t.TYPO3.Severity.error, - [ - { - text: t.TYPO3.lang['button.ok'] || 'OK', - active: true, - btnClass: 'btn-default', - name: 'ok' - } - ] - ).on('button.clicked', function(e) { - t.TYPO3.Modal.dismiss(); - }); - } - return false; - } - }, - submitForm: function() { - if (TBE_EDITOR.doSaveFieldName) { - document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value=1; - } - // Set a short timeout to allow other JS processes to complete, in particular those from - // EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755). - // TODO: This should be solved in a better way when this script is refactored. - window.setTimeout(function() { - document.getElementsByName(TBE_EDITOR.formname).item(0).submit(); - }, 100); - }, - split: function(theStr1, delim, index) { - var theStr = ""+theStr1; - var lengthOfDelim = delim.length; - sPos = -lengthOfDelim; - if (index<1) {index=1;} - for (var a=1; a<index; a++) { - sPos = theStr.indexOf(delim, sPos+lengthOfDelim); - if (sPos==-1) { return null; } - } - ePos = theStr.indexOf(delim, sPos+lengthOfDelim); - if(ePos == -1) { ePos = theStr.length; } - return (theStr.substring(sPos+lengthOfDelim,ePos)); - }, - curSelected: function(theField) { - var fObjSel = $('[data-formengine-input-name="' + theField + '"]').get(1); - var retVal=""; - if (fObjSel) { - if (fObjSel.type=='select-multiple' || fObjSel.type=='select-one') { - var l=fObjSel.length; - for (a=0;a<l;a++) { - if (fObjSel.options[a].selected==1) { - retVal+=fObjSel.options[a].value+","; - } - } - } - } - return retVal; - }, - rawurlencode: function(str,maxlen) { - var output = str; - if (maxlen) output = output.substr(0,200); - output = encodeURIComponent(output); - return output; - }, - str_replace: function(match,replace,string) { - var input = ''+string; - var matchStr = ''+match; - if (!matchStr) { return string; } - var output = ''; - var pointer=0; - var pos = input.indexOf(matchStr); - while (pos!=-1) { - output+=''+input.substr(pointer, pos-pointer)+replace; - pointer=pos+matchStr.length; - pos = input.indexOf(match,pos+1); - } - output+=''+input.substr(pointer); - return output; - }, + if (OK || sendAlert == -1) { + return true; + } else { + if (sendAlert) { + var t = (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top); + t.TYPO3.Modal.confirm( + t.TYPO3.lang['alert'] || 'Alert', + TYPO3.lang['FormEngine.fieldsMissing'], + t.TYPO3.Severity.error, + [ + { + text: t.TYPO3.lang['button.ok'] || 'OK', + active: true, + btnClass: 'btn-default', + name: 'ok' + } + ] + ).on('button.clicked', function(e) { + t.TYPO3.Modal.dismiss(); + }); + } + return false; + } + }, + submitForm: function() { + if (TBE_EDITOR.doSaveFieldName) { + document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value = 1; + } + // Set a short timeout to allow other JS processes to complete, in particular those from + // EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755). + // TODO: This should be solved in a better way when this script is refactored. + window.setTimeout(function() { + document.getElementsByName(TBE_EDITOR.formname).item(0).submit(); + }, 100); + }, + split: function(theStr1, delim, index) { + var theStr = "" + theStr1; + var lengthOfDelim = delim.length; + sPos = -lengthOfDelim; + if (index < 1) { + index = 1; + } + for (var a = 1; a < index; a++) { + sPos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (sPos == -1) { + return null; + } + } + ePos = theStr.indexOf(delim, sPos + lengthOfDelim); + if (ePos == -1) { + ePos = theStr.length; + } + return (theStr.substring(sPos + lengthOfDelim, ePos)); + }, + curSelected: function(theField) { + var fObjSel = $('[data-formengine-input-name="' + theField + '"]').get(1); + var retVal = ""; + if (fObjSel) { + if (fObjSel.type == 'select-multiple' || fObjSel.type == 'select-one') { + var l = fObjSel.length; + for (a = 0; a < l; a++) { + if (fObjSel.options[a].selected == 1) { + retVal += fObjSel.options[a].value + ","; + } + } + } + } + return retVal; + }, + rawurlencode: function(str, maxlen) { + var output = str; + if (maxlen) output = output.substr(0, 200); + output = encodeURIComponent(output); + return output; + }, + str_replace: function(match, replace, string) { + var input = '' + string; + var matchStr = '' + match; + if (!matchStr) { + return string; + } + var output = ''; + var pointer = 0; + var pos = input.indexOf(matchStr); + while (pos != -1) { + output += '' + input.substr(pointer, pos - pointer) + replace; + pointer = pos + matchStr.length; + pos = input.indexOf(match, pos + 1); + } + output += '' + input.substr(pointer); + return output; + } }; // backwards compatibility for extensions @@ -257,55 +268,55 @@ var TBE_EDITOR_str_replace = TBE_EDITOR.str_replace; var typo3form = { - fieldSet: function(theField, evallist, is_in, checkbox, checkboxValue) { - if (document[TBE_EDITOR.formname][theField]) { - var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue); - var theValue = document[TBE_EDITOR.formname][theField].value; - if (checkbox && theValue==checkboxValue) { - document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = ""; - if (document[TBE_EDITOR.formname][theField+"_cb"]) document[TBE_EDITOR.formname][theField+"_cb"].checked = ""; - } else { - document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = evalFunc.outputObjValue(theFObj, theValue); - if (document[TBE_EDITOR.formname][theField+"_cb"]) document[TBE_EDITOR.formname][theField+"_cb"].checked = "on"; - } - } - }, - fieldGet: function(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off, checkSetValue) { - if (document[TBE_EDITOR.formname][theField]) { - var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue); - if (checkbox_off) { - if (document[TBE_EDITOR.formname][theField+"_cb"].checked) { - var split = evallist.split(','); - for (var i = 0; split.length > i; i++) { - var el = split[i].replace(/ /g, ''); - if (el == 'datetime' || el == 'date') { - var now = new Date(); - checkSetValue = Date.parse(now)/1000 - now.getTimezoneOffset()*60; - break; - } else if (el == 'time' || el == 'timesec') { - checkSetValue = evalFunc_getTimeSecs(new Date()); - break; - } - } - document[TBE_EDITOR.formname][theField].value=checkSetValue; - } else { - document[TBE_EDITOR.formname][theField].value=checkboxValue; - } - }else{ - document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value); - } - typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue); - } - } + fieldSet: function(theField, evallist, is_in, checkbox, checkboxValue) { + if (document[TBE_EDITOR.formname][theField]) { + var theFObj = new evalFunc_dummy(evallist, is_in, checkbox, checkboxValue); + var theValue = document[TBE_EDITOR.formname][theField].value; + if (checkbox && theValue == checkboxValue) { + document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = ""; + if (document[TBE_EDITOR.formname][theField + "_cb"]) document[TBE_EDITOR.formname][theField + "_cb"].checked = ""; + } else { + document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = evalFunc.outputObjValue(theFObj, theValue); + if (document[TBE_EDITOR.formname][theField + "_cb"]) document[TBE_EDITOR.formname][theField + "_cb"].checked = "on"; + } + } + }, + fieldGet: function(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off, checkSetValue) { + if (document[TBE_EDITOR.formname][theField]) { + var theFObj = new evalFunc_dummy(evallist, is_in, checkbox, checkboxValue); + if (checkbox_off) { + if (document[TBE_EDITOR.formname][theField + "_cb"].checked) { + var split = evallist.split(','); + for (var i = 0; split.length > i; i++) { + var el = split[i].replace(/ /g, ''); + if (el == 'datetime' || el == 'date') { + var now = new Date(); + checkSetValue = Date.parse(now) / 1000 - now.getTimezoneOffset() * 60; + break; + } else if (el == 'time' || el == 'timesec') { + checkSetValue = evalFunc_getTimeSecs(new Date()); + break; + } + } + document[TBE_EDITOR.formname][theField].value = checkSetValue; + } else { + document[TBE_EDITOR.formname][theField].value = checkboxValue; + } + } else { + document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value); + } + typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue); + } + } }; // @TODO: This function is a copy from jsfunc.evalfield.js // @TODO: Remove it later, after TBE_EDITOR is not used anymore. -function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) { - this.evallist = evallist; - this.is_in = is_in; - this.checkboxValue = checkboxValue; - this.checkbox = checkbox; +function evalFunc_dummy(evallist, is_in, checkbox, checkboxValue) { + this.evallist = evallist; + this.is_in = is_in; + this.checkboxValue = checkboxValue; + this.checkbox = checkbox; } // backwards compatibility for extensions diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/md5.js b/typo3/sysext/backend/Resources/Public/JavaScript/md5.js index 8ed0ad042f02584172efd2a41985eebbf1c8d0db..5108d176dcbffe80085cc0e1e53e3a241b842d8f 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/md5.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/md5.js @@ -1,207 +1,224 @@ /** -* -* MD5 (Message-Digest Algorithm) -* http://www.webtoolkit.info/ -* -**/ + * + * MD5 (Message-Digest Algorithm) + * http://www.webtoolkit.info/ + * + **/ function MD5(string) { - function RotateLeft(lValue, iShiftBits) { - return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits)); - } - - function AddUnsigned(lX,lY) { - var lX4,lY4,lX8,lY8,lResult; - lX8 = (lX & 0x80000000); - lY8 = (lY & 0x80000000); - lX4 = (lX & 0x40000000); - lY4 = (lY & 0x40000000); - lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF); - if (lX4 & lY4) { - return (lResult ^ 0x80000000 ^ lX8 ^ lY8); - } - if (lX4 | lY4) { - if (lResult & 0x40000000) { - return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); - } else { - return (lResult ^ 0x40000000 ^ lX8 ^ lY8); - } - } else { - return (lResult ^ lX8 ^ lY8); - } - } - - function F(x,y,z) { return (x & y) | ((~x) & z); } - function G(x,y,z) { return (x & z) | (y & (~z)); } - function H(x,y,z) { return (x ^ y ^ z); } - function I(x,y,z) { return (y ^ (x | (~z))); } - - function FF(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function GG(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function HH(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function II(a,b,c,d,x,s,ac) { - a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); - return AddUnsigned(RotateLeft(a, s), b); - }; - - function ConvertToWordArray(string) { - var lWordCount; - var lMessageLength = string.length; - var lNumberOfWords_temp1=lMessageLength + 8; - var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64; - var lNumberOfWords = (lNumberOfWords_temp2+1)*16; - var lWordArray=Array(lNumberOfWords-1); - var lBytePosition = 0; - var lByteCount = 0; - while ( lByteCount < lMessageLength ) { - lWordCount = (lByteCount-(lByteCount % 4))/4; - lBytePosition = (lByteCount % 4)*8; - lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition)); - lByteCount++; - } - lWordCount = (lByteCount-(lByteCount % 4))/4; - lBytePosition = (lByteCount % 4)*8; - lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition); - lWordArray[lNumberOfWords-2] = lMessageLength<<3; - lWordArray[lNumberOfWords-1] = lMessageLength>>>29; - return lWordArray; - }; - - function WordToHex(lValue) { - var WordToHexValue="",WordToHexValue_temp="",lByte,lCount; - for (lCount = 0;lCount<=3;lCount++) { - lByte = (lValue>>>(lCount*8)) & 255; - WordToHexValue_temp = "0" + lByte.toString(16); - WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2); - } - return WordToHexValue; - }; - - function Utf8Encode(string) { - string = string.replace(/\r\n/g,"\n"); - var utftext = ""; - - for (var n = 0; n < string.length; n++) { - - var c = string.charCodeAt(n); - - if (c < 128) { - utftext += String.fromCharCode(c); - } - else if((c > 127) && (c < 2048)) { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } - else { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - - } - - return utftext; - }; - - var x=Array(); - var k,AA,BB,CC,DD,a,b,c,d; - var S11=7, S12=12, S13=17, S14=22; - var S21=5, S22=9 , S23=14, S24=20; - var S31=4, S32=11, S33=16, S34=23; - var S41=6, S42=10, S43=15, S44=21; - - string = Utf8Encode(string); - - x = ConvertToWordArray(string); - - a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; - - for (k=0;k<x.length;k+=16) { - AA=a; BB=b; CC=c; DD=d; - a=FF(a,b,c,d,x[k+0], S11,0xD76AA478); - d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756); - c=FF(c,d,a,b,x[k+2], S13,0x242070DB); - b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE); - a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF); - d=FF(d,a,b,c,x[k+5], S12,0x4787C62A); - c=FF(c,d,a,b,x[k+6], S13,0xA8304613); - b=FF(b,c,d,a,x[k+7], S14,0xFD469501); - a=FF(a,b,c,d,x[k+8], S11,0x698098D8); - d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF); - c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1); - b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE); - a=FF(a,b,c,d,x[k+12],S11,0x6B901122); - d=FF(d,a,b,c,x[k+13],S12,0xFD987193); - c=FF(c,d,a,b,x[k+14],S13,0xA679438E); - b=FF(b,c,d,a,x[k+15],S14,0x49B40821); - a=GG(a,b,c,d,x[k+1], S21,0xF61E2562); - d=GG(d,a,b,c,x[k+6], S22,0xC040B340); - c=GG(c,d,a,b,x[k+11],S23,0x265E5A51); - b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA); - a=GG(a,b,c,d,x[k+5], S21,0xD62F105D); - d=GG(d,a,b,c,x[k+10],S22,0x2441453); - c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681); - b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8); - a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6); - d=GG(d,a,b,c,x[k+14],S22,0xC33707D6); - c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87); - b=GG(b,c,d,a,x[k+8], S24,0x455A14ED); - a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905); - d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8); - c=GG(c,d,a,b,x[k+7], S23,0x676F02D9); - b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A); - a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942); - d=HH(d,a,b,c,x[k+8], S32,0x8771F681); - c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122); - b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C); - a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44); - d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9); - c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60); - b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70); - a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6); - d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA); - c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085); - b=HH(b,c,d,a,x[k+6], S34,0x4881D05); - a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039); - d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5); - c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8); - b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665); - a=II(a,b,c,d,x[k+0], S41,0xF4292244); - d=II(d,a,b,c,x[k+7], S42,0x432AFF97); - c=II(c,d,a,b,x[k+14],S43,0xAB9423A7); - b=II(b,c,d,a,x[k+5], S44,0xFC93A039); - a=II(a,b,c,d,x[k+12],S41,0x655B59C3); - d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92); - c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D); - b=II(b,c,d,a,x[k+1], S44,0x85845DD1); - a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F); - d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0); - c=II(c,d,a,b,x[k+6], S43,0xA3014314); - b=II(b,c,d,a,x[k+13],S44,0x4E0811A1); - a=II(a,b,c,d,x[k+4], S41,0xF7537E82); - d=II(d,a,b,c,x[k+11],S42,0xBD3AF235); - c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB); - b=II(b,c,d,a,x[k+9], S44,0xEB86D391); - a=AddUnsigned(a,AA); - b=AddUnsigned(b,BB); - c=AddUnsigned(c,CC); - d=AddUnsigned(d,DD); - } - - var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d); - - return temp.toLowerCase(); -} \ No newline at end of file + function RotateLeft(lValue, iShiftBits) { + return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits)); + } + + function AddUnsigned(lX, lY) { + var lX4, lY4, lX8, lY8, lResult; + lX8 = (lX & 0x80000000); + lY8 = (lY & 0x80000000); + lX4 = (lX & 0x40000000); + lY4 = (lY & 0x40000000); + lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF); + if (lX4 & lY4) { + return (lResult ^ 0x80000000 ^ lX8 ^ lY8); + } + if (lX4 | lY4) { + if (lResult & 0x40000000) { + return (lResult ^ 0xC0000000 ^ lX8 ^ lY8); + } else { + return (lResult ^ 0x40000000 ^ lX8 ^ lY8); + } + } else { + return (lResult ^ lX8 ^ lY8); + } + } + + function F(x, y, z) { + return (x & y) | ((~x) & z); + } + + function G(x, y, z) { + return (x & z) | (y & (~z)); + } + + function H(x, y, z) { + return (x ^ y ^ z); + } + + function I(x, y, z) { + return (y ^ (x | (~z))); + } + + function FF(a, b, c, d, x, s, ac) { + a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac)); + return AddUnsigned(RotateLeft(a, s), b); + }; + + function GG(a, b, c, d, x, s, ac) { + a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac)); + return AddUnsigned(RotateLeft(a, s), b); + }; + + function HH(a, b, c, d, x, s, ac) { + a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac)); + return AddUnsigned(RotateLeft(a, s), b); + }; + + function II(a, b, c, d, x, s, ac) { + a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac)); + return AddUnsigned(RotateLeft(a, s), b); + }; + + function ConvertToWordArray(string) { + var lWordCount; + var lMessageLength = string.length; + var lNumberOfWords_temp1 = lMessageLength + 8; + var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64; + var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16; + var lWordArray = Array(lNumberOfWords - 1); + var lBytePosition = 0; + var lByteCount = 0; + while (lByteCount < lMessageLength) { + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition)); + lByteCount++; + } + lWordCount = (lByteCount - (lByteCount % 4)) / 4; + lBytePosition = (lByteCount % 4) * 8; + lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition); + lWordArray[lNumberOfWords - 2] = lMessageLength << 3; + lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29; + return lWordArray; + }; + + function WordToHex(lValue) { + var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount; + for (lCount = 0; lCount <= 3; lCount++) { + lByte = (lValue >>> (lCount * 8)) & 255; + WordToHexValue_temp = "0" + lByte.toString(16); + WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2); + } + return WordToHexValue; + }; + + function Utf8Encode(string) { + string = string.replace(/\r\n/g, "\n"); + var utftext = ""; + + for (var n = 0; n < string.length; n++) { + + var c = string.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if ((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + + } + + return utftext; + }; + + var x = Array(); + var k, AA, BB, CC, DD, a, b, c, d; + var S11 = 7, S12 = 12, S13 = 17, S14 = 22; + var S21 = 5, S22 = 9, S23 = 14, S24 = 20; + var S31 = 4, S32 = 11, S33 = 16, S34 = 23; + var S41 = 6, S42 = 10, S43 = 15, S44 = 21; + + string = Utf8Encode(string); + + x = ConvertToWordArray(string); + + a = 0x67452301; + b = 0xEFCDAB89; + c = 0x98BADCFE; + d = 0x10325476; + + for (k = 0; k < x.length; k += 16) { + AA = a; + BB = b; + CC = c; + DD = d; + a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478); + d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756); + c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB); + b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE); + a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF); + d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A); + c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613); + b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501); + a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8); + d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF); + c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1); + b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE); + a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122); + d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193); + c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E); + b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821); + a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562); + d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340); + c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51); + b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA); + a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D); + d = GG(d, a, b, c, x[k + 10], S22, 0x2441453); + c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681); + b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8); + a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6); + d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6); + c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87); + b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED); + a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905); + d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8); + c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9); + b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A); + a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942); + d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681); + c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122); + b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C); + a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44); + d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9); + c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60); + b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70); + a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6); + d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA); + c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085); + b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05); + a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039); + d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5); + c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8); + b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665); + a = II(a, b, c, d, x[k + 0], S41, 0xF4292244); + d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97); + c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7); + b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039); + a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3); + d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92); + c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D); + b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1); + a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F); + d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0); + c = II(c, d, a, b, x[k + 6], S43, 0xA3014314); + b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1); + a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82); + d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235); + c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB); + b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391); + a = AddUnsigned(a, AA); + b = AddUnsigned(b, BB); + c = AddUnsigned(c, CC); + d = AddUnsigned(d, DD); + } + + var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d); + + return temp.toLowerCase(); +} diff --git a/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js b/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js index c76186cac6fa5266e4f66f4e35cff9d91b73da84..b9d88053ebf5ad822ed19baeac5ec784faef5f5c 100644 --- a/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js +++ b/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js @@ -1,413 +1,419 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngineValidation'], function($, FormEngineValidation) { - 'use strict'; + 'use strict'; - describe('TYPO3/CMS/Backend/FormEngineValidationTest:', function() { - /** - * @type {*[]} - */ - var formatValueDataProvider = [ - { - 'description': 'works for type date', - 'type': 'date', - 'value': 0, - 'config': [], - 'result': '' - }, - { - 'description': 'works for type date with timestamp', - 'type': 'date', - 'value': 10000000, - 'config': [], - 'result': '26-4-1970' - }, - { - 'description': 'works for type date with iso date', - 'type': 'date', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '02-12-2016' - }, - { - 'description': 'works for type datetime', - 'type': 'datetime', - 'value': 0, - 'config': [], - 'result': '' - }, - { - 'description': 'works for type datetime with timestamp', - 'type': 'datetime', - 'value': 10000000, - 'config': [], - 'result': '17:46 26-4-1970' - }, - { - 'description': 'works for type datetime with iso date', - 'type': 'datetime', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '11:16 02-12-2016' - }, - { - 'description': 'resolves to empty result for zero value', - 'type': 'datetime', - 'value': 0, - 'config': [], - 'result': '' - }, - { - 'description': 'resolves to empty result for invalid value', - 'type': 'datetime', - 'value': 'invalid', - 'config': [], - 'result': '' - }, - { - 'description': 'works for type time', - 'type': 'time', - 'value': 0, - 'config': [], - 'result': '00:00' - }, - { - 'description': 'works for type time with timestamp', - 'type': 'time', - 'value': 10000000, - 'config': [], - 'result': '17:46' - }, - { - 'description': 'works for type time with iso date', - 'type': 'time', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '11:16' - } - ]; + describe('TYPO3/CMS/Backend/FormEngineValidationTest:', function() { + /** + * @type {*[]} + */ + var formatValueDataProvider = [ + { + 'description': 'works for type date', + 'type': 'date', + 'value': 0, + 'config': [], + 'result': '' + }, + { + 'description': 'works for type date with timestamp', + 'type': 'date', + 'value': 10000000, + 'config': [], + 'result': '26-4-1970' + }, + { + 'description': 'works for type date with iso date', + 'type': 'date', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '02-12-2016' + }, + { + 'description': 'works for type datetime', + 'type': 'datetime', + 'value': 0, + 'config': [], + 'result': '' + }, + { + 'description': 'works for type datetime with timestamp', + 'type': 'datetime', + 'value': 10000000, + 'config': [], + 'result': '17:46 26-4-1970' + }, + { + 'description': 'works for type datetime with iso date', + 'type': 'datetime', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '11:16 02-12-2016' + }, + { + 'description': 'resolves to empty result for zero value', + 'type': 'datetime', + 'value': 0, + 'config': [], + 'result': '' + }, + { + 'description': 'resolves to empty result for invalid value', + 'type': 'datetime', + 'value': 'invalid', + 'config': [], + 'result': '' + }, + { + 'description': 'works for type time', + 'type': 'time', + 'value': 0, + 'config': [], + 'result': '00:00' + }, + { + 'description': 'works for type time with timestamp', + 'type': 'time', + 'value': 10000000, + 'config': [], + 'result': '17:46' + }, + { + 'description': 'works for type time with iso date', + 'type': 'time', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '11:16' + } + ]; - /** - * @dataProvider formatValueDataProvider - * @test - */ - describe('tests for formatValue', function() { - using(formatValueDataProvider, function(testCase) { - it(testCase.description, function() { - FormEngineValidation.USmode = 0; - var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config); - expect(result).toBe(testCase.result); - }); - }); - }); + /** + * @dataProvider formatValueDataProvider + * @test + */ + describe('tests for formatValue', function() { + using(formatValueDataProvider, function(testCase) { + it(testCase.description, function() { + FormEngineValidation.USmode = 0; + var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config); + expect(result).toBe(testCase.result); + }); + }); + }); - /** - * @type {*[]} - */ - var formatValueUsModeDataProvider = [ - { - 'description': 'works for type date with timestamp in US mode', - 'type': 'date', - 'value': 10000000, - 'config': [], - 'result': '4-26-1970' - }, - { - 'description': 'works for type date with iso date in US mode', - 'type': 'date', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '12-02-2016' - }, - { - 'description': 'works for type datetime with timestamp in US mode', - 'type': 'datetime', - 'value': 10000000, - 'config': [], - 'result': '17:46 4-26-1970' - }, - { - 'description': 'works for type datetime with iso date in US mode', - 'type': 'datetime', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '11:16 12-02-2016' - }, - { - 'description': 'works for type time with timestamp in US mode', - 'type': 'time', - 'value': 10000000, - 'config': [], - 'result': '17:46' - }, - { - 'description': 'works for type time with iso date in US mode', - 'type': 'time', - 'value': '2016-12-02T11:16:06+00:00', - 'config': [], - 'result': '11:16' - } - ]; + /** + * @type {*[]} + */ + var formatValueUsModeDataProvider = [ + { + 'description': 'works for type date with timestamp in US mode', + 'type': 'date', + 'value': 10000000, + 'config': [], + 'result': '4-26-1970' + }, + { + 'description': 'works for type date with iso date in US mode', + 'type': 'date', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '12-02-2016' + }, + { + 'description': 'works for type datetime with timestamp in US mode', + 'type': 'datetime', + 'value': 10000000, + 'config': [], + 'result': '17:46 4-26-1970' + }, + { + 'description': 'works for type datetime with iso date in US mode', + 'type': 'datetime', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '11:16 12-02-2016' + }, + { + 'description': 'works for type time with timestamp in US mode', + 'type': 'time', + 'value': 10000000, + 'config': [], + 'result': '17:46' + }, + { + 'description': 'works for type time with iso date in US mode', + 'type': 'time', + 'value': '2016-12-02T11:16:06+00:00', + 'config': [], + 'result': '11:16' + } + ]; - /** - * @dataProvider formatValueUsModeDataProvider - * @test - */ - describe('tests for formatValue in US Mode', function() { - using(formatValueUsModeDataProvider, function(testCase) { - it(testCase.description, function() { - FormEngineValidation.USmode = 1; - var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config); - expect(result).toBe(testCase.result); - }); - }); - }); + /** + * @dataProvider formatValueUsModeDataProvider + * @test + */ + describe('tests for formatValue in US Mode', function() { + using(formatValueUsModeDataProvider, function(testCase) { + it(testCase.description, function() { + FormEngineValidation.USmode = 1; + var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config); + expect(result).toBe(testCase.result); + }); + }); + }); - /** - * @type {*[]} - */ - var processValueDataProvider = [ - { - 'description': 'works for command alpha with numeric value', - 'command': 'alpha', - 'value': '1234', - 'config': [], - 'result': '' - }, - { - 'description': 'works for command alpha with string value', - 'command': 'alpha', - 'value': 'abc', - 'config': [], - 'result': 'abc' - }, - { - 'description': 'works for command alpha with alphanum input', - 'command': 'alpha', - 'value': 'abc123', - 'config': [], - 'result': 'abc' - }, - { - 'description': 'works for command alpha with alphanum input', - 'command': 'alpha', - 'value': '123abc123', - 'config': [], - 'result': 'abc' - } - ]; + /** + * @type {*[]} + */ + var processValueDataProvider = [ + { + 'description': 'works for command alpha with numeric value', + 'command': 'alpha', + 'value': '1234', + 'config': [], + 'result': '' + }, + { + 'description': 'works for command alpha with string value', + 'command': 'alpha', + 'value': 'abc', + 'config': [], + 'result': 'abc' + }, + { + 'description': 'works for command alpha with alphanum input', + 'command': 'alpha', + 'value': 'abc123', + 'config': [], + 'result': 'abc' + }, + { + 'description': 'works for command alpha with alphanum input', + 'command': 'alpha', + 'value': '123abc123', + 'config': [], + 'result': 'abc' + } + ]; - /** - * @dataProvider processValueDataProvider - * @test - */ - describe('test for processValue', function() { - using(processValueDataProvider, function(testCase) { - it(testCase.description, function() { - var result = FormEngineValidation.processValue(testCase.command, testCase.value, testCase.config); - expect(result).toBe(testCase.result); - }); - }); - }); + /** + * @dataProvider processValueDataProvider + * @test + */ + describe('test for processValue', function() { + using(processValueDataProvider, function(testCase) { + it(testCase.description, function() { + var result = FormEngineValidation.processValue(testCase.command, testCase.value, testCase.config); + expect(result).toBe(testCase.result); + }); + }); + }); - /** - * @test - */ - xdescribe('tests for validateField', function() {}); + /** + * @test + */ + xdescribe('tests for validateField', function() { + }); - /** - * @test - */ - describe('tests for trimExplode', function () { - it('works for comma as separator and list without spaces', function () { - expect(FormEngineValidation.trimExplode(',', 'foo,bar,baz')).toEqual(['foo', 'bar', 'baz']); - }); - it('works for comma as separator and list with spaces', function () { - expect(FormEngineValidation.trimExplode(',', ' foo , bar , baz ')).toEqual(['foo', 'bar', 'baz']); - }); - it('works for pipe as separator and list with spaces', function () { - expect(FormEngineValidation.trimExplode('|', ' foo | bar | baz ')).toEqual(['foo', 'bar', 'baz']); - }); - }); + /** + * @test + */ + describe('tests for trimExplode', function() { + it('works for comma as separator and list without spaces', function() { + expect(FormEngineValidation.trimExplode(',', 'foo,bar,baz')).toEqual(['foo', 'bar', 'baz']); + }); + it('works for comma as separator and list with spaces', function() { + expect(FormEngineValidation.trimExplode(',', ' foo , bar , baz ')).toEqual(['foo', 'bar', 'baz']); + }); + it('works for pipe as separator and list with spaces', function() { + expect(FormEngineValidation.trimExplode('|', ' foo | bar | baz ')).toEqual(['foo', 'bar', 'baz']); + }); + }); - /** - * @test - */ - describe('tests for parseInt', function() { - it('works for value 0', function () { - expect(FormEngineValidation.parseInt(0)).toBe(0); - }); - it('works for value 1', function () { - expect(FormEngineValidation.parseInt(1)).toBe(1); - }); - it('works for value -1', function () { - expect(FormEngineValidation.parseInt(-1)).toBe(-1); - }); - it('works for value "0"', function () { - expect(FormEngineValidation.parseInt('0')).toBe(0); - }); - it('works for value "1"', function () { - expect(FormEngineValidation.parseInt('1')).toBe(1); - }); - it('works for value "-1"', function () { - expect(FormEngineValidation.parseInt('-1')).toBe(-1); - }); - it('works for value 0.5', function () { - expect(FormEngineValidation.parseInt(0.5)).toBe(0); - }); - it('works for value "0.5"', function () { - expect(FormEngineValidation.parseInt('0.5')).toBe(0); - }); - it('works for value "foo"', function () { - expect(FormEngineValidation.parseInt('foo')).toBe(0); - }); - it('works for value true', function () { - expect(FormEngineValidation.parseInt(true)).toBe(0); - }); - it('works for value false', function () { - expect(FormEngineValidation.parseInt(false)).toBe(0); - }); - it('works for value null', function () { - expect(FormEngineValidation.parseInt(null)).toBe(0); - }); - }); - /** - * @test - */ - describe('tests for parseDouble', function() { - it('works for value 0', function () { - expect(FormEngineValidation.parseDouble(0)).toBe('0.00'); - }); - it('works for value 1', function () { - expect(FormEngineValidation.parseDouble(1)).toBe('1.00'); - }); - it('works for value -1', function () { - expect(FormEngineValidation.parseDouble(-1)).toBe('-1.00'); - }); - it('works for value "0"', function () { - expect(FormEngineValidation.parseDouble('0')).toBe('0.00'); - }); - it('works for value "1"', function () { - expect(FormEngineValidation.parseDouble('1')).toBe('1.00'); - }); - it('works for value "-1"', function () { - expect(FormEngineValidation.parseDouble('-1')).toBe('-1.00'); - }); - it('works for value 0.5', function () { - expect(FormEngineValidation.parseDouble(0.5)).toBe('0.50'); - }); - it('works for value "0.5"', function () { - expect(FormEngineValidation.parseDouble('0.5')).toBe('0.50'); - }); - it('works for value "foo"', function () { - expect(FormEngineValidation.parseDouble('foo')).toBe('0.00'); - }); - it('works for value true', function () { - expect(FormEngineValidation.parseDouble(true)).toBe('0.00'); - }); - it('works for value false', function () { - expect(FormEngineValidation.parseDouble(false)).toBe('0.00'); - }); - it('works for value null', function () { - expect(FormEngineValidation.parseDouble(null)).toBe('0.00'); - }); - }); + /** + * @test + */ + describe('tests for parseInt', function() { + it('works for value 0', function() { + expect(FormEngineValidation.parseInt(0)).toBe(0); + }); + it('works for value 1', function() { + expect(FormEngineValidation.parseInt(1)).toBe(1); + }); + it('works for value -1', function() { + expect(FormEngineValidation.parseInt(-1)).toBe(-1); + }); + it('works for value "0"', function() { + expect(FormEngineValidation.parseInt('0')).toBe(0); + }); + it('works for value "1"', function() { + expect(FormEngineValidation.parseInt('1')).toBe(1); + }); + it('works for value "-1"', function() { + expect(FormEngineValidation.parseInt('-1')).toBe(-1); + }); + it('works for value 0.5', function() { + expect(FormEngineValidation.parseInt(0.5)).toBe(0); + }); + it('works for value "0.5"', function() { + expect(FormEngineValidation.parseInt('0.5')).toBe(0); + }); + it('works for value "foo"', function() { + expect(FormEngineValidation.parseInt('foo')).toBe(0); + }); + it('works for value true', function() { + expect(FormEngineValidation.parseInt(true)).toBe(0); + }); + it('works for value false', function() { + expect(FormEngineValidation.parseInt(false)).toBe(0); + }); + it('works for value null', function() { + expect(FormEngineValidation.parseInt(null)).toBe(0); + }); + }); + /** + * @test + */ + describe('tests for parseDouble', function() { + it('works for value 0', function() { + expect(FormEngineValidation.parseDouble(0)).toBe('0.00'); + }); + it('works for value 1', function() { + expect(FormEngineValidation.parseDouble(1)).toBe('1.00'); + }); + it('works for value -1', function() { + expect(FormEngineValidation.parseDouble(-1)).toBe('-1.00'); + }); + it('works for value "0"', function() { + expect(FormEngineValidation.parseDouble('0')).toBe('0.00'); + }); + it('works for value "1"', function() { + expect(FormEngineValidation.parseDouble('1')).toBe('1.00'); + }); + it('works for value "-1"', function() { + expect(FormEngineValidation.parseDouble('-1')).toBe('-1.00'); + }); + it('works for value 0.5', function() { + expect(FormEngineValidation.parseDouble(0.5)).toBe('0.50'); + }); + it('works for value "0.5"', function() { + expect(FormEngineValidation.parseDouble('0.5')).toBe('0.50'); + }); + it('works for value "foo"', function() { + expect(FormEngineValidation.parseDouble('foo')).toBe('0.00'); + }); + it('works for value true', function() { + expect(FormEngineValidation.parseDouble(true)).toBe('0.00'); + }); + it('works for value false', function() { + expect(FormEngineValidation.parseDouble(false)).toBe('0.00'); + }); + it('works for value null', function() { + expect(FormEngineValidation.parseDouble(null)).toBe('0.00'); + }); + }); - /** - * @test - */ - describe('tests for btrim', function() { - var result = FormEngineValidation.btrim(' test '); + /** + * @test + */ + describe('tests for btrim', function() { + var result = FormEngineValidation.btrim(' test '); - it('works for string with whitespace in begin and end', function() { - expect(result).toBe(' test'); - }); - }); + it('works for string with whitespace in begin and end', function() { + expect(result).toBe(' test'); + }); + }); - /** - * @test - */ - describe('tests for ltrim', function() { - var result = FormEngineValidation.ltrim(' test '); + /** + * @test + */ + describe('tests for ltrim', function() { + var result = FormEngineValidation.ltrim(' test '); - it('works for string with whitespace in begin and end', function() { - expect(result).toBe('test '); - }); - }); + it('works for string with whitespace in begin and end', function() { + expect(result).toBe('test '); + }); + }); - /** - * @test - */ - xdescribe('tests for parseDateTime', function() {}); + /** + * @test + */ + xdescribe('tests for parseDateTime', function() { + }); - /** - * @test - */ - xdescribe('tests for parseDate', function() {}); + /** + * @test + */ + xdescribe('tests for parseDate', function() { + }); - /** - * @test - */ - xdescribe('tests for parseTime', function() {}); + /** + * @test + */ + xdescribe('tests for parseTime', function() { + }); - /** - * @test - */ - xdescribe('tests for parseYear', function() {}); + /** + * @test + */ + xdescribe('tests for parseYear', function() { + }); - /** - * @test - */ - describe('tests for getYear', function () { - var currentDate = new Date(); - afterEach(function() { - jasmine.clock().mockDate(currentDate); - }); + /** + * @test + */ + describe('tests for getYear', function() { + var currentDate = new Date(); + afterEach(function() { + jasmine.clock().mockDate(currentDate); + }); - it('works for current date', function () { - var date = new Date(); - expect(FormEngineValidation.getYear(date)).toBe(date.getYear() + 1900); - }); - it('works for year 2013', function () { - var baseTime = new Date(2013, 9, 23); - jasmine.clock().mockDate(baseTime); - expect(FormEngineValidation.getYear(baseTime)).toBe(2013); - }) - }); + it('works for current date', function() { + var date = new Date(); + expect(FormEngineValidation.getYear(date)).toBe(date.getYear() + 1900); + }); + it('works for year 2013', function() { + var baseTime = new Date(2013, 9, 23); + jasmine.clock().mockDate(baseTime); + expect(FormEngineValidation.getYear(baseTime)).toBe(2013); + }) + }); - /** - * @test - */ - describe('tests for getDate', function () { - var currentDate = new Date(); - afterEach(function() { - jasmine.clock().mockDate(currentDate); - }); + /** + * @test + */ + describe('tests for getDate', function() { + var currentDate = new Date(); + afterEach(function() { + jasmine.clock().mockDate(currentDate); + }); - xit('works for year 2013', function () { - var baseTime = new Date(2013, 9, 23, 13, 13, 13); - jasmine.clock().mockDate(baseTime); - expect(FormEngineValidation.getDate(baseTime)).toBe(1382479200); - }) - }); + xit('works for year 2013', function() { + var baseTime = new Date(2013, 9, 23, 13, 13, 13); + jasmine.clock().mockDate(baseTime); + expect(FormEngineValidation.getDate(baseTime)).toBe(1382479200); + }) + }); - /** - * @test - */ - describe('tests for splitStr', function () { - it('works for command and index', function () { - expect(FormEngineValidation.splitStr('foo,bar,baz', ',', -1)).toBe('foo'); - expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 0)).toBe('foo'); - expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 1)).toBe('foo'); - expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 2)).toBe('bar'); - expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 3)).toBe('baz'); - expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 1)).toBe(' foo '); - expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 2)).toBe(' bar '); - expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 3)).toBe(' baz '); - }); - }); + /** + * @test + */ + describe('tests for splitStr', function() { + it('works for command and index', function() { + expect(FormEngineValidation.splitStr('foo,bar,baz', ',', -1)).toBe('foo'); + expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 0)).toBe('foo'); + expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 1)).toBe('foo'); + expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 2)).toBe('bar'); + expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 3)).toBe('baz'); + expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 1)).toBe(' foo '); + expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 2)).toBe(' bar '); + expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 3)).toBe(' baz '); + }); + }); - /** - * @test - */ - xdescribe('tests for split', function() {}); - }); + /** + * @test + */ + xdescribe('tests for split', function() { + }); + }); }); diff --git a/typo3/sysext/backend/Tests/JavaScript/IconsTest.js b/typo3/sysext/backend/Tests/JavaScript/IconsTest.js index 72a8dc65ac7fe27393b4e81dd11847f6846a9d52..cc0efde0bf60f43e18134a77a4c7120f6af1b298 100644 --- a/typo3/sysext/backend/Tests/JavaScript/IconsTest.js +++ b/typo3/sysext/backend/Tests/JavaScript/IconsTest.js @@ -1,74 +1,74 @@ define(['jquery', 'TYPO3/CMS/Backend/Icons'], function($, Icons) { - 'use strict'; + 'use strict'; - describe('TYPO3/CMS/Backend/IconsTest:', function() { - /** - * @test - */ - describe('tests for Icons object', function() { - it('has all sizes', function() { - expect(Icons.sizes.small).toBe('small'); - expect(Icons.sizes.default).toBe('default'); - expect(Icons.sizes.large).toBe('large'); - expect(Icons.sizes.overlay).toBe('overlay'); - }); - it('has all states', function() { - expect(Icons.states.default).toBe('default'); - expect(Icons.states.disabled).toBe('disabled'); - }); - it('has all markupIdentifiers', function() { - expect(Icons.markupIdentifiers.default).toBe('default'); - expect(Icons.markupIdentifiers.inline).toBe('inline'); - }); - }); + describe('TYPO3/CMS/Backend/IconsTest:', function() { + /** + * @test + */ + describe('tests for Icons object', function() { + it('has all sizes', function() { + expect(Icons.sizes.small).toBe('small'); + expect(Icons.sizes.default).toBe('default'); + expect(Icons.sizes.large).toBe('large'); + expect(Icons.sizes.overlay).toBe('overlay'); + }); + it('has all states', function() { + expect(Icons.states.default).toBe('default'); + expect(Icons.states.disabled).toBe('disabled'); + }); + it('has all markupIdentifiers', function() { + expect(Icons.markupIdentifiers.default).toBe('default'); + expect(Icons.markupIdentifiers.inline).toBe('inline'); + }); + }); - /** - * @test - */ - describe('tests for Icons::getIcon', function() { - beforeEach(function() { - spyOn(Icons, 'getIcon'); - Icons.getIcon('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default); - }); + /** + * @test + */ + describe('tests for Icons::getIcon', function() { + beforeEach(function() { + spyOn(Icons, 'getIcon'); + Icons.getIcon('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default); + }); - it("tracks that the spy was called", function() { - expect(Icons.getIcon).toHaveBeenCalled(); - }); - it("tracks all the arguments of its calls", function() { - expect(Icons.getIcon).toHaveBeenCalledWith('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default); - }); - xit('works get icon from remote server'); - }); + it("tracks that the spy was called", function() { + expect(Icons.getIcon).toHaveBeenCalled(); + }); + it("tracks all the arguments of its calls", function() { + expect(Icons.getIcon).toHaveBeenCalledWith('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default); + }); + xit('works get icon from remote server'); + }); - /** - * @test - */ - describe('tests for Icons::putInCache', function() { - it('works for simply identifier and markup', function() { - Icons.putInCache('foo', 'bar'); - expect(Icons.cache['foo']).toBe('bar'); - }); - }); + /** + * @test + */ + describe('tests for Icons::putInCache', function() { + it('works for simply identifier and markup', function() { + Icons.putInCache('foo', 'bar'); + expect(Icons.cache['foo']).toBe('bar'); + }); + }); - /** - * @test - */ - describe('tests for Icons::getFromCache', function() { - it('return undefined for uncached icon', function() { - expect(Icons.getFromCache('bar')).not.toBeDefined(); - }); - }); + /** + * @test + */ + describe('tests for Icons::getFromCache', function() { + it('return undefined for uncached icon', function() { + expect(Icons.getFromCache('bar')).not.toBeDefined(); + }); + }); - /** - * @test - */ - describe('tests for Icons::isCached', function() { - it('return true for cached icon', function() { - expect(Icons.isCached('foo')).toBe(true); - }); - it('return false for uncached icon', function() { - expect(Icons.isCached('bar')).toBe(false); - }); - }); - }); + /** + * @test + */ + describe('tests for Icons::isCached', function() { + it('return true for cached icon', function() { + expect(Icons.isCached('foo')).toBe(true); + }); + it('return false for uncached icon', function() { + expect(Icons.isCached('bar')).toBe(false); + }); + }); + }); }); diff --git a/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js b/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js index e213158757af8c0a34a8cbaae03414fa3378516a..ceca7f6d44cf27d9155f2cf94372da1c5e35d235 100644 --- a/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js +++ b/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js @@ -1,75 +1,75 @@ define(['jquery', 'bootstrap', 'TYPO3/CMS/Backend/Popover'], function($, bootstrap, Popover) { - 'use strict'; + 'use strict'; - describe('TYPO3/CMS/Backend/PopoverTest:', function() { - /** - * @test - */ - describe('initialize', function() { - var $body = $('body'); - var $element = $('<div data-toggle="popover">'); - $body.append($element); - it('works with default selector', function() { - Popover.initialize(); - expect($element[0].outerHTML).toBe('<div data-toggle="popover" data-original-title="" title=""></div>'); - }); + describe('TYPO3/CMS/Backend/PopoverTest:', function() { + /** + * @test + */ + describe('initialize', function() { + var $body = $('body'); + var $element = $('<div data-toggle="popover">'); + $body.append($element); + it('works with default selector', function() { + Popover.initialize(); + expect($element[0].outerHTML).toBe('<div data-toggle="popover" data-original-title="" title=""></div>'); + }); - var $element2 = $('<div data-toggle="popover" data-title="foo">'); - $body.append($element2); - it('works with default selector and title attribute', function() { - Popover.initialize(); - expect($element2[0].outerHTML).toBe('<div data-toggle="popover" data-title="foo" data-original-title="" title=""></div>'); - }); + var $element2 = $('<div data-toggle="popover" data-title="foo">'); + $body.append($element2); + it('works with default selector and title attribute', function() { + Popover.initialize(); + expect($element2[0].outerHTML).toBe('<div data-toggle="popover" data-title="foo" data-original-title="" title=""></div>'); + }); - var $element3 = $('<div data-toggle="popover" data-content="foo">'); - $body.append($element3); - it('works with default selector and content attribute', function() { - Popover.initialize(); - expect($element3[0].outerHTML).toBe('<div data-toggle="popover" data-content="foo" data-original-title="" title=""></div>'); - }); + var $element3 = $('<div data-toggle="popover" data-content="foo">'); + $body.append($element3); + it('works with default selector and content attribute', function() { + Popover.initialize(); + expect($element3[0].outerHTML).toBe('<div data-toggle="popover" data-content="foo" data-original-title="" title=""></div>'); + }); - var $element4 = $('<div class="t3js-popover">'); - $body.append($element4); - it('works with custom selector', function() { - Popover.initialize('.t3js-popover'); - expect($element4[0].outerHTML).toBe('<div class="t3js-popover" data-original-title="" title=""></div>'); - }); - }); + var $element4 = $('<div class="t3js-popover">'); + $body.append($element4); + it('works with custom selector', function() { + Popover.initialize('.t3js-popover'); + expect($element4[0].outerHTML).toBe('<div class="t3js-popover" data-original-title="" title=""></div>'); + }); + }); - describe('call setOptions', function() { - var $body = $('body'); - var $element = $('<div class="t3js-test-set-options" data-title="foo-title" data-content="foo-content">'); - $body.append($element); - it('can set title', function() { - Popover.initialize('.t3js-test-set-options'); - expect($element.attr('data-title')).toBe('foo-title'); - expect($element.attr('data-content')).toBe('foo-content'); - expect($element.attr('data-original-title')).toBe(''); - expect($element.attr('title')).toBe(''); - Popover.setOptions($element, { - 'title': 'bar-title' - }); - expect($element.attr('data-title')).toBe('foo-title'); - expect($element.attr('data-content')).toBe('foo-content'); - expect($element.attr('data-original-title')).toBe('bar-title'); - expect($element.attr('title')).toBe(''); - }); - var $element2 = $('<div class="t3js-test-set-options2" data-title="foo-title" data-content="foo-content">'); - $body.append($element2); - it('can set content', function() { - Popover.initialize('.t3js-test-set-options2'); - expect($element2.attr('data-title')).toBe('foo-title'); - expect($element2.attr('data-content')).toBe('foo-content'); - expect($element2.attr('data-original-title')).toBe(''); - expect($element2.attr('title')).toBe(''); - Popover.setOptions($element2, { - 'content': 'bar-content' - }); - expect($element2.attr('data-title')).toBe('foo-title'); - expect($element2.attr('data-content')).toBe('bar-content'); - expect($element2.attr('data-original-title')).toBe('foo-title'); - expect($element2.attr('title')).toBe(''); - }); - }); - }); + describe('call setOptions', function() { + var $body = $('body'); + var $element = $('<div class="t3js-test-set-options" data-title="foo-title" data-content="foo-content">'); + $body.append($element); + it('can set title', function() { + Popover.initialize('.t3js-test-set-options'); + expect($element.attr('data-title')).toBe('foo-title'); + expect($element.attr('data-content')).toBe('foo-content'); + expect($element.attr('data-original-title')).toBe(''); + expect($element.attr('title')).toBe(''); + Popover.setOptions($element, { + 'title': 'bar-title' + }); + expect($element.attr('data-title')).toBe('foo-title'); + expect($element.attr('data-content')).toBe('foo-content'); + expect($element.attr('data-original-title')).toBe('bar-title'); + expect($element.attr('title')).toBe(''); + }); + var $element2 = $('<div class="t3js-test-set-options2" data-title="foo-title" data-content="foo-content">'); + $body.append($element2); + it('can set content', function() { + Popover.initialize('.t3js-test-set-options2'); + expect($element2.attr('data-title')).toBe('foo-title'); + expect($element2.attr('data-content')).toBe('foo-content'); + expect($element2.attr('data-original-title')).toBe(''); + expect($element2.attr('title')).toBe(''); + Popover.setOptions($element2, { + 'content': 'bar-content' + }); + expect($element2.attr('data-title')).toBe('foo-title'); + expect($element2.attr('data-content')).toBe('bar-content'); + expect($element2.attr('data-original-title')).toBe('foo-title'); + expect($element2.attr('title')).toBe(''); + }); + }); + }); }); diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js b/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js index 6e3c1fc08d910d9ffc4b0a53dd0a787bb42bb871..e0e59a66de3b1c8fe9f83b65f3269a6865b54ed7 100644 --- a/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js +++ b/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js @@ -18,16 +18,16 @@ */ define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) { - var $searchFields = $('#tx_Beuser_username'); - var searchResultShown = ('' !== $searchFields.first().val()); + var $searchFields = $('#tx_Beuser_username'); + var searchResultShown = ('' !== $searchFields.first().val()); - // make search field clearable - $searchFields.clearable({ - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - }); + // make search field clearable + $searchFields.clearable({ + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } + } + }); }); diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js index 9ebe346606a03c08fecf8865b67436ffbb359968..f3eeb16c20bca9f8671ab97d61af1021e7a1f7ab 100644 --- a/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js +++ b/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js @@ -17,30 +17,30 @@ * JavaScript to handle permissions module from context menu * @exports TYPO3/CMS/Beuser/ContextMenuActions */ -define(function () { - 'use strict'; +define(function() { + 'use strict'; - /** - * @exports TYPO3/CMS/Beuser/ContextMenuActions - */ - var ContextMenuActions = {}; + /** + * @exports TYPO3/CMS/Beuser/ContextMenuActions + */ + var ContextMenuActions = {}; - /** - * Open permission module for given uid - * - * @param {string} table - * @param {int} uid of the page - */ - ContextMenuActions.openPermissionsModule = function (table, uid) { - if (table === 'pages') { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.AccessPermissions.moduleUrl + - '&id=' + uid + - '&tx_beuser_system_beusertxpermission[action]=edit' + - '&tx_beuser_system_beusertxpermission[controller]=Permission' - ); - } - }; + /** + * Open permission module for given uid + * + * @param {string} table + * @param {int} uid of the page + */ + ContextMenuActions.openPermissionsModule = function(table, uid) { + if (table === 'pages') { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.AccessPermissions.moduleUrl + + '&id=' + uid + + '&tx_beuser_system_beusertxpermission[action]=edit' + + '&tx_beuser_system_beusertxpermission[controller]=Permission' + ); + } + }; - return ContextMenuActions; + return ContextMenuActions; }); diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js b/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js index cb49991920189170ecd1f016964c9c5ea84130bb..78bdddb044181830e450658cb501622f9db75038 100644 --- a/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js +++ b/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js @@ -17,324 +17,324 @@ */ define(['jquery'], function($) { - /** - * - * @type {{options: {containerSelector: string}}} - * @exports TYPO3/CMS/Beuser/Permissons - */ - var Permissions = { - options: { - containerSelector: '#typo3-permissionList' - } - }; - var ajaxUrl = TYPO3.settings.ajaxUrls['user_access_permissions']; + /** + * + * @type {{options: {containerSelector: string}}} + * @exports TYPO3/CMS/Beuser/Permissons + */ + var Permissions = { + options: { + containerSelector: '#typo3-permissionList' + } + }; + var ajaxUrl = TYPO3.settings.ajaxUrls['user_access_permissions']; - /** - * Changes the value of the permissions in the form - * - * @param {String} checknames - * @param {String} varname - */ - Permissions.setCheck = function(checknames, varname) { - if (document.editform[varname]) { - var res = document.editform[varname].value; - for (var a = 1; a <= 5; a++) { - document.editform[checknames + '[' + a + ']'].checked = (res & Math.pow(2, a-1)); - } - } - }; + /** + * Changes the value of the permissions in the form + * + * @param {String} checknames + * @param {String} varname + */ + Permissions.setCheck = function(checknames, varname) { + if (document.editform[varname]) { + var res = document.editform[varname].value; + for (var a = 1; a <= 5; a++) { + document.editform[checknames + '[' + a + ']'].checked = (res & Math.pow(2, a - 1)); + } + } + }; - /** - * checks for a change of the permissions in the form - * - * @param {String} checknames - * @param {String} varname - */ - Permissions.checkChange = function(checknames, varname) { - var res = 0; - for (var a = 1; a <= 5; a++) { - if (document.editform[checknames + '[' + a + ']'].checked) { - res |= Math.pow(2,a-1); - } - } - document.editform[varname].value = res | (checknames === 'tx_beuser_system_beusertxpermission[check][perms_user]' ? 1 : 0); - Permissions.setCheck(checknames, varname); - }; + /** + * checks for a change of the permissions in the form + * + * @param {String} checknames + * @param {String} varname + */ + Permissions.checkChange = function(checknames, varname) { + var res = 0; + for (var a = 1; a <= 5; a++) { + if (document.editform[checknames + '[' + a + ']'].checked) { + res |= Math.pow(2, a - 1); + } + } + document.editform[varname].value = res | (checknames === 'tx_beuser_system_beusertxpermission[check][perms_user]' ? 1 : 0); + Permissions.setCheck(checknames, varname); + }; - /** - * wrapper function to call a URL in the current frame - */ - Permissions.jumpToUrl = function(url) { - window.location.href = url; - }; + /** + * wrapper function to call a URL in the current frame + */ + Permissions.jumpToUrl = function(url) { + window.location.href = url; + }; - /** - * changes permissions by sending an AJAX request to the server - * - * @param {Object} $element - */ - Permissions.setPermissions = function($element) { - var page = $element.data('page'); - var who = $element.data('who'); - var elementSelector = '#' + page + '_' + who; + /** + * changes permissions by sending an AJAX request to the server + * + * @param {Object} $element + */ + Permissions.setPermissions = function($element) { + var page = $element.data('page'); + var who = $element.data('who'); + var elementSelector = '#' + page + '_' + who; - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'page': page, - 'who': who, - 'permissions': $element.data('permissions'), - 'mode': $element.data('mode'), - 'bits': $element.data('bits') - } - }).done(function(data) { - // Replace content - $(elementSelector).replaceWith(data); - // Reinitialize tooltip - $(elementSelector).find('span').tooltip(); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'page': page, + 'who': who, + 'permissions': $element.data('permissions'), + 'mode': $element.data('mode'), + 'bits': $element.data('bits') + } + }).done(function(data) { + // Replace content + $(elementSelector).replaceWith(data); + // Reinitialize tooltip + $(elementSelector).find('span').tooltip(); + }); + }; - /** - * changes the flag to lock the editing on a page by sending an AJAX request - * - * @param {Object} $element - */ - Permissions.toggleEditLock = function($element) { - var page = $element.data('page'); + /** + * changes the flag to lock the editing on a page by sending an AJAX request + * + * @param {Object} $element + */ + Permissions.toggleEditLock = function($element) { + var page = $element.data('page'); - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'action': 'toggle_edit_lock', - 'page': page, - 'editLockState': $element.data('lockstate') - } - }).done(function(data) { - // Replace content - $('#el_' + page).replaceWith(data); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'action': 'toggle_edit_lock', + 'page': page, + 'editLockState': $element.data('lockstate') + } + }).done(function(data) { + // Replace content + $('#el_' + page).replaceWith(data); + }); + }; - /** - * Owner-related: Set the new owner of a page by executing an ajax call - * - * @param {Object} $element - */ - Permissions.changeOwner = function($element) { - var page = $element.data('page'); + /** + * Owner-related: Set the new owner of a page by executing an ajax call + * + * @param {Object} $element + */ + Permissions.changeOwner = function($element) { + var page = $element.data('page'); - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'action': 'change_owner', - 'page': page, - 'ownerUid': $element.data('owner'), - 'newOwnerUid': $('#new_page_owner').val() - } - }).done(function(data) { - // Replace content - $('#o_' + page).replaceWith(data); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'action': 'change_owner', + 'page': page, + 'ownerUid': $element.data('owner'), + 'newOwnerUid': $('#new_page_owner').val() + } + }).done(function(data) { + // Replace content + $('#o_' + page).replaceWith(data); + }); + }; - /** - * Owner-related: load the selector for selecting - * the owner of a page by executing an ajax call - * - * @param {Object} $element - */ - Permissions.showChangeOwnerSelector = function($element) { - var page = $element.data('page'); + /** + * Owner-related: load the selector for selecting + * the owner of a page by executing an ajax call + * + * @param {Object} $element + */ + Permissions.showChangeOwnerSelector = function($element) { + var page = $element.data('page'); - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'action': 'show_change_owner_selector', - 'page': page, - 'ownerUid': $element.data('owner'), - 'username': $element.data('username') - } - }).done(function(data) { - // Replace content - $('#o_' + page).replaceWith(data); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'action': 'show_change_owner_selector', + 'page': page, + 'ownerUid': $element.data('owner'), + 'username': $element.data('username') + } + }).done(function(data) { + // Replace content + $('#o_' + page).replaceWith(data); + }); + }; - /** - * Owner-related: Update the HTML view and show the original owner - * - * @param {Object} $element - */ - Permissions.restoreOwner = function($element) { - var page = $element.data('page'); - var username = $element.data('username'); - var usernameHtml = username; - if (typeof username === 'undefined') { - username = $('<span>', { - 'class': 'not_set', - 'text': '[not set]' - }); - usernameHtml = username.html(); - username = username.text(); - } + /** + * Owner-related: Update the HTML view and show the original owner + * + * @param {Object} $element + */ + Permissions.restoreOwner = function($element) { + var page = $element.data('page'); + var username = $element.data('username'); + var usernameHtml = username; + if (typeof username === 'undefined') { + username = $('<span>', { + 'class': 'not_set', + 'text': '[not set]' + }); + usernameHtml = username.html(); + username = username.text(); + } - var html = $('<span/>', { - 'id': 'o_' + page - }); - var aSelector = $('<a/>', { - 'class': 'ug_selector changeowner', - 'data-page': page, - 'data-owner': $element.data('owner'), - 'data-username': usernameHtml, - 'text': username - }); - html.append(aSelector); + var html = $('<span/>', { + 'id': 'o_' + page + }); + var aSelector = $('<a/>', { + 'class': 'ug_selector changeowner', + 'data-page': page, + 'data-owner': $element.data('owner'), + 'data-username': usernameHtml, + 'text': username + }); + html.append(aSelector); - // Replace content - $('#o_' + page).replaceWith(html); - }; + // Replace content + $('#o_' + page).replaceWith(html); + }; - /** - * Group-related: Set the new group by executing an ajax call - * - * @param {Object} $element - */ - Permissions.changeGroup = function($element) { - var page = $element.data('page'); + /** + * Group-related: Set the new group by executing an ajax call + * + * @param {Object} $element + */ + Permissions.changeGroup = function($element) { + var page = $element.data('page'); - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'action': 'change_group', - 'page': page, - 'groupUid': $element.data('groupId'), - 'newGroupUid': $('#new_page_group').val() - } - }).done(function(data) { - // Replace content - $('#g_' + page).replaceWith(data); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'action': 'change_group', + 'page': page, + 'groupUid': $element.data('groupId'), + 'newGroupUid': $('#new_page_group').val() + } + }).done(function(data) { + // Replace content + $('#g_' + page).replaceWith(data); + }); + }; - /** - * Group-related: Load the selector by executing an ajax call - * - * @param {Object} $element - */ - Permissions.showChangeGroupSelector = function($element) { - var page = $element.data('page'); + /** + * Group-related: Load the selector by executing an ajax call + * + * @param {Object} $element + */ + Permissions.showChangeGroupSelector = function($element) { + var page = $element.data('page'); - $.ajax({ - url: ajaxUrl, - type: 'post', - dataType: 'html', - cache: false, - data: { - 'action': 'show_change_group_selector', - 'page': page, - 'groupUid': $element.data('groupId'), - 'groupname': $element.data('groupname') - } - }).done(function(data) { - // Replace content - $('#g_' + page).replaceWith(data); - }); - }; + $.ajax({ + url: ajaxUrl, + type: 'post', + dataType: 'html', + cache: false, + data: { + 'action': 'show_change_group_selector', + 'page': page, + 'groupUid': $element.data('groupId'), + 'groupname': $element.data('groupname') + } + }).done(function(data) { + // Replace content + $('#g_' + page).replaceWith(data); + }); + }; - /** - * Group-related: Update the HTML view and show the original group - * - * @param {Object} $element - */ - Permissions.restoreGroup = function($element) { - var page = $element.data('page'); - var groupname = $element.data('groupname'); - var groupnameHtml = groupname; - if (typeof groupname === 'undefined') { - groupname = $('<span>', { - 'class': 'not_set', - 'text': '[not set]' - }); - groupnameHtml = groupname.html(); - groupname = groupname.text(); - } - var html = $('<span/>', { - 'id': 'g_' + page - }); - var aSelector = $('<a/>', { - 'class': 'ug_selector changegroup', - 'data-page': page, - 'data-group': $element.data('groupId'), - 'data-groupname': groupnameHtml, - 'text': groupname - }); - html.append(aSelector); + /** + * Group-related: Update the HTML view and show the original group + * + * @param {Object} $element + */ + Permissions.restoreGroup = function($element) { + var page = $element.data('page'); + var groupname = $element.data('groupname'); + var groupnameHtml = groupname; + if (typeof groupname === 'undefined') { + groupname = $('<span>', { + 'class': 'not_set', + 'text': '[not set]' + }); + groupnameHtml = groupname.html(); + groupname = groupname.text(); + } + var html = $('<span/>', { + 'id': 'g_' + page + }); + var aSelector = $('<a/>', { + 'class': 'ug_selector changegroup', + 'data-page': page, + 'data-group': $element.data('groupId'), + 'data-groupname': groupnameHtml, + 'text': groupname + }); + html.append(aSelector); - // Replace content - $('#g_' + page).replaceWith(html); - }; + // Replace content + $('#g_' + page).replaceWith(html); + }; - /** - * initializes events using deferred bound to document - * so AJAX reloads are no problem - */ - Permissions.initializeEvents = function() { + /** + * initializes events using deferred bound to document + * so AJAX reloads are no problem + */ + Permissions.initializeEvents = function() { - // Click event to change permissions - $(Permissions.options.containerSelector).on('click', '.change-permission', function(evt) { - evt.preventDefault(); - Permissions.setPermissions($(this)); - }).on('click', '.editlock', function(evt) { - // Click event for lock state - evt.preventDefault(); - Permissions.toggleEditLock($(this)); - }).on('click', '.changeowner', function(evt) { - // Click event to change owner - evt.preventDefault(); - Permissions.showChangeOwnerSelector($(this)); - }).on('click', '.changegroup', function(evt) { - // click event to change group - evt.preventDefault(); - Permissions.showChangeGroupSelector($(this)); - }).on('click', '.restoreowner', function(evt) { - // Add click handler for restoring previous owner - evt.preventDefault(); - Permissions.restoreOwner($(this)); - }).on('click', '.saveowner', function(evt) { - // Add click handler for saving owner - evt.preventDefault(); - Permissions.changeOwner($(this)); - }).on('click', '.restoregroup', function(evt) { - // Add click handler for restoring previous group - evt.preventDefault(); - Permissions.restoreGroup($(this)); - }).on('click', '.savegroup', function(evt) { - // Add click handler for saving group - evt.preventDefault(); - Permissions.changeGroup($(this)); - }); - }; + // Click event to change permissions + $(Permissions.options.containerSelector).on('click', '.change-permission', function(evt) { + evt.preventDefault(); + Permissions.setPermissions($(this)); + }).on('click', '.editlock', function(evt) { + // Click event for lock state + evt.preventDefault(); + Permissions.toggleEditLock($(this)); + }).on('click', '.changeowner', function(evt) { + // Click event to change owner + evt.preventDefault(); + Permissions.showChangeOwnerSelector($(this)); + }).on('click', '.changegroup', function(evt) { + // click event to change group + evt.preventDefault(); + Permissions.showChangeGroupSelector($(this)); + }).on('click', '.restoreowner', function(evt) { + // Add click handler for restoring previous owner + evt.preventDefault(); + Permissions.restoreOwner($(this)); + }).on('click', '.saveowner', function(evt) { + // Add click handler for saving owner + evt.preventDefault(); + Permissions.changeOwner($(this)); + }).on('click', '.restoregroup', function(evt) { + // Add click handler for restoring previous group + evt.preventDefault(); + Permissions.restoreGroup($(this)); + }).on('click', '.savegroup', function(evt) { + // Add click handler for saving group + evt.preventDefault(); + Permissions.changeGroup($(this)); + }); + }; - $(Permissions.initializeEvents); + $(Permissions.initializeEvents); - // expose to global - TYPO3.Permissions = Permissions; + // expose to global + TYPO3.Permissions = Permissions; - return Permissions; + return Permissions; }); diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js index 43a0292d4ae4bede31ef60816a7a2d3bee5760b4..82332ad760f9424e18e45ce86c6e31028df0e5d2 100644 --- a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js +++ b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js @@ -16,135 +16,135 @@ * JavaScript module for ext:documentation */ define(['jquery', 'datatables', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Notification', 'TYPO3/CMS/Backend/Severity', 'TYPO3/CMS/Backend/jquery.clearable'], function($, DataTable, Modal, Notification, Severity) { - 'use strict'; + 'use strict'; - /** - * - * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string, deleteButtons: string}}} - * @exports TYPO3/CMS/Documentation/Main - */ - var Documentation = { - dataTable: null, - searchField: null, - identifier: { - documentationList: '.t3js-documentation-list', - searchField: '.t3js-documentation-searchfield', - deleteButtons: '.t3js-documentation-delete' - } - }; + /** + * + * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string, deleteButtons: string}}} + * @exports TYPO3/CMS/Documentation/Main + */ + var Documentation = { + dataTable: null, + searchField: null, + identifier: { + documentationList: '.t3js-documentation-list', + searchField: '.t3js-documentation-searchfield', + deleteButtons: '.t3js-documentation-delete' + } + }; - /** - * Initializes the data table, depending on the current view - */ - Documentation.initializeView = function() { - var getVars = Documentation.getUrlVars(); - // init datatable - this.dataTable = $(this.identifier.documentationList).DataTable({ - paging: false, - dom: 'lrtip', - lengthChange: false, - pageLength: 15, - stateSave: true, - order: [[ 1, 'asc' ]] - }); - // search field - this.searchField = $(this.identifier.searchField); - if (this.dataTable && this.searchField.length) { - this.searchField.parents('form').on('submit', function() { - return false; - }); - var currentSearch = (getVars['search'] ? getVars['search'] : this.dataTable.search()); - this.searchField.val(currentSearch); - this.searchField.on('input', function(e) { - Documentation.dataTable.search($(this).val()).draw(); - }); - } - }; + /** + * Initializes the data table, depending on the current view + */ + Documentation.initializeView = function() { + var getVars = Documentation.getUrlVars(); + // init datatable + this.dataTable = $(this.identifier.documentationList).DataTable({ + paging: false, + dom: 'lrtip', + lengthChange: false, + pageLength: 15, + stateSave: true, + order: [[1, 'asc']] + }); + // search field + this.searchField = $(this.identifier.searchField); + if (this.dataTable && this.searchField.length) { + this.searchField.parents('form').on('submit', function() { + return false; + }); + var currentSearch = (getVars['search'] ? getVars['search'] : this.dataTable.search()); + this.searchField.val(currentSearch); + this.searchField.on('input', function(e) { + Documentation.dataTable.search($(this).val()).draw(); + }); + } + }; - /** - * Utility method to retrieve query parameters - * - * @returns {Array} - */ - Documentation.getUrlVars = function getUrlVars() { - var vars = [], hash; - var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split('='); - vars.push(hash[0]); - vars[hash[0]] = hash[1]; - } - return vars; - }; + /** + * Utility method to retrieve query parameters + * + * @returns {Array} + */ + Documentation.getUrlVars = function getUrlVars() { + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; + }; - /** - * Delete documentation - * - * @param {Object} $documentationRecord - */ - Documentation.deleteDocumentation = function($documentationRecord) { + /** + * Delete documentation + * + * @param {Object} $documentationRecord + */ + Documentation.deleteDocumentation = function($documentationRecord) { - Modal.confirm($documentationRecord.data('documentationName'), $documentationRecord.data('documentationDeleteDescription'), Severity.warning, [ - { - text: TYPO3.lang['cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['delete'], - btnClass: 'btn-info', - trigger: function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['documentation_remove'], - data: { - documentationKey: $documentationRecord.data('documentationKey') - }, - type: 'post', - cache: false - }).done(function(data) { - if(data) { - $documentationRecord.closest('tr').fadeOut(); - } else { - Documentation.handleErrors(data); - } - }); - Modal.dismiss(); - } - } - ]); + Modal.confirm($documentationRecord.data('documentationName'), $documentationRecord.data('documentationDeleteDescription'), Severity.warning, [ + { + text: TYPO3.lang['cancel'], + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['delete'], + btnClass: 'btn-info', + trigger: function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['documentation_remove'], + data: { + documentationKey: $documentationRecord.data('documentationKey') + }, + type: 'post', + cache: false + }).done(function(data) { + if (data) { + $documentationRecord.closest('tr').fadeOut(); + } else { + Documentation.handleErrors(data); + } + }); + Modal.dismiss(); + } + } + ]); - }; + }; - /** - * handle the errors from result object - * - * @param {Object} result - * @private - */ - Documentation.handleErrors = function(result) { - $.each(result.messages, function(position, message) { - Notification.error(message.title, message.message); - }); - }; + /** + * handle the errors from result object + * + * @param {Object} result + * @private + */ + Documentation.handleErrors = function(result) { + $.each(result.messages, function(position, message) { + Notification.error(message.title, message.message); + }); + }; - $(function() { - // Initialize the view - Documentation.initializeView(); + $(function() { + // Initialize the view + Documentation.initializeView(); - // Make the data table filter react to the clearing of the filter field - $(Documentation.identifier.searchField).clearable({ - onClear: function() { - Documentation.dataTable.search('').draw(); - } - }); - $(Documentation.identifier.deleteButtons).on('click', function(e) { - e.preventDefault(); - e.stopPropagation(); - Documentation.deleteDocumentation($(this)); - }) - }); + // Make the data table filter react to the clearing of the filter field + $(Documentation.identifier.searchField).clearable({ + onClear: function() { + Documentation.dataTable.search('').draw(); + } + }); + $(Documentation.identifier.deleteButtons).on('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + Documentation.deleteDocumentation($(this)); + }) + }); - return Documentation; + return Documentation; }); diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js index ade1fd321efd481192ab6ae6d419d5071c4cf80f..73aa6675424b2122123a5ce1f35347d763ab5590 100644 --- a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js +++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js @@ -19,712 +19,716 @@ * ExtensionManager.uploadForm => helper to show the upload form */ define([ - 'jquery', - 'nprogress', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/SplitButtons', - 'TYPO3/CMS/Backend/Tooltip', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Severity', - 'datatables', - 'TYPO3/CMS/Backend/jquery.clearable' + 'jquery', + 'nprogress', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/SplitButtons', + 'TYPO3/CMS/Backend/Tooltip', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Severity', + 'datatables', + 'TYPO3/CMS/Backend/jquery.clearable' ], function($, NProgress, Modal, SplitButtons, Tooltip, Notification, Severity) { - /** - * - * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}} - * @exports TYPO3/CMS/Extensionmanager/Main - */ - var ExtensionManager = { - identifier: { - extensionlist: '#typo3-extension-list', - searchField: '#Tx_Extensionmanager_extensionkey' - } - }; - - /** - * - * @returns {Object} - */ - ExtensionManager.manageExtensionListing = function() { - var $searchField = $(this.identifier.searchField), - dataTable = $(this.identifier.extensionlist).DataTable({ - paging: false, - dom: 'lrtip', - lengthChange: false, - pageLength: 15, - stateSave: true, - drawCallback: this.bindExtensionListActions, - columns: [ - null, - null, - { - type: 'extension' - }, - null, - { - type: 'version' - }, { - orderable: false - }, - null, - null - ] - }); - - $searchField.parents('form').on('submit', function() { - return false; - }); - - var getVars = ExtensionManager.getUrlVars(); - - // restore filter - var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search()); - $searchField.val(currentSearch); - - $searchField.on('input', function(e) { - dataTable.search($(this).val()).draw(); - }); - - return dataTable; - }; - - /** - * - */ - ExtensionManager.bindExtensionListActions = function() { - $('.removeExtension').not('.transformed').each(function() { - var $me = $(this); - $me.data('href', $me.attr('href')); - $me.attr('href', '#'); - $me.addClass('transformed'); - $me.click(function() { - Modal.confirm( - TYPO3.lang['extensionList.removalConfirmation.title'], - TYPO3.lang['extensionList.removalConfirmation.question'], - Severity.error, - [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.remove'], - btnClass: 'btn-danger', - trigger: function() { - ExtensionManager.removeExtensionFromDisk($me); - Modal.dismiss(); - } - } - ] - ); - }); - }); - }; - - /** - * - * @param {Object} $extension - */ - ExtensionManager.removeExtensionFromDisk = function($extension) { - $.ajax({ - url: $extension.data('href'), - beforeSend: function() { - NProgress.start(); - }, - success: function() { - location.reload(); - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * - * @returns {Array} - */ - ExtensionManager.getUrlVars = function() { - var vars = [], hash; - var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split('='); - vars.push(hash[0]); - vars[hash[0]] = hash[1]; - } - return vars; - }; - - $.fn.dataTableExt.oSort['extension-asc'] = function(a, b) { - return ExtensionManager.extensionCompare(a, b); - }; - - $.fn.dataTableExt.oSort['extension-desc'] = function(a, b) { - var result = ExtensionManager.extensionCompare(a, b); - return result * -1; - }; - - $.fn.dataTableExt.oSort['version-asc'] = function(a, b) { - var result = ExtensionManager.versionCompare(a, b); - return result * -1; - }; - - $.fn.dataTableExt.oSort['version-desc'] = function(a, b) { - return ExtensionManager.versionCompare(a, b); - }; - - /** - * Special sorting for the extension version column - * - * @param {String} a - * @param {String} b - * @returns {Number} - */ - ExtensionManager.versionCompare = function(a, b) { - if (a === b) { - return 0; - } - - var a_components = a.split("."); - var b_components = b.split("."); - - var len = Math.min(a_components.length, b_components.length); - - // loop while the components are equal - for (var i = 0; i < len; i++) { - // A bigger than B - if (parseInt(a_components[i]) > parseInt(b_components[i])) { - return 1; - } - - // B bigger than A - if (parseInt(a_components[i]) < parseInt(b_components[i])) { - return -1; - } - } - - // If one's a prefix of the other, the longer one is greaRepository. - if (a_components.length > b_components.length) { - return 1; - } - - if (a_components.length < b_components.length) { - return -1; - } - // Otherwise they are the same. - return 0; - }; - - /** - * The extension name column can contain various forms of HTML that - * break a direct comparison of values - * - * @param {String} a - * @param {String} b - * @returns {Number} - */ - ExtensionManager.extensionCompare = function(a, b) { - var div = document.createElement("div"); - div.innerHTML = a; - var aStr = div.textContent || div.innerText || a; - - div.innerHTML = b; - var bStr = div.textContent || div.innerText || b; - - return aStr.trim().localeCompare(bStr.trim()); - } - - /** - * - * @param {Object} data - */ - ExtensionManager.updateExtension = function(data) { - var message = '<h1>' + TYPO3.lang['extensionList.updateConfirmation.title'] + '</h1>'; - message += '<h2>' + TYPO3.lang['extensionList.updateConfirmation.message'] + '</h2>'; - message += '<form>'; - var i = 0; - $.each(data.updateComments, function(version, comment) { - comment = comment.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2'); - message += '<h3><input type="radio" ' + (i === 0 ? 'checked="checked" ' : '') + 'name="version" value="' + version + '" /> ' + version + '</h3>'; - message += '<div>' + comment + '</div>'; - i++; - }); - message += '</form>'; - - NProgress.done(); - - Modal.confirm( - TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'], - message, - Severity.warning, - [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.updateExtension'], - btnClass: 'btn-warning', - trigger: function() { - $.ajax({ - url: data.url, - data: { - tx_extensionmanager_tools_extensionmanagerextensionmanager: { - version: $('input:radio[name=version]:checked', Modal.currentModal).val() - } - }, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - complete: function() { - location.reload(); - } - }); - Modal.dismiss(); - } - } - ] - ); - }; - - /** - * - * @type {{downloadPath: string}} - */ - var Repository = { - downloadPath: '' - }; - - /** - * - */ - Repository.initDom = function() { - NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); - - $('#terTable').DataTable({ - lengthChange: false, - pageLength: 15, - stateSave: false, - info: false, - paging: false, - searching: false, - ordering: false, - drawCallback: Repository.bindDownload - }); - - $('#terVersionTable').DataTable({ - lengthChange: false, - pageLength: 15, - stateSave: false, - info: false, - paging: false, - searching: false, - drawCallback: Repository.bindDownload, - order: [ - [2, 'asc'] - ], - columns: [ - {orderable: false}, - null, - {type: 'version'}, - null, - null, - null - ] - }); - - $('#terSearchTable').DataTable({ - paging: false, - lengthChange: false, - stateSave: false, - searching: false, - language: { - search: 'Filter results:' - }, - ordering: false, - drawCallback: Repository.bindDownload - }); - - Repository.bindDownload(); - Repository.bindSearchFieldResetter(); - }; - - /** - * - */ - Repository.bindDownload = function() { - var installButtons = $('.downloadFromTer form.download button[type=submit]'); - installButtons.off('click'); - installButtons.on('click', function(event) { - event.preventDefault(); - var url = $(event.currentTarget.form).attr('data-href'); - Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val(); - $.ajax({ - url: url, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: Repository.getDependencies - }); - }); - }; - - /** - * - * @param {Object} data - * @returns {Boolean} - */ - Repository.getDependencies = function(data) { - NProgress.done(); - if (data.hasDependencies) { - Modal.confirm(data.title, data.message, Severity.info, [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.resolveDependencies'], - btnClass: 'btn-info', - trigger: function() { - Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); - Modal.dismiss(); - } - } - ]); - } else { - if(data.hasErrors) { - Notification.error(data.title, data.message, 15); - } else { - Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); - } - } - return false; - }; - - /** - * - * @param {String} url - */ - Repository.getResolveDependenciesAndInstallResult = function(url) { - $.ajax({ - url: url, - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: function (data) { - if (data.errorCount > 0) { - Modal.confirm(data.errorTitle, data.errorMessage, Severity.error, [ - { - text: TYPO3.lang['button.cancel'], - active: true, - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.resolveDependenciesIgnore'], - btnClass: 'btn-danger disabled t3js-dependencies', - trigger: function() { - if (!$(this).hasClass('disabled')) { - Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri); - Modal.dismiss(); - } - } - } - ]); - Modal.currentModal.on('shown.bs.modal', function() { - var $actionButton = Modal.currentModal.find('.t3js-dependencies'); - $('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() { - $actionButton.toggleClass('disabled', !$(this).prop('checked')); - }); - }); - } else { - var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension); - - successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': '; - $.each(data.result, function(index, value) { - successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': '; - $.each(value, function(extkey) { - successMessage += '\n* ' + extkey - }); - }); - Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15); - top.TYPO3.ModuleMenu.App.refreshMenu(); - } - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * - */ - Repository.bindSearchFieldResetter = function() { - var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]'); - var searchResultShown = ('' !== $searchFields.first().val()); - - $searchFields.clearable( - { - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - } - ); - }; - - /** - * - * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}} - */ - ExtensionManager.Update = { - identifier: { - extensionTable: '#terTable', - terUpdateAction: '.update-from-ter', - pagination: '.pagination-wrap', - splashscreen: '.splash-receivedata', - terTableWrapper: '#terTableWrapper', - terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper' - } - }; - - /** - * Register "update from ter" action - */ - ExtensionManager.Update.initializeEvents = function() { - $(ExtensionManager.Update.identifier.terUpdateAction).each(function() { - - // "this" is the form which updates the extension list from - // TER on submit - var $me = $(this), - updateURL = $(this).attr('action'); - - $me.attr('action', '#'); - $me.submit(function() { - // Force update on click. - ExtensionManager.Update.updateFromTer(updateURL, true); - - // Prevent normal submit action. - return false; - }); - - // This might give problems when there are more "update"-buttons, - // each one would trigger a TER-ExtensionManager.Update. - ExtensionManager.Update.updateFromTer(updateURL, false); - }); - }; - - /** - * - * @param {String} url - * @param {Boolean} forceUpdate - */ - ExtensionManager.Update.updateFromTer = function(url, forceUpdate) { - if (forceUpdate) { - url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1'; - } - - // Hide triggers for TER update - $(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden'); - - // Hide extension table - $(ExtensionManager.Update.identifier.extensionTable).hide(); - - // Show loaders - $(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown'); - $(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading'); - $(ExtensionManager.Update.identifier.pagination).addClass('is-loading'); - - var reload = false; - - $.ajax({ - url: url, - dataType: 'json', - cache: false, - beforeSend: function() { - NProgress.start(); - }, - success: function(data) { - // Something went wrong, show message - if (data.errorMessage.length) { - Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10); - } - - // Message with latest updates - var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update'); - $lastUpdate.text(data.timeSinceLastUpdate); - $lastUpdate.attr( - 'title', - TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime - ); - - if (data.updated) { - // Reload page - reload = true; - window.location.replace(window.location.href); - } - }, - error: function(jqXHR, textStatus, errorThrown) { - // Create an error message with diagnosis info. - var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText; - - Notification.warning( - TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], - errorMessage, - 10 - ); - }, - complete: function() { - NProgress.done(); - - if (!reload) { - // Hide loaders - $(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown'); - $(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading'); - $(ExtensionManager.Update.identifier.pagination).removeClass('is-loading'); - - // Show triggers for TER-update - $(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden'); - - // Show extension table - $(ExtensionManager.Update.identifier.extensionTable).show(); - } - } - }); - }; - - /** - * - */ - ExtensionManager.Update.transformPaginatorToAjax = function () { - $(ExtensionManager.Update.identifier.pagination + ' a').each(function() { - var $me = $(this); - $me.data('href', $(this).attr('href')); - $me.attr('href', '#'); - $me.click(function() { - var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper); - NProgress.start(); - $.ajax({ - url: $(this).data('href'), - dataType: 'json', - success: function(data) { - $terTableWrapper.html(data); - ExtensionManager.Update.transformPaginatorToAjax(); - }, - complete: function() { - NProgress.done(); - } - }); - }); - }); - }; - - /** - * show the uploading form - */ - ExtensionManager.UploadForm = { - expandedUploadFormClass: 'transformed' - }; - - /** - * - */ - ExtensionManager.UploadForm.initializeEvents = function() { - // Show upload form - $(document).on('click', '.t3js-upload', function(event) { - var $me = $(this), - $uploadForm = $('.uploadForm'); - - event.preventDefault(); - if($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) { - $uploadForm.stop().slideUp(); - $me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass); - } else { - $me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass); - $uploadForm.stop().slideDown(); - - $.ajax({ - url: $me.attr('href'), - dataType: 'html', - success: function (data) { - $uploadForm.html(data); - } - }); - } - }); - }; - - $(function() { - var dataTable = ExtensionManager.manageExtensionListing(); - - $(document).on('click', '.onClickMaskExtensionManager', function() { - NProgress.start(); - }).on('click', 'a[data-action=update-extension]', function(e) { - e.preventDefault(); - $.ajax({ - url: $(this).attr('href'), - dataType: 'json', - beforeSend: function() { - NProgress.start(); - }, - success: ExtensionManager.updateExtension - }); - }).on('change', 'input[name=unlockDependencyIgnoreButton]', function() { - var $actionButton = $('.t3js-dependencies'); - $actionButton.toggleClass('disabled', !$(this).prop('checked')); - }); - - $(ExtensionManager.identifier.searchField).clearable({ - onClear: function() { - dataTable.search('').draw(); - } - }); - - $(document).on('click', '.t3-button-action-installdistribution', function() { - NProgress.start(); - }); - - SplitButtons.addPreSubmitCallback(function(e) { - if ($(e.target).hasClass('t3js-save-close')) { - $('#configurationform').append($('<input />', {type: 'hidden', name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', value: 'saveAndClose'})); - } - }); - - // initialize the repository - Repository.initDom(); - - ExtensionManager.Update.initializeEvents(); - ExtensionManager.UploadForm.initializeEvents(); - - Tooltip.initialize('#typo3-extension-list [title]', { - delay: { - show: 500, - hide: 100 - }, - trigger: 'hover', - container: 'body' - }); - }); - - if (typeof TYPO3.ExtensionManager === 'undefined') { - TYPO3.ExtensionManager = ExtensionManager; - } - - return ExtensionManager; + /** + * + * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}} + * @exports TYPO3/CMS/Extensionmanager/Main + */ + var ExtensionManager = { + identifier: { + extensionlist: '#typo3-extension-list', + searchField: '#Tx_Extensionmanager_extensionkey' + } + }; + + /** + * + * @returns {Object} + */ + ExtensionManager.manageExtensionListing = function() { + var $searchField = $(this.identifier.searchField), + dataTable = $(this.identifier.extensionlist).DataTable({ + paging: false, + dom: 'lrtip', + lengthChange: false, + pageLength: 15, + stateSave: true, + drawCallback: this.bindExtensionListActions, + columns: [ + null, + null, + { + type: 'extension' + }, + null, + { + type: 'version' + }, { + orderable: false + }, + null, + null + ] + }); + + $searchField.parents('form').on('submit', function() { + return false; + }); + + var getVars = ExtensionManager.getUrlVars(); + + // restore filter + var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search()); + $searchField.val(currentSearch); + + $searchField.on('input', function(e) { + dataTable.search($(this).val()).draw(); + }); + + return dataTable; + }; + + /** + * + */ + ExtensionManager.bindExtensionListActions = function() { + $('.removeExtension').not('.transformed').each(function() { + var $me = $(this); + $me.data('href', $me.attr('href')); + $me.attr('href', '#'); + $me.addClass('transformed'); + $me.click(function() { + Modal.confirm( + TYPO3.lang['extensionList.removalConfirmation.title'], + TYPO3.lang['extensionList.removalConfirmation.question'], + Severity.error, + [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.remove'], + btnClass: 'btn-danger', + trigger: function() { + ExtensionManager.removeExtensionFromDisk($me); + Modal.dismiss(); + } + } + ] + ); + }); + }); + }; + + /** + * + * @param {Object} $extension + */ + ExtensionManager.removeExtensionFromDisk = function($extension) { + $.ajax({ + url: $extension.data('href'), + beforeSend: function() { + NProgress.start(); + }, + success: function() { + location.reload(); + }, + complete: function() { + NProgress.done(); + } + }); + }; + + /** + * + * @returns {Array} + */ + ExtensionManager.getUrlVars = function() { + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; + }; + + $.fn.dataTableExt.oSort['extension-asc'] = function(a, b) { + return ExtensionManager.extensionCompare(a, b); + }; + + $.fn.dataTableExt.oSort['extension-desc'] = function(a, b) { + var result = ExtensionManager.extensionCompare(a, b); + return result * -1; + }; + + $.fn.dataTableExt.oSort['version-asc'] = function(a, b) { + var result = ExtensionManager.versionCompare(a, b); + return result * -1; + }; + + $.fn.dataTableExt.oSort['version-desc'] = function(a, b) { + return ExtensionManager.versionCompare(a, b); + }; + + /** + * Special sorting for the extension version column + * + * @param {String} a + * @param {String} b + * @returns {Number} + */ + ExtensionManager.versionCompare = function(a, b) { + if (a === b) { + return 0; + } + + var a_components = a.split("."); + var b_components = b.split("."); + + var len = Math.min(a_components.length, b_components.length); + + // loop while the components are equal + for (var i = 0; i < len; i++) { + // A bigger than B + if (parseInt(a_components[i]) > parseInt(b_components[i])) { + return 1; + } + + // B bigger than A + if (parseInt(a_components[i]) < parseInt(b_components[i])) { + return -1; + } + } + + // If one's a prefix of the other, the longer one is greaRepository. + if (a_components.length > b_components.length) { + return 1; + } + + if (a_components.length < b_components.length) { + return -1; + } + // Otherwise they are the same. + return 0; + }; + + /** + * The extension name column can contain various forms of HTML that + * break a direct comparison of values + * + * @param {String} a + * @param {String} b + * @returns {Number} + */ + ExtensionManager.extensionCompare = function(a, b) { + var div = document.createElement("div"); + div.innerHTML = a; + var aStr = div.textContent || div.innerText || a; + + div.innerHTML = b; + var bStr = div.textContent || div.innerText || b; + + return aStr.trim().localeCompare(bStr.trim()); + } + + /** + * + * @param {Object} data + */ + ExtensionManager.updateExtension = function(data) { + var message = '<h1>' + TYPO3.lang['extensionList.updateConfirmation.title'] + '</h1>'; + message += '<h2>' + TYPO3.lang['extensionList.updateConfirmation.message'] + '</h2>'; + message += '<form>'; + var i = 0; + $.each(data.updateComments, function(version, comment) { + comment = comment.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2'); + message += '<h3><input type="radio" ' + (i === 0 ? 'checked="checked" ' : '') + 'name="version" value="' + version + '" /> ' + version + '</h3>'; + message += '<div>' + comment + '</div>'; + i++; + }); + message += '</form>'; + + NProgress.done(); + + Modal.confirm( + TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'], + message, + Severity.warning, + [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.updateExtension'], + btnClass: 'btn-warning', + trigger: function() { + $.ajax({ + url: data.url, + data: { + tx_extensionmanager_tools_extensionmanagerextensionmanager: { + version: $('input:radio[name=version]:checked', Modal.currentModal).val() + } + }, + dataType: 'json', + beforeSend: function() { + NProgress.start(); + }, + complete: function() { + location.reload(); + } + }); + Modal.dismiss(); + } + } + ] + ); + }; + + /** + * + * @type {{downloadPath: string}} + */ + var Repository = { + downloadPath: '' + }; + + /** + * + */ + Repository.initDom = function() { + NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); + + $('#terTable').DataTable({ + lengthChange: false, + pageLength: 15, + stateSave: false, + info: false, + paging: false, + searching: false, + ordering: false, + drawCallback: Repository.bindDownload + }); + + $('#terVersionTable').DataTable({ + lengthChange: false, + pageLength: 15, + stateSave: false, + info: false, + paging: false, + searching: false, + drawCallback: Repository.bindDownload, + order: [ + [2, 'asc'] + ], + columns: [ + {orderable: false}, + null, + {type: 'version'}, + null, + null, + null + ] + }); + + $('#terSearchTable').DataTable({ + paging: false, + lengthChange: false, + stateSave: false, + searching: false, + language: { + search: 'Filter results:' + }, + ordering: false, + drawCallback: Repository.bindDownload + }); + + Repository.bindDownload(); + Repository.bindSearchFieldResetter(); + }; + + /** + * + */ + Repository.bindDownload = function() { + var installButtons = $('.downloadFromTer form.download button[type=submit]'); + installButtons.off('click'); + installButtons.on('click', function(event) { + event.preventDefault(); + var url = $(event.currentTarget.form).attr('data-href'); + Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val(); + $.ajax({ + url: url, + dataType: 'json', + beforeSend: function() { + NProgress.start(); + }, + success: Repository.getDependencies + }); + }); + }; + + /** + * + * @param {Object} data + * @returns {Boolean} + */ + Repository.getDependencies = function(data) { + NProgress.done(); + if (data.hasDependencies) { + Modal.confirm(data.title, data.message, Severity.info, [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.resolveDependencies'], + btnClass: 'btn-info', + trigger: function() { + Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); + Modal.dismiss(); + } + } + ]); + } else { + if (data.hasErrors) { + Notification.error(data.title, data.message, 15); + } else { + Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath); + } + } + return false; + }; + + /** + * + * @param {String} url + */ + Repository.getResolveDependenciesAndInstallResult = function(url) { + $.ajax({ + url: url, + dataType: 'json', + beforeSend: function() { + NProgress.start(); + }, + success: function(data) { + if (data.errorCount > 0) { + Modal.confirm(data.errorTitle, data.errorMessage, Severity.error, [ + { + text: TYPO3.lang['button.cancel'], + active: true, + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.resolveDependenciesIgnore'], + btnClass: 'btn-danger disabled t3js-dependencies', + trigger: function() { + if (!$(this).hasClass('disabled')) { + Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri); + Modal.dismiss(); + } + } + } + ]); + Modal.currentModal.on('shown.bs.modal', function() { + var $actionButton = Modal.currentModal.find('.t3js-dependencies'); + $('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() { + $actionButton.toggleClass('disabled', !$(this).prop('checked')); + }); + }); + } else { + var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension); + + successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': '; + $.each(data.result, function(index, value) { + successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': '; + $.each(value, function(extkey) { + successMessage += '\n* ' + extkey + }); + }); + Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15); + top.TYPO3.ModuleMenu.App.refreshMenu(); + } + }, + complete: function() { + NProgress.done(); + } + }); + }; + + /** + * + */ + Repository.bindSearchFieldResetter = function() { + var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]'); + var searchResultShown = ('' !== $searchFields.first().val()); + + $searchFields.clearable( + { + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } + } + } + ); + }; + + /** + * + * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}} + */ + ExtensionManager.Update = { + identifier: { + extensionTable: '#terTable', + terUpdateAction: '.update-from-ter', + pagination: '.pagination-wrap', + splashscreen: '.splash-receivedata', + terTableWrapper: '#terTableWrapper', + terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper' + } + }; + + /** + * Register "update from ter" action + */ + ExtensionManager.Update.initializeEvents = function() { + $(ExtensionManager.Update.identifier.terUpdateAction).each(function() { + + // "this" is the form which updates the extension list from + // TER on submit + var $me = $(this), + updateURL = $(this).attr('action'); + + $me.attr('action', '#'); + $me.submit(function() { + // Force update on click. + ExtensionManager.Update.updateFromTer(updateURL, true); + + // Prevent normal submit action. + return false; + }); + + // This might give problems when there are more "update"-buttons, + // each one would trigger a TER-ExtensionManager.Update. + ExtensionManager.Update.updateFromTer(updateURL, false); + }); + }; + + /** + * + * @param {String} url + * @param {Boolean} forceUpdate + */ + ExtensionManager.Update.updateFromTer = function(url, forceUpdate) { + if (forceUpdate) { + url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1'; + } + + // Hide triggers for TER update + $(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden'); + + // Hide extension table + $(ExtensionManager.Update.identifier.extensionTable).hide(); + + // Show loaders + $(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown'); + $(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading'); + $(ExtensionManager.Update.identifier.pagination).addClass('is-loading'); + + var reload = false; + + $.ajax({ + url: url, + dataType: 'json', + cache: false, + beforeSend: function() { + NProgress.start(); + }, + success: function(data) { + // Something went wrong, show message + if (data.errorMessage.length) { + Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10); + } + + // Message with latest updates + var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update'); + $lastUpdate.text(data.timeSinceLastUpdate); + $lastUpdate.attr( + 'title', + TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime + ); + + if (data.updated) { + // Reload page + reload = true; + window.location.replace(window.location.href); + } + }, + error: function(jqXHR, textStatus, errorThrown) { + // Create an error message with diagnosis info. + var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText; + + Notification.warning( + TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], + errorMessage, + 10 + ); + }, + complete: function() { + NProgress.done(); + + if (!reload) { + // Hide loaders + $(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown'); + $(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading'); + $(ExtensionManager.Update.identifier.pagination).removeClass('is-loading'); + + // Show triggers for TER-update + $(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden'); + + // Show extension table + $(ExtensionManager.Update.identifier.extensionTable).show(); + } + } + }); + }; + + /** + * + */ + ExtensionManager.Update.transformPaginatorToAjax = function() { + $(ExtensionManager.Update.identifier.pagination + ' a').each(function() { + var $me = $(this); + $me.data('href', $(this).attr('href')); + $me.attr('href', '#'); + $me.click(function() { + var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper); + NProgress.start(); + $.ajax({ + url: $(this).data('href'), + dataType: 'json', + success: function(data) { + $terTableWrapper.html(data); + ExtensionManager.Update.transformPaginatorToAjax(); + }, + complete: function() { + NProgress.done(); + } + }); + }); + }); + }; + + /** + * show the uploading form + */ + ExtensionManager.UploadForm = { + expandedUploadFormClass: 'transformed' + }; + + /** + * + */ + ExtensionManager.UploadForm.initializeEvents = function() { + // Show upload form + $(document).on('click', '.t3js-upload', function(event) { + var $me = $(this), + $uploadForm = $('.uploadForm'); + + event.preventDefault(); + if ($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) { + $uploadForm.stop().slideUp(); + $me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass); + } else { + $me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass); + $uploadForm.stop().slideDown(); + + $.ajax({ + url: $me.attr('href'), + dataType: 'html', + success: function(data) { + $uploadForm.html(data); + } + }); + } + }); + }; + + $(function() { + var dataTable = ExtensionManager.manageExtensionListing(); + + $(document).on('click', '.onClickMaskExtensionManager', function() { + NProgress.start(); + }).on('click', 'a[data-action=update-extension]', function(e) { + e.preventDefault(); + $.ajax({ + url: $(this).attr('href'), + dataType: 'json', + beforeSend: function() { + NProgress.start(); + }, + success: ExtensionManager.updateExtension + }); + }).on('change', 'input[name=unlockDependencyIgnoreButton]', function() { + var $actionButton = $('.t3js-dependencies'); + $actionButton.toggleClass('disabled', !$(this).prop('checked')); + }); + + $(ExtensionManager.identifier.searchField).clearable({ + onClear: function() { + dataTable.search('').draw(); + } + }); + + $(document).on('click', '.t3-button-action-installdistribution', function() { + NProgress.start(); + }); + + SplitButtons.addPreSubmitCallback(function(e) { + if ($(e.target).hasClass('t3js-save-close')) { + $('#configurationform').append($('<input />', { + type: 'hidden', + name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', + value: 'saveAndClose' + })); + } + }); + + // initialize the repository + Repository.initDom(); + + ExtensionManager.Update.initializeEvents(); + ExtensionManager.UploadForm.initializeEvents(); + + Tooltip.initialize('#typo3-extension-list [title]', { + delay: { + show: 500, + hide: 100 + }, + trigger: 'hover', + container: 'body' + }); + }); + + if (typeof TYPO3.ExtensionManager === 'undefined') { + TYPO3.ExtensionManager = ExtensionManager; + } + + return ExtensionManager; }); diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js index 045b826b1a51b341570583ee1e8ae9844bc71c7b..af348f053a7d4ce48fe2f2f6b1d2cac833a8f858 100644 --- a/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js +++ b/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js @@ -17,182 +17,181 @@ * JavaScript to handle filelist actions from context menu * @exports TYPO3/CMS/Filelist/ContextMenuActions */ -define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) { - 'use strict'; - - /** - * @exports TYPO3/CMS/Filelist/ContextMenuActions - */ - var ContextMenuActions = {}; - ContextMenuActions.getReturnUrl = function () { - return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search); - }; - - ContextMenuActions.renameFile = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileRename.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.editFile = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileEdit.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.editFileStorage = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FormEngine.moduleUrl + '&edit[sys_file_storage][' + parseInt(uid, 10) + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.openInfoPopUp = function (table, uid) { - if (table === 'sys_file_storage') { - top.launchView(table, uid); - } else { - //files and folders - top.launchView('_FILE', uid); +define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) { + 'use strict'; + + /** + * @exports TYPO3/CMS/Filelist/ContextMenuActions + */ + var ContextMenuActions = {}; + ContextMenuActions.getReturnUrl = function() { + return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search); + }; + + ContextMenuActions.renameFile = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileRename.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.editFile = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileEdit.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.editFileStorage = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FormEngine.moduleUrl + '&edit[sys_file_storage][' + parseInt(uid, 10) + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.openInfoPopUp = function(table, uid) { + if (table === 'sys_file_storage') { + top.launchView(table, uid); + } else { + //files and folders + top.launchView('_FILE', uid); + } + }; + + ContextMenuActions.uploadFile = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileUpload.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.createFile = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileCreate.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() + ); + }; + + ContextMenuActions.deleteFile = function(table, uid) { + var $anchorElement = $(this); + var performDelete = function() { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileCommit.moduleUrl + '&data[delete][0][data]=' + top.rawurlencode(uid) + '&data[delete][0][redirect]=' + ContextMenuActions.getReturnUrl() + ); + }; + if (!$anchorElement.data('title')) { + performDelete(); + return; + } + + var $modal = Modal.confirm( + $anchorElement.data('title'), + $anchorElement.data('message'), + Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', + btnClass: 'btn-warning', + name: 'delete' } - }; - - ContextMenuActions.uploadFile = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileUpload.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.createFile = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileCreate.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl() - ); - }; - - ContextMenuActions.deleteFile = function (table, uid) { - var $anchorElement = $(this); - var performDelete = function () { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileCommit.moduleUrl + '&data[delete][0][data]=' + top.rawurlencode(uid) + '&data[delete][0][redirect]=' + ContextMenuActions.getReturnUrl() - ); - }; - if (!$anchorElement.data('title')) { - performDelete(); - return; + ]); + + $modal.on('button.clicked', function(e) { + if (e.target.name === 'delete') { + performDelete(); + } + Modal.dismiss(); + }); + }; + + ContextMenuActions.copyFile = function(table, uid) { + var shortMD5 = top.MD5(uid).substring(0, 10); + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid) + '&CB[setCopyMode]=1'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.copyReleaseFile = function(table, uid) { + var shortMD5 = top.MD5(uid).substring(0, 10); + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][_FILE%7C' + shortMD5 + ']=0&CB[setCopyMode]=1'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.cutFile = function(table, uid) { + var shortMD5 = top.MD5(uid).substring(0, 10); + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid); + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.cutReleaseFile = function(table, uid) { + var shortMD5 = top.MD5(uid).substring(0, 10); + var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; + url += '&CB[el][_FILE%7C' + shortMD5 + ']=0'; + $.ajax(url).always(function() { + top.TYPO3.Backend.ContentContainer.refresh(true); + }); + }; + + ContextMenuActions.pasteFileInto = function(table, uid) { + var $anchorElement = $(this); + var title = $anchorElement.data('title'); + var performPaste = function() { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileCommit.moduleUrl + '&CB[paste]=FILE|' + top.rawurlencode(uid) + '&CB[pad]=normal&redirect=' + ContextMenuActions.getReturnUrl() + ); + }; + if (!$anchorElement.data('title')) { + performPaste(); + return; + } + var $modal = Modal.confirm( + $anchorElement.data('title'), + $anchorElement.data('message'), + Severity.warning, [ + { + text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'cancel' + }, + { + text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', + btnClass: 'btn-warning', + name: 'ok' } - - var $modal = Modal.confirm( - $anchorElement.data('title'), - $anchorElement.data('message'), - Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete', - btnClass: 'btn-warning', - name: 'delete' - } - ]); - - $modal.on('button.clicked', function (e) { - if (e.target.name === 'delete') { - performDelete(); - } - Modal.dismiss(); - }); - }; - - ContextMenuActions.copyFile = function (table, uid) { - var shortMD5 = top.MD5(uid).substring(0, 10); - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid) + '&CB[setCopyMode]=1'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.copyReleaseFile = function (table, uid) { - var shortMD5 = top.MD5(uid).substring(0, 10); - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][_FILE%7C' + shortMD5 + ']=0&CB[setCopyMode]=1'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.cutFile = function (table, uid) { - var shortMD5 = top.MD5(uid).substring(0, 10); - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid); - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.cutReleaseFile = function (table, uid) { - var shortMD5 = top.MD5(uid).substring(0, 10); - var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard']; - url += '&CB[el][_FILE%7C' + shortMD5 + ']=0'; - $.ajax(url).always(function () { - top.TYPO3.Backend.ContentContainer.refresh(true); - }); - }; - - ContextMenuActions.pasteFileInto = function (table, uid) { - var $anchorElement = $(this); - var title = $anchorElement.data('title'); - var performPaste = function () { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileCommit.moduleUrl + '&CB[paste]=FILE|' + top.rawurlencode(uid) + '&CB[pad]=normal&redirect=' + ContextMenuActions.getReturnUrl() - ); - }; - if (!$anchorElement.data('title')) { - performPaste(); - return; - } - var $modal = Modal.confirm( - $anchorElement.data('title'), - $anchorElement.data('message'), - Severity.warning, [ - { - text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'cancel' - }, - { - text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK', - btnClass: 'btn-warning', - name: 'ok' - } - ]); - - $modal.on('button.clicked', function (e) { - if (e.target.name === 'ok') { - performPaste(); - } - Modal.dismiss(); - }); - }; - - - - ContextMenuActions.dropInto = function (table, uid, mode) { - var target = $(this).data('drop-target'); - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.FileCommit.moduleUrl - + '&file['+ mode + '][0][data]=' + top.rawurlencode(uid) - + '&file['+ mode + '][0][target]=' + top.rawurlencode(target) - + '&redirect=' + ContextMenuActions.getReturnUrl() - ); - }; - ContextMenuActions.dropMoveInto = function (table, uid) { - ContextMenuActions.dropInto.bind($(this))(table, uid, 'move'); - }; - ContextMenuActions.dropCopyInto = function (table, uid) { - ContextMenuActions.dropInto.bind($(this))(table, uid, 'copy'); - }; - return ContextMenuActions; + ]); + + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + performPaste(); + } + Modal.dismiss(); + }); + }; + + + ContextMenuActions.dropInto = function(table, uid, mode) { + var target = $(this).data('drop-target'); + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.FileCommit.moduleUrl + + '&file[' + mode + '][0][data]=' + top.rawurlencode(uid) + + '&file[' + mode + '][0][target]=' + top.rawurlencode(target) + + '&redirect=' + ContextMenuActions.getReturnUrl() + ); + }; + ContextMenuActions.dropMoveInto = function(table, uid) { + ContextMenuActions.dropInto.bind($(this))(table, uid, 'move'); + }; + ContextMenuActions.dropCopyInto = function(table, uid) { + ContextMenuActions.dropInto.bind($(this))(table, uid, 'copy'); + }; + return ContextMenuActions; }); diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js index 0dd2ec469639d6ebdd3b6de00190a8316c040ce8..d5cb054a5924ce9d31d7fd75a9fa2a5382855f34 100644 --- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js +++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js @@ -15,45 +15,45 @@ * Module: TYPO3/CMS/Filelist/FileDelete * JavaScript for file delete */ -define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) { +define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) { - $(document).on('click', '.t3js-filelist-delete', function(e) { - e.preventDefault(); - var $anchorElement = $(this); - var redirectUrl = $anchorElement.data('redirectUrl'); - if (redirectUrl) { - redirectUrl = top.rawurlencode(redirectUrl); - } else { - redirectUrl = top.rawurlencode(top.list_frame.document.location.pathname+top.list_frame.document.location.search); - } - var identifier = $anchorElement.data('identifier'); - var deleteType = $anchorElement.data('deleteType'); - var deleteUrl = $anchorElement.data('deleteUrl') + '&data[delete][0][data]=' + encodeURIComponent(identifier); - if ($anchorElement.data('check')) { - var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('content'), Severity.warning, [ - { - text: TYPO3.lang['buttons.confirm.delete_file.no'] || 'Cancel', - active: true, - btnClass: 'btn-default', - name: 'no' - }, - { - text: TYPO3.lang['buttons.confirm.' + deleteType + '.yes'] || 'Yes, delete this file or folder', - btnClass: 'btn-warning', - name: 'yes' - } - ]); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'no') { - Modal.dismiss(); - } else if (e.target.name === 'yes') { - Modal.dismiss(); - top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl; - } - }); - } else { - top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl; - } - }); + $(document).on('click', '.t3js-filelist-delete', function(e) { + e.preventDefault(); + var $anchorElement = $(this); + var redirectUrl = $anchorElement.data('redirectUrl'); + if (redirectUrl) { + redirectUrl = top.rawurlencode(redirectUrl); + } else { + redirectUrl = top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search); + } + var identifier = $anchorElement.data('identifier'); + var deleteType = $anchorElement.data('deleteType'); + var deleteUrl = $anchorElement.data('deleteUrl') + '&data[delete][0][data]=' + encodeURIComponent(identifier); + if ($anchorElement.data('check')) { + var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('content'), Severity.warning, [ + { + text: TYPO3.lang['buttons.confirm.delete_file.no'] || 'Cancel', + active: true, + btnClass: 'btn-default', + name: 'no' + }, + { + text: TYPO3.lang['buttons.confirm.' + deleteType + '.yes'] || 'Yes, delete this file or folder', + btnClass: 'btn-warning', + name: 'yes' + } + ]); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'no') { + Modal.dismiss(); + } else if (e.target.name === 'yes') { + Modal.dismiss(); + top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl; + } + }); + } else { + top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl; + } + }); }); diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js index 10eeaf83d319e69e9d7fe6d9d4857d1e5dcc418f..ecf6d395b645d16936cf553b5fa3e18c5d5b64ce 100644 --- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js +++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js @@ -17,60 +17,60 @@ */ define(['jquery'], function($) { - $('a.filelist-file-title').click(function(event) { - event.preventDefault(); + $('a.filelist-file-title').click(function(event) { + event.preventDefault(); - var url = $(this).attr('data-url'); - window.location.href=url; - }); + var url = $(this).attr('data-url'); + window.location.href = url; + }); - $('a.btn.filelist-file-edit').click(function(event) { - event.preventDefault(); + $('a.btn.filelist-file-edit').click(function(event) { + event.preventDefault(); - var url = $(this).attr('data-url'); - top.list_frame.location.href=url; - }); + var url = $(this).attr('data-url'); + top.list_frame.location.href = url; + }); - $('a.btn.filelist-file-view').click(function(event) { - event.preventDefault(); + $('a.btn.filelist-file-view').click(function(event) { + event.preventDefault(); - var url = $(this).attr('data-url'); - top.openUrlInWindow(url, 'WebFile') - }); + var url = $(this).attr('data-url'); + top.openUrlInWindow(url, 'WebFile') + }); - $('a.btn.filelist-file-replace').click(function(event) { - event.preventDefault(); + $('a.btn.filelist-file-replace').click(function(event) { + event.preventDefault(); - var url = $(this).attr('data-url'); - top.list_frame.location.href=url; - }); + var url = $(this).attr('data-url'); + top.list_frame.location.href = url; + }); - $('a.btn.filelist-file-rename').click(function(event) { - event.preventDefault(); + $('a.btn.filelist-file-rename').click(function(event) { + event.preventDefault(); - var url = $(this).attr('data-url'); - top.list_frame.location.href=url; - }); + var url = $(this).attr('data-url'); + top.list_frame.location.href = url; + }); - $('a.btn.filelist-file-info').click(function(event) { - event.preventDefault(); + $('a.btn.filelist-file-info').click(function(event) { + event.preventDefault(); - var identifier = $(this).attr('data-identifier'); - openFileInfoPopup(identifier); - }); + var identifier = $(this).attr('data-identifier'); + openFileInfoPopup(identifier); + }); - $('a.filelist-file-references').click(function(event) { - event.preventDefault(); + $('a.filelist-file-references').click(function(event) { + event.preventDefault(); - var identifier = $(this).attr('data-identifier'); - openFileInfoPopup(identifier); - }); + var identifier = $(this).attr('data-identifier'); + openFileInfoPopup(identifier); + }); - /** - * @param identifier - */ - function openFileInfoPopup(identifier) { - top.launchView('_FILE', identifier); - } + /** + * @param identifier + */ + function openFileInfoPopup(identifier) { + top.launchView('_FILE', identifier); + } }); diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js index a4cdff00961da43c69fe751834ba9c5af2f292d3..f94205b68d550fdeeb371f384004da4f666edb6b 100644 --- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js +++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js @@ -17,10 +17,10 @@ */ define(['jquery'], function($) { - $('a.filelist-translationToggler').click(function(event) { - var id = $(this).attr('data-fileid'); - $('div[data-fileid="' + id + '"]').toggle(); - }); + $('a.filelist-translationToggler').click(function(event) { + var id = $(this).attr('data-fileid'); + $('div[data-fileid="' + id + '"]').toggle(); + }); - return null; + return null; }); diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js index 86b097489b444dba6dc039db0b56ec2d7398c2ee..b2a08d18f9fa078b43e9cce453c2bf0b3063fdb9 100644 --- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js +++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js @@ -18,16 +18,16 @@ */ define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) { - var $searchFields = $('input[name="tx_filelist_file_filelistlist[searchWord]"]'); - var searchResultShown = ('' !== $searchFields.first().val()); + var $searchFields = $('input[name="tx_filelist_file_filelistlist[searchWord]"]'); + var searchResultShown = ('' !== $searchFields.first().val()); - // make search field clearable - $searchFields.clearable({ - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - }); + // make search field clearable + $searchFields.clearable({ + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } + } + }); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js index 871120534a6b102de077539df8350d22fc206d6e..be985682c5ded7eada488772c34226006419499a 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js @@ -15,1139 +15,1139 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Core', - ], function($, core) { - 'use strict'; + 'TYPO3/CMS/Form/Backend/FormEditor/Core' +], function($, core) { + 'use strict'; + + /** + * Return a static method named "getInstance". + * Use this method to create the formeditor app. + */ + return (function(_core) { + + /** + * @private + * + * Hold the instance (Singleton Pattern) + */ + var _formEditorInstance = null; + + /** + * @public + * + * @param object _configuration + * @param object _mediator + * @param object _viewModel + * @return object + */ + function FormEditor(_configuration, _mediator, _viewModel) { + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @private + * + * @var bool + */ + var _unsavedContent = false; + + /** + * @private + * + * @var bool + */ + var _previewMode = false; + + /** + * @public + * + * @return object + */ + function getPublisherSubscriber() { + return _core.getPublisherSubscriber(); + }; + + /** + * @public + * + * @return void + */ + function _saveApplicationState() { + + _getApplicationStateStack().addAndReset({ + formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(), + currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'), + currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath') + }); + }; + + /** + * @public + * + * @return void + */ + function undoApplicationState() { + _getApplicationStateStack().incrementCurrentStackPointer(); + }; + + /** + * @public + * + * @return void + */ + function redoApplicationState() { + _getApplicationStateStack().decrementCurrentStackPointer(); + }; + + /** + * @public + * + * @return int + */ + function getMaximalApplicationStates() { + return _getApplicationStateStack().getMaximalStackSize(); + }; + + /** + * @public + * + * @return int + */ + function getCurrentApplicationStates() { + return _getApplicationStateStack().getCurrentStackSize(); + }; + + /** + * @public + * + * @return int + */ + function getCurrentApplicationStatePosition() { + return _getApplicationStateStack().getCurrentStackPointer(); + }; + + /** + * @public + * + * @param string type + * @return object + * @throws 1475378543 + */ + function getRunningAjaxRequest(type) { + assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543); + return _core.getRunningAjaxRequest(type); + }; + + /** + * @public + * + * @return object + */ + function getUtility() { + return _core.getUtility(); + }; + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + getUtility().assert(test, message, messageCode); + }; + + /** + * @public + * + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param boolean allowEmptyReturnValue + * @return string + */ + function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @param function func + * @return void + */ + function addPropertyValidationValidator(validatorIdentifier, func) { + _getPropertyValidationService().addValidator(validatorIdentifier, func); + }; + + /** + * @public + * + * @param string propertyPath + * @return object + */ + function validateCurrentlySelectedFormElementProperty(propertyPath) { + return validateFormElementProperty( + getCurrentlySelectedFormElement(), + propertyPath + ); + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @return object + */ + function validateFormElementProperty(formElement, propertyPath) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath); + }; + + /** + * @public + * + * @param object formElement + * @return object + */ + function validateFormElement(formElement) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElement(formElement); + }; + + /** + * @public + * + * @param object validationResults + * @return boolean + */ + function validationResultsHasErrors(validationResults) { + return _getPropertyValidationService().validationResultsHasErrors(validationResults); + }; + + /** + * @public + * + * @param object formElement + * @param boolean returnAfterFirstMatch + * @return object + */ + function validateFormElementRecursive(formElement, returnAfterFirstMatch) { + formElement = _getRepository().findFormElement(formElement); + return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch); + }; + + /** + * @public + * + * @param bool unsavedContent + * @return void + * @throws 1475378544 + */ + function setUnsavedContent(unsavedContent) { + assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544); + _unsavedContent = unsavedContent; + }; + + /** + * @public + * + * @return boolean + */ + function getUnsavedContent() { + return _unsavedContent; + }; + + /** + * @public + * + * @return object + */ + function getRootFormElement() { + return _getRepository().getRootFormElement(); + }; + + /** + * @public + * + * @return string + */ + function getCurrentlySelectedFormElement() { + return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')); + }; + + /** + * @public + * + * @param string|object formElement + * @param boolean doNotRefreshCurrentlySelectedPageIndex + * @return void + * @publish core/currentlySelectedFormElementChanged + */ + function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) { + doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex; + + formElement = _getRepository().findFormElement(formElement); + _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath')); + + if (!doNotRefreshCurrentlySelectedPageIndex) { + refreshCurrentlySelectedPageIndex(); + } + getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]); + }; + + /** + * @public + * + * @param string identifierPath + * @return object + * @throws 1475378545 + */ + function getFormElementByIdentifierPath(identifierPath) { + assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545); + return _getRepository().findFormElementByIdentifierPath(identifierPath); + }; + + /** + * @public + * + * @param string identifierPath + * @return bool + */ + function isFormElementIdentifierUsed(formElementIdentifier) { + return _getRepository().isFormElementIdentifierUsed(formElementIdentifier); + } + + /** + * @public + * + * @param string formElementType + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + */ + function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { + var formElement; + formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet); + formElement.set('renderables', formElement.get('renderables')); + return formElement; + }; + + /** + * @public + * + * @param object formElement + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475434337 + */ + function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) { + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(referenceFormElement)) { + referenceFormElement = getCurrentlySelectedFormElement(); + } + referenceFormElement = _getRepository().findFormElement(referenceFormElement); + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337); + return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string formElementType + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475434336 + * @throws 1475435857 + */ + function createFormElement(formElementType, disablePublishersOnSet) { + var formElementDefinition, identifier; + assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336); + + identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType); + formElementDefinition = getFormElementDefinitionByType(formElementType); + return _getFactory().createFormElement({ + type: formElementType, + identifier: identifier, + label: formElementDefinition['label'] || formElementType + }, undefined, undefined, undefined, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string|object formElementToRemove + * @param boolean disablePublishersOnSet + * @return object + */ + function removeFormElement(formElementToRemove, disablePublishersOnSet) { + var parentFormElement; + _saveApplicationState(); + + formElementToRemove = _getRepository().findFormElement(formElementToRemove); + parentFormElement = formElementToRemove.get('__parentRenderable'); + _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet); + return parentFormElement; + }; + + /** + * @public + * + * @param string|object formElementToMove + * @param string position + * @param string|object referenceFormElement + * @param boolean disablePublishersOnSet + * @return string + * @throws 1475378551 + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + _saveApplicationState(); + + formElementToMove = _getRepository().findFormElement(formElementToMove); + referenceFormElement = _getRepository().findFormElement(referenceFormElement); + + assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551); + + formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true); + disablePublishersOnSet = !!disablePublishersOnSet; + if (!disablePublishersOnSet) { + formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables')); + } + return formElementToMove; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @return object (dereferenced) + * @throws 1475378555 + * @throws 1475378556 + * @throws 1475446108 + */ + function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) { + var collection, collectionElement, formElementDefinition; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556); + + formElementDefinition = getFormElementDefinitionByType(formElement.get('type')); + if (!getUtility().isUndefinedOrNull(formElementDefinition['propertyCollections'])) { + collection = formElementDefinition['propertyCollections'][collectionName]; + assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108); + collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection); + return $.extend(true, {}, collectionElement); + } else { + return {}; + } + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @return int + * @throws 1475378557 + * @throws 1475378558 + */ + function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) { + var indexFromPropertyCollectionElement; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558); + + indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier( + collectionElementIdentifier, + collectionName, + formElement + ); + + return indexFromPropertyCollectionElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param object collectionElementConfiguration + * @param string referenceCollectionElementIdentifier + * @return object + */ + function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) { + return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier); + }; + + /** + * @public + * + * @param object collectionElement + * @param string collectionName + * @param string|object formElement + * @param string referenceCollectionElementIdentifier + * @return object + * @throws 1475443300 + * @throws 1475443301 + */ + function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) { + var collection; + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300); + + if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { + collection = formElement.get(collectionName); + if ('array' === $.type(collection) && collection.length > 0) { + referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier']; + } + } + + return _getRepository().addPropertyCollectionElement( + collectionElement, + collectionName, + formElement, + referenceCollectionElementIdentifier, + false + ); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object collectionElementConfiguration + * @return void + * @throws 1475378559 + * @throws 1475378560 + */ + function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) { + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560); + if ('object' !== $.type(collectionElementConfiguration)) { + collectionElementConfiguration = {}; + } + + return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param string formElement + * @param bool disablePublishersOnSet + * @return void + * @throws 1475378561 + * @throws 1475378562 + */ + function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + _saveApplicationState(); + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + formElement = _getRepository().findFormElement(formElement); + + assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562); + + _getRepository().removePropertyCollectionElementByIdentifier( + formElement, + collectionElementIdentifier, + collectionName, + true + ); + + disablePublishersOnSet = !!disablePublishersOnSet; + if (!disablePublishersOnSet) { + getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']); + } + }; + + /** + * @public + * + * @param string collectionElementToMove + * @param string position + * @param string referenceCollectionElement + * @param string collectionName + * @param object formElement + * @param boolean disablePublishersOnSet + * @return string + * @throws 1477404352 + * @throws 1477404353 + * @throws 1477404354 + * @throws 1477404355 + */ + function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { + _saveApplicationState(); + + formElement = _getRepository().findFormElement(formElement); + + assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352); + assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353); + assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354); + assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355); + + return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet); + }; + + /** + * @public + * + * @param string elementType + * @param string formElementDefinitionKey + * @returnmixed + * @throws 1475378563 + */ + function getFormElementDefinitionByType(elementType, formElementDefinitionKey) { + var formElementDefinition; + assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563); + + formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType); + + if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) { + formElementDefinition = formElementDefinition[formElementDefinitionKey]; + } + + if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) { + return $.extend(true, {}, formElementDefinition); + } else { + return formElementDefinition; + } + }; + + /** + * @public + * + * @param object formElement + * @param string formElementDefinitionKey + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + formElement = _getRepository().findFormElement(formElement); + return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey); + }; + + /** + * @public + * + * @param string collectionName + * @param string collectionElementIdentifier + * @return mixed + */ + function getFormEditorDefinition(definitionName, subject) { + return _getRepository().getFormEditorDefinition(definitionName, subject); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @return object (dereferenced) + * @throws 1475672362 + */ + function getFormElementPropertyValidatorDefinition(validatorIdentifier) { + var validatorDefinition; + assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362); + + validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier); + return $.extend(true, {}, validatorDefinition); + }; + + /** + * @public + * + * @return int + */ + function getCurrentlySelectedPageIndex() { + return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'); + }; + + /** + * @public + * + * @return void + */ + function refreshCurrentlySelectedPageIndex() { + _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement())); + }; + + /** + * @public + * + * @return object + * @throws 1477786068 + */ + function getCurrentlySelectedPage() { + var currentPage; + + currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()]; + assert('object' === $.type(currentPage), 'No page found', 1477786068); + return currentPage; + }; + + /** + * @public + * + * @return object + */ + function getLastTopLevelElementOnCurrentPage() { + var lastRenderable, renderables; + + renderables = getCurrentlySelectedPage().get('renderables'); + if (getUtility().isUndefinedOrNull(renderables)) { + return undefined; + } + lastRenderable = renderables[renderables.length - 1]; + return lastRenderable; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getLastFormElementWithinParentFormElement(formElement) { + var lastElement; + + formElement = _getRepository().findFormElement(formElement); + if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { + return formElement; + } + return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1]; + }; + + /** + * @public + * + * @param object + * @return int + */ + function getPageIndexFromFormElement(formElement) { + formElement = _getRepository().findFormElement(formElement); + + return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement( + formElement + ); + }; + + /** + * @public + * + * @return void + */ + function renderCurrentFormPage() { + renderFormPage(getCurrentlySelectedPageIndex()); + }; + + /** + * @public + * + * @param int pageIndex + * @return void + * @throws 1475446442 + */ + function renderFormPage(pageIndex) { + assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442); + _getDataBackend().renderFormDefinitionPage(pageIndex); + }; + + /** + * @public + * + * @param object formElement + * @return object|null + */ + function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { + return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel( + _getRepository().findFormElement(formElement) + ); + }; + + /** + * @public + * + * @param object formElement + * @return object|null + */ + function findEnclosingGridContainerFormElement(formElement) { + return _getRepository().findEnclosingGridContainerFormElement( + _getRepository().findFormElement(formElement) + ); + }; + + /** + * @public + * + * @param object formElement + * @return object|null + */ + function findEnclosingGridRowFormElement(formElement) { + return _getRepository().findEnclosingGridRowFormElement( + _getRepository().findFormElement(formElement) + ); + }; + + /** + * @public + * + * @return object + */ + function getNonCompositeNonToplevelFormElements() { + return _getRepository().getNonCompositeNonToplevelFormElements(); + }; + + /** + * @public + * + * @return boolean + */ + function isRootFormElementSelected() { + return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath')); + }; + + /** + * @public + * + * @return object + */ + function getViewModel() { + return _viewModel; + }; + + /** + * @public + * + * @return void + */ + function saveFormDefinition() { + _getDataBackend().saveFormDefinition(); + }; + + /** + * @private + * + * @return object + */ + function _getDataBackend() { + return _core.getDataBackend(); + }; + + /** + * @private + * + * @return object + */ + function _getFactory() { + return _core.getFactory(); + }; + + /** + * @private + * + * @return object + */ + function _getRepository() { + return _core.getRepository(); + }; + + /** + * @private + * + * @return object + */ + function _getPropertyValidationService() { + return _core.getPropertyValidationService(); + }; + + /** + * @public + * + * @return object + */ + function _getApplicationStateStack() { + return _core.getApplicationStateStack(); + }; + + /** + * @private + * + * @return void + * @publish ajax/beforeSend + * @publish ajax/complete + */ + function _ajaxSetup() { + $.ajaxSetup({ + beforeSend: function() { + getPublisherSubscriber().publish('ajax/beforeSend'); + }, + complete: function() { + getPublisherSubscriber().publish('ajax/complete'); + } + }); + }; + + /** + * @private + * + * @param object endpoints + * @param string prototypeName + * @param string formPersistenceIdentifier + * @return void + * @throws 1475379748 + * @throws 1475379749 + * @throws 1475927876 + */ + function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) { + assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748); + assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876); + assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749); + + _core.getDataBackend().setEndpoints(endpoints); + _core.getDataBackend().setPrototypeName(prototypeName); + _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier); + }; + + /** + * @private + * + * @param object formEditorDefinitions + * @return void + * @throws 1475379750 + */ + function _repositorySetup(formEditorDefinitions) { + assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750); + + _getRepository().setFormEditorDefinitions(formEditorDefinitions); + } + + /** + * @private + * + * @param object additionalViewModelModules + * @return void + * @throws 1475379752 + * @throws 1475492374 + */ + function _viewSetup(additionalViewModelModules) { + assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374); + + if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) { + assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752); + } else { + additionalViewModelModules = []; + } + _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules); + }; + + /** + * @private + * + * @return void + * @throws 1475492032 + */ + function _mediatorSetup() { + assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032); + _mediator.bootstrap(_formEditorInstance, _viewModel); + }; + + /** + * @private + * + * @param object rootFormElement + * @param int maximumUndoSteps + * @return void + * @throws 1475379751 + */ + function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) { + assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751); + + if ('number' !== $.type(maximumUndoSteps)) { + maximumUndoSteps = 10; + } + _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps); + + _getApplicationStateStack().addAndReset({ + currentlySelectedPageIndex: 0, + currentlySelectedFormElementIdentifierPath: rootFormElement['identifier'] + }, true); + + _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true)); + }; + + /** + * @private + * + * @return void + */ + function _bootstrap() { + _configuration = _configuration || {}; + + _mediatorSetup(); + _ajaxSetup(); + _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']); + _repositorySetup(_configuration['formEditorDefinitions']); + _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']); + setCurrentlySelectedFormElement(_getRepository().getRootFormElement()); + + _viewSetup(_configuration['additionalViewModelModules']); + }; + + /** + * @public + * + * @return TYPO3/CMS/Form/Backend/FormEditor + * @throws 1473200696 + */ + function run() { + if (_isRunning) { + throw 'You can not run the app twice (1473200696)'; + } + + _bootstrap(); + _isRunning = true; + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getRootFormElement: getRootFormElement, + + createAndAddFormElement: createAndAddFormElement, + createFormElement: createFormElement, + addFormElement: addFormElement, + moveFormElement: moveFormElement, + removeFormElement: removeFormElement, + + getCurrentlySelectedFormElement: getCurrentlySelectedFormElement, + setCurrentlySelectedFormElement: setCurrentlySelectedFormElement, + + getFormElementByIdentifierPath: getFormElementByIdentifierPath, + isFormElementIdentifierUsed: isFormElementIdentifierUsed, + + createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, + createPropertyCollectionElement: createPropertyCollectionElement, + addPropertyCollectionElement: addPropertyCollectionElement, + removePropertyCollectionElement: removePropertyCollectionElement, + movePropertyCollectionElement: movePropertyCollectionElement, + getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement, + getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration, + + saveFormDefinition: saveFormDefinition, + renderCurrentFormPage: renderCurrentFormPage, + renderFormPage: renderFormPage, + + getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex, + refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex, + getPageIndexFromFormElement: getPageIndexFromFormElement, + getCurrentlySelectedPage: getCurrentlySelectedPage, + getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage, + findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, + findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, + findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, + isRootFormElementSelected: isRootFormElementSelected, + getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement, + getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, + + getFormElementDefinitionByType: getFormElementDefinitionByType, + getFormElementDefinition: getFormElementDefinition, + getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition, + getFormEditorDefinition: getFormEditorDefinition, + + getPublisherSubscriber: getPublisherSubscriber, + getRunningAjaxRequest: getRunningAjaxRequest, + + setUnsavedContent: setUnsavedContent, + getUnsavedContent: getUnsavedContent, + + addPropertyValidationValidator: addPropertyValidationValidator, + validateFormElementProperty: validateFormElementProperty, + validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty, + validateFormElement: validateFormElement, + validateFormElementRecursive: validateFormElementRecursive, + validationResultsHasErrors: validationResultsHasErrors, + + getUtility: getUtility, + assert: assert, + buildPropertyPath: buildPropertyPath, + + getViewModel: getViewModel, + undoApplicationState: undoApplicationState, + redoApplicationState: redoApplicationState, + getMaximalApplicationStates: getMaximalApplicationStates, + getCurrentApplicationStates: getCurrentApplicationStates, + getCurrentApplicationStatePosition: getCurrentApplicationStatePosition, + + run: run + }; + }; /** - * Return a static method named "getInstance". - * Use this method to create the formeditor app. + * Emulation of static methods */ - return (function(_core) { - - /** - * @private - * - * Hold the instance (Singleton Pattern) - */ - var _formEditorInstance = null; - - /** - * @public - * - * @param object _configuration - * @param object _mediator - * @param object _viewModel - * @return object - */ - function FormEditor(_configuration, _mediator, _viewModel) { - - /** - * @private - * - * @var bool - */ - var _isRunning = false; - - /** - * @private - * - * @var bool - */ - var _unsavedContent = false; - - /** - * @private - * - * @var bool - */ - var _previewMode = false; - - /** - * @public - * - * @return object - */ - function getPublisherSubscriber() { - return _core.getPublisherSubscriber(); - }; - - /** - * @public - * - * @return void - */ - function _saveApplicationState() { - - _getApplicationStateStack().addAndReset({ - formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(), - currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'), - currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath') - }); - }; - - /** - * @public - * - * @return void - */ - function undoApplicationState() { - _getApplicationStateStack().incrementCurrentStackPointer(); - }; - - /** - * @public - * - * @return void - */ - function redoApplicationState() { - _getApplicationStateStack().decrementCurrentStackPointer(); - }; - - /** - * @public - * - * @return int - */ - function getMaximalApplicationStates() { - return _getApplicationStateStack().getMaximalStackSize(); - }; - - /** - * @public - * - * @return int - */ - function getCurrentApplicationStates() { - return _getApplicationStateStack().getCurrentStackSize(); - }; - - /** - * @public - * - * @return int - */ - function getCurrentApplicationStatePosition() { - return _getApplicationStateStack().getCurrentStackPointer(); - }; - - /** - * @public - * - * @param string type - * @return object - * @throws 1475378543 - */ - function getRunningAjaxRequest(type) { - assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543); - return _core.getRunningAjaxRequest(type); - }; - - /** - * @public - * - * @return object - */ - function getUtility() { - return _core.getUtility(); - }; - - /** - * @public - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - getUtility().assert(test, message, messageCode); - }; - - /** - * @public - * - * @param string propertyPath - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @param boolean allowEmptyReturnValue - * @return string - */ - function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - formElement = _getRepository().findFormElement(formElement); - return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue); - }; - - /** - * @public - * - * @param string validatorIdentifier - * @param function func - * @return void - */ - function addPropertyValidationValidator(validatorIdentifier, func) { - _getPropertyValidationService().addValidator(validatorIdentifier, func); - }; - - /** - * @public - * - * @param string propertyPath - * @return object - */ - function validateCurrentlySelectedFormElementProperty(propertyPath) { - return validateFormElementProperty( - getCurrentlySelectedFormElement(), - propertyPath - ); - }; - - /** - * @public - * - * @param object formElement - * @param string propertyPath - * @return object - */ - function validateFormElementProperty(formElement, propertyPath) { - formElement = _getRepository().findFormElement(formElement); - return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath); - }; - - /** - * @public - * - * @param object formElement - * @return object - */ - function validateFormElement(formElement) { - formElement = _getRepository().findFormElement(formElement); - return _getPropertyValidationService().validateFormElement(formElement); - }; - - /** - * @public - * - * @param object validationResults - * @return boolean - */ - function validationResultsHasErrors(validationResults) { - return _getPropertyValidationService().validationResultsHasErrors(validationResults); - }; - - /** - * @public - * - * @param object formElement - * @param boolean returnAfterFirstMatch - * @return object - */ - function validateFormElementRecursive(formElement, returnAfterFirstMatch) { - formElement = _getRepository().findFormElement(formElement); - return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch); - }; - - /** - * @public - * - * @param bool unsavedContent - * @return void - * @throws 1475378544 - */ - function setUnsavedContent(unsavedContent) { - assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544); - _unsavedContent = unsavedContent; - }; - - /** - * @public - * - * @return boolean - */ - function getUnsavedContent() { - return _unsavedContent; - }; - - /** - * @public - * - * @return object - */ - function getRootFormElement() { - return _getRepository().getRootFormElement(); - }; - - /** - * @public - * - * @return string - */ - function getCurrentlySelectedFormElement() { - return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')); - }; - - /** - * @public - * - * @param string|object formElement - * @param boolean doNotRefreshCurrentlySelectedPageIndex - * @return void - * @publish core/currentlySelectedFormElementChanged - */ - function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) { - doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex; - - formElement = _getRepository().findFormElement(formElement); - _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath')); - - if (!doNotRefreshCurrentlySelectedPageIndex) { - refreshCurrentlySelectedPageIndex(); - } - getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]); - }; - - /** - * @public - * - * @param string identifierPath - * @return object - * @throws 1475378545 - */ - function getFormElementByIdentifierPath(identifierPath) { - assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545); - return _getRepository().findFormElementByIdentifierPath(identifierPath); - }; - - /** - * @public - * - * @param string identifierPath - * @return bool - */ - function isFormElementIdentifierUsed(formElementIdentifier) { - return _getRepository().isFormElementIdentifierUsed(formElementIdentifier); - } - - /** - * @public - * - * @param string formElementType - * @param string|object referenceFormElement - * @param boolean disablePublishersOnSet - * @return object - */ - function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { - var formElement; - formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet); - formElement.set('renderables', formElement.get('renderables')); - return formElement; - }; - - /** - * @public - * - * @param object formElement - * @param string|object referenceFormElement - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475434337 - */ - function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) { - _saveApplicationState(); - - if (getUtility().isUndefinedOrNull(referenceFormElement)) { - referenceFormElement = getCurrentlySelectedFormElement(); - } - referenceFormElement = _getRepository().findFormElement(referenceFormElement); - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337); - return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet); - }; - - /** - * @public - * - * @param string formElementType - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475434336 - * @throws 1475435857 - */ - function createFormElement(formElementType, disablePublishersOnSet) { - var formElementDefinition, identifier; - assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336); - - identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType); - formElementDefinition = getFormElementDefinitionByType(formElementType); - return _getFactory().createFormElement({ - type: formElementType, - identifier: identifier, - label: formElementDefinition['label'] || formElementType - }, undefined, undefined, undefined, disablePublishersOnSet); - }; - - /** - * @public - * - * @param string|object formElementToRemove - * @param boolean disablePublishersOnSet - * @return object - */ - function removeFormElement(formElementToRemove, disablePublishersOnSet) { - var parentFormElement; - _saveApplicationState(); - - formElementToRemove = _getRepository().findFormElement(formElementToRemove); - parentFormElement = formElementToRemove.get('__parentRenderable'); - _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet); - return parentFormElement; - }; - - /** - * @public - * - * @param string|object formElementToMove - * @param string position - * @param string|object referenceFormElement - * @param boolean disablePublishersOnSet - * @return string - * @throws 1475378551 - */ - function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { - _saveApplicationState(); - - formElementToMove = _getRepository().findFormElement(formElementToMove); - referenceFormElement = _getRepository().findFormElement(referenceFormElement); - - assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551); - - formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true); - disablePublishersOnSet = !!disablePublishersOnSet; - if (!disablePublishersOnSet) { - formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables')); - } - return formElementToMove; - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param string formElement - * @return object (dereferenced) - * @throws 1475378555 - * @throws 1475378556 - * @throws 1475446108 - */ - function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) { - var collection, collectionElement, formElementDefinition; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - formElement = _getRepository().findFormElement(formElement); - - assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556); - - formElementDefinition = getFormElementDefinitionByType(formElement.get('type')); - if (!getUtility().isUndefinedOrNull(formElementDefinition['propertyCollections'])) { - collection = formElementDefinition['propertyCollections'][collectionName]; - assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108); - collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection); - return $.extend(true, {}, collectionElement); - } else { - return {}; - } - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param string formElement - * @return int - * @throws 1475378557 - * @throws 1475378558 - */ - function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) { - var indexFromPropertyCollectionElement; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - formElement = _getRepository().findFormElement(formElement); - - assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558); - - indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier( - collectionElementIdentifier, - collectionName, - formElement - ); - - return indexFromPropertyCollectionElement; - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @param object collectionElementConfiguration - * @param string referenceCollectionElementIdentifier - * @return object - */ - function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) { - return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier); - }; - - /** - * @public - * - * @param object collectionElement - * @param string collectionName - * @param string|object formElement - * @param string referenceCollectionElementIdentifier - * @return object - * @throws 1475443300 - * @throws 1475443301 - */ - function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) { - var collection; - _saveApplicationState(); - - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - formElement = _getRepository().findFormElement(formElement); - - assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300); - - if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { - collection = formElement.get(collectionName); - if ('array' === $.type(collection) && collection.length > 0) { - referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier']; - } - } - - return _getRepository().addPropertyCollectionElement( - collectionElement, - collectionName, - formElement, - referenceCollectionElementIdentifier, - false - ); - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object collectionElementConfiguration - * @return void - * @throws 1475378559 - * @throws 1475378560 - */ - function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) { - assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560); - if ('object' !== $.type(collectionElementConfiguration)) { - collectionElementConfiguration = {}; - } - - return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName); - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param string formElement - * @param bool disablePublishersOnSet - * @return void - * @throws 1475378561 - * @throws 1475378562 - */ - function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { - _saveApplicationState(); - - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - formElement = _getRepository().findFormElement(formElement); - - assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562); - - _getRepository().removePropertyCollectionElementByIdentifier( - formElement, - collectionElementIdentifier, - collectionName, - true - ); - - disablePublishersOnSet = !!disablePublishersOnSet; - if (!disablePublishersOnSet) { - getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']); - } - }; - - /** - * @public - * - * @param string collectionElementToMove - * @param string position - * @param string referenceCollectionElement - * @param string collectionName - * @param object formElement - * @param boolean disablePublishersOnSet - * @return string - * @throws 1477404352 - * @throws 1477404353 - * @throws 1477404354 - * @throws 1477404355 - */ - function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { - _saveApplicationState(); - - formElement = _getRepository().findFormElement(formElement); - - assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352); - assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353); - assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354); - assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355); - - return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet); - }; - - /** - * @public - * - * @param string elementType - * @param string formElementDefinitionKey - * @returnmixed - * @throws 1475378563 - */ - function getFormElementDefinitionByType(elementType, formElementDefinitionKey) { - var formElementDefinition; - assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563); - - formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType); - - if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) { - formElementDefinition = formElementDefinition[formElementDefinitionKey]; - } - - if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) { - return $.extend(true, {}, formElementDefinition); - } else { - return formElementDefinition; - } - }; - - /** - * @public - * - * @param object formElement - * @param string formElementDefinitionKey - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - formElement = _getRepository().findFormElement(formElement); - return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey); - }; - - /** - * @public - * - * @param string collectionName - * @param string collectionElementIdentifier - * @return mixed - */ - function getFormEditorDefinition(definitionName, subject) { - return _getRepository().getFormEditorDefinition(definitionName, subject); - }; - - /** - * @public - * - * @param string validatorIdentifier - * @return object (dereferenced) - * @throws 1475672362 - */ - function getFormElementPropertyValidatorDefinition(validatorIdentifier) { - var validatorDefinition; - assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362); - - validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier); - return $.extend(true, {}, validatorDefinition); - }; - - /** - * @public - * - * @return int - */ - function getCurrentlySelectedPageIndex() { - return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'); - }; - - /** - * @public - * - * @return void - */ - function refreshCurrentlySelectedPageIndex() { - _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement())); - }; - - /** - * @public - * - * @return object - * @throws 1477786068 - */ - function getCurrentlySelectedPage() { - var currentPage; - - currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()]; - assert('object' === $.type(currentPage), 'No page found', 1477786068); - return currentPage; - }; - - /** - * @public - * - * @return object - */ - function getLastTopLevelElementOnCurrentPage() { - var lastRenderable, renderables; - - renderables = getCurrentlySelectedPage().get('renderables'); - if (getUtility().isUndefinedOrNull(renderables)) { - return undefined; - } - lastRenderable = renderables[renderables.length - 1]; - return lastRenderable; - }; - - /** - * @public - * - * @param object - * @return object - */ - function getLastFormElementWithinParentFormElement(formElement) { - var lastElement; - - formElement = _getRepository().findFormElement(formElement); - if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { - return formElement; - } - return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1]; - }; - - /** - * @public - * - * @param object - * @return int - */ - function getPageIndexFromFormElement(formElement) { - formElement = _getRepository().findFormElement(formElement); - - return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement( - formElement - ); - }; - - /** - * @public - * - * @return void - */ - function renderCurrentFormPage() { - renderFormPage(getCurrentlySelectedPageIndex()); - }; - - /** - * @public - * - * @param int pageIndex - * @return void - * @throws 1475446442 - */ - function renderFormPage(pageIndex) { - assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442); - _getDataBackend().renderFormDefinitionPage(pageIndex); - }; - - /** - * @public - * - * @param object formElement - * @return object|null - */ - function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { - return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel( - _getRepository().findFormElement(formElement) - ); - }; - - /** - * @public - * - * @param object formElement - * @return object|null - */ - function findEnclosingGridContainerFormElement(formElement) { - return _getRepository().findEnclosingGridContainerFormElement( - _getRepository().findFormElement(formElement) - ); - }; - - /** - * @public - * - * @param object formElement - * @return object|null - */ - function findEnclosingGridRowFormElement(formElement) { - return _getRepository().findEnclosingGridRowFormElement( - _getRepository().findFormElement(formElement) - ); - }; - - /** - * @public - * - * @return object - */ - function getNonCompositeNonToplevelFormElements() { - return _getRepository().getNonCompositeNonToplevelFormElements(); - }; - - /** - * @public - * - * @return boolean - */ - function isRootFormElementSelected() { - return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath')); - }; - - /** - * @public - * - * @return object - */ - function getViewModel() { - return _viewModel; - }; - - /** - * @public - * - * @return void - */ - function saveFormDefinition() { - _getDataBackend().saveFormDefinition(); - }; - - /** - * @private - * - * @return object - */ - function _getDataBackend() { - return _core.getDataBackend(); - }; - - /** - * @private - * - * @return object - */ - function _getFactory() { - return _core.getFactory(); - }; - - /** - * @private - * - * @return object - */ - function _getRepository() { - return _core.getRepository(); - }; - - /** - * @private - * - * @return object - */ - function _getPropertyValidationService() { - return _core.getPropertyValidationService(); - }; - - /** - * @public - * - * @return object - */ - function _getApplicationStateStack() { - return _core.getApplicationStateStack(); - }; - - /** - * @private - * - * @return void - * @publish ajax/beforeSend - * @publish ajax/complete - */ - function _ajaxSetup() { - $.ajaxSetup({ - beforeSend: function() { - getPublisherSubscriber().publish('ajax/beforeSend'); - }, - complete: function() { - getPublisherSubscriber().publish('ajax/complete'); - } - }); - }; - - /** - * @private - * - * @param object endpoints - * @param string prototypeName - * @param string formPersistenceIdentifier - * @return void - * @throws 1475379748 - * @throws 1475379749 - * @throws 1475927876 - */ - function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) { - assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748); - assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876); - assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749); - - _core.getDataBackend().setEndpoints(endpoints); - _core.getDataBackend().setPrototypeName(prototypeName); - _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier); - }; - - /** - * @private - * - * @param object formEditorDefinitions - * @return void - * @throws 1475379750 - */ - function _repositorySetup(formEditorDefinitions) { - assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750); - - _getRepository().setFormEditorDefinitions(formEditorDefinitions); - } - - /** - * @private - * - * @param object additionalViewModelModules - * @return void - * @throws 1475379752 - * @throws 1475492374 - */ - function _viewSetup(additionalViewModelModules) { - assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374); - - if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) { - assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752); - } else { - additionalViewModelModules = []; - } - _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules); - }; - - /** - * @private - * - * @return void - * @throws 1475492032 - */ - function _mediatorSetup() { - assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032); - _mediator.bootstrap(_formEditorInstance, _viewModel); - }; - - /** - * @private - * - * @param object rootFormElement - * @param int maximumUndoSteps - * @return void - * @throws 1475379751 - */ - function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) { - assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751); - - if ('number' !== $.type(maximumUndoSteps)) { - maximumUndoSteps = 10; - } - _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps); - - _getApplicationStateStack().addAndReset({ - currentlySelectedPageIndex: 0, - currentlySelectedFormElementIdentifierPath: rootFormElement['identifier'] - }, true); - - _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true)); - }; - - /** - * @private - * - * @return void - */ - function _bootstrap() { - _configuration = _configuration || {}; - - _mediatorSetup(); - _ajaxSetup(); - _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']); - _repositorySetup(_configuration['formEditorDefinitions']); - _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']); - setCurrentlySelectedFormElement(_getRepository().getRootFormElement()); - - _viewSetup(_configuration['additionalViewModelModules']); - }; - - /** - * @public - * - * @return TYPO3/CMS/Form/Backend/FormEditor - * @throws 1473200696 - */ - function run() { - if (_isRunning) { - throw 'You can not run the app twice (1473200696)'; - } - - _bootstrap(); - _isRunning = true; - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - getRootFormElement: getRootFormElement, - - createAndAddFormElement: createAndAddFormElement, - createFormElement: createFormElement, - addFormElement: addFormElement, - moveFormElement: moveFormElement, - removeFormElement: removeFormElement, - - getCurrentlySelectedFormElement: getCurrentlySelectedFormElement, - setCurrentlySelectedFormElement: setCurrentlySelectedFormElement, - - getFormElementByIdentifierPath: getFormElementByIdentifierPath, - isFormElementIdentifierUsed: isFormElementIdentifierUsed, - - createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, - createPropertyCollectionElement: createPropertyCollectionElement, - addPropertyCollectionElement: addPropertyCollectionElement, - removePropertyCollectionElement: removePropertyCollectionElement, - movePropertyCollectionElement: movePropertyCollectionElement, - getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement, - getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration, - - saveFormDefinition: saveFormDefinition, - renderCurrentFormPage: renderCurrentFormPage, - renderFormPage: renderFormPage, - - getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex, - refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex, - getPageIndexFromFormElement: getPageIndexFromFormElement, - getCurrentlySelectedPage: getCurrentlySelectedPage, - getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage, - findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, - findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, - findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, - isRootFormElementSelected: isRootFormElementSelected, - getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement, - getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, - - getFormElementDefinitionByType: getFormElementDefinitionByType, - getFormElementDefinition: getFormElementDefinition, - getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition, - getFormEditorDefinition: getFormEditorDefinition, - - getPublisherSubscriber: getPublisherSubscriber, - getRunningAjaxRequest: getRunningAjaxRequest, - - setUnsavedContent: setUnsavedContent, - getUnsavedContent: getUnsavedContent, - - addPropertyValidationValidator: addPropertyValidationValidator, - validateFormElementProperty: validateFormElementProperty, - validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty, - validateFormElement: validateFormElement, - validateFormElementRecursive: validateFormElementRecursive, - validationResultsHasErrors: validationResultsHasErrors, - - getUtility: getUtility, - assert: assert, - buildPropertyPath: buildPropertyPath, - - getViewModel: getViewModel, - undoApplicationState: undoApplicationState, - redoApplicationState: redoApplicationState, - getMaximalApplicationStates: getMaximalApplicationStates, - getCurrentApplicationStates: getCurrentApplicationStates, - getCurrentApplicationStatePosition: getCurrentApplicationStatePosition, - - run: run - }; - }; - - /** - * Emulation of static methods - */ - return { - /** - * @public - * @static - * - * Implement the "Singleton Pattern". - * - * Return a singleton instance of a - * "FormEditor" object. - * - * @param object configuration - * @param object mediator - * @param object viewModel - * @return object - */ - getInstance: function(configuration, mediator, viewModel) { - if(_formEditorInstance === null) { - _formEditorInstance = new FormEditor(configuration, mediator, viewModel); - } - return _formEditorInstance; - } - }; - })(core); + return { + /** + * @public + * @static + * + * Implement the "Singleton Pattern". + * + * Return a singleton instance of a + * "FormEditor" object. + * + * @param object configuration + * @param object mediator + * @param object viewModel + * @return object + */ + getInstance: function(configuration, mediator, viewModel) { + if (_formEditorInstance === null) { + _formEditorInstance = new FormEditor(configuration, mediator, viewModel); + } + return _formEditorInstance; + } + }; + })(core); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js index b135e577d524dfeb936b2984c5ad10fbff45dce1..965fe93ce52562bd1e22fe3881647d94bbd30721 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js @@ -15,1739 +15,923 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/Core */ define(['jquery'], function($) { - 'use strict'; - - return (function($) { - - /** - * @private - * - * @var object - */ - var _dataBackendEndpoints = {}; - - /** - * @private - * - * @var string - */ - var _dataBackendPrototypeName = null; - - /** - * @private - * - * @var string - */ - var _dataBackendPersistenceIdentifier = null; - - /** - * @private - * - * @var object - */ - var _publisherSubscriberTopics = {}; - - /** - * @private - * - * @var int - */ - var _publisherSubscriberUid = -1; + 'use strict'; + + return (function($) { + + /** + * @private + * + * @var object + */ + var _dataBackendEndpoints = {}; + + /** + * @private + * + * @var string + */ + var _dataBackendPrototypeName = null; + + /** + * @private + * + * @var string + */ + var _dataBackendPersistenceIdentifier = null; + + /** + * @private + * + * @var object + */ + var _publisherSubscriberTopics = {}; + + /** + * @private + * + * @var int + */ + var _publisherSubscriberUid = -1; + + /** + * @private + * + * @var object + */ + var _repositoryFormEditorDefinitions = {}; + + /** + * @private + * + * @var object + */ + var _runningAjaxRequests = []; + + /** + * @private + * + * @var object + */ + var _propertyValidationServiceValidators = {}; + + /** + * @private + * + * @var int + */ + var _applicationStateStackSize = 10; + + /** + * @private + * + * @var int + */ + var _applicationStateStackPointer = 0; + + /** + * @private + * + * @var object + */ + var _applicationStateStack = []; + + /** + * @public + * + * @return object + */ + function utility() { + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + if ('function' === $.type(test)) { + test = (test() !== false); + } + if (!test) { + message = message || "Assertion failed"; + if (messageCode) { + message = message + ' (' + messageCode + ')'; + } + if ('undefined' !== typeof Error) { + throw new Error(message); + } + throw message; + } + }; + + /** + * @public + * + * @param mixed value + * @return bool + */ + function isUndefinedOrNull(value) { + return ('undefined' === $.type(value) || 'null' === $.type(value)); + }; + + /** + * @public + * + * @param mixed value + * @return bool + */ + function isNonEmptyString(value) { + return ('string' === $.type(value) && value.length > 0); + }; + + /** + * @public + * + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param boolean allowEmptyReturnValue + * @return string + * @throws 1475412569 + * @throws 1475412570 + * @throws 1475415988 + * @throws 1475663210 + */ + function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { + var newPropertyPath = ''; + + allowEmptyReturnValue = !!allowEmptyReturnValue; + if (isNonEmptyString(collectionElementIdentifier) || isNonEmptyString(collectionName)) { + assert(isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475412569); + assert(isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475412570); + newPropertyPath = collectionName + '.' + repository().getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); + } else { + newPropertyPath = ''; + } + + if (!isUndefinedOrNull(propertyPath)) { + assert(isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475415988); + if (isNonEmptyString(newPropertyPath)) { + newPropertyPath = newPropertyPath + '.' + propertyPath; + } else { + newPropertyPath = propertyPath; + } + } + + if (!allowEmptyReturnValue) { + assert(isNonEmptyString(newPropertyPath), 'The property path could not be resolved', 1475663210); + } + return newPropertyPath; + }; + + /** + * @public + * + * @param object formElement + * @return object + * @throws 1475377782 + */ + function convertToSimpleObject(formElement) { + var childFormElements, simpleObject, objectData; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475377782); + + simpleObject = {}; + objectData = ('function' === $.type(formElement.getObjectData)) ? formElement.getObjectData() : formElement; + childFormElements = objectData['renderables']; + delete objectData['renderables']; + + for (var key in objectData) { + if (!objectData.hasOwnProperty(key)) { + continue; + } + var value = objectData[key]; + if (key.match(/^__/)) { + continue; + } + + if ('object' === $.type(value)) { + simpleObject[key] = convertToSimpleObject(value); + } else if ('function' !== $.type(value) && 'undefined' !== $.type(value)) { + simpleObject[key] = value; + } + } + + if ('array' === $.type(childFormElements)) { + simpleObject['renderables'] = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + simpleObject['renderables'].push(convertToSimpleObject(childFormElements[i])); + } + } + + return simpleObject; + }; + + /** + * Publish the public methods. + */ + return { + assert: assert, + convertToSimpleObject: convertToSimpleObject, + isNonEmptyString: isNonEmptyString, + isUndefinedOrNull: isUndefinedOrNull, + buildPropertyPath: buildPropertyPath + }; + }; + + /** + * @public + * + * @return object + */ + function propertyValidationService() { + + /** + * @public + * + * @param object formElement + * @param object validators + * @param string propertyPath + * @param string collectionElementIdentifier + * @param string collectionName + * @param object configuration + * @return void + * @throws 1475661025 + * @throws 1475661026 + * @throws 1479238074 + */ + function addValidatorIdentifiersToFormElementProperty(formElement, validators, propertyPath, collectionElementIdentifier, collectionName, configuration) { + var formElementIdentifierPath, propertyPath, propertyValidationServiceRegisteredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475661025); + utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1475661026); + utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1479238074); + + formElementIdentifierPath = formElement.get('__identifierPath'); + propertyPath = utility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement); + + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = {}; + } + if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath] = { + validators: [], + configuration: configuration + }; + } + for (var i = 0, len = validators.length; i < len; ++i) { + if (propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].indexOf(validators[i]) === -1) { + propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].push(validators[i]); + } + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @return void + * @throws 1475700618 + * @throws 1475706896 + */ + function removeValidatorIdentifiersFromFormElementProperty(formElement, propertyPath) { + var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, + registeredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475700618); + utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475706896); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + registeredValidators = {}; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { + if ( + !propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath) + || registeredPropertyPath.indexOf(propertyPath) > -1 + ) { + continue; + } + registeredValidators[registeredPropertyPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][registeredPropertyPath]; + } + propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = registeredValidators; + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + }; + + /** + * @public + * + * @param string|object formElement + * @return void + * @throws 1475668189 + */ + function removeAllValidatorIdentifiersFromFormElement(formElement) { + var propertyValidationServiceRegisteredValidators, registeredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475668189); + + registeredValidators = {}; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + for (var formElementIdentifierPath in propertyValidationServiceRegisteredValidators) { + if ( + !propertyValidationServiceRegisteredValidators.hasOwnProperty(formElementIdentifierPath) + || formElementIdentifierPath === formElement.get('__identifierPath') + || formElementIdentifierPath.indexOf(formElement.get('__identifierPath') + '/') > -1 + ) { + continue; + } + registeredValidators[formElementIdentifierPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath]; + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', registeredValidators); + }; + + /** + * @public + * + * @param string validatorIdentifier + * @param function func + * @return void + * @throws 1475669143 + * @throws 1475669144 + * @throws 1475669145 + */ + function addValidator(validatorIdentifier, func) { + utility().assert(utility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475669143); + utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475669144); + utility().assert('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier]), 'The validator "' + validatorIdentifier + '" is already registered', 1475669145); + + _propertyValidationServiceValidators[validatorIdentifier] = func; + }; + + /** + * @public + * + * @param object formElement + * @param string propertyPath + * @param string errorMessage + * @return object + * @throws 1475676517 + * @throws 1475676518 + */ + function validateFormElementProperty(formElement, propertyPath) { + var configuration, formElementIdentifierPath, propertyValidationServiceRegisteredValidators, + validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475676517); + utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475676518); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + validationResults = []; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + configuration = { + propertyValidatorsMode: 'AND' + }; - /** - * @private - * - * @var object - */ - var _repositoryFormEditorDefinitions = {}; + if ( + !utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) + && 'object' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]) + && 'array' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators']) + ) { + configuration = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['configuration']; + for (var i = 0, len = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length; i < len; ++i) { + var validatorIdentifier, validationResult; + + validatorIdentifier = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'][i]; + if ('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier])) { + continue; + } + validationResult = _propertyValidationServiceValidators[validatorIdentifier](formElement, propertyPath); - /** - * @private - * - * @var object - */ - var _runningAjaxRequests = []; + if (utility().isNonEmptyString(validationResult)) { + validationResults.push(validationResult); + } + } + } + + if ( + validationResults.length > 0 + && configuration['propertyValidatorsMode'] === 'OR' + && validationResults.length !== propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length + ) { + return []; + } + + return validationResults; + }; + + /** + * @public + * + * @param object formElement + * @return object + * @throws 1475749668 + */ + function validateFormElement(formElement) { + var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, + validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475749668); + + formElementIdentifierPath = formElement.get('__identifierPath'); + + validationResults = []; + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { + for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { + var validationResult; + if (!propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)) { + continue; + } + validationResult = { + propertyPath: registeredPropertyPath, + validationResults: validateFormElementProperty(formElement, registeredPropertyPath) + }; + validationResults.push(validationResult); + } + } + return validationResults; + }; + + /** + * @public + * + * @param array validationResults + * @return bool + * @throws 1478613477 + */ + function validationResultsHasErrors(validationResults) { + utility().assert('array' === $.type(validationResults), 'Invalid parameter "validationResults"', 1478613477); + + for (var i = 0, len = validationResults.length; i < len; ++i) { + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + return true; + } + } + } + return false; + }; + + /** + * @public + * + * @param object formElement + * @param boolean returnAfterFirstMatch + * @param object validationResults + * @return object + * @throws 1475749668 + */ + function validateFormElementRecursive(formElement, returnAfterFirstMatch, validationResults) { + var formElements, validationResult, validationResults; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475756764); + returnAfterFirstMatch = !!returnAfterFirstMatch; + + validationResults = validationResults || []; + validationResult = { + formElementIdentifierPath: formElement.get('__identifierPath'), + validationResults: validateFormElement(formElement) + }; + validationResults.push(validationResult); + + if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { + return validationResults; + } + + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + validateFormElementRecursive(formElements[i], returnAfterFirstMatch, validationResults); + if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { + return validationResults; + } + } + } + + return validationResults; + } + + /** + * @public + * + * @param object formElement + * @return void + * @throws 1475707334 + */ + function addValidatorIdentifiersFromFormElementPropertyCollections(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475707334); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + + if (!utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'])) { + for (var collectionName in formElementTypeDefinition['propertyCollections']) { + if ( + !formElementTypeDefinition['propertyCollections'].hasOwnProperty(collectionName) + || 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName]) + ) { + continue; + } + for (var i = 0, len1 = formElementTypeDefinition['propertyCollections'][collectionName].length; i < len1; ++i) { + if ( + 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors']) + || repository().getIndexFromPropertyCollectionElementByIdentifier(formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], collectionName, formElement) === -1 + ) { + continue; + } + for (var j = 0, len2 = formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'].length; j < len2; ++j) { + var configuration = {}; - /** - * @private - * - * @var object - */ - var _propertyValidationServiceValidators = {}; + if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) { + continue; + } - /** - * @private - * - * @var int - */ - var _applicationStateStackSize = 10; + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode']) + && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'], + formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyPath'], + formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], + collectionName, + configuration + ); + } + } + } + } + }; + + /** + * Publish the public methods. + */ + return { + addValidatorIdentifiersToFormElementProperty: addValidatorIdentifiersToFormElementProperty, + removeValidatorIdentifiersFromFormElementProperty: removeValidatorIdentifiersFromFormElementProperty, + removeAllValidatorIdentifiersFromFormElement: removeAllValidatorIdentifiersFromFormElement, + validateFormElementProperty: validateFormElementProperty, + validateFormElement: validateFormElement, + validateFormElementRecursive: validateFormElementRecursive, + validationResultsHasErrors: validationResultsHasErrors, + addValidator: addValidator, + addValidatorIdentifiersFromFormElementPropertyCollections: addValidatorIdentifiersFromFormElementPropertyCollections + }; + }; + + /** + * @public + * + * @param string ajaxRequestIdentifier + * @return object|null + * @throws 1475358064 + */ + function getRunningAjaxRequest(ajaxRequestIdentifier) { + utility().assert(utility().isNonEmptyString(ajaxRequestIdentifier), 'Invalid parameter "ajaxRequestIdentifier"', 1475358064); + return _runningAjaxRequests[ajaxRequestIdentifier] || null; + }; + + /** + * @public + * + * Implements the "Publish/Subscribe Pattern" + * + * @return object + * @credits Addy Osmani https://addyosmani.com/resources/essentialjsdesignpatterns/book/#highlighter_634280 + */ + function publisherSubscriber() { + + /** + * @public + * + * @param string topic + * @param mixed args + * @return void + * @throws 1475358066 + */ + function publish(topic, args) { + utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358066); + if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { + return; + } + + for (var i = 0, len = _publisherSubscriberTopics[topic].length; i < len; ++i) { + _publisherSubscriberTopics[topic][i].func(topic, args); + } + }; + + /** + * @public + * + * @param string topic + * @param function func + * @return string + * @throws 1475358067 + */ + function subscribe(topic, func) { + utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358067); + utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475411986); + + if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { + _publisherSubscriberTopics[topic] = []; + } + + var token = (++_publisherSubscriberUid).toString(); + _publisherSubscriberTopics[topic].push({ + token: token, + func: func + }); + return token; + }; + + /** + * @public + * + * @param string token + * @return null|string + * @throws 1475358068 + */ + function unsubscribe(token) { + utility().assert(utility().isNonEmptyString(token), 'Invalid parameter "token"', 1475358068); + + for (var key in _publisherSubscriberTopics) { + if (!_publisherSubscriberTopics.hasOwnProperty(key)) { + continue; + } + for (var i = 0, len = _publisherSubscriberTopics[key].length; i < len; ++i) { + if (_publisherSubscriberTopics[key][i].token === token) { + _publisherSubscriberTopics[key].splice(i, 1); + return token; + } + } + } + return null; + }; + + /** + * Publish the public methods. + */ + return { + publish: publish, + subscribe: subscribe, + unsubscribe: unsubscribe + }; + }; + + /** + * @private + * + * @param object modelToExtend + * @param object modelExtension + * @param string pathPrefix + * @return void + * @throws 1474640022 + * @throws 1475358069 + * @throws 1475358070 + * @publish core/formElement/somePropertyChanged + */ + function extendModel(modelToExtend, modelExtension, pathPrefix, disablePublishersOnSet) { + utility().assert('object' === $.type(modelToExtend), 'Invalid parameter "modelToExtend"', 1475358069); + utility().assert('object' === $.type(modelExtension) || 'array' === $.type(modelExtension), 'Invalid parameter "modelExtension"', 1475358070); + + disablePublishersOnSet = !!disablePublishersOnSet; + pathPrefix = pathPrefix || ''; + + if ($.isEmptyObject(modelExtension)) { + utility().assert('' !== pathPrefix, 'Empty path is not allowed', 1474640022); + modelToExtend.on(pathPrefix, 'core/formElement/somePropertyChanged'); + modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet); + } else { + for (var key in modelExtension) { + if (!modelExtension.hasOwnProperty(key)) { + continue; + } + var path = (pathPrefix === '') ? key : pathPrefix + '.' + key; + + modelToExtend.on(path, 'core/formElement/somePropertyChanged'); + + if ('object' === $.type(modelExtension[key]) || 'array' === $.type(modelExtension[key])) { + extendModel(modelToExtend, modelExtension[key], path, disablePublishersOnSet); + } else if (pathPrefix === 'properties.options') { + modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet); + } else { + modelToExtend.set(path, modelExtension[key], disablePublishersOnSet); + } + } + } + }; + + /** + * @private + * + * @param object modelExtension + * @return object + */ + function createModel(modelExtension) { + var newModel; + + modelExtension = modelExtension || {}; + + function M() { /** * @private - * - * @var int */ - var _applicationStateStackPointer = 0; + var _objectData = {}; /** * @private - * - * @var object */ - var _applicationStateStack = []; + var _publisherTopics = {}; /** * @public * - * @return object + * @param string key + * @return mixed|undefined + * @throws 1475361755 */ - function utility() { - - /** - * @public - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - if ('function' === $.type(test)) { - test = (test() !== false); - } - if (!test) { - message = message || "Assertion failed"; - if (messageCode) { - message = message + ' (' + messageCode + ')'; - } - if ('undefined' !== typeof Error) { - throw new Error(message); - } - throw message; - } - }; - - /** - * @public - * - * @param mixed value - * @return bool - */ - function isUndefinedOrNull(value) { - return ('undefined' === $.type(value) || 'null' === $.type(value)); - }; - - /** - * @public - * - * @param mixed value - * @return bool - */ - function isNonEmptyString(value) { - return ('string' === $.type(value) && value.length > 0); - }; - - /** - * @public - * - * @param string propertyPath - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @param boolean allowEmptyReturnValue - * @return string - * @throws 1475412569 - * @throws 1475412570 - * @throws 1475415988 - * @throws 1475663210 - */ - function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) { - var newPropertyPath = ''; - - allowEmptyReturnValue = !!allowEmptyReturnValue; - if (isNonEmptyString(collectionElementIdentifier) || isNonEmptyString(collectionName)) { - assert(isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475412569); - assert(isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475412570); - newPropertyPath = collectionName + '.' + repository().getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); - } else { - newPropertyPath = ''; - } - - if (!isUndefinedOrNull(propertyPath)) { - assert(isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475415988); - if (isNonEmptyString(newPropertyPath)) { - newPropertyPath = newPropertyPath + '.' + propertyPath; - } else { - newPropertyPath = propertyPath; - } - } - - if (!allowEmptyReturnValue) { - assert(isNonEmptyString(newPropertyPath), 'The property path could not be resolved', 1475663210); - } - return newPropertyPath; - }; - - /** - * @public - * - * @param object formElement - * @return object - * @throws 1475377782 - */ - function convertToSimpleObject(formElement) { - var childFormElements, simpleObject, objectData; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475377782); - - simpleObject = {}; - objectData = ('function' === $.type(formElement.getObjectData)) ? formElement.getObjectData() : formElement; - childFormElements = objectData['renderables']; - delete objectData['renderables']; - - for (var key in objectData) { - if (!objectData.hasOwnProperty(key)) { - continue; - } - var value = objectData[key]; - if (key.match(/^__/)) { - continue; - } - - if ('object' === $.type(value)) { - simpleObject[key] = convertToSimpleObject(value); - } else if ('function' !== $.type(value) && 'undefined' !== $.type(value)) { - simpleObject[key] = value; - } - } - - if ('array' === $.type(childFormElements)) { - simpleObject['renderables'] = []; - for (var i = 0, len = childFormElements.length; i < len; ++i) { - simpleObject['renderables'].push(convertToSimpleObject(childFormElements[i])); - } - } - - return simpleObject; - }; + function get(key) { + var firstPartOfPath, obj; + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361755); + + obj = _objectData; + while (key.indexOf('.') > 0) { + firstPartOfPath = key.slice(0, key.indexOf('.')); + key = key.slice(firstPartOfPath.length + 1); + if (!obj.hasOwnProperty(firstPartOfPath)) { + return undefined; + } + obj = obj[firstPartOfPath]; + } - /** - * Publish the public methods. - */ - return { - assert: assert, - convertToSimpleObject: convertToSimpleObject, - isNonEmptyString: isNonEmptyString, - isUndefinedOrNull: isUndefinedOrNull, - buildPropertyPath: buildPropertyPath - }; + return obj[key]; }; /** * @public * - * @return object + * @param string key + * @param mixed value + * @param bool disablePublishersOnSet + * @return void + * @throws 1475361756 + * @publish mixed */ - function propertyValidationService() { - - /** - * @public - * - * @param object formElement - * @param object validators - * @param string propertyPath - * @param string collectionElementIdentifier - * @param string collectionName - * @param object configuration - * @return void - * @throws 1475661025 - * @throws 1475661026 - * @throws 1479238074 - */ - function addValidatorIdentifiersToFormElementProperty(formElement, validators, propertyPath, collectionElementIdentifier, collectionName, configuration) { - var formElementIdentifierPath, propertyPath, propertyValidationServiceRegisteredValidators; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475661025); - utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1475661026); - utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1479238074); - - formElementIdentifierPath = formElement.get('__identifierPath'); - propertyPath = utility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement); - - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { - propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = {}; - } - if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])) { - propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath] = { - validators: [], - configuration: configuration - }; - } - for (var i = 0, len = validators.length; i < len; ++i) { - if (propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].indexOf(validators[i]) === -1) { - propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].push(validators[i]); - } - } - getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); - }; - - /** - * @public - * - * @param object formElement - * @param string propertyPath - * @return void - * @throws 1475700618 - * @throws 1475706896 - */ - function removeValidatorIdentifiersFromFormElementProperty(formElement, propertyPath) { - var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, registeredValidators; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475700618); - utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475706896); - - formElementIdentifierPath = formElement.get('__identifierPath'); - - registeredValidators = {}; - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { - if ( - !propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath) - || registeredPropertyPath.indexOf(propertyPath) > -1 - ) { - continue; - } - registeredValidators[registeredPropertyPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][registeredPropertyPath]; - } - propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = registeredValidators; - getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); - }; - - /** - * @public - * - * @param string|object formElement - * @return void - * @throws 1475668189 - */ - function removeAllValidatorIdentifiersFromFormElement(formElement) { - var propertyValidationServiceRegisteredValidators, registeredValidators; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475668189); - - registeredValidators = {}; - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - for (var formElementIdentifierPath in propertyValidationServiceRegisteredValidators) { - if ( - !propertyValidationServiceRegisteredValidators.hasOwnProperty(formElementIdentifierPath) - || formElementIdentifierPath === formElement.get('__identifierPath') - || formElementIdentifierPath.indexOf(formElement.get('__identifierPath') + '/') > -1 - ) { - continue; - } - registeredValidators[formElementIdentifierPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath]; - } - getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', registeredValidators); - }; - - /** - * @public - * - * @param string validatorIdentifier - * @param function func - * @return void - * @throws 1475669143 - * @throws 1475669144 - * @throws 1475669145 - */ - function addValidator(validatorIdentifier, func) { - utility().assert(utility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475669143); - utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475669144); - utility().assert('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier]), 'The validator "' + validatorIdentifier + '" is already registered', 1475669145); - - _propertyValidationServiceValidators[validatorIdentifier] = func; - }; - - /** - * @public - * - * @param object formElement - * @param string propertyPath - * @param string errorMessage - * @return object - * @throws 1475676517 - * @throws 1475676518 - */ - function validateFormElementProperty(formElement, propertyPath) { - var configuration, formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475676517); - utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475676518); - - formElementIdentifierPath = formElement.get('__identifierPath'); - - validationResults = []; - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - configuration = { - propertyValidatorsMode: 'AND' - }; - - if ( - !utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) - && 'object' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]) - && 'array' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators']) - ) { - configuration = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['configuration']; - for (var i = 0, len = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length; i < len; ++i) { - var validatorIdentifier, validationResult; - - validatorIdentifier = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'][i]; - if ('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier])) { - continue; - } - validationResult = _propertyValidationServiceValidators[validatorIdentifier](formElement, propertyPath); - - if (utility().isNonEmptyString(validationResult)) { - validationResults.push(validationResult); - } - } - } - - if ( - validationResults.length > 0 - && configuration['propertyValidatorsMode'] === 'OR' - && validationResults.length !== propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length - ) { - return []; - } - - return validationResults; - }; - - /** - * @public - * - * @param object formElement - * @return object - * @throws 1475749668 - */ - function validateFormElement(formElement) { - var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475749668); - - formElementIdentifierPath = formElement.get('__identifierPath'); - - validationResults = []; - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) { - for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) { - var validationResult; - if (!propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)) { - continue; - } - validationResult = { - propertyPath: registeredPropertyPath, - validationResults: validateFormElementProperty(formElement, registeredPropertyPath) - }; - validationResults.push(validationResult); - } - } - return validationResults; - }; - - /** - * @public - * - * @param array validationResults - * @return bool - * @throws 1478613477 - */ - function validationResultsHasErrors(validationResults) { - utility().assert('array' === $.type(validationResults), 'Invalid parameter "validationResults"', 1478613477); - - for (var i = 0, len = validationResults.length; i < len; ++i) { - for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { - if ( - validationResults[i]['validationResults'][j]['validationResults'] - && validationResults[i]['validationResults'][j]['validationResults'].length > 0 - ) { - return true; - } - } - } - return false; - }; - - /** - * @public - * - * @param object formElement - * @param boolean returnAfterFirstMatch - * @param object validationResults - * @return object - * @throws 1475749668 - */ - function validateFormElementRecursive(formElement, returnAfterFirstMatch, validationResults) { - var formElements, validationResult, validationResults; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475756764); - returnAfterFirstMatch = !!returnAfterFirstMatch; - - validationResults = validationResults || []; - validationResult = { - formElementIdentifierPath: formElement.get('__identifierPath'), - validationResults: validateFormElement(formElement) - }; - validationResults.push(validationResult); - - if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { - return validationResults; - } - - formElements = formElement.get('renderables'); - if ('array' === $.type(formElements)) { - for (var i = 0, len = formElements.length; i < len; ++i) { - validateFormElementRecursive(formElements[i], returnAfterFirstMatch, validationResults); - if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) { - return validationResults; - } - } - } - - return validationResults; + function set(key, value, disablePublishersOnSet) { + var obj, oldValue, path; + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361756); + disablePublishersOnSet = !!disablePublishersOnSet; + + oldValue = get(key); + obj = _objectData; + path = key; + + while (path.indexOf('.') > 0) { + var firstPartOfPath, nextPartOfPath; + + firstPartOfPath = path.slice(0, path.indexOf('.')); + path = path.slice(firstPartOfPath.length + 1); + if ($.isNumeric(firstPartOfPath)) { + firstPartOfPath = parseInt(firstPartOfPath); } + if ('undefined' === $.type(obj[firstPartOfPath])) { + nextPartOfPath = path.slice(0, path.indexOf('.')); + if ($.isNumeric(nextPartOfPath)) { + obj[firstPartOfPath] = []; + } else { + obj[firstPartOfPath] = {}; + } + } + obj = obj[firstPartOfPath]; + } + obj[path] = value; - /** - * @public - * - * @param object formElement - * @return void - * @throws 1475707334 - */ - function addValidatorIdentifiersFromFormElementPropertyCollections(formElement) { - var formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475707334); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - - if (!utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'])) { - for (var collectionName in formElementTypeDefinition['propertyCollections']) { - if ( - !formElementTypeDefinition['propertyCollections'].hasOwnProperty(collectionName) - || 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName]) - ) { - continue; - } - for (var i = 0, len1 = formElementTypeDefinition['propertyCollections'][collectionName].length; i < len1; ++i) { - if ( - 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors']) - || repository().getIndexFromPropertyCollectionElementByIdentifier(formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], collectionName, formElement) === -1 - ) { - continue; - } - for (var j = 0, len2 = formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'].length; j < len2; ++j) { - var configuration = {}; - - if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) { - continue; - } - - if ( - !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode']) - && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR' - ) { - configuration['propertyValidatorsMode'] = 'OR'; - } else { - configuration['propertyValidatorsMode'] = 'AND'; - } - addValidatorIdentifiersToFormElementProperty( - formElement, - formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'], - formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyPath'], - formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], - collectionName, - configuration - ); - } - } - } - } - }; - - /** - * Publish the public methods. - */ - return { - addValidatorIdentifiersToFormElementProperty: addValidatorIdentifiersToFormElementProperty, - removeValidatorIdentifiersFromFormElementProperty: removeValidatorIdentifiersFromFormElementProperty, - removeAllValidatorIdentifiersFromFormElement: removeAllValidatorIdentifiersFromFormElement, - validateFormElementProperty: validateFormElementProperty, - validateFormElement: validateFormElement, - validateFormElementRecursive: validateFormElementRecursive, - validationResultsHasErrors: validationResultsHasErrors, - addValidator: addValidator, - addValidatorIdentifiersFromFormElementPropertyCollections: addValidatorIdentifiersFromFormElementPropertyCollections - }; + if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) { + for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) { + publisherSubscriber().publish(_publisherTopics[key][i], [key, value, oldValue, _objectData['__identifierPath']]); + } + } }; /** * @public * - * @param string ajaxRequestIdentifier - * @return object|null - * @throws 1475358064 + * @param string key + * @param bool disablePublishersOnSet + * @return void + * @throws 1489321637 + * @throws 1489319753 + * @publish mixed */ - function getRunningAjaxRequest(ajaxRequestIdentifier) { - utility().assert(utility().isNonEmptyString(ajaxRequestIdentifier), 'Invalid parameter "ajaxRequestIdentifier"', 1475358064); - return _runningAjaxRequests[ajaxRequestIdentifier] || null; + function unset(key, disablePublishersOnSet) { + var obj, oldValue, parentPropertyData, parentPropertyPath, propertyToRemove; + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1489321637); + disablePublishersOnSet = !!disablePublishersOnSet; + + oldValue = get(key); + + if (key.indexOf('.') > 0) { + parentPropertyPath = key.split('.'); + propertyToRemove = parentPropertyPath.pop(); + parentPropertyPath = parentPropertyPath.join('.'); + parentPropertyData = get(parentPropertyPath); + delete parentPropertyData[propertyToRemove]; + } else { + assert(false, 'remove toplevel properties is not supported', 1489319753); + } + + if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) { + for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) { + publisherSubscriber().publish(_publisherTopics[key][i], [key, undefined, oldValue, _objectData['__identifierPath']]); + } + } }; /** * @public * - * Implements the "Publish/Subscribe Pattern" - * - * @return object - * @credits Addy Osmani https://addyosmani.com/resources/essentialjsdesignpatterns/book/#highlighter_634280 + * @param string key + * @param string topicName + * @return void + * @throws 1475361757 + * @throws 1475361758 */ - function publisherSubscriber() { - - /** - * @public - * - * @param string topic - * @param mixed args - * @return void - * @throws 1475358066 - */ - function publish(topic, args) { - utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358066); - if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { - return; - } - - for (var i = 0, len = _publisherSubscriberTopics[topic].length; i < len; ++i) { - _publisherSubscriberTopics[topic][i].func(topic, args); - } - }; - - /** - * @public - * - * @param string topic - * @param function func - * @return string - * @throws 1475358067 - */ - function subscribe(topic, func) { - utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358067); - utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475411986); - - if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) { - _publisherSubscriberTopics[topic] = []; - } - - var token = (++_publisherSubscriberUid).toString(); - _publisherSubscriberTopics[topic].push({ - token: token, - func: func - }); - return token; - }; - - /** - * @public - * - * @param string token - * @return null|string - * @throws 1475358068 - */ - function unsubscribe(token) { - utility().assert(utility().isNonEmptyString(token), 'Invalid parameter "token"', 1475358068); - - for (var key in _publisherSubscriberTopics) { - if (!_publisherSubscriberTopics.hasOwnProperty(key)) { - continue; - } - for (var i = 0, len = _publisherSubscriberTopics[key].length; i < len; ++i) { - if (_publisherSubscriberTopics[key][i].token === token) { - _publisherSubscriberTopics[key].splice(i, 1); - return token; - } - } - } - return null; - }; - - /** - * Publish the public methods. - */ - return { - publish: publish, - subscribe: subscribe, - unsubscribe: unsubscribe - }; + function on(key, topicName) { + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361757); + utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361758); + + if ('array' !== $.type(_publisherTopics[key])) { + _publisherTopics[key] = []; + } + if (_publisherTopics[key].indexOf(topicName) === -1) { + _publisherTopics[key].push(topicName); + } }; /** - * @private + * @public * - * @param object modelToExtend - * @param object modelExtension - * @param string pathPrefix + * @param string key + * @param string topicName * @return void - * @throws 1474640022 - * @throws 1475358069 - * @throws 1475358070 - * @publish core/formElement/somePropertyChanged + * @throws 1475361759 + * @throws 1475361760 */ - function extendModel(modelToExtend, modelExtension, pathPrefix, disablePublishersOnSet) { - utility().assert('object' === $.type(modelToExtend), 'Invalid parameter "modelToExtend"', 1475358069); - utility().assert('object' === $.type(modelExtension) || 'array' === $.type(modelExtension), 'Invalid parameter "modelExtension"', 1475358070); - - disablePublishersOnSet = !!disablePublishersOnSet; - pathPrefix = pathPrefix || ''; - - if ($.isEmptyObject(modelExtension)) { - utility().assert('' !== pathPrefix, 'Empty path is not allowed', 1474640022); - modelToExtend.on(pathPrefix, 'core/formElement/somePropertyChanged'); - modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet); - } else { - for (var key in modelExtension) { - if (!modelExtension.hasOwnProperty(key)) { - continue; - } - var path = (pathPrefix === '') ? key : pathPrefix + '.' + key; - - modelToExtend.on(path, 'core/formElement/somePropertyChanged'); - - if ('object' === $.type(modelExtension[key]) || 'array' === $.type(modelExtension[key])) { - extendModel(modelToExtend, modelExtension[key], path, disablePublishersOnSet); - } else if (pathPrefix === 'properties.options') { - modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet); - } else { - modelToExtend.set(path, modelExtension[key], disablePublishersOnSet); - } - } - } + function off(key, topicName) { + utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361759); + utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361760); + + if ('array' === $.type(_publisherTopics[key])) { + _publisherTopics[key] = _publisherTopics[key].filter(function(topicName) { + return topicName !== topicName; + }); + } }; /** - * @private + * @public * - * @param object modelExtension - * @return object + * @return object (dereferenced) */ - function createModel(modelExtension) { - var newModel; - - modelExtension = modelExtension || {}; - - function M() { - - /** - * @private - */ - var _objectData = {}; - - /** - * @private - */ - var _publisherTopics = {}; - - /** - * @public - * - * @param string key - * @return mixed|undefined - * @throws 1475361755 - */ - function get(key) { - var firstPartOfPath, obj; - utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361755); - - obj = _objectData; - while (key.indexOf('.') > 0) { - firstPartOfPath = key.slice(0, key.indexOf('.')); - key = key.slice(firstPartOfPath.length + 1); - if (!obj.hasOwnProperty(firstPartOfPath)) { - return undefined; - } - obj = obj[firstPartOfPath]; - } - - return obj[key]; - }; - - /** - * @public - * - * @param string key - * @param mixed value - * @param bool disablePublishersOnSet - * @return void - * @throws 1475361756 - * @publish mixed - */ - function set(key, value, disablePublishersOnSet) { - var obj, oldValue, path; - utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361756); - disablePublishersOnSet = !!disablePublishersOnSet; - - oldValue = get(key); - obj = _objectData; - path = key; - - while (path.indexOf('.') > 0) { - var firstPartOfPath, nextPartOfPath; - - firstPartOfPath = path.slice(0, path.indexOf('.')); - path = path.slice(firstPartOfPath.length + 1); - if ($.isNumeric(firstPartOfPath)) { - firstPartOfPath = parseInt(firstPartOfPath); - } - if ('undefined' === $.type(obj[firstPartOfPath])) { - nextPartOfPath = path.slice(0, path.indexOf('.')); - if ($.isNumeric(nextPartOfPath)) { - obj[firstPartOfPath] = []; - } else { - obj[firstPartOfPath] = {}; - } - } - obj = obj[firstPartOfPath]; - } - obj[path] = value; - - if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) { - for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) { - publisherSubscriber().publish(_publisherTopics[key][i], [key, value, oldValue, _objectData['__identifierPath']]); - } - } - }; - - /** - * @public - * - * @param string key - * @param bool disablePublishersOnSet - * @return void - * @throws 1489321637 - * @throws 1489319753 - * @publish mixed - */ - function unset(key, disablePublishersOnSet) { - var obj, oldValue, parentPropertyData, parentPropertyPath, propertyToRemove; - utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1489321637); - disablePublishersOnSet = !!disablePublishersOnSet; - - oldValue = get(key); - - if (key.indexOf('.') > 0) { - parentPropertyPath = key.split('.'); - propertyToRemove = parentPropertyPath.pop(); - parentPropertyPath = parentPropertyPath.join('.'); - parentPropertyData = get(parentPropertyPath); - delete parentPropertyData[propertyToRemove]; - } else { - assert(false, 'remove toplevel properties is not supported', 1489319753); - } - - if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) { - for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) { - publisherSubscriber().publish(_publisherTopics[key][i], [key, undefined, oldValue, _objectData['__identifierPath']]); - } - } - }; - - /** - * @public - * - * @param string key - * @param string topicName - * @return void - * @throws 1475361757 - * @throws 1475361758 - */ - function on(key, topicName) { - utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361757); - utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361758); - - if ('array' !== $.type(_publisherTopics[key])) { - _publisherTopics[key] = []; - } - if (_publisherTopics[key].indexOf(topicName) === -1) { - _publisherTopics[key].push(topicName); - } - }; - - /** - * @public - * - * @param string key - * @param string topicName - * @return void - * @throws 1475361759 - * @throws 1475361760 - */ - function off(key, topicName) { - utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361759); - utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361760); - - if ('array' === $.type(_publisherTopics[key])) { - _publisherTopics[key] = _publisherTopics[key].filter(function (topicName) { - return topicName !== topicName; - }); - } - }; - - /** - * @public - * - * @return object (dereferenced) - */ - function getObjectData() { - return $.extend(true, {}, _objectData); - }; - - /** - * @public - * - * @return string - */ - function toString() { - var childFormElements, objectData; - - objectData = getObjectData(); - childFormElements = objectData['renderables'] || null; - delete objectData['renderables']; - - if (!utility().isUndefinedOrNull(objectData['__parentRenderable'])) { - objectData['__parentRenderable'] = objectData['__parentRenderable'].getObjectData()['__identifierPath'] + ' (filtered)'; - } - - if (null !== childFormElements) { - objectData['renderables'] = []; - for (var i = 0, len = childFormElements.length; i < len; ++i) { - var childFormElement = childFormElements[i]; - objectData['renderables'].push(JSON.parse(childFormElement.toString())); - } - } - - return JSON.stringify(objectData, null, 2); - }; - - /** - * @public - * - * @return object - */ - function clone() { - var childFormElements, newModel, newRenderables, objectData; - - objectData = getObjectData(); - childFormElements = objectData['renderables'] || null; - delete objectData['renderables']; - delete objectData['__parentRenderable']; - objectData['renderables'] = (childFormElements) ? true : null, - - newModel = new M(); - extendModel(newModel, objectData, '', true); - - if (null !== childFormElements) { - newRenderables = []; - for (var i = 0, len = childFormElements.length; i < len; ++i) { - var childFormElement = childFormElements[i]; - - childFormElement = childFormElement.clone(); - childFormElement.set('__parentRenderable', newModel, true); - newRenderables.push(childFormElement); - } - newModel.set('renderables', newRenderables, true); - } - - return newModel; - }; - - /** - * Publish the public methods. - */ - return { - get: get, - set: set, - unset: unset, - - on: on, - off: off, - - getObjectData: getObjectData, - toString: toString, - clone: clone - }; - }; - - newModel = new M(); - extendModel(newModel, modelExtension, '', true); - - return newModel; + function getObjectData() { + return $.extend(true, {}, _objectData); }; /** * @public * - * @return object + * @return string */ - function repository() { - - /** - * @public - * - * @param object typeDefinitions - * @return void - * @throws 1475364394 - */ - function setFormEditorDefinitions(formEditorDefinitions) { - utility().assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475364394); - - for (var key1 in formEditorDefinitions) { - if (!formEditorDefinitions.hasOwnProperty(key1) || 'object' !== $.type(formEditorDefinitions[key1])) { - continue; - } - for (var key2 in formEditorDefinitions[key1]) { - if (!formEditorDefinitions[key1].hasOwnProperty(key2)) { - continue; - } - if ('object' !== $.type(formEditorDefinitions[key1][key2])) { - formEditorDefinitions[key1][key2] = {}; - } - } - } - _repositoryFormEditorDefinitions = formEditorDefinitions; - }; - - /** - * @public - * - * @param string typeName - * @param string subject - * @return object (dereferenced) - * @throws 1475364952 - * @throws 1475364953 - */ - function getFormEditorDefinition(definitionName, subject) { - utility().assert(utility().isNonEmptyString(definitionName), 'Invalid parameter "definitionName"', 1475364952); - utility().assert(utility().isNonEmptyString(subject), 'Invalid parameter "subject"', 1475364953); - return $.extend(true, {}, _repositoryFormEditorDefinitions[definitionName][subject]); - }; - - /** - * @public - * - * @return object - */ - function getRootFormElement() { - return getApplicationStateStack().getCurrentState('formDefinition'); - }; - - /** - * @public - * - * @param object formElement - * @param object referenceFormElement - * @param boolean registerPropertyValidators - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475436224 - * @throws 1475364956 - */ - function addFormElement(formElement, referenceFormElement, registerPropertyValidators, disablePublishersOnSet) { - var enclosingCompositeFormElement, identifier, formElementTypeDefinition, parentFormElementsArray, parentFormElementTypeDefinition, referenceFormElementElements, referenceFormElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475436224); - utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364956); - - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - - registerPropertyValidators = !!registerPropertyValidators; - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); - - // formElement != Page / SummaryPage && referenceFormElement == Page / Fieldset / GridContainer / GridRow - if (!formElementTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isCompositeFormElement']) { - if ('array' !== $.type(referenceFormElement.get('renderables'))) { - referenceFormElement.set('renderables', [], disablePublishersOnSet); - } - - formElement.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); - formElement.set('__identifierPath', referenceFormElement.get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); - referenceFormElement.get('renderables').push(formElement); - } else { - // referenceFormElement == root form element - if (referenceFormElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { - referenceFormElementElements = referenceFormElement.get('renderables'); - // referenceFormElement = last page - referenceFormElement = referenceFormElementElements[referenceFormElementElements.length - 1]; - // if formElement == Page / SummaryPage && referenceFormElement != Page / SummaryPage - } else if (formElementTypeDefinition['_isTopLevelFormElement'] && !referenceFormElementTypeDefinition['_isTopLevelFormElement']) { - // referenceFormElement = parent Page - referenceFormElement = findEnclosingCompositeFormElementWhichIsOnTopLevel(referenceFormElement); - // formElement == Page / SummaryPage / Fieldset / GridContainer / GridRow - } else if (formElementTypeDefinition['_isCompositeFormElement']) { - enclosingCompositeFormElement = findEnclosingCompositeFormElementWhichIsNotOnTopLevel(referenceFormElement); - if (enclosingCompositeFormElement) { - // referenceFormElement = parent Fieldset / GridContainer / GridRow - referenceFormElement = enclosingCompositeFormElement; - } - } - - formElement.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); - formElement.set('__identifierPath', referenceFormElement.get('__parentRenderable').get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); - parentFormElementsArray = referenceFormElement.get('__parentRenderable').get('renderables'); - parentFormElementsArray.splice(parentFormElementsArray.indexOf(referenceFormElement) + 1, 0, formElement); - } - - if (registerPropertyValidators) { - if ('array' === $.type(formElementTypeDefinition['editors'])) { - for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { - var configuration = {}; - - if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { - continue; - } - - if ( - !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) - && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' - ) { - configuration['propertyValidatorsMode'] = 'OR'; - } else { - configuration['propertyValidatorsMode'] = 'AND'; - } - - propertyValidationService().addValidatorIdentifiersToFormElementProperty( - formElement, - formElementTypeDefinition['editors'][i]['propertyValidators'], - formElementTypeDefinition['editors'][i]['propertyPath'], - undefined, - undefined, - configuration - ); - } - } - } - - return formElement; - }; - - /** - * @param object formElement - * @param boolean removeRegisteredPropertyValidators - * @param boolean disablePublishersOnSet - * @return void - * @throws 1472553024 - * @throws 1475364957 - */ - function removeFormElement(formElement, removeRegisteredPropertyValidators, disablePublishersOnSet) { - var parentFormElementElements; - - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - removeRegisteredPropertyValidators = !!removeRegisteredPropertyValidators; - - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364957); - utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'Removing the root element is not allowed', 1472553024); - - parentFormElementElements = formElement.get('__parentRenderable').get('renderables'); - parentFormElementElements.splice(parentFormElementElements.indexOf(formElement), 1); - formElement.get('__parentRenderable').set('renderables', parentFormElementElements, disablePublishersOnSet); - - if (removeRegisteredPropertyValidators) { - propertyValidationService().removeAllValidatorIdentifiersFromFormElement(formElement); - } - }; - - /** - * @param object formElementToMove - * @param string position - * @param object referenceFormElement - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475364958 - * @throws 1475364959 - * @throws 1475364960 - * @throws 1475364961 - * @throws 1475364962 - * @throws 1476993731 - * @throws 1476993732 - */ - function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { - var formElementToMoveTypeDefinition, referenceFormElementParentElements, referenceFormElementElements, referenceFormElementIndex, referenceFormElementTypeDefinition, reSetIdentifierPath; - utility().assert('object' === $.type(formElementToMove), 'Invalid parameter "formElementToMove"', 1475364958); - utility().assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475364959); - utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364960); - - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - - formElementToMoveTypeDefinition = repository().getFormEditorDefinition('formElements', formElementToMove.get('type')); - referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); - - removeFormElement(formElementToMove, false); - reSetIdentifierPath = function(formElement, pathPrefix) { - var formElements, newIdentifierPath, oldIdentifierPath, propertyValidationServiceRegisteredValidators; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961); - utility().assert(utility().isNonEmptyString(pathPrefix), 'Invalid parameter "pathPrefix"', 1475364962); - - oldIdentifierPath = formElement.get('__identifierPath'); - newIdentifierPath = pathPrefix + '/' + formElement.get('identifier'); - - propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); - if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[oldIdentifierPath])) { - propertyValidationServiceRegisteredValidators[newIdentifierPath] = propertyValidationServiceRegisteredValidators[oldIdentifierPath]; - delete propertyValidationServiceRegisteredValidators[oldIdentifierPath]; - } - getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); - - formElement.set('__identifierPath', newIdentifierPath, disablePublishersOnSet); - formElements = formElement.get('renderables'); - if ('array' === $.type(formElements)) { - for (var i = 0, len = formElements.length; i < len; ++i) { - reSetIdentifierPath(formElements[i], formElement.get('__identifierPath')); - } - } - }; - - /** - * This is true on: - * * Drag a Element on a Page Element (tree) - * * Drag a Element on a Section Element (tree) - */ - if (position === 'inside') { - // formElementToMove == Page / SummaryPage - utility().assert(!formElementToMoveTypeDefinition['_isTopLevelFormElement'], 'This move is not allowed', 1476993731); - // referenceFormElement != Page / Fieldset / GridContainer / GridRow - utility().assert(referenceFormElementTypeDefinition['_isCompositeFormElement'], 'This move is not allowed', 1476993732); - - formElementToMove.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); - reSetIdentifierPath(formElementToMove, referenceFormElement.get('__identifierPath')); - - referenceFormElementElements = referenceFormElement.get('renderables'); - if (utility().isUndefinedOrNull(referenceFormElementElements)) { - referenceFormElementElements = []; - } - referenceFormElementElements.splice(0, 0, formElementToMove); - referenceFormElement.set('renderables', referenceFormElementElements, disablePublishersOnSet); - } else { - /** - * This is true on: - * * Drag a Page before another Page (tree) - * * Drag a Page after another Page (tree) - */ - if (formElementToMoveTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isTopLevelFormElement']) { - referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); - referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); - - if (position === 'after') { - referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); - } else { - referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); - } - - referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); - } else { - /** - * This is true on: - * * Drag a Element before another Element within the same level (tree) - * * Drag a Element after another Element within the same level (tree) - * * Drag a Element before another Element (stage) - * * Drag a Element after another Element (stage) - */ - if (formElementToMove.get('__parentRenderable').get('identifier') === referenceFormElement.get('__parentRenderable').get('identifier')) { - referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); - referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); - } else { - /** - * This is true on: - * * Drag a Element before an Element on another page (tree / stage) - * * Drag a Element after an Element on another page (tree / stage) - */ - formElementToMove.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); - reSetIdentifierPath(formElementToMove, referenceFormElement.get('__parentRenderable').get('__identifierPath')); - - referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); - referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); - } - - if (position === 'after') { - referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); - } else { - referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); - } - - referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); - } - } - - return formElementToMove; - }; - - /** - * @param object formElement - * @return int - * @throws 1475364963 - */ - function getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(formElement) { - var enclosingCompositeFormElementWhichIsOnTopLevel, formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364963); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - - if (formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { - enclosingCompositeFormElementWhichIsOnTopLevel = formElement; - } else if (formElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { - enclosingCompositeFormElementWhichIsOnTopLevel = getApplicationStateStack().getCurrentState('formDefinition').get('renderables')[0]; - } else { - enclosingCompositeFormElementWhichIsOnTopLevel = findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement); - } - return enclosingCompositeFormElementWhichIsOnTopLevel.get('__parentRenderable').get('renderables').indexOf(enclosingCompositeFormElementWhichIsOnTopLevel); - }; - - /** - * @param object formElement - * @return object - * @throws 1472556223 - * @throws 1475364964 - */ - function findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement) { - var formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364964); - utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'The root element is never encloused by anything', 1472556223); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - while (!formElementTypeDefinition['_isTopLevelFormElement']) { - formElement = formElement.get('__parentRenderable'); - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - } - - return formElement; - }; - - /** - * @param object formElement - * @return object|null - * @throws 1489447996 - */ - function findEnclosingGridContainerFormElement(formElement) { - var formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1489447996); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - while (!formElementTypeDefinition['_isGridContainerFormElement']) { - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - formElement = formElement.get('__parentRenderable'); - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - } - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - return formElement; - }; - - /** - * @param object formElement - * @return object|null - * @throws 1490520271 - */ - function findEnclosingGridRowFormElement(formElement) { - var formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1490520271); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - while (!formElementTypeDefinition['_isGridRowFormElement']) { - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - formElement = formElement.get('__parentRenderable'); - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - } - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - return formElement; - }; - - /** - * @param object formElement - * @return object|null - * @throws 1475364965 - */ - function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { - var formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364965); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - while (!formElementTypeDefinition['_isCompositeFormElement']) { - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - formElement = formElement.get('__parentRenderable'); - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - } - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return null; - } - return formElement; - }; - - /** - * @return object - */ - function getNonCompositeNonToplevelFormElements() { - var collect, nonCompositeNonToplevelFormElements; - - collect = function(formElement) { - var formElements, formElementTypeDefinition; - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961); - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); - - if (!formElementTypeDefinition['_isTopLevelFormElement'] && !formElementTypeDefinition['_isCompositeFormElement']) { - nonCompositeNonToplevelFormElements.push(formElement); - } - - formElements = formElement.get('renderables'); - if ('array' === $.type(formElements)) { - for (var i = 0, len = formElements.length; i < len; ++i) { - collect(formElements[i]); - } - } - }; - - nonCompositeNonToplevelFormElements = []; - collect(getRootFormElement()); - return nonCompositeNonToplevelFormElements; - }; - - /** - * @param string identifier - * @returl bool - * @throws 1475364966 - */ - function isFormElementIdentifierUsed(identifier) { - var checkIdentifier, identifierFound; - utility().assert(utility().isNonEmptyString(identifier), 'Invalid parameter "identifier"', 1475364966); - - checkIdentifier = function(formElement) { - var formElements; - - if (formElement.get('identifier') === identifier) { - identifierFound = true; - } - - if (!identifierFound) { - formElements = formElement.get('renderables'); - if ('array' === $.type(formElements)) { - for (var i = 0, len = formElements.length; i < len; ++i) { - checkIdentifier(formElements[i]); - if (identifierFound) { - break; - } - } - } - } - } - - checkIdentifier(getApplicationStateStack().getCurrentState('formDefinition')); - return identifierFound; - }; - - /** - * @param string formElementType - * @return string - * @throws 1475373676 - */ - function getNextFreeFormElementIdentifier(formElementType) { - var i, prefix; - utility().assert(utility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475373676); - - prefix = formElementType.toLowerCase().replace(/[^a-z0-9]/g, '-') + '-'; - i = 1; - while (isFormElementIdentifierUsed(prefix + i)) { - i++; - } - return prefix + i; - }; - - /** - * @param string identifierPath - * @return object - * @throws 1472424333 - * @throws 1472424334 - * @throws 1472424330 - * @throws 1475373677 - */ - function findFormElementByIdentifierPath(identifierPath) { - var obj, pathParts, pathPartsLength, formElement, formElements; - - utility().assert(utility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475373677); - - formElement = getApplicationStateStack().getCurrentState('formDefinition'); - pathParts = identifierPath.split('/'); - pathPartsLength = pathParts.length; - - for (var i = 0; i < pathPartsLength; ++i) { - var key = pathParts[i]; - if (i === 0 || i === pathPartsLength) { - utility().assert(key === formElement.get('identifier'), '"' + key + '" does not exist in path "' + identifierPath + '"', 1472424333); - continue; - } - - formElements = formElement.get('renderables'); - if ('array' === $.type(formElements)) { - obj = null; - for (var j = 0, len = formElements.length; j < len; ++j) { - if (key === formElements[j].get('identifier')) { - obj = formElements[j]; - break; - } - } - - utility().assert('null' !== $.type(obj), 'Could not find form element "' + key + '" in path "' + identifierPath + '"', 1472424334); - formElement = obj; - } else { - utility().assert(false, 'No form elements found', 1472424330); - } - } - return formElement; - }; - - /** - * @param string|object formElement - * @return object - */ - function findFormElement(formElement) { - if ('object' === $.type(formElement)) { - formElement = formElement.get('__identifierPath'); - } - return findFormElementByIdentifierPath(formElement); - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param object collection - * @return undefined|object - * @throws 1475375281 - * @throws 1475375282 - */ - function findCollectionElementByIdentifierPath(collectionElementIdentifier, collection) { - utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375281); - utility().assert('array' === $.type(collection), 'Invalid parameter "collection"', 1475375282); - - for (var i = 0, len = collection.length; i < len; ++i) { - if (collection[i]['identifier'] === collectionElementIdentifier) { - return collection[i]; - } - } - - return undefined; - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @return int - * @throws 1475375283 - * @throws 1475375284 - * @throws 1475375285 - */ - function getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement) { - var collection; - utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375283); - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375284); - utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375285); - - collection = formElement.get(collectionName); - if ('array' === $.type(collection)) { - for (var i = 0, len = collection.length; i < len; ++i) { - if (collection[i]['identifier'] === collectionElementIdentifier) { - return i; - } - } - } - return -1; - }; - - /** - * @public - * - * @param object collectionElementToAdd - * @param string collectionName - * @param object formElement - * @param string referenceCollectionElementIdentifier - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475375686 - * @throws 1475375687 - * @throws 1475375688 - * @throws 1477413154 - */ - function addPropertyCollectionElement(collectionElementToAdd, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) { - var collection, formElementTypeDefinition, newCollection, newCollectionElementIndex; - utility().assert('object' === $.type(collectionElementToAdd), 'Invalid parameter "collectionElementToAdd"', 1475375686); - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375687); - utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375688); - - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - - collection = formElement.get(collectionName); - if ('array' !== $.type(collection)) { - extendModel(formElement, [], collectionName, true); - collection = formElement.get(collectionName); - } - - if (utility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { - newCollectionElementIndex = 0; - } else { - newCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement) + 1; - utility().assert(-1 < newCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477413154); - } - - collection.splice(newCollectionElementIndex, 0, collectionElementToAdd); - formElement.set(collectionName, collection, true); - - propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); - - for (var i = 0, len = collection.length; i < len; ++i) { - extendModel(formElement, collection[i], collectionName + '.' + i, true); - } - - formElement.set(collectionName, collection, true); - propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); - formElement.set(collectionName, collection, disablePublishersOnSet); - - return formElement; - }; - - /** - * @public - * - * @param object formElement - * @param string collectionElementIdentifier - * @param string collectionName - * @param boolean disablePublishersOnSet - * @return void - * @throws 1475375689 - * @throws 1475375690 - * @throws 1475375691 - * @throws 1475375692 - */ - function removePropertyCollectionElementByIdentifier(formElement, collectionElementIdentifier, collectionName, disablePublishersOnSet) { - var collection, collectionElementIndex; - utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375689); - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375690); - utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375691); - - collection = formElement.get(collectionName); - utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1475375692); - - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - - propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); - collectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); - collection.splice(collectionElementIndex, 1); - formElement.set(collectionName, collection, disablePublishersOnSet); - propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); - }; - - /** - * @param string collectionElementToMoveIdentifier - * @param string position - * @param string referenceCollectionElementIdentifier - * @param string position - * @param object formElement - * @param boolean disablePublishersOnSet - * @return void - * @throws 1477404484 - * @throws 1477404485 - * @throws 1477404486 - * @throws 1477404488 - * @throws 1477404489 - * @throws 1477404490 - */ - function movePropertyCollectionElement(collectionElementToMoveIdentifier, position, referenceCollectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { - var collection, collectionElementToMove, referenceCollectionElement, referenceCollectionElementIndex; - - utility().assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404485); - utility().assert('string' === $.type(referenceCollectionElementIdentifier), 'Invalid parameter "referenceCollectionElementIdentifier"', 1477404486); - utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1477404488); - - collection = formElement.get(collectionName); - utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1477404490); - - collectionElementToMove = findCollectionElementByIdentifierPath(collectionElementToMoveIdentifier, collection); - utility().assert('object' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404484); - - removePropertyCollectionElementByIdentifier(formElement, collectionElementToMoveIdentifier, collectionName); - - referenceCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement); - utility().assert(-1 < referenceCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477404489); - - if ('before' === position) { - referenceCollectionElement = collection[referenceCollectionElementIndex - 1]; - if (utility().isUndefinedOrNull(referenceCollectionElement)) { - referenceCollectionElementIdentifier = undefined; - } else { - referenceCollectionElementIdentifier = referenceCollectionElement['identifier']; - } - } - - addPropertyCollectionElement(collectionElementToMove, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) - }; + function toString() { + var childFormElements, objectData; + + objectData = getObjectData(); + childFormElements = objectData['renderables'] || null; + delete objectData['renderables']; + + if (!utility().isUndefinedOrNull(objectData['__parentRenderable'])) { + objectData['__parentRenderable'] = objectData['__parentRenderable'].getObjectData()['__identifierPath'] + ' (filtered)'; + } + + if (null !== childFormElements) { + objectData['renderables'] = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + var childFormElement = childFormElements[i]; + objectData['renderables'].push(JSON.parse(childFormElement.toString())); + } + } - /** - * Publish the public methods. - */ - return { - getRootFormElement: getRootFormElement, - - getFormEditorDefinition: getFormEditorDefinition, - setFormEditorDefinitions: setFormEditorDefinitions, - - findFormElement: findFormElement, - findFormElementByIdentifierPath: findFormElementByIdentifierPath, - findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, - findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel, - findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, - findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, - getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement, - getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, - - getNextFreeFormElementIdentifier: getNextFreeFormElementIdentifier, - isFormElementIdentifierUsed: isFormElementIdentifierUsed, - - addFormElement: addFormElement, - moveFormElement: moveFormElement, - removeFormElement: removeFormElement, - - findCollectionElementByIdentifierPath: findCollectionElementByIdentifierPath, - getIndexFromPropertyCollectionElementByIdentifier: getIndexFromPropertyCollectionElementByIdentifier, - addPropertyCollectionElement: addPropertyCollectionElement, - removePropertyCollectionElementByIdentifier: removePropertyCollectionElementByIdentifier, - movePropertyCollectionElement: movePropertyCollectionElement - }; + return JSON.stringify(objectData, null, 2); }; /** @@ -1755,509 +939,1335 @@ define(['jquery'], function($) { * * @return object */ - function factory() { + function clone() { + var childFormElements, newModel, newRenderables, objectData; - /** - * @public - * - * @param object configuration - * @param string identifierPathPrefix - * @param object parentFormElement - * @param boolean registerPropertyValidators - * @param boolean disablePublishersOnSet - * @return object - * @throws 1475375693 - * @throws 1475436040 - * @throws 1475604050 - */ - function createFormElement(configuration, identifierPathPrefix, parentFormElement, registerPropertyValidators, disablePublishersOnSet) { - var currentChildFormElements, collections, formElementTypeDefinition, identifierPath, rawChildFormElements, formElement, predefinedDefaults; - utility().assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1475375693); - utility().assert(utility().isNonEmptyString(configuration['identifier']), '"identifier" must not be empty', 1475436040); - utility().assert(utility().isNonEmptyString(configuration['type']), '"type" must not be empty', 1475604050); - - registerPropertyValidators = !!registerPropertyValidators; - if (utility().isUndefinedOrNull(disablePublishersOnSet)) { - disablePublishersOnSet = true; - } - disablePublishersOnSet = !!disablePublishersOnSet; - - formElementTypeDefinition = repository().getFormEditorDefinition('formElements', configuration['type']); - rawChildFormElements = configuration['renderables']; - delete configuration['renderables']; - - collections = {}; - predefinedDefaults = formElementTypeDefinition['predefinedDefaults'] || {}; - for (var collectionName in configuration) { - if (!configuration.hasOwnProperty(collectionName)) { - continue; - } - if (utility().isUndefinedOrNull(_repositoryFormEditorDefinitions[collectionName])) { - continue; - } - - predefinedDefaults[collectionName] = predefinedDefaults[collectionName] || {}; - collections[collectionName] = $.extend( - predefinedDefaults[collectionName] || {}, - configuration[collectionName] - ); - - delete predefinedDefaults[collectionName]; - delete configuration[collectionName]; - } - - identifierPathPrefix = identifierPathPrefix || ''; - identifierPath = (identifierPathPrefix === '') ? configuration['identifier'] : identifierPathPrefix + '/' + configuration['identifier']; - - configuration = $.extend( - predefinedDefaults, - configuration, - { - renderables: (rawChildFormElements) ? true : null, - __parentRenderable: null, - __identifierPath: identifierPath - } - ); - - formElement = createModel(configuration); - formElement.set('__parentRenderable', parentFormElement || null, disablePublishersOnSet); - - for (var collectionName in collections) { - if (!collections.hasOwnProperty(collectionName)) { - continue; - } - - for (var i in collections[collectionName]) { - var previousCreatePropertyCollectionElementIdentifier, propertyCollectionElement; - if (!collections[collectionName].hasOwnProperty(i)) { - continue; - } - propertyCollectionElement = createPropertyCollectionElement( - collections[collectionName][i]['identifier'], - collections[collectionName][i], - collectionName - ); - if (i > 0) { - previousCreatePropertyCollectionElementIdentifier = collections[collectionName][i - 1]['identifier'] - } - repository().addPropertyCollectionElement(propertyCollectionElement, collectionName, formElement, previousCreatePropertyCollectionElementIdentifier, true); - } - } + objectData = getObjectData(); + childFormElements = objectData['renderables'] || null; + delete objectData['renderables']; + delete objectData['__parentRenderable']; + objectData['renderables'] = (childFormElements) ? true : null, - if (registerPropertyValidators) { - if ('array' === $.type(formElementTypeDefinition['editors'])) { - for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { - var configuration = {}; - - if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { - continue; - } - - if ( - !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) - && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' - ) { - configuration['propertyValidatorsMode'] = 'OR'; - } else { - configuration['propertyValidatorsMode'] = 'AND'; - } - - propertyValidationService().addValidatorIdentifiersToFormElementProperty( - formElement, - formElementTypeDefinition['editors'][i]['propertyValidators'], - formElementTypeDefinition['editors'][i]['propertyPath'], - undefined, - undefined, - configuration - ); - } - } - } - - if ('array' === $.type(rawChildFormElements)) { - currentChildFormElements = []; - for (var i = 0, len = rawChildFormElements.length; i < len; ++i) { - currentChildFormElements.push(createFormElement(rawChildFormElements[i], identifierPath, formElement, registerPropertyValidators, disablePublishersOnSet)); - } - formElement.set('renderables', currentChildFormElements, disablePublishersOnSet); - } - return formElement; - }; + newModel = new M(); + extendModel(newModel, objectData, '', true); - /** - * @public - * - * @param string collectionElementIdentifier - * @param object collectionElementConfiguration - * @param string collectionName - * @return object - * @throws 1475377160 - * @throws 1475377161 - * @throws 1475377162 - */ - function createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName) { - var collectionDefinition, collectionElementPresets; - utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475377160); - utility().assert('object' === $.type(collectionElementConfiguration), 'Invalid parameter "collectionElementConfiguration"', 1475377161); - utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475377162); - - collectionElementConfiguration['identifier'] = collectionElementIdentifier; - collectionDefinition = repository().getFormEditorDefinition(collectionName, collectionElementIdentifier); - if (collectionDefinition['predefinedDefaults']) { - collectionElementPresets = collectionDefinition['predefinedDefaults']; - } else { - collectionElementPresets = {}; - } + if (null !== childFormElements) { + newRenderables = []; + for (var i = 0, len = childFormElements.length; i < len; ++i) { + var childFormElement = childFormElements[i]; - return $.extend(collectionElementPresets, collectionElementConfiguration); - }; + childFormElement = childFormElement.clone(); + childFormElement.set('__parentRenderable', newModel, true); + newRenderables.push(childFormElement); + } + newModel.set('renderables', newRenderables, true); + } - /** - * Publish the public methods. - */ - return { - createFormElement: createFormElement, - createPropertyCollectionElement: createPropertyCollectionElement - }; + return newModel; }; /** - * @public - * - * @return object + * Publish the public methods. */ - function dataBackend() { - - /** - * @public - * - * @param object endpoints - * @return void - * @throws 1475377488 - */ - function setEndpoints(endpoints) { - utility().assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475377488); - _dataBackendEndpoints = endpoints; - }; - - /** - * @public - * - * @param string prototypeName - * @return void - * @throws 1475377489 - */ - function setPrototypeName(prototypeName) { - utility().assert(utility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475928095); - _dataBackendPrototypeName = prototypeName; - }; - - /** - * @public - * - * @param string persistenceIdentifier - * @return void - * @throws 1475377489 - */ - function setPersistenceIdentifier(persistenceIdentifier) { - utility().assert(utility().isNonEmptyString(persistenceIdentifier), 'Invalid parameter "persistenceIdentifier"', 1475377489); - _dataBackendPersistenceIdentifier = persistenceIdentifier; - }; - - /** - * @public - * - * @return void - * @publish core/ajax/saveFormDefinition/success - * @publish core/ajax/error - * @throws 1475520918 - */ - function saveFormDefinition() { - utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['saveForm']), 'The endpoint "saveForm" is not configured', 1475520918); - - if (_runningAjaxRequests['saveForm']) { - _runningAjaxRequests['saveForm'].abort(); - } - - _runningAjaxRequests['saveForm'] = $.post(_dataBackendEndpoints['saveForm'], { - tx_form_web_formformbuilder: { - formPersistenceIdentifier: _dataBackendPersistenceIdentifier, - formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))) - } - }, function(data, textStatus, jqXHR) { - if (_runningAjaxRequests['saveForm'] !== jqXHR) { - return; - } - _runningAjaxRequests['saveForm'] = null; - if (data['status'] === 'success') { - publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]); - } else { - publisherSubscriber().publish('core/ajax/saveFormDefinition/error', [data]); - } - }).fail(function(jqXHR, textStatus, errorThrown) { - publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); - }); - }; - - /** - * @public - * - * @param int pageIndex - * @return void - * @publish core/ajax/renderFormDefinitionPage/success - * @publish core/ajax/error - * @throws 1473447677 - * @throws 1475377781 - * @throws 1475377782 - */ - function renderFormDefinitionPage(pageIndex) { - utility().assert($.isNumeric(pageIndex), 'Invalid parameter "pageIndex"', 1475377781); - utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['formPageRenderer']), 'The endpoint "formPageRenderer" is not configured', 1473447677); - - if (_runningAjaxRequests['renderFormDefinitionPage']) { - _runningAjaxRequests['renderFormDefinitionPage'].abort(); - } + return { + get: get, + set: set, + unset: unset, - _runningAjaxRequests['renderFormDefinitionPage'] = $.post(_dataBackendEndpoints['formPageRenderer'], { - tx_form_web_formformbuilder: { - formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))), - pageIndex: pageIndex, - prototypeName: _dataBackendPrototypeName - } - }, function(data, textStatus, jqXHR) { - if (_runningAjaxRequests['renderFormDefinitionPage'] !== jqXHR) { - return; - } - _runningAjaxRequests['renderFormDefinitionPage'] = null; - publisherSubscriber().publish('core/ajax/renderFormDefinitionPage/success', [data, pageIndex]); - }).fail(function(jqXHR, textStatus, errorThrown) { - publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); - }); - }; + on: on, + off: off, - /** - * Publish the public methods. - */ - return { - renderFormDefinitionPage: renderFormDefinitionPage, - saveFormDefinition: saveFormDefinition, - setEndpoints: setEndpoints, - setPersistenceIdentifier: setPersistenceIdentifier, - setPrototypeName: setPrototypeName - }; + getObjectData: getObjectData, + toString: toString, + clone: clone + }; + }; + + newModel = new M(); + extendModel(newModel, modelExtension, '', true); + + return newModel; + }; + + /** + * @public + * + * @return object + */ + function repository() { + + /** + * @public + * + * @param object typeDefinitions + * @return void + * @throws 1475364394 + */ + function setFormEditorDefinitions(formEditorDefinitions) { + utility().assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475364394); + + for (var key1 in formEditorDefinitions) { + if (!formEditorDefinitions.hasOwnProperty(key1) || 'object' !== $.type(formEditorDefinitions[key1])) { + continue; + } + for (var key2 in formEditorDefinitions[key1]) { + if (!formEditorDefinitions[key1].hasOwnProperty(key2)) { + continue; + } + if ('object' !== $.type(formEditorDefinitions[key1][key2])) { + formEditorDefinitions[key1][key2] = {}; + } + } + } + _repositoryFormEditorDefinitions = formEditorDefinitions; + }; + + /** + * @public + * + * @param string typeName + * @param string subject + * @return object (dereferenced) + * @throws 1475364952 + * @throws 1475364953 + */ + function getFormEditorDefinition(definitionName, subject) { + utility().assert(utility().isNonEmptyString(definitionName), 'Invalid parameter "definitionName"', 1475364952); + utility().assert(utility().isNonEmptyString(subject), 'Invalid parameter "subject"', 1475364953); + return $.extend(true, {}, _repositoryFormEditorDefinitions[definitionName][subject]); + }; + + /** + * @public + * + * @return object + */ + function getRootFormElement() { + return getApplicationStateStack().getCurrentState('formDefinition'); + }; + + /** + * @public + * + * @param object formElement + * @param object referenceFormElement + * @param boolean registerPropertyValidators + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475436224 + * @throws 1475364956 + */ + function addFormElement(formElement, referenceFormElement, registerPropertyValidators, disablePublishersOnSet) { + var enclosingCompositeFormElement, identifier, formElementTypeDefinition, + parentFormElementsArray, parentFormElementTypeDefinition, referenceFormElementElements, + referenceFormElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475436224); + utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364956); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + registerPropertyValidators = !!registerPropertyValidators; + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); + + // formElement != Page / SummaryPage && referenceFormElement == Page / Fieldset / GridContainer / GridRow + if (!formElementTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isCompositeFormElement']) { + if ('array' !== $.type(referenceFormElement.get('renderables'))) { + referenceFormElement.set('renderables', [], disablePublishersOnSet); + } + + formElement.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); + formElement.set('__identifierPath', referenceFormElement.get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); + referenceFormElement.get('renderables').push(formElement); + } else { + // referenceFormElement == root form element + if (referenceFormElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { + referenceFormElementElements = referenceFormElement.get('renderables'); + // referenceFormElement = last page + referenceFormElement = referenceFormElementElements[referenceFormElementElements.length - 1]; + // if formElement == Page / SummaryPage && referenceFormElement != Page / SummaryPage + } else if (formElementTypeDefinition['_isTopLevelFormElement'] && !referenceFormElementTypeDefinition['_isTopLevelFormElement']) { + // referenceFormElement = parent Page + referenceFormElement = findEnclosingCompositeFormElementWhichIsOnTopLevel(referenceFormElement); + // formElement == Page / SummaryPage / Fieldset / GridContainer / GridRow + } else if (formElementTypeDefinition['_isCompositeFormElement']) { + enclosingCompositeFormElement = findEnclosingCompositeFormElementWhichIsNotOnTopLevel(referenceFormElement); + if (enclosingCompositeFormElement) { + // referenceFormElement = parent Fieldset / GridContainer / GridRow + referenceFormElement = enclosingCompositeFormElement; + } + } + + formElement.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); + formElement.set('__identifierPath', referenceFormElement.get('__parentRenderable').get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet); + parentFormElementsArray = referenceFormElement.get('__parentRenderable').get('renderables'); + parentFormElementsArray.splice(parentFormElementsArray.indexOf(referenceFormElement) + 1, 0, formElement); + } + + if (registerPropertyValidators) { + if ('array' === $.type(formElementTypeDefinition['editors'])) { + for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { + var configuration = {}; + + if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { + continue; + } + + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) + && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + + propertyValidationService().addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['editors'][i]['propertyValidators'], + formElementTypeDefinition['editors'][i]['propertyPath'], + undefined, + undefined, + configuration + ); + } + } + } + + return formElement; + }; + + /** + * @param object formElement + * @param boolean removeRegisteredPropertyValidators + * @param boolean disablePublishersOnSet + * @return void + * @throws 1472553024 + * @throws 1475364957 + */ + function removeFormElement(formElement, removeRegisteredPropertyValidators, disablePublishersOnSet) { + var parentFormElementElements; + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + removeRegisteredPropertyValidators = !!removeRegisteredPropertyValidators; + + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364957); + utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'Removing the root element is not allowed', 1472553024); + + parentFormElementElements = formElement.get('__parentRenderable').get('renderables'); + parentFormElementElements.splice(parentFormElementElements.indexOf(formElement), 1); + formElement.get('__parentRenderable').set('renderables', parentFormElementElements, disablePublishersOnSet); + + if (removeRegisteredPropertyValidators) { + propertyValidationService().removeAllValidatorIdentifiersFromFormElement(formElement); + } + }; + + /** + * @param object formElementToMove + * @param string position + * @param object referenceFormElement + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475364958 + * @throws 1475364959 + * @throws 1475364960 + * @throws 1475364961 + * @throws 1475364962 + * @throws 1476993731 + * @throws 1476993732 + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + var formElementToMoveTypeDefinition, referenceFormElementParentElements, + referenceFormElementElements, referenceFormElementIndex, + referenceFormElementTypeDefinition, reSetIdentifierPath; + utility().assert('object' === $.type(formElementToMove), 'Invalid parameter "formElementToMove"', 1475364958); + utility().assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475364959); + utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364960); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + formElementToMoveTypeDefinition = repository().getFormEditorDefinition('formElements', formElementToMove.get('type')); + referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type')); + + removeFormElement(formElementToMove, false); + reSetIdentifierPath = function(formElement, pathPrefix) { + var formElements, newIdentifierPath, oldIdentifierPath, + propertyValidationServiceRegisteredValidators; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961); + utility().assert(utility().isNonEmptyString(pathPrefix), 'Invalid parameter "pathPrefix"', 1475364962); + + oldIdentifierPath = formElement.get('__identifierPath'); + newIdentifierPath = pathPrefix + '/' + formElement.get('identifier'); + + propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators'); + if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[oldIdentifierPath])) { + propertyValidationServiceRegisteredValidators[newIdentifierPath] = propertyValidationServiceRegisteredValidators[oldIdentifierPath]; + delete propertyValidationServiceRegisteredValidators[oldIdentifierPath]; + } + getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators); + + formElement.set('__identifierPath', newIdentifierPath, disablePublishersOnSet); + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + reSetIdentifierPath(formElements[i], formElement.get('__identifierPath')); + } + } }; /** - * @public - * - * @return object + * This is true on: + * * Drag a Element on a Page Element (tree) + * * Drag a Element on a Section Element (tree) */ - function getApplicationStateStack() { - - /** - * @public - * - * @param object applicationState - * @param bool disablePublishersOnSet - * @return void - * @publish core/applicationState/add - * @throws 1477847415 - */ - function add(applicationState, disablePublishersOnSet) { - utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477847415); - disablePublishersOnSet = !!disablePublishersOnSet; - - $.extend(applicationState, { - propertyValidationServiceRegisteredValidators: $.extend(true, {}, getCurrentState('propertyValidationServiceRegisteredValidators')) - }); - - _applicationStateStack.splice(0, 0, applicationState); - if (_applicationStateStack.length > _applicationStateStackSize) { - _applicationStateStack.splice(_applicationStateStackSize - 1, (_applicationStateStack.length - _applicationStateStackSize)); - } - - if (!disablePublishersOnSet) { - publisherSubscriber().publish('core/applicationState/add', [applicationState, getCurrentStackPointer(), getCurrentStackSize()]); - } - }; - - /** - * @public - * - * @param applicationState - * @param bool disablePublishersOnSet - * @return void - * @publish core/applicationState/add - * @throws 1477872641 - */ - function addAndReset(applicationState, disablePublishersOnSet) { - utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477872641); - - if (_applicationStateStackPointer > 0) { - _applicationStateStack.splice(0, _applicationStateStackPointer); - } - - _applicationStateStackPointer = 0; - add(applicationState, true); - - if (!disablePublishersOnSet) { - publisherSubscriber().publish('core/applicationState/add', [getCurrentState(), getCurrentStackPointer(), getCurrentStackSize()]); - } - }; - - /** - * @public - * - * @param string - * @return object - * @throws 1477932754 - */ - function getCurrentState(type) { - if (!utility().isUndefinedOrNull(type)) { - utility().assert( - 'formDefinition' === type - || 'currentlySelectedPageIndex' === type - || 'currentlySelectedFormElementIdentifierPath' === type - || 'propertyValidationServiceRegisteredValidators' === type, - - 'Invalid parameter "type"', 1477932754 - ); - - if ('undefined' === $.type(_applicationStateStack[_applicationStateStackPointer])) { - return undefined; - } - return _applicationStateStack[_applicationStateStackPointer][type]; - } - return _applicationStateStack[_applicationStateStackPointer]; - }; - - /** - * @public - * - * @param string - * @param mixed - * @return void - * @throws 1477934111 - */ - function setCurrentState(type, value) { - utility().assert( - 'formDefinition' === type - || 'currentlySelectedPageIndex' === type - || 'currentlySelectedFormElementIdentifierPath' === type - || 'propertyValidationServiceRegisteredValidators' === type, - - 'Invalid parameter "type"', 1477934111 - ); - _applicationStateStack[_applicationStateStackPointer][type] = value; - }; - - /** - * @public - * - * @param int - * @return void - * @throws 1477846933 - */ - function setMaximalStackSize(stackSize) { - utility().assert('number' === $.type(stackSize), 'Invalid parameter "size"', 1477846933); - _applicationStateStackSize = stackSize; - }; - - /** - * @public - * - * @return int - */ - function getMaximalStackSize() { - return _applicationStateStackSize; - }; - - /** - * @public - * - * @return int - */ - function getCurrentStackSize() { - return _applicationStateStack.length; - }; - - /** - * @public - * - * @return object - */ - function getCurrentStackPointer() { - return _applicationStateStackPointer; - }; - - /** - * @public - * - * @param int - * @return void - * @throws 1477852138 - */ - function setCurrentStackPointer(stackPointer) { - utility().assert('number' === $.type(stackPointer), 'Invalid parameter "size"', 1477852138); - if (stackPointer < 0) { - _applicationStateStackPointer = 0; - } else if (stackPointer > _applicationStateStack.length - 1) { - _applicationStateStackPointer = _applicationStateStack.length - 1; - } else { - _applicationStateStackPointer = stackPointer; - } - }; - + if (position === 'inside') { + // formElementToMove == Page / SummaryPage + utility().assert(!formElementToMoveTypeDefinition['_isTopLevelFormElement'], 'This move is not allowed', 1476993731); + // referenceFormElement != Page / Fieldset / GridContainer / GridRow + utility().assert(referenceFormElementTypeDefinition['_isCompositeFormElement'], 'This move is not allowed', 1476993732); + + formElementToMove.set('__parentRenderable', referenceFormElement, disablePublishersOnSet); + reSetIdentifierPath(formElementToMove, referenceFormElement.get('__identifierPath')); + + referenceFormElementElements = referenceFormElement.get('renderables'); + if (utility().isUndefinedOrNull(referenceFormElementElements)) { + referenceFormElementElements = []; + } + referenceFormElementElements.splice(0, 0, formElementToMove); + referenceFormElement.set('renderables', referenceFormElementElements, disablePublishersOnSet); + } else { + /** + * This is true on: + * * Drag a Page before another Page (tree) + * * Drag a Page after another Page (tree) + */ + if (formElementToMoveTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isTopLevelFormElement']) { + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + + if (position === 'after') { + referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); + } else { + referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); + } + referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); + } else { /** - * @public - * - * @return void + * This is true on: + * * Drag a Element before another Element within the same level (tree) + * * Drag a Element after another Element within the same level (tree) + * * Drag a Element before another Element (stage) + * * Drag a Element after another Element (stage) */ - function decrementCurrentStackPointer() { - setCurrentStackPointer(--_applicationStateStackPointer); - }; + if (formElementToMove.get('__parentRenderable').get('identifier') === referenceFormElement.get('__parentRenderable').get('identifier')) { + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + } else { + /** + * This is true on: + * * Drag a Element before an Element on another page (tree / stage) + * * Drag a Element after an Element on another page (tree / stage) + */ + formElementToMove.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet); + reSetIdentifierPath(formElementToMove, referenceFormElement.get('__parentRenderable').get('__identifierPath')); + + referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables'); + referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement); + } - /** - * @public - * - * @return void - */ - function incrementCurrentStackPointer() { - setCurrentStackPointer(++_applicationStateStackPointer); - }; + if (position === 'after') { + referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove); + } else { + referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove); + } - /** - * Publish the public methods. - */ - return { - add: add, - addAndReset: addAndReset, - getCurrentState: getCurrentState, - setCurrentState: setCurrentState, - getCurrentStackPointer: getCurrentStackPointer, - setCurrentStackPointer: setCurrentStackPointer, - decrementCurrentStackPointer: decrementCurrentStackPointer, - incrementCurrentStackPointer: incrementCurrentStackPointer, - setMaximalStackSize: setMaximalStackSize, - getMaximalStackSize: getMaximalStackSize, - getCurrentStackSize: getCurrentStackSize - }; + referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet); + } + } + + return formElementToMove; + }; + + /** + * @param object formElement + * @return int + * @throws 1475364963 + */ + function getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(formElement) { + var enclosingCompositeFormElementWhichIsOnTopLevel, formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364963); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + + if (formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { + enclosingCompositeFormElementWhichIsOnTopLevel = formElement; + } else if (formElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) { + enclosingCompositeFormElementWhichIsOnTopLevel = getApplicationStateStack().getCurrentState('formDefinition').get('renderables')[0]; + } else { + enclosingCompositeFormElementWhichIsOnTopLevel = findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement); + } + return enclosingCompositeFormElementWhichIsOnTopLevel.get('__parentRenderable').get('renderables').indexOf(enclosingCompositeFormElementWhichIsOnTopLevel); + }; + + /** + * @param object formElement + * @return object + * @throws 1472556223 + * @throws 1475364964 + */ + function findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364964); + utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'The root element is never encloused by anything', 1472556223); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isTopLevelFormElement']) { + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + + return formElement; + }; + + /** + * @param object formElement + * @return object|null + * @throws 1489447996 + */ + function findEnclosingGridContainerFormElement(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1489447996); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isGridContainerFormElement']) { + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + return formElement; + }; + + /** + * @param object formElement + * @return object|null + * @throws 1490520271 + */ + function findEnclosingGridRowFormElement(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1490520271); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isGridRowFormElement']) { + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + return formElement; + }; + + /** + * @param object formElement + * @return object|null + * @throws 1475364965 + */ + function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) { + var formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364965); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + while (!formElementTypeDefinition['_isCompositeFormElement']) { + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + formElement = formElement.get('__parentRenderable'); + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + } + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return null; + } + return formElement; + }; + + /** + * @return object + */ + function getNonCompositeNonToplevelFormElements() { + var collect, nonCompositeNonToplevelFormElements; + + collect = function(formElement) { + var formElements, formElementTypeDefinition; + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961); + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type')); + + if (!formElementTypeDefinition['_isTopLevelFormElement'] && !formElementTypeDefinition['_isCompositeFormElement']) { + nonCompositeNonToplevelFormElements.push(formElement); + } + + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + collect(formElements[i]); + } + } }; - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - getDataBackend: dataBackend, - getFactory: factory, - getPublisherSubscriber: publisherSubscriber, - getRepository: repository, - getUtility: utility, - getPropertyValidationService: propertyValidationService, - getRunningAjaxRequest: getRunningAjaxRequest, - getApplicationStateStack: getApplicationStateStack - }; - })($); + nonCompositeNonToplevelFormElements = []; + collect(getRootFormElement()); + return nonCompositeNonToplevelFormElements; + }; + + /** + * @param string identifier + * @returl bool + * @throws 1475364966 + */ + function isFormElementIdentifierUsed(identifier) { + var checkIdentifier, identifierFound; + utility().assert(utility().isNonEmptyString(identifier), 'Invalid parameter "identifier"', 1475364966); + + checkIdentifier = function(formElement) { + var formElements; + + if (formElement.get('identifier') === identifier) { + identifierFound = true; + } + + if (!identifierFound) { + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + for (var i = 0, len = formElements.length; i < len; ++i) { + checkIdentifier(formElements[i]); + if (identifierFound) { + break; + } + } + } + } + } + + checkIdentifier(getApplicationStateStack().getCurrentState('formDefinition')); + return identifierFound; + }; + + /** + * @param string formElementType + * @return string + * @throws 1475373676 + */ + function getNextFreeFormElementIdentifier(formElementType) { + var i, prefix; + utility().assert(utility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475373676); + + prefix = formElementType.toLowerCase().replace(/[^a-z0-9]/g, '-') + '-'; + i = 1; + while (isFormElementIdentifierUsed(prefix + i)) { + i++; + } + return prefix + i; + }; + + /** + * @param string identifierPath + * @return object + * @throws 1472424333 + * @throws 1472424334 + * @throws 1472424330 + * @throws 1475373677 + */ + function findFormElementByIdentifierPath(identifierPath) { + var obj, pathParts, pathPartsLength, formElement, formElements; + + utility().assert(utility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475373677); + + formElement = getApplicationStateStack().getCurrentState('formDefinition'); + pathParts = identifierPath.split('/'); + pathPartsLength = pathParts.length; + + for (var i = 0; i < pathPartsLength; ++i) { + var key = pathParts[i]; + if (i === 0 || i === pathPartsLength) { + utility().assert(key === formElement.get('identifier'), '"' + key + '" does not exist in path "' + identifierPath + '"', 1472424333); + continue; + } + + formElements = formElement.get('renderables'); + if ('array' === $.type(formElements)) { + obj = null; + for (var j = 0, len = formElements.length; j < len; ++j) { + if (key === formElements[j].get('identifier')) { + obj = formElements[j]; + break; + } + } + + utility().assert('null' !== $.type(obj), 'Could not find form element "' + key + '" in path "' + identifierPath + '"', 1472424334); + formElement = obj; + } else { + utility().assert(false, 'No form elements found', 1472424330); + } + } + return formElement; + }; + + /** + * @param string|object formElement + * @return object + */ + function findFormElement(formElement) { + if ('object' === $.type(formElement)) { + formElement = formElement.get('__identifierPath'); + } + return findFormElementByIdentifierPath(formElement); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param object collection + * @return undefined|object + * @throws 1475375281 + * @throws 1475375282 + */ + function findCollectionElementByIdentifierPath(collectionElementIdentifier, collection) { + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375281); + utility().assert('array' === $.type(collection), 'Invalid parameter "collection"', 1475375282); + + for (var i = 0, len = collection.length; i < len; ++i) { + if (collection[i]['identifier'] === collectionElementIdentifier) { + return collection[i]; + } + } + + return undefined; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return int + * @throws 1475375283 + * @throws 1475375284 + * @throws 1475375285 + */ + function getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement) { + var collection; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375283); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375284); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375285); + + collection = formElement.get(collectionName); + if ('array' === $.type(collection)) { + for (var i = 0, len = collection.length; i < len; ++i) { + if (collection[i]['identifier'] === collectionElementIdentifier) { + return i; + } + } + } + return -1; + }; + + /** + * @public + * + * @param object collectionElementToAdd + * @param string collectionName + * @param object formElement + * @param string referenceCollectionElementIdentifier + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475375686 + * @throws 1475375687 + * @throws 1475375688 + * @throws 1477413154 + */ + function addPropertyCollectionElement(collectionElementToAdd, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) { + var collection, formElementTypeDefinition, newCollection, newCollectionElementIndex; + utility().assert('object' === $.type(collectionElementToAdd), 'Invalid parameter "collectionElementToAdd"', 1475375686); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375687); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375688); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + collection = formElement.get(collectionName); + if ('array' !== $.type(collection)) { + extendModel(formElement, [], collectionName, true); + collection = formElement.get(collectionName); + } + + if (utility().isUndefinedOrNull(referenceCollectionElementIdentifier)) { + newCollectionElementIndex = 0; + } else { + newCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement) + 1; + utility().assert(-1 < newCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477413154); + } + + collection.splice(newCollectionElementIndex, 0, collectionElementToAdd); + formElement.set(collectionName, collection, true); + + propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); + + for (var i = 0, len = collection.length; i < len; ++i) { + extendModel(formElement, collection[i], collectionName + '.' + i, true); + } + + formElement.set(collectionName, collection, true); + propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); + formElement.set(collectionName, collection, disablePublishersOnSet); + + return formElement; + }; + + /** + * @public + * + * @param object formElement + * @param string collectionElementIdentifier + * @param string collectionName + * @param boolean disablePublishersOnSet + * @return void + * @throws 1475375689 + * @throws 1475375690 + * @throws 1475375691 + * @throws 1475375692 + */ + function removePropertyCollectionElementByIdentifier(formElement, collectionElementIdentifier, collectionName, disablePublishersOnSet) { + var collection, collectionElementIndex; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375689); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375690); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375691); + + collection = formElement.get(collectionName); + utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1475375692); + + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName); + collectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement); + collection.splice(collectionElementIndex, 1); + formElement.set(collectionName, collection, disablePublishersOnSet); + propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement); + }; + + /** + * @param string collectionElementToMoveIdentifier + * @param string position + * @param string referenceCollectionElementIdentifier + * @param string position + * @param object formElement + * @param boolean disablePublishersOnSet + * @return void + * @throws 1477404484 + * @throws 1477404485 + * @throws 1477404486 + * @throws 1477404488 + * @throws 1477404489 + * @throws 1477404490 + */ + function movePropertyCollectionElement(collectionElementToMoveIdentifier, position, referenceCollectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + var collection, collectionElementToMove, referenceCollectionElement, + referenceCollectionElementIndex; + + utility().assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404485); + utility().assert('string' === $.type(referenceCollectionElementIdentifier), 'Invalid parameter "referenceCollectionElementIdentifier"', 1477404486); + utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1477404488); + + collection = formElement.get(collectionName); + utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1477404490); + + collectionElementToMove = findCollectionElementByIdentifierPath(collectionElementToMoveIdentifier, collection); + utility().assert('object' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404484); + + removePropertyCollectionElementByIdentifier(formElement, collectionElementToMoveIdentifier, collectionName); + + referenceCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement); + utility().assert(-1 < referenceCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477404489); + + if ('before' === position) { + referenceCollectionElement = collection[referenceCollectionElementIndex - 1]; + if (utility().isUndefinedOrNull(referenceCollectionElement)) { + referenceCollectionElementIdentifier = undefined; + } else { + referenceCollectionElementIdentifier = referenceCollectionElement['identifier']; + } + } + + addPropertyCollectionElement(collectionElementToMove, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) + }; + + /** + * Publish the public methods. + */ + return { + getRootFormElement: getRootFormElement, + + getFormEditorDefinition: getFormEditorDefinition, + setFormEditorDefinitions: setFormEditorDefinitions, + + findFormElement: findFormElement, + findFormElementByIdentifierPath: findFormElementByIdentifierPath, + findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel, + findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel, + findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement, + findEnclosingGridRowFormElement: findEnclosingGridRowFormElement, + getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement, + getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements, + + getNextFreeFormElementIdentifier: getNextFreeFormElementIdentifier, + isFormElementIdentifierUsed: isFormElementIdentifierUsed, + + addFormElement: addFormElement, + moveFormElement: moveFormElement, + removeFormElement: removeFormElement, + + findCollectionElementByIdentifierPath: findCollectionElementByIdentifierPath, + getIndexFromPropertyCollectionElementByIdentifier: getIndexFromPropertyCollectionElementByIdentifier, + addPropertyCollectionElement: addPropertyCollectionElement, + removePropertyCollectionElementByIdentifier: removePropertyCollectionElementByIdentifier, + movePropertyCollectionElement: movePropertyCollectionElement + }; + }; + + /** + * @public + * + * @return object + */ + function factory() { + + /** + * @public + * + * @param object configuration + * @param string identifierPathPrefix + * @param object parentFormElement + * @param boolean registerPropertyValidators + * @param boolean disablePublishersOnSet + * @return object + * @throws 1475375693 + * @throws 1475436040 + * @throws 1475604050 + */ + function createFormElement(configuration, identifierPathPrefix, parentFormElement, registerPropertyValidators, disablePublishersOnSet) { + var currentChildFormElements, collections, formElementTypeDefinition, identifierPath, + rawChildFormElements, formElement, predefinedDefaults; + utility().assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1475375693); + utility().assert(utility().isNonEmptyString(configuration['identifier']), '"identifier" must not be empty', 1475436040); + utility().assert(utility().isNonEmptyString(configuration['type']), '"type" must not be empty', 1475604050); + + registerPropertyValidators = !!registerPropertyValidators; + if (utility().isUndefinedOrNull(disablePublishersOnSet)) { + disablePublishersOnSet = true; + } + disablePublishersOnSet = !!disablePublishersOnSet; + + formElementTypeDefinition = repository().getFormEditorDefinition('formElements', configuration['type']); + rawChildFormElements = configuration['renderables']; + delete configuration['renderables']; + + collections = {}; + predefinedDefaults = formElementTypeDefinition['predefinedDefaults'] || {}; + for (var collectionName in configuration) { + if (!configuration.hasOwnProperty(collectionName)) { + continue; + } + if (utility().isUndefinedOrNull(_repositoryFormEditorDefinitions[collectionName])) { + continue; + } + + predefinedDefaults[collectionName] = predefinedDefaults[collectionName] || {}; + collections[collectionName] = $.extend( + predefinedDefaults[collectionName] || {}, + configuration[collectionName] + ); + + delete predefinedDefaults[collectionName]; + delete configuration[collectionName]; + } + + identifierPathPrefix = identifierPathPrefix || ''; + identifierPath = (identifierPathPrefix === '') ? configuration['identifier'] : identifierPathPrefix + '/' + configuration['identifier']; + + configuration = $.extend( + predefinedDefaults, + configuration, + { + renderables: (rawChildFormElements) ? true : null, + __parentRenderable: null, + __identifierPath: identifierPath + } + ); + + formElement = createModel(configuration); + formElement.set('__parentRenderable', parentFormElement || null, disablePublishersOnSet); + + for (var collectionName in collections) { + if (!collections.hasOwnProperty(collectionName)) { + continue; + } + + for (var i in collections[collectionName]) { + var previousCreatePropertyCollectionElementIdentifier, propertyCollectionElement; + if (!collections[collectionName].hasOwnProperty(i)) { + continue; + } + propertyCollectionElement = createPropertyCollectionElement( + collections[collectionName][i]['identifier'], + collections[collectionName][i], + collectionName + ); + if (i > 0) { + previousCreatePropertyCollectionElementIdentifier = collections[collectionName][i - 1]['identifier'] + } + repository().addPropertyCollectionElement(propertyCollectionElement, collectionName, formElement, previousCreatePropertyCollectionElementIdentifier, true); + } + } + + if (registerPropertyValidators) { + if ('array' === $.type(formElementTypeDefinition['editors'])) { + for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) { + var configuration = {}; + + if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) { + continue; + } + + if ( + !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode']) + && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR' + ) { + configuration['propertyValidatorsMode'] = 'OR'; + } else { + configuration['propertyValidatorsMode'] = 'AND'; + } + + propertyValidationService().addValidatorIdentifiersToFormElementProperty( + formElement, + formElementTypeDefinition['editors'][i]['propertyValidators'], + formElementTypeDefinition['editors'][i]['propertyPath'], + undefined, + undefined, + configuration + ); + } + } + } + + if ('array' === $.type(rawChildFormElements)) { + currentChildFormElements = []; + for (var i = 0, len = rawChildFormElements.length; i < len; ++i) { + currentChildFormElements.push(createFormElement(rawChildFormElements[i], identifierPath, formElement, registerPropertyValidators, disablePublishersOnSet)); + } + formElement.set('renderables', currentChildFormElements, disablePublishersOnSet); + } + return formElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param object collectionElementConfiguration + * @param string collectionName + * @return object + * @throws 1475377160 + * @throws 1475377161 + * @throws 1475377162 + */ + function createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName) { + var collectionDefinition, collectionElementPresets; + utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475377160); + utility().assert('object' === $.type(collectionElementConfiguration), 'Invalid parameter "collectionElementConfiguration"', 1475377161); + utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475377162); + + collectionElementConfiguration['identifier'] = collectionElementIdentifier; + collectionDefinition = repository().getFormEditorDefinition(collectionName, collectionElementIdentifier); + if (collectionDefinition['predefinedDefaults']) { + collectionElementPresets = collectionDefinition['predefinedDefaults']; + } else { + collectionElementPresets = {}; + } + + return $.extend(collectionElementPresets, collectionElementConfiguration); + }; + + /** + * Publish the public methods. + */ + return { + createFormElement: createFormElement, + createPropertyCollectionElement: createPropertyCollectionElement + }; + }; + + /** + * @public + * + * @return object + */ + function dataBackend() { + + /** + * @public + * + * @param object endpoints + * @return void + * @throws 1475377488 + */ + function setEndpoints(endpoints) { + utility().assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475377488); + _dataBackendEndpoints = endpoints; + }; + + /** + * @public + * + * @param string prototypeName + * @return void + * @throws 1475377489 + */ + function setPrototypeName(prototypeName) { + utility().assert(utility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475928095); + _dataBackendPrototypeName = prototypeName; + }; + + /** + * @public + * + * @param string persistenceIdentifier + * @return void + * @throws 1475377489 + */ + function setPersistenceIdentifier(persistenceIdentifier) { + utility().assert(utility().isNonEmptyString(persistenceIdentifier), 'Invalid parameter "persistenceIdentifier"', 1475377489); + _dataBackendPersistenceIdentifier = persistenceIdentifier; + }; + + /** + * @public + * + * @return void + * @publish core/ajax/saveFormDefinition/success + * @publish core/ajax/error + * @throws 1475520918 + */ + function saveFormDefinition() { + utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['saveForm']), 'The endpoint "saveForm" is not configured', 1475520918); + + if (_runningAjaxRequests['saveForm']) { + _runningAjaxRequests['saveForm'].abort(); + } + + _runningAjaxRequests['saveForm'] = $.post(_dataBackendEndpoints['saveForm'], { + tx_form_web_formformbuilder: { + formPersistenceIdentifier: _dataBackendPersistenceIdentifier, + formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))) + } + }, function(data, textStatus, jqXHR) { + if (_runningAjaxRequests['saveForm'] !== jqXHR) { + return; + } + _runningAjaxRequests['saveForm'] = null; + if (data['status'] === 'success') { + publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]); + } else { + publisherSubscriber().publish('core/ajax/saveFormDefinition/error', [data]); + } + }).fail(function(jqXHR, textStatus, errorThrown) { + publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); + }); + }; + + /** + * @public + * + * @param int pageIndex + * @return void + * @publish core/ajax/renderFormDefinitionPage/success + * @publish core/ajax/error + * @throws 1473447677 + * @throws 1475377781 + * @throws 1475377782 + */ + function renderFormDefinitionPage(pageIndex) { + utility().assert($.isNumeric(pageIndex), 'Invalid parameter "pageIndex"', 1475377781); + utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['formPageRenderer']), 'The endpoint "formPageRenderer" is not configured', 1473447677); + + if (_runningAjaxRequests['renderFormDefinitionPage']) { + _runningAjaxRequests['renderFormDefinitionPage'].abort(); + } + + _runningAjaxRequests['renderFormDefinitionPage'] = $.post(_dataBackendEndpoints['formPageRenderer'], { + tx_form_web_formformbuilder: { + formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))), + pageIndex: pageIndex, + prototypeName: _dataBackendPrototypeName + } + }, function(data, textStatus, jqXHR) { + if (_runningAjaxRequests['renderFormDefinitionPage'] !== jqXHR) { + return; + } + _runningAjaxRequests['renderFormDefinitionPage'] = null; + publisherSubscriber().publish('core/ajax/renderFormDefinitionPage/success', [data, pageIndex]); + }).fail(function(jqXHR, textStatus, errorThrown) { + publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]); + }); + }; + + /** + * Publish the public methods. + */ + return { + renderFormDefinitionPage: renderFormDefinitionPage, + saveFormDefinition: saveFormDefinition, + setEndpoints: setEndpoints, + setPersistenceIdentifier: setPersistenceIdentifier, + setPrototypeName: setPrototypeName + }; + }; + + /** + * @public + * + * @return object + */ + function getApplicationStateStack() { + + /** + * @public + * + * @param object applicationState + * @param bool disablePublishersOnSet + * @return void + * @publish core/applicationState/add + * @throws 1477847415 + */ + function add(applicationState, disablePublishersOnSet) { + utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477847415); + disablePublishersOnSet = !!disablePublishersOnSet; + + $.extend(applicationState, { + propertyValidationServiceRegisteredValidators: $.extend(true, {}, getCurrentState('propertyValidationServiceRegisteredValidators')) + }); + + _applicationStateStack.splice(0, 0, applicationState); + if (_applicationStateStack.length > _applicationStateStackSize) { + _applicationStateStack.splice(_applicationStateStackSize - 1, (_applicationStateStack.length - _applicationStateStackSize)); + } + + if (!disablePublishersOnSet) { + publisherSubscriber().publish('core/applicationState/add', [applicationState, getCurrentStackPointer(), getCurrentStackSize()]); + } + }; + + /** + * @public + * + * @param applicationState + * @param bool disablePublishersOnSet + * @return void + * @publish core/applicationState/add + * @throws 1477872641 + */ + function addAndReset(applicationState, disablePublishersOnSet) { + utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477872641); + + if (_applicationStateStackPointer > 0) { + _applicationStateStack.splice(0, _applicationStateStackPointer); + } + + _applicationStateStackPointer = 0; + add(applicationState, true); + + if (!disablePublishersOnSet) { + publisherSubscriber().publish('core/applicationState/add', [getCurrentState(), getCurrentStackPointer(), getCurrentStackSize()]); + } + }; + + /** + * @public + * + * @param string + * @return object + * @throws 1477932754 + */ + function getCurrentState(type) { + if (!utility().isUndefinedOrNull(type)) { + utility().assert( + 'formDefinition' === type + || 'currentlySelectedPageIndex' === type + || 'currentlySelectedFormElementIdentifierPath' === type + || 'propertyValidationServiceRegisteredValidators' === type, + + 'Invalid parameter "type"', 1477932754 + ); + + if ('undefined' === $.type(_applicationStateStack[_applicationStateStackPointer])) { + return undefined; + } + return _applicationStateStack[_applicationStateStackPointer][type]; + } + return _applicationStateStack[_applicationStateStackPointer]; + }; + + /** + * @public + * + * @param string + * @param mixed + * @return void + * @throws 1477934111 + */ + function setCurrentState(type, value) { + utility().assert( + 'formDefinition' === type + || 'currentlySelectedPageIndex' === type + || 'currentlySelectedFormElementIdentifierPath' === type + || 'propertyValidationServiceRegisteredValidators' === type, + + 'Invalid parameter "type"', 1477934111 + ); + _applicationStateStack[_applicationStateStackPointer][type] = value; + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1477846933 + */ + function setMaximalStackSize(stackSize) { + utility().assert('number' === $.type(stackSize), 'Invalid parameter "size"', 1477846933); + _applicationStateStackSize = stackSize; + }; + + /** + * @public + * + * @return int + */ + function getMaximalStackSize() { + return _applicationStateStackSize; + }; + + /** + * @public + * + * @return int + */ + function getCurrentStackSize() { + return _applicationStateStack.length; + }; + + /** + * @public + * + * @return object + */ + function getCurrentStackPointer() { + return _applicationStateStackPointer; + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1477852138 + */ + function setCurrentStackPointer(stackPointer) { + utility().assert('number' === $.type(stackPointer), 'Invalid parameter "size"', 1477852138); + if (stackPointer < 0) { + _applicationStateStackPointer = 0; + } else if (stackPointer > _applicationStateStack.length - 1) { + _applicationStateStackPointer = _applicationStateStack.length - 1; + } else { + _applicationStateStackPointer = stackPointer; + } + }; + + + /** + * @public + * + * @return void + */ + function decrementCurrentStackPointer() { + setCurrentStackPointer(--_applicationStateStackPointer); + }; + + /** + * @public + * + * @return void + */ + function incrementCurrentStackPointer() { + setCurrentStackPointer(++_applicationStateStackPointer); + }; + + /** + * Publish the public methods. + */ + return { + add: add, + addAndReset: addAndReset, + getCurrentState: getCurrentState, + setCurrentState: setCurrentState, + getCurrentStackPointer: getCurrentStackPointer, + setCurrentStackPointer: setCurrentStackPointer, + decrementCurrentStackPointer: decrementCurrentStackPointer, + incrementCurrentStackPointer: incrementCurrentStackPointer, + setMaximalStackSize: setMaximalStackSize, + getMaximalStackSize: getMaximalStackSize, + getCurrentStackSize: getCurrentStackSize + }; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getDataBackend: dataBackend, + getFactory: factory, + getPublisherSubscriber: publisherSubscriber, + getRepository: repository, + getUtility: utility, + getPropertyValidationService: propertyValidationService, + getRunningAjaxRequest: getRunningAjaxRequest, + getApplicationStateStack: getApplicationStateStack + }; + })($); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js index 2f300caf7138ef729caedd9305f7751e2d4a3d46..f6305edcb7266c0424465dfa7b121699365ab671 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js @@ -15,300 +15,300 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/Helper */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - return (function($) { + return (function($) { - /** - * @private - * - * @var object - */ - var _formEditorApp = null; + /** + * @private + * + * @var object + */ + var _formEditorApp = null; - /** - * @private - * - * @var object - */ - var _configuration = {}; + /** + * @private + * + * @var object + */ + var _configuration = {}; - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - active: 'active', - buttonCollectionElementRemove: 't3-form-collection-element-remove-button', - buttonFormEditor: 't3-form-button', - disabled: 'disabled', - hidden: 'hidden', - icon: 't3-form-icon', - jQueryUiStateDisabled: 'ui-state-disabled', - sortableHover: 'sortable-hover' - }, - domElementDataAttributeNames: { - elementIdentifier: 'data-element-identifier-path', - identifier: 'data-identifier', - template: 'data-template-name', - templateProperty: 'data-template-property' - }, - domElementSelectorPattern: { - bracesWithKey: '[{0}]', - bracesWithKeyValue: '[{0}="{1}"]', - class: '.{0}', - id: '#{0}', - keyValue: '{0}="{1}"' - } - }; + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + active: 'active', + buttonCollectionElementRemove: 't3-form-collection-element-remove-button', + buttonFormEditor: 't3-form-button', + disabled: 'disabled', + hidden: 'hidden', + icon: 't3-form-icon', + jQueryUiStateDisabled: 'ui-state-disabled', + sortableHover: 'sortable-hover' + }, + domElementDataAttributeNames: { + elementIdentifier: 'data-element-identifier-path', + identifier: 'data-identifier', + template: 'data-template-name', + templateProperty: 'data-template-property' + }, + domElementSelectorPattern: { + bracesWithKey: '[{0}]', + bracesWithKeyValue: '[{0}="{1}"]', + class: '.{0}', + id: '#{0}', + keyValue: '{0}="{1}"' + } + }; - /* ************************************************************* - * Private Methodes - * ************************************************************/ + /* ************************************************************* + * Private Methodes + * ************************************************************/ - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; - /* ************************************************************* - * Public Methodes - * ************************************************************/ + /* ************************************************************* + * Public Methodes + * ************************************************************/ - /** - * @public - * - * @param object - * @return this - * @throws 1478950623 - */ - function setConfiguration(configuration) { - assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1478950623); - _configuration = $.extend(true, _defaultConfiguration, configuration); - return this; - }; + /** + * @public + * + * @param object + * @return this + * @throws 1478950623 + */ + function setConfiguration(configuration) { + assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1478950623); + _configuration = $.extend(true, _defaultConfiguration, configuration); + return this; + }; - /** - * @public - * - * @param string - * @param array - * @return string - * @throws 1478801251 - * @throws 1478801252 - */ - function buildDomElementSelectorHelper(patternIdentifier, replacements) { - var newString; - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][patternIdentifier]), - 'Invalid parameter "patternIdentifier" (' + patternIdentifier + ')', - 1478801251 - ); - assert('array' === $.type(replacements), 'Invalid parameter "replacements"', 1478801252); + /** + * @public + * + * @param string + * @param array + * @return string + * @throws 1478801251 + * @throws 1478801252 + */ + function buildDomElementSelectorHelper(patternIdentifier, replacements) { + var newString; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][patternIdentifier]), + 'Invalid parameter "patternIdentifier" (' + patternIdentifier + ')', + 1478801251 + ); + assert('array' === $.type(replacements), 'Invalid parameter "replacements"', 1478801252); - newString = _configuration['domElementSelectorPattern'][patternIdentifier]; - for (var i = 0, len = replacements.length; i < len; ++i) { - newString = newString.replace('{' + i + '}', replacements[i]); - } - return newString; - }; + newString = _configuration['domElementSelectorPattern'][patternIdentifier]; + for (var i = 0, len = replacements.length; i < len; ++i) { + newString = newString.replace('{' + i + '}', replacements[i]); + } + return newString; + }; - /** - * @public - * - * @param string - * @param array - * @return string - * @throws 1478372374 - */ - function getDomElementSelector(selectorIdentifier, args) { - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][selectorIdentifier]), - 'Invalid parameter "selectorIdentifier" (' + selectorIdentifier + ')', - 1478372374 - ); - return buildDomElementSelectorHelper(selectorIdentifier, args); - }; + /** + * @public + * + * @param string + * @param array + * @return string + * @throws 1478372374 + */ + function getDomElementSelector(selectorIdentifier, args) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][selectorIdentifier]), + 'Invalid parameter "selectorIdentifier" (' + selectorIdentifier + ')', + 1478372374 + ); + return buildDomElementSelectorHelper(selectorIdentifier, args); + }; - /** - * @public - * - * @param string - * @param bool - * @return string - * @throws 1478803906 - */ - function getDomElementClassName(classNameIdentifier, asSelector) { - var className; - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementClassNames'][classNameIdentifier]), - 'Invalid parameter "classNameIdentifier" (' + classNameIdentifier + ')', - 1478803906 - ); + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1478803906 + */ + function getDomElementClassName(classNameIdentifier, asSelector) { + var className; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementClassNames'][classNameIdentifier]), + 'Invalid parameter "classNameIdentifier" (' + classNameIdentifier + ')', + 1478803906 + ); - className = _configuration['domElementClassNames'][classNameIdentifier]; - if (!!asSelector) { - className = getDomElementSelector('class', [className]); - } - return className; - }; + className = _configuration['domElementClassNames'][classNameIdentifier]; + if (!!asSelector) { + className = getDomElementSelector('class', [className]); + } + return className; + }; - /** - * @public - * - * @param string - * @param bool - * @return string - * @throws 1479251518 - */ - function getDomElementIdName(idNameIdentifier, asSelector) { - var idName; - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementIdNames'][idNameIdentifier]), - 'Invalid parameter "domElementIdNames" (' + idNameIdentifier + ')', - 1479251518 - ); + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1479251518 + */ + function getDomElementIdName(idNameIdentifier, asSelector) { + var idName; + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementIdNames'][idNameIdentifier]), + 'Invalid parameter "domElementIdNames" (' + idNameIdentifier + ')', + 1479251518 + ); - idName = _configuration['domElementIdNames'][idNameIdentifier]; - if (!!asSelector) { - idName = getDomElementSelector('id', [idName]); - } - return idName; - }; + idName = _configuration['domElementIdNames'][idNameIdentifier]; + if (!!asSelector) { + idName = getDomElementSelector('id', [idName]); + } + return idName; + }; - /** - * @public - * - * @param string - * @param bool - * @return string - * @throws 1478806884 - */ - function getDomElementDataAttributeValue(dataAttributeValueIdentifier) { - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]), - 'Invalid parameter "dataAttributeValueIdentifier" (' + dataAttributeValueIdentifier + ')', - 1478806884 - ); - return _configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]; - }; + /** + * @public + * + * @param string + * @param bool + * @return string + * @throws 1478806884 + */ + function getDomElementDataAttributeValue(dataAttributeValueIdentifier) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]), + 'Invalid parameter "dataAttributeValueIdentifier" (' + dataAttributeValueIdentifier + ')', + 1478806884 + ); + return _configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]; + }; - /** - * @public - * - * @param string - * @param string - * @param array - * @return string - * @throws 1478808035 - */ - function getDomElementDataAttribute(dataAttributeIdentifier, selectorIdentifier, additionalSelectorArgs) { - assert( - !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]), - 'Invalid parameter "dataAttributeIdentifier" (' + dataAttributeIdentifier + ')', - 1478808035 - ); + /** + * @public + * + * @param string + * @param string + * @param array + * @return string + * @throws 1478808035 + */ + function getDomElementDataAttribute(dataAttributeIdentifier, selectorIdentifier, additionalSelectorArgs) { + assert( + !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]), + 'Invalid parameter "dataAttributeIdentifier" (' + dataAttributeIdentifier + ')', + 1478808035 + ); - if (getUtility().isUndefinedOrNull(selectorIdentifier)) { - return _configuration['domElementDataAttributeNames'][dataAttributeIdentifier]; - } + if (getUtility().isUndefinedOrNull(selectorIdentifier)) { + return _configuration['domElementDataAttributeNames'][dataAttributeIdentifier]; + } - additionalSelectorArgs = additionalSelectorArgs || []; - return getDomElementSelector( - selectorIdentifier, - [_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]].concat(additionalSelectorArgs) - ); - }; + additionalSelectorArgs = additionalSelectorArgs || []; + return getDomElementSelector( + selectorIdentifier, + [_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]].concat(additionalSelectorArgs) + ); + }; - /** - * @public - * - * Return a string like [data-identifier="someValue"] - * - * @return string - */ - function getDomElementDataIdentifierSelector(dataAttributeValueIdentifier) { - return getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [getDomElementDataAttributeValue(dataAttributeValueIdentifier)]); - }; + /** + * @public + * + * Return a string like [data-identifier="someValue"] + * + * @return string + */ + function getDomElementDataIdentifierSelector(dataAttributeValueIdentifier) { + return getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [getDomElementDataAttributeValue(dataAttributeValueIdentifier)]); + }; - /** - * @public - * - * @param string - * @return object - */ - function getTemplate(templateName) { - if (!getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][templateName])) { - templateName = getDomElementDataAttributeValue(templateName); - } + /** + * @public + * + * @param string + * @return object + */ + function getTemplate(templateName) { + if (!getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][templateName])) { + templateName = getDomElementDataAttributeValue(templateName); + } - return $(getDomElementDataAttribute('template', 'bracesWithKeyValue', [templateName])); - }; + return $(getDomElementDataAttribute('template', 'bracesWithKeyValue', [templateName])); + }; - /** - * @public - * - * @param string - * @param object - * @return object - */ - function getTemplatePropertyDomElement(templatePropertyName, templateDomElement) { - return $(getDomElementDataAttribute('templateProperty', 'bracesWithKeyValue', [templatePropertyName]), $(templateDomElement)); - }; + /** + * @public + * + * @param string + * @param object + * @return object + */ + function getTemplatePropertyDomElement(templatePropertyName, templateDomElement) { + return $(getDomElementDataAttribute('templateProperty', 'bracesWithKeyValue', [templatePropertyName]), $(templateDomElement)); + }; - /** - * @public - * - * @param object formEditorApp - * @return void - */ - function bootstrap(formEditorApp) { - _formEditorApp = formEditorApp; - }; + /** + * @public + * + * @param object formEditorApp + * @return void + */ + function bootstrap(formEditorApp) { + _formEditorApp = formEditorApp; + }; - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - buildDomElementSelectorHelper: buildDomElementSelectorHelper, - getDomElementClassName: getDomElementClassName, - getDomElementIdName: getDomElementIdName, - getDomElementDataAttribute: getDomElementDataAttribute, - getDomElementDataAttributeValue: getDomElementDataAttributeValue, - getDomElementDataIdentifierSelector: getDomElementDataIdentifierSelector, - getDomElementSelector: getDomElementSelector, - getTemplate: getTemplate, - getTemplatePropertyDomElement: getTemplatePropertyDomElement, - setConfiguration: setConfiguration - }; - })($); + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildDomElementSelectorHelper: buildDomElementSelectorHelper, + getDomElementClassName: getDomElementClassName, + getDomElementIdName: getDomElementIdName, + getDomElementDataAttribute: getDomElementDataAttribute, + getDomElementDataAttributeValue: getDomElementDataAttributeValue, + getDomElementDataIdentifierSelector: getDomElementDataIdentifierSelector, + getDomElementSelector: getDomElementSelector, + getTemplate: getTemplate, + getTemplatePropertyDomElement: getTemplatePropertyDomElement, + setConfiguration: setConfiguration + }; + })($); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js index d4d843cc44320bfc67c9ddc65fc13930ba4abe25..5a7cadd086a1e0ec6a0a1f3ef5631582183c6686 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js @@ -22,2199 +22,2205 @@ var setFormValueFromBrowseWin; define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' - ], function($, Helper, Icons, Notification, Modal) { - 'use strict'; - - return (function($, Helper, Icons, Notification) { - - /** - * @private - * - * @var object - */ - var _configuration = null; - - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - buttonFormElementRemove: 't3-form-remove-element-button', - collectionElement: 't3-form-collection-element', - finisherEditorPrefix: 't3-form-inspector-finishers-editor-', - inspectorEditor: 'form-editor', - inspectorInputGroup: 'input-group', - validatorEditorPrefix: 't3-form-inspector-validators-editor-' - }, - domElementDataAttributeNames: { - contentElementSelectorTarget: 'data-insert-target', - finisher: 'data-finisher-identifier', - validator: 'data-validator-identifier' - }, - domElementDataAttributeValues: { - collapse: 'actions-view-table-expand', - editorControlsInputGroup: 'inspectorEditorControlsGroup', - editorWrapper: 'editorWrapper', - editorControlsWrapper: 'inspectorEditorControlsWrapper', - formElementHeaderEditor: 'inspectorFormElementHeaderEditor', - formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper', - formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer', - formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer', - iconNotAvailable: 'actions-close', - iconPage: 'apps-pagetree-page-default', - iconTtContent: 'mimetypes-x-content-text', - inspector: 'inspector', - 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor', - 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor', - 'Inspector-FinishersEditor': 'Inspector-FinishersEditor', - 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor', - 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor', - 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor', - 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor', - 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor', - 'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor', - 'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor', - 'Inspector-TextareaEditor': 'Inspector-TextareaEditor', - 'Inspector-TextEditor': 'Inspector-TextEditor', - 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor', - 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor', - inspectorFinishers: 'inspectorFinishers', - inspectorValidators: 'inspectorValidators', - propertyGridEditorAddRow: 'addRow', - propertyGridEditorAddRowItem: 'addRowItem', - propertyGridEditorContainer: 'propertyGridContainer', - propertyGridEditorDeleteRow: 'deleteRow', - propertyGridEditorLabel: 'label', - propertyGridEditorRowItem: 'rowItem', - propertyGridEditorSelectValue: 'selectValue', - propertyGridEditorSortRow: 'sortRow', - propertyGridEditorValue: 'value', - viewportButton: 'viewportButton' - }, - domElementIdNames: { - finisherPrefix: 't3-form-inspector-finishers-', - validatorPrefix: 't3-form-inspector-validators-' - }, - isSortable: true - }; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @private - * - * @return object - */ - function getViewModel() { - return getFormEditorApp().getViewModel(); - }; - - /** - * @private - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @param object - * @param string - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @private - * - * @param object - * @param object - * @param string - * @param string - * @return void - * @publish view/inspector/editor/insert/perform - */ - function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - switch (editorConfiguration['templateName']) { - case 'Inspector-FormElementHeaderEditor': - renderFormElementHeaderEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-CollectionElementHeaderEditor': - renderCollectionElementHeaderEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-TextEditor': - renderTextEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-FinishersEditor': - renderCollectionElementSelectionEditor( - 'finishers', - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-ValidatorsEditor': - renderCollectionElementSelectionEditor( - 'validators', - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-RemoveElementEditor': - renderRemoveElementEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-RequiredValidatorEditor': - renderRequiredValidatorEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-CheckboxEditor': - renderCheckboxEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-SingleSelectEditor': - renderSingleSelectEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-MultiSelectEditor': - renderMultiSelectEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-GridColumnViewPortConfigurationEditor': - renderGridColumnViewPortConfigurationEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-PropertyGridEditor': - renderPropertyGridEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-TextareaEditor': - renderTextareaEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - case 'Inspector-Typo3WinBrowserEditor': - renderTypo3WinBrowserEditor( - editorConfiguration, - editorHtml, - collectionElementIdentifier, - collectionName - ); - break; - } - getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [ - editorConfiguration, editorHtml, collectionElementIdentifier, collectionName - ]); - }; - - /** - * @private - * - * opens a popup window with the element browser - * - * @param string mode - * @param string params - */ - function _openTypo3WinBrowser(mode, params) { - Modal.advanced({ - type: Modal.types.iframe, - content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params, - size: Modal.sizes.large - }); - }; - - /** - * @private - * - * @param string - * @param string - * @return object - */ - function _getCollectionElementClass(collectionName, collectionElementIdentifier) { - if (collectionName === 'finishers') { - return getHelper() - .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier; - } else { - return getHelper() - .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier; - } - }; - - /** - * @private - * - * @param string - * @param string - * @param bool - * @return object - */ - function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) { - if (collectionName === 'finishers') { - return getHelper() - .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier; - } else { - return getHelper() - .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier; - } - }; - - /** - * @private - * - * @param object - * @param string - * @return void - */ - function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) { - sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({ - revert: 'true', - items: getHelper().getDomElementClassName('collectionElement', true), - cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,textarea,select', - delay: 200, - update: function(e, o) { - var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier, previousCollectionElementIdentifier; - - if (collectionName === 'finishers') { - dataAttributeName = getHelper().getDomElementDataAttribute('finisher'); - } else { - dataAttributeName = getHelper().getDomElementDataAttribute('validator'); - } - - movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName); - previousCollectionElementIdentifier = $(o.item) - .prevAll(getHelper().getDomElementClassName('collectionElement', true)) - .first() - .attr(dataAttributeName); - nextCollectionElementIdentifier = $(o.item) - .nextAll(getHelper().getDomElementClassName('collectionElement', true)) - .first() - .attr(dataAttributeName); - - getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [ - movedCollectionElementIdentifier, - previousCollectionElementIdentifier, - nextCollectionElementIdentifier, - collectionName - ]); - } - }); - }; - - /** - * @private - * - * @param object editorHtml - * @param bool multiSelection - * @param string propertyPath - * @param string propertyPathPrefix - * @return void - */ - function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) { - var defaultValue, newPropertyData; - - if (multiSelection) { - defaultValue = []; - - $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', - $(editorHtml) - ).each(function(i) { - defaultValue.push( - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val() - ); - }); - getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue); - } else { - getCurrentlySelectedFormElement().set( - propertyPathPrefix + 'defaultValue', - $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', - $(editorHtml) - ).first() - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val(), - true - ); - } - - newPropertyData = []; - $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - $(editorHtml) - ).each(function(i) { - var value, label, tmpObject; - - value = $(this) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val(); - label = $(this) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel')) - .val(); - - if ('' === value) { - value = label; - } - - tmpObject = {}; - tmpObject[value] = label; - newPropertyData.push({ - _label: label, - _value: value - }); - }); - - getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData); - }; - - /** - * @private - * - * @param object - * @return object - */ - function _getEditorWrapperDomElement(editorDomElement) { - return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement)); - }; - - /** - * @private - * - * @param object - * @return object - */ - function _getEditorControlsWrapperDomElement(editorDomElement) { - return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement)); - }; - - /** - * @private - * - * @param string - * @param object - * @return void - */ - function _validateCollectionElement(propertyPath, editorHtml) { - var hasError, propertyPrefix, validationResults; - - validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath); - - if (validationResults.length > 0) { - getHelper() - .getTemplatePropertyDomElement('validationErrors', editorHtml) - .text(validationResults[0]); - getViewModel().setElementValidationErrorClass( - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) - ); - getViewModel().setElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml), - 'hasError' - ); - } else { - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text(''); - getViewModel().removeElementValidationErrorClass( - getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) - ); - getViewModel().removeElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml), - 'hasError' - ); - } - - validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()); - propertyPrefix = propertyPath.split('.'); - propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1]; - - hasError = false; - for (var i = 0, len = validationResults.length; i < len; ++i) { - if ( - validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0 - && validationResults[i]['validationResults'] - && validationResults[i]['validationResults'].length > 0 - ) { - hasError = true; - break; - } - } - - if (hasError) { - getViewModel().setElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) - ); - } else { - getViewModel().removeElementValidationErrorClass( - _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) - ); - } - }; - - /* ************************************************************* - * Public Methodes - * ************************************************************/ - - /** - * @public - * - * callback from TYPO3/CMS/Recordlist/ElementBrowser - * - * @param string fieldReference - * @param string elValue - * @param string elName - * @return void - */ - setFormValueFromBrowseWin = function(fieldReference, elValue, elName) { - var result; - result = elValue.split('_'); - - $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference])) - .val(result.pop()) - .trigger('paste'); - }; - - /** - * @public - * - * @return object - */ - function getInspectorDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspector')); - }; - - /** - * @public - * - * @return object - */ - function getFinishersContainerDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement()); - }; - - /** - * @public - * - * @return object - */ - function getValidatorsContainerDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement()); - }; - - /** - * @public - * - * @param string - * @param string - * @return object - */ - function getCollectionElementDomElement(collectionName, collectionElementIdentifier) { - if (collectionName === 'finishers') { - return $(getHelper().getDomElementDataAttribute( - 'finisher', - 'bracesWithKeyValue', - [collectionElementIdentifier] - ), getFinishersContainerDomElement()); - } else { - return $(getHelper().getDomElementDataAttribute( - 'validator', - 'bracesWithKeyValue', - [collectionElementIdentifier] - ), getValidatorsContainerDomElement()); - } - }; - - /** - * @public - * - * @param object - * @param function - * @return void - */ - function renderEditors(formElement, callback) { - var formElementTypeDefinition; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - - getInspectorDomElement().off().empty(); - - formElementTypeDefinition = getFormElementDefinition(formElement); - if ('array' !== $.type(formElementTypeDefinition['editors'])) { - return; - } - - for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) { - var html, template; - - template = getHelper() - .getTemplate(formElementTypeDefinition['editors'][i]['templateName']) - .clone(); - if (!template.length) { - continue; - } - html = $(template.html()); - - $(html) - .first() - .addClass(getHelper().getDomElementClassName('inspectorEditor')); - getInspectorDomElement().append($(html)); - - _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html); - } - - if ('function' === $.type(callback)) { - callback(); - } - }; - - /** - * @public - * - * @param string collectionName - * @param string collectionElementIdentifier - * @return void - * @publish view/inspector/collectionElements/dnd/update - * @throws 1478354853 - * @throws 1478354854 - */ - function renderCollectionElementEditors(collectionName, collectionElementIdentifier) { - var collapseWrapper, collectionContainer, collectionContainerElementWrapper, collectionElementConfiguration, collectionElementEditorsLength; - - assert( - getUtility().isNonEmptyString(collectionName), - 'Invalid parameter "collectionName"', - 1478354853 - ); - assert( - getUtility().isNonEmptyString(collectionElementIdentifier), - 'Invalid parameter "collectionElementIdentifier"', - 1478354854 - ); - - collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( - collectionElementIdentifier, - collectionName - ); - if ('array' !== $.type(collectionElementConfiguration['editors'])) { - return; - } + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' +], function($, Helper, Icons, Notification, Modal) { + 'use strict'; + + return (function($, Helper, Icons, Notification) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + buttonFormElementRemove: 't3-form-remove-element-button', + collectionElement: 't3-form-collection-element', + finisherEditorPrefix: 't3-form-inspector-finishers-editor-', + inspectorEditor: 'form-editor', + inspectorInputGroup: 'input-group', + validatorEditorPrefix: 't3-form-inspector-validators-editor-' + }, + domElementDataAttributeNames: { + contentElementSelectorTarget: 'data-insert-target', + finisher: 'data-finisher-identifier', + validator: 'data-validator-identifier' + }, + domElementDataAttributeValues: { + collapse: 'actions-view-table-expand', + editorControlsInputGroup: 'inspectorEditorControlsGroup', + editorWrapper: 'editorWrapper', + editorControlsWrapper: 'inspectorEditorControlsWrapper', + formElementHeaderEditor: 'inspectorFormElementHeaderEditor', + formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper', + formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer', + formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer', + iconNotAvailable: 'actions-close', + iconPage: 'apps-pagetree-page-default', + iconTtContent: 'mimetypes-x-content-text', + inspector: 'inspector', + 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor', + 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor', + 'Inspector-FinishersEditor': 'Inspector-FinishersEditor', + 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor', + 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor', + 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor', + 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor', + 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor', + 'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor', + 'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor', + 'Inspector-TextareaEditor': 'Inspector-TextareaEditor', + 'Inspector-TextEditor': 'Inspector-TextEditor', + 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor', + 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor', + inspectorFinishers: 'inspectorFinishers', + inspectorValidators: 'inspectorValidators', + propertyGridEditorAddRow: 'addRow', + propertyGridEditorAddRowItem: 'addRowItem', + propertyGridEditorContainer: 'propertyGridContainer', + propertyGridEditorDeleteRow: 'deleteRow', + propertyGridEditorLabel: 'label', + propertyGridEditorRowItem: 'rowItem', + propertyGridEditorSelectValue: 'selectValue', + propertyGridEditorSortRow: 'sortRow', + propertyGridEditorValue: 'value', + viewportButton: 'viewportButton' + }, + domElementIdNames: { + finisherPrefix: 't3-form-inspector-finishers-', + validatorPrefix: 't3-form-inspector-validators-' + }, + isSortable: true + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return getFormEditorApp().getViewModel(); + }; + + /** + * @private + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @param object + * @param object + * @param string + * @param string + * @return void + * @publish view/inspector/editor/insert/perform + */ + function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + switch (editorConfiguration['templateName']) { + case 'Inspector-FormElementHeaderEditor': + renderFormElementHeaderEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CollectionElementHeaderEditor': + renderCollectionElementHeaderEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-TextEditor': + renderTextEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-FinishersEditor': + renderCollectionElementSelectionEditor( + 'finishers', + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-ValidatorsEditor': + renderCollectionElementSelectionEditor( + 'validators', + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-RemoveElementEditor': + renderRemoveElementEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-RequiredValidatorEditor': + renderRequiredValidatorEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-CheckboxEditor': + renderCheckboxEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-SingleSelectEditor': + renderSingleSelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-MultiSelectEditor': + renderMultiSelectEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-GridColumnViewPortConfigurationEditor': + renderGridColumnViewPortConfigurationEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-PropertyGridEditor': + renderPropertyGridEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-TextareaEditor': + renderTextareaEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + case 'Inspector-Typo3WinBrowserEditor': + renderTypo3WinBrowserEditor( + editorConfiguration, + editorHtml, + collectionElementIdentifier, + collectionName + ); + break; + } + getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [ + editorConfiguration, editorHtml, collectionElementIdentifier, collectionName + ]); + }; + + /** + * @private + * + * opens a popup window with the element browser + * + * @param string mode + * @param string params + */ + function _openTypo3WinBrowser(mode, params) { + Modal.advanced({ + type: Modal.types.iframe, + content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params, + size: Modal.sizes.large + }); + }; + + /** + * @private + * + * @param string + * @param string + * @return object + */ + function _getCollectionElementClass(collectionName, collectionElementIdentifier) { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier; + } + }; + + /** + * @private + * + * @param string + * @param string + * @param bool + * @return object + */ + function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) { + if (collectionName === 'finishers') { + return getHelper() + .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier; + } else { + return getHelper() + .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier; + } + }; + + /** + * @private + * + * @param object + * @param string + * @return void + */ + function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) { + sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({ + revert: 'true', + items: getHelper().getDomElementClassName('collectionElement', true), + cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,textarea,select', + delay: 200, + update: function(e, o) { + var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier, + previousCollectionElementIdentifier; + + if (collectionName === 'finishers') { + dataAttributeName = getHelper().getDomElementDataAttribute('finisher'); + } else { + dataAttributeName = getHelper().getDomElementDataAttribute('validator'); + } + + movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName); + previousCollectionElementIdentifier = $(o.item) + .prevAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + nextCollectionElementIdentifier = $(o.item) + .nextAll(getHelper().getDomElementClassName('collectionElement', true)) + .first() + .attr(dataAttributeName); + + getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [ + movedCollectionElementIdentifier, + previousCollectionElementIdentifier, + nextCollectionElementIdentifier, + collectionName + ]); + } + }); + }; + + /** + * @private + * + * @param object editorHtml + * @param bool multiSelection + * @param string propertyPath + * @param string propertyPathPrefix + * @return void + */ + function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) { + var defaultValue, newPropertyData; + + if (multiSelection) { + defaultValue = []; + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).each(function(i) { + defaultValue.push( + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val() + ); + }); + getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue); + } else { + getCurrentlySelectedFormElement().set( + propertyPathPrefix + 'defaultValue', + $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', + $(editorHtml) + ).first() + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(), + true + ); + } + + newPropertyData = []; + $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).each(function(i) { + var value, label, tmpObject; + + value = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val(); + label = $(this) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel')) + .val(); + + if ('' === value) { + value = label; + } - collectionContainerElementWrapper = $('<div></div>'). - addClass(getHelper().getDomElementClassName('collectionElement')); - if (collectionName === 'finishers') { - collectionContainer = getFinishersContainerDomElement(); - collectionContainerElementWrapper - .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier); - } else { - collectionContainer = getValidatorsContainerDomElement(); - collectionContainerElementWrapper - .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier); - } - collectionContainer.append(collectionContainerElementWrapper); + tmpObject = {}; + tmpObject[value] = label; + newPropertyData.push({ + _label: label, + _value: value + }); + }); + + getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData); + }; + + /** + * @private + * + * @param object + * @return object + */ + function _getEditorWrapperDomElement(editorDomElement) { + return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement)); + }; + + /** + * @private + * + * @param object + * @return object + */ + function _getEditorControlsWrapperDomElement(editorDomElement) { + return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement)); + }; + + /** + * @private + * + * @param string + * @param object + * @return void + */ + function _validateCollectionElement(propertyPath, editorHtml) { + var hasError, propertyPrefix, validationResults; + + validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath); + + if (validationResults.length > 0) { + getHelper() + .getTemplatePropertyDomElement('validationErrors', editorHtml) + .text(validationResults[0]); + getViewModel().setElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().setElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } else { + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text(''); + getViewModel().removeElementValidationErrorClass( + getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml) + ); + getViewModel().removeElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml), + 'hasError' + ); + } + + validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement()); + propertyPrefix = propertyPath.split('.'); + propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1]; + + hasError = false; + for (var i = 0, len = validationResults.length; i < len; ++i) { + if ( + validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0 + && validationResults[i]['validationResults'] + && validationResults[i]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + getViewModel().setElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } else { + getViewModel().removeElementValidationErrorClass( + _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true)) + ); + } + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * callback from TYPO3/CMS/Recordlist/ElementBrowser + * + * @param string fieldReference + * @param string elValue + * @param string elName + * @return void + */ + setFormValueFromBrowseWin = function(fieldReference, elValue, elName) { + var result; + result = elValue.split('_'); + + $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference])) + .val(result.pop()) + .trigger('paste'); + }; + + /** + * @public + * + * @return object + */ + function getInspectorDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspector')); + }; + + /** + * @public + * + * @return object + */ + function getFinishersContainerDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement()); + }; + + /** + * @public + * + * @return object + */ + function getValidatorsContainerDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement()); + }; + + /** + * @public + * + * @param string + * @param string + * @return object + */ + function getCollectionElementDomElement(collectionName, collectionElementIdentifier) { + if (collectionName === 'finishers') { + return $(getHelper().getDomElementDataAttribute( + 'finisher', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getFinishersContainerDomElement()); + } else { + return $(getHelper().getDomElementDataAttribute( + 'validator', + 'bracesWithKeyValue', + [collectionElementIdentifier] + ), getValidatorsContainerDomElement()); + } + }; + + /** + * @public + * + * @param object + * @param function + * @return void + */ + function renderEditors(formElement, callback) { + var formElementTypeDefinition; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + getInspectorDomElement().off().empty(); + + formElementTypeDefinition = getFormElementDefinition(formElement); + if ('array' !== $.type(formElementTypeDefinition['editors'])) { + return; + } + + for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) { + var html, template; + + template = getHelper() + .getTemplate(formElementTypeDefinition['editors'][i]['templateName']) + .clone(); + if (!template.length) { + continue; + } + html = $(template.html()); + + $(html) + .first() + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + getInspectorDomElement().append($(html)); + + _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html); + } + + if ('function' === $.type(callback)) { + callback(); + } + }; + + /** + * @public + * + * @param string collectionName + * @param string collectionElementIdentifier + * @return void + * @publish view/inspector/collectionElements/dnd/update + * @throws 1478354853 + * @throws 1478354854 + */ + function renderCollectionElementEditors(collectionName, collectionElementIdentifier) { + var collapseWrapper, collectionContainer, collectionContainerElementWrapper, + collectionElementConfiguration, collectionElementEditorsLength; + + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid parameter "collectionName"', + 1478354853 + ); + assert( + getUtility().isNonEmptyString(collectionElementIdentifier), + 'Invalid parameter "collectionElementIdentifier"', + 1478354854 + ); + + collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( + collectionElementIdentifier, + collectionName + ); + if ('array' !== $.type(collectionElementConfiguration['editors'])) { + return; + } + + collectionContainerElementWrapper = $('<div></div>').addClass(getHelper().getDomElementClassName('collectionElement')); + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier); + } else { + collectionContainer = getValidatorsContainerDomElement(); + collectionContainerElementWrapper + .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier); + } + collectionContainer.append(collectionContainerElementWrapper); + + collectionElementEditorsLength = collectionElementConfiguration['editors'].length; + if ( + collectionElementEditorsLength > 0 + && collectionElementConfiguration['editors'][0]['identifier'] === 'header' + ) { + collapseWrapper = $('<div role="tabpanel"></div>') + .addClass('panel-collapse collapse') + .prop('id', _getCollectionElementId( + collectionName, + collectionElementIdentifier + )); + } + + for (var i = 0; i < collectionElementEditorsLength; ++i) { + var html, template; + + template = getHelper() + .getTemplate(collectionElementConfiguration['editors'][i]['templateName']) + .clone(); + if (!template.length) { + continue; + } + html = $(template.html()); + + $(html).first() + .addClass(_getCollectionElementClass( + collectionName, + collectionElementConfiguration['editors'][i]['identifier'] + )) + .addClass(getHelper().getDomElementClassName('inspectorEditor')); + + if (i === 0 && collapseWrapper) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier) + .append(html) + .append(collapseWrapper); + } else if ( + i === (collectionElementEditorsLength - 1) + && collapseWrapper + && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton' + ) { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } else if (i > 0 && collapseWrapper) { + collapseWrapper.append(html); + } else { + getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); + } - collectionElementEditorsLength = collectionElementConfiguration['editors'].length; - if ( - collectionElementEditorsLength > 0 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - ) { - collapseWrapper = $('<div role="tabpanel"></div>') - .addClass('panel-collapse collapse') - .prop('id', _getCollectionElementId( - collectionName, - collectionElementIdentifier - )); + _renderEditorDispatcher( + collectionElementConfiguration['editors'][i], + html, + collectionElementIdentifier, + collectionName + ); + } + + if ( + ( + collectionElementEditorsLength === 2 + && collectionElementConfiguration['editors'][0]['identifier'] === 'header' + && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton' + ) || ( + collectionElementEditorsLength === 1 + && collectionElementConfiguration['editors'][0]['identifier'] === 'header' + ) + ) { + $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove(); + } + + if (_configuration['isSortable']) { + _addSortableCollectionElementsEvents(collectionContainer, collectionName); + } + }; + + /** + * @public + * + * @string collectionName + * @param object editorConfiguration + * @param object editorHtml + * @return void + * @publish view/inspector/collectionElement/existing/selected + * @publish view/inspector/collectionElement/new/selected + * @throws 1475423098 + * @throws 1475423099 + * @throws 1475423100 + * @throws 1475423101 + * @throws 1478362968 + */ + function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) { + var alreadySelectedCollectionElements, selectElement, collectionContainer, + removeSelectElement; + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid configuration "collectionName"', + 1478362968 + ); + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475423098 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475423099 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475423100 + ); + assert( + 'array' === $.type(editorConfiguration['selectOptions']), + 'Invalid configuration "selectOptions"', + 1475423101 + ); + + if (collectionName === 'finishers') { + collectionContainer = getFinishersContainerDomElement(); + alreadySelectedCollectionElements = getRootFormElement().get(collectionName); + } else { + collectionContainer = getValidatorsContainerDomElement(); + alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName); + } + + collectionContainer.off().empty(); + + getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']); + selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml); + + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) { + getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [ + alreadySelectedCollectionElements[i]['identifier'], + collectionName + ]); + } + } + + removeSelectElement = true; + for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { + var appendOption = true; + if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { + for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) { + if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) { + appendOption = false; + break; } + } + } + if (appendOption) { + selectElement.append(new Option( + editorConfiguration['selectOptions'][i]['label'], + editorConfiguration['selectOptions'][i]['value'] + )); + if (editorConfiguration['selectOptions'][i]['value'] !== '') { + removeSelectElement = false; + } + } + } - for (var i = 0; i < collectionElementEditorsLength; ++i) { - var html, template; - - template = getHelper() - .getTemplate(collectionElementConfiguration['editors'][i]['templateName']) - .clone(); - if (!template.length) { - continue; - } - html = $(template.html()); - - $(html).first() - .addClass(_getCollectionElementClass( - collectionName, - collectionElementConfiguration['editors'][i]['identifier'] - )) - .addClass(getHelper().getDomElementClassName('inspectorEditor')); - - if (i === 0 && collapseWrapper) { - getCollectionElementDomElement(collectionName, collectionElementIdentifier) - .append(html) - .append(collapseWrapper); - } else if ( - i === (collectionElementEditorsLength - 1) - && collapseWrapper - && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton' - ) { - getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); - } else if (i > 0 && collapseWrapper) { - collapseWrapper.append(html); - } else { - getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html); - } + if (removeSelectElement) { + selectElement.off().empty().remove(); + } - _renderEditorDispatcher( - collectionElementConfiguration['editors'][i], - html, - collectionElementIdentifier, - collectionName - ); - } + selectElement.on('change', function() { + if ($(this).val() !== '') { + var value = $(this).val(); + $('option[value="' + value + '"]', $(this)).remove(); + getFormEditorApp().getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [value, collectionName] + ); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421525 + * @throws 1475421526 + * @throws 1475421527 + * @throws 1475421528 + */ + function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526); + + Icons.getIcon( + getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + getHelper().getTemplatePropertyDomElement('header-label', editorHtml) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))) + .append(buildTitleByFormElement()); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421257 + * @throws 1475421258 + * @throws 1475421259 + */ + function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var collectionElementConfiguration, setData; + + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421258 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421257 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421259 + ); + + setData = function(icon) { + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend($(icon)); + + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('collapse'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + var iconWrap; + iconWrap = $('<a></a>') + .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true)) + .attr('data-toggle', 'collapse') + .attr('aria-expanded', 'true') + .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier)) + .addClass('collapsed') + .append($(icon)); + + getHelper() + .getTemplatePropertyDomElement('header-label', editorHtml) + .prepend(iconWrap); + }); + }; + + collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier); + if (collectionName === 'validators') { + Icons.getIcon( + collectionElementConfiguration['iconIdentifier'], + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + setData(icon); + }); + } else { + Icons.getIcon( + collectionElementConfiguration['iconIdentifier'], + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + setData(icon); + }); + } + + if (editorConfiguration['label']) { + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + } + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421053 + * @throws 1475421054 + * @throws 1475421055 + * @throws 1475421056 + */ + function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421053 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421054 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421055 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475421056 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration['propertyPath'], + collectionElementIdentifier, + collectionName + ); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + _validateCollectionElement(propertyPath, editorHtml); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); + + renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { + if ( + !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] + && !getUtility().isNonEmptyString($(this).val()) + ) { + getCurrentlySelectedFormElement().unset(propertyPath); + } else { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + } + _validateCollectionElement(propertyPath, editorHtml); + if ( + !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths']) + && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths']) + ) { + for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) { if ( - ( - collectionElementEditorsLength === 2 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton' - ) || ( - collectionElementEditorsLength === 1 - && collectionElementConfiguration['editors'][0]['identifier'] === 'header' - ) + !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] + && !getUtility().isNonEmptyString($(this).val()) ) { - $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove(); - } - - if (_configuration['isSortable']) { - _addSortableCollectionElementsEvents(collectionContainer, collectionName); - } - }; - - /** - * @public - * - * @string collectionName - * @param object editorConfiguration - * @param object editorHtml - * @return void - * @publish view/inspector/collectionElement/existing/selected - * @publish view/inspector/collectionElement/new/selected - * @throws 1475423098 - * @throws 1475423099 - * @throws 1475423100 - * @throws 1475423101 - * @throws 1478362968 - */ - function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) { - var alreadySelectedCollectionElements, selectElement, collectionContainer, removeSelectElement; - assert( - getUtility().isNonEmptyString(collectionName), - 'Invalid configuration "collectionName"', - 1478362968 - ); - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475423098 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475423099 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475423100 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1475423101 - ); - - if (collectionName === 'finishers') { - collectionContainer = getFinishersContainerDomElement(); - alreadySelectedCollectionElements = getRootFormElement().get(collectionName); + getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]); } else { - collectionContainer = getValidatorsContainerDomElement(); - alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName); + getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val()); } + } + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475421048 + * @throws 1475421049 + * @throws 1475421050 + * @throws 1475421051 + * @throws 1475421052 + */ + function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath, selectElement; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475421048 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475421049 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475421050 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475421051 + ); + assert( + 'array' === $.type(editorConfiguration['selectOptions']), + 'Invalid configuration "selectOptions"', + 1475421052 + ); + + propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration['propertyPath'], + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) { + var option; + + if (editorConfiguration['selectOptions'][i]['value'] === propertyData) { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); + } else { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i); + } + $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); + selectElement.append(option); + } + + selectElement.on('change', function() { + getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value')); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1485712399 + * @throws 1485712400 + * @throws 1485712401 + * @throws 1485712402 + * @throws 1485712403 + */ + function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath, selectElement; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1485712399 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1485712400 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1485712401 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1485712402 + ); + assert( + 'array' === $.type(editorConfiguration['selectOptions']), + 'Invalid configuration "selectOptions"', + 1485712403 + ); + + propertyPath = getFormEditorApp().buildPropertyPath( + editorConfiguration['propertyPath'], + collectionElementIdentifier, + collectionName + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + selectElement = getHelper() + .getTemplatePropertyDomElement('selectOptions', editorHtml); + + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { + var option, value; + + option = null; + for (var propertyDataKey in propertyData) { + if (!propertyData.hasOwnProperty(propertyDataKey)) { + continue; + } + if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); + break; + } + } - collectionContainer.off().empty(); - - getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']); - selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml); - - if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { - for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) { - getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [ - alreadySelectedCollectionElements[i]['identifier'], - collectionName - ]); - } - } + if (!option) { + option = new Option(editorConfiguration['selectOptions'][i]['label'], i); + } - removeSelectElement = true; - for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { - var appendOption = true; - if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) { - for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) { - if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) { - appendOption = false; - break; - } - } - } - if (appendOption) { - selectElement.append(new Option( - editorConfiguration['selectOptions'][i]['label'], - editorConfiguration['selectOptions'][i]['value'] - )); - if (editorConfiguration['selectOptions'][i]['value'] !== '') { - removeSelectElement = false; - } - } - } + $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); + + selectElement.append(option); + } + + selectElement.on('change', function() { + var selectValues = []; + $('option:selected', $(this)).each(function(i) { + selectValues.push($(this).data('value')); + }); + + getCurrentlySelectedFormElement().set(propertyPath, selectValues); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1489528242 + * @throws 1489528243 + * @throws 1489528244 + * @throws 1489528245 + * @throws 1489528246 + * @throws 1489528247 + */ + function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement, + viewportButtonTemplate; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1489528242 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1489528243 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1489528244 + ); + assert( + 'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']), + 'Invalid configurationOptions "viewPorts"', + 1489528245 + ); + assert( + !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']), + 'Invalid configurationOptions "numbersOfColumnsToUse"', + 1489528246 + ); + assert( + !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']), + 'Invalid configuration "selectOptions"', + 1489528247 + ); + + if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) { + editorHtml.remove(); + return; + } + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + + viewportButtonTemplate = $(getHelper() + .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) + .clone(); + + $(getHelper() + .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) + .remove(); + + numbersOfColumnsTemplate = getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .clone(); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .remove(); + + editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml); + + initNumbersOfColumnsField = function(element) { + var numbersOfColumnsTemplateClone, propertyPath; + + getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) + .off() + .empty() + .remove(); + + numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); + _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); + + $('input', numbersOfColumnsTemplateClone).focus(); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone) + .append( + editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label'] + .replace('{@viewPortLabel}', element.data('viewPortLabel')) + ); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone) + .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']); + + propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath'] + .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier')); + + getHelper() + .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone) + .val(getCurrentlySelectedFormElement().get(propertyPath)); + + getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() { + var that = $(this); + if (!$.isNumeric(that.val())) { + that.val(''); + } else { + getCurrentlySelectedFormElement().set(propertyPath, that.val()); + } + }); + }; + + for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) { + var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier, + viewPortLabel; + + viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier']; + viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label']; + + viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true); + viewportButtonTemplateClone.text(viewPortLabel); + viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier); + viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel); + editorControlsWrapper.append(viewportButtonTemplateClone); + + if (i === (len - 1)) { + numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); + _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); + initNumbersOfColumnsField(viewportButtonTemplateClone); + viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active')); + } - if (removeSelectElement) { - selectElement.off().empty().remove(); + $('button', editorControlsWrapper).on('click', function() { + var that = $(this); + + $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active')); + that.addClass(getHelper().getDomElementClassName('active')); + + initNumbersOfColumnsField(that); + }); + } + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475419226 + * @throws 1475419227 + * @throws 1475419228 + * @throws 1475419229 + * @throws 1475419230 + * @throws 1475419231 + * @throws 1475419232 + */ + function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix, + rowItemTemplate, setData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475419226 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475419227 + ); + assert( + 'boolean' === $.type(editorConfiguration['enableAddRow']), + 'Invalid configuration "enableAddRow"', + 1475419228 + ); + assert( + 'boolean' === $.type(editorConfiguration['enableDeleteRow']), + 'Invalid configuration "enableDeleteRow"', + 1475419230 + ); + assert( + 'boolean' === $.type(editorConfiguration['isSortable']), + 'Invalid configuration "isSortable"', + 1475419229 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475419231 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475419232 + ); + + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + propertyPathPrefix = getFormEditorApp().buildPropertyPath( + undefined, + collectionElementIdentifier, + collectionName, + undefined, + true + ); + if (getUtility().isNonEmptyString(propertyPathPrefix)) { + propertyPathPrefix = propertyPathPrefix + '.'; + } + + if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) { + multiSelection = false; + } else { + multiSelection = !!editorConfiguration['multiSelection']; + } + + rowItemTemplate = $( + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + $(editorHtml) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove(); + + if (!!editorConfiguration['enableDeleteRow']) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), + $(rowItemTemplate) + ).on('click', function() { + if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .off() + .empty() + .remove(); + + _setPropertyGridData( + $(editorHtml), + multiSelection, + editorConfiguration['propertyPath'], + propertyPathPrefix + ); + } else { + Notification.error( + editorConfiguration['removeLastAvailableRowFlashMessageTitle'], + editorConfiguration['removeLastAvailableRowFlashMessageMessage'], + 2 + ); + } + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + if (!!editorConfiguration['isSortable']) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .addClass(getHelper().getDomElementClassName('sortable')) + .sortable({ + revert: 'true', + items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), + update: function(e, o) { + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); } + }); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate)) + .parent() + .off() + .empty(); + } + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), + $(rowItemTemplate) + ).on('change', function() { + if (!multiSelection) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml)) + .not($(this)) + .prop('checked', false); + } + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); + }); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' + + getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), + $(rowItemTemplate) + ).on('keyup paste', function() { + _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); + }); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), + $(rowItemTemplate) + ).on('focusout', function() { + if ('' === $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val() + ) { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) + .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) + .val($(this).val()); + } + }); + + if (!!editorConfiguration['enableAddRow']) { + addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() { + $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem')) + .before($(rowItemTemplate).clone(true, true)); + }); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(addRowTemplate).clone(true, true)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); + } + + defaultValue = {}; + if (multiSelection) { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'); + } + } else { + if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { + defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')}; + } + } + propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {}; + + setData = function(label, value) { + var isPreselected, newRowTemplate; + + isPreselected = false; + newRowTemplate = $(rowItemTemplate).clone(true, true); + + for (var defaultValueKey in defaultValue) { + if (!defaultValue.hasOwnProperty(defaultValueKey)) { + continue; + } + if (defaultValue[defaultValueKey] === value) { + isPreselected = true; + break; + } + } - selectElement.on('change', function() { - if ($(this).val() !== '') { - var value = $(this).val(); - $('option[value="' + value + '"]', $(this)).remove(); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label); + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value); + if (isPreselected) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate)) + .prop('checked', true); + } - getFormEditorApp().getPublisherSubscriber().publish( - 'view/inspector/collectionElement/new/selected', - [value, collectionName] - ); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421525 - * @throws 1475421526 - * @throws 1475421527 - * @throws 1475421528 - */ - function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525); - assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526); + if (!!editorConfiguration['enableAddRow']) { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)) + .before($(newRowTemplate)); + } else { + $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) + .prepend($(newRowTemplate)); + } + }; + + if ('object' === $.type(propertyData)) { + for (var propertyDataKey in propertyData) { + if (!propertyData.hasOwnProperty(propertyDataKey)) { + continue; + } + setData(propertyData[propertyDataKey], propertyDataKey); + } + } else if ('array' === $.type(propertyData)) { + for (var propertyDataKey in propertyData) { + if (!propertyData.hasOwnProperty(propertyDataKey)) { + continue; + } + if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) { + setData(propertyData[propertyDataKey], propertyDataKey); + } else { + setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']); + } + } + } + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @publish view/inspector/collectionElement/new/selected + * @publish view/inspector/removeCollectionElement/perform + * @throws 1475417093 + * @throws 1475417094 + * @throws 1475417095 + * @throws 1475417096 + */ + function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyPath, propertyValue, validatorIdentifier; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475417093 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475417094 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']), + 'Invalid configuration "validatorIdentifier"', + 1475417095 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475417096 + ); + + validatorIdentifier = editorConfiguration['validatorIdentifier']; + getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + + if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) { + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + } + if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) { + propertyValue = editorConfiguration['propertyValue']; + } else { + propertyValue = ''; + } + + if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().set(propertyPath, propertyValue); + } + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function() { + if ($(this).is(":checked")) { + getPublisherSubscriber().publish( + 'view/inspector/collectionElement/new/selected', + [validatorIdentifier, 'validators'] + ); + + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().set(propertyPath, propertyValue); + } + } else { + getPublisherSubscriber().publish( + 'view/inspector/removeCollectionElement/perform', + [validatorIdentifier, 'validators'] + ); + if (getUtility().isNonEmptyString(propertyPath)) { + getCurrentlySelectedFormElement().unset(propertyPath); + } + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1476218671 + * @throws 1476218672 + * @throws 1476218673 + * @throws 1476218674 + */ + function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyData, propertyPath; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1476218671 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1476218672 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1476218673 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1476218674 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + if ( + ('boolean' === $.type(propertyData) && propertyData) + || propertyData === 'true' + || propertyData === 1 + || propertyData === "1" + ) { + $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); + } + + $('input[type="checkbox"]', $(editorHtml)).on('change', function() { + if ($(this).is(":checked")) { + getCurrentlySelectedFormElement().set(propertyPath, true); + } else { + getCurrentlySelectedFormElement().set(propertyPath, false); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475412567 + * @throws 1475412568 + * @throws 1475416098 + * @throws 1475416099 + */ + function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var propertyPath, propertyData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1475412567 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1475412568 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1475416098 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1475416099 + ); + + propertyPath = getFormEditorApp() + .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); + + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + $('textarea', $(editorHtml)).val(propertyData); + + $('textarea', $(editorHtml)).on('keyup paste', function() { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1477300587 + * @throws 1477300588 + * @throws 1477300589 + * @throws 1477300590 + * @throws 1477318981 + * @throws 1477319859 + */ + function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + var iconType, propertyPath, propertyData; + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1477300587 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1477300588 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['label']), + 'Invalid configuration "label"', + 1477300589 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['buttonLabel']), + 'Invalid configuration "buttonLabel"', + 1477318981 + ); + assert( + getUtility().isNonEmptyString(editorConfiguration['propertyPath']), + 'Invalid configuration "propertyPath"', + 1477300590 + ); + assert( + 'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'], + 'Invalid configuration "browsableType"', + 1477319859 + ); + + getHelper() + .getTemplatePropertyDomElement('label', editorHtml) + .append(editorConfiguration['label']); + getHelper() + .getTemplatePropertyDomElement('buttonLabel', editorHtml) + .append(editorConfiguration['buttonLabel']); + + if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .text(editorConfiguration['fieldExplanationText']); + } else { + getHelper() + .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) + .remove(); + } + + $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']); + + iconType = ('tt_content' === editorConfiguration['browsableType']) + ? getHelper().getDomElementDataAttributeValue('iconTtContent') + : getHelper().getDomElementDataAttributeValue('iconPage'); + Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) { + getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon)); + }); + + getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() { + var insertTarget, randomIdentifier; + + randomIdentifier = Math.floor((Math.random() * 100000) + 1); + insertTarget = $(this) + .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper')) + .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey')); + + insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier); + _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']); + }); + + propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); + + _validateCollectionElement(propertyPath, editorHtml); + getHelper() + .getTemplatePropertyDomElement('propertyPath', editorHtml) + .val(propertyData); + + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { + getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + _validateCollectionElement(propertyPath, editorHtml); + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string collectionElementIdentifier + * @param string collectionName + * @return void + * @throws 1475412563 + * @throws 1475412564 + */ + function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { + assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563); + assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564); + + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + + $('button', $(editorHtml)) + .addClass( + getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' + + getHelper().getDomElementClassName('buttonFormEditor') + ); + } else { + $('button', $(editorHtml)).addClass( + getHelper().getDomElementClassName('buttonCollectionElementRemove') + ); + } + + $('button', $(editorHtml)).on('click', function(e) { + if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { + getViewModel().showRemoveFormElementModal(); + } else { + getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName); + } + }); + }; + + /** + * @public + * + * @param object editorConfiguration + * @param object editorHtml + * @param string propertyPath + * @return void + * @throws 1484574704 + * @throws 1484574705 + * @throws 1484574706 + */ + function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) { + var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper, + formElementSelectorSplitButtonListContainer, itemTemplate; + + assert( + 'object' === $.type(editorConfiguration), + 'Invalid parameter "editorConfiguration"', + 1484574704 + ); + assert( + 'object' === $.type(editorHtml), + 'Invalid parameter "editorHtml"', + 1484574705 + ); + assert( + getUtility().isNonEmptyString(propertyPath), + 'Invalid parameter "propertyPath"', + 1484574706 + ); + + formElementSelectorControlsWrapper = $( + getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml + ); + + if (editorConfiguration['enableFormelementSelectionButton'] === true) { + if (formElementSelectorControlsWrapper.length === 0) { + return; + } + formElementSelectorSplitButtonListContainer = $( + getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml + ); + + formElementSelectorSplitButtonListContainer.off().empty(); + nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements(); + + if (nonCompositeNonToplevelFormElements.length === 0) { + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('iconNotAvailable'), + Icons.sizes.small, + null, + Icons.states.default + ).done(function(icon) { + itemTemplate = $('<li data-no-sorting>' + + '<a href="#"></a>' + + '</li>'); + + itemTemplate + .append($(icon)) + .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements')); + formElementSelectorSplitButtonListContainer.append(itemTemplate); + }); + } else { + for (var i = 0, len = nonCompositeNonToplevelFormElements.length; i < len; ++i) { + var nonCompositeNonToplevelFormElement; + + nonCompositeNonToplevelFormElement = nonCompositeNonToplevelFormElements[i]; Icons.getIcon( - getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'), - Icons.sizes.small, - null, - Icons.states.default + getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default ).done(function(icon) { - getHelper().getTemplatePropertyDomElement('header-label', editorHtml) - .append($(icon).addClass(getHelper().getDomElementClassName('icon'))) - .append(buildTitleByFormElement()); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421257 - * @throws 1475421258 - * @throws 1475421259 - */ - function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var collectionElementConfiguration, setData; - - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421258 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421257 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421259 - ); - - setData = function(icon) { - getHelper() - .getTemplatePropertyDomElement('header-label', editorHtml) - .prepend($(icon)); - - Icons.getIcon( - getHelper().getDomElementDataAttributeValue('collapse'), - Icons.sizes.small, - null, - Icons.states.default, - Icons.markupIdentifiers.inline - ).done(function(icon) { - var iconWrap; - iconWrap = $('<a></a>') - .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true)) - .attr('data-toggle', 'collapse') - .attr('aria-expanded', 'true') - .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier)) - .addClass('collapsed') - .append($(icon)); - - getHelper() - .getTemplatePropertyDomElement('header-label', editorHtml) - .prepend(iconWrap); - }); - }; - - collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier); - if (collectionName === 'validators') { - Icons.getIcon( - collectionElementConfiguration['iconIdentifier'], - Icons.sizes.small, - null, - Icons.states.default - ).done(function(icon) { - setData(icon); - }); - } else { - Icons.getIcon( - collectionElementConfiguration['iconIdentifier'], - Icons.sizes.small, - null, - Icons.states.default - ).done(function(icon) { - setData(icon); - }); - } - - if (editorConfiguration['label']) { - getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - } - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421053 - * @throws 1475421054 - * @throws 1475421055 - * @throws 1475421056 - */ - function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421053 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421054 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421055 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475421056 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - _validateCollectionElement(propertyPath, editorHtml); + itemTemplate = $('<li data-no-sorting>' + + '<a href="#" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">' + + '</a>' + + '</li>'); - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); + $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate) + .append($(icon)) + .append(' ' + nonCompositeNonToplevelFormElement.get('label')); - renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath); + $('a', itemTemplate).on('click', function() { + var propertyData; - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { - if ( - !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] - && !getUtility().isNonEmptyString($(this).val()) - ) { - getCurrentlySelectedFormElement().unset(propertyPath); - } else { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); - } - _validateCollectionElement(propertyPath, editorHtml); - if ( - !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths']) - && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths']) - ) { - for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) { - if ( - !!editorConfiguration['doNotSetIfPropertyValueIsEmpty'] - && !getUtility().isNonEmptyString($(this).val()) - ) { - getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]); - } else { - getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val()); - } - } - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475421048 - * @throws 1475421049 - * @throws 1475421050 - * @throws 1475421051 - * @throws 1475421052 - */ - function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, selectElement; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475421048 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475421049 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475421050 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475421051 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1475421052 - ); + propertyData = getCurrentlySelectedFormElement().get(propertyPath); - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - selectElement = getHelper() - .getTemplatePropertyDomElement('selectOptions', editorHtml); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) { - var option; - - if (editorConfiguration['selectOptions'][i]['value'] === propertyData) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); + if (propertyData.length === 0) { + propertyData = '{' + $(this).attr('data-formelement-identifier') + '}'; } else { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i); - } - $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); - selectElement.append(option); - } - - selectElement.on('change', function() { - getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value')); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1485712399 - * @throws 1485712400 - * @throws 1485712401 - * @throws 1485712402 - * @throws 1485712403 - */ - function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath, selectElement; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1485712399 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1485712400 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1485712401 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1485712402 - ); - assert( - 'array' === $.type(editorConfiguration['selectOptions']), - 'Invalid configuration "selectOptions"', - 1485712403 - ); - - propertyPath = getFormEditorApp().buildPropertyPath( - editorConfiguration['propertyPath'], - collectionElementIdentifier, - collectionName - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - selectElement = getHelper() - .getTemplatePropertyDomElement('selectOptions', editorHtml); - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) { - var option, value; - - option = null; - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true); - break; - } + propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}'; } - if (!option) { - option = new Option(editorConfiguration['selectOptions'][i]['label'], i); - } - - $(option).data({value: editorConfiguration['selectOptions'][i]['value']}); - - selectElement.append(option); - } - - selectElement.on('change', function() { - var selectValues = []; - $('option:selected', $(this)).each(function(i) { - selectValues.push($(this).data('value')); - }); - - getCurrentlySelectedFormElement().set(propertyPath, selectValues); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1489528242 - * @throws 1489528243 - * @throws 1489528244 - * @throws 1489528245 - * @throws 1489528246 - * @throws 1489528247 - */ - function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement, viewportButtonTemplate; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1489528242 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1489528243 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1489528244 - ); - assert( - 'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']), - 'Invalid configurationOptions "viewPorts"', - 1489528245 - ); - assert( - !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']), - 'Invalid configurationOptions "numbersOfColumnsToUse"', - 1489528246 - ); - assert( - !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']), - 'Invalid configuration "selectOptions"', - 1489528247 - ); - - if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) { - editorHtml.remove(); - return; - } - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - - viewportButtonTemplate = $(getHelper() - .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) - .clone(); - - $(getHelper() - .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml)) - .remove(); - - numbersOfColumnsTemplate = getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .clone(); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .remove(); - - editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml); - - initNumbersOfColumnsField = function(element) { - var numbersOfColumnsTemplateClone, propertyPath; - - getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml)) - .off() - .empty() - .remove(); - - numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); - _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); - - $('input', numbersOfColumnsTemplateClone).focus(); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone) - .append( - editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label'] - .replace('{@viewPortLabel}', element.data('viewPortLabel')) - ); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone) - .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']); - - propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath'] - .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier')); - - getHelper() - .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone) - .val(getCurrentlySelectedFormElement().get(propertyPath)); - - getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() { - var that = $(this); - if (!$.isNumeric(that.val())) { - that.val(''); - } else { - getCurrentlySelectedFormElement().set(propertyPath, that.val()); - } - }); - }; - - for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) { - var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier, viewPortLabel; - - viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier']; - viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label']; - - viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true); - viewportButtonTemplateClone.text(viewPortLabel); - viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier); - viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel); - editorControlsWrapper.append(viewportButtonTemplateClone); - - if (i === (len - 1)) { - numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true); - _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone); - initNumbersOfColumnsField(viewportButtonTemplateClone); - viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active')); - } - - $('button', editorControlsWrapper).on('click', function() { - var that = $(this); - - $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active')); - that.addClass(getHelper().getDomElementClassName('active')); - - initNumbersOfColumnsField(that); - }); - } - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475419226 - * @throws 1475419227 - * @throws 1475419228 - * @throws 1475419229 - * @throws 1475419230 - * @throws 1475419231 - * @throws 1475419232 - */ - function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix, rowItemTemplate, setData; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475419226 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475419227 - ); - assert( - 'boolean' === $.type(editorConfiguration['enableAddRow']), - 'Invalid configuration "enableAddRow"', - 1475419228 - ); - assert( - 'boolean' === $.type(editorConfiguration['enableDeleteRow']), - 'Invalid configuration "enableDeleteRow"', - 1475419230 - ); - assert( - 'boolean' === $.type(editorConfiguration['isSortable']), - 'Invalid configuration "isSortable"', - 1475419229 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475419231 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475419232 - ); - - getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - propertyPathPrefix = getFormEditorApp().buildPropertyPath( - undefined, - collectionElementIdentifier, - collectionName, - undefined, - true - ); - if (getUtility().isNonEmptyString(propertyPathPrefix)) { - propertyPathPrefix = propertyPathPrefix + '.'; - } - - if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) { - multiSelection = false; - } else { - multiSelection = !!editorConfiguration['multiSelection']; - } - - rowItemTemplate = $( - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - $(editorHtml) - ).clone(); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove(); - - if (!!editorConfiguration['enableDeleteRow']) { - $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), - $(rowItemTemplate) - ).on('click', function() { - if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .off() - .empty() - .remove(); - - _setPropertyGridData( - $(editorHtml), - multiSelection, - editorConfiguration['propertyPath'], - propertyPathPrefix - ); - } else { - Notification.error( - editorConfiguration['removeLastAvailableRowFlashMessageTitle'], - editorConfiguration['removeLastAvailableRowFlashMessageMessage'], - 2 - ); - } - }); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate)) - .parent() - .off() - .empty(); - } - - if (!!editorConfiguration['isSortable']) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) - .addClass(getHelper().getDomElementClassName('sortable')) - .sortable({ - revert: 'true', - items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), - update: function(e, o) { - _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); - } - }); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate)) - .parent() - .off() - .empty(); - } - - $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), - $(rowItemTemplate) - ).on('change', function() { - if (!multiSelection) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml)) - .not($(this)) - .prop('checked', false); - } - _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); - }); - - $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' + - getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), - $(rowItemTemplate) - ).on('keyup paste', function() { - _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix); - }); - - $( getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), - $(rowItemTemplate) - ).on('focusout', function() { - if ('' === $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val() - ) { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem')) - .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue')) - .val($(this).val()); - } - }); - - if (!!editorConfiguration['enableAddRow']) { - addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone(); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() { - $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem')) - .before($(rowItemTemplate).clone(true, true)); - }); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) - .prepend($(addRowTemplate).clone(true, true)); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove(); - } - - defaultValue = {}; - if (multiSelection) { - if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { - defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'); - } - } else { - if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) { - defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')}; - } - } - propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {}; - - setData = function(label, value) { - var isPreselected, newRowTemplate; - - isPreselected = false; - newRowTemplate = $(rowItemTemplate).clone(true, true); - - for (var defaultValueKey in defaultValue) { - if (!defaultValue.hasOwnProperty(defaultValueKey)) { - continue; - } - if (defaultValue[defaultValueKey] === value) { - isPreselected = true; - break; - } - } - - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label); - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value); - if (isPreselected) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate)) - .prop('checked', true); - } - - if (!!editorConfiguration['enableAddRow']) { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)) - .before($(newRowTemplate)); - } else { - $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml)) - .prepend($(newRowTemplate)); - } - }; - - if ('object' === $.type(propertyData)) { - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - setData(propertyData[propertyDataKey], propertyDataKey); - } - } else if ('array' === $.type(propertyData)) { - for (var propertyDataKey in propertyData) { - if (!propertyData.hasOwnProperty(propertyDataKey)) { - continue; - } - if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) { - setData(propertyData[propertyDataKey], propertyDataKey); - } else { - setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']); - } - } - } - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @publish view/inspector/collectionElement/new/selected - * @publish view/inspector/removeCollectionElement/perform - * @throws 1475417093 - * @throws 1475417094 - * @throws 1475417095 - * @throws 1475417096 - */ - function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyPath, propertyValue, validatorIdentifier; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475417093 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475417094 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']), - 'Invalid configuration "validatorIdentifier"', - 1475417095 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475417096 - ); - - validatorIdentifier = editorConfiguration['validatorIdentifier']; - getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - - if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) { - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - } - if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) { - propertyValue = editorConfiguration['propertyValue']; - } else { - propertyValue = ''; - } - - if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) { - $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().set(propertyPath, propertyValue); - } - } - - $('input[type="checkbox"]', $(editorHtml)).on('change', function() { - if ($(this).is(":checked")) { - getPublisherSubscriber().publish( - 'view/inspector/collectionElement/new/selected', - [validatorIdentifier, 'validators'] - ); - - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().set(propertyPath, propertyValue); - } - } else { - getPublisherSubscriber().publish( - 'view/inspector/removeCollectionElement/perform', - [validatorIdentifier, 'validators'] - ); - if (getUtility().isNonEmptyString(propertyPath)) { - getCurrentlySelectedFormElement().unset(propertyPath); - } - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1476218671 - * @throws 1476218672 - * @throws 1476218673 - * @throws 1476218674 - */ - function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyData, propertyPath; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1476218671 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1476218672 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1476218673 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1476218674 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - if ( - ('boolean' === $.type(propertyData) && propertyData) - || propertyData === 'true' - || propertyData === 1 - || propertyData === "1" - ) { - $('input[type="checkbox"]', $(editorHtml)).prop('checked', true); - } - - $('input[type="checkbox"]', $(editorHtml)).on('change', function() { - if ($(this).is(":checked")) { - getCurrentlySelectedFormElement().set(propertyPath, true); - } else { - getCurrentlySelectedFormElement().set(propertyPath, false); - } - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475412567 - * @throws 1475412568 - * @throws 1475416098 - * @throws 1475416099 - */ - function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var propertyPath, propertyData; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1475412567 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1475412568 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1475416098 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1475416099 - ); - - propertyPath = getFormEditorApp() - .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']); - - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - $('textarea', $(editorHtml)).val(propertyData); - - $('textarea', $(editorHtml)).on('keyup paste', function() { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1477300587 - * @throws 1477300588 - * @throws 1477300589 - * @throws 1477300590 - * @throws 1477318981 - * @throws 1477319859 - */ - function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - var iconType, propertyPath, propertyData; - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1477300587 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1477300588 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['label']), - 'Invalid configuration "label"', - 1477300589 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['buttonLabel']), - 'Invalid configuration "buttonLabel"', - 1477318981 - ); - assert( - getUtility().isNonEmptyString(editorConfiguration['propertyPath']), - 'Invalid configuration "propertyPath"', - 1477300590 - ); - assert( - 'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'], - 'Invalid configuration "browsableType"', - 1477319859 - ); - - getHelper() - .getTemplatePropertyDomElement('label', editorHtml) - .append(editorConfiguration['label']); - getHelper() - .getTemplatePropertyDomElement('buttonLabel', editorHtml) - .append(editorConfiguration['buttonLabel']); - - if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .text(editorConfiguration['fieldExplanationText']); - } else { - getHelper() - .getTemplatePropertyDomElement('fieldExplanationText', editorHtml) - .remove(); - } - - $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']); - - iconType = ('tt_content' === editorConfiguration['browsableType']) - ? getHelper().getDomElementDataAttributeValue('iconTtContent') - : getHelper().getDomElementDataAttributeValue('iconPage'); - Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) { - getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon)); - }); - - getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() { - var insertTarget, randomIdentifier; - - randomIdentifier = Math.floor((Math.random() * 100000) + 1); - insertTarget = $(this) - .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper')) - .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey')); - - insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier); - _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']); - }); - - propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName); - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - _validateCollectionElement(propertyPath, editorHtml); - getHelper() - .getTemplatePropertyDomElement('propertyPath', editorHtml) - .val(propertyData); - - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() { - getCurrentlySelectedFormElement().set(propertyPath, $(this).val()); + getCurrentlySelectedFormElement().set(propertyPath, propertyData); + getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); _validateCollectionElement(propertyPath, editorHtml); - }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string collectionElementIdentifier - * @param string collectionName - * @return void - * @throws 1475412563 - * @throws 1475412564 - */ - function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) { - assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563); - assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564); - - if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { - - $('button', $(editorHtml)) - .addClass( - getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' + - getHelper().getDomElementClassName('buttonFormEditor') - ); - } else { - $('button', $(editorHtml)).addClass( - getHelper().getDomElementClassName('buttonCollectionElementRemove') - ); - } + }); - $('button', $(editorHtml)).on('click', function(e) { - if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) { - getViewModel().showRemoveFormElementModal(); - } else { - getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName); - } + formElementSelectorSplitButtonListContainer.append(itemTemplate); }); - }; - - /** - * @public - * - * @param object editorConfiguration - * @param object editorHtml - * @param string propertyPath - * @return void - * @throws 1484574704 - * @throws 1484574705 - * @throws 1484574706 - */ - function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) { - var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper, formElementSelectorSplitButtonListContainer, itemTemplate; - - assert( - 'object' === $.type(editorConfiguration), - 'Invalid parameter "editorConfiguration"', - 1484574704 - ); - assert( - 'object' === $.type(editorHtml), - 'Invalid parameter "editorHtml"', - 1484574705 - ); - assert( - getUtility().isNonEmptyString(propertyPath), - 'Invalid parameter "propertyPath"', - 1484574706 - ); - - formElementSelectorControlsWrapper = $( - getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml - ); - - if (editorConfiguration['enableFormelementSelectionButton'] === true) { - if (formElementSelectorControlsWrapper.length === 0) { - return; - } - - formElementSelectorSplitButtonListContainer = $( - getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml - ); - - formElementSelectorSplitButtonListContainer.off().empty(); - nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements(); - - if (nonCompositeNonToplevelFormElements.length === 0) { - Icons.getIcon( - getHelper().getDomElementDataAttributeValue('iconNotAvailable'), - Icons.sizes.small, - null, - Icons.states.default - ).done(function(icon) { - itemTemplate = $('<li data-no-sorting>' - + '<a href="#"></a>' - + '</li>'); - - itemTemplate - .append($(icon)) - .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements')); - formElementSelectorSplitButtonListContainer.append(itemTemplate); - }); - } else { - for (var i = 0, len = nonCompositeNonToplevelFormElements.length; i < len; ++i) { - var nonCompositeNonToplevelFormElement; - - nonCompositeNonToplevelFormElement = nonCompositeNonToplevelFormElements[i]; - Icons.getIcon( - getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'), - Icons.sizes.small, - null, - Icons.states.default - ).done(function(icon) { - itemTemplate = $('<li data-no-sorting>' - + '<a href="#" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">' - + '</a>' - + '</li>'); - - $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate) - .append($(icon)) - .append(' ' + nonCompositeNonToplevelFormElement.get('label')); - - $('a', itemTemplate).on('click', function() { - var propertyData; - - propertyData = getCurrentlySelectedFormElement().get(propertyPath); - - if (propertyData.length === 0) { - propertyData = '{' + $(this).attr('data-formelement-identifier') + '}'; - } else { - propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}'; - } - - getCurrentlySelectedFormElement().set(propertyPath, propertyData); - getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData); - _validateCollectionElement(propertyPath, editorHtml); - }); - - formElementSelectorSplitButtonListContainer.append(itemTemplate); - }); - } - } - } else { - $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml) - .removeClass(getHelper().getDomElementClassName('inspectorInputGroup')); - formElementSelectorControlsWrapper.off().empty().remove(); - } + } } - - /** - * @public - * - * @param string content - * @return void - */ - function setFormElementHeaderEditorContent(content) { - if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) { - content = buildTitleByFormElement(); - } - - $(getHelper() - .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement()) - .html(content); - }; - - /** - * @public - * - * @param object - * @return object - * @throws 1478967319 - */ - function buildTitleByFormElement(formElement) { - var label; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319); - - return $('<span></span>').text((formElement.get('label') - ? formElement.get('label') - : formElement.get('identifier'))); - }; - - /** - * @public - * - * @param object - * @param object - * @return this - */ - function bootstrap(formEditorApp, configuration) { - _formEditorApp = formEditorApp; - _configuration = $.extend(true, _defaultConfiguration, configuration || {}); - _helperSetup(); - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - buildTitleByFormElement: buildTitleByFormElement, - getCollectionElementDomElement: getCollectionElementDomElement, - getFinishersContainerDomElement: getFinishersContainerDomElement, - getInspectorDomElement: getInspectorDomElement, - getValidatorsContainerDomElement: getValidatorsContainerDomElement, - renderCheckboxEditor: renderCheckboxEditor, - renderCollectionElementEditors: renderCollectionElementEditors, - renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor, - renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor, - renderEditors: renderEditors, - renderFormElementHeaderEditor: renderFormElementHeaderEditor, - renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition, - renderPropertyGridEditor: renderPropertyGridEditor, - renderRemoveElementEditor: renderRemoveElementEditor, - renderRequiredValidatorEditor: renderRequiredValidatorEditor, - renderSingleSelectEditor: renderSingleSelectEditor, - renderMultiSelectEditor: renderMultiSelectEditor, - renderTextareaEditor: renderTextareaEditor, - renderTextEditor: renderTextEditor, - renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor, - setFormElementHeaderEditorContent: setFormElementHeaderEditorContent - }; - })($, Helper, Icons, Notification); + } else { + $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml) + .removeClass(getHelper().getDomElementClassName('inspectorInputGroup')); + formElementSelectorControlsWrapper.off().empty().remove(); + } + } + + /** + * @public + * + * @param string content + * @return void + */ + function setFormElementHeaderEditorContent(content) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) { + content = buildTitleByFormElement(); + } + + $(getHelper() + .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement()) + .html(content); + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1478967319 + */ + function buildTitleByFormElement(formElement) { + var label; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319); + + return $('<span></span>').text((formElement.get('label') + ? formElement.get('label') + : formElement.get('identifier'))); + }; + + /** + * @public + * + * @param object + * @param object + * @return this + */ + function bootstrap(formEditorApp, configuration) { + _formEditorApp = formEditorApp; + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + getCollectionElementDomElement: getCollectionElementDomElement, + getFinishersContainerDomElement: getFinishersContainerDomElement, + getInspectorDomElement: getInspectorDomElement, + getValidatorsContainerDomElement: getValidatorsContainerDomElement, + renderCheckboxEditor: renderCheckboxEditor, + renderCollectionElementEditors: renderCollectionElementEditors, + renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor, + renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor, + renderEditors: renderEditors, + renderFormElementHeaderEditor: renderFormElementHeaderEditor, + renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition, + renderPropertyGridEditor: renderPropertyGridEditor, + renderRemoveElementEditor: renderRemoveElementEditor, + renderRequiredValidatorEditor: renderRequiredValidatorEditor, + renderSingleSelectEditor: renderSingleSelectEditor, + renderMultiSelectEditor: renderMultiSelectEditor, + renderTextareaEditor: renderTextareaEditor, + renderTextEditor: renderTextEditor, + renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor, + setFormElementHeaderEditorContent: setFormElementHeaderEditorContent + }; + })($, Helper, Icons, Notification); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js index 8a30e1068131abb4ba6866c712bfcc17cc1ad60f..f698da186a9694c8ce00317051a8b6913639c4fc 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js @@ -15,1077 +15,1077 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/Mediator */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper' - ], function($, Helper) { - 'use strict'; - - return (function($, Helper) { - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /** - * @private - * - * @var object - */ - var _viewModel = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @private - * - * @return object - */ - function getViewModel() { - return _viewModel; - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(getViewModel().getConfiguration()); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return void - */ - function _subscribeEvents() { - - /* ********************************************************* - * Misc - * ********************************************************/ - - /** - * @private - * - * @return string - */ - window.onbeforeunload = function(e) { - if (!getFormEditorApp().getUnsavedContent()) { - return; - } - e = e || window.event; - if (e) { - e.returnValue = getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'); - } - return getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'); - }; - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/ready - */ - getPublisherSubscriber().subscribe('view/ready', function(topic, args) { - getViewModel().onViewReadyBatch(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = applicationState - * args[1] = stackPointer - * args[2] = stackSize - * @return void - * @subscribe core/applicationState/add - */ - getPublisherSubscriber().subscribe('core/applicationState/add', function(topic, args) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - if (args[2] > 1 && args[1] <= args[2]) { - getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - } else { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - } - }); - - /* ********************************************************* - * Ajax - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * args[0] = html - * @return void - * @subscribe core/ajax/saveFormDefinition/success - */ - getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/success', function(topic, args) { - getFormEditorApp().setUnsavedContent(false); - getViewModel().showSaveSuccessMessage(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = object - * @return void - * @subscribe core/ajax/saveFormDefinition/error - */ - getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/error', function(topic, args) { - getViewModel().showSaveErrorMessage(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = html - * args[1] = pageIndex - * @return void - * @subscribe core/ajax/renderFormDefinitionPage/success - */ - getPublisherSubscriber().subscribe('core/ajax/renderFormDefinitionPage/success', function(topic, args) { - getViewModel().renderPreviewStageArea(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = jqXHR - * args[1] = textStatus - * args[2] = errorThrown - * @return void - * @subscribe core/ajax/saveFormDefinition/error - */ - getPublisherSubscriber().subscribe('core/ajax/error', function(topic, args) { - if (args[0].status !== 0) { - getViewModel().showErrorFlashMessage(args[1], args[2]); - getViewModel().renderPreviewStageArea(args[0].responseText); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe ajax/beforeSend - */ - getPublisherSubscriber().subscribe('ajax/beforeSend', function(topic, args) { - getViewModel().showSaveButtonSpinnerIcon(); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe ajax/complete - */ - getPublisherSubscriber().subscribe('ajax/complete', function(topic, args) { - getViewModel().showSaveButtonSaveIcon(); - }); - - /* ********************************************************* - * Header - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/header/button/save/clicked - */ - getPublisherSubscriber().subscribe('view/header/button/save/clicked', function(topic, args) { - if (getFormEditorApp().validationResultsHasErrors(getFormEditorApp().validateFormElementRecursive(getRootFormElement(), true))) { - getViewModel().showValidationErrorsModal(); - } else { - getFormEditorApp().saveFormDefinition(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/header/formSettings/clicked - */ - getPublisherSubscriber().subscribe('view/header/formSettings/clicked', function(topic, args) { - getViewModel().addStructureRootElementSelection(); - getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement()); - getViewModel().renderAbstractStageArea(); - getViewModel().renewStructure(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = targetEvent - * @return void - * @subscribe view/header/button/newPage/clicked - */ - getPublisherSubscriber().subscribe('view/header/button/newPage/clicked', function(topic, args) { - if (getFormEditorApp().isRootFormElementSelected()) { - getViewModel().selectPageBatch(0); - } - getViewModel().showInsertPagesModal(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/header/button/close/clicked - */ - getPublisherSubscriber().subscribe('view/header/button/close/clicked', function(topic, args) { - getViewModel().showCloseConfirmationModal(); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/undoButton/clicked - */ - getPublisherSubscriber().subscribe('view/undoButton/clicked', function(topic, args) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - getFormEditorApp().undoApplicationState(); - - if (getViewModel().getPreviewMode()) { - getFormEditorApp().renderCurrentFormPage(); - } else { - getViewModel().renderAbstractStageArea(); - } - getFormEditorApp().setUnsavedContent(true); - - getViewModel().renewStructure(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/redoButton/clicked - */ - getPublisherSubscriber().subscribe('view/redoButton/clicked', function(topic, args) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - getFormEditorApp().redoApplicationState(); - - if (getViewModel().getPreviewMode()) { - getFormEditorApp().renderCurrentFormPage(); - } else { - getViewModel().renderAbstractStageArea(); - } - getFormEditorApp().setUnsavedContent(true); - - getViewModel().renewStructure(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - }); - - /* ********************************************************* - * Stage - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementIdentifierPath - * @return void - * @subscribe view/stage/element/clicked - */ - getPublisherSubscriber().subscribe('view/stage/element/clicked', function(topic, args) { - if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - getViewModel().renewStructure(); - getViewModel().refreshSelectedElementItemsBatch(); - getViewModel().addAbstractViewValidationResults(); - getViewModel().renderInspectorEditors(); - } - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = targetEvent - * args[1] = configuration - * @return void - * @subscribe view/stage/abstract/elementToolbar/button/newElement/clicked - */ - getPublisherSubscriber().subscribe('view/stage/abstract/elementToolbar/button/newElement/clicked', function(topic, args) { - if (getFormEditorApp().isRootFormElementSelected()) { - getViewModel().selectPageBatch(0); - } - getViewModel().showInsertElementsModal(args[0], args[1]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = targetEvent - * args[1] = configuration - * @return void - * @subscribe view/newElementButton/clicked - */ - getPublisherSubscriber().subscribe('view/stage/abstract/button/newElement/clicked', function(topic, args) { - if (getFormEditorApp().isRootFormElementSelected()) { - getViewModel().selectPageBatch(0); - } - getViewModel().showInsertElementsModal(args[0], args[1]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = draggedFormElementDomElement - * args[1] = draggedFormPlaceholderDomElement - * @return void - * @subscribe view/stage/abstract/dnd/start - */ - getPublisherSubscriber().subscribe('view/stage/abstract/dnd/start', function(topic, args) { - getViewModel().onAbstractViewDndStartBatch(args[0], args[1]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = draggedFormElementIdentifierPath - * @return void - * @subscribe view/stage/abstract/dnd/stop - */ - getPublisherSubscriber().subscribe('view/stage/abstract/dnd/stop', function(topic, args) { - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - getViewModel().renewStructure(); - getViewModel().renderAbstractStageArea(false, false); - getViewModel().refreshSelectedElementItemsBatch(); - getViewModel().addAbstractViewValidationResults(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = placeholderDomElement - * args[1] = parentFormElementIdentifierPath - * args[2] = enclosingCompositeFormElement - * @return void - * @subscribe view/stage/abstract/dnd/change - */ - getPublisherSubscriber().subscribe('view/stage/abstract/dnd/change', function(topic, args) { - getViewModel().onAbstractViewDndChangeBatch(args[0], args[1], args[2]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = movedDomElement - * args[1] = movedFormElementIdentifierPath - * args[2] = previousFormElementIdentifierPath - * args[3] = nextFormElementIdentifierPath - * @return void - * @subscribe view/stage/abstract/dnd/update - */ - getPublisherSubscriber().subscribe('view/stage/abstract/dnd/update', function(topic, args) { - getViewModel().onAbstractViewDndUpdateBatch(args[0], args[1], args[2], args[3]); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/viewModeButton/abstract/clicked - */ - getPublisherSubscriber().subscribe('view/viewModeButton/abstract/clicked', function(topic, args) { - if (getViewModel().getPreviewMode()) { - getViewModel().setPreviewMode(false); - getViewModel().renderAbstractStageArea(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/viewModeButton/preview/clicked - */ - getPublisherSubscriber().subscribe('view/viewModeButton/preview/clicked', function(topic, args) { - if (!getViewModel().getPreviewMode()) { - getViewModel().setPreviewMode(true); - getFormEditorApp().renderCurrentFormPage(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/paginationPrevious/clicked - */ - getPublisherSubscriber().subscribe('view/paginationPrevious/clicked', function(topic, args) { - getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() - 1); - if (getViewModel().getPreviewMode()) { - getFormEditorApp().renderCurrentFormPage(); - } else { - getViewModel().renderAbstractStageArea(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/paginationNext/clicked - */ - getPublisherSubscriber().subscribe('view/paginationNext/clicked', function(topic, args) { - getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() + 1); - if (getViewModel().getPreviewMode()) { - getFormEditorApp().renderCurrentFormPage(); - } else { - getViewModel().renderAbstractStageArea(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/stage/abstract/render/postProcess - */ - getPublisherSubscriber().subscribe('view/stage/abstract/render/postProcess', function(topic, args) { - getViewModel().renderUndoRedo(); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/stage/preview/render/postProcess - */ - getPublisherSubscriber().subscribe('view/stage/preview/render/postProcess', function(topic, args) { - getViewModel().renderUndoRedo(); - }); - - /* ********************************************************* - * Structure - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementIdentifierPath - * @return void - * @subscribe view/tree/node/clicked - */ - getPublisherSubscriber().subscribe('view/tree/node/clicked', function(topic, args) { - var oldPageIndex; - if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { - oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { - getViewModel().renderAbstractStageArea(); - } else { - getViewModel().renderAbstractStageArea(false); - } - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - } - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/structure/root/selected - */ - getPublisherSubscriber().subscribe('view/structure/root/selected', function(topic, args) { - if (!getFormEditorApp().isRootFormElementSelected()) { - getViewModel().addStructureRootElementSelection(); - getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement()); - getViewModel().renderAbstractStageArea(); - getViewModel().renewStructure(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - } - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = targetEvent - * @return void - * @subscribe view/header/button/newPage/clicked - */ - getPublisherSubscriber().subscribe('view/structure/button/newPage/clicked', function(topic, args) { - if (getFormEditorApp().isRootFormElementSelected()) { - getViewModel().selectPageBatch(0); - } - getViewModel().showInsertPagesModal(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = draggedFormElementIdentifierPath - * @return void - * @subscribe view/tree/dnd/stop - */ - getPublisherSubscriber().subscribe('view/tree/dnd/stop', function(topic, args) { - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - getViewModel().renewStructure(); - getViewModel().renderPagination(); - getViewModel().renderAbstractStageArea(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = placeholderDomElement - * args[1] = parentFormElementIdentifierPath - * args[2] = enclosingCompositeFormElement - * @return void - * @subscribe view/tree/dnd/change - */ - getPublisherSubscriber().subscribe('view/tree/dnd/change', function(topic, args) { - getViewModel().onStructureDndChangeBatch(args[0], args[1], args[2]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = movedDomElement - * args[1] = movedFormElementIdentifierPath - * args[2] = previousFormElementIdentifierPath - * args[3] = nextFormElementIdentifierPath - * @return void - * @subscribe view/tree/dnd/update - */ - getPublisherSubscriber().subscribe('view/tree/dnd/update', function(topic, args) { - getViewModel().onStructureDndUpdateBatch(args[0], args[1], args[2], args[3]); - }); - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/structure/renew/postProcess - */ - getPublisherSubscriber().subscribe('view/structure/renew/postProcess', function(topic, args) { - getViewModel().addStructureValidationResults(); - }); - - /* ********************************************************* - * Inspector - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * args[2] = formElement - * @return void - * @subscribe view/inspector/removeCollectionElement/perform - */ - getPublisherSubscriber().subscribe('view/inspector/removeCollectionElement/perform', function(topic, args) { - getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * @return void - * @subscribe view/inspector/collectionElement/selected - */ - getPublisherSubscriber().subscribe('view/inspector/collectionElement/new/selected', function(topic, args) { - getViewModel().createAndAddPropertyCollectionElement(args[0], args[1]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * @return void - * @subscribe view/inspector/collectionElement/selected - */ - getPublisherSubscriber().subscribe('view/inspector/collectionElement/existing/selected', function(topic, args) { - getViewModel().renderInspectorCollectionElementEditors(args[1], args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = movedCollectionElementIdentifier - * args[1] = previousCollectionElementIdentifier - * args[2] = nextCollectionElementIdentifier - * args[3] = collectionName - * @return void - * @subscribe view/inspector/collectionElements/dnd/update - * @throws 1477407673 - */ - getPublisherSubscriber().subscribe('view/inspector/collectionElements/dnd/update', function(topic, args) { - if (args[2]) { - getViewModel().movePropertyCollectionElement(args[0], 'before', args[2], args[3]); - } else if (args[1]) { - getViewModel().movePropertyCollectionElement(args[0], 'after', args[1], args[3]); - } else { - assert(false, 'Next element or previous element need to be set.', 1477407673); - } - }); - - /* ********************************************************* - * Form element - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * args[0] = propertyPath - * args[1] = value - * args[2] = oldValue - * args[3] = formElementIdentifierPath - * @return void - * @subscribe core/formElement/somePropertyChanged - */ - getPublisherSubscriber().subscribe('core/formElement/somePropertyChanged', function(topic, args) { - var hasError, validationElement, validationResults; - - validationResults = []; - if ('renderables' !== args[0]) { - if (!getFormEditorApp().isRootFormElementSelected() && 'label' === args[0]) { - getViewModel().getStructure().setTreeNodeTitle(); - getViewModel().setInspectorFormElementHeaderEditorContent(); - } else if (!getFormEditorApp().getUtility().isUndefinedOrNull(args[3]) && getRootFormElement().get('__identifierPath') === args[3]) { - getViewModel().setStructureRootElementTitle(); - getViewModel().setStageHeadline(); - getViewModel().setInspectorFormElementHeaderEditorContent(); - } - - if (getViewModel().getPreviewMode()) { - getFormEditorApp().renderCurrentFormPage(); - } else { - getViewModel().renderAbstractStageArea(false, false); - } - getViewModel().addStructureValidationResults(); - } - - getFormEditorApp().setUnsavedContent(true); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = parentFormElement - * @return void - * @subscribe view/formElement/removed - */ - getPublisherSubscriber().subscribe('view/formElement/removed', function(topic, args) { - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - getViewModel().renewStructure(); - getViewModel().renderAbstractStageArea(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = newFormElement - * @return void - * @subscribe view/formElement/inserted - */ - getPublisherSubscriber().subscribe('view/formElement/inserted', function(topic, args) { - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - getViewModel().renewStructure(); - getViewModel().renderAbstractStageArea(); - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * args[2] = formElement - * args[3] = collectionElementConfiguration - * args[4] = referenceCollectionElementIdentifier - * @return void - * @subscribe view/collectionElement/new/added - */ - getPublisherSubscriber().subscribe('view/collectionElement/new/added', function(topic, args) { - getViewModel().renderInspectorEditors(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = movedCollectionElementIdentifier - * args[1] = previousCollectionElementIdentifier - * args[2] = nextCollectionElementIdentifier - * args[3] = collectionName - * @return void - * @subscribe view/collectionElement/moved - * @throws 1477407673 - */ - getPublisherSubscriber().subscribe('view/collectionElement/moved', function(topic, args) { - getViewModel().renderInspectorEditors(undefined, false); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * args[2] = formElement - * @return void - * @subscribe view/collectionElement/removed - */ - getPublisherSubscriber().subscribe('view/collectionElement/removed', function(topic, args) { - getViewModel().renderInspectorEditors(undefined, false); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementType - * @return void - * @subscribe view/insertElements/perform/bottom - */ - getPublisherSubscriber().subscribe('view/insertElements/perform/bottom', function(topic, args) { - var lastRenderable; - - lastRenderable = getFormEditorApp().getLastTopLevelElementOnCurrentPage(); - if (!lastRenderable) { - getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); - } else { - if ( - !getFormEditorApp().getFormElementDefinition(lastRenderable, '_isTopLevelFormElement') - && getFormEditorApp().getFormElementDefinition(lastRenderable, '_isCompositeFormElement') - ) { - getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); - } else { - getViewModel().createAndAddFormElement(args[0], lastRenderable); - } - } - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementType - * @return void - * @publish view/formElement/inserted - * @subscribe view/insertElements/perform/after - */ - getPublisherSubscriber().subscribe('view/insertElements/perform/after', function(topic, args) { - var newFormElement; - newFormElement = getViewModel().createAndAddFormElement(args[0], undefined, true); - newFormElement = getViewModel().moveFormElement(newFormElement, 'after', getFormEditorApp().getCurrentlySelectedFormElement()); - getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementType - * @return void - * @subscribe view/insertElements/perform/inside - */ - getPublisherSubscriber().subscribe('view/insertElements/perform/inside', function(topic, args) { - getViewModel().createAndAddFormElement(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementType - * @return void - * @subscribe view/insertElements/perform/after - */ - getPublisherSubscriber().subscribe('view/insertPages/perform', function(topic, args) { - getViewModel().createAndAddFormElement(args[0]); - }); - - /* ********************************************************* - * Modals - * ********************************************************/ - - /** - * @private - * - * @param string - * @param array - * @return void - * @subscribe view/modal/close/perform - */ - getPublisherSubscriber().subscribe('view/modal/close/perform', function(topic, args) { - getFormEditorApp().setUnsavedContent(false); - getViewModel().closeEditor(); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElement - * @return void - * @subscribe view/modal/removeFormElement/perform - */ - getPublisherSubscriber().subscribe('view/modal/removeFormElement/perform', function(topic, args) { - getViewModel().removeFormElement(args[0]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = collectionElementIdentifier - * args[1] = collectionName - * args[2] = formElement - * @return void - * @subscribe view/modal/removeCollectionElement/perform - */ - getPublisherSubscriber().subscribe('view/modal/removeCollectionElement/perform', function(topic, args) { - getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); - }); - - /** - * @private - * - * @param string - * @param array - * args[0] = formElementIdentifierPath - * @return void - * @subscribe view/modal/validationErrors/element/clicked - */ - getPublisherSubscriber().subscribe('view/modal/validationErrors/element/clicked', function(topic, args) { - var oldPageIndex; - if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { - oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); - getFormEditorApp().setCurrentlySelectedFormElement(args[0]); - - if (getViewModel().getPreviewMode()) { - getViewModel().setPreviewMode(false); - } - - if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { - getViewModel().renderAbstractStageArea(); - } else { - getViewModel().renderAbstractStageArea(false); - } - - getViewModel().renderPagination(); - getViewModel().renderInspectorEditors(); - } - }); - }; - - /** - * @public - * - * @param object - * @param object - * @return void - */ - function bootstrap(formEditorApp, viewModel) { - _formEditorApp = formEditorApp; - _viewModel = viewModel; - _helperSetup(); - _subscribeEvents(); - }; - - /** - * Implements the "Revealing Module Pattern". - */ - return { - /** - * Publish the public methods. - */ - bootstrap: bootstrap - }; - })($, Helper); + 'TYPO3/CMS/Form/Backend/FormEditor/Helper' +], function($, Helper) { + 'use strict'; + + return (function($, Helper) { + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _viewModel = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return _viewModel; + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(getViewModel().getConfiguration()); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return void + */ + function _subscribeEvents() { + + /* ********************************************************* + * Misc + * ********************************************************/ + + /** + * @private + * + * @return string + */ + window.onbeforeunload = function(e) { + if (!getFormEditorApp().getUnsavedContent()) { + return; + } + e = e || window.event; + if (e) { + e.returnValue = getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'); + } + return getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'); + }; + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/ready + */ + getPublisherSubscriber().subscribe('view/ready', function(topic, args) { + getViewModel().onViewReadyBatch(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = applicationState + * args[1] = stackPointer + * args[2] = stackSize + * @return void + * @subscribe core/applicationState/add + */ + getPublisherSubscriber().subscribe('core/applicationState/add', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + if (args[2] > 1 && args[1] <= args[2]) { + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } else { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } + }); + + /* ********************************************************* + * Ajax + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = html + * @return void + * @subscribe core/ajax/saveFormDefinition/success + */ + getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/success', function(topic, args) { + getFormEditorApp().setUnsavedContent(false); + getViewModel().showSaveSuccessMessage(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = object + * @return void + * @subscribe core/ajax/saveFormDefinition/error + */ + getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/error', function(topic, args) { + getViewModel().showSaveErrorMessage(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = html + * args[1] = pageIndex + * @return void + * @subscribe core/ajax/renderFormDefinitionPage/success + */ + getPublisherSubscriber().subscribe('core/ajax/renderFormDefinitionPage/success', function(topic, args) { + getViewModel().renderPreviewStageArea(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = jqXHR + * args[1] = textStatus + * args[2] = errorThrown + * @return void + * @subscribe core/ajax/saveFormDefinition/error + */ + getPublisherSubscriber().subscribe('core/ajax/error', function(topic, args) { + if (args[0].status !== 0) { + getViewModel().showErrorFlashMessage(args[1], args[2]); + getViewModel().renderPreviewStageArea(args[0].responseText); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe ajax/beforeSend + */ + getPublisherSubscriber().subscribe('ajax/beforeSend', function(topic, args) { + getViewModel().showSaveButtonSpinnerIcon(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe ajax/complete + */ + getPublisherSubscriber().subscribe('ajax/complete', function(topic, args) { + getViewModel().showSaveButtonSaveIcon(); + }); + + /* ********************************************************* + * Header + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/header/button/save/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/save/clicked', function(topic, args) { + if (getFormEditorApp().validationResultsHasErrors(getFormEditorApp().validateFormElementRecursive(getRootFormElement(), true))) { + getViewModel().showValidationErrorsModal(); + } else { + getFormEditorApp().saveFormDefinition(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/header/formSettings/clicked + */ + getPublisherSubscriber().subscribe('view/header/formSettings/clicked', function(topic, args) { + getViewModel().addStructureRootElementSelection(); + getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement()); + getViewModel().renderAbstractStageArea(); + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/header/button/newPage/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/newPage/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertPagesModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/header/button/close/clicked + */ + getPublisherSubscriber().subscribe('view/header/button/close/clicked', function(topic, args) { + getViewModel().showCloseConfirmationModal(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/undoButton/clicked + */ + getPublisherSubscriber().subscribe('view/undoButton/clicked', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + getFormEditorApp().undoApplicationState(); + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + getFormEditorApp().setUnsavedContent(true); + + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/redoButton/clicked + */ + getPublisherSubscriber().subscribe('view/redoButton/clicked', function(topic, args) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + getFormEditorApp().redoApplicationState(); + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + getFormEditorApp().setUnsavedContent(true); + + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /* ********************************************************* + * Stage + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/stage/element/clicked + */ + getPublisherSubscriber().subscribe('view/stage/element/clicked', function(topic, args) { + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().refreshSelectedElementItemsBatch(); + getViewModel().addAbstractViewValidationResults(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * args[1] = configuration + * @return void + * @subscribe view/stage/abstract/elementToolbar/button/newElement/clicked + */ + getPublisherSubscriber().subscribe('view/stage/abstract/elementToolbar/button/newElement/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertElementsModal(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * args[1] = configuration + * @return void + * @subscribe view/newElementButton/clicked + */ + getPublisherSubscriber().subscribe('view/stage/abstract/button/newElement/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertElementsModal(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementDomElement + * args[1] = draggedFormPlaceholderDomElement + * @return void + * @subscribe view/stage/abstract/dnd/start + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/start', function(topic, args) { + getViewModel().onAbstractViewDndStartBatch(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementIdentifierPath + * @return void + * @subscribe view/stage/abstract/dnd/stop + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/stop', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderAbstractStageArea(false, false); + getViewModel().refreshSelectedElementItemsBatch(); + getViewModel().addAbstractViewValidationResults(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = placeholderDomElement + * args[1] = parentFormElementIdentifierPath + * args[2] = enclosingCompositeFormElement + * @return void + * @subscribe view/stage/abstract/dnd/change + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/change', function(topic, args) { + getViewModel().onAbstractViewDndChangeBatch(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedDomElement + * args[1] = movedFormElementIdentifierPath + * args[2] = previousFormElementIdentifierPath + * args[3] = nextFormElementIdentifierPath + * @return void + * @subscribe view/stage/abstract/dnd/update + */ + getPublisherSubscriber().subscribe('view/stage/abstract/dnd/update', function(topic, args) { + getViewModel().onAbstractViewDndUpdateBatch(args[0], args[1], args[2], args[3]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/viewModeButton/abstract/clicked + */ + getPublisherSubscriber().subscribe('view/viewModeButton/abstract/clicked', function(topic, args) { + if (getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(false); + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/viewModeButton/preview/clicked + */ + getPublisherSubscriber().subscribe('view/viewModeButton/preview/clicked', function(topic, args) { + if (!getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(true); + getFormEditorApp().renderCurrentFormPage(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/paginationPrevious/clicked + */ + getPublisherSubscriber().subscribe('view/paginationPrevious/clicked', function(topic, args) { + getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() - 1); + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/paginationNext/clicked + */ + getPublisherSubscriber().subscribe('view/paginationNext/clicked', function(topic, args) { + getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() + 1); + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/stage/abstract/render/postProcess + */ + getPublisherSubscriber().subscribe('view/stage/abstract/render/postProcess', function(topic, args) { + getViewModel().renderUndoRedo(); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/stage/preview/render/postProcess + */ + getPublisherSubscriber().subscribe('view/stage/preview/render/postProcess', function(topic, args) { + getViewModel().renderUndoRedo(); + }); + + /* ********************************************************* + * Structure + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/tree/node/clicked + */ + getPublisherSubscriber().subscribe('view/tree/node/clicked', function(topic, args) { + var oldPageIndex; + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { + getViewModel().renderAbstractStageArea(); + } else { + getViewModel().renderAbstractStageArea(false); + } + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/structure/root/selected + */ + getPublisherSubscriber().subscribe('view/structure/root/selected', function(topic, args) { + if (!getFormEditorApp().isRootFormElementSelected()) { + getViewModel().addStructureRootElementSelection(); + getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement()); + getViewModel().renderAbstractStageArea(); + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = targetEvent + * @return void + * @subscribe view/header/button/newPage/clicked + */ + getPublisherSubscriber().subscribe('view/structure/button/newPage/clicked', function(topic, args) { + if (getFormEditorApp().isRootFormElementSelected()) { + getViewModel().selectPageBatch(0); + } + getViewModel().showInsertPagesModal(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = draggedFormElementIdentifierPath + * @return void + * @subscribe view/tree/dnd/stop + */ + getPublisherSubscriber().subscribe('view/tree/dnd/stop', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderPagination(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = placeholderDomElement + * args[1] = parentFormElementIdentifierPath + * args[2] = enclosingCompositeFormElement + * @return void + * @subscribe view/tree/dnd/change + */ + getPublisherSubscriber().subscribe('view/tree/dnd/change', function(topic, args) { + getViewModel().onStructureDndChangeBatch(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedDomElement + * args[1] = movedFormElementIdentifierPath + * args[2] = previousFormElementIdentifierPath + * args[3] = nextFormElementIdentifierPath + * @return void + * @subscribe view/tree/dnd/update + */ + getPublisherSubscriber().subscribe('view/tree/dnd/update', function(topic, args) { + getViewModel().onStructureDndUpdateBatch(args[0], args[1], args[2], args[3]); + }); + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/structure/renew/postProcess + */ + getPublisherSubscriber().subscribe('view/structure/renew/postProcess', function(topic, args) { + getViewModel().addStructureValidationResults(); + }); + + /* ********************************************************* + * Inspector + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/inspector/removeCollectionElement/perform + */ + getPublisherSubscriber().subscribe('view/inspector/removeCollectionElement/perform', function(topic, args) { + getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * @return void + * @subscribe view/inspector/collectionElement/selected + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElement/new/selected', function(topic, args) { + getViewModel().createAndAddPropertyCollectionElement(args[0], args[1]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * @return void + * @subscribe view/inspector/collectionElement/selected + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElement/existing/selected', function(topic, args) { + getViewModel().renderInspectorCollectionElementEditors(args[1], args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedCollectionElementIdentifier + * args[1] = previousCollectionElementIdentifier + * args[2] = nextCollectionElementIdentifier + * args[3] = collectionName + * @return void + * @subscribe view/inspector/collectionElements/dnd/update + * @throws 1477407673 + */ + getPublisherSubscriber().subscribe('view/inspector/collectionElements/dnd/update', function(topic, args) { + if (args[2]) { + getViewModel().movePropertyCollectionElement(args[0], 'before', args[2], args[3]); + } else if (args[1]) { + getViewModel().movePropertyCollectionElement(args[0], 'after', args[1], args[3]); + } else { + assert(false, 'Next element or previous element need to be set.', 1477407673); + } + }); + + /* ********************************************************* + * Form element + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * args[0] = propertyPath + * args[1] = value + * args[2] = oldValue + * args[3] = formElementIdentifierPath + * @return void + * @subscribe core/formElement/somePropertyChanged + */ + getPublisherSubscriber().subscribe('core/formElement/somePropertyChanged', function(topic, args) { + var hasError, validationElement, validationResults; + + validationResults = []; + if ('renderables' !== args[0]) { + if (!getFormEditorApp().isRootFormElementSelected() && 'label' === args[0]) { + getViewModel().getStructure().setTreeNodeTitle(); + getViewModel().setInspectorFormElementHeaderEditorContent(); + } else if (!getFormEditorApp().getUtility().isUndefinedOrNull(args[3]) && getRootFormElement().get('__identifierPath') === args[3]) { + getViewModel().setStructureRootElementTitle(); + getViewModel().setStageHeadline(); + getViewModel().setInspectorFormElementHeaderEditorContent(); + } + + if (getViewModel().getPreviewMode()) { + getFormEditorApp().renderCurrentFormPage(); + } else { + getViewModel().renderAbstractStageArea(false, false); + } + getViewModel().addStructureValidationResults(); + } + + getFormEditorApp().setUnsavedContent(true); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = parentFormElement + * @return void + * @subscribe view/formElement/removed + */ + getPublisherSubscriber().subscribe('view/formElement/removed', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = newFormElement + * @return void + * @subscribe view/formElement/inserted + */ + getPublisherSubscriber().subscribe('view/formElement/inserted', function(topic, args) { + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + getViewModel().renewStructure(); + getViewModel().renderAbstractStageArea(); + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * args[3] = collectionElementConfiguration + * args[4] = referenceCollectionElementIdentifier + * @return void + * @subscribe view/collectionElement/new/added + */ + getPublisherSubscriber().subscribe('view/collectionElement/new/added', function(topic, args) { + getViewModel().renderInspectorEditors(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = movedCollectionElementIdentifier + * args[1] = previousCollectionElementIdentifier + * args[2] = nextCollectionElementIdentifier + * args[3] = collectionName + * @return void + * @subscribe view/collectionElement/moved + * @throws 1477407673 + */ + getPublisherSubscriber().subscribe('view/collectionElement/moved', function(topic, args) { + getViewModel().renderInspectorEditors(undefined, false); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/collectionElement/removed + */ + getPublisherSubscriber().subscribe('view/collectionElement/removed', function(topic, args) { + getViewModel().renderInspectorEditors(undefined, false); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/bottom + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/bottom', function(topic, args) { + var lastRenderable; + + lastRenderable = getFormEditorApp().getLastTopLevelElementOnCurrentPage(); + if (!lastRenderable) { + getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); + } else { + if ( + !getFormEditorApp().getFormElementDefinition(lastRenderable, '_isTopLevelFormElement') + && getFormEditorApp().getFormElementDefinition(lastRenderable, '_isCompositeFormElement') + ) { + getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage()); + } else { + getViewModel().createAndAddFormElement(args[0], lastRenderable); + } + } + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @publish view/formElement/inserted + * @subscribe view/insertElements/perform/after + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/after', function(topic, args) { + var newFormElement; + newFormElement = getViewModel().createAndAddFormElement(args[0], undefined, true); + newFormElement = getViewModel().moveFormElement(newFormElement, 'after', getFormEditorApp().getCurrentlySelectedFormElement()); + getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/inside + */ + getPublisherSubscriber().subscribe('view/insertElements/perform/inside', function(topic, args) { + getViewModel().createAndAddFormElement(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementType + * @return void + * @subscribe view/insertElements/perform/after + */ + getPublisherSubscriber().subscribe('view/insertPages/perform', function(topic, args) { + getViewModel().createAndAddFormElement(args[0]); + }); + + /* ********************************************************* + * Modals + * ********************************************************/ + + /** + * @private + * + * @param string + * @param array + * @return void + * @subscribe view/modal/close/perform + */ + getPublisherSubscriber().subscribe('view/modal/close/perform', function(topic, args) { + getFormEditorApp().setUnsavedContent(false); + getViewModel().closeEditor(); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElement + * @return void + * @subscribe view/modal/removeFormElement/perform + */ + getPublisherSubscriber().subscribe('view/modal/removeFormElement/perform', function(topic, args) { + getViewModel().removeFormElement(args[0]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = collectionElementIdentifier + * args[1] = collectionName + * args[2] = formElement + * @return void + * @subscribe view/modal/removeCollectionElement/perform + */ + getPublisherSubscriber().subscribe('view/modal/removeCollectionElement/perform', function(topic, args) { + getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]); + }); + + /** + * @private + * + * @param string + * @param array + * args[0] = formElementIdentifierPath + * @return void + * @subscribe view/modal/validationErrors/element/clicked + */ + getPublisherSubscriber().subscribe('view/modal/validationErrors/element/clicked', function(topic, args) { + var oldPageIndex; + if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) { + oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + getFormEditorApp().setCurrentlySelectedFormElement(args[0]); + + if (getViewModel().getPreviewMode()) { + getViewModel().setPreviewMode(false); + } + + if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) { + getViewModel().renderAbstractStageArea(); + } else { + getViewModel().renderAbstractStageArea(false); + } + + getViewModel().renderPagination(); + getViewModel().renderInspectorEditors(); + } + }); + }; + + /** + * @public + * + * @param object + * @param object + * @return void + */ + function bootstrap(formEditorApp, viewModel) { + _formEditorApp = formEditorApp; + _viewModel = viewModel; + _helperSetup(); + _subscribeEvents(); + }; + + /** + * Implements the "Revealing Module Pattern". + */ + return { + /** + * Publish the public methods. + */ + bootstrap: bootstrap + }; + })($, Helper); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js index 9030bd1f72f41093c13ed4b8b50f6f39c0d24172..0c89d51e8bf9b1bf9d3a2008eb6859d9e552f436 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js @@ -15,524 +15,524 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Icons' - ], function($, Helper, Modal, Severity, Icons) { - 'use strict'; - - return (function($, Helper, Modal, Severity, Icons) { - - /** - * @private - * - * @var object - */ - var _configuration = null; - - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - buttonDefault: 'btn-default', - buttonInfo: 'btn-info', - buttonWarning: 'btn-warning' - }, - domElementDataAttributeNames: { - elementType: 'element-type', - fullElementType: 'data-element-type' - }, - domElementDataAttributeValues: { - rowItem: 'rowItem', - rowLink: 'rowLink', - rowsContainer: 'rowsContainer', - templateInsertElements: 'Modal-InsertElements', - templateInsertPages: 'Modal-InsertPages', - templateValidationErrors: 'Modal-ValidationErrors' - } - }; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @public - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @param object - * @param string - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @public - * - * @param string publisherTopicName - * @param object publisherTopicArguments - * @return void - * @throws 1478889044 - * @throws 1478889049 - */ - function _showRemoveElementModal(publisherTopicName, publisherTopicArguments) { - var modalButtons = []; - - assert( - getUtility().isNonEmptyString(publisherTopicName), - 'Invalid parameter "publisherTopicName"', - 1478889049 - ); - assert( - 'array' === $.type(publisherTopicArguments), - 'Invalid parameter "formElement"', - 1478889044 - ); - - modalButtons.push({ - text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementCancleButton'), - active: true, - btnClass: getHelper().getDomElementClassName('buttonDefault'), - name: 'cancel', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - modalButtons.push({ - text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementConfirmButton'), - active: true, - btnClass: getHelper().getDomElementClassName('buttonWarning'), - name: 'confirm', - trigger: function () { - getPublisherSubscriber().publish(publisherTopicName, publisherTopicArguments); - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - Modal.show( - getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogTitle'), - getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogMessage'), - Severity.warning, - modalButtons - ); - }; - - /** - * @private - * - * @param object modalContent - * @param string publisherTopicName - * @param object configuration - * @return void - * @publish mixed - * @throws 1478910954 - */ - function _insertElementsModalSetup(modalContent, publisherTopicName, configuration) { - var formElementItems; - - assert( - getUtility().isNonEmptyString(publisherTopicName), - 'Invalid parameter "publisherTopicName"', - 1478910954 - ); - - if ('object' === $.type(configuration)) { - for (var key in configuration) { - if (!configuration.hasOwnProperty(key)) { - continue; - } - if ( - key === 'disableElementTypes' - && 'array' === $.type(configuration[key]) - ) { - for (var i = 0, len = configuration[key].length; i < len; ++i) { - $( - getHelper().getDomElementDataAttribute( - 'fullElementType', - 'bracesWithKeyValue', [configuration[key][i]] - ), - modalContent - ).addClass(getHelper().getDomElementClassName('disabled')); - } - } - - if ( - key === 'onlyEnableElementTypes' - && 'array' === $.type(configuration[key]) - ) { - $( - getHelper().getDomElementDataAttribute( - 'fullElementType', - 'bracesWithKey' - ), - modalContent - ).each(function(i, element) { - for (var i = 0, len = configuration[key].length; i < len; ++i) { - var that = $(this); - if (that.data(getHelper().getDomElementDataAttribute('elementType')) !== configuration[key][i]) { - that.addClass(getHelper().getDomElementClassName('disabled')); - } - } - }); - } - } - } - - $('a', modalContent).on("click", function(e) { - getPublisherSubscriber().publish(publisherTopicName, [$(this).data(getHelper().getDomElementDataAttribute('elementType'))]); - $('a', modalContent).off(); - Modal.currentModal.trigger('modal-dismiss'); - }); - }; - - /** - * @private - * - * @param object modalContent - * @param object validationResults - * @return void - * @publish view/modal/validationErrors/element/clicked - * @throws 1479161268 - */ - function _validationErrorsModalSetup(modalContent, validationResults) { - var formElement, newRowItem, rowItemTemplate; - - assert( - 'array' === $.type(validationResults), - 'Invalid parameter "validationResults"', - 1479161268 - ); - - rowItemTemplate = $( - getHelper().getDomElementDataIdentifierSelector('rowItem'), + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Icons' +], function($, Helper, Modal, Severity, Icons) { + 'use strict'; + + return (function($, Helper, Modal, Severity, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + buttonDefault: 'btn-default', + buttonInfo: 'btn-info', + buttonWarning: 'btn-warning' + }, + domElementDataAttributeNames: { + elementType: 'element-type', + fullElementType: 'data-element-type' + }, + domElementDataAttributeValues: { + rowItem: 'rowItem', + rowLink: 'rowLink', + rowsContainer: 'rowsContainer', + templateInsertElements: 'Modal-InsertElements', + templateInsertPages: 'Modal-InsertPages', + templateValidationErrors: 'Modal-ValidationErrors' + } + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @public + * + * @param string publisherTopicName + * @param object publisherTopicArguments + * @return void + * @throws 1478889044 + * @throws 1478889049 + */ + function _showRemoveElementModal(publisherTopicName, publisherTopicArguments) { + var modalButtons = []; + + assert( + getUtility().isNonEmptyString(publisherTopicName), + 'Invalid parameter "publisherTopicName"', + 1478889049 + ); + assert( + 'array' === $.type(publisherTopicArguments), + 'Invalid parameter "formElement"', + 1478889044 + ); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementCancleButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'cancel', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonWarning'), + name: 'confirm', + trigger: function() { + getPublisherSubscriber().publish(publisherTopicName, publisherTopicArguments); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogTitle'), + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogMessage'), + Severity.warning, + modalButtons + ); + }; + + /** + * @private + * + * @param object modalContent + * @param string publisherTopicName + * @param object configuration + * @return void + * @publish mixed + * @throws 1478910954 + */ + function _insertElementsModalSetup(modalContent, publisherTopicName, configuration) { + var formElementItems; + + assert( + getUtility().isNonEmptyString(publisherTopicName), + 'Invalid parameter "publisherTopicName"', + 1478910954 + ); + + if ('object' === $.type(configuration)) { + for (var key in configuration) { + if (!configuration.hasOwnProperty(key)) { + continue; + } + if ( + key === 'disableElementTypes' + && 'array' === $.type(configuration[key]) + ) { + for (var i = 0, len = configuration[key].length; i < len; ++i) { + $( + getHelper().getDomElementDataAttribute( + 'fullElementType', + 'bracesWithKeyValue', [configuration[key][i]] + ), modalContent - ).clone(); - - $(getHelper().getDomElementDataIdentifierSelector('rowItem'), modalContent).remove(); - - for (var i = 0, len = validationResults.length; i < len; ++i) { - var hasError = false, validationElement; - for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { - if ( - validationResults[i]['validationResults'][j]['validationResults'] - && validationResults[i]['validationResults'][j]['validationResults'].length > 0 - ) { - hasError = true; - break; - } - } - - if (hasError) { - formElement = getFormEditorApp() - .getFormElementByIdentifierPath(validationResults[i]['formElementIdentifierPath']); - newRowItem = rowItemTemplate.clone(); - $(getHelper().getDomElementDataIdentifierSelector('rowLink'), newRowItem) - .attr( - getHelper().getDomElementDataAttribute('elementIdentifier'), - validationResults[i]['formElementIdentifierPath'] - ) - .html(_buildTitleByFormElement(formElement)); - $(getHelper().getDomElementDataIdentifierSelector('rowsContainer'), modalContent) - .append(newRowItem); - } + ).addClass(getHelper().getDomElementClassName('disabled')); } - - $('a', modalContent).on("click", function(e) { - getPublisherSubscriber().publish('view/modal/validationErrors/element/clicked', [ - $(this).attr(getHelper().getDomElementDataAttribute('elementIdentifier')) - ]); - $('a', modalContent).off(); - Modal.currentModal.trigger('modal-dismiss'); - }); - }; - - /** - * @private - * - * @param object - * @return object - * @throws 1479162557 - */ - function _buildTitleByFormElement(formElement) { - var label; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479162557); - - return $('<span></span>').text((formElement.get('label') - ? formElement.get('label') - : formElement.get('identifier'))); - }; - - /* ************************************************************* - * Public Methodes - * ************************************************************/ - - /** - * @public - * - * @param object formElement - * @return void - * @publish view/modal/removeFormElement/perform - */ - function showRemoveFormElementModal(formElement) { - _showRemoveElementModal('view/modal/removeFormElement/perform', [formElement]); - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @return void - * @publish view/modal/removeCollectionElement/perform - * @throws 1478894420 - * @throws 1478894421 - */ - function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { - assert( - getUtility().isNonEmptyString(collectionElementIdentifier), - 'Invalid parameter "collectionElementIdentifier"', - 1478894420 - ); - assert( - getUtility().isNonEmptyString(collectionName), - 'Invalid parameter "collectionName"', - 1478894421 - ); - - _showRemoveElementModal('view/modal/removeCollectionElement/perform', [collectionElementIdentifier, collectionName, formElement]); - }; - - /** - * @public - * - * @return void - * @publish view/modal/close/perform - */ - function showCloseConfirmationModal() { - var modalButtons = []; - - modalButtons.push({ - text: getFormElementDefinition(getRootFormElement(), 'modalCloseCancleButton'), - active: true, - btnClass: getHelper().getDomElementClassName('buttonDefault'), - name: 'cancel', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - modalButtons.push({ - text: getFormElementDefinition(getRootFormElement(), 'modalCloseConfirmButton'), - active: true, - btnClass: getHelper().getDomElementClassName('buttonWarning'), - name: 'confirm', - trigger: function () { - getPublisherSubscriber().publish('view/modal/close/perform', []); - Modal.currentModal.trigger('modal-dismiss'); + } + + if ( + key === 'onlyEnableElementTypes' + && 'array' === $.type(configuration[key]) + ) { + $( + getHelper().getDomElementDataAttribute( + 'fullElementType', + 'bracesWithKey' + ), + modalContent + ).each(function(i, element) { + for (var i = 0, len = configuration[key].length; i < len; ++i) { + var that = $(this); + if (that.data(getHelper().getDomElementDataAttribute('elementType')) !== configuration[key][i]) { + that.addClass(getHelper().getDomElementClassName('disabled')); } + } }); - - Modal.show( - getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'), - getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'), - Severity.warning, - modalButtons - ); - }; - - /** - * @public - * - * @param string - * @param object - * @return void - */ - function showInsertElementsModal(publisherTopicName, configuration) { - var html, template; - - template = getHelper().getTemplate('templateInsertElements'); - if (template.length > 0) { - html = $(template.html()); - _insertElementsModalSetup(html, publisherTopicName, configuration); - - Modal.show( - getFormElementDefinition(getRootFormElement(), 'modalInsertElementsDialogTitle'), - $(html), - Severity.info - ); - } - }; - - /** - * @public - * - * @param string - * @return void - */ - function showInsertPagesModal(publisherTopicName) { - var html, template; - - template = getHelper().getTemplate('templateInsertPages'); - if (template.length > 0) { - html = $(template.html()); - _insertElementsModalSetup(html, publisherTopicName); - - Modal.show( - getFormElementDefinition(getRootFormElement(), 'modalInsertPagesDialogTitle'), - $(html), - Severity.info - ); - } - }; - - /** - * @public - * - * @param object - * @return void - */ - function showValidationErrorsModal(validationResults) { - var html, template, modalButtons = []; - - modalButtons.push({ - text: getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsConfirmButton'), - active: true, - btnClass: getHelper().getDomElementClassName('buttonDefault'), - name: 'confirm', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - template = getHelper().getTemplate('templateValidationErrors'); - if (template.length > 0) { - html = $(template.html()).clone(); - _validationErrorsModalSetup(html, validationResults); - - Modal.show( - getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsDialogTitle'), - html, - Severity.error, - modalButtons - ); - } + } + } + } + + $('a', modalContent).on("click", function(e) { + getPublisherSubscriber().publish(publisherTopicName, [$(this).data(getHelper().getDomElementDataAttribute('elementType'))]); + $('a', modalContent).off(); + Modal.currentModal.trigger('modal-dismiss'); + }); + }; + + /** + * @private + * + * @param object modalContent + * @param object validationResults + * @return void + * @publish view/modal/validationErrors/element/clicked + * @throws 1479161268 + */ + function _validationErrorsModalSetup(modalContent, validationResults) { + var formElement, newRowItem, rowItemTemplate; + + assert( + 'array' === $.type(validationResults), + 'Invalid parameter "validationResults"', + 1479161268 + ); + + rowItemTemplate = $( + getHelper().getDomElementDataIdentifierSelector('rowItem'), + modalContent + ).clone(); + + $(getHelper().getDomElementDataIdentifierSelector('rowItem'), modalContent).remove(); + + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } } - /** - * @public - * - * @param object - * @param object - * @return this - */ - function bootstrap(formEditorApp, configuration) { - _formEditorApp = formEditorApp; - _configuration = $.extend(true, _defaultConfiguration, configuration || {}); - _helperSetup(); - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - showCloseConfirmationModal: showCloseConfirmationModal, - showInsertElementsModal: showInsertElementsModal, - showInsertPagesModal: showInsertPagesModal, - showRemoveCollectionElementModal: showRemoveCollectionElementModal, - showRemoveFormElementModal: showRemoveFormElementModal, - showValidationErrorsModal: showValidationErrorsModal - }; - })($, Helper, Modal, Severity, Icons); + if (hasError) { + formElement = getFormEditorApp() + .getFormElementByIdentifierPath(validationResults[i]['formElementIdentifierPath']); + newRowItem = rowItemTemplate.clone(); + $(getHelper().getDomElementDataIdentifierSelector('rowLink'), newRowItem) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + validationResults[i]['formElementIdentifierPath'] + ) + .html(_buildTitleByFormElement(formElement)); + $(getHelper().getDomElementDataIdentifierSelector('rowsContainer'), modalContent) + .append(newRowItem); + } + } + + $('a', modalContent).on("click", function(e) { + getPublisherSubscriber().publish('view/modal/validationErrors/element/clicked', [ + $(this).attr(getHelper().getDomElementDataAttribute('elementIdentifier')) + ]); + $('a', modalContent).off(); + Modal.currentModal.trigger('modal-dismiss'); + }); + }; + + /** + * @private + * + * @param object + * @return object + * @throws 1479162557 + */ + function _buildTitleByFormElement(formElement) { + var label; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479162557); + + return $('<span></span>').text((formElement.get('label') + ? formElement.get('label') + : formElement.get('identifier'))); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @param object formElement + * @return void + * @publish view/modal/removeFormElement/perform + */ + function showRemoveFormElementModal(formElement) { + _showRemoveElementModal('view/modal/removeFormElement/perform', [formElement]); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return void + * @publish view/modal/removeCollectionElement/perform + * @throws 1478894420 + * @throws 1478894421 + */ + function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { + assert( + getUtility().isNonEmptyString(collectionElementIdentifier), + 'Invalid parameter "collectionElementIdentifier"', + 1478894420 + ); + assert( + getUtility().isNonEmptyString(collectionName), + 'Invalid parameter "collectionName"', + 1478894421 + ); + + _showRemoveElementModal('view/modal/removeCollectionElement/perform', [collectionElementIdentifier, collectionName, formElement]); + }; + + /** + * @public + * + * @return void + * @publish view/modal/close/perform + */ + function showCloseConfirmationModal() { + var modalButtons = []; + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalCloseCancleButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'cancel', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalCloseConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonWarning'), + name: 'confirm', + trigger: function() { + getPublisherSubscriber().publish('view/modal/close/perform', []); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'), + getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'), + Severity.warning, + modalButtons + ); + }; + + /** + * @public + * + * @param string + * @param object + * @return void + */ + function showInsertElementsModal(publisherTopicName, configuration) { + var html, template; + + template = getHelper().getTemplate('templateInsertElements'); + if (template.length > 0) { + html = $(template.html()); + _insertElementsModalSetup(html, publisherTopicName, configuration); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalInsertElementsDialogTitle'), + $(html), + Severity.info + ); + } + }; + + /** + * @public + * + * @param string + * @return void + */ + function showInsertPagesModal(publisherTopicName) { + var html, template; + + template = getHelper().getTemplate('templateInsertPages'); + if (template.length > 0) { + html = $(template.html()); + _insertElementsModalSetup(html, publisherTopicName); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalInsertPagesDialogTitle'), + $(html), + Severity.info + ); + } + }; + + /** + * @public + * + * @param object + * @return void + */ + function showValidationErrorsModal(validationResults) { + var html, template, modalButtons = []; + + modalButtons.push({ + text: getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsConfirmButton'), + active: true, + btnClass: getHelper().getDomElementClassName('buttonDefault'), + name: 'confirm', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + template = getHelper().getTemplate('templateValidationErrors'); + if (template.length > 0) { + html = $(template.html()).clone(); + _validationErrorsModalSetup(html, validationResults); + + Modal.show( + getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsDialogTitle'), + html, + Severity.error, + modalButtons + ); + } + } + + /** + * @public + * + * @param object + * @param object + * @return this + */ + function bootstrap(formEditorApp, configuration) { + _formEditorApp = formEditorApp; + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + showCloseConfirmationModal: showCloseConfirmationModal, + showInsertElementsModal: showInsertElementsModal, + showInsertPagesModal: showInsertPagesModal, + showRemoveCollectionElementModal: showRemoveCollectionElementModal, + showRemoveFormElementModal: showRemoveFormElementModal, + showValidationErrorsModal: showValidationErrorsModal + }; + })($, Helper, Modal, Severity, Icons); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js index 793c1499325ee48d2a0bdd84c8449f86131ec655..31b238433d88ea49bd0e7c6c6608774d8f3768fb 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js @@ -15,1223 +15,1225 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/StageComponent */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' - ], function($, Helper, Icons) { - 'use strict'; - - return (function($, Helper, Icons) { - - /** - * @private - * - * @var object - */ - var _configuration = null; - - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - formElementIsComposit: 't3-form-element-composit', - formElementIsTopLevel: 't3-form-element-toplevel', - noNesting: 'mjs-nestedSortable-no-nesting', - selected: 'selected', - sortable: 'sortable', - previewViewPreviewElement: 't3-form-element-preview' - }, - domElementDataAttributeNames: { - abstractType: 'data-element-abstract-type', - noSorting: 'data-no-sorting' - }, - domElementDataAttributeValues: { - abstractViewToolbar: 'elementToolbar', - abstractViewToolbarNewElement: 'stageElementToolbarNewElement', - abstractViewToolbarNewElementSplitButton: 'stageElementToolbarNewElementSplitButton', - abstractViewToolbarNewElementSplitButtonAfter: 'stageElementToolbarNewElementSplitButtonAfter', - abstractViewToolbarNewElementSplitButtonInside: 'stageElementToolbarNewElementSplitButtonInside', - abstractViewToolbarRemoveElement: 'stageElementToolbarRemoveElement', - buttonHeaderRedo: 'redoButton', - buttonHeaderUndo: 'undoButton', - buttonPaginationPrevious: 'buttonPaginationPrevious', - buttonPaginationNext: 'buttonPaginationNext', - 'FormElement-_ElementToolbar': 'FormElement-_ElementToolbar', - 'FormElement-_UnknownElement': 'FormElement-_UnknownElement', - 'FormElement-AdvancedPassword': 'FormElement-AdvancedPassword', - 'FormElement-Checkbox': 'FormElement-Checkbox', - 'FormElement-ContentElement': 'FormElement-ContentElement', - 'FormElement-DatePicker': 'FormElement-DatePicker', - 'FormElement-Fieldset': 'FormElement-Fieldset', - 'FormElement-GridContainer': 'FormElement-GridContainer', - 'FormElement-GridRow': 'FormElement-GridRow', - 'FormElement-FileUpload': 'FormElement-FileUpload', - 'FormElement-Hidden': 'FormElement-Hidden', - 'FormElement-ImageUpload': 'FormElement-ImageUpload', - 'FormElement-MultiCheckbox': 'FormElement-MultiCheckbox', - 'FormElement-MultiSelect': 'FormElement-MultiSelect', - 'FormElement-Page': 'FormElement-Page', - 'FormElement-Password': 'FormElement-Password', - 'FormElement-RadioButton': 'FormElement-RadioButton', - 'FormElement-SingleSelect': 'FormElement-SingleSelect', - 'FormElement-StaticText': 'FormElement-StaticText', - 'FormElement-SummaryPage': 'FormElement-SummaryPage', - 'FormElement-Text': 'FormElement-Text', - 'FormElement-Textarea': 'FormElement-Textarea', - 'FormElement-Email': 'FormElement-Email', - 'FormElement-Url': 'FormElement-Url', - 'FormElement-Telephone': 'FormElement-Telephone', - 'FormElement-Number': 'FormElement-Number', - formElementIcon: 'elementIcon', - iconValidator: 't3-form-icon-validator', - multiValueContainer: 'multiValueContainer', - paginationTitle: 'paginationTitle', - stageHeadline: 'formDefinitionLabel', - stagePanel: 'stagePanel', - validatorsContainer: 'validatorsContainer', - validatorIcon: 'validatorIcon' - }, - isSortable: true - }; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /** - * @private - * - * @var object - */ - var _stageDomElement = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @public - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @return object - */ - function getViewModel() { - return getFormEditorApp().getViewModel(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @param object - * @param string - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @private - * - * @return object - * @return string - * @return void - */ - function _setTemplateTextContent(domElement, content) { - if (getUtility().isNonEmptyString(content)) { - $(domElement).text(content); - } + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' +], function($, Helper, Icons) { + 'use strict'; + + return (function($, Helper, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + formElementIsComposit: 't3-form-element-composit', + formElementIsTopLevel: 't3-form-element-toplevel', + noNesting: 'mjs-nestedSortable-no-nesting', + selected: 'selected', + sortable: 'sortable', + previewViewPreviewElement: 't3-form-element-preview' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type', + noSorting: 'data-no-sorting' + }, + domElementDataAttributeValues: { + abstractViewToolbar: 'elementToolbar', + abstractViewToolbarNewElement: 'stageElementToolbarNewElement', + abstractViewToolbarNewElementSplitButton: 'stageElementToolbarNewElementSplitButton', + abstractViewToolbarNewElementSplitButtonAfter: 'stageElementToolbarNewElementSplitButtonAfter', + abstractViewToolbarNewElementSplitButtonInside: 'stageElementToolbarNewElementSplitButtonInside', + abstractViewToolbarRemoveElement: 'stageElementToolbarRemoveElement', + buttonHeaderRedo: 'redoButton', + buttonHeaderUndo: 'undoButton', + buttonPaginationPrevious: 'buttonPaginationPrevious', + buttonPaginationNext: 'buttonPaginationNext', + 'FormElement-_ElementToolbar': 'FormElement-_ElementToolbar', + 'FormElement-_UnknownElement': 'FormElement-_UnknownElement', + 'FormElement-AdvancedPassword': 'FormElement-AdvancedPassword', + 'FormElement-Checkbox': 'FormElement-Checkbox', + 'FormElement-ContentElement': 'FormElement-ContentElement', + 'FormElement-DatePicker': 'FormElement-DatePicker', + 'FormElement-Fieldset': 'FormElement-Fieldset', + 'FormElement-GridContainer': 'FormElement-GridContainer', + 'FormElement-GridRow': 'FormElement-GridRow', + 'FormElement-FileUpload': 'FormElement-FileUpload', + 'FormElement-Hidden': 'FormElement-Hidden', + 'FormElement-ImageUpload': 'FormElement-ImageUpload', + 'FormElement-MultiCheckbox': 'FormElement-MultiCheckbox', + 'FormElement-MultiSelect': 'FormElement-MultiSelect', + 'FormElement-Page': 'FormElement-Page', + 'FormElement-Password': 'FormElement-Password', + 'FormElement-RadioButton': 'FormElement-RadioButton', + 'FormElement-SingleSelect': 'FormElement-SingleSelect', + 'FormElement-StaticText': 'FormElement-StaticText', + 'FormElement-SummaryPage': 'FormElement-SummaryPage', + 'FormElement-Text': 'FormElement-Text', + 'FormElement-Textarea': 'FormElement-Textarea', + 'FormElement-Email': 'FormElement-Email', + 'FormElement-Url': 'FormElement-Url', + 'FormElement-Telephone': 'FormElement-Telephone', + 'FormElement-Number': 'FormElement-Number', + formElementIcon: 'elementIcon', + iconValidator: 't3-form-icon-validator', + multiValueContainer: 'multiValueContainer', + paginationTitle: 'paginationTitle', + stageHeadline: 'formDefinitionLabel', + stagePanel: 'stagePanel', + validatorsContainer: 'validatorsContainer', + validatorIcon: 'validatorIcon' + }, + isSortable: true + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _stageDomElement = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @return object + */ + function getViewModel() { + return getFormEditorApp().getViewModel(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @return object + * @return string + * @return void + */ + function _setTemplateTextContent(domElement, content) { + if (getUtility().isNonEmptyString(content)) { + $(domElement).text(content); + } + } + + /** + * @private + * + * @param object + * @param object + * @return void + * @publish view/stage/abstract/render/template/perform + */ + function _renderTemplateDispatcher(formElement, template) { + switch (formElement.get('type')) { + case 'Checkbox': + renderCheckboxTemplate(formElement, template); + break; + case 'FileUpload': + case 'ImageUpload': + renderFileUploadTemplates(formElement, template); + break; + case 'SingleSelect': + case 'RadioButton': + case 'MultiSelect': + case 'MultiCheckbox': + renderSelectTemplates(formElement, template); + break; + case 'Textarea': + case 'AdvancedPassword': + case 'Password': + case 'Text': + case 'Email': + case 'Url': + case 'Telephone': + case 'Number': + case 'DatePicker': + renderSimpleTemplateWithValidators(formElement, template); + break; + case 'Fieldset': + case 'GridContainer': + case 'GridRow': + case 'SummaryPage': + case 'Page': + case 'StaticText': + case 'Hidden': + case 'ContentElement': + renderSimpleTemplate(formElement, template); + break; + } + getPublisherSubscriber().publish('view/stage/abstract/render/template/perform', [formElement, template]); + }; + + /** + * @private + * + * @param object + * @return object + * @throws 1478987818 + */ + function _renderNestedSortableListItem(formElement) { + var childFormElements, childList, listItem, template; + + listItem = $('<li></li>'); + if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('noNesting')); + } + + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); + } + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('formElementIsComposit')); + } + + try { + template = getHelper().getTemplate('FormElement-' + formElement.get('type')).clone(); + } catch (error) { + template = getHelper().getTemplate('FormElement-_UnknownElement').clone(); + assert( + template.length, + 'No template found for element "' + formElement.get('__identifierPath') + '"', + 1478987818 + ); + } + + template = $('<div></div>') + .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) + .append($(template.html())); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); + } + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); + } + listItem.append(template); + + _renderTemplateDispatcher(formElement, template); + + childFormElements = formElement.get('renderables'); + childList = null; + if ('array' === $.type(childFormElements)) { + childList = $('<ol></ol>'); + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + childList.addClass(getHelper().getDomElementClassName('sortable')); } - - /** - * @private - * - * @param object - * @param object - * @return void - * @publish view/stage/abstract/render/template/perform - */ - function _renderTemplateDispatcher(formElement, template) { - switch (formElement.get('type')) { - case 'Checkbox': - renderCheckboxTemplate(formElement, template); - break; - case 'FileUpload': - case 'ImageUpload': - renderFileUploadTemplates(formElement, template); - break; - case 'SingleSelect': - case 'RadioButton': - case 'MultiSelect': - case 'MultiCheckbox': - renderSelectTemplates(formElement, template); - break; - case 'Textarea': - case 'AdvancedPassword': - case 'Password': - case 'Text': - case 'Email': - case 'Url': - case 'Telephone': - case 'Number': - case 'DatePicker': - renderSimpleTemplateWithValidators(formElement, template); - break; - case 'Fieldset': - case 'GridContainer': - case 'GridRow': - case 'SummaryPage': - case 'Page': - case 'StaticText': - case 'Hidden': - case 'ContentElement': - renderSimpleTemplate(formElement, template); - break; - } - getPublisherSubscriber().publish('view/stage/abstract/render/template/perform', [formElement, template]); - }; - - /** - * @private - * - * @param object - * @return object - * @throws 1478987818 - */ - function _renderNestedSortableListItem(formElement) { - var childFormElements, childList, listItem, template; - - listItem = $('<li></li>'); - if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { - listItem.addClass(getHelper().getDomElementClassName('noNesting')); - } - - if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { - listItem.addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); - } - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - listItem.addClass(getHelper().getDomElementClassName('formElementIsComposit')); - } - - try { - template = getHelper().getTemplate('FormElement-' + formElement.get('type')).clone(); - } catch(error) { - template = getHelper().getTemplate('FormElement-_UnknownElement').clone(); - assert( - template.length, - 'No template found for element "' + formElement.get('__identifierPath') + '"', - 1478987818 - ); - } - - template = $('<div></div>') - .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) - .append($(template.html())); - - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); - } - if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { - template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); - } - listItem.append(template); - - _renderTemplateDispatcher(formElement, template); - - childFormElements = formElement.get('renderables'); - childList = null; - if ('array' === $.type(childFormElements)) { - childList = $('<ol></ol>'); - if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { - childList.addClass(getHelper().getDomElementClassName('sortable')); - } - for (var i = 0, len = childFormElements.length; i < len; ++i) { - childList.append(_renderNestedSortableListItem(childFormElements[i])); - } - } - - if (childList) { - listItem.append(childList); - } - return listItem; - }; - - /** - * @private - * - * @return void - * @publish view/stage/abstract/dnd/start - * @publish view/stage/abstract/dnd/stop - * @publish view/stage/abstract/dnd/change - * @publish view/stage/abstract/dnd/update - */ - function _addSortableEvents() { - $('ol.' + getHelper().getDomElementClassName('sortable'), _stageDomElement).nestedSortable({ - forcePlaceholderSize: true, - handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), - helper: 'clone', - items: 'li:not(' + getHelper().getDomElementDataAttribute('noSorting', 'bracesWithKey') + ')', - opacity: .6, - revert: 250, - delay: 200, - tolerance: 'pointer', - toleranceElement: '> div', - - isAllowed: function (placeholder, placeholderParent, currentItem) { - var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, targetFormElementTypeDefinition; - - formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(currentItem)); - targetFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(placeholderParent)); - if (!targetFormElementIdentifierPath) { - targetFormElementIdentifierPath = getFormEditorApp().getCurrentlySelectedPage(); - } - - formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath); - targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath); - - if ( - formElementTypeDefinition['_isGridContainerFormElement'] - && ( - getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) - || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) - ) - ) { - return false; - } - - if ( - !formElementTypeDefinition['_isGridContainerFormElement'] - && !formElementTypeDefinition['_isGridRowFormElement'] - && targetFormElementTypeDefinition['_isGridContainerFormElement'] - ) { - return false; - } - - return true; - }, - start: function(e, o) { - getPublisherSubscriber().publish('view/stage/abstract/dnd/start', [$(o.item), $(o.placeholder)]); - }, - stop: function(e, o) { - getPublisherSubscriber().publish('view/stage/abstract/dnd/stop', [ - getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)) - ]); - }, - change: function(e, o) { - var enclosingCompositeFormElement, parentFormElementIdentifierPath; - - parentFormElementIdentifierPath = getAbstractViewParentFormElementIdentifierPathWithinDomElement($(o.placeholder)); - if (parentFormElementIdentifierPath) { - enclosingCompositeFormElement = getFormEditorApp() - .findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); - } - getPublisherSubscriber().publish('view/stage/abstract/dnd/change', [ - $(o.placeholder), - parentFormElementIdentifierPath, enclosingCompositeFormElement - ]); - }, - update: function(e, o) { - var nextFormElementIdentifierPath, movedFormElement, movedFormElementIdentifierPath, parentFormElementIdentifierPath, previousFormElementIdentifierPath; - - movedFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)); - previousFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'prev'); - nextFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'next'); - - getPublisherSubscriber().publish('view/stage/abstract/dnd/update', [ - $(o.item), - movedFormElementIdentifierPath, - previousFormElementIdentifierPath, - nextFormElementIdentifierPath - ]); - } - }); - }; - - /* ************************************************************* - * Public Methodes - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getStageDomElement() { - return _stageDomElement; - }; - - /** - * @public - * - * @param object - * @return object - * @throws 1479037151 - */ - function buildTitleByFormElement(formElement) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getRootFormElement(); - } - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479037151); - - return $('<span></span>') - .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))); - }; - - /** - * @public - * - * @param string title - * @return void - */ - function setStageHeadline(title) { - if (getUtility().isUndefinedOrNull(title)) { - title = buildTitleByFormElement(); - } - - $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title); - }; - - /** - * @public - * - * @return object - */ - function getStagePanelDomElement() { - return $(getHelper().getDomElementDataIdentifierSelector('stagePanel')); - }; - - /** - * @public - * - * @return void - */ - function renderPagination() { - var pageCount; - - pageCount = getRootFormElement().get('renderables').length; - - getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); - getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); - - if (getFormEditorApp().getCurrentlySelectedPageIndex() === 0) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); - } - - if (pageCount === 1 || getFormEditorApp().getCurrentlySelectedPageIndex() === (pageCount - 1)) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); - } - - $(getHelper().getDomElementDataIdentifierSelector('paginationTitle')).text( - getFormElementDefinition(getRootFormElement(), 'paginationTitle') - .replace('{0}', getFormEditorApp().getCurrentlySelectedPageIndex() + 1) - .replace('{1}', pageCount) - ); - }; - - /** - * @public - * - * @return void - */ - function renderUndoRedo() { - getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - - if (getFormEditorApp().getCurrentApplicationStatePosition() + 1 >= getFormEditorApp().getCurrentApplicationStates()) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - } - if (getFormEditorApp().getCurrentApplicationStatePosition() === 0) { - getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - } - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAllFormElementDomElements() { - return $( getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), - _stageDomElement - ); - }; - - /* ************************************************************* - * Abstract stage - * ************************************************************/ - - /** - * @public - * - * @param int - * @return object - * @throws 1478721208 - */ - function renderFormDefinitionPageAsSortableList(pageIndex) { - assert( - 'number' === $.type(pageIndex), - 'Invalid parameter "pageIndex"', - 1478721208 - ); - - return $('<ol></ol>') - .append(_renderNestedSortableListItem(getRootFormElement().get('renderables')[pageIndex])); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAbstractViewParentFormElementWithinDomElement(element) { - return $(element) - .parent() - .closest('li') - .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .first(); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAbstractViewParentFormElementIdentifierPathWithinDomElement(element) { - return getAbstractViewParentFormElementWithinDomElement(element) - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAbstractViewFormElementWithinDomElement(element) { - return $(element) - .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .first(); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAbstractViewFormElementIdentifierPathWithinDomElement(element) { - return getAbstractViewFormElementWithinDomElement($(element)) - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @private - * - * @param object - * @param string - * @return string - */ - function getAbstractViewSiblingFormElementIdentifierPathWithinDomElement(element, position) { - var formElementIdentifierPath; - - if (getUtility().isUndefinedOrNull(position)) { - position = 'prev'; - } - formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement(element); - element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); - return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) - .first() - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @public - * - * @param string|object - * @return object - */ - function getAbstractViewFormElementDomElement(formElement) { - var formElementIdentifierPath; - - if ('string' === $.type(formElement)) { - formElementIdentifierPath = formElement; - } else { - if (getUtility().isUndefinedOrNull(formElement)) { - formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); - } else { - formElementIdentifierPath = formElement.get('__identifierPath'); - } - } - return $(getHelper() - .getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _stageDomElement); - }; - - /** - * @public - * - * @return void - */ - function removeAllStageToolbars() { - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), _stageDomElement).off().empty().remove(); - }; - - /** - * @public - * - * @param object - * @return object - * @publish view/insertElements/perform/after - * @publish view/insertElements/perform/inside - * @throws 1479035778 - */ - function createAbstractViewFormElementToolbar(formElement) { - var formElementTypeDefinition, template; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035778); - - formElementTypeDefinition = getFormElementDefinition(formElement); - if (formElementTypeDefinition['_isTopLevelFormElement']) { - return $(); - } - - template = getHelper().getTemplate('FormElement-_ElementToolbar').clone(); - if (!template.length) { - return $(); - } - - template = $($(template.html())); - - getHelper().getTemplatePropertyDomElement('_type', template).text(formElement.get('type')); - getHelper().getTemplatePropertyDomElement('_identifier', template).text(formElement.get('identifier')); - - if (formElementTypeDefinition['_isCompositeFormElement']) { - getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template)); - - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonAfter'), template).on('click', function(e) { - var disableElementTypes, onlyEnableElementTypes; - - disableElementTypes = []; - onlyEnableElementTypes = []; - if (formElementTypeDefinition['_isGridRowFormElement']) { - if (getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())) { - onlyEnableElementTypes = ['GridRow']; - } else if (getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement().get('__parentRenderable'))) { - disableElementTypes = ['GridContainer']; - } - } else { - if ( - !formElementTypeDefinition['_isGridContainerFormElement'] - && ( - getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) - || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) - ) - ) { - disableElementTypes = ['GridContainer']; - } - } - - getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ - 'view/insertElements/perform/after', - { - disableElementTypes: disableElementTypes, - onlyEnableElementTypes: onlyEnableElementTypes - } - ] - ); - }); - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) { - var disableElementTypes, onlyEnableElementTypes; - - disableElementTypes = []; - onlyEnableElementTypes = []; - if (formElementTypeDefinition['_isGridContainerFormElement']) { - onlyEnableElementTypes = ['GridRow']; - } else if ( - formElementTypeDefinition['_isGridRowFormElement'] - || ( - getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) - || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) - ) - ) { - disableElementTypes = ['GridContainer']; - } - - getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ - 'view/insertElements/perform/inside', - { - disableElementTypes: disableElementTypes, - onlyEnableElementTypes: onlyEnableElementTypes - } - ] - ); - }); - } else { - getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template)); - - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) { - var disableElementTypes; - - disableElementTypes = []; - if (getFormEditorApp().findEnclosingGridRowFormElement(formElement)) { - disableElementTypes = ['GridContainer']; - } - - getPublisherSubscriber().publish( - 'view/stage/abstract/elementToolbar/button/newElement/clicked', [ - 'view/insertElements/perform/after', - { - disableElementTypes: disableElementTypes - } - ] - ); - }); - } - - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarRemoveElement'), template).on('click', function(e) { - getViewModel().showRemoveFormElementModal(); - }); - - return template; - }; - - /** - * @public - * - * @param object - * @param object - * @param bool - * @return void - */ - function createAndAddAbstractViewFormElementToolbar(selectedFormElementDomElement, formElement, useFadeEffect) { - var toolbar; - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - - if (useFadeEffect) { - createAbstractViewFormElementToolbar(formElement).fadeOut(0, function() { - selectedFormElementDomElement.prepend($(this)); - $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), selectedFormElementDomElement).fadeIn('fast'); - }); - } else { - selectedFormElementDomElement.prepend(createAbstractViewFormElementToolbar(formElement)); + for (var i = 0, len = childFormElements.length; i < len; ++i) { + childList.append(_renderNestedSortableListItem(childFormElements[i])); + } + } + + if (childList) { + listItem.append(childList); + } + return listItem; + }; + + /** + * @private + * + * @return void + * @publish view/stage/abstract/dnd/start + * @publish view/stage/abstract/dnd/stop + * @publish view/stage/abstract/dnd/change + * @publish view/stage/abstract/dnd/update + */ + function _addSortableEvents() { + $('ol.' + getHelper().getDomElementClassName('sortable'), _stageDomElement).nestedSortable({ + forcePlaceholderSize: true, + handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + helper: 'clone', + items: 'li:not(' + getHelper().getDomElementDataAttribute('noSorting', 'bracesWithKey') + ')', + opacity: .6, + revert: 250, + delay: 200, + tolerance: 'pointer', + toleranceElement: '> div', + + isAllowed: function(placeholder, placeholderParent, currentItem) { + var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, + targetFormElementTypeDefinition; + + formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(currentItem)); + targetFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(placeholderParent)); + if (!targetFormElementIdentifierPath) { + targetFormElementIdentifierPath = getFormEditorApp().getCurrentlySelectedPage(); + } + + formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath); + targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath); + + if ( + formElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) + || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) + ) + ) { + return false; + } + + if ( + !formElementTypeDefinition['_isGridContainerFormElement'] + && !formElementTypeDefinition['_isGridRowFormElement'] + && targetFormElementTypeDefinition['_isGridContainerFormElement'] + ) { + return false; + } + + return true; + }, + start: function(e, o) { + getPublisherSubscriber().publish('view/stage/abstract/dnd/start', [$(o.item), $(o.placeholder)]); + }, + stop: function(e, o) { + getPublisherSubscriber().publish('view/stage/abstract/dnd/stop', [ + getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)) + ]); + }, + change: function(e, o) { + var enclosingCompositeFormElement, parentFormElementIdentifierPath; + + parentFormElementIdentifierPath = getAbstractViewParentFormElementIdentifierPathWithinDomElement($(o.placeholder)); + if (parentFormElementIdentifierPath) { + enclosingCompositeFormElement = getFormEditorApp() + .findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); + } + getPublisherSubscriber().publish('view/stage/abstract/dnd/change', [ + $(o.placeholder), + parentFormElementIdentifierPath, enclosingCompositeFormElement + ]); + }, + update: function(e, o) { + var nextFormElementIdentifierPath, movedFormElement, movedFormElementIdentifierPath, + parentFormElementIdentifierPath, previousFormElementIdentifierPath; + + movedFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item)); + previousFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'prev'); + nextFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'next'); + + getPublisherSubscriber().publish('view/stage/abstract/dnd/update', [ + $(o.item), + movedFormElementIdentifierPath, + previousFormElementIdentifierPath, + nextFormElementIdentifierPath + ]); + } + }); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStageDomElement() { + return _stageDomElement; + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1479037151 + */ + function buildTitleByFormElement(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getRootFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479037151); + + return $('<span></span>') + .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))); + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStageHeadline(title) { + if (getUtility().isUndefinedOrNull(title)) { + title = buildTitleByFormElement(); + } + + $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title); + }; + + /** + * @public + * + * @return object + */ + function getStagePanelDomElement() { + return $(getHelper().getDomElementDataIdentifierSelector('stagePanel')); + }; + + /** + * @public + * + * @return void + */ + function renderPagination() { + var pageCount; + + pageCount = getRootFormElement().get('renderables').length; + + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); + + if (getFormEditorApp().getCurrentlySelectedPageIndex() === 0) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious'))); + } + + if (pageCount === 1 || getFormEditorApp().getCurrentlySelectedPageIndex() === (pageCount - 1)) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext'))); + } + + $(getHelper().getDomElementDataIdentifierSelector('paginationTitle')).text( + getFormElementDefinition(getRootFormElement(), 'paginationTitle') + .replace('{0}', getFormEditorApp().getCurrentlySelectedPageIndex() + 1) + .replace('{1}', pageCount) + ); + }; + + /** + * @public + * + * @return void + */ + function renderUndoRedo() { + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + + if (getFormEditorApp().getCurrentApplicationStatePosition() + 1 >= getFormEditorApp().getCurrentApplicationStates()) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + } + if (getFormEditorApp().getCurrentApplicationStatePosition() === 0) { + getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + } + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAllFormElementDomElements() { + return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + _stageDomElement + ); + }; + + /* ************************************************************* + * Abstract stage + * ************************************************************/ + + /** + * @public + * + * @param int + * @return object + * @throws 1478721208 + */ + function renderFormDefinitionPageAsSortableList(pageIndex) { + assert( + 'number' === $.type(pageIndex), + 'Invalid parameter "pageIndex"', + 1478721208 + ); + + return $('<ol></ol>') + .append(_renderNestedSortableListItem(getRootFormElement().get('renderables')[pageIndex])); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewParentFormElementWithinDomElement(element) { + return $(element) + .parent() + .closest('li') + .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewParentFormElementIdentifierPathWithinDomElement(element) { + return getAbstractViewParentFormElementWithinDomElement(element) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewFormElementWithinDomElement(element) { + return $(element) + .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAbstractViewFormElementIdentifierPathWithinDomElement(element) { + return getAbstractViewFormElementWithinDomElement($(element)) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @private + * + * @param object + * @param string + * @return string + */ + function getAbstractViewSiblingFormElementIdentifierPathWithinDomElement(element, position) { + var formElementIdentifierPath; + + if (getUtility().isUndefinedOrNull(position)) { + position = 'prev'; + } + formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement(element); + element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); + return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) + .first() + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param string|object + * @return object + */ + function getAbstractViewFormElementDomElement(formElement) { + var formElementIdentifierPath; + + if ('string' === $.type(formElement)) { + formElementIdentifierPath = formElement; + } else { + if (getUtility().isUndefinedOrNull(formElement)) { + formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); + } else { + formElementIdentifierPath = formElement.get('__identifierPath'); + } + } + return $(getHelper() + .getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _stageDomElement); + }; + + /** + * @public + * + * @return void + */ + function removeAllStageToolbars() { + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), _stageDomElement).off().empty().remove(); + }; + + /** + * @public + * + * @param object + * @return object + * @publish view/insertElements/perform/after + * @publish view/insertElements/perform/inside + * @throws 1479035778 + */ + function createAbstractViewFormElementToolbar(formElement) { + var formElementTypeDefinition, template; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035778); + + formElementTypeDefinition = getFormElementDefinition(formElement); + if (formElementTypeDefinition['_isTopLevelFormElement']) { + return $(); + } + + template = getHelper().getTemplate('FormElement-_ElementToolbar').clone(); + if (!template.length) { + return $(); + } + + template = $($(template.html())); + + getHelper().getTemplatePropertyDomElement('_type', template).text(formElement.get('type')); + getHelper().getTemplatePropertyDomElement('_identifier', template).text(formElement.get('identifier')); + + if (formElementTypeDefinition['_isCompositeFormElement']) { + getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template)); + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonAfter'), template).on('click', function(e) { + var disableElementTypes, onlyEnableElementTypes; + + disableElementTypes = []; + onlyEnableElementTypes = []; + if (formElementTypeDefinition['_isGridRowFormElement']) { + if (getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())) { + onlyEnableElementTypes = ['GridRow']; + } else if (getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement().get('__parentRenderable'))) { + disableElementTypes = ['GridContainer']; } - - }; - - /** - * @public - * - * @param int - * @param function - * @return void - * @publish view/stage/dnd/stop - * @publish view/stage/element/clicked - * @throws 1478169511 - */ - function renderAbstractStageArea(pageIndex, callback) { - if (getUtility().isUndefinedOrNull(pageIndex)) { - pageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + } else { + if ( + !formElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) + || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) + ) + ) { + disableElementTypes = ['GridContainer']; } - _stageDomElement.off().empty().append(renderFormDefinitionPageAsSortableList(pageIndex)); - - _stageDomElement.on("click", function(e) { - var formElementIdentifierPath; - - formElementIdentifierPath = $(e.target) - .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - if ( - getUtility().isUndefinedOrNull(formElementIdentifierPath) - || !getUtility().isNonEmptyString(formElementIdentifierPath) - ) { - return; - } - - getPublisherSubscriber().publish('view/stage/element/clicked', [formElementIdentifierPath]); - }); + } + + getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ + 'view/insertElements/perform/after', + { + disableElementTypes: disableElementTypes, + onlyEnableElementTypes: onlyEnableElementTypes + } + ] + ); + }); + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) { + var disableElementTypes, onlyEnableElementTypes; + + disableElementTypes = []; + onlyEnableElementTypes = []; + if (formElementTypeDefinition['_isGridContainerFormElement']) { + onlyEnableElementTypes = ['GridRow']; + } else if ( + formElementTypeDefinition['_isGridRowFormElement'] + || ( + getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement()) + || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement()) + ) + ) { + disableElementTypes = ['GridContainer']; + } + + getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [ + 'view/insertElements/perform/inside', + { + disableElementTypes: disableElementTypes, + onlyEnableElementTypes: onlyEnableElementTypes + } + ] + ); + }); + } else { + getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template)); + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) { + var disableElementTypes; + + disableElementTypes = []; + if (getFormEditorApp().findEnclosingGridRowFormElement(formElement)) { + disableElementTypes = ['GridContainer']; + } + + getPublisherSubscriber().publish( + 'view/stage/abstract/elementToolbar/button/newElement/clicked', [ + 'view/insertElements/perform/after', + { + disableElementTypes: disableElementTypes + } + ] + ); + }); + } + + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarRemoveElement'), template).on('click', function(e) { + getViewModel().showRemoveFormElementModal(); + }); + + return template; + }; + + /** + * @public + * + * @param object + * @param object + * @param bool + * @return void + */ + function createAndAddAbstractViewFormElementToolbar(selectedFormElementDomElement, formElement, useFadeEffect) { + var toolbar; + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + if (useFadeEffect) { + createAbstractViewFormElementToolbar(formElement).fadeOut(0, function() { + selectedFormElementDomElement.prepend($(this)); + $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), selectedFormElementDomElement).fadeIn('fast'); + }); + } else { + selectedFormElementDomElement.prepend(createAbstractViewFormElementToolbar(formElement)); + } + + }; + + /** + * @public + * + * @param int + * @param function + * @return void + * @publish view/stage/dnd/stop + * @publish view/stage/element/clicked + * @throws 1478169511 + */ + function renderAbstractStageArea(pageIndex, callback) { + if (getUtility().isUndefinedOrNull(pageIndex)) { + pageIndex = getFormEditorApp().getCurrentlySelectedPageIndex(); + } + _stageDomElement.off().empty().append(renderFormDefinitionPageAsSortableList(pageIndex)); + + _stageDomElement.on("click", function(e) { + var formElementIdentifierPath; + + formElementIdentifierPath = $(e.target) + .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + if ( + getUtility().isUndefinedOrNull(formElementIdentifierPath) + || !getUtility().isNonEmptyString(formElementIdentifierPath) + ) { + return; + } - if (_configuration['isSortable']) { - _addSortableEvents(); - } + getPublisherSubscriber().publish('view/stage/element/clicked', [formElementIdentifierPath]); + }); + + if (_configuration['isSortable']) { + _addSortableEvents(); + } + + if ('function' === $.type(callback)) { + callback(); + } + }; + + + /* ************************************************************* + * Preview stage + * ************************************************************/ + + /** + * @public + * + * @param string html + * @return void + * @throws 1475424409 + */ + function renderPreviewStageArea(html) { + assert(getUtility().isNonEmptyString(html), 'Invalid parameter "html"', 1475424409); + + _stageDomElement.off().empty().html(html); + + $(':input', _stageDomElement).prop('disabled', 'disabled').on('click dblclick select focus keydown keypress keyup mousedown mouseup', function(e) { + return e.preventDefault(); + }); + + $('form', _stageDomElement).submit(function(e) { + return e.preventDefault(); + }); + + getAllFormElementDomElements().each(function(i, element) { + var formElement, metaLabel; + + formElement = getFormEditorApp() + .getFormElementByIdentifierPath($(this).data('elementIdentifierPath')); + + if ( + !getFormElementDefinition(formElement, '_isTopLevelFormElement') + && getFormElementDefinition(formElement, '_isCompositeFormElement') + && !getFormElementDefinition(formElement, '_isGridContainerFormElement') + ) { + $(this).tooltip({ + title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', + placement: 'rigth' + }); + } else if ( + !getFormElementDefinition(formElement, '_isTopLevelFormElement') + && !getFormElementDefinition(formElement, '_isCompositeFormElement') + ) { + $(this).tooltip({ + title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', + placement: 'left' + }); + } - if ('function' === $.type(callback)) { - callback(); + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + $(this).addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); + } + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + $(this).addClass(getHelper().getDomElementClassName('formElementIsComposit')); + } + }); + + }; + + /* ************************************************************* + * Template rendering + * ************************************************************/ + + /** + * @public + * + * @param object + * @param template + * @param function + * @return void + */ + function eachTemplateProperty(formElement, template, callback) { + $(getHelper().getDomElementDataAttribute('templateProperty', 'bracesWithKey'), template).each(function(i, element) { + var propertyPath, propertyValue; + + propertyPath = $(element).attr(getHelper().getDomElementDataAttribute('templateProperty')); + propertyValue = formElement.get(propertyPath); + + if ('function' === $.type(callback)) { + callback(propertyPath, propertyValue, element); + } + }); + }; + + /** + * @private + * + * @return object + * @return object + * @return void + */ + function renderCheckboxTemplate(formElement, template) { + renderSimpleTemplateWithValidators(formElement, template); + + eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { + if ( + ('boolean' === $.type(propertyValue) && propertyValue) + || propertyValue === 'true' + || propertyValue === 1 + || propertyValue === "1" + ) { + $(domElement).addClass(getHelper().getDomElementClassName('noNesting')); + } + }); + }; + + /** + * @public + * + * @return object + * @return object + * @return void + * @throws 1479035696 + */ + function renderSimpleTemplate(formElement, template) { + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035696); + + eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { + _setTemplateTextContent(domElement, propertyValue); + }); + + Icons.getIcon( + getFormElementDefinition(formElement, 'iconIdentifier'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + $(getHelper().getDomElementDataIdentifierSelector('formElementIcon'), template) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); + }); + + getHelper() + .getTemplatePropertyDomElement('_type', template) + .append(formElement.get('type')); + getHelper() + .getTemplatePropertyDomElement('_identifier', template) + .append(formElement.get('identifier')); + }; + + /** + * @public + * + * @return object + * @return object + * @return void + * @throws 1479035674 + */ + function renderSimpleTemplateWithValidators(formElement, template) { + var validators, validatorsCountWithoutRequired, validatorsTemplateContent; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035674); + + renderSimpleTemplate(formElement, template); + + validatorsTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), + $(template) + ).clone(); + + $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)).empty(); + validators = formElement.get('validators'); + + if ('array' === $.type(validators)) { + validatorsCountWithoutRequired = 0; + if (validators.length > 0) { + for (var i = 0, len = validators.length; i < len; ++i) { + var collectionElementConfiguration, rowTemplate; + + if ('NotEmpty' === validators[i]['identifier']) { + getHelper() + .getTemplatePropertyDomElement('_required', template) + .text('*'); + continue; } - }; - + validatorsCountWithoutRequired++; - /* ************************************************************* - * Preview stage - * ************************************************************/ + collectionElementConfiguration = getFormEditorApp() + .getFormEditorDefinition('validators', validators[i]['identifier']); + rowTemplate = $($(validatorsTemplateContent).clone()); - /** - * @public - * - * @param string html - * @return void - * @throws 1475424409 - */ - function renderPreviewStageArea(html) { - assert(getUtility().isNonEmptyString(html), 'Invalid parameter "html"', 1475424409); - - _stageDomElement.off().empty().html(html); + getHelper() + .getTemplatePropertyDomElement('_label', rowTemplate) + .append(collectionElementConfiguration['label']); + $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)) + .append(rowTemplate.html()); + } - $(':input', _stageDomElement).prop('disabled', 'disabled').on('click dblclick select focus keydown keypress keyup mousedown mouseup', function(e) { - return e.preventDefault(); + if (validatorsCountWithoutRequired > 0) { + Icons.getIcon( + getHelper().getDomElementDataAttributeValue('iconValidator'), + Icons.sizes.small, + null, + Icons.states.default, + Icons.markupIdentifiers.inline + ).done(function(icon) { + $(getHelper().getDomElementDataIdentifierSelector('validatorIcon'), $(template)) + .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); }); + } + } + } + }; + + /** + * @public + * + * @return object + * @return object + * @return void + */ + function renderSelectTemplates(formElement, template) { + var appendMultiValue, defaultValue, multiValueTemplateContent, propertyPath, propertyValue; + + multiValueTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), + $(template) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); + + renderSimpleTemplateWithValidators(formElement, template); + + propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .attr(getHelper().getDomElementDataAttribute('templateProperty')); + + propertyValue = formElement.get(propertyPath); + + appendMultiValue = function(label, value, defaultValue) { + var isPreselected, rowTemplate; + + isPreselected = false; + rowTemplate = $($(multiValueTemplateContent).clone()); + + for (var defaultValueKey in defaultValue) { + if (!defaultValue.hasOwnProperty(defaultValueKey)) { + continue; + } + if (defaultValue[defaultValueKey] === value) { + isPreselected = true; + break; + } + } - $('form', _stageDomElement).submit(function(e) { - return e.preventDefault(); - }); + getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label); - getAllFormElementDomElements().each(function(i, element) { - var formElement, metaLabel; - - formElement = getFormEditorApp() - .getFormElementByIdentifierPath($(this).data('elementIdentifierPath')); - - if ( - !getFormElementDefinition(formElement, '_isTopLevelFormElement') - && getFormElementDefinition(formElement, '_isCompositeFormElement') - && !getFormElementDefinition(formElement, '_isGridContainerFormElement') - ) { - $(this).tooltip({ - title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', - placement : 'rigth' - }); - } else if ( - !getFormElementDefinition(formElement, '_isTopLevelFormElement') - && !getFormElementDefinition(formElement, '_isCompositeFormElement') - ) { - $(this).tooltip({ - title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')', - placement : 'left' - }); - } - - if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { - $(this).addClass(getHelper().getDomElementClassName('formElementIsTopLevel')); - } - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - $(this).addClass(getHelper().getDomElementClassName('formElementIsComposit')); - } - }); + if (isPreselected) { + getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass( + getHelper().getDomElementClassName('selected') + ); + } - }; - - /* ************************************************************* - * Template rendering - * ************************************************************/ - - /** - * @public - * - * @param object - * @param template - * @param function - * @return void - */ - function eachTemplateProperty(formElement, template, callback) { - $(getHelper().getDomElementDataAttribute('templateProperty', 'bracesWithKey'), template).each(function(i, element) { - var propertyPath, propertyValue; - - propertyPath = $(element).attr(getHelper().getDomElementDataAttribute('templateProperty')); - propertyValue = formElement.get(propertyPath); - - if ('function' === $.type(callback)) { - callback(propertyPath, propertyValue, element); - } - }); - }; - - /** - * @private - * - * @return object - * @return object - * @return void - */ - function renderCheckboxTemplate(formElement, template) { - renderSimpleTemplateWithValidators(formElement, template); - - eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { - if ( - ('boolean' === $.type(propertyValue) && propertyValue) - || propertyValue === 'true' - || propertyValue === 1 - || propertyValue === "1" - ) { - $(domElement).addClass(getHelper().getDomElementClassName('noNesting')); - } - }); - }; - - /** - * @public - * - * @return object - * @return object - * @return void - * @throws 1479035696 - */ - function renderSimpleTemplate(formElement, template) { - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035696); - - eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) { - _setTemplateTextContent(domElement, propertyValue); - }); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .append(rowTemplate.html()); + }; - Icons.getIcon( - getFormElementDefinition(formElement, 'iconIdentifier'), - Icons.sizes.small, - null, - Icons.states.default, - Icons.markupIdentifiers.inline - ).done(function(icon) { - $(getHelper().getDomElementDataIdentifierSelector('formElementIcon'), template) - .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); - }); + defaultValue = formElement.get('defaultValue'); - getHelper() - .getTemplatePropertyDomElement('_type', template) - .append(formElement.get('type')); - getHelper() - .getTemplatePropertyDomElement('_identifier', template) - .append(formElement.get('identifier')); - }; - - /** - * @public - * - * @return object - * @return object - * @return void - * @throws 1479035674 - */ - function renderSimpleTemplateWithValidators(formElement, template) { - var validators, validatorsCountWithoutRequired, validatorsTemplateContent; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035674); - - renderSimpleTemplate(formElement, template); - - validatorsTemplateContent = $( - getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), - $(template) - ).clone(); - - $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)).empty(); - validators = formElement.get('validators'); - - if ('array' === $.type(validators)) { - validatorsCountWithoutRequired = 0; - if (validators.length > 0) { - for (var i = 0, len = validators.length; i < len; ++i) { - var collectionElementConfiguration, rowTemplate; - - if ('NotEmpty' === validators[i]['identifier']) { - getHelper() - .getTemplatePropertyDomElement('_required', template) - .text('*'); - continue; - } - validatorsCountWithoutRequired++; - - collectionElementConfiguration = getFormEditorApp() - .getFormEditorDefinition('validators', validators[i]['identifier']); - rowTemplate = $($(validatorsTemplateContent).clone()); - - getHelper() - .getTemplatePropertyDomElement('_label', rowTemplate) - .append(collectionElementConfiguration['label']); - $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)) - .append(rowTemplate.html()); - } - - if (validatorsCountWithoutRequired > 0) { - Icons.getIcon( - getHelper().getDomElementDataAttributeValue('iconValidator'), - Icons.sizes.small, - null, - Icons.states.default, - Icons.markupIdentifiers.inline - ).done(function(icon) { - $(getHelper().getDomElementDataIdentifierSelector('validatorIcon'), $(template)) - .append($(icon).addClass(getHelper().getDomElementClassName('icon'))); - }); - } - } - } - }; - - /** - * @public - * - * @return object - * @return object - * @return void - */ - function renderSelectTemplates(formElement, template) { - var appendMultiValue, defaultValue, multiValueTemplateContent, propertyPath, propertyValue; - - multiValueTemplateContent = $( - getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), - $(template) - ).clone(); - $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); - - renderSimpleTemplateWithValidators(formElement, template); - - propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) - .attr(getHelper().getDomElementDataAttribute('templateProperty')); - - propertyValue = formElement.get(propertyPath); - - appendMultiValue = function(label, value, defaultValue) { - var isPreselected, rowTemplate; - - isPreselected = false; - rowTemplate = $($(multiValueTemplateContent).clone()); - - for (var defaultValueKey in defaultValue) { - if (!defaultValue.hasOwnProperty(defaultValueKey)) { - continue; - } - if (defaultValue[defaultValueKey] === value) { - isPreselected = true; - break; - } - } - - getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label); - - if (isPreselected) { - getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass( - getHelper().getDomElementClassName('selected') - ); - } - - $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) - .append(rowTemplate.html()); - }; - - defaultValue = formElement.get('defaultValue'); - - if (getFormEditorApp().getUtility().isUndefinedOrNull(defaultValue)) { - defaultValue = {}; - } else if ('string' === $.type(defaultValue)) { - defaultValue = {0: defaultValue}; - } + if (getFormEditorApp().getUtility().isUndefinedOrNull(defaultValue)) { + defaultValue = {}; + } else if ('string' === $.type(defaultValue)) { + defaultValue = {0: defaultValue}; + } - if ('object' === $.type(propertyValue)) { - for (var propertyValueKey in propertyValue) { - if (!propertyValue.hasOwnProperty(propertyValueKey)) { - continue; - } - appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue); - } - } else if ('array' === $.type(propertyValue)) { - for (var propertyValueKey in propertyValue) { - if (!propertyValue.hasOwnProperty(propertyValueKey)) { - continue; - } - if (getUtility().isUndefinedOrNull(propertyValue[propertyValueKey]['_label'])) { - appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue); - } else { - appendMultiValue(propertyValue[propertyValueKey]['_label'], propertyValue[propertyValueKey]['_value'], defaultValue); - } - } - } - }; - - /** - * @public - * - * @return object - * @return object - * @return void - */ - function renderFileUploadTemplates(formElement, template) { - var appendMultiValue, multiValueTemplateContent, propertyPath, propertyValue; - - multiValueTemplateContent = $( - getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), - $(template) - ).clone(); - $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); - - renderSimpleTemplateWithValidators(formElement, template); - - propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) - .attr(getHelper().getDomElementDataAttribute('templateProperty')); - propertyValue = formElement.get(propertyPath); - - appendMultiValue = function(value) { - var rowTemplate; - - rowTemplate = $($(multiValueTemplateContent).clone()); - - getHelper().getTemplatePropertyDomElement('_value', rowTemplate).append(value); - $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) - .append(rowTemplate.html()); - }; - - if ('object' === $.type(propertyValue)) { - for (var propertyValueKey in propertyValue) { - if (!propertyValue.hasOwnProperty(propertyValueKey)) { - continue; - } - appendMultiValue(propertyValue[propertyValueKey]); - } - } else if ('array' === $.type(propertyValue)) { - for (var i = 0, len = propertyValue.length; i < len; ++i) { - appendMultiValue(propertyValue[i]); - } - } - }; - - /** - * @public - * - * @param object - * @param object - * @param object - * @return this - * @throws 1478992119 - */ - function bootstrap(formEditorApp, appendToDomElement, configuration) { - _formEditorApp = formEditorApp; - assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478992119); - - _stageDomElement = $(appendToDomElement); - _configuration = $.extend(true, _defaultConfiguration, configuration || {}); - _helperSetup(); - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - buildTitleByFormElement: buildTitleByFormElement, - createAndAddAbstractViewFormElementToolbar: createAndAddAbstractViewFormElementToolbar, - createAbstractViewFormElementToolbar: createAbstractViewFormElementToolbar, - eachTemplateProperty: eachTemplateProperty, - getAbstractViewFormElementDomElement: getAbstractViewFormElementDomElement, - getAbstractViewFormElementWithinDomElement: getAbstractViewFormElementWithinDomElement, - getAbstractViewFormElementIdentifierPathWithinDomElement: getAbstractViewFormElementIdentifierPathWithinDomElement, - getAbstractViewParentFormElementWithinDomElement: getAbstractViewParentFormElementWithinDomElement, - getAbstractViewParentFormElementIdentifierPathWithinDomElement: getAbstractViewParentFormElementIdentifierPathWithinDomElement, - getAbstractViewSiblingFormElementIdentifierPathWithinDomElement: getAbstractViewSiblingFormElementIdentifierPathWithinDomElement, - getAllFormElementDomElements: getAllFormElementDomElements, - getStageDomElement: getStageDomElement, - getStagePanelDomElement: getStagePanelDomElement, - removeAllStageToolbars: removeAllStageToolbars, - renderAbstractStageArea: renderAbstractStageArea, - renderCheckboxTemplate: renderCheckboxTemplate, - renderFileUploadTemplates: renderFileUploadTemplates, - renderFormDefinitionPageAsSortableList: renderFormDefinitionPageAsSortableList, - renderPagination: renderPagination, - renderPreviewStageArea: renderPreviewStageArea, - renderSelectTemplates: renderSelectTemplates, - renderSimpleTemplate: renderSimpleTemplate, - renderSimpleTemplateWithValidators: renderSimpleTemplateWithValidators, - renderUndoRedo: renderUndoRedo, - setStageHeadline: setStageHeadline - }; - })($, Helper, Icons); + if ('object' === $.type(propertyValue)) { + for (var propertyValueKey in propertyValue) { + if (!propertyValue.hasOwnProperty(propertyValueKey)) { + continue; + } + appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue); + } + } else if ('array' === $.type(propertyValue)) { + for (var propertyValueKey in propertyValue) { + if (!propertyValue.hasOwnProperty(propertyValueKey)) { + continue; + } + if (getUtility().isUndefinedOrNull(propertyValue[propertyValueKey]['_label'])) { + appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue); + } else { + appendMultiValue(propertyValue[propertyValueKey]['_label'], propertyValue[propertyValueKey]['_value'], defaultValue); + } + } + } + }; + + /** + * @public + * + * @return object + * @return object + * @return void + */ + function renderFileUploadTemplates(formElement, template) { + var appendMultiValue, multiValueTemplateContent, propertyPath, propertyValue; + + multiValueTemplateContent = $( + getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), + $(template) + ).clone(); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty(); + + renderSimpleTemplateWithValidators(formElement, template); + + propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .attr(getHelper().getDomElementDataAttribute('templateProperty')); + propertyValue = formElement.get(propertyPath); + + appendMultiValue = function(value) { + var rowTemplate; + + rowTemplate = $($(multiValueTemplateContent).clone()); + + getHelper().getTemplatePropertyDomElement('_value', rowTemplate).append(value); + $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)) + .append(rowTemplate.html()); + }; + + if ('object' === $.type(propertyValue)) { + for (var propertyValueKey in propertyValue) { + if (!propertyValue.hasOwnProperty(propertyValueKey)) { + continue; + } + appendMultiValue(propertyValue[propertyValueKey]); + } + } else if ('array' === $.type(propertyValue)) { + for (var i = 0, len = propertyValue.length; i < len; ++i) { + appendMultiValue(propertyValue[i]); + } + } + }; + + /** + * @public + * + * @param object + * @param object + * @param object + * @return this + * @throws 1478992119 + */ + function bootstrap(formEditorApp, appendToDomElement, configuration) { + _formEditorApp = formEditorApp; + assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478992119); + + _stageDomElement = $(appendToDomElement); + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + createAndAddAbstractViewFormElementToolbar: createAndAddAbstractViewFormElementToolbar, + createAbstractViewFormElementToolbar: createAbstractViewFormElementToolbar, + eachTemplateProperty: eachTemplateProperty, + getAbstractViewFormElementDomElement: getAbstractViewFormElementDomElement, + getAbstractViewFormElementWithinDomElement: getAbstractViewFormElementWithinDomElement, + getAbstractViewFormElementIdentifierPathWithinDomElement: getAbstractViewFormElementIdentifierPathWithinDomElement, + getAbstractViewParentFormElementWithinDomElement: getAbstractViewParentFormElementWithinDomElement, + getAbstractViewParentFormElementIdentifierPathWithinDomElement: getAbstractViewParentFormElementIdentifierPathWithinDomElement, + getAbstractViewSiblingFormElementIdentifierPathWithinDomElement: getAbstractViewSiblingFormElementIdentifierPathWithinDomElement, + getAllFormElementDomElements: getAllFormElementDomElements, + getStageDomElement: getStageDomElement, + getStagePanelDomElement: getStagePanelDomElement, + removeAllStageToolbars: removeAllStageToolbars, + renderAbstractStageArea: renderAbstractStageArea, + renderCheckboxTemplate: renderCheckboxTemplate, + renderFileUploadTemplates: renderFileUploadTemplates, + renderFormDefinitionPageAsSortableList: renderFormDefinitionPageAsSortableList, + renderPagination: renderPagination, + renderPreviewStageArea: renderPreviewStageArea, + renderSelectTemplates: renderSelectTemplates, + renderSimpleTemplate: renderSimpleTemplate, + renderSimpleTemplateWithValidators: renderSimpleTemplateWithValidators, + renderUndoRedo: renderUndoRedo, + setStageHeadline: setStageHeadline + }; + })($, Helper, Icons); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js index 902125cbeca4b1c655d2c4596d5dd6e1ae175473..b296c8452ca0b1e0843d503f916fa215288d89a9 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js @@ -15,674 +15,677 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/TreeComponent */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' - ], function($, Helper, Icons) { - 'use strict'; - - return (function($, Helper, Icons) { - - /** - * @private - * - * @var object - */ - var _configuration = null; - - /** - * @private - * - * @var object - */ - var _expanderStates = {}; - - /** - * @private - * - * @var object - */ - var _defaultConfiguration = { - domElementClassNames: { - collapsed: 'mjs-nestedSortable-collapsed', - expanded: 'mjs-nestedSortable-expanded', - hasChildren: 't3-form-element-has-children', - sortable: 'sortable', - svgLinkWrapper: 'svg-wrapper', - noNesting: 'mjs-nestedSortable-no-nesting' - }, - domElementDataAttributeNames: { - abstractType: 'data-element-abstract-type' - }, - domElementDataAttributeValues: { - collapse: 'actions-pagetree-collapse', - expander: 'treeExpander', - title: 'treeTitle' - }, - isSortable: true, - svgLink: { - height: 15, - paths: { - angle: 'M0 0 V20 H15', - vertical: 'M0 0 V20 H0', - hidden: 'M0 0 V0 H0' - }, - width: 15 - } - }; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /** - * @private - * - * @var object - */ - var _treeDomElement = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @public - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @param object - * @param string - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @private - * - * @return object - */ - function _getLinkSvg(type) { - return $('<span class="' + getHelper().getDomElementClassName('svgLinkWrapper') + '">' - + '<svg version="1.1" width="' + _configuration['svgLink']['width'] + '" height="' + _configuration['svgLink']['height'] + '">' - + '<path class="link" d="' + _configuration['svgLink']['paths'][type] + '">' - + '</svg>' - + '</span>'); - }; - - /** - * @private - * - * @param object - * @return object - * @publish view/tree/render/listItemAdded - * @throws 1478715704 - */ - function _renderNestedSortableListItem(formElement) { - var childFormElements, childList, expanderItem, isLastFormElementWithinParentFormElement, listItem, listItemContent, searchElement; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478715704); - - isLastFormElementWithinParentFormElement = false; - if (formElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(formElement).get('__identifierPath')) { - isLastFormElementWithinParentFormElement = true; - } - - listItem = $('<li></li>'); - if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { - listItem.addClass(getHelper().getDomElementClassName('noNesting')); - } - - listItemContent = $('<div></div>') - .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) - .append( - $('<span></span>') - .attr(getHelper().getDomElementDataAttribute('identifier'), getHelper().getDomElementDataAttributeValue('title')) - .html(buildTitleByFormElement(formElement)) - ); - - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); - } - if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { - listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); - } - - expanderItem = $('<span></span>').attr('data-identifier', getHelper().getDomElementDataAttributeValue('expander')); - listItemContent.prepend(expanderItem); - - Icons.getIcon(getFormElementDefinition(formElement, 'iconIdentifier'), Icons.sizes.small, null, Icons.states.default).done(function(icon) { - expanderItem.after( - $(icon).addClass(getHelper().getDomElementClassName('icon')) - .tooltip({ - title: 'identifier: ' + formElement.get('identifier'), - placement: 'right' - }) - ); - - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - if (formElement.get('renderables') && formElement.get('renderables').length > 0) { - Icons.getIcon(getHelper().getDomElementDataAttributeValue('collapse'), Icons.sizes.small).done(function(icon) { - expanderItem.before(_getLinkSvg('angle')).html($(icon)); - listItem.addClass(getHelper().getDomElementClassName('hasChildren')); - }); - } else { - expanderItem.before(_getLinkSvg('angle')).remove(); - } - } else { - listItemContent.prepend(_getLinkSvg('angle')); - expanderItem.remove(); - } - - searchElement = formElement.get('__parentRenderable'); - while (searchElement) { - if (searchElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { - break; - } - - if (searchElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(searchElement).get('__identifierPath')) { - listItemContent.prepend(_getLinkSvg('hidden')); - } else { - listItemContent.prepend(_getLinkSvg('vertical')); - } - searchElement = searchElement.get('__parentRenderable'); - } - }); - listItem.append(listItemContent); - - getPublisherSubscriber().publish('view/tree/render/listItemAdded', [listItem, formElement]); - childFormElements = formElement.get('renderables'); - childList = null; - if ('array' === $.type(childFormElements)) { - childList = $('<ol></ol>'); - for (var i = 0, len = childFormElements.length; i < len; ++i) { - childList.append(_renderNestedSortableListItem(childFormElements[i])); - } - } - - if (childList) { - listItem.append(childList); - } - return listItem; - }; - - /** - * @private - * - * @return void - * @publish view/tree/dnd/stop - * @publish view/tree/dnd/change - * @publish view/tree/dnd/update - */ - function _addSortableEvents() { - $('ol.' + getHelper().getDomElementClassName('sortable'), _treeDomElement).nestedSortable({ - forcePlaceholderSize: true, - protectRoot: true, - isTree: true, - handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), - helper: 'clone', - items: 'li', - opacity: .6, - revert: 250, - delay: 200, - tolerance: 'pointer', - toleranceElement: '> div', - - isAllowed: function (placeholder, placeholderParent, currentItem) { - var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, targetFormElementTypeDefinition; - - if (typeof placeholderParent === 'undefined') { - return true; - } - - formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(currentItem)); - targetFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(placeholderParent)); - - formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath); - targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath); - - if ( - targetFormElementTypeDefinition['_isTopLevelFormElement'] - && !targetFormElementTypeDefinition['_isCompositeFormElement'] - ) { - return false; - } - - if ( - formElementTypeDefinition['_isGridContainerFormElement'] - && ( - getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) - || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) - ) - ) { - return false; - } - - if ( - !formElementTypeDefinition['_isGridContainerFormElement'] - && !formElementTypeDefinition['_isGridRowFormElement'] - && targetFormElementTypeDefinition['_isGridContainerFormElement'] - ) { - return false; - } - - return true; - }, - stop: function(e, o) { - getPublisherSubscriber().publish('view/tree/dnd/stop', [getTreeNodeIdentifierPathWithinDomElement($(o.item))]); - }, - change: function(e, o) { - var enclosingCompositeFormElement, parentFormElementIdentifierPath; - - parentFormElementIdentifierPath = getParentTreeNodeIdentifierPathWithinDomElement($(o.placeholder)); - if (parentFormElementIdentifierPath) { - enclosingCompositeFormElement = getFormEditorApp().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); - } - getPublisherSubscriber().publish('view/tree/dnd/change', [$(o.placeholder), parentFormElementIdentifierPath, enclosingCompositeFormElement]); - }, - update: function(e, o) { - var nextFormElementIdentifierPath, movedFormElementIdentifierPath, previousFormElementIdentifierPath; - - movedFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(o.item)); - previousFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'prev'); - nextFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'next'); - - getPublisherSubscriber().publish('view/tree/dnd/update', [$(o.item), movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath]); - } + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable' +], function($, Helper, Icons) { + 'use strict'; + + return (function($, Helper, Icons) { + + /** + * @private + * + * @var object + */ + var _configuration = null; + + /** + * @private + * + * @var object + */ + var _expanderStates = {}; + + /** + * @private + * + * @var object + */ + var _defaultConfiguration = { + domElementClassNames: { + collapsed: 'mjs-nestedSortable-collapsed', + expanded: 'mjs-nestedSortable-expanded', + hasChildren: 't3-form-element-has-children', + sortable: 'sortable', + svgLinkWrapper: 'svg-wrapper', + noNesting: 'mjs-nestedSortable-no-nesting' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type' + }, + domElementDataAttributeValues: { + collapse: 'actions-pagetree-collapse', + expander: 'treeExpander', + title: 'treeTitle' + }, + isSortable: true, + svgLink: { + height: 15, + paths: { + angle: 'M0 0 V20 H15', + vertical: 'M0 0 V20 H0', + hidden: 'M0 0 V0 H0' + }, + width: 15 + } + }; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _treeDomElement = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @param object + * @param string + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @private + * + * @return object + */ + function _getLinkSvg(type) { + return $('<span class="' + getHelper().getDomElementClassName('svgLinkWrapper') + '">' + + '<svg version="1.1" width="' + _configuration['svgLink']['width'] + '" height="' + _configuration['svgLink']['height'] + '">' + + '<path class="link" d="' + _configuration['svgLink']['paths'][type] + '">' + + '</svg>' + + '</span>'); + }; + + /** + * @private + * + * @param object + * @return object + * @publish view/tree/render/listItemAdded + * @throws 1478715704 + */ + function _renderNestedSortableListItem(formElement) { + var childFormElements, childList, expanderItem, isLastFormElementWithinParentFormElement, + listItem, listItemContent, searchElement; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478715704); + + isLastFormElementWithinParentFormElement = false; + if (formElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(formElement).get('__identifierPath')) { + isLastFormElementWithinParentFormElement = true; + } + + listItem = $('<li></li>'); + if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItem.addClass(getHelper().getDomElementClassName('noNesting')); + } + + listItemContent = $('<div></div>') + .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath')) + .append( + $('<span></span>') + .attr(getHelper().getDomElementDataAttribute('identifier'), getHelper().getDomElementDataAttributeValue('title')) + .html(buildTitleByFormElement(formElement)) + ); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement'); + } + if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) { + listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement'); + } + + expanderItem = $('<span></span>').attr('data-identifier', getHelper().getDomElementDataAttributeValue('expander')); + listItemContent.prepend(expanderItem); + + Icons.getIcon(getFormElementDefinition(formElement, 'iconIdentifier'), Icons.sizes.small, null, Icons.states.default).done(function(icon) { + expanderItem.after( + $(icon).addClass(getHelper().getDomElementClassName('icon')) + .tooltip({ + title: 'identifier: ' + formElement.get('identifier'), + placement: 'right' + }) + ); + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + if (formElement.get('renderables') && formElement.get('renderables').length > 0) { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('collapse'), Icons.sizes.small).done(function(icon) { + expanderItem.before(_getLinkSvg('angle')).html($(icon)); + listItem.addClass(getHelper().getDomElementClassName('hasChildren')); }); - }; - - /** - * @private - * - * @return void - */ - function _saveExpanderStates() { - var addStates; - - addStates = function(formElement) { - var childFormElements, treeNode; - - if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { - treeNode = getTreeNode(formElement); - if (treeNode.length) { - if (treeNode.closest('li').hasClass(getHelper().getDomElementClassName('expanded'))) { - _expanderStates[formElement.get('__identifierPath')] = true; - } else { - _expanderStates[formElement.get('__identifierPath')] = false; - } - } - - if (getUtility().isUndefinedOrNull(_expanderStates[formElement.get('__identifierPath')])) { - _expanderStates[formElement.get('__identifierPath')] = true; - } - } - - childFormElements = formElement.get('renderables'); - if ('array' === $.type(childFormElements)) { - for (var i = 0, len = childFormElements.length; i < len; ++i) { - addStates(childFormElements[i]); - } - } - }; - addStates(getRootFormElement()); - - for (var identifierPath in _expanderStates) { - if (!_expanderStates.hasOwnProperty(identifierPath)) { - continue; - } - try { - getFormEditorApp().getFormElementByIdentifierPath(identifierPath); - } catch(error) { - delete _expanderStates[identifierPath]; - } - } - }; - - /** - * @private - * - * @return void - */ - function _loadExpanderStates() { - for (var identifierPath in _expanderStates) { - var treeNode; - - if (!_expanderStates.hasOwnProperty(identifierPath)) { - continue; - } - treeNode = getTreeNode(identifierPath); - if (treeNode.length) { - if (_expanderStates[identifierPath]) { - treeNode.closest('li') - .removeClass(getHelper().getDomElementClassName('collapsed')) - .addClass(getHelper().getDomElementClassName('expanded')); - } else { - treeNode.closest('li') - .addClass(getHelper().getDomElementClassName('collapsed')) - .removeClass(getHelper().getDomElementClassName('expanded')); - } - } - } - }; - - /* ************************************************************* - * Public Methodes - * ************************************************************/ - - /** - * @public - * - * @param object - * @return object - * @throws 1478721208 - */ - function renderCompositeFormElementChildsAsSortableList(formElement) { - var elementList; - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478721208); - - elementList = $('<ol></ol>').addClass(getHelper().getDomElementClassName('sortable')); - if ('array' === $.type(formElement.get('renderables'))) { - for (var i = 0, len = formElement.get('renderables').length; i < len; ++i) { - elementList.append(_renderNestedSortableListItem(formElement.get('renderables')[i])); - } - } - return elementList; - }; - - /** - * @public - * - * @return void - * @param object - * @publish view/tree/node/clicked - */ - function renew(formElement) { - if (getFormEditorApp().getUtility().isUndefinedOrNull(formElement)) { - formElement = getRootFormElement(); - } - _saveExpanderStates(); - _treeDomElement.off().empty().append(renderCompositeFormElementChildsAsSortableList(formElement)); - - _treeDomElement.on("click", function(e) { - var formElementIdentifierPath; - - formElementIdentifierPath = $(e.target) - .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - if (getUtility().isUndefinedOrNull(formElementIdentifierPath) || !getUtility().isNonEmptyString(formElementIdentifierPath)) { - return; - } - getPublisherSubscriber().publish('view/tree/node/clicked', [formElementIdentifierPath]); - }); - - $(getHelper().getDomElementDataIdentifierSelector('expander'), _treeDomElement).on('click', function() { - $(this).closest('li').toggleClass(getHelper().getDomElementClassName('collapsed')).toggleClass(getHelper().getDomElementClassName('expanded')); - }); - - if (_configuration['isSortable']) { - _addSortableEvents(); - } - _loadExpanderStates(); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getAllTreeNodes() { - return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), _treeDomElement); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getTreeNodeWithinDomElement(element) { - return $(element).find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getTreeNodeIdentifierPathWithinDomElement(element) { - return getTreeNodeWithinDomElement($(element)).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getParentTreeNodeWithinDomElement(element) { - return $(element).parent().closest('li').find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); - }; - - /** - * @public - * - * @param object - * @return string - */ - function getParentTreeNodeIdentifierPathWithinDomElement(element) { - return getParentTreeNodeWithinDomElement(element).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @private - * - * @param object - * @param string - * @return string - */ - function getSiblingTreeNodeIdentifierPathWithinDomElement(element, position) { - var formElementIdentifierPath; - - if (getUtility().isUndefinedOrNull(position)) { - position = 'prev'; - } - formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement(element); - element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); - return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) - .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) - .first() - .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); - }; - - /** - * @public - * - * @param string - * @param object - * @return void - */ - function setTreeNodeTitle(title, formElement) { - if (getUtility().isUndefinedOrNull(title)) { - title = buildTitleByFormElement(formElement); - } - - $(getHelper().getDomElementDataIdentifierSelector('title'), getTreeNode(formElement)).html(title); - }; - - /** - * @public - * - * @param string|object - * @return object - */ - function getTreeNode(formElement) { - var formElementIdentifierPath; - - if ('string' === $.type(formElement)) { - formElementIdentifierPath = formElement; + } else { + expanderItem.before(_getLinkSvg('angle')).remove(); + } + } else { + listItemContent.prepend(_getLinkSvg('angle')); + expanderItem.remove(); + } + + searchElement = formElement.get('__parentRenderable'); + while (searchElement) { + if (searchElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) { + break; + } + + if (searchElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(searchElement).get('__identifierPath')) { + listItemContent.prepend(_getLinkSvg('hidden')); + } else { + listItemContent.prepend(_getLinkSvg('vertical')); + } + searchElement = searchElement.get('__parentRenderable'); + } + }); + listItem.append(listItemContent); + + getPublisherSubscriber().publish('view/tree/render/listItemAdded', [listItem, formElement]); + childFormElements = formElement.get('renderables'); + childList = null; + if ('array' === $.type(childFormElements)) { + childList = $('<ol></ol>'); + for (var i = 0, len = childFormElements.length; i < len; ++i) { + childList.append(_renderNestedSortableListItem(childFormElements[i])); + } + } + + if (childList) { + listItem.append(childList); + } + return listItem; + }; + + /** + * @private + * + * @return void + * @publish view/tree/dnd/stop + * @publish view/tree/dnd/change + * @publish view/tree/dnd/update + */ + function _addSortableEvents() { + $('ol.' + getHelper().getDomElementClassName('sortable'), _treeDomElement).nestedSortable({ + forcePlaceholderSize: true, + protectRoot: true, + isTree: true, + handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), + helper: 'clone', + items: 'li', + opacity: .6, + revert: 250, + delay: 200, + tolerance: 'pointer', + toleranceElement: '> div', + + isAllowed: function(placeholder, placeholderParent, currentItem) { + var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, + targetFormElementTypeDefinition; + + if (typeof placeholderParent === 'undefined') { + return true; + } + + formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(currentItem)); + targetFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(placeholderParent)); + + formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath); + targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath); + + if ( + targetFormElementTypeDefinition['_isTopLevelFormElement'] + && !targetFormElementTypeDefinition['_isCompositeFormElement'] + ) { + return false; + } + + if ( + formElementTypeDefinition['_isGridContainerFormElement'] + && ( + getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath) + || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath) + ) + ) { + return false; + } + + if ( + !formElementTypeDefinition['_isGridContainerFormElement'] + && !formElementTypeDefinition['_isGridRowFormElement'] + && targetFormElementTypeDefinition['_isGridContainerFormElement'] + ) { + return false; + } + + return true; + }, + stop: function(e, o) { + getPublisherSubscriber().publish('view/tree/dnd/stop', [getTreeNodeIdentifierPathWithinDomElement($(o.item))]); + }, + change: function(e, o) { + var enclosingCompositeFormElement, parentFormElementIdentifierPath; + + parentFormElementIdentifierPath = getParentTreeNodeIdentifierPathWithinDomElement($(o.placeholder)); + if (parentFormElementIdentifierPath) { + enclosingCompositeFormElement = getFormEditorApp().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath); + } + getPublisherSubscriber().publish('view/tree/dnd/change', [$(o.placeholder), parentFormElementIdentifierPath, enclosingCompositeFormElement]); + }, + update: function(e, o) { + var nextFormElementIdentifierPath, movedFormElementIdentifierPath, + previousFormElementIdentifierPath; + + movedFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(o.item)); + previousFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'prev'); + nextFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'next'); + + getPublisherSubscriber().publish('view/tree/dnd/update', [$(o.item), movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath]); + } + }); + }; + + /** + * @private + * + * @return void + */ + function _saveExpanderStates() { + var addStates; + + addStates = function(formElement) { + var childFormElements, treeNode; + + if (getFormElementDefinition(formElement, '_isCompositeFormElement')) { + treeNode = getTreeNode(formElement); + if (treeNode.length) { + if (treeNode.closest('li').hasClass(getHelper().getDomElementClassName('expanded'))) { + _expanderStates[formElement.get('__identifierPath')] = true; } else { - if (getUtility().isUndefinedOrNull(formElement)) { - formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); - } else { - formElementIdentifierPath = formElement.get('__identifierPath'); - } - } - return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _treeDomElement); - }; - - /** - * @public - * - * @param object - * @return object - * @throws 1478719287 - */ - function buildTitleByFormElement(formElement) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); + _expanderStates[formElement.get('__identifierPath')] = false; } - assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478719287); - - return $('<span></span>') - .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))) - .append($('<small></small>').text("(" + getFormElementDefinition(formElement, 'label') + ")")); - }; - - /** - * @public - * - * @return object - */ - function getTreeDomElement() { - return _treeDomElement; - }; - - /** - * @public - * - * @param object - * @param object - * @param object - * @return this - * @throws 1478714814 - */ - function bootstrap(formEditorApp, appendToDomElement, configuration) { - _formEditorApp = formEditorApp; - assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478714814); - - _treeDomElement = $(appendToDomElement); - _configuration = $.extend(true, _defaultConfiguration, configuration || {}); - _helperSetup(); - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - bootstrap: bootstrap, - buildTitleByFormElement: buildTitleByFormElement, - getAllTreeNodes: getAllTreeNodes, - getParentTreeNodeWithinDomElement: getParentTreeNodeWithinDomElement, - getParentTreeNodeIdentifierPathWithinDomElement: getParentTreeNodeIdentifierPathWithinDomElement, - getSiblingTreeNodeIdentifierPathWithinDomElement: getSiblingTreeNodeIdentifierPathWithinDomElement, - getTreeDomElement: getTreeDomElement, - getTreeNode: getTreeNode, - getTreeNodeWithinDomElement: getTreeNodeWithinDomElement, - getTreeNodeIdentifierPathWithinDomElement: getTreeNodeIdentifierPathWithinDomElement, - renderCompositeFormElementChildsAsSortableList: renderCompositeFormElementChildsAsSortableList, - renew: renew, - setTreeNodeTitle: setTreeNodeTitle - }; - })($, Helper, Icons); + } + + if (getUtility().isUndefinedOrNull(_expanderStates[formElement.get('__identifierPath')])) { + _expanderStates[formElement.get('__identifierPath')] = true; + } + } + + childFormElements = formElement.get('renderables'); + if ('array' === $.type(childFormElements)) { + for (var i = 0, len = childFormElements.length; i < len; ++i) { + addStates(childFormElements[i]); + } + } + }; + addStates(getRootFormElement()); + + for (var identifierPath in _expanderStates) { + if (!_expanderStates.hasOwnProperty(identifierPath)) { + continue; + } + try { + getFormEditorApp().getFormElementByIdentifierPath(identifierPath); + } catch (error) { + delete _expanderStates[identifierPath]; + } + } + }; + + /** + * @private + * + * @return void + */ + function _loadExpanderStates() { + for (var identifierPath in _expanderStates) { + var treeNode; + + if (!_expanderStates.hasOwnProperty(identifierPath)) { + continue; + } + treeNode = getTreeNode(identifierPath); + if (treeNode.length) { + if (_expanderStates[identifierPath]) { + treeNode.closest('li') + .removeClass(getHelper().getDomElementClassName('collapsed')) + .addClass(getHelper().getDomElementClassName('expanded')); + } else { + treeNode.closest('li') + .addClass(getHelper().getDomElementClassName('collapsed')) + .removeClass(getHelper().getDomElementClassName('expanded')); + } + } + } + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @param object + * @return object + * @throws 1478721208 + */ + function renderCompositeFormElementChildsAsSortableList(formElement) { + var elementList; + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478721208); + + elementList = $('<ol></ol>').addClass(getHelper().getDomElementClassName('sortable')); + if ('array' === $.type(formElement.get('renderables'))) { + for (var i = 0, len = formElement.get('renderables').length; i < len; ++i) { + elementList.append(_renderNestedSortableListItem(formElement.get('renderables')[i])); + } + } + return elementList; + }; + + /** + * @public + * + * @return void + * @param object + * @publish view/tree/node/clicked + */ + function renew(formElement) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(formElement)) { + formElement = getRootFormElement(); + } + _saveExpanderStates(); + _treeDomElement.off().empty().append(renderCompositeFormElementChildsAsSortableList(formElement)); + + _treeDomElement.on("click", function(e) { + var formElementIdentifierPath; + + formElementIdentifierPath = $(e.target) + .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + if (getUtility().isUndefinedOrNull(formElementIdentifierPath) || !getUtility().isNonEmptyString(formElementIdentifierPath)) { + return; + } + getPublisherSubscriber().publish('view/tree/node/clicked', [formElementIdentifierPath]); + }); + + $(getHelper().getDomElementDataIdentifierSelector('expander'), _treeDomElement).on('click', function() { + $(this).closest('li').toggleClass(getHelper().getDomElementClassName('collapsed')).toggleClass(getHelper().getDomElementClassName('expanded')); + }); + + if (_configuration['isSortable']) { + _addSortableEvents(); + } + _loadExpanderStates(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getAllTreeNodes() { + return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), _treeDomElement); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getTreeNodeWithinDomElement(element) { + return $(element).find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getTreeNodeIdentifierPathWithinDomElement(element) { + return getTreeNodeWithinDomElement($(element)).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getParentTreeNodeWithinDomElement(element) { + return $(element).parent().closest('li').find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first(); + }; + + /** + * @public + * + * @param object + * @return string + */ + function getParentTreeNodeIdentifierPathWithinDomElement(element) { + return getParentTreeNodeWithinDomElement(element).attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @private + * + * @param object + * @param string + * @return string + */ + function getSiblingTreeNodeIdentifierPathWithinDomElement(element, position) { + var formElementIdentifierPath; + + if (getUtility().isUndefinedOrNull(position)) { + position = 'prev'; + } + formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement(element); + element = (position === 'prev') ? $(element).prev('li') : $(element).next('li'); + return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')) + .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath])) + .first() + .attr(getHelper().getDomElementDataAttribute('elementIdentifier')); + }; + + /** + * @public + * + * @param string + * @param object + * @return void + */ + function setTreeNodeTitle(title, formElement) { + if (getUtility().isUndefinedOrNull(title)) { + title = buildTitleByFormElement(formElement); + } + + $(getHelper().getDomElementDataIdentifierSelector('title'), getTreeNode(formElement)).html(title); + }; + + /** + * @public + * + * @param string|object + * @return object + */ + function getTreeNode(formElement) { + var formElementIdentifierPath; + + if ('string' === $.type(formElement)) { + formElementIdentifierPath = formElement; + } else { + if (getUtility().isUndefinedOrNull(formElement)) { + formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath'); + } else { + formElementIdentifierPath = formElement.get('__identifierPath'); + } + } + return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _treeDomElement); + }; + + /** + * @public + * + * @param object + * @return object + * @throws 1478719287 + */ + function buildTitleByFormElement(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478719287); + + return $('<span></span>') + .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier'))) + .append($('<small></small>').text("(" + getFormElementDefinition(formElement, 'label') + ")")); + }; + + /** + * @public + * + * @return object + */ + function getTreeDomElement() { + return _treeDomElement; + }; + + /** + * @public + * + * @param object + * @param object + * @param object + * @return this + * @throws 1478714814 + */ + function bootstrap(formEditorApp, appendToDomElement, configuration) { + _formEditorApp = formEditorApp; + assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478714814); + + _treeDomElement = $(appendToDomElement); + _configuration = $.extend(true, _defaultConfiguration, configuration || {}); + _helperSetup(); + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap, + buildTitleByFormElement: buildTitleByFormElement, + getAllTreeNodes: getAllTreeNodes, + getParentTreeNodeWithinDomElement: getParentTreeNodeWithinDomElement, + getParentTreeNodeIdentifierPathWithinDomElement: getParentTreeNodeIdentifierPathWithinDomElement, + getSiblingTreeNodeIdentifierPathWithinDomElement: getSiblingTreeNodeIdentifierPathWithinDomElement, + getTreeDomElement: getTreeDomElement, + getTreeNode: getTreeNode, + getTreeNodeWithinDomElement: getTreeNodeWithinDomElement, + getTreeNodeIdentifierPathWithinDomElement: getTreeNodeIdentifierPathWithinDomElement, + renderCompositeFormElementChildsAsSortableList: renderCompositeFormElementChildsAsSortableList, + renew: renew, + setTreeNodeTitle: setTreeNodeTitle + }; + })($, Helper, Icons); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js index 2ee4e2763d3d81bcc13f739988daf78dfe757a3e..201ef7d193d44d07db8ab85f3e11314734d42cdc 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js @@ -15,1757 +15,1757 @@ * Module: TYPO3/CMS/Form/Backend/FormEditor/ViewModel */ define(['jquery', - 'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent', - 'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent', - 'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent', - 'TYPO3/CMS/Form/Backend/FormEditor/StageComponent', - 'TYPO3/CMS/Form/Backend/FormEditor/Helper', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification' - ], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { - 'use strict'; - - return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { - - /** - * @private - * - * @var object - */ - var _configuration = { - domElementClassNames: { - formElementIsComposit: 't3-form-element-composit', - formElementIsTopLevel: 't3-form-element-toplevel', - hasError: 'has-error', - headerButtonBar: 'module-docheader-bar-column-left', - selectedCompositFormElement: 't3-form-form-composit-element-selected', - selectedFormElement: 't3-form-form-element-selected', - selectedRootFormElement: 't3-form-root-element-selected', - selectedStagePanel: 't3-form-form-stage-selected', - sortableHover: 'sortable-hover', - stageViewModeAbstract: 't3-form-stage-viewmode-abstract', - stageViewModePreview: 't3-form-stage-viewmode-preview', - validationErrors: 't3-form-validation-errors', - validationChildHasErrors: 't3-form-validation-child-has-error' - }, - domElementDataAttributeNames: { - abstractType: 'data-element-abstract-type' - }, - domElementDataAttributeValues: { - buttonHeaderClose: 'closeButton', - buttonHeaderNewPage: 'headerNewPage', - buttonHeaderPaginationNext: 'buttonPaginationNext', - buttonHeaderPaginationPrevious: 'buttonPaginationPrevious', - buttonHeaderRedo: 'redoButton', - buttonHeaderSave: 'saveButton', - buttonHeaderSettings: 'formSettingsButton', - buttonHeaderUndo: 'undoButton', - buttonHeaderViewModeAbstract: 'buttonViewModeAbstract', - buttonHeaderViewModePreview: 'buttonViewModePreview', - buttonStageNewElementBottom: 'stageNewElementBottom', - buttonStructureNewPage: 'treeNewPageBottom', - iconMailform: 'content-elements-mailform', - iconSave: 'actions-document-save', - iconSaveSpinner: 'spinner-circle-dark', - inspectorSection: 'inspectorSection', - moduleLoadingIndicator: 'moduleLoadingIndicator', - moduleWrapper: 'moduleWrapper', - stageArea: 'stageArea', - stageContainer: 'stageContainer', - stageContainerInner: 'stageContainerInner', - stageNewElementRow: 'stageNewElementRow', - stagePanelHeading: 'panelHeading', - stageSection: 'stageSection', - structure: 'structure-element', - structureSection: 'structureSection', - structureRootContainer: 'treeRootContainer', - structureRootElement: 'treeRootElement' - }, - panels: { - structure: { - width: 300 - }, - stage: { - marginLeft: 300, - marginRight: 325, - marginLeftCollapsed: 0, - marginRightCollapsed: -25, - maxWidthPreview: 1000, - maxWidthAbstract: 800 - }, - inspector: { - width: 350 - } - } - }; - - /** - * @private - * - * @var bool - */ - var _previewMode = false; - - /** - * @private - * - * @var object - */ - var _formEditorApp = null; - - /** - * @private - * - * @var object - */ - var _structureComponent = null; - - /** - * @private - * - * @var object - */ - var _modalsComponent = null; - - /** - * @private - * - * @var object - */ - var _inspectorsComponent = null; - - /** - * @private - * - * @var object - */ - var _stageComponent = null; - - /* ************************************************************* - * Private Methodes - * ************************************************************/ - - /** - * @private - * - * @return object - */ - function getRootFormElement() { - return getFormEditorApp().getRootFormElement(); - }; - - /** - * @private - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - return getFormEditorApp().assert(test, message, messageCode); - }; - - /** - * @private - * - * @return object - */ - function getUtility() { - return getFormEditorApp().getUtility(); - }; - - /** - * @private - * - * @return object - */ - function getCurrentlySelectedFormElement() { - return getFormEditorApp().getCurrentlySelectedFormElement(); - }; - - - /** - * @private - * - * @return object - */ - function getPublisherSubscriber() { - return getFormEditorApp().getPublisherSubscriber(); - }; - - /** - * @private - * - * @return void - */ - function _addPropertyValidators() { - getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) { - if (formElement.get(propertyPath) === '') { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) { - if (!$.isNumeric(formElement.get(propertyPath))) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('IntegerOrEmpty', function(formElement, propertyPath) { - if (formElement.get(propertyPath).length > 0 && !$.isNumeric(formElement.get(propertyPath))) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) { - if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) { - if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) { - var match, regex; - regex = /\{([a-z0-9-_]+)?\}/gi; - match = regex.exec(formElement.get(propertyPath)); - if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) { - var match, regex; - regex = /^\{([a-z0-9-_]+)?\}$/i; - match = regex.exec(formElement.get(propertyPath)); - if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; - } - }); - - getFormEditorApp().addPropertyValidationValidator('FileSize', function(formElement, propertyPath) { - if (!formElement.get(propertyPath).match(/^(\d*\.?\d+)(B|K|M|G)$/i)) { - return getFormEditorApp().getFormElementPropertyValidatorDefinition('FileSize')['errorMessage'] || 'invalid value'; - } - }); - }; - - /** - * @private - * - * @param object additionalViewModelModules - * @return void - * @publish view/ready - * @throws 1475425785 - */ - function _loadAdditionalModules(additionalViewModelModules) { - var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules; - - if ('array' !== $.type(additionalViewModelModules)) { - return; - } - additionalViewModelModulesLength = additionalViewModelModules.length; - - if (additionalViewModelModulesLength > 0) { - loadedAdditionalViewModelModules = 0; - for (var i = 0; i < additionalViewModelModulesLength; ++i) { - require([additionalViewModelModules[i]], function (additionalViewModelModule) { - assert( - 'function' === $.type(additionalViewModelModule.bootstrap), - 'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"', - 1475425785 - ); - additionalViewModelModule.bootstrap(getFormEditorApp()); - - loadedAdditionalViewModelModules++; - if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) { - getPublisherSubscriber().publish('view/ready'); - } - }); - } - } else { - getPublisherSubscriber().publish('view/ready'); - } - }; - - /** - * @private - * - * @return void - * @throws 1478268638 - */ - function _helperSetup() { - assert('function' === $.type(Helper.bootstrap), - 'The view model helper does not implement the method "bootstrap"', - 1478268638 - ); - - Helper.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return void - * @throws 1478268639 - */ - function _structureComponentSetup() { - assert( - 'function' === $.type(TreeComponent.bootstrap), - 'The structure component does not implement the method "bootstrap"', - 1478268639 - ); - - _structureComponent = TreeComponent.bootstrap( - getFormEditorApp(), - $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ - getHelper().getDomElementDataAttributeValue('structure') - ])) - ); - - $( getHelper().getDomElementDataIdentifierSelector('iconMailform'), - $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')) - ).tooltip({ - title: 'identifier: ' + getRootFormElement().get('identifier'), - placement: 'right' - }); - }; - - /** - * @private - * - * @return void - * @throws 1478895106 - */ - function _modalsComponentSetup() { - assert( - 'function' === $.type(ModalsComponent.bootstrap), - 'The modals component does not implement the method "bootstrap"', - 1478895106 - ); - _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return void - * @throws 1478895106 - */ - function _inspectorsComponentSetup() { - assert( - 'function' === $.type(InspectorComponent.bootstrap), - 'The inspector component does not implement the method "bootstrap"', - 1478895106 - ); - _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp()); - }; - - /** - * @private - * - * @return void - * @throws 1478986610 - */ - function _stageComponentSetup() { + 'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/StageComponent', + 'TYPO3/CMS/Form/Backend/FormEditor/Helper', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification' +], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { + 'use strict'; + + return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) { + + /** + * @private + * + * @var object + */ + var _configuration = { + domElementClassNames: { + formElementIsComposit: 't3-form-element-composit', + formElementIsTopLevel: 't3-form-element-toplevel', + hasError: 'has-error', + headerButtonBar: 'module-docheader-bar-column-left', + selectedCompositFormElement: 't3-form-form-composit-element-selected', + selectedFormElement: 't3-form-form-element-selected', + selectedRootFormElement: 't3-form-root-element-selected', + selectedStagePanel: 't3-form-form-stage-selected', + sortableHover: 'sortable-hover', + stageViewModeAbstract: 't3-form-stage-viewmode-abstract', + stageViewModePreview: 't3-form-stage-viewmode-preview', + validationErrors: 't3-form-validation-errors', + validationChildHasErrors: 't3-form-validation-child-has-error' + }, + domElementDataAttributeNames: { + abstractType: 'data-element-abstract-type' + }, + domElementDataAttributeValues: { + buttonHeaderClose: 'closeButton', + buttonHeaderNewPage: 'headerNewPage', + buttonHeaderPaginationNext: 'buttonPaginationNext', + buttonHeaderPaginationPrevious: 'buttonPaginationPrevious', + buttonHeaderRedo: 'redoButton', + buttonHeaderSave: 'saveButton', + buttonHeaderSettings: 'formSettingsButton', + buttonHeaderUndo: 'undoButton', + buttonHeaderViewModeAbstract: 'buttonViewModeAbstract', + buttonHeaderViewModePreview: 'buttonViewModePreview', + buttonStageNewElementBottom: 'stageNewElementBottom', + buttonStructureNewPage: 'treeNewPageBottom', + iconMailform: 'content-elements-mailform', + iconSave: 'actions-document-save', + iconSaveSpinner: 'spinner-circle-dark', + inspectorSection: 'inspectorSection', + moduleLoadingIndicator: 'moduleLoadingIndicator', + moduleWrapper: 'moduleWrapper', + stageArea: 'stageArea', + stageContainer: 'stageContainer', + stageContainerInner: 'stageContainerInner', + stageNewElementRow: 'stageNewElementRow', + stagePanelHeading: 'panelHeading', + stageSection: 'stageSection', + structure: 'structure-element', + structureSection: 'structureSection', + structureRootContainer: 'treeRootContainer', + structureRootElement: 'treeRootElement' + }, + panels: { + structure: { + width: 300 + }, + stage: { + marginLeft: 300, + marginRight: 325, + marginLeftCollapsed: 0, + marginRightCollapsed: -25, + maxWidthPreview: 1000, + maxWidthAbstract: 800 + }, + inspector: { + width: 350 + } + } + }; + + /** + * @private + * + * @var bool + */ + var _previewMode = false; + + /** + * @private + * + * @var object + */ + var _formEditorApp = null; + + /** + * @private + * + * @var object + */ + var _structureComponent = null; + + /** + * @private + * + * @var object + */ + var _modalsComponent = null; + + /** + * @private + * + * @var object + */ + var _inspectorsComponent = null; + + /** + * @private + * + * @var object + */ + var _stageComponent = null; + + /* ************************************************************* + * Private Methodes + * ************************************************************/ + + /** + * @private + * + * @return object + */ + function getRootFormElement() { + return getFormEditorApp().getRootFormElement(); + }; + + /** + * @private + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + return getFormEditorApp().assert(test, message, messageCode); + }; + + /** + * @private + * + * @return object + */ + function getUtility() { + return getFormEditorApp().getUtility(); + }; + + /** + * @private + * + * @return object + */ + function getCurrentlySelectedFormElement() { + return getFormEditorApp().getCurrentlySelectedFormElement(); + }; + + + /** + * @private + * + * @return object + */ + function getPublisherSubscriber() { + return getFormEditorApp().getPublisherSubscriber(); + }; + + /** + * @private + * + * @return void + */ + function _addPropertyValidators() { + getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) { + if (formElement.get(propertyPath) === '') { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) { + if (!$.isNumeric(formElement.get(propertyPath))) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('IntegerOrEmpty', function(formElement, propertyPath) { + if (formElement.get(propertyPath).length > 0 && !$.isNumeric(formElement.get(propertyPath))) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) { + if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) { + if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) { + var match, regex; + regex = /\{([a-z0-9-_]+)?\}/gi; + match = regex.exec(formElement.get(propertyPath)); + if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) { + var match, regex; + regex = /^\{([a-z0-9-_]+)?\}$/i; + match = regex.exec(formElement.get(propertyPath)); + if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value'; + } + }); + + getFormEditorApp().addPropertyValidationValidator('FileSize', function(formElement, propertyPath) { + if (!formElement.get(propertyPath).match(/^(\d*\.?\d+)(B|K|M|G)$/i)) { + return getFormEditorApp().getFormElementPropertyValidatorDefinition('FileSize')['errorMessage'] || 'invalid value'; + } + }); + }; + + /** + * @private + * + * @param object additionalViewModelModules + * @return void + * @publish view/ready + * @throws 1475425785 + */ + function _loadAdditionalModules(additionalViewModelModules) { + var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules; + + if ('array' !== $.type(additionalViewModelModules)) { + return; + } + additionalViewModelModulesLength = additionalViewModelModules.length; + + if (additionalViewModelModulesLength > 0) { + loadedAdditionalViewModelModules = 0; + for (var i = 0; i < additionalViewModelModulesLength; ++i) { + require([additionalViewModelModules[i]], function(additionalViewModelModule) { assert( - 'function' === $.type(InspectorComponent.bootstrap), - 'The stage component does not implement the method "bootstrap"', - 1478986610 + 'function' === $.type(additionalViewModelModule.bootstrap), + 'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"', + 1475425785 ); - _stageComponent = StageComponent.bootstrap( - getFormEditorApp(), - $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ - getHelper().getDomElementDataAttributeValue('stageArea') - ])) - ); - - getStage().getStagePanelDomElement().on("click", function(e) { - if ( - $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stagePanelHeading') - || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageSection') - || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageArea') - ) { - selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex()); - } - getPublisherSubscriber().publish('view/stage/panel/clicked', []); - }); - }; - - /** - * @private - * - * @return void - * @publish view/header/button/save/clicked - * @publish view/stage/abstract/button/newElement/clicked - * @publish view/header/button/newPage/clicked - * @publish view/structure/button/newPage/clicked - * @publish view/header/button/close/clicked - */ - function _buttonsSetup() { - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) { - getPublisherSubscriber().publish('view/header/button/save/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')).on('click', function(e) { - getPublisherSubscriber().publish('view/header/formSettings/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) { - getPublisherSubscriber().publish( - 'view/stage/abstract/button/newElement/clicked', [ - 'view/insertElements/perform/bottom' - ] - ); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) { - getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) { - getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) { - if (!getFormEditorApp().getUnsavedContent()) { - return; - } - e.preventDefault(); - getPublisherSubscriber().publish('view/header/button/close/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) { - getPublisherSubscriber().publish('view/undoButton/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) { - getPublisherSubscriber().publish('view/redoButton/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) { - getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) { - getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) { - getPublisherSubscriber().publish('view/structure/root/selected'); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) { - getPublisherSubscriber().publish('view/paginationNext/clicked', []); - }); - - $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) { - getPublisherSubscriber().publish('view/paginationPrevious/clicked', []); - }); - }; - - /* ************************************************************* - * Public Methodes - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getFormEditorApp() { - return _formEditorApp; - }; - - /** - * @public - * - * @param object - * @return object - */ - function getHelper(configuration) { - if (getUtility().isUndefinedOrNull(configuration)) { - return Helper.setConfiguration(_configuration); - } - return Helper.setConfiguration(configuration); - }; - - /** - * @public - * - * @param object formElement - * @param string formElementDefinitionKey - * @return mixed - */ - function getFormElementDefinition(formElement, formElementDefinitionKey) { - return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); - }; - - /** - * @public - * - * @return object (derefernced) - */ - function getConfiguration() { - return $.extend(true, {}, _configuration); - }; - - /** - * @public - * - * @return int - */ - function getPreviewMode() { - return _previewMode; - }; - - /** - * @public - * - * @param bool - * @return void - */ - function setPreviewMode(previewMode) { - _previewMode = !!previewMode; - }; - - /* ************************************************************* - * Structure - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getStructure() { - return _structureComponent; - }; - - /** - * @public - * - * @return void - * @publish view/structure/renew/postProcess - */ - function renewStructure() { - getStructure().renew(); - getPublisherSubscriber().publish('view/structure/renew/postProcess'); - }; - - /** - * @public - * - * @param object - * @return void - */ - function addStructureSelection(formElement) { - getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement')); - }; - - /** - * @public - * - * @param object - * @return void - */ - function removeStructureSelection(formElement) { - getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement')); - }; - - /** - * @public - * - * @return void - */ - function removeAllStructureSelections() { - $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement()) - .removeClass(getHelper().getDomElementClassName('selectedFormElement')); - }; - - /** - * @public - * - * @return object - */ - function getStructureRootElement() { - return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ - getHelper().getDomElementDataAttributeValue('structureRootElement') - ])); - }; - - /** - * @public - * - * @return void - */ - function removeStructureRootElementSelection() { - $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ - getHelper().getDomElementDataAttributeValue('structureRootContainer') - ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement')); - }; - - /** - * @public - * - * @return void - */ - function addStructureRootElementSelection() { - $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ - getHelper().getDomElementDataAttributeValue('structureRootContainer') - ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement')); - }; - - /** - * @public - * - * @param string title - * @return void - */ - function setStructureRootElementTitle(title) { - if (getUtility().isUndefinedOrNull(title)) { - title = $('<span></span>') - .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier'))) - .text(); - } - getStructureRootElement().text(title); - }; - - /** - * @public - * - * @return void - */ - function addStructureValidationResults() { - var validationResults; - - getStructure().getAllTreeNodes() - .removeClass(getHelper().getDomElementClassName('validationErrors')) - .removeClass(getHelper().getDomElementClassName('validationChildHasErrors')); - - removeElementValidationErrorClass(getStructureRootElement()); - - validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); - for (var i = 0, len = validationResults.length; i < len; ++i) { - var hasError = false, pathParts, validationElement; - for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { - if ( - validationResults[i]['validationResults'][j]['validationResults'] - && validationResults[i]['validationResults'][j]['validationResults'].length > 0 - ) { - hasError = true; - break; - } - } - - if (hasError) { - if (i === 0) { - setElementValidationErrorClass(getStructureRootElement()); - } else { - validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']); - setElementValidationErrorClass(validationElement); - - pathParts = validationResults[i]['formElementIdentifierPath'].split('/'); - while(pathParts.pop()) { - validationElement = getStructure().getTreeNode(pathParts.join('/')); - if ('object' === $.type(validationElement)) { - setElementValidationErrorClass(validationElement, 'validationChildHasErrors'); - } - } - } - } - } - }; - - /* ************************************************************* - * Modals - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getModals() { - return _modalsComponent - }; - - /** - * @public - * - * @param object formElement - * @return void - */ - function showRemoveFormElementModal(formElement) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - getModals().showRemoveFormElementModal(formElement); - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @return void - */ - function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement); - }; - - /** - * @public - * - * @return void - */ - function showCloseConfirmationModal() { - getModals().showCloseConfirmationModal(); - }; - - /** - * @public - * - * @param string targetEvent - * @param object configuration - * @return void - */ - function showInsertElementsModal(targetEvent, configuration) { - getModals().showInsertElementsModal(targetEvent, configuration); - }; - - /** - * @public - * - * @param string targetEvent - * @return void - */ - function showInsertPagesModal(targetEvent) { - getModals().showInsertPagesModal(targetEvent); - }; - - /** - * @public - * - * @param bool - * @return void - */ - function showValidationErrorsModal() { - var validationResults; - validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); - - getModals().showValidationErrorsModal(validationResults); - }; - - /* ************************************************************* - * Inspector - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getInspector() { - return _inspectorsComponent - }; - - /** - * @public - * - * @param object - * @param bool - * @return void - */ - function renderInspectorEditors(formElement, useFadeEffect) { - var render; - if (getUtility().isUndefinedOrNull(useFadeEffect)) { - useFadeEffect = true; - } + additionalViewModelModule.bootstrap(getFormEditorApp()); - /** - * @private - * - * @param function - * @return void - */ - render = function(callback) { - getInspector().renderEditors(formElement, callback); - }; - - if (!!useFadeEffect) { - getInspector().getInspectorDomElement().fadeOut('fast', function() { - render(function() { - getInspector().getInspectorDomElement().fadeIn('fast'); - }); - }); - } else { - render(); - } - }; - - /** - * @public - * - * @param string - * @param string - * @return void - */ - function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) { - getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier); - }; - - /** - * @public - * - * @param string content - * @return void - */ - function setInspectorFormElementHeaderEditorContent(content) { - getInspector().setFormElementHeaderEditorContent(content); - }; - - /* ************************************************************* - * Stage - * ************************************************************/ - - /** - * @public - * - * @return object - */ - function getStage() { - return _stageComponent; - }; - - /** - * @public - * - * @param string title - * @return void - */ - function setStageHeadline(title) { - getStage().setStageHeadline(title); - }; - - /** - * @public - * - * @return void - */ - function addStagePanelSelection() { - getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel')); - }; - - /** - * @public - * - * @return void - */ - function removeStagePanelSelection() { - getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel')); - }; - - /** - * @public - * - * @return void - */ - function renderPagination() { - getStage().renderPagination(); - }; - - /** - * @public - * - * @return void - */ - function renderUndoRedo() { - getStage().renderUndoRedo(); - }; - - /** - * @public - * - * @param bool - * @param bool - * @return void - * @publish view/stage/abstract/render/postProcess - * @publish view/stage/abstract/render/preProcess - */ - function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) { - var render, renderPostProcess; - - $(getHelper().getDomElementDataIdentifierSelector('structureSection')) - .animate({ - 'left': '0px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) - .animate({ - 'right': '0px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) - .animate({ - 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', - 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner')) - .animate({ - 'max-width': _configuration['panels']['stage']['maxWidthAbstract'] + 'px' - }, 'slow'); - $(getHelper().getDomElementClassName('headerButtonBar', true)) - .animate({ - 'margin-left': _configuration['panels']['structure']['width'] + 'px' - }, 'slow'); - - if (getUtility().isUndefinedOrNull(useFadeEffect)) { - useFadeEffect = true; - } - - if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { - toolbarUseFadeEffect = true; - } - - setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); - removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); - - /** - * @private - * - * @param function - * @return void - */ - render = function(callback) { - $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) - .addClass(getHelper().getDomElementClassName('stageViewModeAbstract')) - .removeClass(getHelper().getDomElementClassName('stageViewModePreview')); - - getStage().renderAbstractStageArea(undefined, callback); - }; - - /** - * @private - * - * @return void - */ - renderPostProcess = function() { - var formElementTypeDefinition; - - formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); - getStage().getAllFormElementDomElements().hover(function() { - getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); - if ( - $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit')) - && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel')) - ) { - $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover')); - } - }); - - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); - if ( - formElementTypeDefinition['_isTopLevelFormElement'] - && !formElementTypeDefinition['_isCompositeFormElement'] - && !getFormEditorApp().isRootFormElementSelected() - ) { - hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); - hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); - } else { - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); - } - - refreshSelectedElementItemsBatch(toolbarUseFadeEffect); - getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); - }; - - if (useFadeEffect) { - $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { - render(function() { - getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); - $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); - renderPostProcess(); - getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); - }); - }); - } else { - render(function() { - getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); - renderPostProcess(); - getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); - }); - } - }; - - /** - * @public - * - * @param string html - * @return void - * @publish view/stage/preview/render/postProcess - */ - function renderPreviewStageArea(html) { - $(getHelper().getDomElementDataIdentifierSelector('structureSection')) - .animate({ - 'left': '-=' + _configuration['panels']['structure']['width'] + 'px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) - .animate({ - 'right': '-=' + _configuration['panels']['inspector']['width'] + 'px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) - .animate({ - 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px', - 'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px' - }, 'slow'); - $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner')) - .animate({ - 'max-width': _configuration['panels']['stage']['maxWidthPreview'] + 'px' - }, 'slow'); - $(getHelper().getDomElementClassName('headerButtonBar', true)) - .animate({ - 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px' - }, 'slow'); - - setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); - removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); - - $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { - $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) - .addClass(getHelper().getDomElementClassName('stageViewModePreview')) - .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract')); - - hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); - hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); - - getStage().renderPreviewStageArea(html); - $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); - getPublisherSubscriber().publish('view/stage/preview/render/postProcess'); - }); - }; - - /** - * @public - * - * @return void - */ - function addAbstractViewValidationResults() { - var validationResults; - - validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); - for (var i = 0, len = validationResults.length; i < len; ++i) { - var hasError = false, validationElement; - for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { - if ( - validationResults[i]['validationResults'][j]['validationResults'] - && validationResults[i]['validationResults'][j]['validationResults'].length > 0 - ) { - hasError = true; - break; - } - } - - if (hasError) { - if (i > 0) { - validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']); - setElementValidationErrorClass(validationElement); - } - } - } - }; - - /* ************************************************************* - * Form element methods - * ************************************************************/ - - /** - * @public - * - * @param string formElementType - * @param string|object referenceFormElement - * @param bool - * @return object - * @publish view/formElement/inserted - */ - function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { - var newFormElement; - - newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement); - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); + loadedAdditionalViewModelModules++; + if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) { + getPublisherSubscriber().publish('view/ready'); } - return newFormElement; - }; - - /** - * @public - * - * @param string|object formElementToMove - * @param string position - * @param string|object referenceFormElement - * @param bool - * @return object - * @publish view/formElement/moved - */ - function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { - var movedFormElement; - - movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false); - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]); + }); + } + } else { + getPublisherSubscriber().publish('view/ready'); + } + }; + + /** + * @private + * + * @return void + * @throws 1478268638 + */ + function _helperSetup() { + assert('function' === $.type(Helper.bootstrap), + 'The view model helper does not implement the method "bootstrap"', + 1478268638 + ); + + Helper.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478268639 + */ + function _structureComponentSetup() { + assert( + 'function' === $.type(TreeComponent.bootstrap), + 'The structure component does not implement the method "bootstrap"', + 1478268639 + ); + + _structureComponent = TreeComponent.bootstrap( + getFormEditorApp(), + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structure') + ])) + ); + + $(getHelper().getDomElementDataIdentifierSelector('iconMailform'), + $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')) + ).tooltip({ + title: 'identifier: ' + getRootFormElement().get('identifier'), + placement: 'right' + }); + }; + + /** + * @private + * + * @return void + * @throws 1478895106 + */ + function _modalsComponentSetup() { + assert( + 'function' === $.type(ModalsComponent.bootstrap), + 'The modals component does not implement the method "bootstrap"', + 1478895106 + ); + _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478895106 + */ + function _inspectorsComponentSetup() { + assert( + 'function' === $.type(InspectorComponent.bootstrap), + 'The inspector component does not implement the method "bootstrap"', + 1478895106 + ); + _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp()); + }; + + /** + * @private + * + * @return void + * @throws 1478986610 + */ + function _stageComponentSetup() { + assert( + 'function' === $.type(InspectorComponent.bootstrap), + 'The stage component does not implement the method "bootstrap"', + 1478986610 + ); + _stageComponent = StageComponent.bootstrap( + getFormEditorApp(), + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('stageArea') + ])) + ); + + getStage().getStagePanelDomElement().on("click", function(e) { + if ( + $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stagePanelHeading') + || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageSection') + || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageArea') + ) { + selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex()); + } + getPublisherSubscriber().publish('view/stage/panel/clicked', []); + }); + }; + + /** + * @private + * + * @return void + * @publish view/header/button/save/clicked + * @publish view/stage/abstract/button/newElement/clicked + * @publish view/header/button/newPage/clicked + * @publish view/structure/button/newPage/clicked + * @publish view/header/button/close/clicked + */ + function _buttonsSetup() { + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) { + getPublisherSubscriber().publish('view/header/button/save/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')).on('click', function(e) { + getPublisherSubscriber().publish('view/header/formSettings/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) { + getPublisherSubscriber().publish( + 'view/stage/abstract/button/newElement/clicked', [ + 'view/insertElements/perform/bottom' + ] + ); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) { + getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) { + getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) { + if (!getFormEditorApp().getUnsavedContent()) { + return; + } + e.preventDefault(); + getPublisherSubscriber().publish('view/header/button/close/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) { + getPublisherSubscriber().publish('view/undoButton/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) { + getPublisherSubscriber().publish('view/redoButton/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) { + getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) { + getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) { + getPublisherSubscriber().publish('view/structure/root/selected'); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) { + getPublisherSubscriber().publish('view/paginationNext/clicked', []); + }); + + $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) { + getPublisherSubscriber().publish('view/paginationPrevious/clicked', []); + }); + }; + + /* ************************************************************* + * Public Methodes + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getFormEditorApp() { + return _formEditorApp; + }; + + /** + * @public + * + * @param object + * @return object + */ + function getHelper(configuration) { + if (getUtility().isUndefinedOrNull(configuration)) { + return Helper.setConfiguration(_configuration); + } + return Helper.setConfiguration(configuration); + }; + + /** + * @public + * + * @param object formElement + * @param string formElementDefinitionKey + * @return mixed + */ + function getFormElementDefinition(formElement, formElementDefinitionKey) { + return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey); + }; + + /** + * @public + * + * @return object (derefernced) + */ + function getConfiguration() { + return $.extend(true, {}, _configuration); + }; + + /** + * @public + * + * @return int + */ + function getPreviewMode() { + return _previewMode; + }; + + /** + * @public + * + * @param bool + * @return void + */ + function setPreviewMode(previewMode) { + _previewMode = !!previewMode; + }; + + /* ************************************************************* + * Structure + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStructure() { + return _structureComponent; + }; + + /** + * @public + * + * @return void + * @publish view/structure/renew/postProcess + */ + function renewStructure() { + getStructure().renew(); + getPublisherSubscriber().publish('view/structure/renew/postProcess'); + }; + + /** + * @public + * + * @param object + * @return void + */ + function addStructureSelection(formElement) { + getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function removeStructureSelection(formElement) { + getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @return void + */ + function removeAllStructureSelections() { + $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement()) + .removeClass(getHelper().getDomElementClassName('selectedFormElement')); + }; + + /** + * @public + * + * @return object + */ + function getStructureRootElement() { + return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootElement') + ])); + }; + + /** + * @public + * + * @return void + */ + function removeStructureRootElementSelection() { + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootContainer') + ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement')); + }; + + /** + * @public + * + * @return void + */ + function addStructureRootElementSelection() { + $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [ + getHelper().getDomElementDataAttributeValue('structureRootContainer') + ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement')); + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStructureRootElementTitle(title) { + if (getUtility().isUndefinedOrNull(title)) { + title = $('<span></span>') + .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier'))) + .text(); + } + getStructureRootElement().text(title); + }; + + /** + * @public + * + * @return void + */ + function addStructureValidationResults() { + var validationResults; + + getStructure().getAllTreeNodes() + .removeClass(getHelper().getDomElementClassName('validationErrors')) + .removeClass(getHelper().getDomElementClassName('validationChildHasErrors')); + + removeElementValidationErrorClass(getStructureRootElement()); + + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, pathParts, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + if (i === 0) { + setElementValidationErrorClass(getStructureRootElement()); + } else { + validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']); + setElementValidationErrorClass(validationElement); + + pathParts = validationResults[i]['formElementIdentifierPath'].split('/'); + while (pathParts.pop()) { + validationElement = getStructure().getTreeNode(pathParts.join('/')); + if ('object' === $.type(validationElement)) { + setElementValidationErrorClass(validationElement, 'validationChildHasErrors'); + } } - return movedFormElement; - }; - - /** - * @public - * - * @param object formElement - * @param bool - * @return object - * @publish view/formElement/removed - */ - function removeFormElement(formElement, disablePublishersOnSet) { - var parentFormElement; - - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); + } + } + } + }; + + /* ************************************************************* + * Modals + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getModals() { + return _modalsComponent + }; + + /** + * @public + * + * @param object formElement + * @return void + */ + function showRemoveFormElementModal(formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getModals().showRemoveFormElementModal(formElement); + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @return void + */ + function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement); + }; + + /** + * @public + * + * @return void + */ + function showCloseConfirmationModal() { + getModals().showCloseConfirmationModal(); + }; + + /** + * @public + * + * @param string targetEvent + * @param object configuration + * @return void + */ + function showInsertElementsModal(targetEvent, configuration) { + getModals().showInsertElementsModal(targetEvent, configuration); + }; + + /** + * @public + * + * @param string targetEvent + * @return void + */ + function showInsertPagesModal(targetEvent) { + getModals().showInsertPagesModal(targetEvent); + }; + + /** + * @public + * + * @param bool + * @return void + */ + function showValidationErrorsModal() { + var validationResults; + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + + getModals().showValidationErrorsModal(validationResults); + }; + + /* ************************************************************* + * Inspector + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getInspector() { + return _inspectorsComponent + }; + + /** + * @public + * + * @param object + * @param bool + * @return void + */ + function renderInspectorEditors(formElement, useFadeEffect) { + var render; + if (getUtility().isUndefinedOrNull(useFadeEffect)) { + useFadeEffect = true; + } + + /** + * @private + * + * @param function + * @return void + */ + render = function(callback) { + getInspector().renderEditors(formElement, callback); + }; + + if (!!useFadeEffect) { + getInspector().getInspectorDomElement().fadeOut('fast', function() { + render(function() { + getInspector().getInspectorDomElement().fadeIn('fast'); + }); + }); + } else { + render(); + } + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) { + getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier); + }; + + /** + * @public + * + * @param string content + * @return void + */ + function setInspectorFormElementHeaderEditorContent(content) { + getInspector().setFormElementHeaderEditorContent(content); + }; + + /* ************************************************************* + * Stage + * ************************************************************/ + + /** + * @public + * + * @return object + */ + function getStage() { + return _stageComponent; + }; + + /** + * @public + * + * @param string title + * @return void + */ + function setStageHeadline(title) { + getStage().setStageHeadline(title); + }; + + /** + * @public + * + * @return void + */ + function addStagePanelSelection() { + getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel')); + }; + + /** + * @public + * + * @return void + */ + function removeStagePanelSelection() { + getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel')); + }; + + /** + * @public + * + * @return void + */ + function renderPagination() { + getStage().renderPagination(); + }; + + /** + * @public + * + * @return void + */ + function renderUndoRedo() { + getStage().renderUndoRedo(); + }; + + /** + * @public + * + * @param bool + * @param bool + * @return void + * @publish view/stage/abstract/render/postProcess + * @publish view/stage/abstract/render/preProcess + */ + function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) { + var render, renderPostProcess; + + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .animate({ + 'left': '0px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .animate({ + 'right': '0px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .animate({ + 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner')) + .animate({ + 'max-width': _configuration['panels']['stage']['maxWidthAbstract'] + 'px' + }, 'slow'); + $(getHelper().getDomElementClassName('headerButtonBar', true)) + .animate({ + 'margin-left': _configuration['panels']['structure']['width'] + 'px' + }, 'slow'); + + if (getUtility().isUndefinedOrNull(useFadeEffect)) { + useFadeEffect = true; + } + + if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { + toolbarUseFadeEffect = true; + } + + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); + + /** + * @private + * + * @param function + * @return void + */ + render = function(callback) { + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .addClass(getHelper().getDomElementClassName('stageViewModeAbstract')) + .removeClass(getHelper().getDomElementClassName('stageViewModePreview')); + + getStage().renderAbstractStageArea(undefined, callback); + }; + + /** + * @private + * + * @return void + */ + renderPostProcess = function() { + var formElementTypeDefinition; + + formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); + getStage().getAllFormElementDomElements().hover(function() { + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + if ( + $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit')) + && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel')) + ) { + $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover')); + } + }); + + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + if ( + formElementTypeDefinition['_isTopLevelFormElement'] + && !formElementTypeDefinition['_isCompositeFormElement'] + && !getFormEditorApp().isRootFormElementSelected() + ) { + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + } else { + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + } + + refreshSelectedElementItemsBatch(toolbarUseFadeEffect); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }; + + if (useFadeEffect) { + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { + render(function() { + getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); + renderPostProcess(); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }); + }); + } else { + render(function() { + getPublisherSubscriber().publish('view/stage/abstract/render/preProcess'); + renderPostProcess(); + getPublisherSubscriber().publish('view/stage/abstract/render/postProcess'); + }); + } + }; + + /** + * @public + * + * @param string html + * @return void + * @publish view/stage/preview/render/postProcess + */ + function renderPreviewStageArea(html) { + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .animate({ + 'left': '-=' + _configuration['panels']['structure']['width'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .animate({ + 'right': '-=' + _configuration['panels']['inspector']['width'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .animate({ + 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px' + }, 'slow'); + $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner')) + .animate({ + 'max-width': _configuration['panels']['stage']['maxWidthPreview'] + 'px' + }, 'slow'); + $(getHelper().getDomElementClassName('headerButtonBar', true)) + .animate({ + 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px' + }, 'slow'); + + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview'))); + removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() { + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .addClass(getHelper().getDomElementClassName('stageViewModePreview')) + .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract')); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + + getStage().renderPreviewStageArea(html); + $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400); + getPublisherSubscriber().publish('view/stage/preview/render/postProcess'); + }); + }; + + /** + * @public + * + * @return void + */ + function addAbstractViewValidationResults() { + var validationResults; + + validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement()); + for (var i = 0, len = validationResults.length; i < len; ++i) { + var hasError = false, validationElement; + for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) { + if ( + validationResults[i]['validationResults'][j]['validationResults'] + && validationResults[i]['validationResults'][j]['validationResults'].length > 0 + ) { + hasError = true; + break; + } + } + + if (hasError) { + if (i > 0) { + validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']); + setElementValidationErrorClass(validationElement); + } + } + } + }; + + /* ************************************************************* + * Form element methods + * ************************************************************/ + + /** + * @public + * + * @param string formElementType + * @param string|object referenceFormElement + * @param bool + * @return object + * @publish view/formElement/inserted + */ + function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) { + var newFormElement; + + newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]); + } + return newFormElement; + }; + + /** + * @public + * + * @param string|object formElementToMove + * @param string position + * @param string|object referenceFormElement + * @param bool + * @return object + * @publish view/formElement/moved + */ + function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) { + var movedFormElement; + + movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]); + } + return movedFormElement; + }; + + /** + * @public + * + * @param object formElement + * @param bool + * @return object + * @publish view/formElement/removed + */ + function removeFormElement(formElement, disablePublishersOnSet) { + var parentFormElement; + + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + + if ( + getFormElementDefinition(formElement, '_isTopLevelFormElement') + && getFormElementDefinition(formElement, '_isCompositeFormElement') + && getRootFormElement().get('renderables').length === 1 + ) { + Notification.error( + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'), + 2 + ); + } else { + parentFormElement = getFormEditorApp().removeFormElement(formElement, false); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]); + } + } + return parentFormElement; + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param object collectionElementConfiguration + * @param string referenceCollectionElementIdentifier + * @param bool + * @return void + * @publish view/collectionElement/new/added + */ + function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) { + getFormEditorApp().createAndAddPropertyCollectionElement( + collectionElementIdentifier, + collectionName, + formElement, + collectionElementConfiguration, + referenceCollectionElementIdentifier + ); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/new/added', [ + collectionElementIdentifier, + collectionName, + formElement, + collectionElementConfiguration, + referenceCollectionElementIdentifier + ]); + } + }; + + /** + * @public + * + * @param string collectionElementToMove + * @param string position + * @param string referenceCollectionElement + * @param string collectionName + * @param object formElement + * @param bool + * @return void + */ + function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { + if (getUtility().isUndefinedOrNull(formElement)) { + formElement = getCurrentlySelectedFormElement(); + } + getFormEditorApp().movePropertyCollectionElement( + collectionElementToMove, + position, + referenceCollectionElement, + collectionName, + formElement, + false + ); + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/moved', [ + collectionElementToMove, + position, + referenceCollectionElement, + collectionName, + formElement] + ); + } + }; + + /** + * @public + * + * @param string collectionElementIdentifier + * @param string collectionName + * @param object formElement + * @param bool + * @return void + * @publish view/collectionElement/removed + */ + function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { + var collectionElementConfiguration; + + getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement); + + collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( + collectionElementIdentifier, + collectionName + ); + if ('array' === $.type(collectionElementConfiguration['editors'])) { + for (var i = 0, len1 = collectionElementConfiguration['editors'].length; i < len1; ++i) { + if ('array' === $.type(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'])) { + for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'].length; j < len2; ++j) { + getCurrentlySelectedFormElement().unset(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'][j], true); } - - if ( - getFormElementDefinition(formElement, '_isTopLevelFormElement') - && getFormElementDefinition(formElement, '_isCompositeFormElement') - && getRootFormElement().get('renderables').length === 1 - ) { - Notification.error( - getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'), - getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'), - 2 - ); - } else { - parentFormElement = getFormEditorApp().removeFormElement(formElement, false); - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]); - } - } - return parentFormElement; - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @param object collectionElementConfiguration - * @param string referenceCollectionElementIdentifier - * @param bool - * @return void - * @publish view/collectionElement/new/added - */ - function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) { - getFormEditorApp().createAndAddPropertyCollectionElement( - collectionElementIdentifier, - collectionName, - formElement, - collectionElementConfiguration, - referenceCollectionElementIdentifier - ); - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/collectionElement/new/added', [ - collectionElementIdentifier, - collectionName, - formElement, - collectionElementConfiguration, - referenceCollectionElementIdentifier - ]); - } - }; - - /** - * @public - * - * @param string collectionElementToMove - * @param string position - * @param string referenceCollectionElement - * @param string collectionName - * @param object formElement - * @param bool - * @return void - */ - function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) { - if (getUtility().isUndefinedOrNull(formElement)) { - formElement = getCurrentlySelectedFormElement(); - } - getFormEditorApp().movePropertyCollectionElement( - collectionElementToMove, - position, - referenceCollectionElement, - collectionName, - formElement, - false - ); - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/collectionElement/moved', [ - collectionElementToMove, - position, - referenceCollectionElement, - collectionName, - formElement] - ); - } - }; - - /** - * @public - * - * @param string collectionElementIdentifier - * @param string collectionName - * @param object formElement - * @param bool - * @return void - * @publish view/collectionElement/removed - */ - function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) { - var collectionElementConfiguration; - - getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement); - - collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration( - collectionElementIdentifier, - collectionName - ); - if ('array' === $.type(collectionElementConfiguration['editors'])) { - for (var i = 0, len1 = collectionElementConfiguration['editors'].length; i < len1; ++i) { - if ('array' === $.type(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'])) { - for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'].length; j < len2; ++j) { - getCurrentlySelectedFormElement().unset(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'][j], true); - } - } - } - } - - if (!!!disablePublishersOnSet) { - getPublisherSubscriber().publish('view/collectionElement/removed', [ - collectionElementIdentifier, - collectionName, - formElement] - ); - } - }; - - /* ************************************************************* - * Batch methodes - * ************************************************************/ - - /** - * @public - * - * @param bool - * @return void - */ - function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) { - var formElementTypeDefinition, selectedElement; - - if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { - toolbarUseFadeEffect = true; - } - - formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); - - getStage().removeAllStageToolbars(); - removeAllStageElementSelectionsBatch(); - removeAllStructureSelections(); - - if (!getFormEditorApp().isRootFormElementSelected()) { - removeStructureRootElementSelection(); - addStructureSelection(); - - selectedElement = getStage().getAbstractViewFormElementDomElement(); - - if (formElementTypeDefinition['_isTopLevelFormElement']) { - addStagePanelSelection(); - } else { - selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement')); - getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect); - } - - getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement')); - if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { - selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement')); - } - } - }; - - /** - * @public - * - * @param int - * @return void - * @throws 1478651732 - * @throws 1478651733 - * @throws 1478651734 - */ - function selectPageBatch(pageIndex) { - assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732); - assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733); - assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734); - - getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]); - renewStructure(); - renderPagination() - refreshSelectedElementItemsBatch(); - renderInspectorEditors(); - }; - - /** - * @public - * - * @return void - */ - function removeAllStageElementSelectionsBatch() { - getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement')); - removeStagePanelSelection(); - getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); - }; - - /** - * @public - * - * @return void - */ - function onViewReadyBatch() { - $(getHelper().getDomElementDataIdentifierSelector('structureSection')) - .css({ - width: _configuration['panels']['structure']['width'] + 'px', - left: '-=' + _configuration['panels']['structure']['width'] + 'px' - }); - $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) - .css({ - width: _configuration['panels']['inspector']['width'] + 'px', - right: '-=' + _configuration['panels']['inspector']['width'] + 'px' - }); - - $(getHelper().getDomElementClassName('headerButtonBar', true)) - .css({ - 'margin-left': _configuration['panels']['structure']['width'] + 'px' - }); - - $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) - .css({ - 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', - 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' - }); - - hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); - hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); - - setStageHeadline(); - setStructureRootElementTitle(); - renderAbstractStageArea(false); - renewStructure(); - addStructureRootElementSelection(); - renderInspectorEditors(); - renderPagination(); - - hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); - showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); - setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); - }; - - /** - * @public - * - * @param object - * @param object - * @return void - */ - function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) { - draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover')); - }; - - /** - * @public - * - * @param object - * @param string - * @param object - * @return void - */ - function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { - getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); - if (enclosingCompositeFormElement) { - getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover')); - } - }; - - /** - * @public - * - * @param object - * @param string - * @param string - * @param string - * @return void - * @throws 1472502237 - */ - function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { - var movedFormElement, parentFormElementIdentifierPath; - if (nextFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); - } else if (previousFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); - } else { - parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement); - if (parentFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); - } else { - assert(false, 'Next element, previous or parent element need to be set.', 1472502237); - } - } - - getStage() - .getAbstractViewFormElementWithinDomElement(movedDomElement) - .attr( - getHelper().getDomElementDataAttribute('elementIdentifier'), - movedFormElement.get('__identifierPath') - ); - }; - - /** - * @public - * - * @param object - * @param string - * @param object - * @return void - */ - function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { - getStructure() - .getAllTreeNodes() - .parent() - .removeClass(getHelper().getDomElementClassName('sortableHover')); - - getStage() - .getAllFormElementDomElements() - .parent() - .removeClass(getHelper().getDomElementClassName('sortableHover')); - - if (enclosingCompositeFormElement) { - getStructure() - .getParentTreeNodeWithinDomElement(placeholderDomElement) - .parent() - .addClass(getHelper().getDomElementClassName('sortableHover')); - - getStage() - .getAbstractViewFormElementDomElement(enclosingCompositeFormElement) - .parent() - .addClass(getHelper().getDomElementClassName('sortableHover')); - } - }; - - /** - * @public - * - * @param object - * @param string - * @param string - * @param string - * @return void - * @throws 1479048646 - */ - function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { - var movedFormElement, parentFormElementIdentifierPath; - if (nextFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); - } else if (previousFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); - } else { - parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement); - if (parentFormElementIdentifierPath) { - movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); - } else { - getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646); - } - } - - getStructure() - .getTreeNodeWithinDomElement(movedDomElement) - .attr( - getHelper().getDomElementDataAttribute('elementIdentifier'), - movedFormElement.get('__identifierPath') - ); - }; - - /* ************************************************************* - * Misc - * ************************************************************/ - - /** - * @public - * - * @return void - */ - function closeEditor() { - document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href'); - }; - - /** - * @public - * - * @param object - * @param string - * @return void - */ - function setElementValidationErrorClass(element, classIdentifier) { - if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { - element.addClass(getHelper().getDomElementClassName('validationErrors')); - } else { - element.addClass(getHelper().getDomElementClassName(classIdentifier)); - } - }; - - /** - * @public - * - * @param object - * @param string - * @return void - */ - function removeElementValidationErrorClass(element, classIdentifier) { - if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { - element.removeClass(getHelper().getDomElementClassName('validationErrors')); - } else { - element.removeClass(getHelper().getDomElementClassName(classIdentifier)); - } - }; - - /** - * @public - * - * @param object - * @return void - */ - function showComponent(element) { - element.removeClass(getHelper().getDomElementClassName('hidden')).show(); - }; - - /** - * @public - * - * @param object - * @return void - */ - function hideComponent(element) { - element.addClass(getHelper().getDomElementClassName('hidden')).hide(); - }; - - /** - * @public - * - * @param object - * @return void - */ - function enableButton(buttonElement) { - buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled')); - }; - - /** - * @public - * - * @param object - * @return void - */ - function disableButton(buttonElement) { - buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled')); - }; - - /** - * @public - * - * @param object - * @return void - */ - function setButtonActive(buttonElement) { - buttonElement.addClass(getHelper().getDomElementClassName('active')); - }; - - /** - * @public - * - * @param object - * @return void - */ - function removeButtonActive(buttonElement) { - buttonElement.removeClass(getHelper().getDomElementClassName('active')); - }; - - /** - * @public - * - * @return void - */ - function showSaveButtonSpinnerIcon() { - Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) { - $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup)); - }); - }; - - /** - * @public - * - * @return void - */ - function showSaveButtonSaveIcon() { - Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) { - $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup)); - }); - }; - - /** - * @public - * - * @return void - */ - function showSaveSuccessMessage() { - Notification.success( - getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'), - getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'), - 2 - ); - }; - - /** - * @public - * - * @return void - */ - function showSaveErrorMessage(response) { - Notification.error( - getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'), - getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') + - " " + - response.message - ); - }; - - /** - * @public - * - * @param string - * @param string - * @return void - */ - function showErrorFlashMessage(title, message) { - Notification.error(title, message, 2); - }; - - /** - * @public - * - * @param object formEditorApp - * @param object additionalViewModelModules - * @return void - */ - function bootstrap(formEditorApp, additionalViewModelModules) { - _formEditorApp = formEditorApp; - - _helperSetup(); - _structureComponentSetup(); - _modalsComponentSetup(); - _inspectorsComponentSetup(); - _stageComponentSetup(); - _buttonsSetup(); - _addPropertyValidators(); - _loadAdditionalModules(additionalViewModelModules); - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - addAbstractViewValidationResults: addAbstractViewValidationResults, - addStagePanelSelection: addStagePanelSelection, - addStructureRootElementSelection: addStructureRootElementSelection, - addStructureSelection: addStructureSelection, - addStructureValidationResults: addStructureValidationResults, - bootstrap: bootstrap, - closeEditor: closeEditor, - createAndAddFormElement: createAndAddFormElement, - createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, - disableButton: disableButton, - enableButton: enableButton, - getConfiguration: getConfiguration, - getFormEditorApp: getFormEditorApp, - getFormElementDefinition: getFormElementDefinition, - getHelper: getHelper, - getInspector: getInspector, - getModals: getModals, - getPreviewMode: getPreviewMode, - getStage: getStage, - getStructure: getStructure, - getStructureRootElement: getStructureRootElement, - hideComponent: hideComponent, - moveFormElement: moveFormElement, - movePropertyCollectionElement: movePropertyCollectionElement, - onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch, - onAbstractViewDndStartBatch: onAbstractViewDndStartBatch, - onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch, - onStructureDndChangeBatch: onStructureDndChangeBatch, - onStructureDndUpdateBatch: onStructureDndUpdateBatch, - onViewReadyBatch: onViewReadyBatch, - refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch, - removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch, - removeAllStructureSelections: removeAllStructureSelections, - removeButtonActive: removeButtonActive, - removeElementValidationErrorClass: removeElementValidationErrorClass, - removeFormElement: removeFormElement, - removePropertyCollectionElement: removePropertyCollectionElement, - removeStagePanelSelection: removeStagePanelSelection, - removeStructureRootElementSelection: removeStructureRootElementSelection, - removeStructureSelection: removeStructureSelection, - renderAbstractStageArea: renderAbstractStageArea, - renderInspectorEditors: renderInspectorEditors, - renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors, - renderPagination: renderPagination, - renderPreviewStageArea: renderPreviewStageArea, - renewStructure: renewStructure, - renderUndoRedo: renderUndoRedo, - selectPageBatch: selectPageBatch, - setButtonActive: setButtonActive, - setElementValidationErrorClass: setElementValidationErrorClass, - setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent, - setPreviewMode: setPreviewMode, - setStageHeadline: setStageHeadline, - setStructureRootElementTitle: setStructureRootElementTitle, - showCloseConfirmationModal: showCloseConfirmationModal, - showComponent: showComponent, - showErrorFlashMessage: showErrorFlashMessage, - showInsertElementsModal: showInsertElementsModal, - showInsertPagesModal: showInsertPagesModal, - showRemoveFormElementModal: showRemoveFormElementModal, - showRemoveCollectionElementModal: showRemoveCollectionElementModal, - showSaveButtonSaveIcon: showSaveButtonSaveIcon, - showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon, - showSaveSuccessMessage: showSaveSuccessMessage, - showSaveErrorMessage: showSaveErrorMessage, - showValidationErrorsModal: showValidationErrorsModal - }; - })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification); + } + } + } + + if (!!!disablePublishersOnSet) { + getPublisherSubscriber().publish('view/collectionElement/removed', [ + collectionElementIdentifier, + collectionName, + formElement] + ); + } + }; + + /* ************************************************************* + * Batch methodes + * ************************************************************/ + + /** + * @public + * + * @param bool + * @return void + */ + function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) { + var formElementTypeDefinition, selectedElement; + + if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) { + toolbarUseFadeEffect = true; + } + + formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement()); + + getStage().removeAllStageToolbars(); + removeAllStageElementSelectionsBatch(); + removeAllStructureSelections(); + + if (!getFormEditorApp().isRootFormElementSelected()) { + removeStructureRootElementSelection(); + addStructureSelection(); + + selectedElement = getStage().getAbstractViewFormElementDomElement(); + + if (formElementTypeDefinition['_isTopLevelFormElement']) { + addStagePanelSelection(); + } else { + selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement')); + getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect); + } + + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement')); + if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) { + selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement')); + } + } + }; + + /** + * @public + * + * @param int + * @return void + * @throws 1478651732 + * @throws 1478651733 + * @throws 1478651734 + */ + function selectPageBatch(pageIndex) { + assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732); + assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733); + assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734); + + getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]); + renewStructure(); + renderPagination() + refreshSelectedElementItemsBatch(); + renderInspectorEditors(); + }; + + /** + * @public + * + * @return void + */ + function removeAllStageElementSelectionsBatch() { + getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement')); + removeStagePanelSelection(); + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + }; + + /** + * @public + * + * @return void + */ + function onViewReadyBatch() { + $(getHelper().getDomElementDataIdentifierSelector('structureSection')) + .css({ + width: _configuration['panels']['structure']['width'] + 'px', + left: '-=' + _configuration['panels']['structure']['width'] + 'px' + }); + $(getHelper().getDomElementDataIdentifierSelector('inspectorSection')) + .css({ + width: _configuration['panels']['inspector']['width'] + 'px', + right: '-=' + _configuration['panels']['inspector']['width'] + 'px' + }); + + $(getHelper().getDomElementClassName('headerButtonBar', true)) + .css({ + 'margin-left': _configuration['panels']['structure']['width'] + 'px' + }); + + $(getHelper().getDomElementDataIdentifierSelector('stageContainer')) + .css({ + 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px', + 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px' + }); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom'))); + hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow'))); + + setStageHeadline(); + setStructureRootElementTitle(); + renderAbstractStageArea(false); + renewStructure(); + addStructureRootElementSelection(); + renderInspectorEditors(); + renderPagination(); + + hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo'))); + showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo'))); + setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract'))); + }; + + /** + * @public + * + * @param object + * @param object + * @return void + */ + function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) { + draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover')); + }; + + /** + * @public + * + * @param object + * @param string + * @param object + * @return void + */ + function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { + getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover')); + if (enclosingCompositeFormElement) { + getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover')); + } + }; + + /** + * @public + * + * @param object + * @param string + * @param string + * @param string + * @return void + * @throws 1472502237 + */ + function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { + var movedFormElement, parentFormElementIdentifierPath; + if (nextFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); + } else if (previousFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); + } else { + parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement); + if (parentFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); + } else { + assert(false, 'Next element, previous or parent element need to be set.', 1472502237); + } + } + + getStage() + .getAbstractViewFormElementWithinDomElement(movedDomElement) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + movedFormElement.get('__identifierPath') + ); + }; + + /** + * @public + * + * @param object + * @param string + * @param object + * @return void + */ + function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) { + getStructure() + .getAllTreeNodes() + .parent() + .removeClass(getHelper().getDomElementClassName('sortableHover')); + + getStage() + .getAllFormElementDomElements() + .parent() + .removeClass(getHelper().getDomElementClassName('sortableHover')); + + if (enclosingCompositeFormElement) { + getStructure() + .getParentTreeNodeWithinDomElement(placeholderDomElement) + .parent() + .addClass(getHelper().getDomElementClassName('sortableHover')); + + getStage() + .getAbstractViewFormElementDomElement(enclosingCompositeFormElement) + .parent() + .addClass(getHelper().getDomElementClassName('sortableHover')); + } + }; + + /** + * @public + * + * @param object + * @param string + * @param string + * @param string + * @return void + * @throws 1479048646 + */ + function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) { + var movedFormElement, parentFormElementIdentifierPath; + if (nextFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath); + } else if (previousFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath); + } else { + parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement); + if (parentFormElementIdentifierPath) { + movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath); + } else { + getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646); + } + } + + getStructure() + .getTreeNodeWithinDomElement(movedDomElement) + .attr( + getHelper().getDomElementDataAttribute('elementIdentifier'), + movedFormElement.get('__identifierPath') + ); + }; + + /* ************************************************************* + * Misc + * ************************************************************/ + + /** + * @public + * + * @return void + */ + function closeEditor() { + document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href'); + }; + + /** + * @public + * + * @param object + * @param string + * @return void + */ + function setElementValidationErrorClass(element, classIdentifier) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { + element.addClass(getHelper().getDomElementClassName('validationErrors')); + } else { + element.addClass(getHelper().getDomElementClassName(classIdentifier)); + } + }; + + /** + * @public + * + * @param object + * @param string + * @return void + */ + function removeElementValidationErrorClass(element, classIdentifier) { + if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) { + element.removeClass(getHelper().getDomElementClassName('validationErrors')); + } else { + element.removeClass(getHelper().getDomElementClassName(classIdentifier)); + } + }; + + /** + * @public + * + * @param object + * @return void + */ + function showComponent(element) { + element.removeClass(getHelper().getDomElementClassName('hidden')).show(); + }; + + /** + * @public + * + * @param object + * @return void + */ + function hideComponent(element) { + element.addClass(getHelper().getDomElementClassName('hidden')).hide(); + }; + + /** + * @public + * + * @param object + * @return void + */ + function enableButton(buttonElement) { + buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function disableButton(buttonElement) { + buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function setButtonActive(buttonElement) { + buttonElement.addClass(getHelper().getDomElementClassName('active')); + }; + + /** + * @public + * + * @param object + * @return void + */ + function removeButtonActive(buttonElement) { + buttonElement.removeClass(getHelper().getDomElementClassName('active')); + }; + + /** + * @public + * + * @return void + */ + function showSaveButtonSpinnerIcon() { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) { + $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup)); + }); + }; + + /** + * @public + * + * @return void + */ + function showSaveButtonSaveIcon() { + Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) { + $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup)); + }); + }; + + /** + * @public + * + * @return void + */ + function showSaveSuccessMessage() { + Notification.success( + getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'), + 2 + ); + }; + + /** + * @public + * + * @return void + */ + function showSaveErrorMessage(response) { + Notification.error( + getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'), + getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') + + " " + + response.message + ); + }; + + /** + * @public + * + * @param string + * @param string + * @return void + */ + function showErrorFlashMessage(title, message) { + Notification.error(title, message, 2); + }; + + /** + * @public + * + * @param object formEditorApp + * @param object additionalViewModelModules + * @return void + */ + function bootstrap(formEditorApp, additionalViewModelModules) { + _formEditorApp = formEditorApp; + + _helperSetup(); + _structureComponentSetup(); + _modalsComponentSetup(); + _inspectorsComponentSetup(); + _stageComponentSetup(); + _buttonsSetup(); + _addPropertyValidators(); + _loadAdditionalModules(additionalViewModelModules); + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + addAbstractViewValidationResults: addAbstractViewValidationResults, + addStagePanelSelection: addStagePanelSelection, + addStructureRootElementSelection: addStructureRootElementSelection, + addStructureSelection: addStructureSelection, + addStructureValidationResults: addStructureValidationResults, + bootstrap: bootstrap, + closeEditor: closeEditor, + createAndAddFormElement: createAndAddFormElement, + createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement, + disableButton: disableButton, + enableButton: enableButton, + getConfiguration: getConfiguration, + getFormEditorApp: getFormEditorApp, + getFormElementDefinition: getFormElementDefinition, + getHelper: getHelper, + getInspector: getInspector, + getModals: getModals, + getPreviewMode: getPreviewMode, + getStage: getStage, + getStructure: getStructure, + getStructureRootElement: getStructureRootElement, + hideComponent: hideComponent, + moveFormElement: moveFormElement, + movePropertyCollectionElement: movePropertyCollectionElement, + onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch, + onAbstractViewDndStartBatch: onAbstractViewDndStartBatch, + onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch, + onStructureDndChangeBatch: onStructureDndChangeBatch, + onStructureDndUpdateBatch: onStructureDndUpdateBatch, + onViewReadyBatch: onViewReadyBatch, + refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch, + removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch, + removeAllStructureSelections: removeAllStructureSelections, + removeButtonActive: removeButtonActive, + removeElementValidationErrorClass: removeElementValidationErrorClass, + removeFormElement: removeFormElement, + removePropertyCollectionElement: removePropertyCollectionElement, + removeStagePanelSelection: removeStagePanelSelection, + removeStructureRootElementSelection: removeStructureRootElementSelection, + removeStructureSelection: removeStructureSelection, + renderAbstractStageArea: renderAbstractStageArea, + renderInspectorEditors: renderInspectorEditors, + renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors, + renderPagination: renderPagination, + renderPreviewStageArea: renderPreviewStageArea, + renewStructure: renewStructure, + renderUndoRedo: renderUndoRedo, + selectPageBatch: selectPageBatch, + setButtonActive: setButtonActive, + setElementValidationErrorClass: setElementValidationErrorClass, + setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent, + setPreviewMode: setPreviewMode, + setStageHeadline: setStageHeadline, + setStructureRootElementTitle: setStructureRootElementTitle, + showCloseConfirmationModal: showCloseConfirmationModal, + showComponent: showComponent, + showErrorFlashMessage: showErrorFlashMessage, + showInsertElementsModal: showInsertElementsModal, + showInsertPagesModal: showInsertPagesModal, + showRemoveFormElementModal: showRemoveFormElementModal, + showRemoveCollectionElementModal: showRemoveCollectionElementModal, + showSaveButtonSaveIcon: showSaveButtonSaveIcon, + showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon, + showSaveSuccessMessage: showSaveSuccessMessage, + showSaveErrorMessage: showSaveErrorMessage, + showValidationErrorsModal: showValidationErrorsModal + }; + })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js index 26a70aa1941dd521be5e894be5344c2a42f82649..eb0a8c3f2e59bd13d30577d36a8ec49261b00415 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js @@ -15,226 +15,226 @@ * Module: TYPO3/CMS/Form/Backend/FormManager */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; + + /** + * Return a static method named "getInstance". + * Use this method to create the formmanager app. + */ + return (function() { + + /** + * @private + * + * Hold the instance (Singleton Pattern) + */ + var _formManagerInstance = null; /** - * Return a static method named "getInstance". - * Use this method to create the formmanager app. + * @public + * + * @param object _configuration + * @param object _viewModel + * @return object */ - return (function() { - - /** - * @private - * - * Hold the instance (Singleton Pattern) - */ - var _formManagerInstance = null; - - /** - * @public - * - * @param object _configuration - * @param object _viewModel - * @return object - */ - function FormManager(_configuration, _viewModel) { - - /** - * @private - * - * @var bool - */ - var _isRunning = false; - - /** - * @public - * - * @param mixed test - * @param string message - * @param int messageCode - * @return void - */ - function assert(test, message, messageCode) { - if ('function' === $.type(test)) { - test = (test() !== false); - } - if (!test) { - message = message || "Assertion failed"; - if (messageCode) { - message = message + ' (' + messageCode + ')'; - } - if ('undefined' !== typeof Error) { - throw new Error(message); - } - throw message; - } - }; - - /** - * @private - * - * @var bool - */ - var _isRunning = false; - - /** - * @public - * - * @return object - */ - function getPrototypes() { - var prototypes = []; - - if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { - for (var i = 0, len = _configuration['selectablePrototypesConfiguration'].length; i < len; ++i) { - prototypes.push({ - label: _configuration['selectablePrototypesConfiguration'][i]['label'], - value: _configuration['selectablePrototypesConfiguration'][i]['identifier'], - }); - } - } - return prototypes; - }; - - /** - * @public - * - * @param string prototypeName - * @return object - */ - function getTemplatesForPrototype(prototypeName) { - var templates = []; - assert('string' === $.type(prototypeName), 'Invalid parameter "prototypeName"', 1475945286); - if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { - for (var i = 0, len1 = _configuration['selectablePrototypesConfiguration'].length; i < len1; ++i) { - if (_configuration['selectablePrototypesConfiguration'][i]['identifier'] !== prototypeName) { - continue; - } - if ('array' === $.type(_configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'])) { - for (var j = 0, len2 = _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'].length; j < len2; ++j) { - templates.push({ - label: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['label'], - value: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['templatePath'], - }); - } - } - } - } - - return templates; - }; - - /** - * @public - * - * @param string prototypeName - * @return object - */ - function getAccessibleFormStorageFolders() { - var folders = []; - - if ('array' === $.type(_configuration['accessibleFormStorageFolders'])) { - for (var i = 0, len1 = _configuration['accessibleFormStorageFolders'].length; i < len1; ++i) { - folders.push({ - label: _configuration['accessibleFormStorageFolders'][i]['label'], - value: _configuration['accessibleFormStorageFolders'][i]['value'], - }); - } - } - return folders; - }; - - /** - * @public - * - * @param string prototypeName - * @return object - * @throws 1477506508 - */ - function getAjaxEndpoint(endpointName) { - var templates = []; - assert(typeof _configuration['endpoints'][endpointName] !== 'undefined', 'Endpoint ' + endpointName + ' does not exist', 1477506508); - - return _configuration['endpoints'][endpointName]; - }; - - /** - * @private - * - * @return void - * @throws 1475942906 - */ - function _viewSetup() { - assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475942906); - _viewModel.bootstrap(_formManagerInstance); - }; - - /** - * @private - * - * @return void - * @throws 1477506504 - */ - function _bootstrap() { - _configuration = _configuration || {}; - assert('object' === $.type(_configuration['endpoints']), 'Invalid parameter "endpoints"', 1477506504); - _viewSetup(); - }; - - /** - * @public - * - * @return TYPO3/CMS/Form/Backend/FormManager - * @throws 1475942618 - */ - function run() { - if (_isRunning) { - throw 'You can not run the app twice (1475942618)'; - } - - _bootstrap(); - _isRunning = true; - return this; - }; - - /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". - */ - return { - getPrototypes: getPrototypes, - getTemplatesForPrototype: getTemplatesForPrototype, - getAccessibleFormStorageFolders: getAccessibleFormStorageFolders, - getAjaxEndpoint: getAjaxEndpoint, - - assert: assert, - run: run - }; - }; - - /** - * Emulation of static methods - */ - return { - /** - * @public - * @static - * - * Implement the "Singleton Pattern". - * - * Return a singleton instance of a - * "FormManager" object. - * - * @param object configuration - * @param object viewModel - * @return object - */ - getInstance: function(configuration, viewModel) { - if(_formManagerInstance === null) { - _formManagerInstance = new FormManager(configuration, viewModel); - } - return _formManagerInstance; + function FormManager(_configuration, _viewModel) { + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @public + * + * @param mixed test + * @param string message + * @param int messageCode + * @return void + */ + function assert(test, message, messageCode) { + if ('function' === $.type(test)) { + test = (test() !== false); + } + if (!test) { + message = message || "Assertion failed"; + if (messageCode) { + message = message + ' (' + messageCode + ')'; + } + if ('undefined' !== typeof Error) { + throw new Error(message); + } + throw message; + } + }; + + /** + * @private + * + * @var bool + */ + var _isRunning = false; + + /** + * @public + * + * @return object + */ + function getPrototypes() { + var prototypes = []; + + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { + for (var i = 0, len = _configuration['selectablePrototypesConfiguration'].length; i < len; ++i) { + prototypes.push({ + label: _configuration['selectablePrototypesConfiguration'][i]['label'], + value: _configuration['selectablePrototypesConfiguration'][i]['identifier'] + }); + } + } + return prototypes; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + */ + function getTemplatesForPrototype(prototypeName) { + var templates = []; + assert('string' === $.type(prototypeName), 'Invalid parameter "prototypeName"', 1475945286); + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) { + for (var i = 0, len1 = _configuration['selectablePrototypesConfiguration'].length; i < len1; ++i) { + if (_configuration['selectablePrototypesConfiguration'][i]['identifier'] !== prototypeName) { + continue; } - }; - })(); + if ('array' === $.type(_configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'])) { + for (var j = 0, len2 = _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'].length; j < len2; ++j) { + templates.push({ + label: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['label'], + value: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['templatePath'] + }); + } + } + } + } + + return templates; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + */ + function getAccessibleFormStorageFolders() { + var folders = []; + + if ('array' === $.type(_configuration['accessibleFormStorageFolders'])) { + for (var i = 0, len1 = _configuration['accessibleFormStorageFolders'].length; i < len1; ++i) { + folders.push({ + label: _configuration['accessibleFormStorageFolders'][i]['label'], + value: _configuration['accessibleFormStorageFolders'][i]['value'] + }); + } + } + return folders; + }; + + /** + * @public + * + * @param string prototypeName + * @return object + * @throws 1477506508 + */ + function getAjaxEndpoint(endpointName) { + var templates = []; + assert(typeof _configuration['endpoints'][endpointName] !== 'undefined', 'Endpoint ' + endpointName + ' does not exist', 1477506508); + + return _configuration['endpoints'][endpointName]; + }; + + /** + * @private + * + * @return void + * @throws 1475942906 + */ + function _viewSetup() { + assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475942906); + _viewModel.bootstrap(_formManagerInstance); + }; + + /** + * @private + * + * @return void + * @throws 1477506504 + */ + function _bootstrap() { + _configuration = _configuration || {}; + assert('object' === $.type(_configuration['endpoints']), 'Invalid parameter "endpoints"', 1477506504); + _viewSetup(); + }; + + /** + * @public + * + * @return TYPO3/CMS/Form/Backend/FormManager + * @throws 1475942618 + */ + function run() { + if (_isRunning) { + throw 'You can not run the app twice (1475942618)'; + } + + _bootstrap(); + _isRunning = true; + return this; + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + getPrototypes: getPrototypes, + getTemplatesForPrototype: getTemplatesForPrototype, + getAccessibleFormStorageFolders: getAccessibleFormStorageFolders, + getAjaxEndpoint: getAjaxEndpoint, + + assert: assert, + run: run + }; + }; + + /** + * Emulation of static methods + */ + return { + /** + * @public + * @static + * + * Implement the "Singleton Pattern". + * + * Return a singleton instance of a + * "FormManager" object. + * + * @param object configuration + * @param object viewModel + * @return object + */ + getInstance: function(configuration, viewModel) { + if (_formManagerInstance === null) { + _formManagerInstance = new FormManager(configuration, viewModel); + } + return _formManagerInstance; + } + }; + })(); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js index b7f5225870fec10de7101938bdc30393ff4fd62b..19edf1e163447ae64fd054b807e9be4095ef1a1c 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js @@ -15,559 +15,561 @@ * Module: TYPO3/CMS/Form/Backend/FormManager/ViewModel */ define(['jquery', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Wizard', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification' - ], function($, Modal, Severity, Wizard, Icons, Notification) { - 'use strict'; - - return (function($, Modal, Severity, Wizard, Icons,Notification) { - - /** - * @private - * - * @var object - */ - var _formManagerApp = null; + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Wizard', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification' +], function($, Modal, Severity, Wizard, Icons, Notification) { + 'use strict'; + + return (function($, Modal, Severity, Wizard, Icons, Notification) { + + /** + * @private + * + * @var object + */ + var _formManagerApp = null; + + /** + * @private + * + * @var object + */ + var _domElementIdentifierCache = {}; + + /** + * @private + * + * @return void + */ + function _domElementIdentifierCacheSetup() { + _domElementIdentifierCache = { + newFormModalTrigger: {identifier: '[data-identifier="newForm"]'}, + duplicateFormModalTrigger: {identifier: '[data-identifier="duplicateForm"]'}, + removeFormModalTrigger: {identifier: '[data-identifier="removeForm"]'}, + + newFormName: {identifier: '[data-identifier="newFormName"]'}, + newFormSavePath: {identifier: '[data-identifier="newFormSavePath"]'}, + advancedWizard: {identifier: '[data-identifier="advancedWizard"]'}, + newFormPrototypeName: {identifier: '[data-identifier="newFormPrototypeName"]'}, + newFormTemplate: {identifier: '[data-identifier="newFormTemplate"]'}, + + duplicateFormName: {identifier: '[data-identifier="duplicateFormName"]'}, + duplicateFormSavePath: {identifier: '[data-identifier="duplicateFormSavePath"]'}, + + showReferences: {identifier: '[data-identifier="showReferences"]'}, + referenceLink: {identifier: '[data-identifier="referenceLink"]'}, + + tooltip: {identifier: '[data-toggle="tooltip"]'}, + + moduleBody: {class: '.module-body.t3js-module-body'}, + t3Logo: {class: '.t3-message-page-logo'}, + t3Footer: {id: '#t3-footer'} + } + }; + + /** + * @private + * + * @return void + * @throws 1477506500 + * @throws 1477506501 + * @throws 1477506502 + */ + function _newFormSetup() { + $(getDomElementIdentifier('newFormModalTrigger')).on('click', function(e) { + e.preventDefault(); /** - * @private - * - * @var object + * Wizard step 1 */ - var _domElementIdentifierCache = {}; - - /** - * @private - * - * @return void - */ - function _domElementIdentifierCacheSetup() { - _domElementIdentifierCache = { - newFormModalTrigger: { identifier: '[data-identifier="newForm"]' }, - duplicateFormModalTrigger: { identifier: '[data-identifier="duplicateForm"]' }, - removeFormModalTrigger: { identifier: '[data-identifier="removeForm"]' }, - - newFormName: { identifier: '[data-identifier="newFormName"]' }, - newFormSavePath: { identifier: '[data-identifier="newFormSavePath"]' }, - advancedWizard: { identifier: '[data-identifier="advancedWizard"]' }, - newFormPrototypeName: { identifier: '[data-identifier="newFormPrototypeName"]' }, - newFormTemplate: { identifier: '[data-identifier="newFormTemplate"]' }, - - duplicateFormName: { identifier: '[data-identifier="duplicateFormName"]' }, - duplicateFormSavePath: { identifier: '[data-identifier="duplicateFormSavePath"]' }, - - showReferences: { identifier: '[data-identifier="showReferences"]' }, - referenceLink: { identifier: '[data-identifier="referenceLink"]' }, + Wizard.addSlide('new-form-step-1', TYPO3.lang['formManager.newFormWizard.step1.title'], '', Severity.info, function(slide) { + var advandecWizardHasOptions, folders, html, modal, nextButton, prototypes, + savePathSelect, templates; + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + folders = _formManagerApp.getAccessibleFormStorageFolders(); + if (folders.length === 0) { + html = '<div class="new-form-modal">' + + '<div class="form-horizontal">' + + '<div>' + + '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.noStorages'] + '</label>' + + '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + _formManagerApp.assert(false, 'No accessible form storage folders', 1477506500); + } + + Wizard.set('savePath', folders[0]['value']); + if (folders.length > 1) { + savePathSelect = $('<select class="new-form-save-path form-control" data-identifier="newFormSavePath" />'); + for (var i = 0, len = folders.length; i < len; ++i) { + var option = new Option(folders[i]['label'], folders[i]['value']); + $(savePathSelect).append(option); + } + } + + prototypes = _formManagerApp.getPrototypes(); + + _formManagerApp.assert(prototypes.length > 0, 'No prototypes available', 1477506501); + Wizard.set('prototypeName', prototypes[0]['value']); + + templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); + _formManagerApp.assert(templates.length > 0, 'No templates available', 1477506502); + Wizard.set('templatePath', templates[0]['value']); + + html = '<div class="new-form-modal">' + + '<div class="form-horizontal">' + + '<div>' + + '<label class="control-label">' + TYPO3.lang['formManager.form_name'] + '</label>' + + '<input class="new-form-name form-control has-error" data-identifier="newFormName" />'; + + if (savePathSelect) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; + } + + if (prototypes.length > 1 || templates.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.advanced'] + '</label>' + + '<div class="t3-form-controls"><input type="checkbox" class="new-form-advance-wizard" data-identifier="advancedWizard" /></div>'; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + $(getDomElementIdentifier('newFormName'), modal).focus(); + + $(getDomElementIdentifier('newFormName'), modal).on('keyup paste', function(e) { + if ($(this).val().length > 0) { + $(this).removeClass('has-error'); + Wizard.unlockNextStep(); + Wizard.set('formName', $(this).val()); + } else { + $(this).addClass('has-error'); + Wizard.lockNextStep(); + } + }); - tooltip: { identifier: '[data-toggle="tooltip"]' }, + $(getDomElementIdentifier('newFormSavePath'), modal).on('change', function(e) { + Wizard.set('savePath', $(getDomElementIdentifier('newFormSavePath') + ' option:selected', modal).val()); + }); - moduleBody: { class: '.module-body.t3js-module-body' }, - t3Logo: { class: '.t3-message-page-logo' }, - t3Footer: { id: '#t3-footer' } + $(getDomElementIdentifier('advancedWizard'), modal).on('change', function(e) { + if ($(this).is(':checked')) { + Wizard.set('advancedWizard', true); + } else { + Wizard.set('advancedWizard', false); } - }; + }); - /** - * @private - * - * @return void - * @throws 1477506500 - * @throws 1477506501 - * @throws 1477506502 - */ - function _newFormSetup() { - $(getDomElementIdentifier('newFormModalTrigger')).on('click', function(e) { - e.preventDefault(); - - /** - * Wizard step 1 - */ - Wizard.addSlide('new-form-step-1', TYPO3.lang['formManager.newFormWizard.step1.title'], '', Severity.info, function(slide) { - var advandecWizardHasOptions, folders, html, modal, nextButton, prototypes, savePathSelect, templates; - - modal = Wizard.setup.$carousel.closest('.modal'); - nextButton = modal.find('.modal-footer').find('button[name="next"]'); - - folders = _formManagerApp.getAccessibleFormStorageFolders(); - if (folders.length === 0) { - html = '<div class="new-form-modal">' - + '<div class="form-horizontal">' - + '<div>' - + '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.noStorages'] + '</label>' - + '</div>' - + '</div>' - + '</div>'; - - slide.html(html); - _formManagerApp.assert(false, 'No accessible form storage folders', 1477506500); - } - - Wizard.set('savePath', folders[0]['value']); - if (folders.length > 1) { - savePathSelect = $('<select class="new-form-save-path form-control" data-identifier="newFormSavePath" />'); - for (var i = 0, len = folders.length; i < len; ++i) { - var option = new Option(folders[i]['label'], folders[i]['value']); - $(savePathSelect).append(option); - } - } - - prototypes = _formManagerApp.getPrototypes(); - - _formManagerApp.assert(prototypes.length > 0, 'No prototypes available', 1477506501); - Wizard.set('prototypeName', prototypes[0]['value']); - - templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); - _formManagerApp.assert(templates.length > 0, 'No templates available', 1477506502); - Wizard.set('templatePath', templates[0]['value']); - - html = '<div class="new-form-modal">' - + '<div class="form-horizontal">' - + '<div>' - + '<label class="control-label">' + TYPO3.lang['formManager.form_name'] + '</label>' - + '<input class="new-form-name form-control has-error" data-identifier="newFormName" />'; - - if (savePathSelect) { - html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; - } - - if (prototypes.length > 1 || templates.length > 1) { - html += '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.advanced'] + '</label>' - + '<div class="t3-form-controls"><input type="checkbox" class="new-form-advance-wizard" data-identifier="advancedWizard" /></div>'; - } - - html += '</div>' - + '</div>' - + '</div>'; - - slide.html(html); - $(getDomElementIdentifier('newFormName'), modal).focus(); - - $(getDomElementIdentifier('newFormName'), modal).on('keyup paste', function(e) { - if ($(this).val().length > 0) { - $(this).removeClass('has-error'); - Wizard.unlockNextStep(); - Wizard.set('formName', $(this).val()); - } else { - $(this).addClass('has-error'); - Wizard.lockNextStep(); - } - }); - - $(getDomElementIdentifier('newFormSavePath'), modal).on('change', function(e) { - Wizard.set('savePath', $(getDomElementIdentifier('newFormSavePath') + ' option:selected', modal).val()); - }); - - $(getDomElementIdentifier('advancedWizard'), modal).on('change', function(e) { - if ($(this).is(':checked')) { - Wizard.set('advancedWizard', true); - } else { - Wizard.set('advancedWizard', false); - } - }); - - nextButton.on('click', function() { - Wizard.setup.forceSelection = false; - Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { - slide.html($('<div />', {class: 'text-center'}).append(markup)); - }); - }); - }); - - /** - * Wizard step 2 - */ - Wizard.addSlide('new-form-step-2', TYPO3.lang['formManager.newFormWizard.step2.title'], '', Severity.info, function(slide, settings) { - var addOnTemplateChangeEvents, html, modal, nextButton, prototypes, prototypeNameSelect, templates, templateSelect; - - if (settings['advancedWizard'] !== true) { - Wizard.unlockNextStep().trigger('click'); - return; - } - - modal = Wizard.setup.$carousel.closest('.modal'); - nextButton = modal.find('.modal-footer').find('button[name="next"]'); - - prototypeNameSelect = $('<select class="new-form-prototype-name form-control" data-identifier="newFormPrototypeName" />'); - templateSelect = $('<select class="new-form-template form-control" data-identifier="newFormTemplate" />'); - - prototypes = _formManagerApp.getPrototypes(); - templates = {}; - if (prototypes.length > 0) { - for (var i = 0, len = prototypes.length; i < len; ++i) { - var option = new Option(prototypes[i]['label'], prototypes[i]['value']); - $(prototypeNameSelect).append(option); - } - - templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); - for (var i = 0, len = templates.length; i < len; ++i) { - var option = new Option(templates[i]['label'], templates[i]['value']); - $(templateSelect).append(option); - } - } - - html = '<div class="new-form-modal">' - + '<div class="form-horizontal">' - + '<div>'; - - if (prototypes.length > 1) { - html += '<label class="control-label">' + TYPO3.lang['formManager.form_prototype'] + '</label>' + $(prototypeNameSelect)[0].outerHTML; - } - if (templates.length > 1) { - html += '<label class="control-label">' + TYPO3.lang['formManager.form_template'] + '</label>' + $(templateSelect)[0].outerHTML; - } - - html += '</div>' - + '</div>' - + '</div>'; - - slide.html(html); - if (prototypes.length > 1) { - $(getDomElementIdentifier('newFormPrototypeName'), modal).focus(); - } else if (templates.length > 1) { - $(getDomElementIdentifier('newFormTemplate'), modal).focus(); - } - - addOnTemplateChangeEvents = function() { - $(getDomElementIdentifier('newFormTemplate'), modal).on('change', function(e) { - Wizard.set('templatePath', $(getDomElementIdentifier('newFormTemplate') + ' option:selected', modal).val()); - }); - }; - - $(getDomElementIdentifier('newFormPrototypeName'), modal).on('change', function(e) { - Wizard.set('prototypeName', $(this).val()); - templates = _formManagerApp.getTemplatesForPrototype($(this).val()); - $(getDomElementIdentifier('newFormTemplate'), modal).off().empty(); - for (var i = 0, len = templates.length; i < len; ++i) { - var option = new Option(templates[i]['label'], templates[i]['value']); - $(getDomElementIdentifier('newFormTemplate'), modal).append(option); - Wizard.set('templatePath', templates[0]['value']); - } - addOnTemplateChangeEvents(); - }); - - addOnTemplateChangeEvents(); - - nextButton.on('click', function() { - Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { - slide.html($('<div />', {class: 'text-center'}).append(markup)); - }); - }); - }); - - /** - * Wizard step 3 - */ - Wizard.addSlide('new-form-step-3', TYPO3.lang['formManager.newFormWizard.step3.title'], TYPO3.lang['formManager.newFormWizard.step3.message'], Severity.info); - - /** - * Wizard step 4 - */ - Wizard.addFinalProcessingSlide(function() { - $.post(_formManagerApp.getAjaxEndpoint('create'), { - tx_form_web_formformbuilder: { - formName: Wizard.setup.settings['formName'], - templatePath: Wizard.setup.settings['templatePath'], - prototypeName: Wizard.setup.settings['prototypeName'], - savePath: Wizard.setup.settings['savePath'] - } - }, function(data, textStatus, jqXHR) { - if (data['status'] === 'success') { - document.location = data.url; - } else { - Notification.error(TYPO3.lang['formManager.newFormWizard.step4.errorTitle'], TYPO3.lang['formManager.newFormWizard.step4.errorMessage'] + " " + data['message']); - } - Wizard.dismiss(); - }).fail(function(jqXHR, textStatus, errorThrown) { - var parser = new DOMParser(), - responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), - responseBody = $(responseDocument.body); - - Notification.error(textStatus, errorThrown, 2); - Wizard.dismiss(); - - $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); - $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); - $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); - }); - }).done(function() { - Wizard.show(); - }); + nextButton.on('click', function() { + Wizard.setup.forceSelection = false; + Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { + slide.html($('<div />', {class: 'text-center'}).append(markup)); }); - }; + }); + }); /** - * @private - * - * @return void + * Wizard step 2 */ - function _removeFormSetup() { - $(getDomElementIdentifier('removeFormModalTrigger')).on('click', function(e) { - var modalButtons = [], that; - - e.preventDefault(); - that = $(this) - - modalButtons.push({ - text: TYPO3.lang['formManager.cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - modalButtons.push({ - text: TYPO3.lang['formManager.remove_form'], - active: true, - btnClass: 'btn-warning', - name: 'createform', - trigger: function () { - document.location = _formManagerApp.getAjaxEndpoint('delete') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + that.data('formPersistenceIdentifier'); - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - Modal.show( - TYPO3.lang['formManager.remove_form_title'], - TYPO3.lang['formManager.remove_form_message'], - Severity.warning, - modalButtons - ); + Wizard.addSlide('new-form-step-2', TYPO3.lang['formManager.newFormWizard.step2.title'], '', Severity.info, function(slide, settings) { + var addOnTemplateChangeEvents, html, modal, nextButton, prototypes, prototypeNameSelect, + templates, templateSelect; + + if (settings['advancedWizard'] !== true) { + Wizard.unlockNextStep().trigger('click'); + return; + } + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + prototypeNameSelect = $('<select class="new-form-prototype-name form-control" data-identifier="newFormPrototypeName" />'); + templateSelect = $('<select class="new-form-template form-control" data-identifier="newFormTemplate" />'); + + prototypes = _formManagerApp.getPrototypes(); + templates = {}; + if (prototypes.length > 0) { + for (var i = 0, len = prototypes.length; i < len; ++i) { + var option = new Option(prototypes[i]['label'], prototypes[i]['value']); + $(prototypeNameSelect).append(option); + } + + templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']); + for (var i = 0, len = templates.length; i < len; ++i) { + var option = new Option(templates[i]['label'], templates[i]['value']); + $(templateSelect).append(option); + } + } + + html = '<div class="new-form-modal">' + + '<div class="form-horizontal">' + + '<div>'; + + if (prototypes.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_prototype'] + '</label>' + $(prototypeNameSelect)[0].outerHTML; + } + if (templates.length > 1) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_template'] + '</label>' + $(templateSelect)[0].outerHTML; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + if (prototypes.length > 1) { + $(getDomElementIdentifier('newFormPrototypeName'), modal).focus(); + } else if (templates.length > 1) { + $(getDomElementIdentifier('newFormTemplate'), modal).focus(); + } + + addOnTemplateChangeEvents = function() { + $(getDomElementIdentifier('newFormTemplate'), modal).on('change', function(e) { + Wizard.set('templatePath', $(getDomElementIdentifier('newFormTemplate') + ' option:selected', modal).val()); }); - }; + }; + + $(getDomElementIdentifier('newFormPrototypeName'), modal).on('change', function(e) { + Wizard.set('prototypeName', $(this).val()); + templates = _formManagerApp.getTemplatesForPrototype($(this).val()); + $(getDomElementIdentifier('newFormTemplate'), modal).off().empty(); + for (var i = 0, len = templates.length; i < len; ++i) { + var option = new Option(templates[i]['label'], templates[i]['value']); + $(getDomElementIdentifier('newFormTemplate'), modal).append(option); + Wizard.set('templatePath', templates[0]['value']); + } + addOnTemplateChangeEvents(); + }); - /** - * @private - * - * @return void - * @throws 1477649539 - */ - function _duplicateFormSetup() { - $(getDomElementIdentifier('duplicateFormModalTrigger')).on('click', function(e) { - var that; - - e.preventDefault(); - that = $(this); - - /** - * Wizard step 1 - */ - Wizard.addSlide('duplicate-form-step-1', TYPO3.lang['formManager.duplicateFormWizard.step1.title'].replace('{0}', that.data('formName')), '', Severity.info, function(slide) { - var folders, html, modal, nextButton, savePathSelect; - - modal = Wizard.setup.$carousel.closest('.modal'); - nextButton = modal.find('.modal-footer').find('button[name="next"]'); - - folders = _formManagerApp.getAccessibleFormStorageFolders(); - _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477649539); - - Wizard.set('formPersistenceIdentifier', that.data('formPersistenceIdentifier')); - Wizard.set('savePath', folders[0]['value']); - if (folders.length > 1) { - savePathSelect = $('<select class="duplicate-form-save-path form-control" data-identifier="duplicateFormSavePath" />'); - for (var i = 0, len = folders.length; i < len; ++i) { - var option = new Option(folders[i]['label'], folders[i]['value']); - $(savePathSelect).append(option); - } - } - - html = '<div class="duplicate-form-modal">' - + '<div class="form-horizontal">' - + '<div>' - + '<label class="control-label">' + TYPO3.lang['formManager.new_form_name'] + '</label>' - + '<input class="duplicate-form-name form-control has-error" data-identifier="duplicateFormName" />'; - - if (savePathSelect) { - html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; - } - - html += '</div>' - + '</div>' - + '</div>'; - - slide.html(html); - $(getDomElementIdentifier('duplicateFormName'), modal).focus(); - - $(getDomElementIdentifier('duplicateFormName'), modal).on('keyup paste', function(e) { - if ($(this).val().length > 0) { - $(this).removeClass('has-error'); - Wizard.unlockNextStep(); - Wizard.set('formName', $(this).val()); - } else { - $(this).addClass('has-error'); - Wizard.lockNextStep(); - } - }); - - $(getDomElementIdentifier('duplicateFormSavePath'), modal).on('change', function(e) { - Wizard.set('savePath', $(getDomElementIdentifier('duplicateFormSavePath') + ' option:selected', modal).val()); - }); - }); - - /** - * Wizard step 2 - */ - Wizard.addFinalProcessingSlide(function() { - $.post(_formManagerApp.getAjaxEndpoint('duplicate'), { - tx_form_web_formformbuilder: { - formName: Wizard.setup.settings['formName'], - formPersistenceIdentifier: Wizard.setup.settings['formPersistenceIdentifier'], - savePath: Wizard.setup.settings['savePath'] - } - }, function(data, textStatus, jqXHR) { - if (data['status'] === 'success') { - document.location = data.url; - } else { - Notification.error(TYPO3.lang['formManager.duplicateFormWizard.step2.errorTitle'], TYPO3.lang['formManager.duplicateFormWizard.step2.errorMessage'] + " " + data['message']); - } - Wizard.dismiss(); - }).fail(function(jqXHR, textStatus, errorThrown) { - var parser = new DOMParser(), - responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), - responseBody = $(responseDocument.body); - - Notification.error(textStatus, errorThrown, 2); - Wizard.dismiss(); - - $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); - $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); - $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); - }); - }).done(function() { - Wizard.show(); - }); + addOnTemplateChangeEvents(); + + nextButton.on('click', function() { + Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) { + slide.html($('<div />', {class: 'text-center'}).append(markup)); }); - }; + }); + }); /** - * @private - * - * @return void + * Wizard step 3 */ - function _showReferencesSetup() { - $(getDomElementIdentifier('showReferences')).on('click', function(e) { - var that, url; - - e.preventDefault(); - that = this; - url = _formManagerApp.getAjaxEndpoint('references') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + $(this).data('formPersistenceIdentifier'); - - $.get(url, function(data, textStatus, jqXHR) { - var html, modalButtons = [], referencesLength; - - modalButtons.push({ - text: TYPO3.lang['formManager.cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - referencesLength = data['references'].length; - if (referencesLength > 0) { - html = '<div>' - + '<h3>' + TYPO3.lang['formManager.references.headline'].replace('{0}', $(that).data('formName')) + '</h3>' - + '</div>' - + '<div class="table-fit">' - + '<table id="forms" class="table table-striped table-condensed">' - + '<thead>' - + '<tr>' - + '<th>' + TYPO3.lang['formManager.page'] + '</th>' - + '<th>' + TYPO3.lang['formManager.record'] + '</th>' - + '</tr>' - + '</thead>' - + '<tbody>'; - - for (var i = 0, len = data['references'].length; i < len; ++i) { - html += '<tr>' - + '<td>' + data['references'][i]['recordPageTitle'] + '</td>' - + '<td>' - + data['references'][i]['recordIcon'] - + '<a href="' + data['references'][i]['recordEditUrl'] + '" data-identifier="referenceLink">' - + data['references'][i]['recordTitle'] + ' (uid: ' + data['references'][i]['recordUid'] + ')' - + '</a>' - + '</td>' - + '</tr>'; - } - - html += '</tbody>' - + '</table>' - + '</div>'; - } else { - html = '<div>' - + '<h1>' + TYPO3.lang['formManager.references.title'].replace('{0}', data['formPersistenceIdentifier']) + '</h1>' - + '</div>' - + '<div>' + TYPO3.lang['formManager.no_references'] + '</div>'; - } - - html = $(html); - $(getDomElementIdentifier('referenceLink'), html).on('click', function(e) { - e.preventDefault(); - Modal.currentModal.trigger('modal-dismiss'); - document.location = $(this).prop('href'); - }); - - Modal.show( - TYPO3.lang['formManager.references.title'], - html, - Severity.info, - modalButtons - ); - }).fail(function(jqXHR, textStatus, errorThrown) { - if (jqXHR.status !== 0) { - Notification.error(textStatus, errorThrown, 2); - } - }); - }); - }; + Wizard.addSlide('new-form-step-3', TYPO3.lang['formManager.newFormWizard.step3.title'], TYPO3.lang['formManager.newFormWizard.step3.message'], Severity.info); /** - * @public - * - * @param string elementIdentifier - * @param string type - * @return mixed|undefined - * @throws 1477506413 - * @throws 1477506414 + * Wizard step 4 */ - function getDomElementIdentifier(elementIdentifier, type) { - _formManagerApp.assert(elementIdentifier.length > 0, 'Invalid parameter "elementIdentifier"', 1477506413); - _formManagerApp.assert(typeof _domElementIdentifierCache[elementIdentifier] !== "undefined", 'elementIdentifier "' + elementIdentifier + '" does not exist', 1477506414); - if (typeof type === "undefined") { - type = 'identifier'; + Wizard.addFinalProcessingSlide(function() { + $.post(_formManagerApp.getAjaxEndpoint('create'), { + tx_form_web_formformbuilder: { + formName: Wizard.setup.settings['formName'], + templatePath: Wizard.setup.settings['templatePath'], + prototypeName: Wizard.setup.settings['prototypeName'], + savePath: Wizard.setup.settings['savePath'] } - - return _domElementIdentifierCache[elementIdentifier][type] || undefined; - }; + }, function(data, textStatus, jqXHR) { + if (data['status'] === 'success') { + document.location = data.url; + } else { + Notification.error(TYPO3.lang['formManager.newFormWizard.step4.errorTitle'], TYPO3.lang['formManager.newFormWizard.step4.errorMessage'] + " " + data['message']); + } + Wizard.dismiss(); + }).fail(function(jqXHR, textStatus, errorThrown) { + var parser = new DOMParser(), + responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), + responseBody = $(responseDocument.body); + + Notification.error(textStatus, errorThrown, 2); + Wizard.dismiss(); + + $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); + $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); + $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); + }); + }).done(function() { + Wizard.show(); + }); + }); + }; + + /** + * @private + * + * @return void + */ + function _removeFormSetup() { + $(getDomElementIdentifier('removeFormModalTrigger')).on('click', function(e) { + var modalButtons = [], that; + + e.preventDefault(); + that = $(this) + + modalButtons.push({ + text: TYPO3.lang['formManager.cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + modalButtons.push({ + text: TYPO3.lang['formManager.remove_form'], + active: true, + btnClass: 'btn-warning', + name: 'createform', + trigger: function() { + document.location = _formManagerApp.getAjaxEndpoint('delete') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + that.data('formPersistenceIdentifier'); + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + TYPO3.lang['formManager.remove_form_title'], + TYPO3.lang['formManager.remove_form_message'], + Severity.warning, + modalButtons + ); + }); + }; + + /** + * @private + * + * @return void + * @throws 1477649539 + */ + function _duplicateFormSetup() { + $(getDomElementIdentifier('duplicateFormModalTrigger')).on('click', function(e) { + var that; + + e.preventDefault(); + that = $(this); /** - * @public - * - * @param object formManagerApp - * @return void + * Wizard step 1 */ - function bootstrap(formManagerApp) { - _formManagerApp = formManagerApp; - _domElementIdentifierCacheSetup(); - _removeFormSetup(); - _newFormSetup(); - _duplicateFormSetup(); - _showReferencesSetup(); - $(getDomElementIdentifier('tooltip')).tooltip(); - }; + Wizard.addSlide('duplicate-form-step-1', TYPO3.lang['formManager.duplicateFormWizard.step1.title'].replace('{0}', that.data('formName')), '', Severity.info, function(slide) { + var folders, html, modal, nextButton, savePathSelect; + + modal = Wizard.setup.$carousel.closest('.modal'); + nextButton = modal.find('.modal-footer').find('button[name="next"]'); + + folders = _formManagerApp.getAccessibleFormStorageFolders(); + _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477649539); + + Wizard.set('formPersistenceIdentifier', that.data('formPersistenceIdentifier')); + Wizard.set('savePath', folders[0]['value']); + if (folders.length > 1) { + savePathSelect = $('<select class="duplicate-form-save-path form-control" data-identifier="duplicateFormSavePath" />'); + for (var i = 0, len = folders.length; i < len; ++i) { + var option = new Option(folders[i]['label'], folders[i]['value']); + $(savePathSelect).append(option); + } + } + + html = '<div class="duplicate-form-modal">' + + '<div class="form-horizontal">' + + '<div>' + + '<label class="control-label">' + TYPO3.lang['formManager.new_form_name'] + '</label>' + + '<input class="duplicate-form-name form-control has-error" data-identifier="duplicateFormName" />'; + + if (savePathSelect) { + html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML; + } + + html += '</div>' + + '</div>' + + '</div>'; + + slide.html(html); + $(getDomElementIdentifier('duplicateFormName'), modal).focus(); + + $(getDomElementIdentifier('duplicateFormName'), modal).on('keyup paste', function(e) { + if ($(this).val().length > 0) { + $(this).removeClass('has-error'); + Wizard.unlockNextStep(); + Wizard.set('formName', $(this).val()); + } else { + $(this).addClass('has-error'); + Wizard.lockNextStep(); + } + }); + + $(getDomElementIdentifier('duplicateFormSavePath'), modal).on('change', function(e) { + Wizard.set('savePath', $(getDomElementIdentifier('duplicateFormSavePath') + ' option:selected', modal).val()); + }); + }); /** - * Publish the public methods. - * Implements the "Revealing Module Pattern". + * Wizard step 2 */ - return { - bootstrap: bootstrap, - }; - })($, Modal, Severity, Wizard, Icons, Notification); + Wizard.addFinalProcessingSlide(function() { + $.post(_formManagerApp.getAjaxEndpoint('duplicate'), { + tx_form_web_formformbuilder: { + formName: Wizard.setup.settings['formName'], + formPersistenceIdentifier: Wizard.setup.settings['formPersistenceIdentifier'], + savePath: Wizard.setup.settings['savePath'] + } + }, function(data, textStatus, jqXHR) { + if (data['status'] === 'success') { + document.location = data.url; + } else { + Notification.error(TYPO3.lang['formManager.duplicateFormWizard.step2.errorTitle'], TYPO3.lang['formManager.duplicateFormWizard.step2.errorMessage'] + " " + data['message']); + } + Wizard.dismiss(); + }).fail(function(jqXHR, textStatus, errorThrown) { + var parser = new DOMParser(), + responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"), + responseBody = $(responseDocument.body); + + Notification.error(textStatus, errorThrown, 2); + Wizard.dismiss(); + + $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove(); + $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove(); + $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html()); + }); + }).done(function() { + Wizard.show(); + }); + }); + }; + + /** + * @private + * + * @return void + */ + function _showReferencesSetup() { + $(getDomElementIdentifier('showReferences')).on('click', function(e) { + var that, url; + + e.preventDefault(); + that = this; + url = _formManagerApp.getAjaxEndpoint('references') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + $(this).data('formPersistenceIdentifier'); + + $.get(url, function(data, textStatus, jqXHR) { + var html, modalButtons = [], referencesLength; + + modalButtons.push({ + text: TYPO3.lang['formManager.cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + referencesLength = data['references'].length; + if (referencesLength > 0) { + html = '<div>' + + '<h3>' + TYPO3.lang['formManager.references.headline'].replace('{0}', $(that).data('formName')) + '</h3>' + + '</div>' + + '<div class="table-fit">' + + '<table id="forms" class="table table-striped table-condensed">' + + '<thead>' + + '<tr>' + + '<th>' + TYPO3.lang['formManager.page'] + '</th>' + + '<th>' + TYPO3.lang['formManager.record'] + '</th>' + + '</tr>' + + '</thead>' + + '<tbody>'; + + for (var i = 0, len = data['references'].length; i < len; ++i) { + html += '<tr>' + + '<td>' + data['references'][i]['recordPageTitle'] + '</td>' + + '<td>' + + data['references'][i]['recordIcon'] + + '<a href="' + data['references'][i]['recordEditUrl'] + '" data-identifier="referenceLink">' + + data['references'][i]['recordTitle'] + ' (uid: ' + data['references'][i]['recordUid'] + ')' + + '</a>' + + '</td>' + + '</tr>'; + } + + html += '</tbody>' + + '</table>' + + '</div>'; + } else { + html = '<div>' + + '<h1>' + TYPO3.lang['formManager.references.title'].replace('{0}', data['formPersistenceIdentifier']) + '</h1>' + + '</div>' + + '<div>' + TYPO3.lang['formManager.no_references'] + '</div>'; + } + + html = $(html); + $(getDomElementIdentifier('referenceLink'), html).on('click', function(e) { + e.preventDefault(); + Modal.currentModal.trigger('modal-dismiss'); + document.location = $(this).prop('href'); + }); + + Modal.show( + TYPO3.lang['formManager.references.title'], + html, + Severity.info, + modalButtons + ); + }).fail(function(jqXHR, textStatus, errorThrown) { + if (jqXHR.status !== 0) { + Notification.error(textStatus, errorThrown, 2); + } + }); + }); + }; + + /** + * @public + * + * @param string elementIdentifier + * @param string type + * @return mixed|undefined + * @throws 1477506413 + * @throws 1477506414 + */ + function getDomElementIdentifier(elementIdentifier, type) { + _formManagerApp.assert(elementIdentifier.length > 0, 'Invalid parameter "elementIdentifier"', 1477506413); + _formManagerApp.assert(typeof _domElementIdentifierCache[elementIdentifier] !== "undefined", 'elementIdentifier "' + elementIdentifier + '" does not exist', 1477506414); + if (typeof type === "undefined") { + type = 'identifier'; + } + + return _domElementIdentifierCache[elementIdentifier][type] || undefined; + }; + + /** + * @public + * + * @param object formManagerApp + * @return void + */ + function bootstrap(formManagerApp) { + _formManagerApp = formManagerApp; + _domElementIdentifierCacheSetup(); + _removeFormSetup(); + _newFormSetup(); + _duplicateFormSetup(); + _showReferencesSetup(); + $(getDomElementIdentifier('tooltip')).tooltip(); + }; + + /** + * Publish the public methods. + * Implements the "Revealing Module Pattern". + */ + return { + bootstrap: bootstrap + }; + })($, Modal, Severity, Wizard, Icons, Notification); }); diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js index 38bf5f7eb0d75d61a528f9c9b0ee7c269a6adf82..7758ecba0a0869d4e6eb7a1bbcb566bef883fbfa 100644 --- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js +++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js @@ -10,898 +10,902 @@ * Licensed under the MIT License * http://www.opensource.org/licenses/mit-license.php */ -(function( factory ) { - "use strict"; +(function(factory) { + "use strict"; - if ( typeof define === "function" && define.amd ) { + if (typeof define === "function" && define.amd) { - // AMD. Register as an anonymous module. - define([ - "jquery", - "jquery-ui/sortable" - ], factory ); - } else { + // AMD. Register as an anonymous module. + define([ + "jquery", + "jquery-ui/sortable" + ], factory); + } else { - // Browser globals - factory( window.jQuery ); - } + // Browser globals + factory(window.jQuery); + } }(function($) { - "use strict"; - - function isOverAxis( x, reference, size ) { - return ( x > reference ) && ( x < ( reference + size ) ); - } - - $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, { - - options: { - disableParentChange: false, - doNotClear: false, - expandOnHover: 700, - isAllowed: function() { return true; }, - isTree: false, - listType: "ol", - maxLevels: 0, - protectRoot: false, - rootID: null, - rtl: false, - startCollapsed: false, - tabSize: 20, - - branchClass: "mjs-nestedSortable-branch", - collapsedClass: "mjs-nestedSortable-collapsed", - disableNestingClass: "mjs-nestedSortable-no-nesting", - errorClass: "mjs-nestedSortable-error", - expandedClass: "mjs-nestedSortable-expanded", - hoveringClass: "mjs-nestedSortable-hovering", - leafClass: "mjs-nestedSortable-leaf", - disabledClass: "mjs-nestedSortable-disabled" - }, - - _create: function() { - var self = this, - err; - - this.element.data("ui-sortable", this.element.data("mjs-nestedSortable")); - - // mjs - prevent browser from freezing if the HTML is not correct - if (!this.element.is(this.options.listType)) { - err = "nestedSortable: " + - "Please check that the listType option is set to your actual list type"; - - throw new Error(err); - } - - // if we have a tree with expanding/collapsing functionality, - // force 'intersect' tolerance method - if (this.options.isTree && this.options.expandOnHover) { - this.options.tolerance = "intersect"; - } - - $.ui.sortable.prototype._create.apply(this, arguments); - - // prepare the tree by applying the right classes - // (the CSS is responsible for actual hide/show functionality) - if (this.options.isTree) { - $(this.items).each(function() { - var $li = this.item, - hasCollapsedClass = $li.hasClass(self.options.collapsedClass), - hasExpandedClass = $li.hasClass(self.options.expandedClass); - - if ($li.children(self.options.listType).length) { - $li.addClass(self.options.branchClass); - // expand/collapse class only if they have children - - if ( !hasCollapsedClass && !hasExpandedClass ) { - if (self.options.startCollapsed) { - $li.addClass(self.options.collapsedClass); - } else { - $li.addClass(self.options.expandedClass); - } - } - } else { - $li.addClass(self.options.leafClass); - } - }); - } - }, - - _destroy: function() { - this.element - .removeData("mjs-nestedSortable") - .removeData("ui-sortable"); - return $.ui.sortable.prototype._destroy.apply(this, arguments); - }, - - _mouseDrag: function(event) { - var i, - item, - itemElement, - intersection, - self = this, - o = this.options, - scrolled = false, - $document = $(document), - previousTopOffset, - parentItem, - level, - childLevels, - itemAfter, - itemBefore, - newList, - method, - a, - previousItem, - nextItem, - helperIsNotSibling; - - //Compute the helpers position - this.position = this._generatePosition(event); - this.positionAbs = this._convertPositionTo("absolute"); - - if (!this.lastPositionAbs) { - this.lastPositionAbs = this.positionAbs; - } - - //Do scrolling - if (this.options.scroll) { - if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { - - if ( - ( - this.overflowOffset.top + - this.scrollParent[0].offsetHeight - ) - - event.pageY < - o.scrollSensitivity - ) { - scrolled = this.scrollParent.scrollTop() + o.scrollSpeed; - this.scrollParent.scrollTop(scrolled); - } else if ( - event.pageY - - this.overflowOffset.top < - o.scrollSensitivity - ) { - scrolled = this.scrollParent.scrollTop() - o.scrollSpeed; - this.scrollParent.scrollTop(scrolled); - } - - if ( - ( - this.overflowOffset.left + - this.scrollParent[0].offsetWidth - ) - - event.pageX < - o.scrollSensitivity - ) { - scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed; - this.scrollParent.scrollLeft(scrolled); - } else if ( - event.pageX - - this.overflowOffset.left < - o.scrollSensitivity - ) { - scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed; - this.scrollParent.scrollLeft(scrolled); - } - - } else { - - if ( - event.pageY - - $document.scrollTop() < - o.scrollSensitivity - ) { - scrolled = $document.scrollTop() - o.scrollSpeed; - $document.scrollTop(scrolled); - } else if ( - $(window).height() - - ( - event.pageY - - $document.scrollTop() - ) < - o.scrollSensitivity - ) { - scrolled = $document.scrollTop() + o.scrollSpeed; - $document.scrollTop(scrolled); - } - - if ( - event.pageX - - $document.scrollLeft() < - o.scrollSensitivity - ) { - scrolled = $document.scrollLeft() - o.scrollSpeed; - $document.scrollLeft(scrolled); - } else if ( - $(window).width() - - ( - event.pageX - - $document.scrollLeft() - ) < - o.scrollSensitivity - ) { - scrolled = $document.scrollLeft() + o.scrollSpeed; - $document.scrollLeft(scrolled); - } - - } - - if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { - $.ui.ddmanager.prepareOffsets(this, event); - } - } - - //Regenerate the absolute position used for position checks - this.positionAbs = this._convertPositionTo("absolute"); - - // mjs - find the top offset before rearrangement, - previousTopOffset = this.placeholder.offset().top; - - //Set the helper position - if (!this.options.axis || this.options.axis !== "y") { - this.helper[0].style.left = this.position.left + "px"; - } - if (!this.options.axis || this.options.axis !== "x") { - this.helper[0].style.top = (this.position.top) + "px"; - } - - // mjs - check and reset hovering state at each cycle - this.hovering = this.hovering ? this.hovering : null; - this.mouseentered = this.mouseentered ? this.mouseentered : false; - - // mjs - let's start caching some variables - (function() { - var _parentItem = this.placeholder.parent().parent(); - if (_parentItem && _parentItem.closest(".ui-sortable").length) { - parentItem = _parentItem; - } - }.call(this)); - - level = this._getLevel(this.placeholder); - childLevels = this._getChildLevels(this.helper); - newList = document.createElement(o.listType); - - //Rearrange - for (i = this.items.length - 1; i >= 0; i--) { - - //Cache variables and intersection, continue if no intersection - item = this.items[i]; - itemElement = item.item[0]; - intersection = this._intersectsWithPointer(item); - if (!intersection) { - continue; - } - - // Only put the placeholder inside the current Container, skip all - // items form other containers. This works because when moving - // an item from one container to another the - // currentContainer is switched before the placeholder is moved. - // - // Without this moving items in "sub-sortables" can cause the placeholder to jitter - // beetween the outer and inner container. - if (item.instance !== this.currentContainer) { - continue; - } - - // No action if intersected item is disabled - // and the element above or below in the direction we're going is also disabled - if (itemElement.className.indexOf(o.disabledClass) !== -1) { - // Note: intersection hardcoded direction values from - // jquery.ui.sortable.js:_intersectsWithPointer - if (intersection === 2) { - // Going down - itemAfter = this.items[i + 1]; - if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) { - continue; - } - - } else if (intersection === 1) { - // Going up - itemBefore = this.items[i - 1]; - if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) { - continue; - } - } - } - - method = intersection === 1 ? "next" : "prev"; - - // cannot intersect with itself - // no useless actions that have been done before - // no action if the item moved is the parent of the item checked - if (itemElement !== this.currentItem[0] && - this.placeholder[method]()[0] !== itemElement && - !$.contains(this.placeholder[0], itemElement) && - ( - this.options.type === "semi-dynamic" ? - !$.contains(this.element[0], itemElement) : - true - ) - ) { - - // mjs - we are intersecting an element: - // trigger the mouseenter event and store this state - if (!this.mouseentered) { - $(itemElement).mouseenter(); - this.mouseentered = true; - } - - // mjs - if the element has children and they are hidden, - // show them after a delay (CSS responsible) - if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) { - if (!this.hovering) { - $(itemElement).addClass(o.hoveringClass); - this.hovering = window.setTimeout(function() { - $(itemElement) - .removeClass(o.collapsedClass) - .addClass(o.expandedClass); - - self.refreshPositions(); - self._trigger("expand", event, self._uiHash()); - }, o.expandOnHover); - } - } - - this.direction = intersection === 1 ? "down" : "up"; - - // mjs - rearrange the elements and reset timeouts and hovering state - if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { - $(itemElement).mouseleave(); - this.mouseentered = false; - $(itemElement).removeClass(o.hoveringClass); - if (this.hovering) { - window.clearTimeout(this.hovering); - } - this.hovering = null; - - // mjs - do not switch container if - // it's a root item and 'protectRoot' is true - // or if it's not a root item but we are trying to make it root - if (o.protectRoot && - !( - this.currentItem[0].parentNode === this.element[0] && - // it's a root item - itemElement.parentNode !== this.element[0] - // it's intersecting a non-root item - ) - ) { - if (this.currentItem[0].parentNode !== this.element[0] && - itemElement.parentNode === this.element[0] - ) { - - if ( !$(itemElement).children(o.listType).length) { - itemElement.appendChild(newList); - if (o.isTree) { - $(itemElement) - .removeClass(o.leafClass) - .addClass(o.branchClass + " " + o.expandedClass); - } - } - - if (this.direction === "down") { - a = $(itemElement).prev().children(o.listType); - } else { - a = $(itemElement).children(o.listType); - } - - if (a[0] !== undefined) { - this._rearrange(event, null, a); - } - - } else { - this._rearrange(event, item); - } - } else if (!o.protectRoot) { - this._rearrange(event, item); - } - } else { - break; - } - - // Clear emtpy ul's/ol's - this._clearEmpty(itemElement); - - this._trigger("change", event, this._uiHash()); - break; - } - } - - // mjs - to find the previous sibling in the list, - // keep backtracking until we hit a valid list item. - (function() { - var _previousItem = this.placeholder.prev(); - if (_previousItem.length) { - previousItem = _previousItem; - } else { - previousItem = null; - } - }.call(this)); - - if (previousItem != null) { - while ( - previousItem[0].nodeName.toLowerCase() !== "li" || - previousItem[0].className.indexOf(o.disabledClass) !== -1 || - previousItem[0] === this.currentItem[0] || - previousItem[0] === this.helper[0] - ) { - if (previousItem[0].previousSibling) { - previousItem = $(previousItem[0].previousSibling); - } else { - previousItem = null; - break; - } - } - } - - // mjs - to find the next sibling in the list, - // keep stepping forward until we hit a valid list item. - (function() { - var _nextItem = this.placeholder.next(); - if (_nextItem.length) { - nextItem = _nextItem; - } else { - nextItem = null; - } - }.call(this)); - - if (nextItem != null) { - while ( - nextItem[0].nodeName.toLowerCase() !== "li" || - nextItem[0].className.indexOf(o.disabledClass) !== -1 || - nextItem[0] === this.currentItem[0] || - nextItem[0] === this.helper[0] - ) { - if (nextItem[0].nextSibling) { - nextItem = $(nextItem[0].nextSibling); - } else { - nextItem = null; - break; - } - } - } - - this.beyondMaxLevels = 0; - - // mjs - if the item is moved to the left, send it one level up - // but only if it's at the bottom of the list - if (parentItem != null && - nextItem == null && - !(o.protectRoot && parentItem[0].parentNode == this.element[0]) && - ( - o.rtl && - ( - this.positionAbs.left + - this.helper.outerWidth() > parentItem.offset().left + - parentItem.outerWidth() - ) || - !o.rtl && (this.positionAbs.left < parentItem.offset().left) - ) - ) { - - parentItem.after(this.placeholder[0]); - helperIsNotSibling = !parentItem - .children(o.listItem) - .children("li:visible:not(.ui-sortable-helper)") - .length; - if (o.isTree && helperIsNotSibling) { - parentItem - .removeClass(this.options.branchClass + " " + this.options.expandedClass) - .addClass(this.options.leafClass); - } - if(typeof parentItem !== 'undefined') - this._clearEmpty(parentItem[0]); - this._trigger("change", event, this._uiHash()); - // mjs - if the item is below a sibling and is moved to the right, - // make it a child of that sibling - } else if (previousItem != null && - !previousItem.hasClass(o.disableNestingClass) && - ( - previousItem.children(o.listType).length && - previousItem.children(o.listType).is(":visible") || - !previousItem.children(o.listType).length - ) && - !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) && - ( - o.rtl && - ( - this.positionAbs.left + - this.helper.outerWidth() < - previousItem.offset().left + - previousItem.outerWidth() - - o.tabSize - ) || - !o.rtl && - (this.positionAbs.left > previousItem.offset().left + o.tabSize) - ) - ) { - - this._isAllowed(previousItem, level, level + childLevels + 1); - - if (!previousItem.children(o.listType).length) { - previousItem[0].appendChild(newList); - if (o.isTree) { - previousItem - .removeClass(o.leafClass) - .addClass(o.branchClass + " " + o.expandedClass); - } - } - - // mjs - if this item is being moved from the top, add it to the top of the list. - if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) { - previousItem.children(o.listType).prepend(this.placeholder); - } else { - // mjs - otherwise, add it to the bottom of the list. - previousItem.children(o.listType)[0].appendChild(this.placeholder[0]); - } - if(typeof parentItem !== 'undefined') - this._clearEmpty(parentItem[0]); - this._trigger("change", event, this._uiHash()); - } else { - this._isAllowed(parentItem, level, level + childLevels); - } - - //Post events to containers - this._contactContainers(event); - - //Interconnect with droppables - if ($.ui.ddmanager) { - $.ui.ddmanager.drag(this, event); - } - - //Call callbacks - this._trigger("sort", event, this._uiHash()); - - this.lastPositionAbs = this.positionAbs; - return false; - - }, - - _mouseStop: function(event) { - // mjs - if the item is in a position not allowed, send it back - if (this.beyondMaxLevels) { - - this.placeholder.removeClass(this.options.errorClass); - - if (this.domPosition.prev) { - $(this.domPosition.prev).after(this.placeholder); - } else { - $(this.domPosition.parent).prepend(this.placeholder); - } - - this._trigger("revert", event, this._uiHash()); - - } - - // mjs - clear the hovering timeout, just to be sure - $("." + this.options.hoveringClass) - .mouseleave() - .removeClass(this.options.hoveringClass); - - this.mouseentered = false; - if (this.hovering) { - window.clearTimeout(this.hovering); - } - this.hovering = null; - - this._relocate_event = event; - this._pid_current = $(this.domPosition.parent).parent().attr("id"); - this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0; - $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event. - }, - - // mjs - this function is slightly modified - // to make it easier to hover over a collapsed element and have it expand - _intersectsWithSides: function(item) { - - var half = this.options.isTree ? .8 : .5, - isOverBottomHalf = isOverAxis( - this.positionAbs.top + this.offset.click.top, - item.top + (item.height * half), - item.height - ), - isOverTopHalf = isOverAxis( - this.positionAbs.top + this.offset.click.top, - item.top - (item.height * half), - item.height - ), - isOverRightHalf = isOverAxis( - this.positionAbs.left + this.offset.click.left, - item.left + (item.width / 2), - item.width - ), - verticalDirection = this._getDragVerticalDirection(), - horizontalDirection = this._getDragHorizontalDirection(); - - if (this.floating && horizontalDirection) { - return ( - (horizontalDirection === "right" && isOverRightHalf) || - (horizontalDirection === "left" && !isOverRightHalf) - ); - } else { - return verticalDirection && ( - (verticalDirection === "down" && isOverBottomHalf) || - (verticalDirection === "up" && isOverTopHalf) - ); - } - - }, - - _contactContainers: function() { - - if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) { - return; - } - - $.ui.sortable.prototype._contactContainers.apply(this, arguments); - - }, - - _clear: function() { - var i, - item; - - $.ui.sortable.prototype._clear.apply(this, arguments); - - //relocate event - if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") && - this._sort_current === this._uiHash().item.index())) { - this._trigger("relocate", this._relocate_event, this._uiHash()); - } - - // mjs - clean last empty ul/ol - for (i = this.items.length - 1; i >= 0; i--) { - item = this.items[i].item[0]; - this._clearEmpty(item); - } - - }, - - serialize: function(options) { - - var o = $.extend({}, this.options, options), - items = this._getItemsAsjQuery(o && o.connected), - str = []; - - $(items).each(function() { - var res = ($(o.item || this).attr(o.attribute || "id") || "") - .match(o.expression || (/(.+)[-=_](.+)/)), - pid = ($(o.item || this).parent(o.listType) - .parent(o.items) - .attr(o.attribute || "id") || "") - .match(o.expression || (/(.+)[-=_](.+)/)); - - if (res) { - str.push( - ( - (o.key || res[1]) + - "[" + - (o.key && o.expression ? res[1] : res[2]) + "]" - ) + - "=" + - (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID)); - } - }); - - if (!str.length && o.key) { - str.push(o.key + "="); - } - - return str.join("&"); - - }, - - toHierarchy: function(options) { - - var o = $.extend({}, this.options, options), - ret = []; - - $(this.element).children(o.items).each(function() { - var level = _recursiveItems(this); - ret.push(level); - }); - - return ret; - - function _recursiveItems(item) { - var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)), - currentItem; - - var data = $(item).data(); - if (data.nestedSortableItem) { - delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data - } - - if (id) { - currentItem = { - "id": id[2] - }; - - currentItem = $.extend({}, currentItem, data); // Combine the two objects - - if ($(item).children(o.listType).children(o.items).length > 0) { - currentItem.children = []; - $(item).children(o.listType).children(o.items).each(function() { - var level = _recursiveItems(this); - currentItem.children.push(level); - }); - } - return currentItem; - } - } - }, - - toArray: function(options) { - - var o = $.extend({}, this.options, options), - sDepth = o.startDepthCount || 0, - ret = [], - left = 1; - - if (!o.excludeRoot) { - ret.push({ - "item_id": o.rootID, - "parent_id": null, - "depth": sDepth, - "left": left, - "right": ($(o.items, this.element).length + 1) * 2 - }); - left++; - } - - $(this.element).children(o.items).each(function() { - left = _recursiveArray(this, sDepth, left); - }); - - ret = ret.sort(function(a, b) { return (a.left - b.left); }); - - return ret; - - function _recursiveArray(item, depth, _left) { - - var right = _left + 1, - id, - pid, - parentItem; - - if ($(item).children(o.listType).children(o.items).length > 0) { - depth++; - $(item).children(o.listType).children(o.items).each(function() { - right = _recursiveArray($(this), depth, right); - }); - depth--; - } - - id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)); - - if (depth === sDepth) { - pid = o.rootID; - } else { - parentItem = ($(item).parent(o.listType) - .parent(o.items) - .attr(o.attribute || "id")) - .match(o.expression || (/(.+)[-=_](.+)/)); - pid = parentItem[2]; - } - - if (id) { - var data = $(item).children('div').data(); - var itemObj = $.extend( data, { - "id":id[2], - "parent_id":pid, - "depth":depth, - "left":_left, - "right":right - } ); - ret.push( itemObj ); - } - - _left = right + 1; - return _left; - } - - }, - - _clearEmpty: function (item) { - function replaceClass(elem, search, replace, swap) { - if (swap) { - search = [replace, replace = search][0]; - } - - $(elem).removeClass(search).addClass(replace); - } - - var o = this.options, - childrenList = $(item).children(o.listType), - hasChildren = childrenList.has('li').length; - - var doNotClear = - o.doNotClear || - hasChildren || - o.protectRoot && $(item)[0] === this.element[0]; - - if (o.isTree) { - replaceClass(item, o.branchClass, o.leafClass, doNotClear); - } - - if (!doNotClear) { - childrenList.parent().removeClass(o.expandedClass); - childrenList.remove(); - } - }, - - _getLevel: function(item) { - - var level = 1, - list; - - if (this.options.listType) { - list = item.closest(this.options.listType); - while (list && list.length > 0 && !list.is(".ui-sortable")) { - level++; - list = list.parent().closest(this.options.listType); - } - } - - return level; - }, - - _getChildLevels: function(parent, depth) { - var self = this, - o = this.options, - result = 0; - depth = depth || 0; - - $(parent).children(o.listType).children(o.items).each(function(index, child) { - result = Math.max(self._getChildLevels(child, depth + 1), result); - }); - - return depth ? result + 1 : result; - }, - - _isAllowed: function(parentItem, level, levels) { - var o = this.options, - // this takes into account the maxLevels set to the recipient list - maxLevels = this - .placeholder - .closest(".ui-sortable") - .nestedSortable("option", "maxLevels"), - - // Check if the parent has changed to prevent it, when o.disableParentChange is true - oldParent = this.currentItem.parent().parent(), - disabledByParentchange = o.disableParentChange && ( - //From somewhere to somewhere else, except the root - typeof parentItem !== 'undefined' && !oldParent.is(parentItem) || - typeof parentItem === 'undefined' && oldParent.is("li") //From somewhere to the root - ); - // mjs - is the root protected? - // mjs - are we nesting too deep? - if ( - disabledByParentchange || - !o.isAllowed(this.placeholder, parentItem, this.currentItem) - ) { - this.placeholder.addClass(o.errorClass); - if (maxLevels < levels && maxLevels !== 0) { - this.beyondMaxLevels = levels - maxLevels; - } else { - this.beyondMaxLevels = 1; - } - } else { - if (maxLevels < levels && maxLevels !== 0) { - this.placeholder.addClass(o.errorClass); - this.beyondMaxLevels = levels - maxLevels; - } else { - this.placeholder.removeClass(o.errorClass); - this.beyondMaxLevels = 0; - } - } - } - - })); - - $.mjs.nestedSortable.prototype.options = $.extend( - {}, - $.ui.sortable.prototype.options, - $.mjs.nestedSortable.prototype.options - ); + "use strict"; + + function isOverAxis(x, reference, size) { + return (x > reference) && (x < (reference + size)); + } + + $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, { + + options: { + disableParentChange: false, + doNotClear: false, + expandOnHover: 700, + isAllowed: function() { + return true; + }, + isTree: false, + listType: "ol", + maxLevels: 0, + protectRoot: false, + rootID: null, + rtl: false, + startCollapsed: false, + tabSize: 20, + + branchClass: "mjs-nestedSortable-branch", + collapsedClass: "mjs-nestedSortable-collapsed", + disableNestingClass: "mjs-nestedSortable-no-nesting", + errorClass: "mjs-nestedSortable-error", + expandedClass: "mjs-nestedSortable-expanded", + hoveringClass: "mjs-nestedSortable-hovering", + leafClass: "mjs-nestedSortable-leaf", + disabledClass: "mjs-nestedSortable-disabled" + }, + + _create: function() { + var self = this, + err; + + this.element.data("ui-sortable", this.element.data("mjs-nestedSortable")); + + // mjs - prevent browser from freezing if the HTML is not correct + if (!this.element.is(this.options.listType)) { + err = "nestedSortable: " + + "Please check that the listType option is set to your actual list type"; + + throw new Error(err); + } + + // if we have a tree with expanding/collapsing functionality, + // force 'intersect' tolerance method + if (this.options.isTree && this.options.expandOnHover) { + this.options.tolerance = "intersect"; + } + + $.ui.sortable.prototype._create.apply(this, arguments); + + // prepare the tree by applying the right classes + // (the CSS is responsible for actual hide/show functionality) + if (this.options.isTree) { + $(this.items).each(function() { + var $li = this.item, + hasCollapsedClass = $li.hasClass(self.options.collapsedClass), + hasExpandedClass = $li.hasClass(self.options.expandedClass); + + if ($li.children(self.options.listType).length) { + $li.addClass(self.options.branchClass); + // expand/collapse class only if they have children + + if (!hasCollapsedClass && !hasExpandedClass) { + if (self.options.startCollapsed) { + $li.addClass(self.options.collapsedClass); + } else { + $li.addClass(self.options.expandedClass); + } + } + } else { + $li.addClass(self.options.leafClass); + } + }); + } + }, + + _destroy: function() { + this.element + .removeData("mjs-nestedSortable") + .removeData("ui-sortable"); + return $.ui.sortable.prototype._destroy.apply(this, arguments); + }, + + _mouseDrag: function(event) { + var i, + item, + itemElement, + intersection, + self = this, + o = this.options, + scrolled = false, + $document = $(document), + previousTopOffset, + parentItem, + level, + childLevels, + itemAfter, + itemBefore, + newList, + method, + a, + previousItem, + nextItem, + helperIsNotSibling; + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if (this.options.scroll) { + if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { + + if ( + ( + this.overflowOffset.top + + this.scrollParent[0].offsetHeight + ) - + event.pageY < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollTop() + o.scrollSpeed; + this.scrollParent.scrollTop(scrolled); + } else if ( + event.pageY - + this.overflowOffset.top < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollTop() - o.scrollSpeed; + this.scrollParent.scrollTop(scrolled); + } + + if ( + ( + this.overflowOffset.left + + this.scrollParent[0].offsetWidth + ) - + event.pageX < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed; + this.scrollParent.scrollLeft(scrolled); + } else if ( + event.pageX - + this.overflowOffset.left < + o.scrollSensitivity + ) { + scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed; + this.scrollParent.scrollLeft(scrolled); + } + + } else { + + if ( + event.pageY - + $document.scrollTop() < + o.scrollSensitivity + ) { + scrolled = $document.scrollTop() - o.scrollSpeed; + $document.scrollTop(scrolled); + } else if ( + $(window).height() - + ( + event.pageY - + $document.scrollTop() + ) < + o.scrollSensitivity + ) { + scrolled = $document.scrollTop() + o.scrollSpeed; + $document.scrollTop(scrolled); + } + + if ( + event.pageX - + $document.scrollLeft() < + o.scrollSensitivity + ) { + scrolled = $document.scrollLeft() - o.scrollSpeed; + $document.scrollLeft(scrolled); + } else if ( + $(window).width() - + ( + event.pageX - + $document.scrollLeft() + ) < + o.scrollSensitivity + ) { + scrolled = $document.scrollLeft() + o.scrollSpeed; + $document.scrollLeft(scrolled); + } + + } + + if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { + $.ui.ddmanager.prepareOffsets(this, event); + } + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + // mjs - find the top offset before rearrangement, + previousTopOffset = this.placeholder.offset().top; + + //Set the helper position + if (!this.options.axis || this.options.axis !== "y") { + this.helper[0].style.left = this.position.left + "px"; + } + if (!this.options.axis || this.options.axis !== "x") { + this.helper[0].style.top = (this.position.top) + "px"; + } + + // mjs - check and reset hovering state at each cycle + this.hovering = this.hovering ? this.hovering : null; + this.mouseentered = this.mouseentered ? this.mouseentered : false; + + // mjs - let's start caching some variables + (function() { + var _parentItem = this.placeholder.parent().parent(); + if (_parentItem && _parentItem.closest(".ui-sortable").length) { + parentItem = _parentItem; + } + }.call(this)); + + level = this._getLevel(this.placeholder); + childLevels = this._getChildLevels(this.helper); + newList = document.createElement(o.listType); + + //Rearrange + for (i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + item = this.items[i]; + itemElement = item.item[0]; + intersection = this._intersectsWithPointer(item); + if (!intersection) { + continue; + } + + // Only put the placeholder inside the current Container, skip all + // items form other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this moving items in "sub-sortables" can cause the placeholder to jitter + // beetween the outer and inner container. + if (item.instance !== this.currentContainer) { + continue; + } + + // No action if intersected item is disabled + // and the element above or below in the direction we're going is also disabled + if (itemElement.className.indexOf(o.disabledClass) !== -1) { + // Note: intersection hardcoded direction values from + // jquery.ui.sortable.js:_intersectsWithPointer + if (intersection === 2) { + // Going down + itemAfter = this.items[i + 1]; + if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) { + continue; + } + + } else if (intersection === 1) { + // Going up + itemBefore = this.items[i - 1]; + if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) { + continue; + } + } + } + + method = intersection === 1 ? "next" : "prev"; + + // cannot intersect with itself + // no useless actions that have been done before + // no action if the item moved is the parent of the item checked + if (itemElement !== this.currentItem[0] && + this.placeholder[method]()[0] !== itemElement && + !$.contains(this.placeholder[0], itemElement) && + ( + this.options.type === "semi-dynamic" ? + !$.contains(this.element[0], itemElement) : + true + ) + ) { + + // mjs - we are intersecting an element: + // trigger the mouseenter event and store this state + if (!this.mouseentered) { + $(itemElement).mouseenter(); + this.mouseentered = true; + } + + // mjs - if the element has children and they are hidden, + // show them after a delay (CSS responsible) + if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) { + if (!this.hovering) { + $(itemElement).addClass(o.hoveringClass); + this.hovering = window.setTimeout(function() { + $(itemElement) + .removeClass(o.collapsedClass) + .addClass(o.expandedClass); + + self.refreshPositions(); + self._trigger("expand", event, self._uiHash()); + }, o.expandOnHover); + } + } + + this.direction = intersection === 1 ? "down" : "up"; + + // mjs - rearrange the elements and reset timeouts and hovering state + if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { + $(itemElement).mouseleave(); + this.mouseentered = false; + $(itemElement).removeClass(o.hoveringClass); + if (this.hovering) { + window.clearTimeout(this.hovering); + } + this.hovering = null; + + // mjs - do not switch container if + // it's a root item and 'protectRoot' is true + // or if it's not a root item but we are trying to make it root + if (o.protectRoot && + !( + this.currentItem[0].parentNode === this.element[0] && + // it's a root item + itemElement.parentNode !== this.element[0] + // it's intersecting a non-root item + ) + ) { + if (this.currentItem[0].parentNode !== this.element[0] && + itemElement.parentNode === this.element[0] + ) { + + if (!$(itemElement).children(o.listType).length) { + itemElement.appendChild(newList); + if (o.isTree) { + $(itemElement) + .removeClass(o.leafClass) + .addClass(o.branchClass + " " + o.expandedClass); + } + } + + if (this.direction === "down") { + a = $(itemElement).prev().children(o.listType); + } else { + a = $(itemElement).children(o.listType); + } + + if (a[0] !== undefined) { + this._rearrange(event, null, a); + } + + } else { + this._rearrange(event, item); + } + } else if (!o.protectRoot) { + this._rearrange(event, item); + } + } else { + break; + } + + // Clear emtpy ul's/ol's + this._clearEmpty(itemElement); + + this._trigger("change", event, this._uiHash()); + break; + } + } + + // mjs - to find the previous sibling in the list, + // keep backtracking until we hit a valid list item. + (function() { + var _previousItem = this.placeholder.prev(); + if (_previousItem.length) { + previousItem = _previousItem; + } else { + previousItem = null; + } + }.call(this)); + + if (previousItem != null) { + while ( + previousItem[0].nodeName.toLowerCase() !== "li" || + previousItem[0].className.indexOf(o.disabledClass) !== -1 || + previousItem[0] === this.currentItem[0] || + previousItem[0] === this.helper[0] + ) { + if (previousItem[0].previousSibling) { + previousItem = $(previousItem[0].previousSibling); + } else { + previousItem = null; + break; + } + } + } + + // mjs - to find the next sibling in the list, + // keep stepping forward until we hit a valid list item. + (function() { + var _nextItem = this.placeholder.next(); + if (_nextItem.length) { + nextItem = _nextItem; + } else { + nextItem = null; + } + }.call(this)); + + if (nextItem != null) { + while ( + nextItem[0].nodeName.toLowerCase() !== "li" || + nextItem[0].className.indexOf(o.disabledClass) !== -1 || + nextItem[0] === this.currentItem[0] || + nextItem[0] === this.helper[0] + ) { + if (nextItem[0].nextSibling) { + nextItem = $(nextItem[0].nextSibling); + } else { + nextItem = null; + break; + } + } + } + + this.beyondMaxLevels = 0; + + // mjs - if the item is moved to the left, send it one level up + // but only if it's at the bottom of the list + if (parentItem != null && + nextItem == null && + !(o.protectRoot && parentItem[0].parentNode == this.element[0]) && + ( + o.rtl && + ( + this.positionAbs.left + + this.helper.outerWidth() > parentItem.offset().left + + parentItem.outerWidth() + ) || + !o.rtl && (this.positionAbs.left < parentItem.offset().left) + ) + ) { + + parentItem.after(this.placeholder[0]); + helperIsNotSibling = !parentItem + .children(o.listItem) + .children("li:visible:not(.ui-sortable-helper)") + .length; + if (o.isTree && helperIsNotSibling) { + parentItem + .removeClass(this.options.branchClass + " " + this.options.expandedClass) + .addClass(this.options.leafClass); + } + if (typeof parentItem !== 'undefined') + this._clearEmpty(parentItem[0]); + this._trigger("change", event, this._uiHash()); + // mjs - if the item is below a sibling and is moved to the right, + // make it a child of that sibling + } else if (previousItem != null && + !previousItem.hasClass(o.disableNestingClass) && + ( + previousItem.children(o.listType).length && + previousItem.children(o.listType).is(":visible") || + !previousItem.children(o.listType).length + ) && + !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) && + ( + o.rtl && + ( + this.positionAbs.left + + this.helper.outerWidth() < + previousItem.offset().left + + previousItem.outerWidth() - + o.tabSize + ) || + !o.rtl && + (this.positionAbs.left > previousItem.offset().left + o.tabSize) + ) + ) { + + this._isAllowed(previousItem, level, level + childLevels + 1); + + if (!previousItem.children(o.listType).length) { + previousItem[0].appendChild(newList); + if (o.isTree) { + previousItem + .removeClass(o.leafClass) + .addClass(o.branchClass + " " + o.expandedClass); + } + } + + // mjs - if this item is being moved from the top, add it to the top of the list. + if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) { + previousItem.children(o.listType).prepend(this.placeholder); + } else { + // mjs - otherwise, add it to the bottom of the list. + previousItem.children(o.listType)[0].appendChild(this.placeholder[0]); + } + if (typeof parentItem !== 'undefined') + this._clearEmpty(parentItem[0]); + this._trigger("change", event, this._uiHash()); + } else { + this._isAllowed(parentItem, level, level + childLevels); + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if ($.ui.ddmanager) { + $.ui.ddmanager.drag(this, event); + } + + //Call callbacks + this._trigger("sort", event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event) { + // mjs - if the item is in a position not allowed, send it back + if (this.beyondMaxLevels) { + + this.placeholder.removeClass(this.options.errorClass); + + if (this.domPosition.prev) { + $(this.domPosition.prev).after(this.placeholder); + } else { + $(this.domPosition.parent).prepend(this.placeholder); + } + + this._trigger("revert", event, this._uiHash()); + + } + + // mjs - clear the hovering timeout, just to be sure + $("." + this.options.hoveringClass) + .mouseleave() + .removeClass(this.options.hoveringClass); + + this.mouseentered = false; + if (this.hovering) { + window.clearTimeout(this.hovering); + } + this.hovering = null; + + this._relocate_event = event; + this._pid_current = $(this.domPosition.parent).parent().attr("id"); + this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0; + $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event. + }, + + // mjs - this function is slightly modified + // to make it easier to hover over a collapsed element and have it expand + _intersectsWithSides: function(item) { + + var half = this.options.isTree ? .8 : .5, + isOverBottomHalf = isOverAxis( + this.positionAbs.top + this.offset.click.top, + item.top + (item.height * half), + item.height + ), + isOverTopHalf = isOverAxis( + this.positionAbs.top + this.offset.click.top, + item.top - (item.height * half), + item.height + ), + isOverRightHalf = isOverAxis( + this.positionAbs.left + this.offset.click.left, + item.left + (item.width / 2), + item.width + ), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ( + (horizontalDirection === "right" && isOverRightHalf) || + (horizontalDirection === "left" && !isOverRightHalf) + ); + } else { + return verticalDirection && ( + (verticalDirection === "down" && isOverBottomHalf) || + (verticalDirection === "up" && isOverTopHalf) + ); + } + + }, + + _contactContainers: function() { + + if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0]) { + return; + } + + $.ui.sortable.prototype._contactContainers.apply(this, arguments); + + }, + + _clear: function() { + var i, + item; + + $.ui.sortable.prototype._clear.apply(this, arguments); + + //relocate event + if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") && + this._sort_current === this._uiHash().item.index())) { + this._trigger("relocate", this._relocate_event, this._uiHash()); + } + + // mjs - clean last empty ul/ol + for (i = this.items.length - 1; i >= 0; i--) { + item = this.items[i].item[0]; + this._clearEmpty(item); + } + + }, + + serialize: function(options) { + + var o = $.extend({}, this.options, options), + items = this._getItemsAsjQuery(o && o.connected), + str = []; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || "id") || "") + .match(o.expression || (/(.+)[-=_](.+)/)), + pid = ($(o.item || this).parent(o.listType) + .parent(o.items) + .attr(o.attribute || "id") || "") + .match(o.expression || (/(.+)[-=_](.+)/)); + + if (res) { + str.push( + ( + (o.key || res[1]) + + "[" + + (o.key && o.expression ? res[1] : res[2]) + "]" + ) + + "=" + + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID)); + } + }); + + if (!str.length && o.key) { + str.push(o.key + "="); + } + + return str.join("&"); + + }, + + toHierarchy: function(options) { + + var o = $.extend({}, this.options, options), + ret = []; + + $(this.element).children(o.items).each(function() { + var level = _recursiveItems(this); + ret.push(level); + }); + + return ret; + + function _recursiveItems(item) { + var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)), + currentItem; + + var data = $(item).data(); + if (data.nestedSortableItem) { + delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data + } + + if (id) { + currentItem = { + "id": id[2] + }; + + currentItem = $.extend({}, currentItem, data); // Combine the two objects + + if ($(item).children(o.listType).children(o.items).length > 0) { + currentItem.children = []; + $(item).children(o.listType).children(o.items).each(function() { + var level = _recursiveItems(this); + currentItem.children.push(level); + }); + } + return currentItem; + } + } + }, + + toArray: function(options) { + + var o = $.extend({}, this.options, options), + sDepth = o.startDepthCount || 0, + ret = [], + left = 1; + + if (!o.excludeRoot) { + ret.push({ + "item_id": o.rootID, + "parent_id": null, + "depth": sDepth, + "left": left, + "right": ($(o.items, this.element).length + 1) * 2 + }); + left++; + } + + $(this.element).children(o.items).each(function() { + left = _recursiveArray(this, sDepth, left); + }); + + ret = ret.sort(function(a, b) { + return (a.left - b.left); + }); + + return ret; + + function _recursiveArray(item, depth, _left) { + + var right = _left + 1, + id, + pid, + parentItem; + + if ($(item).children(o.listType).children(o.items).length > 0) { + depth++; + $(item).children(o.listType).children(o.items).each(function() { + right = _recursiveArray($(this), depth, right); + }); + depth--; + } + + id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)); + + if (depth === sDepth) { + pid = o.rootID; + } else { + parentItem = ($(item).parent(o.listType) + .parent(o.items) + .attr(o.attribute || "id")) + .match(o.expression || (/(.+)[-=_](.+)/)); + pid = parentItem[2]; + } + + if (id) { + var data = $(item).children('div').data(); + var itemObj = $.extend(data, { + "id": id[2], + "parent_id": pid, + "depth": depth, + "left": _left, + "right": right + }); + ret.push(itemObj); + } + + _left = right + 1; + return _left; + } + + }, + + _clearEmpty: function(item) { + function replaceClass(elem, search, replace, swap) { + if (swap) { + search = [replace, replace = search][0]; + } + + $(elem).removeClass(search).addClass(replace); + } + + var o = this.options, + childrenList = $(item).children(o.listType), + hasChildren = childrenList.has('li').length; + + var doNotClear = + o.doNotClear || + hasChildren || + o.protectRoot && $(item)[0] === this.element[0]; + + if (o.isTree) { + replaceClass(item, o.branchClass, o.leafClass, doNotClear); + } + + if (!doNotClear) { + childrenList.parent().removeClass(o.expandedClass); + childrenList.remove(); + } + }, + + _getLevel: function(item) { + + var level = 1, + list; + + if (this.options.listType) { + list = item.closest(this.options.listType); + while (list && list.length > 0 && !list.is(".ui-sortable")) { + level++; + list = list.parent().closest(this.options.listType); + } + } + + return level; + }, + + _getChildLevels: function(parent, depth) { + var self = this, + o = this.options, + result = 0; + depth = depth || 0; + + $(parent).children(o.listType).children(o.items).each(function(index, child) { + result = Math.max(self._getChildLevels(child, depth + 1), result); + }); + + return depth ? result + 1 : result; + }, + + _isAllowed: function(parentItem, level, levels) { + var o = this.options, + // this takes into account the maxLevels set to the recipient list + maxLevels = this + .placeholder + .closest(".ui-sortable") + .nestedSortable("option", "maxLevels"), + + // Check if the parent has changed to prevent it, when o.disableParentChange is true + oldParent = this.currentItem.parent().parent(), + disabledByParentchange = o.disableParentChange && ( + //From somewhere to somewhere else, except the root + typeof parentItem !== 'undefined' && !oldParent.is(parentItem) || + typeof parentItem === 'undefined' && oldParent.is("li") //From somewhere to the root + ); + // mjs - is the root protected? + // mjs - are we nesting too deep? + if ( + disabledByParentchange || + !o.isAllowed(this.placeholder, parentItem, this.currentItem) + ) { + this.placeholder.addClass(o.errorClass); + if (maxLevels < levels && maxLevels !== 0) { + this.beyondMaxLevels = levels - maxLevels; + } else { + this.beyondMaxLevels = 1; + } + } else { + if (maxLevels < levels && maxLevels !== 0) { + this.placeholder.addClass(o.errorClass); + this.beyondMaxLevels = levels - maxLevels; + } else { + this.placeholder.removeClass(o.errorClass); + this.beyondMaxLevels = 0; + } + } + } + + })); + + $.mjs.nestedSortable.prototype.options = $.extend( + {}, + $.ui.sortable.prototype.options, + $.mjs.nestedSortable.prototype.options + ); })); diff --git a/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js index 7ad63b57787f9a2804e59a49d1285d9a4c23498e..02c0ac543ca2527fe86fa071bf4a50ff02678b6b 100644 --- a/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js +++ b/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js @@ -17,40 +17,40 @@ * JavaScript to handle import/export actions from context menu * @exports TYPO3/CMS/Impexp/ContextMenuActions */ -define(function () { - 'use strict'; +define(function() { + 'use strict'; - /** - * @exports TYPO3/CMS/Impexp/ContextMenuActions - */ - var ContextMenuActions = {}; + /** + * @exports TYPO3/CMS/Impexp/ContextMenuActions + */ + var ContextMenuActions = {}; - ContextMenuActions.exportT3d = function (table, uid) { - if (table === 'pages') { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.ImportExport.moduleUrl + - '&tx_impexp[action]=export&' + - 'id=0&tx_impexp[pagetree][id]=' + uid + - '&tx_impexp[pagetree][levels]=0' + - '&tx_impexp[pagetree][tables][]=_ALL' - ); - } else { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.ImportExport.moduleUrl + - '&tx_impexp[action]=export' + - '&tx_impexp[record][]=' + table + ':' + uid + - '&tx_impexp[external_ref][tables][]=_ALL' - ); - } - }; + ContextMenuActions.exportT3d = function(table, uid) { + if (table === 'pages') { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.ImportExport.moduleUrl + + '&tx_impexp[action]=export&' + + 'id=0&tx_impexp[pagetree][id]=' + uid + + '&tx_impexp[pagetree][levels]=0' + + '&tx_impexp[pagetree][tables][]=_ALL' + ); + } else { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.ImportExport.moduleUrl + + '&tx_impexp[action]=export' + + '&tx_impexp[record][]=' + table + ':' + uid + + '&tx_impexp[external_ref][tables][]=_ALL' + ); + } + }; - ContextMenuActions.importT3d = function (table, uid) { - top.TYPO3.Backend.ContentContainer.setUrl( - top.TYPO3.settings.ImportExport.moduleUrl + - '&id=' + uid + - '&table=' + table + '&tx_impexp[action]=import' - ); - }; + ContextMenuActions.importT3d = function(table, uid) { + top.TYPO3.Backend.ContentContainer.setUrl( + top.TYPO3.settings.ImportExport.moduleUrl + + '&id=' + uid + + '&table=' + table + '&tx_impexp[action]=import' + ); + }; - return ContextMenuActions; + return ContextMenuActions; }); diff --git a/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js b/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js index 7dba828d44acc654f9acfc0145e53c3462c1c6f9..a1643a063dd0b165f791c5550f63f4e35983a3a2 100644 --- a/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js +++ b/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js @@ -16,29 +16,29 @@ * JavaScript to handle confirm windows in the Import/Export module * @exports TYPO3/CMS/Impexp/ImportExport */ -define(['jquery', 'TYPO3/CMS/Backend/Modal'], function ($, Modal) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Backend/Modal'], function($, Modal) { + 'use strict'; - $(function() { - $(document).on('click', '.t3js-confirm-trigger', function() { - var $button = $(this); - Modal.confirm($button.data('title'), $button.data('message')) - .on('confirm.button.ok', function() { - $('#t3js-submit-field') - .attr('name', $button.attr('name')) - .closest('form').submit(); - Modal.currentModal.trigger('modal-dismiss'); - }) - .on('confirm.button.cancel', function() { - Modal.currentModal.trigger('modal-dismiss'); - }); - }); + $(function() { + $(document).on('click', '.t3js-confirm-trigger', function() { + var $button = $(this); + Modal.confirm($button.data('title'), $button.data('message')) + .on('confirm.button.ok', function() { + $('#t3js-submit-field') + .attr('name', $button.attr('name')) + .closest('form').submit(); + Modal.currentModal.trigger('modal-dismiss'); + }) + .on('confirm.button.cancel', function() { + Modal.currentModal.trigger('modal-dismiss'); + }); + }); - $('.t3js-impexp-toggledisabled').on('click', function() { - var $checkboxes = $('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox'); - if ($checkboxes.length) { - $checkboxes.prop('checked', !$checkboxes.get(0).checked); - } - }); - }); + $('.t3js-impexp-toggledisabled').on('click', function() { + var $checkboxes = $('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox'); + if ($checkboxes.length) { + $checkboxes.prop('checked', !$checkboxes.get(0).checked); + } + }); + }); }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Install.js b/typo3/sysext/install/Resources/Public/JavaScript/Install.js index 0b96aad1608d77ee91c1de487ca8258fe6202688..2dc48c2203f79accc442ad76aaee874b92113911 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Install.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Install.js @@ -12,12 +12,12 @@ */ require([ - 'jquery', - 'TYPO3/CMS/Install/Router' + 'jquery', + 'TYPO3/CMS/Install/Router' ], function($, Router) { - 'use strict'; + 'use strict'; - $(function() { - Router.initialize(); - }); + $(function() { + Router.initialize(); + }); }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Installer.js b/typo3/sysext/install/Resources/Public/JavaScript/Installer.js index 3213fe76b4f7ebaa78bee279885577afbcc3a72e..e5cdaf00fc63e07e5ecb2ad91a8179f99aaedf7f 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Installer.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Installer.js @@ -15,464 +15,464 @@ * Walk through the installation process of TYPO3 */ require([ - 'jquery', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/PasswordStrength' + 'jquery', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/PasswordStrength' ], function($, InfoBox, Severity, ProgressBar, PasswordStrength) { - 'use strict'; + 'use strict'; - $(function() { - Installer.initialize(); - }); + $(function() { + Installer.initialize(); + }); - var Installer = { - selectorBody: '.t3js-body', - selectorMainContent: '.t3js-installer-content', - selectorProgressBar: '.t3js-installer-progress', - selectorExecuteDatabaseConnectToken: '#t3js-installer-databaseConnect-execute-token', - selectorExecuteDatabaseSelectToken: '#t3js-installer-databaseSelect-execute-token', - selectorExecuteDatabaseDataToken: '#t3js-installer-databaseData-execute-token', - selectorExecuteDefaultConfigurationToken: '#t3js-installer-defaultConfiguration-execute-token', - selectorDatabaseConnectOutput: '.t3js-installer-databaseConnect-output', - selectorDatabaseSelectOutput: '.t3js-installer-databaseSelect-output', - selectorDatabaseDataOutput: '.t3js-installer-databaseData-output', - selectorDefaultConfigurationOutput: '.t3js-installer-defaultConfiguration-output', + var Installer = { + selectorBody: '.t3js-body', + selectorMainContent: '.t3js-installer-content', + selectorProgressBar: '.t3js-installer-progress', + selectorExecuteDatabaseConnectToken: '#t3js-installer-databaseConnect-execute-token', + selectorExecuteDatabaseSelectToken: '#t3js-installer-databaseSelect-execute-token', + selectorExecuteDatabaseDataToken: '#t3js-installer-databaseData-execute-token', + selectorExecuteDefaultConfigurationToken: '#t3js-installer-defaultConfiguration-execute-token', + selectorDatabaseConnectOutput: '.t3js-installer-databaseConnect-output', + selectorDatabaseSelectOutput: '.t3js-installer-databaseSelect-output', + selectorDatabaseDataOutput: '.t3js-installer-databaseData-output', + selectorDefaultConfigurationOutput: '.t3js-installer-defaultConfiguration-output', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - $(document).on('click', '.t3js-installer-environmentFolders-retry', function(e) { - e.preventDefault(); - self.showEnvironmentAndFolders(); - }); - $(document).on('click', '.t3js-installer-environmentFolders-execute', function(e) { - e.preventDefault(); - self.executeEnvironmentAndFolders(); - }); - $(document).on('click', '.t3js-installer-databaseConnect-execute', function(e) { - e.preventDefault(); - self.executeDatabaseConnect(); - }); - $(document).on('click', '.t3js-installer-databaseSelect-execute', function(e) { - e.preventDefault(); - self.executeDatabaseSelect(); - }); - $(document).on('click', '.t3js-installer-databaseData-execute', function(e) { - e.preventDefault(); - self.executeDatabaseData(); - }); - $(document).on('click', '.t3js-installer-defaultConfiguration-execute', function(e) { - e.preventDefault(); - self.executeDefaultConfiguration(); - }); + $(document).on('click', '.t3js-installer-environmentFolders-retry', function(e) { + e.preventDefault(); + self.showEnvironmentAndFolders(); + }); + $(document).on('click', '.t3js-installer-environmentFolders-execute', function(e) { + e.preventDefault(); + self.executeEnvironmentAndFolders(); + }); + $(document).on('click', '.t3js-installer-databaseConnect-execute', function(e) { + e.preventDefault(); + self.executeDatabaseConnect(); + }); + $(document).on('click', '.t3js-installer-databaseSelect-execute', function(e) { + e.preventDefault(); + self.executeDatabaseSelect(); + }); + $(document).on('click', '.t3js-installer-databaseData-execute', function(e) { + e.preventDefault(); + self.executeDatabaseData(); + }); + $(document).on('click', '.t3js-installer-defaultConfiguration-execute', function(e) { + e.preventDefault(); + self.executeDefaultConfiguration(); + }); - $(document).on('keyup', '.t3-install-form-password-strength', function() { - PasswordStrength.initialize('.t3-install-form-password-strength'); - }); + $(document).on('keyup', '.t3-install-form-password-strength', function() { + PasswordStrength.initialize('.t3-install-form-password-strength'); + }); - // Database connect db driver selection - $(document).on('change', '#t3js-connect-database-driver', function() { - var driver = $(this).val(); - $('.t3-install-driver-data').hide(); - $('.t3-install-driver-data input').attr('disabled', 'disabled'); - $('#' + driver + ' input').attr('disabled', false); - $('#' + driver).show(); - }); + // Database connect db driver selection + $(document).on('change', '#t3js-connect-database-driver', function() { + var driver = $(this).val(); + $('.t3-install-driver-data').hide(); + $('.t3-install-driver-data input').attr('disabled', 'disabled'); + $('#' + driver + ' input').attr('disabled', false); + $('#' + driver).show(); + }); - this.setProgress(0); - this.getMainLayout(); - }, + this.setProgress(0); + this.getMainLayout(); + }, - getUrl: function(action) { - var url = location.href; - url = url.replace(location.search, ''); - if (action !== undefined) { - url = url + '?install[action]=' + action; - } - return url; - }, + getUrl: function(action) { + var url = location.href; + url = url.replace(location.search, ''); + if (action !== undefined) { + url = url + '?install[action]=' + action; + } + return url; + }, - setProgress: function(done) { - var $progressBar = $(this.selectorProgressBar); - var percent = 0; - if (done !== 0) { - percent = (done / 5) * 100; - $progressBar.find('.progress-bar').empty().text(done + ' / 5 - ' + percent + '% Complete'); - } - $progressBar - .find('.progress-bar') - .css('width', percent + '%') - .attr('aria-valuenow', percent); - }, + setProgress: function(done) { + var $progressBar = $(this.selectorProgressBar); + var percent = 0; + if (done !== 0) { + percent = (done / 5) * 100; + $progressBar.find('.progress-bar').empty().text(done + ' / 5 - ' + percent + '% Complete'); + } + $progressBar + .find('.progress-bar') + .css('width', percent + '%') + .attr('aria-valuenow', percent); + }, - getMainLayout: function() { - var self = this; - $.ajax({ - url: this.getUrl('mainLayout'), - cache: false, - success: function(data) { - $(self.selectorBody).empty().append(data.html); - self.checkInstallerAvailable(); - } - }) - }, + getMainLayout: function() { + var self = this; + $.ajax({ + url: this.getUrl('mainLayout'), + cache: false, + success: function(data) { + $(self.selectorBody).empty().append(data.html); + self.checkInstallerAvailable(); + } + }) + }, - checkInstallerAvailable: function() { - var self = this; - $.ajax({ - url: this.getUrl('checkInstallerAvailable'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkEnvironmentAndFolders(); - } else { - self.showInstallerNotAvailable(); - } - } - }); - }, + checkInstallerAvailable: function() { + var self = this; + $.ajax({ + url: this.getUrl('checkInstallerAvailable'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkEnvironmentAndFolders(); + } else { + self.showInstallerNotAvailable(); + } + } + }); + }, - showInstallerNotAvailable: function() { - var $outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('showInstallerNotAvailable'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().append(data.html); - } - } - }); - }, + showInstallerNotAvailable: function() { + var $outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('showInstallerNotAvailable'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().append(data.html); + } + } + }); + }, - checkEnvironmentAndFolders: function() { - var self = this; - this.setProgress(1); - $.ajax({ - url: this.getUrl('checkEnvironmentAndFolders'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkTrustedHostsPattern(); - } else { - self.showEnvironmentAndFolders(); - } - } - }); - }, + checkEnvironmentAndFolders: function() { + var self = this; + this.setProgress(1); + $.ajax({ + url: this.getUrl('checkEnvironmentAndFolders'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkTrustedHostsPattern(); + } else { + self.showEnvironmentAndFolders(); + } + } + }); + }, - showEnvironmentAndFolders: function() { - var $outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('showEnvironmentAndFolders'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().html(data.html); - var $detailContainer = $('.t3js-installer-environment-details'); - var hasMessage = false; - if (Array.isArray(data.environmentStatusErrors)) { - data.environmentStatusErrors.forEach(function(element) { - hasMessage = true; - var message = InfoBox.render(element.severity, element.title, element.message); - $detailContainer.append(message); - }); - } - if (Array.isArray(data.environmentStatusWarnings)) { - data.environmentStatusWarnings.forEach(function(element) { - hasMessage = true; - var message = InfoBox.render(element.severity, element.title, element.message); - $detailContainer.append(message); - }); - } - if (Array.isArray(data.structureErrors)) { - data.structureErrors.forEach(function(element) { - hasMessage = true; - var message = InfoBox.render(element.severity, element.title, element.message); - $detailContainer.append(message); - }); - } - if (hasMessage === true) { - $detailContainer.show(); - $('.t3js-installer-environmentFolders-bad').show(); - } else { - $('.t3js-installer-environmentFolders-good').show(); - } - } - } - }); - }, + showEnvironmentAndFolders: function() { + var $outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('showEnvironmentAndFolders'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().html(data.html); + var $detailContainer = $('.t3js-installer-environment-details'); + var hasMessage = false; + if (Array.isArray(data.environmentStatusErrors)) { + data.environmentStatusErrors.forEach(function(element) { + hasMessage = true; + var message = InfoBox.render(element.severity, element.title, element.message); + $detailContainer.append(message); + }); + } + if (Array.isArray(data.environmentStatusWarnings)) { + data.environmentStatusWarnings.forEach(function(element) { + hasMessage = true; + var message = InfoBox.render(element.severity, element.title, element.message); + $detailContainer.append(message); + }); + } + if (Array.isArray(data.structureErrors)) { + data.structureErrors.forEach(function(element) { + hasMessage = true; + var message = InfoBox.render(element.severity, element.title, element.message); + $detailContainer.append(message); + }); + } + if (hasMessage === true) { + $detailContainer.show(); + $('.t3js-installer-environmentFolders-bad').show(); + } else { + $('.t3js-installer-environmentFolders-good').show(); + } + } + } + }); + }, - executeEnvironmentAndFolders: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeEnvironmentAndFolders'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkTrustedHostsPattern(); - } else { - // @todo message output handling - } - } - }); - }, + executeEnvironmentAndFolders: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeEnvironmentAndFolders'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkTrustedHostsPattern(); + } else { + // @todo message output handling + } + } + }); + }, - checkTrustedHostsPattern: function() { - var self = this; - $.ajax({ - url: this.getUrl('checkTrustedHostsPattern'), - cache: false, - success: function(data) { - if (data.success === true) { - self.executeSilentConfigurationUpdate(); - } else { - self.executeAdjustTrustedHostsPattern(); - } - } - }); - }, + checkTrustedHostsPattern: function() { + var self = this; + $.ajax({ + url: this.getUrl('checkTrustedHostsPattern'), + cache: false, + success: function(data) { + if (data.success === true) { + self.executeSilentConfigurationUpdate(); + } else { + self.executeAdjustTrustedHostsPattern(); + } + } + }); + }, - executeAdjustTrustedHostsPattern: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeAdjustTrustedHostsPattern'), - cache: false, - success: function(data) { - self.executeSilentConfigurationUpdate(); - } - }); - }, + executeAdjustTrustedHostsPattern: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeAdjustTrustedHostsPattern'), + cache: false, + success: function(data) { + self.executeSilentConfigurationUpdate(); + } + }); + }, - executeSilentConfigurationUpdate: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeSilentConfigurationUpdate'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkDatabaseConnect(); - } else { - self.executeSilentConfigurationUpdate(); - } - } - }); - }, + executeSilentConfigurationUpdate: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeSilentConfigurationUpdate'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkDatabaseConnect(); + } else { + self.executeSilentConfigurationUpdate(); + } + } + }); + }, - checkDatabaseConnect: function() { - this.setProgress(2); - var self = this; - $.ajax({ - url: this.getUrl('checkDatabaseConnect'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkDatabaseSelect(); - } else { - self.showDatabaseConnect(); - } - } - }); - }, + checkDatabaseConnect: function() { + this.setProgress(2); + var self = this; + $.ajax({ + url: this.getUrl('checkDatabaseConnect'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkDatabaseSelect(); + } else { + self.showDatabaseConnect(); + } + } + }); + }, - showDatabaseConnect: function() { - var $outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('showDatabaseConnect'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().html(data.html); - $('#t3js-connect-database-driver').trigger('change'); - } - } - }); - }, + showDatabaseConnect: function() { + var $outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('showDatabaseConnect'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().html(data.html); + $('#t3js-connect-database-driver').trigger('change'); + } + } + }); + }, - executeDatabaseConnect: function() { - var self = this; - var $outputContainer = $(this.selectorDatabaseConnectOutput); - var postData = { - 'install[action]': 'executeDatabaseConnect', - 'install[token]': $(self.selectorExecuteDatabaseConnectToken).text() - }; - $($(this.selectorBody + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - $.ajax({ - url: this.getUrl(), - cache: false, - method: 'POST', - data: postData, - success: function(data) { - if (data.success === true) { - self.checkDatabaseSelect(); - } else { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } - } - } - }); - }, + executeDatabaseConnect: function() { + var self = this; + var $outputContainer = $(this.selectorDatabaseConnectOutput); + var postData = { + 'install[action]': 'executeDatabaseConnect', + 'install[token]': $(self.selectorExecuteDatabaseConnectToken).text() + }; + $($(this.selectorBody + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + $.ajax({ + url: this.getUrl(), + cache: false, + method: 'POST', + data: postData, + success: function(data) { + if (data.success === true) { + self.checkDatabaseSelect(); + } else { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + } + } + }); + }, - checkDatabaseSelect: function() { - var self = this; - this.setProgress(3); - $.ajax({ - url: this.getUrl('checkDatabaseSelect'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkDatabaseData(); - } else { - self.showDatabaseSelect(); - } - } - }); - }, + checkDatabaseSelect: function() { + var self = this; + this.setProgress(3); + $.ajax({ + url: this.getUrl('checkDatabaseSelect'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkDatabaseData(); + } else { + self.showDatabaseSelect(); + } + } + }); + }, - showDatabaseSelect: function() { - var $outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('showDatabaseSelect'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().html(data.html); - } - } - }); - }, + showDatabaseSelect: function() { + var $outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('showDatabaseSelect'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().html(data.html); + } + } + }); + }, - executeDatabaseSelect: function() { - var self = this; - var $outputContainer = $(this.selectorDatabaseSelectOutput); - var postData = { - 'install[action]': 'executeDatabaseSelect', - 'install[token]': $(self.selectorExecuteDatabaseSelectToken).text() - }; - $($(this.selectorBody + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - $.ajax({ - url: this.getUrl(), - cache: false, - method: 'POST', - data: postData, - success: function(data) { - if (data.success === true) { - self.checkDatabaseData(); - } else { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } - } - } - }); - }, + executeDatabaseSelect: function() { + var self = this; + var $outputContainer = $(this.selectorDatabaseSelectOutput); + var postData = { + 'install[action]': 'executeDatabaseSelect', + 'install[token]': $(self.selectorExecuteDatabaseSelectToken).text() + }; + $($(this.selectorBody + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + $.ajax({ + url: this.getUrl(), + cache: false, + method: 'POST', + data: postData, + success: function(data) { + if (data.success === true) { + self.checkDatabaseData(); + } else { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + } + } + }); + }, - checkDatabaseData: function() { - var self = this; - this.setProgress(4); - $.ajax({ - url: this.getUrl('checkDatabaseData'), - cache: false, - success: function(data) { - if (data.success === true) { - self.showDefaultConfiguration(); - } else { - self.showDatabaseData(); - } - } - }); - }, + checkDatabaseData: function() { + var self = this; + this.setProgress(4); + $.ajax({ + url: this.getUrl('checkDatabaseData'), + cache: false, + success: function(data) { + if (data.success === true) { + self.showDefaultConfiguration(); + } else { + self.showDatabaseData(); + } + } + }); + }, - showDatabaseData: function() { - var $outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('showDatabaseData'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().html(data.html); - } - } - }); - }, + showDatabaseData: function() { + var $outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('showDatabaseData'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().html(data.html); + } + } + }); + }, - executeDatabaseData: function() { - var self = this; - var $outputContainer = $(this.selectorDatabaseDataOutput); - var postData = { - 'install[action]': 'executeDatabaseData', - 'install[token]': $(self.selectorExecuteDatabaseDataToken).text() - }; - $($(this.selectorBody + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: this.getUrl(), - cache: false, - method: 'POST', - data: postData, - success: function(data) { - if (data.success === true) { - self.showDefaultConfiguration(); - } else { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } - } - } - }); - }, + executeDatabaseData: function() { + var self = this; + var $outputContainer = $(this.selectorDatabaseDataOutput); + var postData = { + 'install[action]': 'executeDatabaseData', + 'install[token]': $(self.selectorExecuteDatabaseDataToken).text() + }; + $($(this.selectorBody + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: this.getUrl(), + cache: false, + method: 'POST', + data: postData, + success: function(data) { + if (data.success === true) { + self.showDefaultConfiguration(); + } else { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + } + } + }); + }, - showDefaultConfiguration: function() { - var $outputContainer = $(this.selectorMainContent); - this.setProgress(5); - $.ajax({ - url: this.getUrl('showDefaultConfiguration'), - cache: false, - success: function(data) { - if (data.success === true) { - $outputContainer.empty().html(data.html); - } - } - }); - }, + showDefaultConfiguration: function() { + var $outputContainer = $(this.selectorMainContent); + this.setProgress(5); + $.ajax({ + url: this.getUrl('showDefaultConfiguration'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.empty().html(data.html); + } + } + }); + }, - executeDefaultConfiguration: function() { - var self = this; - var postData = { - 'install[action]': 'executeDefaultConfiguration', - 'install[token]': $(self.selectorExecuteDefaultConfigurationToken).text() - }; - $($(this.selectorBody + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - $.ajax({ - url: this.getUrl(), - cache: false, - method: 'POST', - data: postData, - success: function(data) { - top.location.href = data.redirect; - } - }); - } - }; + executeDefaultConfiguration: function() { + var self = this; + var postData = { + 'install[action]': 'executeDefaultConfiguration', + 'install[token]': $(self.selectorExecuteDefaultConfigurationToken).text() + }; + $($(this.selectorBody + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + $.ajax({ + url: this.getUrl(), + cache: false, + method: 'POST', + data: postData, + success: function(data) { + top.location.href = data.redirect; + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js index a1c7962b0ed91a3e646d56b8b1ea972f0e986837..0db7111917e5b9dc60c89c35f8e28b11bf0149b9 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js @@ -15,52 +15,52 @@ * Module: TYPO3/CMS/Install/Cache */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorClearTrigger: '.t3js-clearAllCache-clear', - selectorOutputContainer: '.t3js-clearAllCache-output', + return { + selectorClearTrigger: '.t3js-clearAllCache-clear', + selectorOutputContainer: '.t3js-clearAllCache-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorClearTrigger, function(e) { - e.preventDefault(); - self.clearAll(); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorClearTrigger, function(e) { + e.preventDefault(); + self.clearAll(); + }); + }, - clearAll: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, '', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('cacheClearAll', 'maintenance'), - cache: false, - success: function(data) { - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - $outputContainer.empty(); - data.status.forEach((function (element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - })); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + clearAll: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, '', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('cacheClearAll', 'maintenance'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + $outputContainer.empty(); + data.status.forEach((function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + })); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js index c73d3085d711fa14446f8887767d95482dfe7a8d..b5287b80d2d9f217d58ac279bb4a55dd4bd70a80 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js @@ -14,168 +14,168 @@ /** * Module: TYPO3/CMS/Install/CardLayout */ -define(['jquery', 'bootstrap'], function ($) { - 'use strict'; +define(['jquery', 'bootstrap'], function($) { + 'use strict'; - /** - * - * @type {{transitionInProgress: boolean}} - */ - var CardLayout = { - transitionInProgress: false - }; + /** + * + * @type {{transitionInProgress: boolean}} + */ + var CardLayout = { + transitionInProgress: false + }; - /** - * Initialize the CardLayout, bind events - */ - CardLayout.initialize = function() { - $(document).on('click', '.gridder-list', function(e) { - e.preventDefault(); - var $element = $(this); - if (!$element.hasClass('selectedItem')) { - CardLayout.openCard($element); - } else { - CardLayout.closeCard($element); - } - }); + /** + * Initialize the CardLayout, bind events + */ + CardLayout.initialize = function() { + $(document).on('click', '.gridder-list', function(e) { + e.preventDefault(); + var $element = $(this); + if (!$element.hasClass('selectedItem')) { + CardLayout.openCard($element); + } else { + CardLayout.closeCard($element); + } + }); - // Close current and open previous card - $(document).on('click', '.gridder-nav-prev', function(e) { - e.preventDefault(); - CardLayout.openPrevCard(); - }); + // Close current and open previous card + $(document).on('click', '.gridder-nav-prev', function(e) { + e.preventDefault(); + CardLayout.openPrevCard(); + }); - // Close current and open next card - $(document).on('click', '.gridder-nav-next', function(e) { - e.preventDefault(); - CardLayout.openNextCard(); - }); + // Close current and open next card + $(document).on('click', '.gridder-nav-next', function(e) { + e.preventDefault(); + CardLayout.openNextCard(); + }); - // Close current open card - $(document).on('click', '.gridder-close', function(e) { - e.preventDefault(); - CardLayout.closeCurrentCard(); - }); + // Close current open card + $(document).on('click', '.gridder-close', function(e) { + e.preventDefault(); + CardLayout.closeCurrentCard(); + }); - CardLayout.checkNavigationButtons(); - }; + CardLayout.checkNavigationButtons(); + }; - /** - * Find and return the current open card - * - * @returns {jQuery} - */ - CardLayout.getCurrentOpenCard = function() { - return $('.gridder-content.gridder-show').prev(); - }; + /** + * Find and return the current open card + * + * @returns {jQuery} + */ + CardLayout.getCurrentOpenCard = function() { + return $('.gridder-content.gridder-show').prev(); + }; - /** - * Find and close the current open card - */ - CardLayout.closeCurrentCard = function() { - CardLayout.closeCard(CardLayout.getCurrentOpenCard()); - CardLayout.checkNavigationButtons(); - }; + /** + * Find and close the current open card + */ + CardLayout.closeCurrentCard = function() { + CardLayout.closeCard(CardLayout.getCurrentOpenCard()); + CardLayout.checkNavigationButtons(); + }; - /** - * Open the given card and call the callback function - * - * @param {jQuery} $element - * @param {function} callback - * @returns {boolean} - */ - CardLayout.openCard = function($element, callback) { - if (CardLayout.transitionInProgress) { - return false; - } - CardLayout.transitionInProgress = true; - $('.gridder-list').removeClass('selectedItem'); - $('.gridder-content.gridder-show').slideUp(function() { - $(this).removeClass('gridder-show'); - }); - $element.addClass('selectedItem'); - $element.next().addClass('gridder-show').slideDown(function() { - CardLayout.transitionInProgress = false; - if (typeof callback === 'function') { - callback(); - } - CardLayout.checkNavigationButtons(); - }); - $(document).trigger('cardlayout:card-opened', [$element]); - }; + /** + * Open the given card and call the callback function + * + * @param {jQuery} $element + * @param {function} callback + * @returns {boolean} + */ + CardLayout.openCard = function($element, callback) { + if (CardLayout.transitionInProgress) { + return false; + } + CardLayout.transitionInProgress = true; + $('.gridder-list').removeClass('selectedItem'); + $('.gridder-content.gridder-show').slideUp(function() { + $(this).removeClass('gridder-show'); + }); + $element.addClass('selectedItem'); + $element.next().addClass('gridder-show').slideDown(function() { + CardLayout.transitionInProgress = false; + if (typeof callback === 'function') { + callback(); + } + CardLayout.checkNavigationButtons(); + }); + $(document).trigger('cardlayout:card-opened', [$element]); + }; - /** - * Close the given card and call the callback function - * - * @param {jQuery} $element - * @param {function} callback - * @returns {boolean} - */ - CardLayout.closeCard = function($element, callback) { - if (CardLayout.transitionInProgress) { - return false; - } - CardLayout.transitionInProgress = true; - var $contentContainer = $element.next(); - $element.removeClass('selectedItem'); - $contentContainer.slideUp(function() { - $contentContainer.removeClass('gridder-show'); - CardLayout.transitionInProgress = false; - if (typeof callback === 'function') { - callback(); - } - CardLayout.checkNavigationButtons(); - }); - $(document).trigger('cardlayout:card-closed', [$element]); - }; + /** + * Close the given card and call the callback function + * + * @param {jQuery} $element + * @param {function} callback + * @returns {boolean} + */ + CardLayout.closeCard = function($element, callback) { + if (CardLayout.transitionInProgress) { + return false; + } + CardLayout.transitionInProgress = true; + var $contentContainer = $element.next(); + $element.removeClass('selectedItem'); + $contentContainer.slideUp(function() { + $contentContainer.removeClass('gridder-show'); + CardLayout.transitionInProgress = false; + if (typeof callback === 'function') { + callback(); + } + CardLayout.checkNavigationButtons(); + }); + $(document).trigger('cardlayout:card-closed', [$element]); + }; - /** - * Find the next card and open it, if it exists - */ - CardLayout.openNextCard = function() { - var $currentOpenCard = CardLayout.getCurrentOpenCard(); - var $nextCard = $currentOpenCard.next().next(); - if ($nextCard.length) { - CardLayout.closeCard($currentOpenCard, function() { - CardLayout.openCard($nextCard); - }); - } - }; + /** + * Find the next card and open it, if it exists + */ + CardLayout.openNextCard = function() { + var $currentOpenCard = CardLayout.getCurrentOpenCard(); + var $nextCard = $currentOpenCard.next().next(); + if ($nextCard.length) { + CardLayout.closeCard($currentOpenCard, function() { + CardLayout.openCard($nextCard); + }); + } + }; - /** - * Find the previous card and open it, if it exists - */ - CardLayout.openPrevCard = function() { - var $currentOpenCard = CardLayout.getCurrentOpenCard(); - var $nextCard = $currentOpenCard.prev().prev(); - if ($nextCard.length) { - CardLayout.closeCard($currentOpenCard, function() { - CardLayout.openCard($nextCard); - }); - } - }; + /** + * Find the previous card and open it, if it exists + */ + CardLayout.openPrevCard = function() { + var $currentOpenCard = CardLayout.getCurrentOpenCard(); + var $nextCard = $currentOpenCard.prev().prev(); + if ($nextCard.length) { + CardLayout.closeCard($currentOpenCard, function() { + CardLayout.openCard($nextCard); + }); + } + }; - /** - * Check the navigation icons and enable/disable the buttons - */ - CardLayout.checkNavigationButtons = function() { - var $currentOpenCard = CardLayout.getCurrentOpenCard(); - if ($currentOpenCard.length === 0) { - $('.gridder-close').addClass('disabled'); - } else { - $('.gridder-close').removeClass('disabled'); - } - if ($currentOpenCard.prev().prev().length === 0) { - $('.gridder-nav-prev').addClass('disabled'); - } else { - $('.gridder-nav-prev').removeClass('disabled'); - } - if ($currentOpenCard.next().next().length === 0) { - $('.gridder-nav-next').addClass('disabled'); - } else { - $('.gridder-nav-next').removeClass('disabled'); - } - }; + /** + * Check the navigation icons and enable/disable the buttons + */ + CardLayout.checkNavigationButtons = function() { + var $currentOpenCard = CardLayout.getCurrentOpenCard(); + if ($currentOpenCard.length === 0) { + $('.gridder-close').addClass('disabled'); + } else { + $('.gridder-close').removeClass('disabled'); + } + if ($currentOpenCard.prev().prev().length === 0) { + $('.gridder-nav-prev').addClass('disabled'); + } else { + $('.gridder-nav-prev').removeClass('disabled'); + } + if ($currentOpenCard.next().next().length === 0) { + $('.gridder-nav-next').addClass('disabled'); + } else { + $('.gridder-nav-next').removeClass('disabled'); + } + }; - return CardLayout; + return CardLayout; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js index 543ced85901bee7e4ba569601fa35b37703112eb..52c542b3aa7ae5760d72944e98e0073df0d73c69 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js @@ -15,64 +15,64 @@ * Module: TYPO3/CMS/Install/CreateAdmin */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'TYPO3/CMS/Install/PasswordStrength' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'TYPO3/CMS/Install/PasswordStrength' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, PasswordStrength) { - 'use strict'; + 'use strict'; - return { - selectorChangeToken: '#t3js-changeInstallToolPassword-token', - selectorChangeTrigger: '.t3js-changeInstallToolPassword-change', - selectorOutputContainer: '.t3js-changeInstallToolPassword-output', + return { + selectorChangeToken: '#t3js-changeInstallToolPassword-token', + selectorChangeTrigger: '.t3js-changeInstallToolPassword-change', + selectorOutputContainer: '.t3js-changeInstallToolPassword-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorChangeTrigger, function(e) { - e.preventDefault(); - self.change(); - }); - $(document).on('keyup', '.t3-install-form-password-strength', function() { - PasswordStrength.initialize('.t3-install-form-password-strength'); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorChangeTrigger, function(e) { + e.preventDefault(); + self.change(); + }); + $(document).on('keyup', '.t3-install-form-password-strength', function() { + PasswordStrength.initialize('.t3-install-form-password-strength'); + }); + }, - change: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'changeInstallToolPassword', - 'token': $(this.selectorChangeToken).text(), - 'password': $('.t3js-changeInstallToolPassword-password').val(), - 'passwordCheck': $('.t3js-changeInstallToolPassword-password-check').val() - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + change: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'changeInstallToolPassword', + 'token': $(this.selectorChangeToken).text(), + 'password': $('.t3js-changeInstallToolPassword-password').val(), + 'passwordCheck': $('.t3js-changeInstallToolPassword-password-check').val() + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js index 4119181609bd6a68b6eca8ebb47af39496d12f58..faebe82a8b7978f36cfea02dde86c534f6c62495 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js @@ -15,123 +15,123 @@ * Module: TYPO3/CMS/Install/ClearTable */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-clearTables-open', - selectorClearToken: '#t3js-clearTables-clear-token', - selectorClearTrigger: '.t3js-clearTables-clear', - selectorStatsTrigger: '.t3js-clearTables-stats', - selectorOutputContainer: '.t3js-clearTables-output', - selectorStatContainer: 't3js-clearTables-stat-container', - selectorStatTemplate: '.t3js-clearTables-stat-template', - selectorStatDescription: '.t3js-clearTables-stat-description', - selectorStatRows: '.t3js-clearTables-stat-rows', - selectorStatName: '.t3js-clearTables-stat-name', - selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler', + return { + selectorGridderOpener: 't3js-clearTables-open', + selectorClearToken: '#t3js-clearTables-clear-token', + selectorClearTrigger: '.t3js-clearTables-clear', + selectorStatsTrigger: '.t3js-clearTables-stats', + selectorOutputContainer: '.t3js-clearTables-output', + selectorStatContainer: 't3js-clearTables-stat-container', + selectorStatTemplate: '.t3js-clearTables-stat-template', + selectorStatDescription: '.t3js-clearTables-stat-description', + selectorStatRows: '.t3js-clearTables-stat-rows', + selectorStatName: '.t3js-clearTables-stat-name', + selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Load stats on first open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { - $card.data('isInitialized', true); - self.getStats(); - } - }); + // Load stats on first open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { + $card.data('isInitialized', true); + self.getStats(); + } + }); - $(document).on('click', this.selectorStatsTrigger, function(e) { - e.preventDefault(); - $(self.selectorOutputContainer).empty(); - self.getStats(); - }); + $(document).on('click', this.selectorStatsTrigger, function(e) { + e.preventDefault(); + $(self.selectorOutputContainer).empty(); + self.getStats(); + }); - $(document).on('click', this.selectorClearTrigger, function(e) { - var table = $(e.target).closest(self.selectorClearTrigger).data('table'); - e.preventDefault(); - self.clear(table); - }); - }, + $(document).on('click', this.selectorClearTrigger, function(e) { + var table = $(e.target).closest(self.selectorClearTrigger).data('table'); + e.preventDefault(); + self.clear(table); + }); + }, - getStats: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var $statContainer = $('.' + this.selectorStatContainer); - $statContainer.empty(); - var $statTemplate = $(this.selectorStatTemplate); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $.ajax({ - url: Router.getUrl('clearTablesStats'), - cache: false, - success: function (data) { - if (data.success === true) { - $outputContainer.find('.alert-loading').remove(); - if (Array.isArray(data.stats) && data.stats.length > 0) { - data.stats.forEach(function(element) { - if (element.rowCount > 0) { - var $aStat = $statTemplate.clone(); - $aStat.find(self.selectorStatDescription).text(element.description); - $aStat.find(self.selectorStatName).text(element.name); - $aStat.find(self.selectorStatRows).text(element.rowCount); - $aStat.find(self.selectorClearTrigger).data('table', element.name); - $statContainer.append($aStat); - } - }); - $statContainer.find(self.selectorStatLastRuler + ':last').remove(); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getStats: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var $statContainer = $('.' + this.selectorStatContainer); + $statContainer.empty(); + var $statTemplate = $(this.selectorStatTemplate); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + url: Router.getUrl('clearTablesStats'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.stats) && data.stats.length > 0) { + data.stats.forEach(function(element) { + if (element.rowCount > 0) { + var $aStat = $statTemplate.clone(); + $aStat.find(self.selectorStatDescription).text(element.description); + $aStat.find(self.selectorStatName).text(element.name); + $aStat.find(self.selectorStatRows).text(element.rowCount); + $aStat.find(self.selectorClearTrigger).data('table', element.name); + $statContainer.append($aStat); + } + }); + $statContainer.find(self.selectorStatLastRuler + ':last').remove(); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - clear: function(table) { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().append(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - context: this, - data: { - 'install': { - 'action': 'clearTablesClear', - 'token': $(this.selectorClearToken).text(), - 'table': table - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.append(message); - } - this.getStats(); - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + clear: function(table) { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().append(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + context: this, + data: { + 'install': { + 'action': 'clearTablesClear', + 'token': $(this.selectorClearToken).text(), + 'table': table + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.append(message); + } + this.getStats(); + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js index 93386c2b0e181e5f7229d5c7ae7654ee74f3f9bd..5a8a87b28228023127ae7f0c343d2c7d8cb09536 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js @@ -15,119 +15,119 @@ * Module: TYPO3/CMS/Install/ClearTypo3tempFiles */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-clearTypo3temp-open', - selectorDeleteToken: '#t3js-clearTypo3temp-delete-token', - selectorDeleteTrigger: '.t3js-clearTypo3temp-delete', - selectorOutputContainer: '.t3js-clearTypo3temp-output', - selectorStatContainer: 't3js-clearTypo3temp-stat-container', - selectorStatsTrigger: '.t3js-clearTypo3temp-stats', - selectorStatTemplate: '.t3js-clearTypo3temp-stat-template', - selectorStatDescription: '.t3js-clearTypo3temp-stat-description', - selectorStatNumberOfFiles: '.t3js-clearTypo3temp-stat-numberOfFiles', - selectorStatDirectory: '.t3js-clearTypo3temp-stat-directory', - selectorStatName: '.t3js-clearTypo3temp-stat-name', - selectorStatLastRuler: '.t3js-clearTypo3temp-stat-lastRuler', + return { + selectorGridderOpener: 't3js-clearTypo3temp-open', + selectorDeleteToken: '#t3js-clearTypo3temp-delete-token', + selectorDeleteTrigger: '.t3js-clearTypo3temp-delete', + selectorOutputContainer: '.t3js-clearTypo3temp-output', + selectorStatContainer: 't3js-clearTypo3temp-stat-container', + selectorStatsTrigger: '.t3js-clearTypo3temp-stats', + selectorStatTemplate: '.t3js-clearTypo3temp-stat-template', + selectorStatDescription: '.t3js-clearTypo3temp-stat-description', + selectorStatNumberOfFiles: '.t3js-clearTypo3temp-stat-numberOfFiles', + selectorStatDirectory: '.t3js-clearTypo3temp-stat-directory', + selectorStatName: '.t3js-clearTypo3temp-stat-name', + selectorStatLastRuler: '.t3js-clearTypo3temp-stat-lastRuler', - initialize: function() { - var self = this; - // Load stats on first open - $(document).on('cardlayout:card-opened', function () { - self.getStats(); - }); + initialize: function() { + var self = this; + // Load stats on first open + $(document).on('cardlayout:card-opened', function() { + self.getStats(); + }); - $(document).on('click', this.selectorStatsTrigger, function (e) { - e.preventDefault(); - $(self.selectorOutputContainer).empty(); - self.getStats(); - }); - $(document).on('click', this.selectorDeleteTrigger, function (e) { - var folder = $(e.target).data('folder'); - e.preventDefault(); - self.delete(folder); - }); - }, + $(document).on('click', this.selectorStatsTrigger, function(e) { + e.preventDefault(); + $(self.selectorOutputContainer).empty(); + self.getStats(); + }); + $(document).on('click', this.selectorDeleteTrigger, function(e) { + var folder = $(e.target).data('folder'); + e.preventDefault(); + self.delete(folder); + }); + }, - getStats: function () { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var $statContainer = $('.' + this.selectorStatContainer); - $statContainer.empty(); - var $statTemplate = $(this.selectorStatTemplate); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $.ajax({ - url: Router.getUrl('clearTypo3tempFilesStats'), - cache: false, - success: function (data) { - if (data.success === true) { - $outputContainer.find('.alert-loading').remove(); - if (Array.isArray(data.stats) && data.stats.length > 0) { - data.stats.forEach(function (element) { - if (element.numberOfFiles > 0) { - var $aStat = $statTemplate.clone(); - $aStat.find(self.selectorStatNumberOfFiles).text(element.numberOfFiles); - $aStat.find(self.selectorStatDirectory).text(element.directory); - $aStat.find(self.selectorDeleteTrigger).data('folder', element.directory); - $statContainer.append($aStat); - } - }); - $statContainer.find(self.selectorStatLastRuler + ':last').remove(); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.append(message); - } - }, - error: function (xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getStats: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var $statContainer = $('.' + this.selectorStatContainer); + $statContainer.empty(); + var $statTemplate = $(this.selectorStatTemplate); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + url: Router.getUrl('clearTypo3tempFilesStats'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.stats) && data.stats.length > 0) { + data.stats.forEach(function(element) { + if (element.numberOfFiles > 0) { + var $aStat = $statTemplate.clone(); + $aStat.find(self.selectorStatNumberOfFiles).text(element.numberOfFiles); + $aStat.find(self.selectorStatDirectory).text(element.directory); + $aStat.find(self.selectorDeleteTrigger).data('folder', element.directory); + $statContainer.append($aStat); + } + }); + $statContainer.find(self.selectorStatLastRuler + ':last').remove(); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - delete: function(folder) { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().append(message); - $.ajax({ - method: 'POST', - url: Router.getUrl(), - context: this, - data: { - 'install': { - 'action': 'clearTypo3tempFiles', - 'token': $(this.selectorDeleteToken).text(), - 'folder': folder - } - }, - cache: false, - success: function (data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function (element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.html(message); - }); - this.getStats(); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + delete: function(folder) { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().append(message); + $.ajax({ + method: 'POST', + url: Router.getUrl(), + context: this, + data: { + 'install': { + 'action': 'clearTypo3tempFiles', + 'token': $(this.selectorDeleteToken).text(), + 'folder': folder + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.html(message); + }); + this.getStats(); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js index d08bd43e19676ab326e4705b79034a6a1a70eb48..089245cd4cff899f12d60aa3bbf70458b7fca525 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js @@ -15,250 +15,250 @@ * Module: TYPO3/CMS/Install/CoreUpdate */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/Severity' -], function ($, Router, FlashMessage, Severity) { - 'use strict'; + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/Severity' +], function($, Router, FlashMessage, Severity) { + 'use strict'; - return { - /** - * The action queue defines what actions are called in which order - */ - actionQueue: { - coreUpdateUpdateVersionMatrix: { - loadingMessage: 'Fetching list of released versions from typo3.org', - finishMessage: 'Fetched list of released versions', - nextActionName: 'coreUpdateIsUpdateAvailable' - }, - coreUpdateIsUpdateAvailable: { - loadingMessage: 'Checking for possible regular or security update', - finishMessage: undefined, - nextActionName: undefined - }, - coreUpdateCheckPreConditions: { - loadingMessage: 'Checking if update is possible', - finishMessage: 'System can be updated', - nextActionName: 'coreUpdateDownload' - }, - coreUpdateDownload: { - loadingMessage: 'Downloading new core', - finishMessage: undefined, - nextActionName: 'coreUpdateVerifyChecksum' - }, - coreUpdateVerifyChecksum: { - loadingMessage: 'Verifying checksum of downloaded core', - finishMessage: undefined, - nextActionName: 'coreUpdateUnpack' - }, - coreUpdateUnpack: { - loadingMessage: 'Unpacking core', - finishMessage: undefined, - nextActionName: 'coreUpdateMove' - }, - coreUpdateMove: { - loadingMessage: 'Moving core', - finishMessage: undefined, - nextActionName: 'coreUpdateClearAllCache' - }, - clearAllCache: { - loadingMessage: 'Clearing caches', - finishMessage: 'Caches cleared', - nextActionName: 'coreUpdateActivate' - }, - coreUpdateActivate: { - loadingMessage: 'Activating core', - finishMessage: 'Core updated - please reload your browser', - nextActionName: undefined - } - }, + return { + /** + * The action queue defines what actions are called in which order + */ + actionQueue: { + coreUpdateUpdateVersionMatrix: { + loadingMessage: 'Fetching list of released versions from typo3.org', + finishMessage: 'Fetched list of released versions', + nextActionName: 'coreUpdateIsUpdateAvailable' + }, + coreUpdateIsUpdateAvailable: { + loadingMessage: 'Checking for possible regular or security update', + finishMessage: undefined, + nextActionName: undefined + }, + coreUpdateCheckPreConditions: { + loadingMessage: 'Checking if update is possible', + finishMessage: 'System can be updated', + nextActionName: 'coreUpdateDownload' + }, + coreUpdateDownload: { + loadingMessage: 'Downloading new core', + finishMessage: undefined, + nextActionName: 'coreUpdateVerifyChecksum' + }, + coreUpdateVerifyChecksum: { + loadingMessage: 'Verifying checksum of downloaded core', + finishMessage: undefined, + nextActionName: 'coreUpdateUnpack' + }, + coreUpdateUnpack: { + loadingMessage: 'Unpacking core', + finishMessage: undefined, + nextActionName: 'coreUpdateMove' + }, + coreUpdateMove: { + loadingMessage: 'Moving core', + finishMessage: undefined, + nextActionName: 'coreUpdateClearAllCache' + }, + clearAllCache: { + loadingMessage: 'Clearing caches', + finishMessage: 'Caches cleared', + nextActionName: 'coreUpdateActivate' + }, + coreUpdateActivate: { + loadingMessage: 'Activating core', + finishMessage: 'Core updated - please reload your browser', + nextActionName: undefined + } + }, - selectorOutput: '.t3js-coreUpdate-output', - selectorTemplate: '.t3js-coreUpdate-buttonTemplate', + selectorOutput: '.t3js-coreUpdate-output', + selectorTemplate: '.t3js-coreUpdate-buttonTemplate', - /** - * Clone of a DOM object acts as button template - */ - buttonTemplate: null, + /** + * Clone of a DOM object acts as button template + */ + buttonTemplate: null, - /** - * Fetching the templates out of the DOM - */ - initialize: function () { - var self = this; - var buttonTemplateSection = $(self.selectorTemplate); - this.buttonTemplate = buttonTemplateSection.children().clone(); + /** + * Fetching the templates out of the DOM + */ + initialize: function() { + var self = this; + var buttonTemplateSection = $(self.selectorTemplate); + this.buttonTemplate = buttonTemplateSection.children().clone(); - $(document).on('click', '.t3js-coreUpdate-init', function (e) { - e.preventDefault(); - var action = $(e.target).data('action'); - $(document).find(self.selectorOutput).empty(); - self[action](); - }); - }, + $(document).on('click', '.t3js-coreUpdate-init', function(e) { + e.preventDefault(); + var action = $(e.target).data('action'); + $(document).find(self.selectorOutput).empty(); + self[action](); + }); + }, - /** - * Public method checkForUpdate - */ - checkForUpdate: function () { - this.callAction('coreUpdateUpdateVersionMatrix'); - }, + /** + * Public method checkForUpdate + */ + checkForUpdate: function() { + this.callAction('coreUpdateUpdateVersionMatrix'); + }, - /** - * Public method updateDevelopment - */ - updateDevelopment: function () { - this.update('development'); - }, + /** + * Public method updateDevelopment + */ + updateDevelopment: function() { + this.update('development'); + }, - updateRegular: function () { - this.update('regular'); - }, + updateRegular: function() { + this.update('regular'); + }, - /** - * Execute core update. - * - * @param type Either 'development' or 'regular' - */ - update: function (type) { - if (type !== "development") { - type = 'regular'; - } - this.callAction('coreUpdateCheckPreConditions', type); - }, + /** + * Execute core update. + * + * @param type Either 'development' or 'regular' + */ + update: function(type) { + if (type !== "development") { + type = 'regular'; + } + this.callAction('coreUpdateCheckPreConditions', type); + }, - /** - * Generic method to call actions from the queue - * - * @param actionName Name of the action to be called - * @param type Update type (optional) - */ - callAction: function (actionName, type) { - var self = this; - var data = { - install: { - action: actionName - } - }; - if (type !== undefined) { - data.install["type"] = type; - } - this.addLoadingMessage(this.actionQueue[actionName].loadingMessage); - $.ajax({ - url: Router.getUrl(), - data: data, - cache: false, - success: function (result) { - var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage); - if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) { - self.callAction(self.actionQueue[actionName].nextActionName, type); - } - }, - error: function (result) { - self.handleResult(result); - } - }); - }, + /** + * Generic method to call actions from the queue + * + * @param actionName Name of the action to be called + * @param type Update type (optional) + */ + callAction: function(actionName, type) { + var self = this; + var data = { + install: { + action: actionName + } + }; + if (type !== undefined) { + data.install["type"] = type; + } + this.addLoadingMessage(this.actionQueue[actionName].loadingMessage); + $.ajax({ + url: Router.getUrl(), + data: data, + cache: false, + success: function(result) { + var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage); + if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) { + self.callAction(self.actionQueue[actionName].nextActionName, type); + } + }, + error: function(result) { + self.handleResult(result); + } + }); + }, - /** - * Handle ajax result of core update step. - * - * @param data - * @param successMessage Optional success message - */ - handleResult: function (data, successMessage) { - var canContinue = false; - this.removeLoadingMessage(); - if (data.success === true) { - canContinue = true; - if (data.status && typeof(data.status) === 'object') { - this.showStatusMessages(data.status); - } - if (data.action && typeof(data.action) === 'object') { - this.showActionButton(data.action); - } - if (successMessage) { - this.addMessage(Severity.ok, successMessage); - } - } else { - Router.handleAjaxError(xhr); - } - return canContinue; - }, + /** + * Handle ajax result of core update step. + * + * @param data + * @param successMessage Optional success message + */ + handleResult: function(data, successMessage) { + var canContinue = false; + this.removeLoadingMessage(); + if (data.success === true) { + canContinue = true; + if (data.status && typeof(data.status) === 'object') { + this.showStatusMessages(data.status); + } + if (data.action && typeof(data.action) === 'object') { + this.showActionButton(data.action); + } + if (successMessage) { + this.addMessage(Severity.ok, successMessage); + } + } else { + Router.handleAjaxError(xhr); + } + return canContinue; + }, - /** - * Add a loading message with some text. - * - * @param messageTitle - */ - addLoadingMessage: function (messageTitle) { - var domMessage = FlashMessage.render(Severity.loading, messageTitle); - $(this.selectorOutput).append(domMessage); - }, + /** + * Add a loading message with some text. + * + * @param messageTitle + */ + addLoadingMessage: function(messageTitle) { + var domMessage = FlashMessage.render(Severity.loading, messageTitle); + $(this.selectorOutput).append(domMessage); + }, - /** - * Remove an enabled loading message - */ - removeLoadingMessage: function () { - $(this.selectorOutput).find('.alert-loading').remove(); - }, + /** + * Remove an enabled loading message + */ + removeLoadingMessage: function() { + $(this.selectorOutput).find('.alert-loading').remove(); + }, - /** - * Show a list of status messages - * - * @param messages - */ - showStatusMessages: function (messages) { - var self = this; - $.each(messages, function (index, element) { - var title = false; - var message = false; - var severity = element.severity; - if (element.title) { - title = element.title; - } - if (element.message) { - message = element.message; - } - self.addMessage(severity, title, message); - }); - }, + /** + * Show a list of status messages + * + * @param messages + */ + showStatusMessages: function(messages) { + var self = this; + $.each(messages, function(index, element) { + var title = false; + var message = false; + var severity = element.severity; + if (element.title) { + title = element.title; + } + if (element.message) { + message = element.message; + } + self.addMessage(severity, title, message); + }); + }, - /** - * Show an action button - * - * @param button - */ - showActionButton: function (button) { - var title = false; - var action = false; - if (button.title) { - title = button.title; - } - if (button.action) { - action = button.action; - } - var domButton = this.buttonTemplate; - if (action) { - domButton.find('button').data('action', action); - } - if (title) { - domButton.find('button').text(title); - } - $(this.selectorOutput).append(domButton); - }, + /** + * Show an action button + * + * @param button + */ + showActionButton: function(button) { + var title = false; + var action = false; + if (button.title) { + title = button.title; + } + if (button.action) { + action = button.action; + } + var domButton = this.buttonTemplate; + if (action) { + domButton.find('button').data('action', action); + } + if (title) { + domButton.find('button').text(title); + } + $(this.selectorOutput).append(domButton); + }, - /** - * Show a status message - * - * @param severity - * @param title - * @param message - */ - addMessage: function (severity, title, message) { - var domMessage = FlashMessage.render(severity, title, message); - $(this.selectorOutput).append(domMessage); - } - }; + /** + * Show a status message + * + * @param severity + * @param title + * @param message + */ + addMessage: function(severity, title, message) { + var domMessage = FlashMessage.render(severity, title, message); + $(this.selectorOutput).append(domMessage); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js index 311942bf31615a41c49085b3380d627b58afe296..a745eb2227c1014f3c5b37ec39e67df347804c5c 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js @@ -15,68 +15,68 @@ * Module: TYPO3/CMS/Install/CreateAdmin */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'TYPO3/CMS/Install/PasswordStrength', + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'TYPO3/CMS/Install/PasswordStrength' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, PasswordStrength) { - 'use strict'; + 'use strict'; - return { - selectorCreateForm: '#t3js-createAdmin-form', - selectorCreateToken: '#t3js-createAdmin-token', - selectorCreateTrigger: '.t3js-createAdmin-create', - selectorOutputContainer: '.t3js-createAdmin-output', + return { + selectorCreateForm: '#t3js-createAdmin-form', + selectorCreateToken: '#t3js-createAdmin-token', + selectorCreateTrigger: '.t3js-createAdmin-create', + selectorOutputContainer: '.t3js-createAdmin-output', - initialize: function() { - var self = this; - $(document).on('submit', this.selectorCreateForm, function(e) { - e.preventDefault(); - self.create(); - }); - $(document).on('keyup', '.t3-install-form-password-strength', function() { - PasswordStrength.initialize('.t3-install-form-password-strength'); - }); - }, + initialize: function() { + var self = this; + $(document).on('submit', this.selectorCreateForm, function(e) { + e.preventDefault(); + self.create(); + }); + $(document).on('keyup', '.t3-install-form-password-strength', function() { + PasswordStrength.initialize('.t3-install-form-password-strength'); + }); + }, - create: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'createAdmin', - 'token': $(self.selectorCreateToken).text(), - 'userName': $('.t3js-createAdmin-user').val(), - 'userPassword': $('.t3js-createAdmin-password').val(), - 'userPasswordCheck': $('.t3js-createAdmin-password-check').val(), - 'userSystemMaintainer': ($('.t3js-createAdmin-system-maintainer').is(':checked'))? 1 : 0 - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.html(message); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + create: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'createAdmin', + 'token': $(self.selectorCreateToken).text(), + 'userName': $('.t3js-createAdmin-user').val(), + 'userPassword': $('.t3js-createAdmin-password').val(), + 'userPasswordCheck': $('.t3js-createAdmin-password-check').val(), + 'userSystemMaintainer': ($('.t3js-createAdmin-system-maintainer').is(':checked')) ? 1 : 0 + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.html(message); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js index 9b8dd870bfe29a3154022334ab3bf48c801dfa91..7daadb1a1c6c06f6e6c994d21a6ce26281085e45 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js @@ -15,159 +15,159 @@ * Module: TYPO3/CMS/Install/DatabaseAnalyzer */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-databaseAnalyzer-open', - selectorAnalyzeTrigger: '.t3js-databaseAnalyzer-analyze', - selectorExecuteTrigger: '.t3js-databaseAnalyzer-execute', - selectorOutputContainer: '.t3js-databaseAnalyzer-output', - selectorSuggestionBlock: '.t3js-databaseAnalyzer-suggestion-block', - selectorSuggestionLine: '.t3js-databaseAnalyzer-suggestion-line', + return { + selectorGridderOpener: 't3js-databaseAnalyzer-open', + selectorAnalyzeTrigger: '.t3js-databaseAnalyzer-analyze', + selectorExecuteTrigger: '.t3js-databaseAnalyzer-execute', + selectorOutputContainer: '.t3js-databaseAnalyzer-output', + selectorSuggestionBlock: '.t3js-databaseAnalyzer-suggestion-block', + selectorSuggestionLine: '.t3js-databaseAnalyzer-suggestion-line', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Load main content on first open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { - $card.data('isInitialized', true); - self.analyze(); - } - }); + // Load main content on first open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { + $card.data('isInitialized', true); + self.analyze(); + } + }); - // Select / deselect all checkboxes - $(document).on('click', '.t3js-databaseAnalyzer-suggestion-block-checkbox', function () { - $(this).closest('fieldset').find(':checkbox').prop('checked', this.checked); - }); - $(document).on('click', this.selectorAnalyzeTrigger, function(e) { - e.preventDefault(); - self.analyze(); - }); - $(document).on('click', this.selectorExecuteTrigger, function(e) { - e.preventDefault(); - self.execute(); - }); - }, + // Select / deselect all checkboxes + $(document).on('click', '.t3js-databaseAnalyzer-suggestion-block-checkbox', function() { + $(this).closest('fieldset').find(':checkbox').prop('checked', this.checked); + }); + $(document).on('click', this.selectorAnalyzeTrigger, function(e) { + e.preventDefault(); + self.analyze(); + }); + $(document).on('click', this.selectorExecuteTrigger, function(e) { + e.preventDefault(); + self.execute(); + }); + }, - analyze: function() { - $(this.selectorOutputContainer).empty(); - this.analyzeAjax(); - }, + analyze: function() { + $(this.selectorOutputContainer).empty(); + this.analyzeAjax(); + }, - analyzeAjax: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var blockTemplate = $(this.selectorSuggestionBlock).html(); - var lineTemplate = $(this.selectorSuggestionLine).html(); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $(this.selectorExecuteTrigger).prop('disabled', true); - $(this.selectorAnalyzeTrigger).prop('disabled', true); - $.ajax({ - url: Router.getUrl('databaseAnalyzerAnalyze'), - cache: false, - success: function (data) { - if (data.success === true) { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - }); - } - if (Array.isArray(data.suggestions)) { - data.suggestions.forEach(function(element) { - var aBlock = $(blockTemplate).clone(); - var key = element.key; - aBlock.find('.t3js-databaseAnalyzer-suggestion-block-legend').text(element.label); - aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('id', 't3-install-' + key + '-checkbox'); - if (element.enabled) { - aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('checked', 'checked'); - } - aBlock.find('.t3js-databaseAnalyzer-suggestion-block-label').attr('for', 't3-install-' + key + '-checkbox'); - element.children.forEach(function(line) { - var aLine = $(lineTemplate).clone(); - var hash = line.hash; - aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('id', 't3-install-db-' + hash); - aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').data('hash', hash); - if (element.enabled) { - aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('checked', 'checked'); - } - aLine.find('.t3js-databaseAnalyzer-suggestion-line-label').attr('for', 't3-install-db-' + hash); - aLine.find('.t3js-databaseAnalyzer-suggestion-line-statement').text(line.statement); - if (line.current !== undefined) { - aLine.find('.t3js-databaseAnalyzer-suggestion-line-current-value').text(line.current); - aLine.find('.t3js-databaseAnalyzer-suggestion-line-current').show(); - } - if (line.rowCount !== undefined) { - aLine.find('.t3js-databaseAnalyzer-suggestion-line-count-value').text(line.rowCount); - aLine.find('.t3js-databaseAnalyzer-suggestion-line-count').show(); - } - aBlock.find('.t3js-databaseAnalyzer-suggestion-block-line').append(aLine); - }); - $outputContainer.append(aBlock); - }); - $(self.selectorExecuteTrigger).prop('disabled', false); - $(self.selectorAnalyzeTrigger).prop('disabled', false); - } - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + analyzeAjax: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var blockTemplate = $(this.selectorSuggestionBlock).html(); + var lineTemplate = $(this.selectorSuggestionLine).html(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $(this.selectorExecuteTrigger).prop('disabled', true); + $(this.selectorAnalyzeTrigger).prop('disabled', true); + $.ajax({ + url: Router.getUrl('databaseAnalyzerAnalyze'), + cache: false, + success: function(data) { + if (data.success === true) { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + }); + } + if (Array.isArray(data.suggestions)) { + data.suggestions.forEach(function(element) { + var aBlock = $(blockTemplate).clone(); + var key = element.key; + aBlock.find('.t3js-databaseAnalyzer-suggestion-block-legend').text(element.label); + aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('id', 't3-install-' + key + '-checkbox'); + if (element.enabled) { + aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('checked', 'checked'); + } + aBlock.find('.t3js-databaseAnalyzer-suggestion-block-label').attr('for', 't3-install-' + key + '-checkbox'); + element.children.forEach(function(line) { + var aLine = $(lineTemplate).clone(); + var hash = line.hash; + aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('id', 't3-install-db-' + hash); + aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').data('hash', hash); + if (element.enabled) { + aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('checked', 'checked'); + } + aLine.find('.t3js-databaseAnalyzer-suggestion-line-label').attr('for', 't3-install-db-' + hash); + aLine.find('.t3js-databaseAnalyzer-suggestion-line-statement').text(line.statement); + if (line.current !== undefined) { + aLine.find('.t3js-databaseAnalyzer-suggestion-line-current-value').text(line.current); + aLine.find('.t3js-databaseAnalyzer-suggestion-line-current').show(); + } + if (line.rowCount !== undefined) { + aLine.find('.t3js-databaseAnalyzer-suggestion-line-count-value').text(line.rowCount); + aLine.find('.t3js-databaseAnalyzer-suggestion-line-count').show(); + } + aBlock.find('.t3js-databaseAnalyzer-suggestion-block-line').append(aLine); + }); + $outputContainer.append(aBlock); + }); + $(self.selectorExecuteTrigger).prop('disabled', false); + $(self.selectorAnalyzeTrigger).prop('disabled', false); + } + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - execute: function() { - var self = this; - var executeToken = $('#t3js-databaseAnalyzer-execute-token').text(); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - var $outputContainer = $('.t3js-databaseAnalyzer-output'); - var selectedHashes = []; - $('.gridder-show .t3js-databaseAnalyzer-output .t3js-databaseAnalyzer-suggestion-block-line input:checked').each(function () { - selectedHashes.push($(this).data('hash')); - }); - $outputContainer.empty().html(message); - $(this.selectorExecuteTrigger).prop('disabled', true); - $(this.selectorAnalyzeTrigger).prop('disabled', true); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'databaseAnalyzerExecute', - 'token': executeToken, - 'hashes': selectedHashes - } - }, - cache: false, - success: function(data) { - if (data.success === true) { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - }); - } - } - self.analyzeAjax(); - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + execute: function() { + var self = this; + var executeToken = $('#t3js-databaseAnalyzer-execute-token').text(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + var $outputContainer = $('.t3js-databaseAnalyzer-output'); + var selectedHashes = []; + $('.gridder-show .t3js-databaseAnalyzer-output .t3js-databaseAnalyzer-suggestion-block-line input:checked').each(function() { + selectedHashes.push($(this).data('hash')); + }); + $outputContainer.empty().html(message); + $(this.selectorExecuteTrigger).prop('disabled', true); + $(this.selectorAnalyzeTrigger).prop('disabled', true); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'databaseAnalyzerExecute', + 'token': executeToken, + 'hashes': selectedHashes + } + }, + cache: false, + success: function(data) { + if (data.success === true) { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + }); + } + } + self.analyzeAjax(); + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js index 9db34731629578cf230b28da05014ae726d2fd19..990f1c0fdc8c2ca86974c299269de4d52660f6c0 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js @@ -15,52 +15,52 @@ * Module: TYPO3/CMS/Install/DumpAutoload */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorDumpTrigger: '.t3js-dumpAutoload-dump', - selectorOutputContainer: '.t3js-dumpAutoload-output', + return { + selectorDumpTrigger: '.t3js-dumpAutoload-dump', + selectorOutputContainer: '.t3js-dumpAutoload-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorDumpTrigger, function(e) { - e.preventDefault(); - self.dump(); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorDumpTrigger, function(e) { + e.preventDefault(); + self.dump(); + }); + }, - dump: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('dumpAutoload'), - cache: false, - success: function(data) { - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - $outputContainer.empty(); - data.status.forEach((function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - })); - } - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + dump: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('dumpAutoload'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + $outputContainer.empty(); + data.status.forEach((function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + })); + } + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js index 81c8699aaf39a6a9625df413d0f123f6843e9703..1d2d05706a85f1daefac78265d3802d624648d69 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js @@ -15,75 +15,75 @@ * Module: TYPO3/CMS/Install/EnvironmentCheck */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderBadge: '.t3js-environmentCheck-badge', - selectorExecuteTrigger: '.t3js-environmentCheck-execute', - selectorOutputContainer: '.t3js-environmentCheck-output', + return { + selectorGridderBadge: '.t3js-environmentCheck-badge', + selectorExecuteTrigger: '.t3js-environmentCheck-execute', + selectorOutputContainer: '.t3js-environmentCheck-output', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Get status on initialize to have the badge and content ready - self.runTests(); + // Get status on initialize to have the badge and content ready + self.runTests(); - $(document).on('click', this.selectorExecuteTrigger, function(e) { - e.preventDefault(); - self.runTests(); - }); - }, + $(document).on('click', this.selectorExecuteTrigger, function(e) { + e.preventDefault(); + self.runTests(); + }); + }, - runTests: function() { - var $outputContainer = $(this.selectorOutputContainer); - var $errorBadge = $(this.selectorGridderBadge); - $errorBadge.text('').hide(); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().append(message); - $.ajax({ - url: Router.getUrl('environmentCheckGetStatus'), - cache: false, - success: function(data) { - $outputContainer.empty(); - var warningCount = 0; - var errorCount = 0; - if (data.success === true && typeof(data.status) === 'object') { - $.each(data.status, function(i, element) { - if (Array.isArray(element) && element.length > 0) { - element.forEach(function(aStatus) { - if (aStatus.severity === 1) { - warningCount += 1; - } - if (aStatus.severity === 2) { - errorCount += 1; - } - var message = InfoBox.render(aStatus.severity, aStatus.title, aStatus.message); - $outputContainer.append(message); - }); - } - }); - if (errorCount > 0) { - $errorBadge.removeClass('label-warning').addClass('label-danger').text(errorCount).show(); - } else if (warningCount > 0) { - $errorBadge.removeClass('label-error').addClass('label-warning').text(warningCount).show(); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } + runTests: function() { + var $outputContainer = $(this.selectorOutputContainer); + var $errorBadge = $(this.selectorGridderBadge); + $errorBadge.text('').hide(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().append(message); + $.ajax({ + url: Router.getUrl('environmentCheckGetStatus'), + cache: false, + success: function(data) { + $outputContainer.empty(); + var warningCount = 0; + var errorCount = 0; + if (data.success === true && typeof(data.status) === 'object') { + $.each(data.status, function(i, element) { + if (Array.isArray(element) && element.length > 0) { + element.forEach(function(aStatus) { + if (aStatus.severity === 1) { + warningCount += 1; + } + if (aStatus.severity === 2) { + errorCount += 1; + } + var message = InfoBox.render(aStatus.severity, aStatus.title, aStatus.message); + $outputContainer.append(message); + }); + } }); + if (errorCount > 0) { + $errorBadge.removeClass('label-warning').addClass('label-danger').text(errorCount).show(); + } else if (warningCount > 0) { + $errorBadge.removeClass('label-error').addClass('label-warning').text(warningCount).show(); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); } - }; + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js index f8daa7291e61495d2e9fc268a3b191c7b938b091..bf0ffcbd71df1d6149ed9e4d377f326bc7b7efd8 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js @@ -15,185 +15,185 @@ * Module: TYPO3/CMS/Install/ExtensionCompatTester */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'TYPO3/CMS/Install/Cache' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'TYPO3/CMS/Install/Cache' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Cache) { - 'use strict'; + 'use strict'; - return { - selectorLoadExtLocalconfToken: '#t3js-extensionCompatTester-loadExtLocalconf-token', - selectorLoadExtTablesToken: '#t3js-extensionCompatTester-loadExtTables-token', - selectorUninstallExtensionToken: '#t3js-extensionCompatTester-uninstallExtension-token', - selectorCheckTrigger: '.t3js-extensionCompatTester-check', - selectorUninstallTrigger: '.t3js-extensionCompatTester-uninstall', - selectorOutputContainer: '.t3js-extensionCompatTester-output', + return { + selectorLoadExtLocalconfToken: '#t3js-extensionCompatTester-loadExtLocalconf-token', + selectorLoadExtTablesToken: '#t3js-extensionCompatTester-loadExtTables-token', + selectorUninstallExtensionToken: '#t3js-extensionCompatTester-uninstallExtension-token', + selectorCheckTrigger: '.t3js-extensionCompatTester-check', + selectorUninstallTrigger: '.t3js-extensionCompatTester-uninstall', + selectorOutputContainer: '.t3js-extensionCompatTester-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorCheckTrigger, function(e) { - $(self.selectorUninstallTrigger).hide(); - $(self.selectorOutputContainer).empty(); - self.getLoadedExtensionList(); - }); - $(document).on('click', this.selectorUninstallTrigger, function(e) { - self.uninstallExtension($(e.target).data('extension')); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorCheckTrigger, function(e) { + $(self.selectorUninstallTrigger).hide(); + $(self.selectorOutputContainer).empty(); + self.getLoadedExtensionList(); + }); + $(document).on('click', this.selectorUninstallTrigger, function(e) { + self.uninstallExtension($(e.target).data('extension')); + }); + }, - getLoadedExtensionList: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var $uninstallButton = $(this.selectorUninstallTrigger); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - var loadResult = false; - $.ajax({ - url: Router.getUrl('extensionCompatTesterLoadedExtensionList'), - cache: false, - success: function(data) { - if (data.success === true && Array.isArray(data.extensions)) { - var extension; - try { - data.extensions.forEach(function(extension) { - loadResult = self.loadExtLocalconf(extension); - if (loadResult === false) { - throw extension; - } - }); - message = InfoBox.render(Severity.OK, 'ext_localconf.php of all loaded extensions successfully loaded', ''); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - try { - data.extensions.forEach(function(extension) { - loadResult = self.loadExtTables(extension); - if (loadResult === false) { - throw extension; - } - }); - message = InfoBox.render(Severity.OK, 'ext_tables.php of all loaded extensions successfully loaded', ''); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - } catch (extension) { - message = InfoBox.render(Severity.error, 'Loading ext_tables.php of extension "' + extension + '" failed'); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show(); - } - } catch (extension) { - message = InfoBox.render(Severity.error, 'Loading ext_localconf.php of extension "' + extension + '" failed'); - $outputContainer.find('.alert-loading').remove(); - $outputContainer.append(message); - $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show(); - } - } else { - message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getLoadedExtensionList: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var $uninstallButton = $(this.selectorUninstallTrigger); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + var loadResult = false; + $.ajax({ + url: Router.getUrl('extensionCompatTesterLoadedExtensionList'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.extensions)) { + var extension; + try { + data.extensions.forEach(function(extension) { + loadResult = self.loadExtLocalconf(extension); + if (loadResult === false) { + throw extension; + } + }); + message = InfoBox.render(Severity.OK, 'ext_localconf.php of all loaded extensions successfully loaded', ''); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + try { + data.extensions.forEach(function(extension) { + loadResult = self.loadExtTables(extension); + if (loadResult === false) { + throw extension; + } + }); + message = InfoBox.render(Severity.OK, 'ext_tables.php of all loaded extensions successfully loaded', ''); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + } catch (extension) { + message = InfoBox.render(Severity.error, 'Loading ext_tables.php of extension "' + extension + '" failed'); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show(); + } + } catch (extension) { + message = InfoBox.render(Severity.error, 'Loading ext_localconf.php of extension "' + extension + '" failed'); + $outputContainer.find('.alert-loading').remove(); + $outputContainer.append(message); + $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show(); + } + } else { + message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - loadExtLocalconf: function(extension) { - var self = this; - var result = false; - $.ajax({ - url: Router.getUrl(), - method: 'POST', - cache: false, - async: false, - data: { - 'install': { - 'action': 'extensionCompatTesterLoadExtLocalconf', - 'token': $(self.selectorLoadExtLocalconfToken).text(), - 'extension': extension - } - }, - success: function(data) { - result = data.success === true; - }, - error: function(data) { - result = false; - } - }); - return result; - }, + loadExtLocalconf: function(extension) { + var self = this; + var result = false; + $.ajax({ + url: Router.getUrl(), + method: 'POST', + cache: false, + async: false, + data: { + 'install': { + 'action': 'extensionCompatTesterLoadExtLocalconf', + 'token': $(self.selectorLoadExtLocalconfToken).text(), + 'extension': extension + } + }, + success: function(data) { + result = data.success === true; + }, + error: function(data) { + result = false; + } + }); + return result; + }, - loadExtTables: function(extension) { - var self = this; - var result = false; - $.ajax({ - url: Router.getUrl(), - method: 'POST', - cache: false, - async: false, - data: { - 'install': { - 'action': 'extensionCompatTesterLoadExtTables', - 'token': $(self.selectorLoadExtTablesToken).text(), - 'extension': extension - } - }, - success: function(data) { - result = data.success === true; - }, - error: function(data) { - result = false; - } - }); - return result; - }, + loadExtTables: function(extension) { + var self = this; + var result = false; + $.ajax({ + url: Router.getUrl(), + method: 'POST', + cache: false, + async: false, + data: { + 'install': { + 'action': 'extensionCompatTesterLoadExtTables', + 'token': $(self.selectorLoadExtTablesToken).text(), + 'extension': extension + } + }, + success: function(data) { + result = data.success === true; + }, + error: function(data) { + result = false; + } + }); + return result; + }, - /** - * Send an ajax request to uninstall an extension (or multiple extensions) - * - * @param extension string of extension(s) - may be comma separated - */ - uninstallExtension: function(extension) { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $.ajax({ - url: Router.getUrl(), - cache: false, - method: 'POST', - data: { - 'install': { - 'action': 'extensionCompatTesterUninstallExtension', - 'token': $(self.selectorUninstallExtensionToken).text(), - 'extension': extension - } - }, - success: function(data) { - if (data.success) { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } - $(self.selectorUninstallTrigger).hide(); - Cache.clearAll(); - self.getLoadedExtensionList(); - } else { - message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + /** + * Send an ajax request to uninstall an extension (or multiple extensions) + * + * @param extension string of extension(s) - may be comma separated + */ + uninstallExtension: function(extension) { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + url: Router.getUrl(), + cache: false, + method: 'POST', + data: { + 'install': { + 'action': 'extensionCompatTesterUninstallExtension', + 'token': $(self.selectorUninstallExtensionToken).text(), + 'extension': extension + } + }, + success: function(data) { + if (data.success) { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + $(self.selectorUninstallTrigger).hide(); + Cache.clearAll(); + self.getLoadedExtensionList(); + } else { + message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js index 5db58ecb6c0aa6f850965b84af871d4222a403ad..13c9970e6e9c8c73471fe73dc078864f836aeb73 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js @@ -15,214 +15,214 @@ * Module: TYPO3/CMS/Install/ExtensionConfiguration */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; - - return { - selectorGridderOpener: 't3js-extensionConfiguration-open', - selectorContentContainer: '.t3js-extensionConfiguration-content', - selectorFormListener: '.t3js-extensionConfiguration-form', - selectorWriteToken: '#t3js-extensionConfiguration-write-token', - selectorOutputContainer: '.t3js-extensionConfiguration-output', - selectorSearchInput: '.t3js-extensionConfiguration-search', - - initialize: function() { - var self = this; - - // Get extension configuration list on card open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener)) { - self.getContent(); - } - }); - - // Focus search field on certain user interactions - $(document).on('keydown', function(e) { - var $searchInput = $(self.selectorSearchInput); - if (e.ctrlKey || e.metaKey) { - // Focus search field on ctrl-f - switch (String.fromCharCode(e.which).toLowerCase()) { - case 'f': - e.preventDefault(); - $searchInput.focus(); - break; - } - } else if (e.keyCode === 27) { - // Clear search on ESC key - e.preventDefault(); - $searchInput.val('').focus(); - } - }); - - // Perform expand collapse on search matches - $(document).on('keyup', this.selectorSearchInput, function() { - var typedQuery = $(this).val(); - var $searchInput = $(self.selectorSearchInput); - $('.search-item').each(function() { - var $item = $(this); - if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { - $item.removeClass('hidden').addClass('searchhit'); - } else { - $item.removeClass('searchhit').addClass('hidden'); - } - }); - $('.searchhit').collapse('show'); - // Make search field clearable - require(['jquery.clearable'], function() { - $searchInput.clearable().focus(); - }); - }); - - $(document).on('submit', this.selectorFormListener, function(e) { - e.preventDefault(); - self.write($(this)); - }); + 'use strict'; + + return { + selectorGridderOpener: 't3js-extensionConfiguration-open', + selectorContentContainer: '.t3js-extensionConfiguration-content', + selectorFormListener: '.t3js-extensionConfiguration-form', + selectorWriteToken: '#t3js-extensionConfiguration-write-token', + selectorOutputContainer: '.t3js-extensionConfiguration-output', + selectorSearchInput: '.t3js-extensionConfiguration-search', + + initialize: function() { + var self = this; + + // Get extension configuration list on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getContent(); + } + }); + + // Focus search field on certain user interactions + $(document).on('keydown', function(e) { + var $searchInput = $(self.selectorSearchInput); + if (e.ctrlKey || e.metaKey) { + // Focus search field on ctrl-f + switch (String.fromCharCode(e.which).toLowerCase()) { + case 'f': + e.preventDefault(); + $searchInput.focus(); + break; + } + } else if (e.keyCode === 27) { + // Clear search on ESC key + e.preventDefault(); + $searchInput.val('').focus(); + } + }); + + // Perform expand collapse on search matches + $(document).on('keyup', this.selectorSearchInput, function() { + var typedQuery = $(this).val(); + var $searchInput = $(self.selectorSearchInput); + $('.search-item').each(function() { + var $item = $(this); + if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { + $item.removeClass('hidden').addClass('searchhit'); + } else { + $item.removeClass('searchhit').addClass('hidden'); + } + }); + $('.searchhit').collapse('show'); + // Make search field clearable + require(['jquery.clearable'], function() { + $searchInput.clearable().focus(); + }); + }); + + $(document).on('submit', this.selectorFormListener, function(e) { + e.preventDefault(); + self.write($(this)); + }); + }, + + getContent: function() { + var self = this; + var outputContainer = $(this.selectorContentContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('extensionConfigurationGetContent'), + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + outputContainer.empty().append(data.html); + self.initializeWrap(); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + outputContainer.empty().append(message); + } }, - - getContent: function() { - var self = this; - var outputContainer = $(this.selectorContentContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('extensionConfigurationGetContent'), - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - outputContainer.empty().append(data.html); - self.initializeWrap(); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - outputContainer.empty().append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, + + /** + * Submit the form and show the result message + * + * @param {jQuery} $form The form of the current extension + */ + write: function($form) { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + var extensionConfiguration = {}; + $.each($form.serializeArray(), function() { + extensionConfiguration[this.name] = this.value; + }); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'token': $(this.selectorWriteToken).text(), + 'action': 'extensionConfigurationWrite', + 'extensionKey': $form.attr('data-extensionKey'), + 'extensionConfiguration': extensionConfiguration + } }, - - /** - * Submit the form and show the result message - * - * @param {jQuery} $form The form of the current extension - */ - write: function($form) { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - var extensionConfiguration = { }; - $.each($form.serializeArray(), function() { - extensionConfiguration[this.name] = this.value; - }); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'token': $(this.selectorWriteToken).text(), - 'action': 'extensionConfigurationWrite', - 'extensionKey': $form.attr('data-extensionKey'), - 'extensionConfiguration': extensionConfiguration - } - }, - success: function (data) { - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }).always(function() { - $outputContainer.find('.alert-loading').remove(); + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); }); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } }, - - /** - * configuration properties - */ - initializeWrap: function() { - $('.t3js-emconf-offset').each(function() { - var $me = $(this), - $parent = $me.parent(), - id = $me.attr('id'), - val = $me.attr('value'), - valArr = val.split(','); - - $me.attr('data-offsetfield-x', '#' + id + '_offset_x') - .attr('data-offsetfield-y', '#' + id + '_offset_y') - .wrap('<div class="hidden"></div>'); - - var elementX = '' + - '<div class="form-multigroup-item">' + - '<div class="input-group">' + - '<div class="input-group-addon">x</div>' + - '<input id="' + id + '_offset_x" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' + - '</div>' + - '</div>'; - var elementY = '' + - '<div class="form-multigroup-item">' + - '<div class="input-group">' + - '<div class="input-group-addon">y</div>' + - '<input id="' + id + '_offset_y" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' + - '</div>' + - '</div>'; - - var offsetGroup = '<div class="form-multigroup-wrap">' + elementX + elementY + '</div>'; - $parent.append(offsetGroup); - $parent.find('.t3js-emconf-offset').keyup(function() { - var $target = $($(this).data('target')); - $target.attr( - 'value', - $($target.data('offsetfield-x')).val() + ',' + $($target.data('offsetfield-y')).val() - ); - }); - }); - - $('.t3js-emconf-wrap').each(function() { - var $me = $(this), - $parent = $me.parent(), - id = $me.attr('id'), - val = $me.attr('value'), - valArr = val.split('|'); - - $me.attr('data-wrapfield-start', '#' + id + '_wrap_start') - .attr('data-wrapfield-end', '#' + id + '_wrap_end') - .wrap('<div class="hidden"></div>'); - - var elementStart = '' + - '<div class="form-multigroup-item">' + - '<input id="' + id + '_wrap_start" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' + - '</div>'; - var elementEnd = '' + - '<div class="form-multigroup-item">' + - '<input id="' + id + '_wrap_end" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' + - '</div>'; - - var wrapGroup = '<div class="form-multigroup-wrap">' + elementStart + elementEnd + '</div>'; - $parent.append(wrapGroup); - $parent.find('.t3js-emconf-wrapfield').keyup(function() { - var $target = $($(this).data('target')); - $target.attr( - 'value', - $($target.data('wrapfield-start')).val() + '|' + $($target.data('wrapfield-end')).val() - ); - }); - }); + error: function(xhr) { + Router.handleAjaxError(xhr); } - }; + }).always(function() { + $outputContainer.find('.alert-loading').remove(); + }); + }, + + /** + * configuration properties + */ + initializeWrap: function() { + $('.t3js-emconf-offset').each(function() { + var $me = $(this), + $parent = $me.parent(), + id = $me.attr('id'), + val = $me.attr('value'), + valArr = val.split(','); + + $me.attr('data-offsetfield-x', '#' + id + '_offset_x') + .attr('data-offsetfield-y', '#' + id + '_offset_y') + .wrap('<div class="hidden"></div>'); + + var elementX = '' + + '<div class="form-multigroup-item">' + + '<div class="input-group">' + + '<div class="input-group-addon">x</div>' + + '<input id="' + id + '_offset_x" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' + + '</div>' + + '</div>'; + var elementY = '' + + '<div class="form-multigroup-item">' + + '<div class="input-group">' + + '<div class="input-group-addon">y</div>' + + '<input id="' + id + '_offset_y" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' + + '</div>' + + '</div>'; + + var offsetGroup = '<div class="form-multigroup-wrap">' + elementX + elementY + '</div>'; + $parent.append(offsetGroup); + $parent.find('.t3js-emconf-offset').keyup(function() { + var $target = $($(this).data('target')); + $target.attr( + 'value', + $($target.data('offsetfield-x')).val() + ',' + $($target.data('offsetfield-y')).val() + ); + }); + }); + + $('.t3js-emconf-wrap').each(function() { + var $me = $(this), + $parent = $me.parent(), + id = $me.attr('id'), + val = $me.attr('value'), + valArr = val.split('|'); + + $me.attr('data-wrapfield-start', '#' + id + '_wrap_start') + .attr('data-wrapfield-end', '#' + id + '_wrap_end') + .wrap('<div class="hidden"></div>'); + + var elementStart = '' + + '<div class="form-multigroup-item">' + + '<input id="' + id + '_wrap_start" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' + + '</div>'; + var elementEnd = '' + + '<div class="form-multigroup-item">' + + '<input id="' + id + '_wrap_end" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' + + '</div>'; + + var wrapGroup = '<div class="form-multigroup-wrap">' + elementStart + elementEnd + '</div>'; + $parent.append(wrapGroup); + $parent.find('.t3js-emconf-wrapfield').keyup(function() { + var $target = $($(this).data('target')); + $target.attr( + 'value', + $($target.data('wrapfield-start')).val() + '|' + $($target.data('wrapfield-end')).val() + ); + }); + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js index 55d81c2a24cc3e2103bb78ec6ce7081f59c67690..ad3a2dd1e122a95f8495ce595c54c388198ab328 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js @@ -15,294 +15,294 @@ * Module: TYPO3/CMS/Install/ExtensionScanner */ define(['jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Backend/Notification' + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Backend/Notification' ], function($, Router, Notification) { - 'use strict'; + 'use strict'; - return { - listOfAffectedRestFileHashes: [], - selectorFilesToken: '#t3js-extensionScanner-files-token', - selectorScanFileToken: '#t3js-extensionScanner-scan-file-token', - selectorMarkFullyScannedRestFilesToken: '#t3js-extensionScanner-mark-fully-scanned-rest-files-token', - selectorExtensionContainer: '.t3js-extensionScanner-extension', - selectorNumberOfFiles: '.t3js-extensionScanner-number-of-files', - selectorScanSingleTrigger: '.t3js-extensionScanner-scan-single', + return { + listOfAffectedRestFileHashes: [], + selectorFilesToken: '#t3js-extensionScanner-files-token', + selectorScanFileToken: '#t3js-extensionScanner-scan-file-token', + selectorMarkFullyScannedRestFilesToken: '#t3js-extensionScanner-mark-fully-scanned-rest-files-token', + selectorExtensionContainer: '.t3js-extensionScanner-extension', + selectorNumberOfFiles: '.t3js-extensionScanner-number-of-files', + selectorScanSingleTrigger: '.t3js-extensionScanner-scan-single', - initialize: function() { - var self = this; - $(document).on('click', this.selectorScanSingleTrigger, function(e) { - // Scan a single extension - var extension = $(e.target).data('extension'); - e.preventDefault(); - self.scanSingleExtension(extension); - return false; - }); - $(document).on('show.bs.collapse', this.selectorExtensionContainer, function(e) { - // Trigger extension scan on opening a extension collapsible - if ($(e.target).closest(self.selectorExtensionContainer).data('hasRun') !== 'true') { - $(this).find(self.selectorScanSingleTrigger).click(); - } - }); - $(document).on('click', '.t3js-extensionScanner-scan-all', function(e) { - // Scann all button - e.preventDefault(); - var $extensions = $(self.selectorExtensionContainer); - self.scanAll($extensions); - return false; - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorScanSingleTrigger, function(e) { + // Scan a single extension + var extension = $(e.target).data('extension'); + e.preventDefault(); + self.scanSingleExtension(extension); + return false; + }); + $(document).on('show.bs.collapse', this.selectorExtensionContainer, function(e) { + // Trigger extension scan on opening a extension collapsible + if ($(e.target).closest(self.selectorExtensionContainer).data('hasRun') !== 'true') { + $(this).find(self.selectorScanSingleTrigger).click(); + } + }); + $(document).on('click', '.t3js-extensionScanner-scan-all', function(e) { + // Scann all button + e.preventDefault(); + var $extensions = $(self.selectorExtensionContainer); + self.scanAll($extensions); + return false; + }); + }, - /** - * @param {string} extension - * @returns {string} - */ - getExtensionSelector: function(extension) { - return this.selectorExtensionContainer + '-' + extension; - }, + /** + * @param {string} extension + * @returns {string} + */ + getExtensionSelector: function(extension) { + return this.selectorExtensionContainer + '-' + extension; + }, - /** - * @param {JQuery} $extensions - */ - scanAll: function($extensions) { - var self = this; - $(this.selectorExtensionContainer) - .removeClass('panel-danger panel-warning panel-success') - .find('.panel-progress-bar') - .css('width', 0) - .attr('aria-valuenow', 0) - .find('span') - .text('0%'); - self.setProgressForAll(); - $extensions.each(function() { - var extension = $(this).data('extension'); - self.scanSingleExtension(extension); - }); - }, + /** + * @param {JQuery} $extensions + */ + scanAll: function($extensions) { + var self = this; + $(this.selectorExtensionContainer) + .removeClass('panel-danger panel-warning panel-success') + .find('.panel-progress-bar') + .css('width', 0) + .attr('aria-valuenow', 0) + .find('span') + .text('0%'); + self.setProgressForAll(); + $extensions.each(function() { + var extension = $(this).data('extension'); + self.scanSingleExtension(extension); + }); + }, - /** - * @param {string} extension - * @param {number} doneFiles - * @param {number} numberOfFiles - */ - setStatusMessageForScan: function(extension, doneFiles, numberOfFiles) { - $(this.getExtensionSelector(extension)) - .find(this.selectorNumberOfFiles) - .text('Checked ' + doneFiles + ' of ' + numberOfFiles + ' files'); - }, + /** + * @param {string} extension + * @param {number} doneFiles + * @param {number} numberOfFiles + */ + setStatusMessageForScan: function(extension, doneFiles, numberOfFiles) { + $(this.getExtensionSelector(extension)) + .find(this.selectorNumberOfFiles) + .text('Checked ' + doneFiles + ' of ' + numberOfFiles + ' files'); + }, - /** - * @param {string} extension - * @param {number} doneFiles - * @param {number} numberOfFiles - */ - setProgressForScan: function(extension, doneFiles, numberOfFiles) { - var percent = (doneFiles / numberOfFiles) * 100; - $(this.getExtensionSelector(extension)) - .find('.panel-progress-bar') - .css('width', percent + '%') - .attr('aria-valuenow', percent) - .find('span') - .text(percent + '%'); - }, + /** + * @param {string} extension + * @param {number} doneFiles + * @param {number} numberOfFiles + */ + setProgressForScan: function(extension, doneFiles, numberOfFiles) { + var percent = (doneFiles / numberOfFiles) * 100; + $(this.getExtensionSelector(extension)) + .find('.panel-progress-bar') + .css('width', percent + '%') + .attr('aria-valuenow', percent) + .find('span') + .text(percent + '%'); + }, - /** - * Update main progress bar - */ - setProgressForAll: function() { - var self = this; - var numberOfExtensions = $(this.selectorExtensionContainer).length; - var numberOfSuccess = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-success').length; - var numberOfWarning = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-warning').length; - var numberOfError = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-danger').length; - var numberOfScannedExtensions = numberOfSuccess + numberOfWarning + numberOfError; - var percent = (numberOfScannedExtensions / numberOfExtensions) * 100; - $('.t3js-extensionScanner-progress-all-extension .progress-bar') - .css('width', percent + '%') - .attr('aria-valuenow', percent) - .find('span') - .text(numberOfScannedExtensions + ' of ' + numberOfExtensions + ' scanned'); - if (numberOfScannedExtensions === numberOfExtensions) { - Notification.success('Scan finished', 'All extensions have been scanned'); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'extensionScannerMarkFullyScannedRestFiles', - 'token': $(self.selectorMarkFullyScannedRestFilesToken).text(), - 'hashes': self.uniqueArray(this.listOfAffectedRestFileHashes) - } - }, - cache: false, - success: function(data) { - if (data.success === true) { - Notification.success('Marked not affected files', 'Marked ' + data.markedAsNotAffected + ' ReST files as not affected.'); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }, + /** + * Update main progress bar + */ + setProgressForAll: function() { + var self = this; + var numberOfExtensions = $(this.selectorExtensionContainer).length; + var numberOfSuccess = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-success').length; + var numberOfWarning = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-warning').length; + var numberOfError = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-danger').length; + var numberOfScannedExtensions = numberOfSuccess + numberOfWarning + numberOfError; + var percent = (numberOfScannedExtensions / numberOfExtensions) * 100; + $('.t3js-extensionScanner-progress-all-extension .progress-bar') + .css('width', percent + '%') + .attr('aria-valuenow', percent) + .find('span') + .text(numberOfScannedExtensions + ' of ' + numberOfExtensions + ' scanned'); + if (numberOfScannedExtensions === numberOfExtensions) { + Notification.success('Scan finished', 'All extensions have been scanned'); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'extensionScannerMarkFullyScannedRestFiles', + 'token': $(self.selectorMarkFullyScannedRestFilesToken).text(), + 'hashes': self.uniqueArray(this.listOfAffectedRestFileHashes) + } + }, + cache: false, + success: function(data) { + if (data.success === true) { + Notification.success('Marked not affected files', 'Marked ' + data.markedAsNotAffected + ' ReST files as not affected.'); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }, - /** - * Helper method removing duplicate entries from an array - * - * @param {Array} anArray - * @returns {Array} - */ - uniqueArray: function(anArray) { - return anArray.filter(function(value, index, self) { - return self.indexOf(value) === index; - }); - }, + /** + * Helper method removing duplicate entries from an array + * + * @param {Array} anArray + * @returns {Array} + */ + uniqueArray: function(anArray) { + return anArray.filter(function(value, index, self) { + return self.indexOf(value) === index; + }); + }, - /** - * Handle a single extension scan - * - * @param {string} extension - */ - scanSingleExtension: function(extension) { - var self = this; - var $extensionContainer = $(this.getExtensionSelector(extension)); - var hitTemplate = $('#t3js-extensionScanner-file-hit-template').html(); - var restTemplate = $('#t3js-extensionScanner-file-hit-rest-template').html(); - var hitFound = false; - $extensionContainer.removeClass('panel-danger panel-warning panel-success t3js-extensionscan-finished'); - $extensionContainer.data('hasRun', 'true'); - $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Scanning...').attr('disabled', 'disabled'); - $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text('0'); - $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text('0'); - $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text('0'); - this.setProgressForAll(); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'extensionScannerFiles', - 'token': $(self.selectorFilesToken).text(), - 'extension': extension - } - }, - cache: false, - success: function(data) { - if (data.success === true && Array.isArray(data.files)) { - var numberOfFiles = data.files.length; - if (numberOfFiles > 0) { - self.setStatusMessageForScan(extension, 0, numberOfFiles); - $extensionContainer.find('.t3js-extensionScanner-extension-body').text(''); - var doneFiles = 0; - data.files.forEach(function(file) { - $.ajax({ - method: 'POST', - data: { - 'install': { - 'action': 'extensionScannerScanFile', - 'token': $(self.selectorScanFileToken).text(), - 'extension': extension, - 'file': file - } - }, - url: Router.getUrl(), - cache: false, - success: function(fileData) { - doneFiles = doneFiles + 1; - self.setStatusMessageForScan(extension, doneFiles, numberOfFiles); - self.setProgressForScan(extension, doneFiles, numberOfFiles); - if (fileData.success && $.isArray(fileData.matches)) { - $(fileData.matches).each(function() { - hitFound = true; - var match = this; - var aMatch = $(hitTemplate).clone(); - aMatch.find('.t3js-extensionScanner-hit-file-panel-head').attr('href', '#collapse' + match.uniqueId); - aMatch.find('.t3js-extensionScanner-hit-file-panel-body').attr('id', 'collapse' + match.uniqueId); - aMatch.find('.t3js-extensionScanner-hit-filename').text(file); - aMatch.find('.t3js-extensionScanner-hit-message').text(match.message); - if (match.indicator === 'strong') { - aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') - .append('<span class="badge" title="Reliable match, false positive unlikely">strong</span>'); - } else { - aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') - .append('<span class="badge" title="Probable match, but can be a false positive">weak</span>'); - } - if (match.silenced === true) { - aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') - .append('<span class="badge" title="Match has been annotated by extension author as false positive match">silenced</span>'); - } - aMatch.find('.t3js-extensionScanner-hit-file-lineContent').empty().text(match.lineContent); - aMatch.find('.t3js-extensionScanner-hit-file-line').empty().text(match.line + ': '); - if ($.isArray(match.restFiles)) { - $(match.restFiles).each(function() { - var restFile = this; - var aRest = $(restTemplate).clone(); - aRest.find('.t3js-extensionScanner-hit-rest-panel-head').attr('href', '#collapse' + restFile.uniqueId); - aRest.find('.t3js-extensionScanner-hit-rest-panel-head .badge').empty().text(restFile.version); - aRest.find('.t3js-extensionScanner-hit-rest-panel-body').attr('id', 'collapse' + restFile.uniqueId); - aRest.find('.t3js-extensionScanner-hit-rest-headline').text(restFile.headline); - aRest.find('.t3js-extensionScanner-hit-rest-body').text(restFile.content); - aRest.addClass('panel-' + restFile.class); - aMatch.find('.t3js-extensionScanner-hit-file-rest-container').append(aRest); - self.listOfAffectedRestFileHashes.push(restFile.file_hash); - }); - } - var panelClass = - aMatch.find('.panel-breaking', '.t3js-extensionScanner-hit-file-rest-container').length > 0 - ? 'panel-danger' - : 'panel-warning'; - aMatch.addClass(panelClass); - $extensionContainer.find('.t3js-extensionScanner-extension-body').removeClass('hide').append(aMatch); - if (panelClass === 'panel-danger') { - $extensionContainer.removeClass('panel-warning').addClass(panelClass); - } - if (panelClass === 'panel-warning' && !$extensionContainer.hasClass('panel-danger')) { - $extensionContainer.addClass(panelClass); - } - }); - } - if (fileData.success) { - var currentLinesOfCode = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-loc').text()); - $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text(currentLinesOfCode + parseInt(fileData.effectiveCodeLines)); - if (fileData.isFileIgnored) { - var currentIgnoredFiles = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').text()); - $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text(currentIgnoredFiles + 1); - } - var currentIgnoredLines = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').text()); - $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text(currentIgnoredLines + parseInt(fileData.ignoredLines)); - } - if (doneFiles === numberOfFiles) { - if (!hitFound) { - $extensionContainer.addClass('panel-success'); - } - $extensionContainer.addClass('t3js-extensionscan-finished'); - self.setProgressForAll(); - $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Rescan').attr('disabled', null); - } - }, - error: function(data) { - doneFiles = doneFiles + 1; - self.setStatusMessageForScan(extension, doneFiles, numberOfFiles); - self.setProgressForScan(extension, doneFiles, numberOfFiles); - self.setProgressForAll(); - Notification.error('Oops, an error occurred', 'Please look at the console output for details'); - console.error(data); - } - }); - }); - } else { - Notification.warning('No files found', 'The extension EXT:' + extension + ' contains no files we can scan'); - } - } else { - Notification.error('Oops, an error occurred', 'Please look at the console output for details'); - console.error(data); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + /** + * Handle a single extension scan + * + * @param {string} extension + */ + scanSingleExtension: function(extension) { + var self = this; + var $extensionContainer = $(this.getExtensionSelector(extension)); + var hitTemplate = $('#t3js-extensionScanner-file-hit-template').html(); + var restTemplate = $('#t3js-extensionScanner-file-hit-rest-template').html(); + var hitFound = false; + $extensionContainer.removeClass('panel-danger panel-warning panel-success t3js-extensionscan-finished'); + $extensionContainer.data('hasRun', 'true'); + $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Scanning...').attr('disabled', 'disabled'); + $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text('0'); + $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text('0'); + $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text('0'); + this.setProgressForAll(); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'extensionScannerFiles', + 'token': $(self.selectorFilesToken).text(), + 'extension': extension + } + }, + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.files)) { + var numberOfFiles = data.files.length; + if (numberOfFiles > 0) { + self.setStatusMessageForScan(extension, 0, numberOfFiles); + $extensionContainer.find('.t3js-extensionScanner-extension-body').text(''); + var doneFiles = 0; + data.files.forEach(function(file) { + $.ajax({ + method: 'POST', + data: { + 'install': { + 'action': 'extensionScannerScanFile', + 'token': $(self.selectorScanFileToken).text(), + 'extension': extension, + 'file': file + } + }, + url: Router.getUrl(), + cache: false, + success: function(fileData) { + doneFiles = doneFiles + 1; + self.setStatusMessageForScan(extension, doneFiles, numberOfFiles); + self.setProgressForScan(extension, doneFiles, numberOfFiles); + if (fileData.success && $.isArray(fileData.matches)) { + $(fileData.matches).each(function() { + hitFound = true; + var match = this; + var aMatch = $(hitTemplate).clone(); + aMatch.find('.t3js-extensionScanner-hit-file-panel-head').attr('href', '#collapse' + match.uniqueId); + aMatch.find('.t3js-extensionScanner-hit-file-panel-body').attr('id', 'collapse' + match.uniqueId); + aMatch.find('.t3js-extensionScanner-hit-filename').text(file); + aMatch.find('.t3js-extensionScanner-hit-message').text(match.message); + if (match.indicator === 'strong') { + aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') + .append('<span class="badge" title="Reliable match, false positive unlikely">strong</span>'); + } else { + aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') + .append('<span class="badge" title="Probable match, but can be a false positive">weak</span>'); + } + if (match.silenced === true) { + aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges') + .append('<span class="badge" title="Match has been annotated by extension author as false positive match">silenced</span>'); + } + aMatch.find('.t3js-extensionScanner-hit-file-lineContent').empty().text(match.lineContent); + aMatch.find('.t3js-extensionScanner-hit-file-line').empty().text(match.line + ': '); + if ($.isArray(match.restFiles)) { + $(match.restFiles).each(function() { + var restFile = this; + var aRest = $(restTemplate).clone(); + aRest.find('.t3js-extensionScanner-hit-rest-panel-head').attr('href', '#collapse' + restFile.uniqueId); + aRest.find('.t3js-extensionScanner-hit-rest-panel-head .badge').empty().text(restFile.version); + aRest.find('.t3js-extensionScanner-hit-rest-panel-body').attr('id', 'collapse' + restFile.uniqueId); + aRest.find('.t3js-extensionScanner-hit-rest-headline').text(restFile.headline); + aRest.find('.t3js-extensionScanner-hit-rest-body').text(restFile.content); + aRest.addClass('panel-' + restFile.class); + aMatch.find('.t3js-extensionScanner-hit-file-rest-container').append(aRest); + self.listOfAffectedRestFileHashes.push(restFile.file_hash); + }); + } + var panelClass = + aMatch.find('.panel-breaking', '.t3js-extensionScanner-hit-file-rest-container').length > 0 + ? 'panel-danger' + : 'panel-warning'; + aMatch.addClass(panelClass); + $extensionContainer.find('.t3js-extensionScanner-extension-body').removeClass('hide').append(aMatch); + if (panelClass === 'panel-danger') { + $extensionContainer.removeClass('panel-warning').addClass(panelClass); + } + if (panelClass === 'panel-warning' && !$extensionContainer.hasClass('panel-danger')) { + $extensionContainer.addClass(panelClass); + } + }); + } + if (fileData.success) { + var currentLinesOfCode = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-loc').text()); + $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text(currentLinesOfCode + parseInt(fileData.effectiveCodeLines)); + if (fileData.isFileIgnored) { + var currentIgnoredFiles = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').text()); + $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text(currentIgnoredFiles + 1); + } + var currentIgnoredLines = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').text()); + $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text(currentIgnoredLines + parseInt(fileData.ignoredLines)); + } + if (doneFiles === numberOfFiles) { + if (!hitFound) { + $extensionContainer.addClass('panel-success'); + } + $extensionContainer.addClass('t3js-extensionscan-finished'); + self.setProgressForAll(); + $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Rescan').attr('disabled', null); + } + }, + error: function(data) { + doneFiles = doneFiles + 1; + self.setStatusMessageForScan(extension, doneFiles, numberOfFiles); + self.setProgressForScan(extension, doneFiles, numberOfFiles); + self.setProgressForAll(); + Notification.error('Oops, an error occurred', 'Please look at the console output for details'); + console.error(data); + } + }); + }); + } else { + Notification.warning('No files found', 'The extension EXT:' + extension + ' contains no files we can scan'); + } + } else { + Notification.error('Oops, an error occurred', 'Please look at the console output for details'); + console.error(data); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js index 8554df58846c5828f8e70c239952f53c51403c4f..372e277d6d225c0bd8fc93fd162481571b20927e 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js @@ -14,36 +14,36 @@ /** * Module: TYPO3/CMS/Install/FlashMessage */ -define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) { + 'use strict'; - /** - * @type {{template: (*)}} - */ - var FlashMessage = { - template: $('<div class="t3js-message typo3-message alert"><h4></h4><p class="messageText"></p></div>') - }; + /** + * @type {{template: (*)}} + */ + var FlashMessage = { + template: $('<div class="t3js-message typo3-message alert"><h4></h4><p class="messageText"></p></div>') + }; - /** - * render a FlashMessage - * @param {Number} severity - * @param {String} title - * @param {String} message - * @returns {jQuery} - */ - FlashMessage.render = function (severity, title, message) { - var flashMessage = this.template.clone(); - flashMessage.addClass('alert-' + Severity.getCssClass(severity)); - if (title) { - flashMessage.find('h4').text(title); - } - if (message) { - flashMessage.find('.messageText').text(message); - } else { - flashMessage.find('.messageText').remove(); - } - return flashMessage; - }; + /** + * render a FlashMessage + * @param {Number} severity + * @param {String} title + * @param {String} message + * @returns {jQuery} + */ + FlashMessage.render = function(severity, title, message) { + var flashMessage = this.template.clone(); + flashMessage.addClass('alert-' + Severity.getCssClass(severity)); + if (title) { + flashMessage.find('h4').text(title); + } + if (message) { + flashMessage.find('.messageText').text(message); + } else { + flashMessage.find('.messageText').remove(); + } + return flashMessage; + }; - return FlashMessage; + return FlashMessage; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js index 70790e82835066918625867fd5957e76fe85125e..2cd3a0a9cab15c668fba5897b1d93bfe99693fb4 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js @@ -15,129 +15,129 @@ * Module: TYPO3/CMS/Install/FolderStructure */ define(['jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderBadge: '.t3js-folderStructure-badge', - selectorFixTrigger: '.t3js-folderStructure-errors-fix', - selectorOutputContainer: '.t3js-folderStructure-output', - selectorErrorContainer: '.t3js-folderStructure-errors', - selectorErrorList: '.t3js-folderStructure-errors-list', - selectorErrorFixTrigger: '.t3js-folderStructure-errors-fix', - selectorOkContainer: '.t3js-folderStructure-ok', - selectorOkList: '.t3js-folderStructure-ok-list', - selectorPermissionContainer: '.t3js-folderStructure-permissions', + return { + selectorGridderBadge: '.t3js-folderStructure-badge', + selectorFixTrigger: '.t3js-folderStructure-errors-fix', + selectorOutputContainer: '.t3js-folderStructure-output', + selectorErrorContainer: '.t3js-folderStructure-errors', + selectorErrorList: '.t3js-folderStructure-errors-list', + selectorErrorFixTrigger: '.t3js-folderStructure-errors-fix', + selectorOkContainer: '.t3js-folderStructure-ok', + selectorOkList: '.t3js-folderStructure-ok-list', + selectorPermissionContainer: '.t3js-folderStructure-permissions', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Get status on initialize to have the badge and content ready - self.getStatus(); + // Get status on initialize to have the badge and content ready + self.getStatus(); - $(document).on('click', this.selectorErrorFixTrigger, function(e) { - e.preventDefault(); - self.fix(); - }); - }, + $(document).on('click', this.selectorErrorFixTrigger, function(e) { + e.preventDefault(); + self.fix(); + }); + }, - getStatus: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var $errorContainer = $(this.selectorErrorContainer); - var $errorBadge = $(this.selectorGridderBadge); - $errorBadge.text('').hide(); - var $errorList = $(this.selectorErrorList); - var $okContainer = $(this.selectorOkContainer); - var $okList = $(this.selectorOkList); - var $permissionContainer = $(this.selectorPermissionContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $.ajax({ - url: Router.getUrl('folderStructureGetStatus'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true && Array.isArray(data.errorStatus)) { - var errorCount = 0; - if (data.errorStatus.length > 0) { - $errorContainer.show(); - $errorList.empty(); - data.errorStatus.forEach((function(element) { - errorCount += 1; - $errorBadge.text(errorCount).show(); - var message = InfoBox.render(element.severity, element.title, element.message); - $errorList.append(message); - })); - } else { - $errorContainer.hide(); - } - } - if (data.success === true && Array.isArray(data.okStatus)) { - if (data.okStatus.length > 0) { - $okContainer.show(); - $okList.empty(); - data.okStatus.forEach((function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $okList.append(message); - })); - } else { - $okList.hide(); - } - } - var element = data.folderStructureFilePermissionStatus; - message = InfoBox.render(element.severity, element.title, element.message); - $permissionContainer.empty().append(message); - element = data.folderStructureDirectoryPermissionStatus; - message = InfoBox.render(element.severity, element.title, element.message); - $permissionContainer.append(message); - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getStatus: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var $errorContainer = $(this.selectorErrorContainer); + var $errorBadge = $(this.selectorGridderBadge); + $errorBadge.text('').hide(); + var $errorList = $(this.selectorErrorList); + var $okContainer = $(this.selectorOkContainer); + var $okList = $(this.selectorOkList); + var $permissionContainer = $(this.selectorPermissionContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + url: Router.getUrl('folderStructureGetStatus'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true && Array.isArray(data.errorStatus)) { + var errorCount = 0; + if (data.errorStatus.length > 0) { + $errorContainer.show(); + $errorList.empty(); + data.errorStatus.forEach((function(element) { + errorCount += 1; + $errorBadge.text(errorCount).show(); + var message = InfoBox.render(element.severity, element.title, element.message); + $errorList.append(message); + })); + } else { + $errorContainer.hide(); + } + } + if (data.success === true && Array.isArray(data.okStatus)) { + if (data.okStatus.length > 0) { + $okContainer.show(); + $okList.empty(); + data.okStatus.forEach((function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $okList.append(message); + })); + } else { + $okList.hide(); + } + } + var element = data.folderStructureFilePermissionStatus; + message = InfoBox.render(element.severity, element.title, element.message); + $permissionContainer.empty().append(message); + element = data.folderStructureDirectoryPermissionStatus; + message = InfoBox.render(element.severity, element.title, element.message); + $permissionContainer.append(message); + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - fix: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('folderStructureFix'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true && Array.isArray(data.fixedStatus)) { - if (data.fixedStatus.length > 0) { - data.fixedStatus.forEach(function(element) { - message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - message = InfoBox.render(Severity.warning, 'Nothing fixed', ''); - $outputContainer.append(message); - } - self.getStatus(); - } else { - message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + fix: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('folderStructureFix'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true && Array.isArray(data.fixedStatus)) { + if (data.fixedStatus.length > 0) { + data.fixedStatus.forEach(function(element) { + message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + message = InfoBox.render(Severity.warning, 'Nothing fixed', ''); + $outputContainer.append(message); + } + self.getStatus(); + } else { + message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - removeLoadingMessage: function($container) { - $container.find('.alert-loading').remove(); - } - }; + removeLoadingMessage: function($container) { + $container.find('.alert-loading').remove(); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js index c4cddcafc10c33b2be2b45892c51284c62385d25..418bcccbd0c7535bdaeeee6bcb84ca0419ec1600 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js @@ -15,87 +15,87 @@ * Module: TYPO3/CMS/Install/ImageProcessing */ define(['jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-imageProcessing-open', - selectorExecuteTrigger: '.t3js-imageProcessing-execute', - selectorTestContainer: '.t3js-imageProcessing-twinContainer', - selectorTwinImageTemplate: '.t3js-imageProcessing-twinImage-template', - selectorCommandContainer: '.t3js-imageProcessing-command', - selectorCommandText: '.t3js-imageProcessing-command-text', - selectorTwinImages: '.t3js-imageProcessing-images', + return { + selectorGridderOpener: 't3js-imageProcessing-open', + selectorExecuteTrigger: '.t3js-imageProcessing-execute', + selectorTestContainer: '.t3js-imageProcessing-twinContainer', + selectorTwinImageTemplate: '.t3js-imageProcessing-twinImage-template', + selectorCommandContainer: '.t3js-imageProcessing-command', + selectorCommandText: '.t3js-imageProcessing-command-text', + selectorTwinImages: '.t3js-imageProcessing-images', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Load main content on first open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { - $card.data('isInitialized', true); - self.runTests(); - } - }); + // Load main content on first open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { + $card.data('isInitialized', true); + self.runTests(); + } + }); - $(document).on('click', this.selectorExecuteTrigger, function(e) { - e.preventDefault(); - self.runTests(); - }); - }, + $(document).on('click', this.selectorExecuteTrigger, function(e) { + e.preventDefault(); + self.runTests(); + }); + }, - runTests: function() { - var self = this; - var $twinImageTemplate = $(this.selectorTwinImageTemplate); - $(this.selectorTestContainer).each(function() { - var $container = $(this); - var testType = $container.data('test'); - var message = InfoBox.render(Severity.loading, 'Loading...', ''); - $container.empty().html(message); - $.ajax({ - url: Router.getUrl(testType), - cache: false, - success: function(data) { - if (data.success === true) { - $container.empty(); - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $container.append(message); - }); - } - var $aTwin = $twinImageTemplate.clone(); - $aTwin.removeClass('t3js-imageProcessing-twinImage-template'); - if (data.fileExists === true) { - $aTwin.find('img.reference').attr('src', data.referenceFile); - $aTwin.find('img.result').attr('src', data.outputFile); - $aTwin.find(self.selectorTwinImages).show(); - } - if (Array.isArray(data.command) && data.command.length > 0) { - $aTwin.find(self.selectorCommandContainer).show(); - var commandText = []; - data.command.forEach(function(element) { - commandText.push('<strong>Command:</strong>\n' + element[1]); - if (element.length === 3) { - commandText.push('<strong>Result:</strong>\n' + element[2]); - } - }); - $aTwin.find(self.selectorCommandText).html(commandText.join('\n')); - } - $container.append($aTwin); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } + runTests: function() { + var self = this; + var $twinImageTemplate = $(this.selectorTwinImageTemplate); + $(this.selectorTestContainer).each(function() { + var $container = $(this); + var testType = $container.data('test'); + var message = InfoBox.render(Severity.loading, 'Loading...', ''); + $container.empty().html(message); + $.ajax({ + url: Router.getUrl(testType), + cache: false, + success: function(data) { + if (data.success === true) { + $container.empty(); + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $container.append(message); }); - }); - } - }; + } + var $aTwin = $twinImageTemplate.clone(); + $aTwin.removeClass('t3js-imageProcessing-twinImage-template'); + if (data.fileExists === true) { + $aTwin.find('img.reference').attr('src', data.referenceFile); + $aTwin.find('img.result').attr('src', data.outputFile); + $aTwin.find(self.selectorTwinImages).show(); + } + if (Array.isArray(data.command) && data.command.length > 0) { + $aTwin.find(self.selectorCommandContainer).show(); + var commandText = []; + data.command.forEach(function(element) { + commandText.push('<strong>Command:</strong>\n' + element[1]); + if (element.length === 3) { + commandText.push('<strong>Result:</strong>\n' + element[2]); + } + }); + $aTwin.find(self.selectorCommandText).html(commandText.join('\n')); + } + $container.append($aTwin); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js index 29278133351900bdffc0647851d1a9215eae0f98..10f44df0517e01fc63dfbabb5ad813f1c93824fb 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js @@ -14,36 +14,36 @@ /** * Module: TYPO3/CMS/Install/InfoBox */ -define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) { + 'use strict'; - /** - * @type {{template: (*)}} - */ - var InfoBox = { - template: $('<div class="t3js-infobox callout callout-sm"><h4 class="callout-title"></h4><div class="callout-body"></div></div>') - }; + /** + * @type {{template: (*)}} + */ + var InfoBox = { + template: $('<div class="t3js-infobox callout callout-sm"><h4 class="callout-title"></h4><div class="callout-body"></div></div>') + }; - /** - * render a InfoBox - * @param {Number} severity - * @param {String} title - * @param {String} message - * @returns {jQuery} - */ - InfoBox.render = function (severity, title, message) { - var infoBox = this.template.clone(); - infoBox.addClass('callout-' + Severity.getCssClass(severity)); - if (title) { - infoBox.find('h4').text(title); - } - if (message) { - infoBox.find('.callout-body').text(message); - } else { - infoBox.find('.callout-body').remove(); - } - return infoBox; - }; + /** + * render a InfoBox + * @param {Number} severity + * @param {String} title + * @param {String} message + * @returns {jQuery} + */ + InfoBox.render = function(severity, title, message) { + var infoBox = this.template.clone(); + infoBox.addClass('callout-' + Severity.getCssClass(severity)); + if (title) { + infoBox.find('h4').text(title); + } + if (message) { + infoBox.find('.callout-body').text(message); + } else { + infoBox.find('.callout-body').remove(); + } + return infoBox; + }; - return InfoBox; + return InfoBox; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js index f96e1850344815e6028c9420ab93a00ac858fb7e..dbf9dd494b97cf2da7b6c0a25820d6a035acc366 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js @@ -15,201 +15,201 @@ * Module: TYPO3/CMS/Install/LocalConfiguration */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-localConfiguration-open', - selectorToggleAllTrigger: '.t3js-localConfiguration-toggleAll', - selectorWriteTrigger: '.t3js-localConfiguration-write', - selectorSearchTrigger: '.t3js-localConfiguration-search', - selectorWriteToken: '#t3js-localConfiguration-write-token', - selectorContentContainer: '.t3js-localConfiguration-content', - selectorOutputContainer: '.t3js-localConfiguration-output', + return { + selectorGridderOpener: 't3js-localConfiguration-open', + selectorToggleAllTrigger: '.t3js-localConfiguration-toggleAll', + selectorWriteTrigger: '.t3js-localConfiguration-write', + selectorSearchTrigger: '.t3js-localConfiguration-search', + selectorWriteToken: '#t3js-localConfiguration-write-token', + selectorContentContainer: '.t3js-localConfiguration-content', + selectorOutputContainer: '.t3js-localConfiguration-output', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Get configuration list on card open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener)) { - self.getContent(); - } - }); + // Get configuration list on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getContent(); + } + }); - // Write out new settings - $(document).on('click', this.selectorWriteTrigger, function() { - self.write(); - }); + // Write out new settings + $(document).on('click', this.selectorWriteTrigger, function() { + self.write(); + }); - // Expand / collapse "Toggle all" button - $(document).on('click', this.selectorToggleAllTrigger, function() { - var $panels = $('.t3js-localConfiguration .panel-collapse'); - var action = ($panels.eq(0).hasClass('in')) ? 'hide' : 'show'; - $panels.collapse(action); - }); + // Expand / collapse "Toggle all" button + $(document).on('click', this.selectorToggleAllTrigger, function() { + var $panels = $('.t3js-localConfiguration .panel-collapse'); + var action = ($panels.eq(0).hasClass('in')) ? 'hide' : 'show'; + $panels.collapse(action); + }); - // Make jquerys "contains" work case-insensitive - jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) { - return function (elem) { - return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; - }; - }); + // Make jquerys "contains" work case-insensitive + jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) { + return function(elem) { + return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; + }; + }); - // Focus search field on certain user interactions - $(document).on('keydown', function(e) { - var $searchInput = $(self.selectorSearchTrigger); - if (e.ctrlKey || e.metaKey) { - // Focus search field on ctrl-f - switch (String.fromCharCode(e.which).toLowerCase()) { - case 'f': - e.preventDefault(); - $searchInput.focus(); - break; - } - } else if (e.keyCode === 27) { - // Clear search on ESC key - e.preventDefault(); - $searchInput.val('').focus(); - } - }); + // Focus search field on certain user interactions + $(document).on('keydown', function(e) { + var $searchInput = $(self.selectorSearchTrigger); + if (e.ctrlKey || e.metaKey) { + // Focus search field on ctrl-f + switch (String.fromCharCode(e.which).toLowerCase()) { + case 'f': + e.preventDefault(); + $searchInput.focus(); + break; + } + } else if (e.keyCode === 27) { + // Clear search on ESC key + e.preventDefault(); + $searchInput.val('').focus(); + } + }); - // Perform expand collapse on search matches - $(document).on('keyup', this.selectorSearchTrigger, function() { - var typedQuery = $(this).val(); - var $searchInput = $(self.selectorSearchTrigger); - $('div.item').each(function() { - var $item = $(this); - if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { - $item.removeClass('hidden').addClass('searchhit'); - } else { - $item.removeClass('searchhit').addClass('hidden'); - } - }); - $('.searchhit').parent().collapse('show'); - self.handleButtonScrolling(); - // Make search field clearable - require(['jquery.clearable'], function() { - var searchResultShown = ('' !== $searchInput.first().val()); - $searchInput.clearable().focus(); - }); - }); + // Perform expand collapse on search matches + $(document).on('keyup', this.selectorSearchTrigger, function() { + var typedQuery = $(this).val(); + var $searchInput = $(self.selectorSearchTrigger); + $('div.item').each(function() { + var $item = $(this); + if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { + $item.removeClass('hidden').addClass('searchhit'); + } else { + $item.removeClass('searchhit').addClass('hidden'); + } + }); + $('.searchhit').parent().collapse('show'); + self.handleButtonScrolling(); + // Make search field clearable + require(['jquery.clearable'], function() { + var searchResultShown = ('' !== $searchInput.first().val()); + $searchInput.clearable().focus(); + }); + }); - // Trigger fixed button calculation on collapse / expand - $(document).on('shown.bs.collapse', '.gridder-show .collapse', function() { - self.handleButtonScrolling(); - }); - $(document).on('hidden.bs.collapse', '.gridder-show .collapse', function() { - self.handleButtonScrolling(); - }); - }, + // Trigger fixed button calculation on collapse / expand + $(document).on('shown.bs.collapse', '.gridder-show .collapse', function() { + self.handleButtonScrolling(); + }); + $(document).on('hidden.bs.collapse', '.gridder-show .collapse', function() { + self.handleButtonScrolling(); + }); + }, - getContent: function() { - var outputContainer = $(this.selectorContentContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('localConfigurationGetContent'), - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - outputContainer.empty().append(data.html); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - outputContainer.empty().append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getContent: function() { + var outputContainer = $(this.selectorContentContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('localConfigurationGetContent'), + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + outputContainer.empty().append(data.html); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + outputContainer.empty().append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - write: function() { - var configurationValues = {}; - $('.gridder-show .t3js-localConfiguration-pathValue').each(function(i, element) { - var $element = $(element); - if ($element.attr('type') === 'checkbox') { - if (element.checked) { - configurationValues[$element.data('path')] = '1'; - } else { - configurationValues[$element.data('path')] = '0'; - } - } else { - configurationValues[$element.data('path')] = $element.val(); - } - }); - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'localConfigurationWrite', - 'token': $(this.selectorWriteToken).text(), - 'configurationValues': configurationValues - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + write: function() { + var configurationValues = {}; + $('.gridder-show .t3js-localConfiguration-pathValue').each(function(i, element) { + var $element = $(element); + if ($element.attr('type') === 'checkbox') { + if (element.checked) { + configurationValues[$element.data('path')] = '1'; + } else { + configurationValues[$element.data('path')] = '0'; + } + } else { + configurationValues[$element.data('path')] = $element.val(); + } + }); + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'localConfigurationWrite', + 'token': $(this.selectorWriteToken).text(), + 'configurationValues': configurationValues + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - /** - * Fix or unfix the "Write configuration" / "Toggle all" buttons at browser window - * bottom if a scrollbar is shown - */ - handleButtonScrolling: function() { - var $fixedFooterHandler = $('#fixed-footer-handler'); - if ($fixedFooterHandler.length > 0) { - var $fixedFooter = $('#fixed-footer'); - if (!this.isScrolledIntoView($fixedFooterHandler)) { - $fixedFooter.addClass('fixed'); - $fixedFooter.width($('.t3js-localConfiguration .panel-group').width()); - } else { - $fixedFooter.removeClass('fixed'); - } - } - }, + /** + * Fix or unfix the "Write configuration" / "Toggle all" buttons at browser window + * bottom if a scrollbar is shown + */ + handleButtonScrolling: function() { + var $fixedFooterHandler = $('#fixed-footer-handler'); + if ($fixedFooterHandler.length > 0) { + var $fixedFooter = $('#fixed-footer'); + if (!this.isScrolledIntoView($fixedFooterHandler)) { + $fixedFooter.addClass('fixed'); + $fixedFooter.width($('.t3js-localConfiguration .panel-group').width()); + } else { + $fixedFooter.removeClass('fixed'); + } + } + }, - /** - * Helper of handleButtonScrolling() - * See if an element is within current viewport. - * - * @param element - * @returns {boolean} - */ - isScrolledIntoView: function(element) { - var $window = $(window); - var docViewTop = $window.scrollTop(); - var docViewBottom = docViewTop + $window.height(); - var $elem = $(element); - var elemTop = $elem.offset().top; - var elemBottom = elemTop + $elem.height(); - return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); - } - }; + /** + * Helper of handleButtonScrolling() + * See if an element is within current viewport. + * + * @param element + * @returns {boolean} + */ + isScrolledIntoView: function(element) { + var $window = $(window); + var docViewTop = $window.scrollTop(); + var docViewBottom = docViewTop + $window.height(); + var $elem = $(element); + var elemTop = $elem.offset().top; + var elemBottom = elemTop + $elem.height(); + return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js index dae54e295aae4b15152e92dd3bd7efadd1502886..3530e07687b4bf2f1f37f4fb73181b00bc31e3bf 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js @@ -15,63 +15,63 @@ * Module: TYPO3/CMS/Install/CreateAdmin */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorSendToken: '#t3js-mailTest-token', - selectorForm: '#t3js-mailTest-form', - selectorEmail: '.t3js-mailTest-email', - selectorOutputContainer: '.t3js-mailTest-output', + return { + selectorSendToken: '#t3js-mailTest-token', + selectorForm: '#t3js-mailTest-form', + selectorEmail: '.t3js-mailTest-email', + selectorOutputContainer: '.t3js-mailTest-output', - initialize: function() { - var self = this; - $(this.selectorForm).submit(function(e) { - e.preventDefault(); - self.send(); - }); - }, + initialize: function() { + var self = this; + $(this.selectorForm).submit(function(e) { + e.preventDefault(); + self.send(); + }); + }, - send: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'mailTest', - 'token': $(this.selectorSendToken).text(), - 'email': $('.t3js-mailTest-email').val() - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.html(message); - }); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - // 500 can happen here if the mail configuration is broken - var message = InfoBox.render(Severity.error, 'Please check your mail settings', 'Sending test mail failed'); - $outputContainer.empty().html(message); - } - }); - } - }; + send: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'mailTest', + 'token': $(this.selectorSendToken).text(), + 'email': $('.t3js-mailTest-email').val() + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.html(message); + }); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + // 500 can happen here if the mail configuration is broken + var message = InfoBox.render(Severity.error, 'Please check your mail settings', 'Sending test mail failed'); + $outputContainer.empty().html(message); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js index f9aff9a5d7fe1a5e395729df10f39f8a9ef51280..ffd696cc2ad2bef03b2ec8ded9ec5dc42824fd9b 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js @@ -15,31 +15,31 @@ * Module: TYPO3/CMS/Install/Cache */ define([ - 'jquery' + 'jquery' ], function($) { - 'use strict'; + 'use strict'; - return { - initialize: function(field) { - // Simple password strength indicator - $(document).on('keyup', field, function() { - var value = $(this).val(); - var strongRegex = new RegExp('^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g'); - var mediumRegex = new RegExp('^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g'); - var enoughRegex = new RegExp('(?=.{8,}).*', 'g'); + return { + initialize: function(field) { + // Simple password strength indicator + $(document).on('keyup', field, function() { + var value = $(this).val(); + var strongRegex = new RegExp('^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g'); + var mediumRegex = new RegExp('^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g'); + var enoughRegex = new RegExp('(?=.{8,}).*', 'g'); - if (value.length === 0) { - $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42'); - } else if (!enoughRegex.test(value)) { - $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42'); - } else if (strongRegex.test(value)) { - $(this).attr('style', 'background-color:#CDEACA; border:1px solid #58B548'); - } else if (mediumRegex.test(value)) { - $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D'); - } else { - $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D'); - } - }); - } - }; + if (value.length === 0) { + $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42'); + } else if (!enoughRegex.test(value)) { + $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42'); + } else if (strongRegex.test(value)) { + $(this).attr('style', 'background-color:#CDEACA; border:1px solid #58B548'); + } else if (mediumRegex.test(value)) { + $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D'); + } else { + $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D'); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js index 62dbf59229643d1874e864868b794a54aae9cce9..7b2536bdf6f4633f966d544e0c6a19e2628243b0 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js @@ -15,119 +15,119 @@ * Module: TYPO3/CMS/Install/Presets */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGetContentToken: '#t3js-presets-getContent-token', - selectorActivateToken: '#t3js-presets-activate-token', - selectorGridderOpener: 't3js-presets-open', - selectorActivateTrigger: '.t3js-presets-activate', - selectorContentContainer: '.t3js-presets-content', - selectorOutputContainer: '.t3js-presets-output', - selectorImageExecutable: '.t3js-presets-image-executable', - selectorImageExecutableTrigger: '.t3js-presets-image-executable-trigger', + return { + selectorGetContentToken: '#t3js-presets-getContent-token', + selectorActivateToken: '#t3js-presets-activate-token', + selectorGridderOpener: 't3js-presets-open', + selectorActivateTrigger: '.t3js-presets-activate', + selectorContentContainer: '.t3js-presets-content', + selectorOutputContainer: '.t3js-presets-output', + selectorImageExecutable: '.t3js-presets-image-executable', + selectorImageExecutableTrigger: '.t3js-presets-image-executable-trigger', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Get current system maintainer list on card open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener)) { - self.getContent(); - } - }); + // Get current system maintainer list on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getContent(); + } + }); - // Load content on click image executable path button - $(document).on('click', this.selectorImageExecutableTrigger, function(e) { - e.preventDefault(); - self.getContent(); - }); + // Load content on click image executable path button + $(document).on('click', this.selectorImageExecutableTrigger, function(e) { + e.preventDefault(); + self.getContent(); + }); - // Write out selected preset - $(document).on('click', this.selectorActivateTrigger, function(e) { - e.preventDefault(); - self.activate(); - }); + // Write out selected preset + $(document).on('click', this.selectorActivateTrigger, function(e) { + e.preventDefault(); + self.activate(); + }); - // Automatically select the custom preset if a value in one of its input fields is changed - $('.t3js-custom-preset').on('input', function() { - $('#' + $(this).data('radio')).prop('checked', true); - }); - }, + // Automatically select the custom preset if a value in one of its input fields is changed + $('.t3js-custom-preset').on('input', function() { + $('#' + $(this).data('radio')).prop('checked', true); + }); + }, - getContent: function() { - var self = this; - var outputContainer = $(this.selectorContentContainer); - var executablePath = $(self.selectorImageExecutable).val(); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'token': $(this.selectorGetContentToken).text(), - 'action': 'presetsGetContent', - 'values': { - 'Image': { - 'additionalSearchPath': executablePath - } - } - } - }, - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - outputContainer.empty().append(data.html); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - outputContainer.empty().append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getContent: function() { + var self = this; + var outputContainer = $(this.selectorContentContainer); + var executablePath = $(self.selectorImageExecutable).val(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'token': $(this.selectorGetContentToken).text(), + 'action': 'presetsGetContent', + 'values': { + 'Image': { + 'additionalSearchPath': executablePath + } + } + } + }, + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + outputContainer.empty().append(data.html); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + outputContainer.empty().append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - activate: function() { - var postData = {}; - $($(this.selectorContentContainer + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - postData['install[action]'] = 'presetsActivate'; - postData['install[token]'] = $(this.selectorActivateToken).text(); - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: postData, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + activate: function() { + var postData = {}; + $($(this.selectorContentContainer + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + postData['install[action]'] = 'presetsActivate'; + postData['install[token]'] = $(this.selectorActivateToken).text(); + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: postData, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js index b44effa2ffe57c8884d828b53f5700646619b8a6..8b4f4e289c077170ee2592c752c22dd0cd4e8572 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js @@ -14,35 +14,35 @@ /** * Module: TYPO3/CMS/Install/ProgressBar */ -define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) { + 'use strict'; - /** - * @type {{template: (*)}} - */ - var ProgressBar = { - template: $('<div class="progress"><div class="t3js-progressbar progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <span class="sr-only"></span></div></div>') - }; + /** + * @type {{template: (*)}} + */ + var ProgressBar = { + template: $('<div class="progress"><div class="t3js-progressbar progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <span class="sr-only"></span></div></div>') + }; - /** - * render a ProgressBar - * @param {Number} severity - * @param {String} title - * @param {Number} progress - * @returns {jQuery} - */ - ProgressBar.render = function (severity, title, progress) { - var progressBar = this.template.clone(); - progressBar.addClass('progress-bar-' + Severity.getCssClass(severity)); - if (progress) { - progressBar.css('width', progress + '%'); - progressBar.attr('aria-valuenow',progresss); - } - if (title) { - progressBar.find('.sr-only').text(title); - } - return progressBar; - }; + /** + * render a ProgressBar + * @param {Number} severity + * @param {String} title + * @param {Number} progress + * @returns {jQuery} + */ + ProgressBar.render = function(severity, title, progress) { + var progressBar = this.template.clone(); + progressBar.addClass('progress-bar-' + Severity.getCssClass(severity)); + if (progress) { + progressBar.css('width', progress + '%'); + progressBar.attr('aria-valuenow', progresss); + } + if (title) { + progressBar.find('.sr-only').text(title); + } + return progressBar; + }; - return ProgressBar; + return ProgressBar; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js index 591e692846f72b81fe95ac37864ac0b0efa4367d..a0067abc7e555b64e1dab62a1677cd5dc56fa0df 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js @@ -15,53 +15,53 @@ * Module: TYPO3/CMS/Install/DumpAutoload */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorResetTrigger: '.t3js-resetBackendUserUc-reset', - selectorOutputContainer: '.t3js-resetBackendUserUc-output', + return { + selectorResetTrigger: '.t3js-resetBackendUserUc-reset', + selectorOutputContainer: '.t3js-resetBackendUserUc-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorResetTrigger, function(e) { - e.preventDefault(); - self.reset(); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorResetTrigger, function(e) { + e.preventDefault(); + self.reset(); + }); + }, - reset: function() { - var self = this; - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('resetBackendUserUc'), - cache: false, - success: function (data) { - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - $outputContainer.empty(); - data.status.forEach(function (element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + reset: function() { + var self = this; + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('resetBackendUserUc'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + $outputContainer.empty(); + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js index 1a43de4ad1303cbb227e91426ad51c65fc11bb23..42afb21cac1720e774328132c2a455f12c2eb3d4 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js @@ -15,302 +15,302 @@ * Module: TYPO3/CMS/Install/Router */ define([ - 'jquery', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'TYPO3/CMS/Install/CardLayout', - 'TYPO3/CMS/Install/ProgressBar' + 'jquery', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'TYPO3/CMS/Install/CardLayout', + 'TYPO3/CMS/Install/ProgressBar' ], function($, InfoBox, Severity, CardLayout, ProgressBar) { - 'use strict'; + 'use strict'; - return { - selectorBody: '.t3js-body', - selectorMainContent: '.t3js-module-body', + return { + selectorBody: '.t3js-body', + selectorMainContent: '.t3js-module-body', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - $(document).on('click', '.t3js-login-lockInstallTool', function(e) { - e.preventDefault(); - self.logout(); - }); - $(document).on('click', '.t3js-login-login', function(e) { - e.preventDefault(); - self.login(); - }); - $(document).on('keydown', '#t3-install-form-password', function(e) { - if (e.keyCode === 13) { - e.preventDefault(); - $('.t3js-login-login').click(); - } - }); + $(document).on('click', '.t3js-login-lockInstallTool', function(e) { + e.preventDefault(); + self.logout(); + }); + $(document).on('click', '.t3js-login-login', function(e) { + e.preventDefault(); + self.login(); + }); + $(document).on('keydown', '#t3-install-form-password', function(e) { + if (e.keyCode === 13) { + e.preventDefault(); + $('.t3js-login-login').click(); + } + }); - this.executeSilentConfigurationUpdate(); - }, + this.executeSilentConfigurationUpdate(); + }, - getUrl: function(action, controller) { - var url = location.href; - var context = $(this.selectorBody).data('context'); - url = url.replace(location.search, ''); - if (controller === undefined) { - controller = $(this.selectorBody).data('controller'); - } - url = url + '?install[controller]=' + controller; - if (context !== undefined && context !== '') { - url = url + '&install[context]=' + context; - } - if (action !== undefined) { - url = url + '&install[action]=' + action; - } - return url; - }, + getUrl: function(action, controller) { + var url = location.href; + var context = $(this.selectorBody).data('context'); + url = url.replace(location.search, ''); + if (controller === undefined) { + controller = $(this.selectorBody).data('controller'); + } + url = url + '?install[controller]=' + controller; + if (context !== undefined && context !== '') { + url = url + '&install[context]=' + context; + } + if (action !== undefined) { + url = url + '&install[action]=' + action; + } + return url; + }, - executeSilentConfigurationUpdate: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeSilentConfigurationUpdate', 'layout'), - cache: false, - success: function(data) { - if (data.success === true) { - self.executeSilentLegacyExtConfExtensionConfigurationUpdate(); - } else { - self.executeSilentConfigurationUpdate(); - } - }, - error: function(xhr) { - self.handleAjaxError(xhr); - } - }); - }, + executeSilentConfigurationUpdate: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeSilentConfigurationUpdate', 'layout'), + cache: false, + success: function(data) { + if (data.success === true) { + self.executeSilentLegacyExtConfExtensionConfigurationUpdate(); + } else { + self.executeSilentConfigurationUpdate(); + } + }, + error: function(xhr) { + self.handleAjaxError(xhr); + } + }); + }, - /** - * Legacy layer to upmerge LocalConfiguration EXT/extConf serialized array keys - * to EXTENSIONS array in LocalConfiguration for initial update from v8 to v9. - * - * @deprecated since TYPO3 v9, will be removed with v10 - re-route executeSilentConfigurationUpdate() - * to executeSilentExtensionConfigurationUpdate() on removal of this function. - */ - executeSilentLegacyExtConfExtensionConfigurationUpdate: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeSilentLegacyExtConfExtensionConfigurationUpdate', 'layout'), - cache: false, - success: function(data) { - if (data.success === true) { - self.executeSilentExtensionConfigurationSynchronization(); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().append(message); - } - }, - error: function(xhr) { - self.handleAjaxError(xhr); - } - }); - }, + /** + * Legacy layer to upmerge LocalConfiguration EXT/extConf serialized array keys + * to EXTENSIONS array in LocalConfiguration for initial update from v8 to v9. + * + * @deprecated since TYPO3 v9, will be removed with v10 - re-route executeSilentConfigurationUpdate() + * to executeSilentExtensionConfigurationUpdate() on removal of this function. + */ + executeSilentLegacyExtConfExtensionConfigurationUpdate: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeSilentLegacyExtConfExtensionConfigurationUpdate', 'layout'), + cache: false, + success: function(data) { + if (data.success === true) { + self.executeSilentExtensionConfigurationSynchronization(); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().append(message); + } + }, + error: function(xhr) { + self.handleAjaxError(xhr); + } + }); + }, - /** - * Extensions which come with new default settings in ext_conf_template.txt extension - * configuration files get their new defaults written to LocalConfiguration. - */ - executeSilentExtensionConfigurationSynchronization: function() { - var self = this; - $.ajax({ - url: this.getUrl('executeSilentExtensionConfigurationSynchronization', 'layout'), - cache: false, - success: function(data) { - if (data.success === true) { - self.loadMainLayout(); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().append(message); - } - }, - error: function(xhr) { - self.handleAjaxError(xhr); - } - }); - }, + /** + * Extensions which come with new default settings in ext_conf_template.txt extension + * configuration files get their new defaults written to LocalConfiguration. + */ + executeSilentExtensionConfigurationSynchronization: function() { + var self = this; + $.ajax({ + url: this.getUrl('executeSilentExtensionConfigurationSynchronization', 'layout'), + cache: false, + success: function(data) { + if (data.success === true) { + self.loadMainLayout(); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().append(message); + } + }, + error: function(xhr) { + self.handleAjaxError(xhr); + } + }); + }, - loadMainLayout: function() { - var self = this; - var $outputContainer = $(this.selectorBody); - $.ajax({ - url: this.getUrl('mainLayout', 'layout'), - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - $outputContainer.empty().append(data.html); - // Mark main module as active in standalone - if ($(self.selectorBody).data('context') !== 'backend') { - var controller = $outputContainer.data('controller'); - $outputContainer.find('.t3js-mainmodule[data-controller="' + controller + '"]').addClass('active'); - } - self.loadCards(); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().append(message); - } - }, - error: function(xhr) { - self.handleAjaxError(xhr); - } - }); - }, + loadMainLayout: function() { + var self = this; + var $outputContainer = $(this.selectorBody); + $.ajax({ + url: this.getUrl('mainLayout', 'layout'), + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + $outputContainer.empty().append(data.html); + // Mark main module as active in standalone + if ($(self.selectorBody).data('context') !== 'backend') { + var controller = $outputContainer.data('controller'); + $outputContainer.find('.t3js-mainmodule[data-controller="' + controller + '"]').addClass('active'); + } + self.loadCards(); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().append(message); + } + }, + error: function(xhr) { + self.handleAjaxError(xhr); + } + }); + }, - handleAjaxError: function(xhr) { - var message = ''; - if (xhr.status === 401) { - // Install tool session expired - depending on context render error message or login - var context = $(this.selectorBody).data('context'); - if (context === 'backend') { - message = InfoBox.render( - Severity.error, - 'The install tool session expired. Please reload the backend and try again.' - ); - $(this.selectorBody).empty().append(message); - } else { - this.checkEnableInstallToolFile(); - } - } else { - // @todo Recovery tests should be started here - var url = this.getUrl(undefined, 'upgrade'); - message = '<div class="t3js-infobox callout callout-sm callout-danger"><div class="callout-body">' - + 'Something went wrong. Please use <b><a href="' + url + '">Check for broken' - + ' extensions</a></b> to see if a loaded extension breaks this part of the install tool' - + ' and unload it.</div></div>'; - $(this.selectorBody).empty().html(message); - } - }, + handleAjaxError: function(xhr) { + var message = ''; + if (xhr.status === 401) { + // Install tool session expired - depending on context render error message or login + var context = $(this.selectorBody).data('context'); + if (context === 'backend') { + message = InfoBox.render( + Severity.error, + 'The install tool session expired. Please reload the backend and try again.' + ); + $(this.selectorBody).empty().append(message); + } else { + this.checkEnableInstallToolFile(); + } + } else { + // @todo Recovery tests should be started here + var url = this.getUrl(undefined, 'upgrade'); + message = '<div class="t3js-infobox callout callout-sm callout-danger"><div class="callout-body">' + + 'Something went wrong. Please use <b><a href="' + url + '">Check for broken' + + ' extensions</a></b> to see if a loaded extension breaks this part of the install tool' + + ' and unload it.</div></div>'; + $(this.selectorBody).empty().html(message); + } + }, - checkEnableInstallToolFile: function() { - var self = this; - $.ajax({ - url: this.getUrl('checkEnableInstallToolFile'), - cache: false, - success: function(data) { - if (data.success === true) { - self.checkLogin(); - } else { - self.showEnableInstallTool(); - } - } - }); - }, + checkEnableInstallToolFile: function() { + var self = this; + $.ajax({ + url: this.getUrl('checkEnableInstallToolFile'), + cache: false, + success: function(data) { + if (data.success === true) { + self.checkLogin(); + } else { + self.showEnableInstallTool(); + } + } + }); + }, - showEnableInstallTool: function() { - var self = this; - $.ajax({ - url: this.getUrl('showEnableInstallToolFile'), - cache: false, - success: function(data) { - if (data.success === true) { - $(self.selectorBody).empty().append(data.html); - } - } - }); - }, + showEnableInstallTool: function() { + var self = this; + $.ajax({ + url: this.getUrl('showEnableInstallToolFile'), + cache: false, + success: function(data) { + if (data.success === true) { + $(self.selectorBody).empty().append(data.html); + } + } + }); + }, - checkLogin: function() { - var self = this; - $.ajax({ - url: this.getUrl('checkLogin'), - cache: false, - success: function(data) { - if (data.success === true) { - self.loadMainLayout(); - } else { - self.showLogin(); - } - } - }); - }, + checkLogin: function() { + var self = this; + $.ajax({ + url: this.getUrl('checkLogin'), + cache: false, + success: function(data) { + if (data.success === true) { + self.loadMainLayout(); + } else { + self.showLogin(); + } + } + }); + }, - showLogin: function() { - var self = this; - $.ajax({ - url: this.getUrl('showLogin'), - cache: false, - success: function(data) { - if (data.success === true) { - $(self.selectorBody).empty().append(data.html); - } - } - }); - }, + showLogin: function() { + var self = this; + $.ajax({ + url: this.getUrl('showLogin'), + cache: false, + success: function(data) { + if (data.success === true) { + $(self.selectorBody).empty().append(data.html); + } + } + }); + }, - login: function() { - var self = this; - var $outputContainer = $('.t3js-login-output'); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: self.getUrl(), - cache: false, - method: 'POST', - data: { - 'install': { - 'action': 'login', - 'token': $('#t3js-login-token').text(), - 'password': $('.t3-install-form-input-text').val() - } - }, - success: function(data) { - if (data.success === true) { - self.loadMainLayout(); - } else { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().html(message); - }); - } - } - }); - }, + login: function() { + var self = this; + var $outputContainer = $('.t3js-login-output'); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: self.getUrl(), + cache: false, + method: 'POST', + data: { + 'install': { + 'action': 'login', + 'token': $('#t3js-login-token').text(), + 'password': $('.t3-install-form-input-text').val() + } + }, + success: function(data) { + if (data.success === true) { + self.loadMainLayout(); + } else { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().html(message); + }); + } + } + }); + }, - logout: function() { - var self = this; - $.ajax({ - url: self.getUrl('logout'), - cache: false, - success: function(data) { - if (data.success === true) { - self.showEnableInstallTool(); - } - } - }); - }, + logout: function() { + var self = this; + $.ajax({ + url: self.getUrl('logout'), + cache: false, + success: function(data) { + if (data.success === true) { + self.showEnableInstallTool(); + } + } + }); + }, - loadCards: function() { - var self = this; - var outputContainer = $(this.selectorMainContent); - $.ajax({ - url: this.getUrl('cards'), - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - outputContainer.empty().append(data.html); - CardLayout.initialize(); - // Each card head can have a t3js-require class and a data-require attribute - // with the name of a requireJS module. Those are loaded here and initialize() - // is executed if exists. - $('.t3js-require').each(function() { - var module = $(this).data('require'); - require([module], function(aModule) { - if (typeof aModule.initialize !== 'undefined') { - aModule.initialize(); - } - }); - }); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - outputContainer.empty().append(message); - } - }, - error: function(xhr) { - self.handleAjaxError(xhr); - } - }); - } - }; + loadCards: function() { + var self = this; + var outputContainer = $(this.selectorMainContent); + $.ajax({ + url: this.getUrl('cards'), + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + outputContainer.empty().append(data.html); + CardLayout.initialize(); + // Each card head can have a t3js-require class and a data-require attribute + // with the name of a requireJS module. Those are loaded here and initialize() + // is executed if exists. + $('.t3js-require').each(function() { + var module = $(this).data('require'); + require([module], function(aModule) { + if (typeof aModule.initialize !== 'undefined') { + aModule.initialize(); + } + }); + }); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + outputContainer.empty().append(message); + } + }, + error: function(xhr) { + self.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js index 63d0faeca1b273f73dec289f16251d324c19ad8a..3906a75af7ee87c71c7519d312e6f936dd1d6435 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js @@ -14,42 +14,42 @@ /** * Module: TYPO3/CMS/Install/Severity */ -define([], function () { - 'use strict'; +define([], function() { + 'use strict'; - var Severity = { - loading: -3, - notice: -2, - info: -1, - ok: 0, - warning: 1, - error: 2 - }; + var Severity = { + loading: -3, + notice: -2, + info: -1, + ok: 0, + warning: 1, + error: 2 + }; - Severity.getCssClass = function (severity) { - var severityClass; - switch (severity) { - case Severity.loading: - severityClass = 'notice alert-loading'; - break; - case Severity.notice: - severityClass = 'notice'; - break; - case Severity.ok: - severityClass = 'success'; - break; - case Severity.warning: - severityClass = 'warning'; - break; - case Severity.error: - severityClass = 'danger'; - break; - case Severity.info: - default: - severityClass = 'info'; - } - return severityClass; - }; + Severity.getCssClass = function(severity) { + var severityClass; + switch (severity) { + case Severity.loading: + severityClass = 'notice alert-loading'; + break; + case Severity.notice: + severityClass = 'notice'; + break; + case Severity.ok: + severityClass = 'success'; + break; + case Severity.warning: + severityClass = 'warning'; + break; + case Severity.error: + severityClass = 'danger'; + break; + case Severity.info: + default: + severityClass = 'info'; + } + return severityClass; + }; - return Severity; + return Severity; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js index 0aacaae60f5d1da9b20f1d8024de21ebf1da63ed..2d3e4b02ce7c0dbbc5505d69c8d9fc1b7e979c2c 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js @@ -15,128 +15,128 @@ * Module: TYPO3/CMS/Install/SystemMaintainer */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap', - 'chosen' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap', + 'chosen' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorGridderOpener: 't3js-systemMaintainer-open', - selectorWriteTrigger: '.t3js-systemMaintainer-write', - selectorWriteToken: '#t3js-systemMaintainer-write-token', - selectorOutputContainer: '.t3js-systemMaintainer-output', - selectorChosenContainer: '.t3js-systemMaintainer-chosen', - selectorChosenField: '.t3js-systemMaintainer-chosen-select', + return { + selectorGridderOpener: 't3js-systemMaintainer-open', + selectorWriteTrigger: '.t3js-systemMaintainer-write', + selectorWriteToken: '#t3js-systemMaintainer-write-token', + selectorOutputContainer: '.t3js-systemMaintainer-output', + selectorChosenContainer: '.t3js-systemMaintainer-chosen', + selectorChosenField: '.t3js-systemMaintainer-chosen-select', - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Get current system maintainer list on card open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener)) { - self.getList(); - } - }); + // Get current system maintainer list on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getList(); + } + }); - $(document).on('click', this.selectorWriteTrigger, function(e) { - e.preventDefault(); - self.write(); - }); - }, + $(document).on('click', this.selectorWriteTrigger, function(e) { + e.preventDefault(); + self.write(); + }); + }, - getList: function() { - var self = this; - var $chosenContainer = $(this.selectorChosenContainer); - var $outputContainer = $(this.selectorOutputContainer); - var $chosenField = $(self.selectorChosenField); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().append(message); - $chosenContainer.hide(); - $chosenField.empty(); - $.ajax({ - url: Router.getUrl('systemMaintainerGetList'), - cache: false, - success: function (data) { - if (data.success === true) { - $outputContainer.find('.alert-loading').remove(); - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - if (Array.isArray(data.users)) { - data.users.forEach(function(element) { - var name = element.username; - if (element.disable) { - name = '[DISABLED] ' + name; - } - var selected = ''; - if (element.isSystemMaintainer) { - selected = 'selected="selected"'; - } - $chosenField.append( - '<option value="' + element.uid + '" ' + selected + '>' + name + '</option>' - ); - }); - } - var config = { - '.chosen-select': {width: "100%", placeholder_text_multiple: "users"}, - '.chosen-select-deselect': {allow_single_deselect: true}, - '.chosen-select-width': {width: "100%"} - }; - for (var selector in config) { - $(selector).chosen(config[selector]); - } - $chosenContainer.show(); - $chosenField.trigger('chosen:updated'); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + getList: function() { + var self = this; + var $chosenContainer = $(this.selectorChosenContainer); + var $outputContainer = $(this.selectorOutputContainer); + var $chosenField = $(self.selectorChosenField); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().append(message); + $chosenContainer.hide(); + $chosenField.empty(); + $.ajax({ + url: Router.getUrl('systemMaintainerGetList'), + cache: false, + success: function(data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + if (Array.isArray(data.users)) { + data.users.forEach(function(element) { + var name = element.username; + if (element.disable) { + name = '[DISABLED] ' + name; + } + var selected = ''; + if (element.isSystemMaintainer) { + selected = 'selected="selected"'; + } + $chosenField.append( + '<option value="' + element.uid + '" ' + selected + '>' + name + '</option>' + ); + }); + } + var config = { + '.chosen-select': {width: "100%", placeholder_text_multiple: "users"}, + '.chosen-select-deselect': {allow_single_deselect: true}, + '.chosen-select-width': {width: "100%"} + }; + for (var selector in config) { + $(selector).chosen(config[selector]); + } + $chosenContainer.show(); + $chosenField.trigger('chosen:updated'); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - write: function() { - var $outputContainer = $(this.selectorOutputContainer); - var selectedUsers = $(this.selectorChosenField).val(); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.append(message); - $.ajax({ - method: 'POST', - url: Router.getUrl(), - data: { - 'install': { - 'users': selectedUsers, - 'token': $(this.selectorWriteToken).text(), - 'action': 'systemMaintainerWrite' - } - }, - success: function (data) { - if (data.success === true) { - $outputContainer.find('.alert-loading').remove(); - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.empty().append(message); - }); - } - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + write: function() { + var $outputContainer = $(this.selectorOutputContainer); + var selectedUsers = $(this.selectorChosenField).val(); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.append(message); + $.ajax({ + method: 'POST', + url: Router.getUrl(), + data: { + 'install': { + 'users': selectedUsers, + 'token': $(this.selectorWriteToken).text(), + 'action': 'systemMaintainerWrite' + } + }, + success: function(data) { + if (data.success === true) { + $outputContainer.find('.alert-loading').remove(); + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.empty().append(message); + }); + } + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js index 6586d7905a0386fa75dac0055a6263159e5e85fd..e29af284840fec0119dca73d40733666b45d17a3 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js @@ -15,61 +15,61 @@ * Module: TYPO3/CMS/Install/TcaExtTablesCheck */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorCheckTrigger: '.t3js-tcaExtTablesCheck-check', - selectorOutputContainer: '.t3js-tcaExtTablesCheck-output', + return { + selectorCheckTrigger: '.t3js-tcaExtTablesCheck-check', + selectorOutputContainer: '.t3js-tcaExtTablesCheck-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorCheckTrigger, function(e) { - e.preventDefault(); - self.check(); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorCheckTrigger, function(e) { + e.preventDefault(); + self.check(); + }); + }, - check: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('tcaExtTablesCheck'), - cache: false, - success: function (data) { - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - var message = InfoBox.render( - Severity.warning, - 'Extensions change TCA in ext_tables.php', - 'Check for ExtensionManagementUtility and $GLOBALS["TCA"]' - ); - $outputContainer.empty(); - $outputContainer.append(message); - data.status.forEach(function (element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = InfoBox.render(Severity.ok, 'No TCA changes in ext_tables.php files. Good job!', ''); - $outputContainer.empty().html(message); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"'); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + check: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('tcaExtTablesCheck'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + var message = InfoBox.render( + Severity.warning, + 'Extensions change TCA in ext_tables.php', + 'Check for ExtensionManagementUtility and $GLOBALS["TCA"]' + ); + $outputContainer.empty(); + $outputContainer.append(message); + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = InfoBox.render(Severity.ok, 'No TCA changes in ext_tables.php files. Good job!', ''); + $outputContainer.empty().html(message); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"'); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js index 0a03946c26de214592644bf146561f66897fa2f1..b6e343421e6f88cd1c13e437048cebe427f8a2a1 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js @@ -15,61 +15,61 @@ * Module: TYPO3/CMS/Install/TcaIntegrityChecker */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'use strict'; - return { - selectorCheckTrigger: '.t3js-tcaMigrationsCheck-check', - selectorOutputContainer: '.t3js-tcaMigrationsCheck-output', + return { + selectorCheckTrigger: '.t3js-tcaMigrationsCheck-check', + selectorOutputContainer: '.t3js-tcaMigrationsCheck-output', - initialize: function() { - var self = this; - $(document).on('click', this.selectorCheckTrigger, function(e) { - e.preventDefault(); - self.check(); - }); - }, + initialize: function() { + var self = this; + $(document).on('click', this.selectorCheckTrigger, function(e) { + e.preventDefault(); + self.check(); + }); + }, - check: function() { - var $outputContainer = $(this.selectorOutputContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - $outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('tcaMigrationsCheck'), - cache: false, - success: function(data) { - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - var message = InfoBox.render( - Severity.warning, - 'TCA migrations need to be applied', - 'Check the following list and apply needed changes.' - ); - $outputContainer.empty(); - $outputContainer.append(message); - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } else { - var message = InfoBox.render(Severity.ok, 'No TCA migrations need to be applied', 'Your TCA looks good.'); - $outputContainer.empty().html(message); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"'); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - } - }; + check: function() { + var $outputContainer = $(this.selectorOutputContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + $outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('tcaMigrationsCheck'), + cache: false, + success: function(data) { + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + var message = InfoBox.render( + Severity.warning, + 'TCA migrations need to be applied', + 'Check the following list and apply needed changes.' + ); + $outputContainer.empty(); + $outputContainer.append(message); + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } else { + var message = InfoBox.render(Severity.ok, 'No TCA migrations need to be applied', 'Your TCA looks good.'); + $outputContainer.empty().html(message); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"'); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js index 91f665af529109ed1ab48a5a717833692792442d..cef55807e152d2e07947ce7a065f825c3738ece4 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js @@ -15,227 +15,227 @@ * Module: TYPO3/CMS/Install/UpgradeDocs */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity', - 'bootstrap', - 'chosen' -], function ($, Router, ProgressBar, InfoBox, Severity) { - 'use strict'; - - return { - selectorGridderOpener: 't3js-upgradeDocs-open', - selectorContentContainer: '.t3js-upgradeDocs-content', - selectorMarkReadToken: '#t3js-upgradeDocs-markRead-token', - selectorUnmarkReadToken: '#t3js-upgradeDocs-unmarkRead-token', - selectorRestFileItem: '.upgrade_analysis_item_to_filter', - selectorFulltextSearch: '.gridder-show .t3js-upgradeDocs-fulltext-search', - selectorChosenField: '.gridder-show .t3js-upgradeDocs-chosen-select', - - chosenField: null, - fulltextSearchField: null, - - initialize: function() { - var self = this; - - // Get content on card open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener)) { - self.getContent(); - } - }); - - // Mark a file as read - $(document).on('click', '.t3js-upgradeDocs-markRead', function(event) { - self.markRead(event.target); - }); - $(document).on('click', '.t3js-upgradeDocs-unmarkRead', function(event) { - self.unmarkRead(event.target); - }); - - // Make jquerys "contains" work case-insensitive - jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) { - return function (elem) { - return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; - }; - }); - }, - - getContent: function() { - var self = this; - var outputContainer = $(this.selectorContentContainer); - var message = ProgressBar.render(Severity.loading, 'Loading...', ''); - outputContainer.empty().html(message); - $.ajax({ - url: Router.getUrl('upgradeDocsGetContent'), - cache: false, - success: function(data) { - if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { - outputContainer.empty().append(data.html); - $('[data-toggle="tooltip"]').tooltip({container: 'body'}); - self.chosenField = $(self.selectorChosenField); - self.fulltextSearchField = $(self.selectorFulltextSearch); - self.initializeChosenSelector(); - self.chosenField.on('change', function() { - self.combinedFilterSearch(); - }); - self.fulltextSearchField.on('keyup', function() { - self.combinedFilterSearch(); - }); - } else { - var message = InfoBox.render(Severity.error, 'Something went wrong', ''); - outputContainer.empty().append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, - - initializeChosenSelector: function() { - var self = this; - var tagString = ''; - $(this.selectorRestFileItem).each(function() { - tagString += $(this).data('item-tags') + ','; - }); - var tagArray = this.trimExplodeAndUnique(',', tagString); - $.each(tagArray, function(i, tag) { - self.chosenField.append('<option>' + tag + '</option>'); - }); - var config = { - '.chosen-select': {width: "100%", placeholder_text_multiple: "tags"}, - '.chosen-select-deselect': {allow_single_deselect: true}, - '.chosen-select-no-single': {disable_search_threshold: 10}, - '.chosen-select-no-results': {no_results_text: 'Oops, nothing found!'}, - '.chosen-select-width': {width: "100%"} - }; - for (var selector in config) { - $(selector).chosen(config[selector]); - } - this.chosenField.trigger('chosen:updated'); - }, - - combinedFilterSearch: function() { - var $items = $('div.item'); - if (this.chosenField.val().length < 1 && this.fulltextSearchField.val().length < 1) { - $('.panel-version:not(:first) > .panel-collapse').collapse('hide'); - $items.removeClass('hidden searchhit filterhit'); - return false; - } - $items.addClass('hidden').removeClass('searchhit filterhit'); - - // apply tags - if (this.chosenField.val().length > 0) { - $items - .addClass('hidden') - .removeClass('filterhit'); - var orTags = []; - var andTags = []; - $.each(this.chosenField.val(), function(index, item) { - var tagFilter = '[data-item-tags*="' + item + '"]'; - if (item.indexOf(':') > 0) { - orTags.push(tagFilter); - } else { - andTags.push(tagFilter); - } - }); - var andString = andTags.join(''); - var tags = []; - if (orTags.length) { - for (var i = 0; i < orTags.length; i++) { - tags.push(andString + orTags[i]); - } - } else { - tags.push(andString); - } - var tagSelection = tags.join(','); - $(tagSelection) - .removeClass('hidden') - .addClass('searchhit filterhit'); - } else { - $items - .addClass('filterhit') - .removeClass('hidden'); - } - // apply fulltext search - var typedQuery = this.fulltextSearchField.val(); - $('div.item.filterhit').each(function() { - var $item = $(this); - if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { - $item.removeClass('hidden').addClass('searchhit'); - } else { - $item.removeClass('searchhit').addClass('hidden'); - } - }); - - $('.searchhit').closest('.panel-collapse').collapse('show'); - - //check for empty panels - $('.panel-version').each(function() { - if ($(this).find('.searchhit', '.filterhit').length < 1) { - $(this).find(' > .panel-collapse').collapse('hide'); - } - }); - }, - - markRead: function(element) { - var $button = $(element).closest('a'); - $button.toggleClass('t3js-upgradeDocs-unmarkRead t3js-upgradeDocs-markRead'); - $button.find('i').toggleClass('fa-check fa-ban'); - $button.closest('.panel').appendTo('.panel-body-read'); - $.ajax({ - method: 'POST', - url: Router.getUrl(), - data: { - 'install': { - 'ignoreFile': $button.data('filepath'), - 'token': $(this.selectorMarkReadToken).text(), - 'action': 'upgradeDocsMarkRead' - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, - - unmarkRead: function(element) { - var $button = $(element).closest('a'); - var version = $button.closest('.panel').data('item-version'); - $button.toggleClass('t3js-upgradeDocs-markRead t3js-upgradeDocs-unmarkRead'); - $button.find('i').toggleClass('fa-check fa-ban'); - $button.closest('.panel').appendTo('*[data-group-version="' + version + '"] .panel-body'); - $.ajax({ - method: 'POST', - url: Router.getUrl(), - data: { - 'install': { - 'ignoreFile': $button.data('filepath'), - 'token': $(this.selectorUnmarkReadToken).text(), - action: 'upgradeDocsUnmarkRead' - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, - - trimExplodeAndUnique: function(delimiter, string) { - var result = []; - var items = string.split(delimiter); - for (var i = 0; i < items.length; i++) { - var item = items[i].trim(); - if (item.length > 0) { - if ($.inArray(item, result) === -1) { - result.push(item); - } - } - } - return result; - } - }; + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity', + 'bootstrap', + 'chosen' +], function($, Router, ProgressBar, InfoBox, Severity) { + 'use strict'; + + return { + selectorGridderOpener: 't3js-upgradeDocs-open', + selectorContentContainer: '.t3js-upgradeDocs-content', + selectorMarkReadToken: '#t3js-upgradeDocs-markRead-token', + selectorUnmarkReadToken: '#t3js-upgradeDocs-unmarkRead-token', + selectorRestFileItem: '.upgrade_analysis_item_to_filter', + selectorFulltextSearch: '.gridder-show .t3js-upgradeDocs-fulltext-search', + selectorChosenField: '.gridder-show .t3js-upgradeDocs-chosen-select', + + chosenField: null, + fulltextSearchField: null, + + initialize: function() { + var self = this; + + // Get content on card open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener)) { + self.getContent(); + } + }); + + // Mark a file as read + $(document).on('click', '.t3js-upgradeDocs-markRead', function(event) { + self.markRead(event.target); + }); + $(document).on('click', '.t3js-upgradeDocs-unmarkRead', function(event) { + self.unmarkRead(event.target); + }); + + // Make jquerys "contains" work case-insensitive + jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) { + return function(elem) { + return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0; + }; + }); + }, + + getContent: function() { + var self = this; + var outputContainer = $(this.selectorContentContainer); + var message = ProgressBar.render(Severity.loading, 'Loading...', ''); + outputContainer.empty().html(message); + $.ajax({ + url: Router.getUrl('upgradeDocsGetContent'), + cache: false, + success: function(data) { + if (data.success === true && data.html !== 'undefined' && data.html.length > 0) { + outputContainer.empty().append(data.html); + $('[data-toggle="tooltip"]').tooltip({container: 'body'}); + self.chosenField = $(self.selectorChosenField); + self.fulltextSearchField = $(self.selectorFulltextSearch); + self.initializeChosenSelector(); + self.chosenField.on('change', function() { + self.combinedFilterSearch(); + }); + self.fulltextSearchField.on('keyup', function() { + self.combinedFilterSearch(); + }); + } else { + var message = InfoBox.render(Severity.error, 'Something went wrong', ''); + outputContainer.empty().append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, + + initializeChosenSelector: function() { + var self = this; + var tagString = ''; + $(this.selectorRestFileItem).each(function() { + tagString += $(this).data('item-tags') + ','; + }); + var tagArray = this.trimExplodeAndUnique(',', tagString); + $.each(tagArray, function(i, tag) { + self.chosenField.append('<option>' + tag + '</option>'); + }); + var config = { + '.chosen-select': {width: "100%", placeholder_text_multiple: "tags"}, + '.chosen-select-deselect': {allow_single_deselect: true}, + '.chosen-select-no-single': {disable_search_threshold: 10}, + '.chosen-select-no-results': {no_results_text: 'Oops, nothing found!'}, + '.chosen-select-width': {width: "100%"} + }; + for (var selector in config) { + $(selector).chosen(config[selector]); + } + this.chosenField.trigger('chosen:updated'); + }, + + combinedFilterSearch: function() { + var $items = $('div.item'); + if (this.chosenField.val().length < 1 && this.fulltextSearchField.val().length < 1) { + $('.panel-version:not(:first) > .panel-collapse').collapse('hide'); + $items.removeClass('hidden searchhit filterhit'); + return false; + } + $items.addClass('hidden').removeClass('searchhit filterhit'); + + // apply tags + if (this.chosenField.val().length > 0) { + $items + .addClass('hidden') + .removeClass('filterhit'); + var orTags = []; + var andTags = []; + $.each(this.chosenField.val(), function(index, item) { + var tagFilter = '[data-item-tags*="' + item + '"]'; + if (item.indexOf(':') > 0) { + orTags.push(tagFilter); + } else { + andTags.push(tagFilter); + } + }); + var andString = andTags.join(''); + var tags = []; + if (orTags.length) { + for (var i = 0; i < orTags.length; i++) { + tags.push(andString + orTags[i]); + } + } else { + tags.push(andString); + } + var tagSelection = tags.join(','); + $(tagSelection) + .removeClass('hidden') + .addClass('searchhit filterhit'); + } else { + $items + .addClass('filterhit') + .removeClass('hidden'); + } + // apply fulltext search + var typedQuery = this.fulltextSearchField.val(); + $('div.item.filterhit').each(function() { + var $item = $(this); + if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) { + $item.removeClass('hidden').addClass('searchhit'); + } else { + $item.removeClass('searchhit').addClass('hidden'); + } + }); + + $('.searchhit').closest('.panel-collapse').collapse('show'); + + //check for empty panels + $('.panel-version').each(function() { + if ($(this).find('.searchhit', '.filterhit').length < 1) { + $(this).find(' > .panel-collapse').collapse('hide'); + } + }); + }, + + markRead: function(element) { + var $button = $(element).closest('a'); + $button.toggleClass('t3js-upgradeDocs-unmarkRead t3js-upgradeDocs-markRead'); + $button.find('i').toggleClass('fa-check fa-ban'); + $button.closest('.panel').appendTo('.panel-body-read'); + $.ajax({ + method: 'POST', + url: Router.getUrl(), + data: { + 'install': { + 'ignoreFile': $button.data('filepath'), + 'token': $(this.selectorMarkReadToken).text(), + 'action': 'upgradeDocsMarkRead' + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, + + unmarkRead: function(element) { + var $button = $(element).closest('a'); + var version = $button.closest('.panel').data('item-version'); + $button.toggleClass('t3js-upgradeDocs-markRead t3js-upgradeDocs-unmarkRead'); + $button.find('i').toggleClass('fa-check fa-ban'); + $button.closest('.panel').appendTo('*[data-group-version="' + version + '"] .panel-body'); + $.ajax({ + method: 'POST', + url: Router.getUrl(), + data: { + 'install': { + 'ignoreFile': $button.data('filepath'), + 'token': $(this.selectorUnmarkReadToken).text(), + action: 'upgradeDocsUnmarkRead' + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, + + trimExplodeAndUnique: function(delimiter, string) { + var result = []; + var items = string.split(delimiter); + for (var i = 0; i < items.length; i++) { + var item = items[i].trim(); + if (item.length > 0) { + if ($.inArray(item, result) === -1) { + result.push(item); + } + } + } + return result; + } + }; }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js index 73f19e12ff4e9bd7b89e38524a3e5c8f0b34ef93..dc80b69e19716c3be7d9c91455ae5fb243206dfc 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js @@ -15,466 +15,466 @@ * Module: TYPO3/CMS/Install/UpgradeWizards */ define([ - 'jquery', - 'TYPO3/CMS/Install/Router', - 'TYPO3/CMS/Install/FlashMessage', - 'TYPO3/CMS/Install/ProgressBar', - 'TYPO3/CMS/Install/InfoBox', - 'TYPO3/CMS/Install/Severity' -], -function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { - 'use strict'; + 'jquery', + 'TYPO3/CMS/Install/Router', + 'TYPO3/CMS/Install/FlashMessage', + 'TYPO3/CMS/Install/ProgressBar', + 'TYPO3/CMS/Install/InfoBox', + 'TYPO3/CMS/Install/Severity' + ], + function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) { + 'use strict'; - return { - selectorGridderOpener: 't3js-upgradeWizards-open', - selectorMarkUndoneToken: '#t3js-upgradeWizards-markUndone-token', - selectorOutputWizardsContainer: '.t3js-upgradeWizards-wizards-output', - selectorOutputDoneContainer: '.t3js-upgradeWizards-done-output', - selectorWizardsBlockingAddsTemplate: '.t3js-upgradeWizards-blocking-adds-template', - selectorWizardsBlockingAddsRows: '.t3js-upgradeWizards-blocking-adds-rows', - selectorWizardsBlockingAddsExecute: '.t3js-upgradeWizards-blocking-adds-execute', - selectorWizardsBlockingCharsetTemplate: '.t3js-upgradeWizards-blocking-charset-template', - selectorWizardsBlockingCharsetFix: '.t3js-upgradeWizards-blocking-charset-fix', - selectorWizardsDoneBodyTemplate: '.t3js-upgradeWizards-done-body-template', - selectorWizardsDoneRows: '.t3js-upgradeWizards-done-rows', - selectorWizardsDoneRowTemplate: '.t3js-upgradeWizards-done-row-template table tbody', - selectorWizardsDoneRowMarkUndone: '.t3js-upgradeWizards-done-markUndone', - selectorWizardsDoneRowTitle: '.t3js-upgradeWizards-done-title', - selectorWizardsListTemplate: '.gridder-show .t3js-upgradeWizards-list-template', - selectorWizardsListRows: '.t3js-upgradeWizards-list-rows', - selectorWizardsListRowTemplate: '.gridder-show .t3js-upgradeWizards-list-row-template', - selectorWizardsListRowTitle: '.t3js-upgradeWizards-list-row-title', - selectorWizardsListRowExplanation: '.t3js-upgradeWizards-list-row-explanation', - selectorWizardsListRowExecute: '.t3js-upgradeWizards-list-row-execute', - selectorWizardsInputToken: '#t3js-upgradeWizards-input-token', - selectorWizardsInputTemplate: '.gridder-show .t3js-upgradeWizards-input', - selectorWizardsInputTitle: '.t3js-upgradeWizards-input-title', - selectorWizardsInputHtml: '.t3js-upgradeWizards-input-html', - selectorWizardsInputPerform: '.t3js-upgradeWizards-input-perform', - selectorWizardsExecuteToken: '#t3js-upgradeWizards-execute-token', + return { + selectorGridderOpener: 't3js-upgradeWizards-open', + selectorMarkUndoneToken: '#t3js-upgradeWizards-markUndone-token', + selectorOutputWizardsContainer: '.t3js-upgradeWizards-wizards-output', + selectorOutputDoneContainer: '.t3js-upgradeWizards-done-output', + selectorWizardsBlockingAddsTemplate: '.t3js-upgradeWizards-blocking-adds-template', + selectorWizardsBlockingAddsRows: '.t3js-upgradeWizards-blocking-adds-rows', + selectorWizardsBlockingAddsExecute: '.t3js-upgradeWizards-blocking-adds-execute', + selectorWizardsBlockingCharsetTemplate: '.t3js-upgradeWizards-blocking-charset-template', + selectorWizardsBlockingCharsetFix: '.t3js-upgradeWizards-blocking-charset-fix', + selectorWizardsDoneBodyTemplate: '.t3js-upgradeWizards-done-body-template', + selectorWizardsDoneRows: '.t3js-upgradeWizards-done-rows', + selectorWizardsDoneRowTemplate: '.t3js-upgradeWizards-done-row-template table tbody', + selectorWizardsDoneRowMarkUndone: '.t3js-upgradeWizards-done-markUndone', + selectorWizardsDoneRowTitle: '.t3js-upgradeWizards-done-title', + selectorWizardsListTemplate: '.gridder-show .t3js-upgradeWizards-list-template', + selectorWizardsListRows: '.t3js-upgradeWizards-list-rows', + selectorWizardsListRowTemplate: '.gridder-show .t3js-upgradeWizards-list-row-template', + selectorWizardsListRowTitle: '.t3js-upgradeWizards-list-row-title', + selectorWizardsListRowExplanation: '.t3js-upgradeWizards-list-row-explanation', + selectorWizardsListRowExecute: '.t3js-upgradeWizards-list-row-execute', + selectorWizardsInputToken: '#t3js-upgradeWizards-input-token', + selectorWizardsInputTemplate: '.gridder-show .t3js-upgradeWizards-input', + selectorWizardsInputTitle: '.t3js-upgradeWizards-input-title', + selectorWizardsInputHtml: '.t3js-upgradeWizards-input-html', + selectorWizardsInputPerform: '.t3js-upgradeWizards-input-perform', + selectorWizardsExecuteToken: '#t3js-upgradeWizards-execute-token', - loadingMessage: ProgressBar.render(Severity.loading, 'Loading...', ''), + loadingMessage: ProgressBar.render(Severity.loading, 'Loading...', ''), - initialize: function() { - var self = this; + initialize: function() { + var self = this; - // Load main content on first open - $(document).on('cardlayout:card-opened', function(event, $card) { - if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { - $card.data('isInitialized', true); - self.silentUpgrades(); - self.doneUpgrades(); - } - }); + // Load main content on first open + $(document).on('cardlayout:card-opened', function(event, $card) { + if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) { + $card.data('isInitialized', true); + self.silentUpgrades(); + self.doneUpgrades(); + } + }); - // Mark a done wizard undone - $(document).on('click', this.selectorWizardsDoneRowMarkUndone, function(event) { - var identifier = $(event.target).data('identifier'); - self.markUndone(identifier); - }); + // Mark a done wizard undone + $(document).on('click', this.selectorWizardsDoneRowMarkUndone, function(event) { + var identifier = $(event.target).data('identifier'); + self.markUndone(identifier); + }); - // Execute "fix default mysql connection db charset" blocking wizard - $(document).on('click', this.selectorWizardsBlockingCharsetFix, function(event) { - self.blockingUpgradesDatabaseCharsetFix(); - }); + // Execute "fix default mysql connection db charset" blocking wizard + $(document).on('click', this.selectorWizardsBlockingCharsetFix, function(event) { + self.blockingUpgradesDatabaseCharsetFix(); + }); - // Execute "add required fields + tables" blocking wizard - $(document).on('click', this.selectorWizardsBlockingAddsExecute, function(event) { - self.blockingUpgradesDatabaseAddsExecute(); - }); + // Execute "add required fields + tables" blocking wizard + $(document).on('click', this.selectorWizardsBlockingAddsExecute, function(event) { + self.blockingUpgradesDatabaseAddsExecute(); + }); - // Get user input of a single upgrade wizard - $(document).on('click', this.selectorWizardsListRowExecute, function(event) { - var identifier = $(event.target).data('identifier'); - self.wizardInput(identifier); - }); + // Get user input of a single upgrade wizard + $(document).on('click', this.selectorWizardsListRowExecute, function(event) { + var identifier = $(event.target).data('identifier'); + self.wizardInput(identifier); + }); - // Execute one upgrade wizard - $(document).on('click', this.selectorWizardsInputPerform, function(event) { - var identifier = $(event.target).data('identifier'); - self.wizardExecute(identifier); - }); - }, + // Execute one upgrade wizard + $(document).on('click', this.selectorWizardsInputPerform, function(event) { + var identifier = $(event.target).data('identifier'); + self.wizardExecute(identifier); + }); + }, - silentUpgrades: function() { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - $outputContainer.empty().html(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsSilentUpgrades'), - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - if (data.status.length > 0) { - data.status.forEach((function (element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - })); - } - self.blockingUpgradesDatabaseCharsetTest(); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + silentUpgrades: function() { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + $outputContainer.empty().html(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsSilentUpgrades'), + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + if (data.status.length > 0) { + data.status.forEach((function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + })); + } + self.blockingUpgradesDatabaseCharsetTest(); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - blockingUpgradesDatabaseCharsetTest: function() { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - var charsetTemplate = $(this.selectorWizardsBlockingCharsetTemplate).html(); - $outputContainer.append().html(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetTest'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true) { - if (data.needsUpdate === true) { - $outputContainer.append($(charsetTemplate).clone()); - } else { - self.blockingUpgradesDatabaseAdds(); - } - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + blockingUpgradesDatabaseCharsetTest: function() { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + var charsetTemplate = $(this.selectorWizardsBlockingCharsetTemplate).html(); + $outputContainer.append().html(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetTest'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true) { + if (data.needsUpdate === true) { + $outputContainer.append($(charsetTemplate).clone()); + } else { + self.blockingUpgradesDatabaseAdds(); + } + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - blockingUpgradesDatabaseCharsetFix: function() { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - $outputContainer.append().html(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetFix'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true) { - if (Array.isArray(data.status) && data.status.length > 0) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - self.removeLoadingMessage($outputContainer); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + blockingUpgradesDatabaseCharsetFix: function() { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + $outputContainer.append().html(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetFix'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true) { + if (Array.isArray(data.status) && data.status.length > 0) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + self.removeLoadingMessage($outputContainer); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - blockingUpgradesDatabaseAdds: function() { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - var breakingAddsTemplate = $(this.selectorWizardsBlockingAddsTemplate).html(); - $outputContainer.append().html(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsBlockingDatabaseAdds'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true) { - if (data.needsUpdate === true) { - var adds = $(breakingAddsTemplate).clone(); - if (typeof(data.adds.tables) === 'object') { - data.adds.tables.forEach(function(element) { - adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + '<br>'); - }); - } - if (typeof(data.adds.columns) === 'object') { - data.adds.columns.forEach(function(element) { - adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Field: ' + element.field + '<br>'); - }); - } - if (typeof(data.adds.indexes) === 'object') { - data.adds.indexes.forEach(function(element) { - adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Index: ' + element.index + '<br>'); - }); - } - $outputContainer.append(adds); - } else { - self.wizardsList(); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - self.removeLoadingMessage($outputContainer); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + blockingUpgradesDatabaseAdds: function() { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + var breakingAddsTemplate = $(this.selectorWizardsBlockingAddsTemplate).html(); + $outputContainer.append().html(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsBlockingDatabaseAdds'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true) { + if (data.needsUpdate === true) { + var adds = $(breakingAddsTemplate).clone(); + if (typeof(data.adds.tables) === 'object') { + data.adds.tables.forEach(function(element) { + adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + '<br>'); + }); + } + if (typeof(data.adds.columns) === 'object') { + data.adds.columns.forEach(function(element) { + adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Field: ' + element.field + '<br>'); + }); + } + if (typeof(data.adds.indexes) === 'object') { + data.adds.indexes.forEach(function(element) { + adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Index: ' + element.index + '<br>'); + }); + } + $outputContainer.append(adds); + } else { + self.wizardsList(); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + self.removeLoadingMessage($outputContainer); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - blockingUpgradesDatabaseAddsExecute: function() { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - $outputContainer.empty().html(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsBlockingDatabaseExecute'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true) { - if (Array.isArray(data.status) && data.status.length > 0) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - self.wizardsList(); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - self.removeLoadingMessage($outputContainer); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + blockingUpgradesDatabaseAddsExecute: function() { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + $outputContainer.empty().html(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsBlockingDatabaseExecute'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true) { + if (Array.isArray(data.status) && data.status.length > 0) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + self.wizardsList(); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + self.removeLoadingMessage($outputContainer); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - wizardsList: function() { - var self = this; - var listTemplate = $(this.selectorWizardsListTemplate); - var wizardTemplate = $(this.selectorWizardsListRowTemplate); - var $outputContainer = $(this.selectorOutputWizardsContainer); - $outputContainer.append(self.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsList'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - var list = $(listTemplate).clone(); - list.removeClass('t3js-upgradeWizards-list-template'); - if (data.success === true) { - var numberOfWizardsTodo = 0; - var numberOfWizards = 0; - if (Array.isArray(data.wizards) && data.wizards.length > 0) { - numberOfWizards = data.wizards.length; - data.wizards.forEach(function(element) { - if (element.shouldRenderWizard === true) { - var aRow = $(wizardTemplate).clone(); - numberOfWizardsTodo = numberOfWizardsTodo +1; - aRow.removeClass('t3js-upgradeWizards-list-row-template'); - aRow.find(self.selectorWizardsListRowTitle).empty().text(element.title); - aRow.find(self.selectorWizardsListRowExplanation).empty().text(element.explanation); - aRow.find(self.selectorWizardsListRowExecute).data('identifier', element.identifier); - list.find(self.selectorWizardsListRows).append(aRow); - } - }); - list.find(self.selectorWizardsListRows + ' hr:last').remove(); - } - var percent = 100; - if (numberOfWizardsTodo > 0) { - percent = ((numberOfWizards - numberOfWizardsTodo) / data.wizards.length) * 100; - } - list.find('.progress-bar') - .css('width', percent + '%') - .attr('aria-valuenow', percent) - .find('span') - .text(parseInt(percent) + '%'); - $outputContainer.append(list); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - self.removeLoadingMessage($outputContainer); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + wizardsList: function() { + var self = this; + var listTemplate = $(this.selectorWizardsListTemplate); + var wizardTemplate = $(this.selectorWizardsListRowTemplate); + var $outputContainer = $(this.selectorOutputWizardsContainer); + $outputContainer.append(self.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsList'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + var list = $(listTemplate).clone(); + list.removeClass('t3js-upgradeWizards-list-template'); + if (data.success === true) { + var numberOfWizardsTodo = 0; + var numberOfWizards = 0; + if (Array.isArray(data.wizards) && data.wizards.length > 0) { + numberOfWizards = data.wizards.length; + data.wizards.forEach(function(element) { + if (element.shouldRenderWizard === true) { + var aRow = $(wizardTemplate).clone(); + numberOfWizardsTodo = numberOfWizardsTodo + 1; + aRow.removeClass('t3js-upgradeWizards-list-row-template'); + aRow.find(self.selectorWizardsListRowTitle).empty().text(element.title); + aRow.find(self.selectorWizardsListRowExplanation).empty().text(element.explanation); + aRow.find(self.selectorWizardsListRowExecute).data('identifier', element.identifier); + list.find(self.selectorWizardsListRows).append(aRow); + } + }); + list.find(self.selectorWizardsListRows + ' hr:last').remove(); + } + var percent = 100; + if (numberOfWizardsTodo > 0) { + percent = ((numberOfWizards - numberOfWizardsTodo) / data.wizards.length) * 100; + } + list.find('.progress-bar') + .css('width', percent + '%') + .attr('aria-valuenow', percent) + .find('span') + .text(parseInt(percent) + '%'); + $outputContainer.append(list); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + self.removeLoadingMessage($outputContainer); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - wizardInput: function(identifier) { - var self = this; - var $outputContainer = $(this.selectorOutputWizardsContainer); - var inputTemplate = $(this.selectorWizardsInputTemplate); - $outputContainer.empty().html(this.loadingMessage); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'upgradeWizardsInput', - 'token': $(this.selectorWizardsInputToken).text(), - 'identifier': identifier - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - var input = $(inputTemplate).clone(); - input.removeClass('t3js-upgradeWizards-input'); - if (data.success === true) { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = FlashMessage.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - if (data.userInput.wizardHtml.length > 0) { - input.find(self.selectorWizardsInputHtml).html(data.userInput.wizardHtml); - } - input.find(self.selectorWizardsInputTitle).text(data.userInput.title); - input.find(self.selectorWizardsInputPerform).data('identifier', data.userInput.identifier); - } - $outputContainer.append(input); - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + wizardInput: function(identifier) { + var self = this; + var $outputContainer = $(this.selectorOutputWizardsContainer); + var inputTemplate = $(this.selectorWizardsInputTemplate); + $outputContainer.empty().html(this.loadingMessage); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'upgradeWizardsInput', + 'token': $(this.selectorWizardsInputToken).text(), + 'identifier': identifier + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + var input = $(inputTemplate).clone(); + input.removeClass('t3js-upgradeWizards-input'); + if (data.success === true) { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = FlashMessage.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + if (data.userInput.wizardHtml.length > 0) { + input.find(self.selectorWizardsInputHtml).html(data.userInput.wizardHtml); + } + input.find(self.selectorWizardsInputTitle).text(data.userInput.title); + input.find(self.selectorWizardsInputPerform).data('identifier', data.userInput.identifier); + } + $outputContainer.append(input); + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - wizardExecute: function(identifier) { - var self = this; - var postData = { - 'install[action]': 'upgradeWizardsExecute', - 'install[token]': $(this.selectorWizardsExecuteToken).text(), - 'install[identifier]': identifier - }; - $($(this.selectorOutputWizardsContainer + ' form').serializeArray()).each(function() { - postData[this.name] = this.value; - }); - var $outputContainer = $(this.selectorOutputWizardsContainer); - var $outputDoneContainer = $(this.selectorOutputDoneContainer); - $outputContainer.empty().html(this.loadingMessage); - $.ajax({ - method: 'POST', - data: postData, - url: Router.getUrl(), - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true) { - if (Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - self.wizardsList(); - $outputDoneContainer.empty(); - self.doneUpgrades(); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + wizardExecute: function(identifier) { + var self = this; + var postData = { + 'install[action]': 'upgradeWizardsExecute', + 'install[token]': $(this.selectorWizardsExecuteToken).text(), + 'install[identifier]': identifier + }; + $($(this.selectorOutputWizardsContainer + ' form').serializeArray()).each(function() { + postData[this.name] = this.value; + }); + var $outputContainer = $(this.selectorOutputWizardsContainer); + var $outputDoneContainer = $(this.selectorOutputDoneContainer); + $outputContainer.empty().html(this.loadingMessage); + $.ajax({ + method: 'POST', + data: postData, + url: Router.getUrl(), + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true) { + if (Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + self.wizardsList(); + $outputDoneContainer.empty(); + self.doneUpgrades(); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - doneUpgrades: function() { - var self = this; - var $outputContainer = $(this.selectorOutputDoneContainer); - var rowTemplate = $(this.selectorWizardsDoneRowTemplate).html(); - var bodyTemplate = $(this.selectorWizardsDoneBodyTemplate).html(); - $outputContainer.append(this.loadingMessage); - $.ajax({ - url: Router.getUrl('upgradeWizardsDoneUpgrades'), - cache: false, - success: function(data) { - self.removeLoadingMessage($outputContainer); - if (data.success === true) { - if (Array.isArray(data.status) && data.status.length > 0) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - }); - } - var body = $(bodyTemplate).clone(); - var hasBodyContent = false; - var $wizardsDoneContainer = body.find(self.selectorWizardsDoneRows); - if (Array.isArray(data.wizardsDone) && data.wizardsDone.length > 0) { - data.wizardsDone.forEach(function(element) { - hasBodyContent = true; - var aRow = $(rowTemplate).clone(); - aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier); - aRow.find(self.selectorWizardsDoneRowTitle).text(element.title); - $wizardsDoneContainer.append(aRow); - }); - } - if (Array.isArray(data.rowUpdatersDone) && data.rowUpdatersDone.length > 0) { - data.rowUpdatersDone.forEach(function(element) { - hasBodyContent = true; - var aRow = $(rowTemplate).clone(); - aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier); - aRow.find(self.selectorWizardsDoneRowTitle).text(element.title); - $wizardsDoneContainer.append(aRow); - }); - } - if (hasBodyContent === true) { - $outputContainer.append(body); - } - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - self.removeLoadingMessage($outputContainer); - $outputContainer.append(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + doneUpgrades: function() { + var self = this; + var $outputContainer = $(this.selectorOutputDoneContainer); + var rowTemplate = $(this.selectorWizardsDoneRowTemplate).html(); + var bodyTemplate = $(this.selectorWizardsDoneBodyTemplate).html(); + $outputContainer.append(this.loadingMessage); + $.ajax({ + url: Router.getUrl('upgradeWizardsDoneUpgrades'), + cache: false, + success: function(data) { + self.removeLoadingMessage($outputContainer); + if (data.success === true) { + if (Array.isArray(data.status) && data.status.length > 0) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + }); + } + var body = $(bodyTemplate).clone(); + var hasBodyContent = false; + var $wizardsDoneContainer = body.find(self.selectorWizardsDoneRows); + if (Array.isArray(data.wizardsDone) && data.wizardsDone.length > 0) { + data.wizardsDone.forEach(function(element) { + hasBodyContent = true; + var aRow = $(rowTemplate).clone(); + aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier); + aRow.find(self.selectorWizardsDoneRowTitle).text(element.title); + $wizardsDoneContainer.append(aRow); + }); + } + if (Array.isArray(data.rowUpdatersDone) && data.rowUpdatersDone.length > 0) { + data.rowUpdatersDone.forEach(function(element) { + hasBodyContent = true; + var aRow = $(rowTemplate).clone(); + aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier); + aRow.find(self.selectorWizardsDoneRowTitle).text(element.title); + $wizardsDoneContainer.append(aRow); + }); + } + if (hasBodyContent === true) { + $outputContainer.append(body); + } + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + self.removeLoadingMessage($outputContainer); + $outputContainer.append(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - markUndone: function(identifier) { - var self = this; - var $outputContainer = $(this.selectorOutputDoneContainer); - $outputContainer.empty().html(this.loadingMessage); - $.ajax({ - url: Router.getUrl(), - method: 'POST', - data: { - 'install': { - 'action': 'upgradeWizardsMarkUndone', - 'token': $(this.selectorMarkUndoneToken).text(), - 'identifier': identifier - } - }, - cache: false, - success: function(data) { - $outputContainer.empty(); - if (data.success === true && Array.isArray(data.status)) { - data.status.forEach(function(element) { - var message = InfoBox.render(element.severity, element.title, element.message); - $outputContainer.append(message); - self.doneUpgrades(); - self.blockingUpgradesDatabaseCharsetTest(); - }); - } else { - var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); - $outputContainer.empty().html(message); - } - }, - error: function(xhr) { - Router.handleAjaxError(xhr); - } - }); - }, + markUndone: function(identifier) { + var self = this; + var $outputContainer = $(this.selectorOutputDoneContainer); + $outputContainer.empty().html(this.loadingMessage); + $.ajax({ + url: Router.getUrl(), + method: 'POST', + data: { + 'install': { + 'action': 'upgradeWizardsMarkUndone', + 'token': $(this.selectorMarkUndoneToken).text(), + 'identifier': identifier + } + }, + cache: false, + success: function(data) { + $outputContainer.empty(); + if (data.success === true && Array.isArray(data.status)) { + data.status.forEach(function(element) { + var message = InfoBox.render(element.severity, element.title, element.message); + $outputContainer.append(message); + self.doneUpgrades(); + self.blockingUpgradesDatabaseCharsetTest(); + }); + } else { + var message = FlashMessage.render(Severity.error, 'Something went wrong', ''); + $outputContainer.empty().html(message); + } + }, + error: function(xhr) { + Router.handleAjaxError(xhr); + } + }); + }, - removeLoadingMessage: function($container) { - $container.find('.alert-loading').remove(); - } - }; -}); + removeLoadingMessage: function($container) { + $container.find('.alert-loading').remove(); + } + }; + }); diff --git a/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js b/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js index 7aca611178aa019590f990e52c9f7367962f70b3..4cc7754e6c081eede6c81befd3da3d1b60dd1713 100644 --- a/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js +++ b/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js @@ -1,21 +1,21 @@ var require = { - baseUrl: '', - urlArgs: 'bust=' + (new Date()).getTime(), - paths: { - 'TYPO3/CMS/Backend': 'sysext/backend/Resources/Public/JavaScript/', - 'TYPO3/CMS/Install': 'sysext/install/Resources/Public/JavaScript/Modules/', - 'jquery': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery/jquery-3.2.1.min', - 'jquery.clearable': 'sysext/backend/Resources/Public/JavaScript/jquery.clearable', - 'TYPO3/CMS/Core/Contrib/jquery.minicolors': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors', - 'bootstrap': 'sysext/install/Resources/Public/JavaScript/bootstrap.min', - 'chosen': 'sysext/install/Resources/Public/JavaScript/chosen.jquery.min' - }, - shim: { - jQuery: { - exports: '$' - }, - 'bootstrap': { - 'deps': ['jquery'] - } - } + baseUrl: '', + urlArgs: 'bust=' + (new Date()).getTime(), + paths: { + 'TYPO3/CMS/Backend': 'sysext/backend/Resources/Public/JavaScript/', + 'TYPO3/CMS/Install': 'sysext/install/Resources/Public/JavaScript/Modules/', + 'jquery': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery/jquery-3.2.1.min', + 'jquery.clearable': 'sysext/backend/Resources/Public/JavaScript/jquery.clearable', + 'TYPO3/CMS/Core/Contrib/jquery.minicolors': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors', + 'bootstrap': 'sysext/install/Resources/Public/JavaScript/bootstrap.min', + 'chosen': 'sysext/install/Resources/Public/JavaScript/chosen.jquery.min' + }, + shim: { + jQuery: { + exports: '$' + }, + 'bootstrap': { + 'deps': ['jquery'] + } + } }; diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js b/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js index 360d91b905d0882f1b266f7c90486d2e19e434fb..0f13c0784322029b31d45dc8d2cec71738022c40 100644 --- a/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js +++ b/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js @@ -18,30 +18,30 @@ * `TYPO3.lang.foo[0].target = 'blah'` becomes `TYPO3.lang['foo'] = 'blah'` */ define(['jquery'], function($) { - /** - * - * @type {{}} - * @exports TYPO3/CMS/Lang/Lang - */ - var Lang = {}; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Lang/Lang + */ + var Lang = {}; - /** - * - */ - Lang.convertToOneDimension = function() { - var originalLangObject = $.extend(true, {}, TYPO3.lang); - TYPO3.lang = []; - $.each(originalLangObject, function(index, value) { - if (typeof value === "object") { - TYPO3.lang[index] = value[0].target || value[0].source; - } else { - TYPO3.lang[index] = value; - } - }); + /** + * + */ + Lang.convertToOneDimension = function() { + var originalLangObject = $.extend(true, {}, TYPO3.lang); + TYPO3.lang = []; + $.each(originalLangObject, function(index, value) { + if (typeof value === "object") { + TYPO3.lang[index] = value[0].target || value[0].source; + } else { + TYPO3.lang[index] = value; + } + }); - delete originalLangObject; - }; + delete originalLangObject; + }; - Lang.convertToOneDimension(); - return TYPO3.lang; + Lang.convertToOneDimension(); + return TYPO3.lang; }); diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js b/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js index 0d8d2e9eb6cd58a18b512da4a737b39405ebb3dd..704dbe50e36c2ddf87b778f90ec4030b4cd34ae6 100644 --- a/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js +++ b/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js @@ -16,748 +16,748 @@ * Language module class */ define(['jquery', - 'moment', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Notification', - 'datatables', - 'TYPO3/CMS/Backend/jquery.clearable' - ], function($, moment, Icons, Notification) { - 'use strict'; - - /** - * - * @type {{me: *, context: null, table: null, topMenu: null, currentRequest: null, settings: {}, icons: {}, labels: {}, identifiers: {searchField: string, topMenu: string, activateIcon: string, deactivateIcon: string, downloadIcon: string, loadingIcon: string, completeIcon: string, progressBar: string, progressBarText: string, progressBarInner: string, lastUpdate: string, languagePrefix: string, extensionPrefix: string}, classes: {enabled: string, disabled: string, processing: string, complete: string, extension: string, actions: string, progressBar: string, loading: string, lastUpdate: string}}} - * @exports TYPO3/CMS/Lang/LanguageModule - */ - var LanguageModule = { - me: this, - context: null, - table: null, - topMenu: null, - currentRequest: null, - userAbortRequest: false, - settings: {}, - icons: {}, - labels: {}, - buttons: { - update: null, - cancel: null - }, - identifiers: { - searchField: '.t3js-language-searchfield', - topMenu: 'div.t3js-module-docheader', - activateIcon: 'span.activateIcon', - deactivateIcon: 'span.deactivateIcon', - downloadIcon: 'span.downloadIcon', - removeIcon: 'span.removeIcon', - loadingIcon: 'span.loadingIcon', - completeIcon: 'span.completeIcon', - progressBar: 'div.progressBar', - progressBarText: 'div.progress-text', - progressBarInner: 'div.progress-bar', - lastUpdate: 'td.lastUpdate', - languagePrefix: 'language-', - extensionPrefix: 'extension-' - }, - classes: { - enabled: 'enabled', - disabled: 'disabled', - processing: 'processing', - complete: 'complete', - extension: 'extensionName', - actions: 'actions', - progressBar: 'progressBar', - loading: 'loading', - lastUpdate: 'lastUpdate' - } - }; - - /** - * Initialize language table - * - * @param {HTMLElement} contextElement - * @param {HTMLElement} tableElement - */ - LanguageModule.initializeLanguageTable = function(contextElement, tableElement) { - LanguageModule.context = $(contextElement); - LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu); - LanguageModule.settings = LanguageModule.context.data(); - LanguageModule.icons = LanguageModule.buildIcons(); - LanguageModule.labels = LanguageModule.buildLabels(); - LanguageModule.table = LanguageModule.buildLanguageTable(tableElement); - LanguageModule.initializeSearchField(); - LanguageModule.initializeEventHandler(); - LanguageModule.initializeButtons(); - }; - - /** - * Initialize translation table - * - * @param {HTMLElement} contextElement - * @param {HTMLElement} tableElement - */ - LanguageModule.initializeTranslationTable = function(contextElement, tableElement) { - LanguageModule.context = $(contextElement); - LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu); - LanguageModule.settings = LanguageModule.context.data(); - LanguageModule.icons = LanguageModule.buildIcons(); - LanguageModule.labels = LanguageModule.buildLabels(); - LanguageModule.table = LanguageModule.buildTranslationTable(tableElement); - LanguageModule.initializeSearchField(); - LanguageModule.initializeEventHandler(); - }; - - /** - * Activate a language - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.activateLanguageAction = function(triggerElement, parameters) { - var $row = $(triggerElement).closest('tr'), - locale = $row.data('locale'); - - if ($row.hasClass(LanguageModule.classes.processing)) { - LanguageModule.abortAjaxRequest(); - } - LanguageModule.executeAjaxRequest(LanguageModule.settings.activateLanguageUri, {locale: locale}, function(response, status) { - if (status === 'success' && response.success) { - $row.removeClass(LanguageModule.classes.disabled).addClass(LanguageModule.classes.enabled); - LanguageModule.displaySuccess(LanguageModule.labels.languageActivated); - } else { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } - }); - }; - - /** - * Deactivate a language - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.deactivateLanguageAction = function(triggerElement, parameters) { - var $row = $(triggerElement).closest('tr'), - locale = $row.data('locale'); - - if ($row.hasClass(LanguageModule.classes.processing)) { - LanguageModule.abortAjaxRequest(); - } - LanguageModule.executeAjaxRequest(LanguageModule.settings.deactivateLanguageUri, {locale: locale}, function(response, status) { - if (status === 'success' && response.success) { - $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled); - LanguageModule.displaySuccess(LanguageModule.labels.languageDeactivated); - } else { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } - }); - }; - - /** - * Remove a language - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.removeLanguageAction = function(triggerElement, parameters) { - var $row = $(triggerElement).closest('tr'), - locale = $row.data('locale'), - $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row); - - if ($row.hasClass(LanguageModule.classes.processing)) { - LanguageModule.abortAjaxRequest(); - } - LanguageModule.executeAjaxRequest(LanguageModule.settings.removeLanguageUri, {locale: locale}, function(response, status) { - if (status === 'success' && response.success) { - $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled); - $lastUpdate.html(''); - LanguageModule.displaySuccess(LanguageModule.labels.languageRemoved); - } else { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } - }); - }; - - /** - * Update a language - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.updateLanguageAction = function(triggerElement, parameters) { - var $row = $(triggerElement).closest('tr'), - locale = $row.data('locale'), - $progressBar = $(LanguageModule.identifiers.progressBar, $row), - $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row); - - $row.addClass(LanguageModule.classes.processing); - LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) { - if (status === 'success') { - LanguageModule.setProgress($progressBar, 100); - LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); - $row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); - $lastUpdate.html(LanguageModule.formatDate(response.timestamp)); - } else if (status === 'progress') { - LanguageModule.setProgress($progressBar, parseFloat(response.progress)); - } else if (status === 'error') { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } - }); - }; - - /** - * Update all active languages - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.updateActiveLanguagesAction = function(triggerElement, parameters) { - var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container()); - if ($activeRows.length > 0) { - LanguageModule.updateButtonStatus('update'); - LanguageModule.topMenu.addClass(LanguageModule.classes.processing); - $activeRows.addClass(LanguageModule.classes.processing); - LanguageModule.loadTranslationsByRows($activeRows, function(row, status, data, response) { - var $progressBar = $(LanguageModule.identifiers.progressBar, row), - $lastUpdate = $(LanguageModule.identifiers.lastUpdate, row); - - if (status === 'success') { - LanguageModule.setProgress($progressBar, 100); - row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); - $lastUpdate.html(LanguageModule.formatDate(response.timestamp)); - } else if (status === 'progress') { - LanguageModule.setProgress($progressBar, parseFloat(response.progress)); - } else if (status === 'error') { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } else if (status === 'finished') { - LanguageModule.updateButtonStatus('cancel'); - LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); - LanguageModule.topMenu.removeClass(LanguageModule.classes.processing); - } - }); - } else { - LanguageModule.displayError(LanguageModule.labels.noLanguageActivated); - } - }; - - /** - * Cancel language update - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.cancelLanguageUpdateAction = function(triggerElement, parameters) { - var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container()); - LanguageModule.updateButtonStatus('cancel'); - LanguageModule.topMenu.removeClass(LanguageModule.classes.processing); - $activeRows.removeClass(LanguageModule.classes.processing); - LanguageModule.abortAjaxRequest(); - }; - - /** - * Update an extension translation - * - * @param {HTMLElement} triggerElement - * @param {Object} parameters - */ - LanguageModule.updateTranslationAction = function(triggerElement, parameters) { - var $row = $(triggerElement).closest('tr'), - $cell = $(triggerElement).closest('td'), - extension = $row.data('extension'), - locale = LanguageModule.table.cell($cell).data().locale; - - $cell.addClass(LanguageModule.classes.processing); - LanguageModule.loadTranslationByExtensionAndLocale(extension, locale, function(status, data, response) { - if (status === 'success') { - LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); - $cell.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); - } else if (status === 'error') { - LanguageModule.displayError(LanguageModule.labels.errorOccurred); - } - }); - }; - - /** - * Build icons - * - * @returns {{activate: (*|jQuery), deactivate: (*|jQuery), download: (*|jQuery), loading: (*|jQuery), complete: (*|jQuery), progressBar: (*|jQuery)}} - */ - LanguageModule.buildIcons = function() { - return { - activate: $(LanguageModule.identifiers.activateIcon, LanguageModule.context).html(), - deactivate: $(LanguageModule.identifiers.deactivateIcon, LanguageModule.context).html(), - download: $(LanguageModule.identifiers.downloadIcon, LanguageModule.context).html(), - remove: $(LanguageModule.identifiers.removeIcon, LanguageModule.context).html(), - loading: $(LanguageModule.identifiers.loadingIcon, LanguageModule.context).html(), - complete: $(LanguageModule.identifiers.completeIcon, LanguageModule.context).html(), - progressBar: $(LanguageModule.identifiers.progressBar, LanguageModule.context).html() - } - }; - - /** - * Build labels - * - * @returns {{processing: *, search: *, loadingRecords: *, zeroRecords: *, emptyTable: *, dateFormat: *, errorHeader: *, infoHeader: *, successHeader: *, languageActivated: *, errorOccurred: *, languageDeactivated: *, languageRemoved: *, updateComplete: *}} - */ - LanguageModule.buildLabels = function() { - return { - processing: TYPO3.lang['table.processing'], - search: TYPO3.lang['table.search'], - loadingRecords: TYPO3.lang['table.loadingRecords'], - zeroRecords: TYPO3.lang['table.zeroRecords'], - emptyTable: TYPO3.lang['table.emptyTable'], - dateFormat: TYPO3.lang['table.dateFormat'], - errorHeader: TYPO3.lang['flashmessage.error'], - infoHeader: TYPO3.lang['flashmessage.information'], - successHeader: TYPO3.lang['flashmessage.success'], - languageActivated: TYPO3.lang['flashmessage.languageActivated'], - errorOccurred: TYPO3.lang['flashmessage.errorOccurred'], - languageDeactivated: TYPO3.lang['flashmessage.languageDeactivated'], - languageRemoved: TYPO3.lang['flashmessage.languageRemoved'], - noLanguageActivated: TYPO3.lang['flashmessage.noLanguageActivated'], - updateComplete: TYPO3.lang['flashmessage.updateComplete'], - canceled: TYPO3.lang['flashmessage.canceled'] - } - }; - - /** - * Build language table - * - * @param {HTMLElement} tableElement - * @returns {Object} - */ - LanguageModule.buildLanguageTable = function(tableElement) { - return $(tableElement).DataTable({ - dom: 'lrtip', - serverSide: false, - stateSave: true, - paging: false, - info: false, - ordering: true, - columnDefs: [{targets: 4, orderable: false}], - language: LanguageModule.labels, - order: [[1, 'asc']] - }); - }; - - /** - * Initialize translation table - * - * @param {HTMLElement} tableElement - * @returns {Object} - */ - LanguageModule.buildTranslationTable = function(tableElement) { - var languageCount = $(tableElement).data('languageCount'), - columns = [ - { - render: function(data, type, row) { - return LanguageModule.buildImage(data.icon, data.title, data.title, data.width, data.height); - }, - width: '20px', - orderable: false, - targets: 0 - }, { - render: function(data, type, row) { - return data.title; - }, - className: LanguageModule.classes.extension, - targets: 1 - } - ]; - - for (var i = 0; i < languageCount; i++) { - columns.push({ - render: function(data, type, row) { - var links = [ - LanguageModule.buildActionLink('updateTranslation', data, LanguageModule.icons.download), - LanguageModule.buildActionLink('removeTranslation', data, LanguageModule.icons.remove), - LanguageModule.buildLoadingIndicator(), - LanguageModule.buildCompleteIndicator() - ]; - return links.join(''); - }, - className: 'dt-center', - targets: (i + 2) - }); - } - - return $(tableElement).DataTable({ - dom: 'lrtip', - serverSide: false, - stateSave: true, - paging: false, - info: false, - ordering: true, - language: LanguageModule.labels, - ajax: LanguageModule.settings.listTranslationsUri, - order: [[1, 'asc']], - columnDefs: columns, - createdRow: function (row, data, index) { - var $row = $(row); - $row.attr('id', LanguageModule.identifiers.extensionPrefix + data[1].key); - $row.attr('data-extension', data[1].key); - } - }); - }; - - /** - * Initialize search field - */ - LanguageModule.initializeSearchField = function() { - var getVars = LanguageModule.getUrlVars(); - var currentSearch = (getVars['search'] ? getVars['search'] : LanguageModule.table.search()); - $(LanguageModule.identifiers.searchField) - .val(currentSearch) - .on('input', function() { - LanguageModule.table.search($(this).val()).draw(); - }) - .clearable({ - onClear: function() { - if (LanguageModule.table !== null) { - LanguageModule.table.search('').draw(); - } - } - }) - .parents('form').on('submit', function() { - return false; - }); - }; - - /** - * Initialize event handler, redirect clicks to controller actions - */ - LanguageModule.initializeEventHandler = function() { - $(document).on('click', function(event) { - var $element = $(event.target); - var $parent = $element.closest('[data-action]'); - - if ($element.data('action') !== undefined) { - LanguageModule.handleActionEvent($element, event); - } else if ($parent.data('action') !== undefined) { - LanguageModule.handleActionEvent($parent, event); - } - }); - }; - - /** - * Initialize buttons - */ - LanguageModule.initializeButtons = function() { - LanguageModule.buttons.update = LanguageModule.topMenu.find('.t3js-button-update'); - LanguageModule.buttons.cancel = LanguageModule.topMenu.find('.t3js-button-cancel'); - }; - - /** - * Update buttons in top menu - * - * @param {String} action - */ - LanguageModule.updateButtonStatus = function(action) { - switch (action) { - case 'update': - LanguageModule.buttons.update.data('action', 'cancelLanguageUpdate'); - LanguageModule.buttons.cancel.removeClass('disabled'); - Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(spinner) { - LanguageModule.buttons.update.find('span.icon').replaceWith(spinner); - }); - break; - case 'cancel': - LanguageModule.buttons.update.data('action', 'updateActiveLanguages'); - LanguageModule.buttons.cancel.addClass('disabled'); - Icons.getIcon('actions-system-extension-download', Icons.sizes.small).done(function(download) { - LanguageModule.buttons.update.find('span.icon').replaceWith(download); - }); - break; - } - }; - - /** - * Handler for "action" events - * - * @param {Object} element - * @param {Event} event - */ - LanguageModule.handleActionEvent = function(element, event) { - event.preventDefault(); - var data = element.data(); - var actionName = data.action + 'Action'; - if (actionName in LanguageModule) { - LanguageModule[actionName](element, data); - } - }; - - /** - * Load translations for all extensions by given locale - * - * @param {String} locale - * @param {function} callback - * @param {Number} counter - */ - LanguageModule.loadTranslationsByLocale = function(locale, callback, counter) { - counter = counter || 0; - var data = {locale: locale, count: counter}; - LanguageModule.executeAjaxRequest(LanguageModule.settings.updateLanguageUri, data, function(response, status) { - if (status === 'success' && response.success) { - if (parseFloat(response.progress) < 100) { - callback('progress', data, response); - counter++; - LanguageModule.loadTranslationsByLocale(locale, callback, counter); - } else { - callback('success', data, response); - } - } else { - callback('error', data, response); - } - }); - }; - - /** - * Load translations for all extensions by given rows - * - * @param {Object} rows - * @param {function} callback - */ - LanguageModule.loadTranslationsByRows = function(rows, callback) { - if (rows) { - rows = $(rows).toArray(); - var $row = $(rows.shift()), - locale = $row.data('locale'); - - LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) { - callback($row, status, data, response); - if (status === 'success') { - if (rows.length) { - LanguageModule.loadTranslationsByRows(rows, callback); - } else { - callback($row, 'finished', data, response); - } - } - }); - } - }; - - /** - * Load translation for one extension by given locale - * - * @param {String} extension - * @param {String} locale - * @param {function} callback - */ - LanguageModule.loadTranslationByExtensionAndLocale = function(extension, locale, callback) { - var data = {extension: extension, locale: locale}; - LanguageModule.executeAjaxRequest(LanguageModule.settings.updateTranslationUri, data, function(response, status) { - if (status === 'success' && response.success) { - callback('success', data, response); - } else { - callback('error', data, response); - } - }); - }; - - /** - * Execute AJAX request - * - * @param {String} uri - * @param {Object} data - * @param {function} callback - */ - LanguageModule.executeAjaxRequest = function(uri, data, callback) { - var newData = {}; - newData[LanguageModule.settings.prefix] = { - data: data - }; - LanguageModule.currentRequest = $.ajax({ - type: 'POST', - cache: false, - url: uri, - data: newData, - dataType: 'json', - success: function(response, status) { - if (typeof callback === 'function') { - callback(response, status, ''); - } - }, - error: function(response, status, error) { - if (typeof callback === 'function') { - callback(response, status, error); - } - } - }); - }; - - /** - * Abort current AJAX request - */ - LanguageModule.abortAjaxRequest = function() { - if (LanguageModule.currentRequest) { - LanguageModule.userAbortRequest = true; - LanguageModule.currentRequest.abort(); - } - }; - - /** - * Display error flash message - * - * @param {String} label - */ - LanguageModule.displayError = function(label) { - if (LanguageModule.userAbortRequest) { - LanguageModule.displaySuccess(LanguageModule.labels.canceled); - } else if (typeof label === 'string' && label !== '') { - Notification.error(LanguageModule.labels.errorHeader, label); - } - }; - - /** - * Display information flash message - * - * @param {String} label - */ - LanguageModule.displayInformation = function(label) { - if (typeof label === 'string' && label !== '') { - Notification.info(LanguageModule.labels.infoHeader, label); - } - }; - - /** - * Display success flash message - * - * @param {String} label - */ - LanguageModule.displaySuccess = function(label) { - if (typeof label === 'string' && label !== '') { - Notification.success(LanguageModule.labels.successHeader, label); - } - }; - - /** - * Build action link - * - * @param {String} action - * @param {Object} parameters - * @param {String} content - * @returns {Object} - */ - LanguageModule.buildActionLink = function(action, parameters, content) { - var $link = $('<a>'); - - $link.addClass(action + 'Link'); - $link.attr('data-action', action); - for (var name in parameters) { - if (parameters.hasOwnProperty(name)) { - $link.attr('data-' + name, parameters[name]); - } - } - $link.html(content); - return $link.wrap('<span>').parent().html(); - }; - - /** - * Build progress bar - * - * @returns {Object} - */ - LanguageModule.buildProgressBar = function() { - var $span = $('<span>'); - $span.addClass(LanguageModule.classes.progressBar); - $span.html(LanguageModule.icons.progressBar); - return $span.wrap('<span>').parent().html(); - }; - - /** - * Build loading indicator - * - * @returns {Object} - */ - LanguageModule.buildLoadingIndicator = function() { - var $span = $('<span>'); - $span.addClass(LanguageModule.classes.loading); - $span.html(LanguageModule.icons.loading); - return $span.wrap('<span>').parent().html(); - }; - - /** - * Build complete state indicator - * - * @returns {Object} - */ - LanguageModule.buildCompleteIndicator = function() { - var $span = $('<span>'); - $span.addClass(LanguageModule.classes.complete); - $span.html(LanguageModule.icons.complete); - return $span.wrap('<span>').parent().html(); - }; - - /** - * Build image - * - * @param {String} uri - * @param {String} alt - * @param {String} title - * @param {Number} width - * @param {Number} heigth - * @returns {Object} - */ - LanguageModule.buildImage = function(uri, alt, title, width, heigth) { - var $image = $('<img>'); - $image.attr('src', uri); - $image.attr('alt', alt ? alt : ''); - $image.attr('title', title ? title : ''); - $image.attr('style', 'width: ' + width + 'px; height: ' + heigth + 'px;'); - var $span = $('<span>'); - $span.addClass('typo3-app-icon'); - $span.attr('style', 'background: none; text-align: center;'); - $span.html($image); - return $span.wrap('<span>').parent().html(); - }; - - /** - * Format date - * - * @param {Number} timestamp - * @returns {*} - */ - LanguageModule.formatDate = function(timestamp) { - return moment.unix(timestamp).format(LanguageModule.labels.dateFormat); - }; - - /** - * Set progress bar progress - * - * @param {Object} progressBar - * @param {String} progress - */ - LanguageModule.setProgress = function(progressBar, progress) { - var $inner = $(LanguageModule.identifiers.progressBarInner, progressBar), - $text = $(LanguageModule.identifiers.progressBarText, progressBar); - $inner.css({width: progress + '%'}); - $inner.attr('aria-valuenow', progress); - $text.text(Math.round(progress) + '%'); - }; - - /** - * Utility method to retrieve query parameters - * - * @returns {Array} - */ - LanguageModule.getUrlVars = function getUrlVars() { - var vars = [], hash; - var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i++) { - hash = hashes[i].split('='); - vars.push(hash[0]); - vars[hash[0]] = hash[1]; - } - return vars; - }; - - $(function() { - if ($('#typo3-language-list').length) { - LanguageModule.initializeLanguageTable('div.typo3-module-lang', '#typo3-language-list'); - } else if ($('#typo3-translation-list').length) { - LanguageModule.initializeTranslationTable('div.typo3-module-lang', '#typo3-translation-list'); - } - }); - - return LanguageModule; + 'moment', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Notification', + 'datatables', + 'TYPO3/CMS/Backend/jquery.clearable' +], function($, moment, Icons, Notification) { + 'use strict'; + + /** + * + * @type {{me: *, context: null, table: null, topMenu: null, currentRequest: null, settings: {}, icons: {}, labels: {}, identifiers: {searchField: string, topMenu: string, activateIcon: string, deactivateIcon: string, downloadIcon: string, loadingIcon: string, completeIcon: string, progressBar: string, progressBarText: string, progressBarInner: string, lastUpdate: string, languagePrefix: string, extensionPrefix: string}, classes: {enabled: string, disabled: string, processing: string, complete: string, extension: string, actions: string, progressBar: string, loading: string, lastUpdate: string}}} + * @exports TYPO3/CMS/Lang/LanguageModule + */ + var LanguageModule = { + me: this, + context: null, + table: null, + topMenu: null, + currentRequest: null, + userAbortRequest: false, + settings: {}, + icons: {}, + labels: {}, + buttons: { + update: null, + cancel: null + }, + identifiers: { + searchField: '.t3js-language-searchfield', + topMenu: 'div.t3js-module-docheader', + activateIcon: 'span.activateIcon', + deactivateIcon: 'span.deactivateIcon', + downloadIcon: 'span.downloadIcon', + removeIcon: 'span.removeIcon', + loadingIcon: 'span.loadingIcon', + completeIcon: 'span.completeIcon', + progressBar: 'div.progressBar', + progressBarText: 'div.progress-text', + progressBarInner: 'div.progress-bar', + lastUpdate: 'td.lastUpdate', + languagePrefix: 'language-', + extensionPrefix: 'extension-' + }, + classes: { + enabled: 'enabled', + disabled: 'disabled', + processing: 'processing', + complete: 'complete', + extension: 'extensionName', + actions: 'actions', + progressBar: 'progressBar', + loading: 'loading', + lastUpdate: 'lastUpdate' + } + }; + + /** + * Initialize language table + * + * @param {HTMLElement} contextElement + * @param {HTMLElement} tableElement + */ + LanguageModule.initializeLanguageTable = function(contextElement, tableElement) { + LanguageModule.context = $(contextElement); + LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu); + LanguageModule.settings = LanguageModule.context.data(); + LanguageModule.icons = LanguageModule.buildIcons(); + LanguageModule.labels = LanguageModule.buildLabels(); + LanguageModule.table = LanguageModule.buildLanguageTable(tableElement); + LanguageModule.initializeSearchField(); + LanguageModule.initializeEventHandler(); + LanguageModule.initializeButtons(); + }; + + /** + * Initialize translation table + * + * @param {HTMLElement} contextElement + * @param {HTMLElement} tableElement + */ + LanguageModule.initializeTranslationTable = function(contextElement, tableElement) { + LanguageModule.context = $(contextElement); + LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu); + LanguageModule.settings = LanguageModule.context.data(); + LanguageModule.icons = LanguageModule.buildIcons(); + LanguageModule.labels = LanguageModule.buildLabels(); + LanguageModule.table = LanguageModule.buildTranslationTable(tableElement); + LanguageModule.initializeSearchField(); + LanguageModule.initializeEventHandler(); + }; + + /** + * Activate a language + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.activateLanguageAction = function(triggerElement, parameters) { + var $row = $(triggerElement).closest('tr'), + locale = $row.data('locale'); + + if ($row.hasClass(LanguageModule.classes.processing)) { + LanguageModule.abortAjaxRequest(); + } + LanguageModule.executeAjaxRequest(LanguageModule.settings.activateLanguageUri, {locale: locale}, function(response, status) { + if (status === 'success' && response.success) { + $row.removeClass(LanguageModule.classes.disabled).addClass(LanguageModule.classes.enabled); + LanguageModule.displaySuccess(LanguageModule.labels.languageActivated); + } else { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } + }); + }; + + /** + * Deactivate a language + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.deactivateLanguageAction = function(triggerElement, parameters) { + var $row = $(triggerElement).closest('tr'), + locale = $row.data('locale'); + + if ($row.hasClass(LanguageModule.classes.processing)) { + LanguageModule.abortAjaxRequest(); + } + LanguageModule.executeAjaxRequest(LanguageModule.settings.deactivateLanguageUri, {locale: locale}, function(response, status) { + if (status === 'success' && response.success) { + $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled); + LanguageModule.displaySuccess(LanguageModule.labels.languageDeactivated); + } else { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } + }); + }; + + /** + * Remove a language + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.removeLanguageAction = function(triggerElement, parameters) { + var $row = $(triggerElement).closest('tr'), + locale = $row.data('locale'), + $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row); + + if ($row.hasClass(LanguageModule.classes.processing)) { + LanguageModule.abortAjaxRequest(); + } + LanguageModule.executeAjaxRequest(LanguageModule.settings.removeLanguageUri, {locale: locale}, function(response, status) { + if (status === 'success' && response.success) { + $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled); + $lastUpdate.html(''); + LanguageModule.displaySuccess(LanguageModule.labels.languageRemoved); + } else { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } + }); + }; + + /** + * Update a language + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.updateLanguageAction = function(triggerElement, parameters) { + var $row = $(triggerElement).closest('tr'), + locale = $row.data('locale'), + $progressBar = $(LanguageModule.identifiers.progressBar, $row), + $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row); + + $row.addClass(LanguageModule.classes.processing); + LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) { + if (status === 'success') { + LanguageModule.setProgress($progressBar, 100); + LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); + $row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); + $lastUpdate.html(LanguageModule.formatDate(response.timestamp)); + } else if (status === 'progress') { + LanguageModule.setProgress($progressBar, parseFloat(response.progress)); + } else if (status === 'error') { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } + }); + }; + + /** + * Update all active languages + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.updateActiveLanguagesAction = function(triggerElement, parameters) { + var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container()); + if ($activeRows.length > 0) { + LanguageModule.updateButtonStatus('update'); + LanguageModule.topMenu.addClass(LanguageModule.classes.processing); + $activeRows.addClass(LanguageModule.classes.processing); + LanguageModule.loadTranslationsByRows($activeRows, function(row, status, data, response) { + var $progressBar = $(LanguageModule.identifiers.progressBar, row), + $lastUpdate = $(LanguageModule.identifiers.lastUpdate, row); + + if (status === 'success') { + LanguageModule.setProgress($progressBar, 100); + row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); + $lastUpdate.html(LanguageModule.formatDate(response.timestamp)); + } else if (status === 'progress') { + LanguageModule.setProgress($progressBar, parseFloat(response.progress)); + } else if (status === 'error') { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } else if (status === 'finished') { + LanguageModule.updateButtonStatus('cancel'); + LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); + LanguageModule.topMenu.removeClass(LanguageModule.classes.processing); + } + }); + } else { + LanguageModule.displayError(LanguageModule.labels.noLanguageActivated); + } + }; + + /** + * Cancel language update + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.cancelLanguageUpdateAction = function(triggerElement, parameters) { + var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container()); + LanguageModule.updateButtonStatus('cancel'); + LanguageModule.topMenu.removeClass(LanguageModule.classes.processing); + $activeRows.removeClass(LanguageModule.classes.processing); + LanguageModule.abortAjaxRequest(); + }; + + /** + * Update an extension translation + * + * @param {HTMLElement} triggerElement + * @param {Object} parameters + */ + LanguageModule.updateTranslationAction = function(triggerElement, parameters) { + var $row = $(triggerElement).closest('tr'), + $cell = $(triggerElement).closest('td'), + extension = $row.data('extension'), + locale = LanguageModule.table.cell($cell).data().locale; + + $cell.addClass(LanguageModule.classes.processing); + LanguageModule.loadTranslationByExtensionAndLocale(extension, locale, function(status, data, response) { + if (status === 'success') { + LanguageModule.displaySuccess(LanguageModule.labels.updateComplete); + $cell.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete); + } else if (status === 'error') { + LanguageModule.displayError(LanguageModule.labels.errorOccurred); + } + }); + }; + + /** + * Build icons + * + * @returns {{activate: (*|jQuery), deactivate: (*|jQuery), download: (*|jQuery), loading: (*|jQuery), complete: (*|jQuery), progressBar: (*|jQuery)}} + */ + LanguageModule.buildIcons = function() { + return { + activate: $(LanguageModule.identifiers.activateIcon, LanguageModule.context).html(), + deactivate: $(LanguageModule.identifiers.deactivateIcon, LanguageModule.context).html(), + download: $(LanguageModule.identifiers.downloadIcon, LanguageModule.context).html(), + remove: $(LanguageModule.identifiers.removeIcon, LanguageModule.context).html(), + loading: $(LanguageModule.identifiers.loadingIcon, LanguageModule.context).html(), + complete: $(LanguageModule.identifiers.completeIcon, LanguageModule.context).html(), + progressBar: $(LanguageModule.identifiers.progressBar, LanguageModule.context).html() + } + }; + + /** + * Build labels + * + * @returns {{processing: *, search: *, loadingRecords: *, zeroRecords: *, emptyTable: *, dateFormat: *, errorHeader: *, infoHeader: *, successHeader: *, languageActivated: *, errorOccurred: *, languageDeactivated: *, languageRemoved: *, updateComplete: *}} + */ + LanguageModule.buildLabels = function() { + return { + processing: TYPO3.lang['table.processing'], + search: TYPO3.lang['table.search'], + loadingRecords: TYPO3.lang['table.loadingRecords'], + zeroRecords: TYPO3.lang['table.zeroRecords'], + emptyTable: TYPO3.lang['table.emptyTable'], + dateFormat: TYPO3.lang['table.dateFormat'], + errorHeader: TYPO3.lang['flashmessage.error'], + infoHeader: TYPO3.lang['flashmessage.information'], + successHeader: TYPO3.lang['flashmessage.success'], + languageActivated: TYPO3.lang['flashmessage.languageActivated'], + errorOccurred: TYPO3.lang['flashmessage.errorOccurred'], + languageDeactivated: TYPO3.lang['flashmessage.languageDeactivated'], + languageRemoved: TYPO3.lang['flashmessage.languageRemoved'], + noLanguageActivated: TYPO3.lang['flashmessage.noLanguageActivated'], + updateComplete: TYPO3.lang['flashmessage.updateComplete'], + canceled: TYPO3.lang['flashmessage.canceled'] + } + }; + + /** + * Build language table + * + * @param {HTMLElement} tableElement + * @returns {Object} + */ + LanguageModule.buildLanguageTable = function(tableElement) { + return $(tableElement).DataTable({ + dom: 'lrtip', + serverSide: false, + stateSave: true, + paging: false, + info: false, + ordering: true, + columnDefs: [{targets: 4, orderable: false}], + language: LanguageModule.labels, + order: [[1, 'asc']] + }); + }; + + /** + * Initialize translation table + * + * @param {HTMLElement} tableElement + * @returns {Object} + */ + LanguageModule.buildTranslationTable = function(tableElement) { + var languageCount = $(tableElement).data('languageCount'), + columns = [ + { + render: function(data, type, row) { + return LanguageModule.buildImage(data.icon, data.title, data.title, data.width, data.height); + }, + width: '20px', + orderable: false, + targets: 0 + }, { + render: function(data, type, row) { + return data.title; + }, + className: LanguageModule.classes.extension, + targets: 1 + } + ]; + + for (var i = 0; i < languageCount; i++) { + columns.push({ + render: function(data, type, row) { + var links = [ + LanguageModule.buildActionLink('updateTranslation', data, LanguageModule.icons.download), + LanguageModule.buildActionLink('removeTranslation', data, LanguageModule.icons.remove), + LanguageModule.buildLoadingIndicator(), + LanguageModule.buildCompleteIndicator() + ]; + return links.join(''); + }, + className: 'dt-center', + targets: (i + 2) + }); + } + + return $(tableElement).DataTable({ + dom: 'lrtip', + serverSide: false, + stateSave: true, + paging: false, + info: false, + ordering: true, + language: LanguageModule.labels, + ajax: LanguageModule.settings.listTranslationsUri, + order: [[1, 'asc']], + columnDefs: columns, + createdRow: function(row, data, index) { + var $row = $(row); + $row.attr('id', LanguageModule.identifiers.extensionPrefix + data[1].key); + $row.attr('data-extension', data[1].key); + } + }); + }; + + /** + * Initialize search field + */ + LanguageModule.initializeSearchField = function() { + var getVars = LanguageModule.getUrlVars(); + var currentSearch = (getVars['search'] ? getVars['search'] : LanguageModule.table.search()); + $(LanguageModule.identifiers.searchField) + .val(currentSearch) + .on('input', function() { + LanguageModule.table.search($(this).val()).draw(); + }) + .clearable({ + onClear: function() { + if (LanguageModule.table !== null) { + LanguageModule.table.search('').draw(); + } + } + }) + .parents('form').on('submit', function() { + return false; + }); + }; + + /** + * Initialize event handler, redirect clicks to controller actions + */ + LanguageModule.initializeEventHandler = function() { + $(document).on('click', function(event) { + var $element = $(event.target); + var $parent = $element.closest('[data-action]'); + + if ($element.data('action') !== undefined) { + LanguageModule.handleActionEvent($element, event); + } else if ($parent.data('action') !== undefined) { + LanguageModule.handleActionEvent($parent, event); + } + }); + }; + + /** + * Initialize buttons + */ + LanguageModule.initializeButtons = function() { + LanguageModule.buttons.update = LanguageModule.topMenu.find('.t3js-button-update'); + LanguageModule.buttons.cancel = LanguageModule.topMenu.find('.t3js-button-cancel'); + }; + + /** + * Update buttons in top menu + * + * @param {String} action + */ + LanguageModule.updateButtonStatus = function(action) { + switch (action) { + case 'update': + LanguageModule.buttons.update.data('action', 'cancelLanguageUpdate'); + LanguageModule.buttons.cancel.removeClass('disabled'); + Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(spinner) { + LanguageModule.buttons.update.find('span.icon').replaceWith(spinner); + }); + break; + case 'cancel': + LanguageModule.buttons.update.data('action', 'updateActiveLanguages'); + LanguageModule.buttons.cancel.addClass('disabled'); + Icons.getIcon('actions-system-extension-download', Icons.sizes.small).done(function(download) { + LanguageModule.buttons.update.find('span.icon').replaceWith(download); + }); + break; + } + }; + + /** + * Handler for "action" events + * + * @param {Object} element + * @param {Event} event + */ + LanguageModule.handleActionEvent = function(element, event) { + event.preventDefault(); + var data = element.data(); + var actionName = data.action + 'Action'; + if (actionName in LanguageModule) { + LanguageModule[actionName](element, data); + } + }; + + /** + * Load translations for all extensions by given locale + * + * @param {String} locale + * @param {function} callback + * @param {Number} counter + */ + LanguageModule.loadTranslationsByLocale = function(locale, callback, counter) { + counter = counter || 0; + var data = {locale: locale, count: counter}; + LanguageModule.executeAjaxRequest(LanguageModule.settings.updateLanguageUri, data, function(response, status) { + if (status === 'success' && response.success) { + if (parseFloat(response.progress) < 100) { + callback('progress', data, response); + counter++; + LanguageModule.loadTranslationsByLocale(locale, callback, counter); + } else { + callback('success', data, response); + } + } else { + callback('error', data, response); + } + }); + }; + + /** + * Load translations for all extensions by given rows + * + * @param {Object} rows + * @param {function} callback + */ + LanguageModule.loadTranslationsByRows = function(rows, callback) { + if (rows) { + rows = $(rows).toArray(); + var $row = $(rows.shift()), + locale = $row.data('locale'); + + LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) { + callback($row, status, data, response); + if (status === 'success') { + if (rows.length) { + LanguageModule.loadTranslationsByRows(rows, callback); + } else { + callback($row, 'finished', data, response); + } + } + }); + } + }; + + /** + * Load translation for one extension by given locale + * + * @param {String} extension + * @param {String} locale + * @param {function} callback + */ + LanguageModule.loadTranslationByExtensionAndLocale = function(extension, locale, callback) { + var data = {extension: extension, locale: locale}; + LanguageModule.executeAjaxRequest(LanguageModule.settings.updateTranslationUri, data, function(response, status) { + if (status === 'success' && response.success) { + callback('success', data, response); + } else { + callback('error', data, response); + } + }); + }; + + /** + * Execute AJAX request + * + * @param {String} uri + * @param {Object} data + * @param {function} callback + */ + LanguageModule.executeAjaxRequest = function(uri, data, callback) { + var newData = {}; + newData[LanguageModule.settings.prefix] = { + data: data + }; + LanguageModule.currentRequest = $.ajax({ + type: 'POST', + cache: false, + url: uri, + data: newData, + dataType: 'json', + success: function(response, status) { + if (typeof callback === 'function') { + callback(response, status, ''); + } + }, + error: function(response, status, error) { + if (typeof callback === 'function') { + callback(response, status, error); + } + } + }); + }; + + /** + * Abort current AJAX request + */ + LanguageModule.abortAjaxRequest = function() { + if (LanguageModule.currentRequest) { + LanguageModule.userAbortRequest = true; + LanguageModule.currentRequest.abort(); + } + }; + + /** + * Display error flash message + * + * @param {String} label + */ + LanguageModule.displayError = function(label) { + if (LanguageModule.userAbortRequest) { + LanguageModule.displaySuccess(LanguageModule.labels.canceled); + } else if (typeof label === 'string' && label !== '') { + Notification.error(LanguageModule.labels.errorHeader, label); + } + }; + + /** + * Display information flash message + * + * @param {String} label + */ + LanguageModule.displayInformation = function(label) { + if (typeof label === 'string' && label !== '') { + Notification.info(LanguageModule.labels.infoHeader, label); + } + }; + + /** + * Display success flash message + * + * @param {String} label + */ + LanguageModule.displaySuccess = function(label) { + if (typeof label === 'string' && label !== '') { + Notification.success(LanguageModule.labels.successHeader, label); + } + }; + + /** + * Build action link + * + * @param {String} action + * @param {Object} parameters + * @param {String} content + * @returns {Object} + */ + LanguageModule.buildActionLink = function(action, parameters, content) { + var $link = $('<a>'); + + $link.addClass(action + 'Link'); + $link.attr('data-action', action); + for (var name in parameters) { + if (parameters.hasOwnProperty(name)) { + $link.attr('data-' + name, parameters[name]); + } + } + $link.html(content); + return $link.wrap('<span>').parent().html(); + }; + + /** + * Build progress bar + * + * @returns {Object} + */ + LanguageModule.buildProgressBar = function() { + var $span = $('<span>'); + $span.addClass(LanguageModule.classes.progressBar); + $span.html(LanguageModule.icons.progressBar); + return $span.wrap('<span>').parent().html(); + }; + + /** + * Build loading indicator + * + * @returns {Object} + */ + LanguageModule.buildLoadingIndicator = function() { + var $span = $('<span>'); + $span.addClass(LanguageModule.classes.loading); + $span.html(LanguageModule.icons.loading); + return $span.wrap('<span>').parent().html(); + }; + + /** + * Build complete state indicator + * + * @returns {Object} + */ + LanguageModule.buildCompleteIndicator = function() { + var $span = $('<span>'); + $span.addClass(LanguageModule.classes.complete); + $span.html(LanguageModule.icons.complete); + return $span.wrap('<span>').parent().html(); + }; + + /** + * Build image + * + * @param {String} uri + * @param {String} alt + * @param {String} title + * @param {Number} width + * @param {Number} heigth + * @returns {Object} + */ + LanguageModule.buildImage = function(uri, alt, title, width, heigth) { + var $image = $('<img>'); + $image.attr('src', uri); + $image.attr('alt', alt ? alt : ''); + $image.attr('title', title ? title : ''); + $image.attr('style', 'width: ' + width + 'px; height: ' + heigth + 'px;'); + var $span = $('<span>'); + $span.addClass('typo3-app-icon'); + $span.attr('style', 'background: none; text-align: center;'); + $span.html($image); + return $span.wrap('<span>').parent().html(); + }; + + /** + * Format date + * + * @param {Number} timestamp + * @returns {*} + */ + LanguageModule.formatDate = function(timestamp) { + return moment.unix(timestamp).format(LanguageModule.labels.dateFormat); + }; + + /** + * Set progress bar progress + * + * @param {Object} progressBar + * @param {String} progress + */ + LanguageModule.setProgress = function(progressBar, progress) { + var $inner = $(LanguageModule.identifiers.progressBarInner, progressBar), + $text = $(LanguageModule.identifiers.progressBarText, progressBar); + $inner.css({width: progress + '%'}); + $inner.attr('aria-valuenow', progress); + $text.text(Math.round(progress) + '%'); + }; + + /** + * Utility method to retrieve query parameters + * + * @returns {Array} + */ + LanguageModule.getUrlVars = function getUrlVars() { + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + return vars; + }; + + $(function() { + if ($('#typo3-language-list').length) { + LanguageModule.initializeLanguageTable('div.typo3-module-lang', '#typo3-language-list'); + } else if ($('#typo3-translation-list').length) { + LanguageModule.initializeTranslationTable('div.typo3-module-lang', '#typo3-translation-list'); + } + }); + + return LanguageModule; }); diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js b/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js index 02dca0a6c8528c6aecfdccde3a78f6bc730b46e9..9f130f451c7eaf53316ff80f406561a68b7215a6 100644 --- a/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js +++ b/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js @@ -15,57 +15,57 @@ Ext.ns('TYPO3.l10n'); TYPO3.l10n = function() { - /** - * Protected copy of translationUnits - * @private - */ - var lang = [], + /** + * Protected copy of translationUnits + * @private + */ + var lang = [], - sanitize = function() { - if (typeof TYPO3.lang !== 'undefined') { - for (key in TYPO3.lang) { - lang[key] = TYPO3.lang[key]; + sanitize = function() { + if (typeof TYPO3.lang !== 'undefined') { + for (key in TYPO3.lang) { + lang[key] = TYPO3.lang[key]; - if (!Ext.isString(TYPO3.lang[key])) { - TYPO3.lang[key] = TYPO3.lang[key][0].target; - } - } - } - }; + if (!Ext.isString(TYPO3.lang[key])) { + TYPO3.lang[key] = TYPO3.lang[key][0].target; + } + } + } + }; - return { + return { - initialize: function() { - sanitize(); - }, + initialize: function() { + sanitize(); + }, - localize: function(label, replace, plural) { - if (typeof lang === 'undefined' || typeof lang[label] === 'undefined') { - return false; - } + localize: function(label, replace, plural) { + if (typeof lang === 'undefined' || typeof lang[label] === 'undefined') { + return false; + } - var i = plural || 0, - translationUnit = lang[label], - label = null, regexp = null; + var i = plural || 0, + translationUnit = lang[label], + label = null, regexp = null; - // Get localized label - if (Ext.isString(translationUnit)) { - label = translationUnit; - } else { - label = translationUnit[i]['target']; - } + // Get localized label + if (Ext.isString(translationUnit)) { + label = translationUnit; + } else { + label = translationUnit[i]['target']; + } - // Replace - if (typeof replace !== 'undefined') { - for (key in replace) { - regexp = new RegExp('%' + key + '|%s'); - label = label.replace(regexp, replace[key]); - } - } + // Replace + if (typeof replace !== 'undefined') { + for (key in replace) { + regexp = new RegExp('%' + key + '|%s'); + label = label.replace(regexp, replace[key]); + } + } - return label; - } - }; + return label; + } + }; }(); -TYPO3.l10n.initialize(); \ No newline at end of file +TYPO3.l10n.initialize(); diff --git a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js index b4578bbe7c81c9a0c446be71cf928fbda21a6301..c166b4f06ea0c16645388e5476db4c8d4acff7e3 100644 --- a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js +++ b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js @@ -15,58 +15,58 @@ * Module: TYPO3/CMS/Linkvalidator/Linkvalidator */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - /** - * - * @type {{}} - * @exports TYPO3/CMS/Linkvalidator/Linkvalidator - */ - var Linkvalidator = {}; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Linkvalidator/Linkvalidator + */ + var Linkvalidator = {}; - /** - * - * @param {String} prefix - */ - Linkvalidator.toggleActionButton = function(prefix) { - var buttonDisable = true; - $('.' + prefix).each(function() { - if ($(this).prop('checked')) { - buttonDisable = false; - } - }); + /** + * + * @param {String} prefix + */ + Linkvalidator.toggleActionButton = function(prefix) { + var buttonDisable = true; + $('.' + prefix).each(function() { + if ($(this).prop('checked')) { + buttonDisable = false; + } + }); - if (prefix === 'check') { - $('#updateLinkList').prop('disabled', buttonDisable); - } else { - $('#refreshLinkList').prop('disabled', buttonDisable); - } - }; + if (prefix === 'check') { + $('#updateLinkList').prop('disabled', buttonDisable); + } else { + $('#refreshLinkList').prop('disabled', buttonDisable); + } + }; - /** - * Registers listeners - */ - Linkvalidator.initializeEvents = function() { - $('.refresh').on('click', function() { - Linkvalidator.toggleActionButton('refresh'); - }); + /** + * Registers listeners + */ + Linkvalidator.initializeEvents = function() { + $('.refresh').on('click', function() { + Linkvalidator.toggleActionButton('refresh'); + }); - $('.check').on('click', function() { - Linkvalidator.toggleActionButton('check'); - }); + $('.check').on('click', function() { + Linkvalidator.toggleActionButton('check'); + }); - $('.t3js-update-button').on('click', function() { - var $element = $(this); - var name = $element.attr('name'); - var message = 'Event triggered'; - if (name === 'refreshLinkList' || name === 'updateLinkList') { - message = $element.data('notification-message'); - } - top.TYPO3.Notification.success(message); - }); - }; + $('.t3js-update-button').on('click', function() { + var $element = $(this); + var name = $element.attr('name'); + var message = 'Event triggered'; + if (name === 'refreshLinkList' || name === 'updateLinkList') { + message = $element.data('notification-message'); + } + top.TYPO3.Notification.success(message); + }); + }; - $(Linkvalidator.initializeEvents); + $(Linkvalidator.initializeEvents); - return Linkvalidator; + return Linkvalidator; }); diff --git a/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js b/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js index 1adb83b180bbc89bd93ed7710587566f2ff02c90..7123e823f48384dcabb4c0d6f88bc960dbb6f189 100644 --- a/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js +++ b/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js @@ -18,20 +18,20 @@ */ define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) { - var $searchFields = $('input[name="searchString"]'); - var searchResultShown = ('' !== $searchFields.first().val()); + var $searchFields = $('input[name="searchString"]'); + var searchResultShown = ('' !== $searchFields.first().val()); - // make search field clearable - $searchFields.clearable({ - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - }); - - if (self.location.hash) { - // scroll page down, so the just opened subtree is visible after reload and not hidden by doc header - $("html, body").scrollTop((document.documentElement.scrollTop || document.body.scrollTop) - 80); + // make search field clearable + $searchFields.clearable({ + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } } + }); + + if (self.location.hash) { + // scroll page down, so the just opened subtree is visible after reload and not hidden by doc header + $("html, body").scrollTop((document.documentElement.scrollTop || document.body.scrollTop) - 80); + } }); diff --git a/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js b/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js index 424a53fcfc964223a1d71c78dd79f9cccd4463fe..47a00da8362fdf7f0337718d45223b8a30730233 100644 --- a/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js +++ b/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js @@ -15,78 +15,78 @@ * Module: TYPO3/CMS/Lowlevel/QueryGenerator * This module handle the QueryGenerator forms. */ -define(['jquery', 'TYPO3/CMS/Backend/DateTimePicker', 'TYPO3/CMS/Backend/jquery.clearable'], function ($) { +define(['jquery', 'TYPO3/CMS/Backend/DateTimePicker', 'TYPO3/CMS/Backend/jquery.clearable'], function($) { - /** - * The QueryGenerator AMD module - * - * @type {{form: null, limitField: null}} - * @exports TYPO3/CMS/Lowlevel/QueryGenerator - */ - var QueryGenerator = { - form: null, - limitField: null - }; + /** + * The QueryGenerator AMD module + * + * @type {{form: null, limitField: null}} + * @exports TYPO3/CMS/Lowlevel/QueryGenerator + */ + var QueryGenerator = { + form: null, + limitField: null + }; - /** - * Initialize the QueryGenerator object - */ - QueryGenerator.initialize = function() { - QueryGenerator.form = $('form[name="queryform"]'); - QueryGenerator.limitField = $('#queryLimit'); - QueryGenerator.form.on('click', '.t3js-submit-click', function(e) { - e.preventDefault(); - QueryGenerator.doSubmit(); - }); - QueryGenerator.form.on('change', '.t3js-submit-change', function(e) { - e.preventDefault(); - QueryGenerator.doSubmit(); - }); - QueryGenerator.form.on('click', '.t3js-limit-submit button', function(e) { - e.preventDefault(); - QueryGenerator.setLimit($(this).data('value')); - QueryGenerator.doSubmit(); - }); - QueryGenerator.form.on('click', '.t3js-addfield', function(e) { - e.preventDefault(); - QueryGenerator.addValueToField($(this).data('field'), $(this).val()); - }); - QueryGenerator.form.find('.t3js-clearable').clearable({ - onClear: function() { - QueryGenerator.doSubmit(); - } - }); - }; + /** + * Initialize the QueryGenerator object + */ + QueryGenerator.initialize = function() { + QueryGenerator.form = $('form[name="queryform"]'); + QueryGenerator.limitField = $('#queryLimit'); + QueryGenerator.form.on('click', '.t3js-submit-click', function(e) { + e.preventDefault(); + QueryGenerator.doSubmit(); + }); + QueryGenerator.form.on('change', '.t3js-submit-change', function(e) { + e.preventDefault(); + QueryGenerator.doSubmit(); + }); + QueryGenerator.form.on('click', '.t3js-limit-submit button', function(e) { + e.preventDefault(); + QueryGenerator.setLimit($(this).data('value')); + QueryGenerator.doSubmit(); + }); + QueryGenerator.form.on('click', '.t3js-addfield', function(e) { + e.preventDefault(); + QueryGenerator.addValueToField($(this).data('field'), $(this).val()); + }); + QueryGenerator.form.find('.t3js-clearable').clearable({ + onClear: function() { + QueryGenerator.doSubmit(); + } + }); + }; - /** - * Submit the form - */ - QueryGenerator.doSubmit = function() { - QueryGenerator.form.submit(); - }; + /** + * Submit the form + */ + QueryGenerator.doSubmit = function() { + QueryGenerator.form.submit(); + }; - /** - * Set query limit - * - * @param {String} value - */ - QueryGenerator.setLimit = function(value) { - QueryGenerator.limitField.val(value); - }; + /** + * Set query limit + * + * @param {String} value + */ + QueryGenerator.setLimit = function(value) { + QueryGenerator.limitField.val(value); + }; - /** - * Add value to text field - * - * @param {String} field the name of the field - * @param {String} value the value to add - */ - QueryGenerator.addValueToField = function(field, value) { - var $target = QueryGenerator.form.find('[name="' + field + '"]'); - var currentValue = $target.val(); - $target.val(currentValue + ',' + value); - }; + /** + * Add value to text field + * + * @param {String} field the name of the field + * @param {String} value the value to add + */ + QueryGenerator.addValueToField = function(field, value) { + var $target = QueryGenerator.form.find('[name="' + field + '"]'); + var currentValue = $target.val(); + $target.val(currentValue + ',' + value); + }; - // Initialize - QueryGenerator.initialize(); - return QueryGenerator; + // Initialize + QueryGenerator.initialize(); + return QueryGenerator; }); diff --git a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js index a690a23bf46d82e4e42b67c760eea563a41a93c0..e294f55f64ba7c02d18f8b039c58d1e3d557527e 100644 --- a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js +++ b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js @@ -18,112 +18,112 @@ * - updating the menu */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Icons', - 'TYPO3/CMS/Backend/Viewport' + 'jquery', + 'TYPO3/CMS/Backend/Icons', + 'TYPO3/CMS/Backend/Viewport' ], function($, Icons, Viewport) { - 'use strict'; + 'use strict'; - /** - * - * @type {{options: {containerSelector: string, hashDataAttributeName: string, closeSelector: string, menuContainerSelector: string, toolbarIconSelector: string, openDocumentsItemsSelector: string, counterSelector: string}}} - * @exports TYPO3/CMS/Opendocs/OpendocsMenu - */ - var OpendocsMenu = { - options: { - containerSelector: '#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem', - hashDataAttributeName: 'opendocsidentifier', - closeSelector: '.t3js-topbar-opendocs-close', - menuContainerSelector: '.dropdown-menu', - toolbarIconSelector: '.toolbar-item-icon .t3js-icon', - openDocumentsItemsSelector: '.t3js-topbar-opendocs-item', - counterSelector: '#tx-opendocs-counter' - } - }; + /** + * + * @type {{options: {containerSelector: string, hashDataAttributeName: string, closeSelector: string, menuContainerSelector: string, toolbarIconSelector: string, openDocumentsItemsSelector: string, counterSelector: string}}} + * @exports TYPO3/CMS/Opendocs/OpendocsMenu + */ + var OpendocsMenu = { + options: { + containerSelector: '#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem', + hashDataAttributeName: 'opendocsidentifier', + closeSelector: '.t3js-topbar-opendocs-close', + menuContainerSelector: '.dropdown-menu', + toolbarIconSelector: '.toolbar-item-icon .t3js-icon', + openDocumentsItemsSelector: '.t3js-topbar-opendocs-item', + counterSelector: '#tx-opendocs-counter' + } + }; - /** - * register event handlers - */ - OpendocsMenu.initializeEvents = function() { - // send a request when removing an opendoc - $(OpendocsMenu.options.containerSelector).on('click', OpendocsMenu.options.closeSelector, function(evt) { - evt.preventDefault(); - var md5 = $(this).data(OpendocsMenu.options.hashDataAttributeName); - if (md5) { - OpendocsMenu.closeDocument(md5); - } - }); - }; + /** + * register event handlers + */ + OpendocsMenu.initializeEvents = function() { + // send a request when removing an opendoc + $(OpendocsMenu.options.containerSelector).on('click', OpendocsMenu.options.closeSelector, function(evt) { + evt.preventDefault(); + var md5 = $(this).data(OpendocsMenu.options.hashDataAttributeName); + if (md5) { + OpendocsMenu.closeDocument(md5); + } + }); + }; - /** - * Displays the menu and does the AJAX call to the TYPO3 backend - */ - OpendocsMenu.updateMenu = function() { - var $toolbarItemIcon = $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector), - $existingIcon = $toolbarItemIcon.clone(); + /** + * Displays the menu and does the AJAX call to the TYPO3 backend + */ + OpendocsMenu.updateMenu = function() { + var $toolbarItemIcon = $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector), + $existingIcon = $toolbarItemIcon.clone(); - Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { - $toolbarItemIcon.replaceWith(spinner); - }); + Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) { + $toolbarItemIcon.replaceWith(spinner); + }); - $.ajax({ - url: TYPO3.settings.ajaxUrls['opendocs_menu'], - type: 'post', - cache: false, - success: function(data) { - $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.menuContainerSelector).html(data); - OpendocsMenu.updateNumberOfDocs(); - $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector).replaceWith($existingIcon); - } - }); - }; + $.ajax({ + url: TYPO3.settings.ajaxUrls['opendocs_menu'], + type: 'post', + cache: false, + success: function(data) { + $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.menuContainerSelector).html(data); + OpendocsMenu.updateNumberOfDocs(); + $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector).replaceWith($existingIcon); + } + }); + }; - /** - * Updates the number of open documents in the toolbar according to the - * number of items in the menu bar. - */ - OpendocsMenu.updateNumberOfDocs = function() { - var num = $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.openDocumentsItemsSelector).length; - $(OpendocsMenu.options.counterSelector).text(num).toggle(num > 0); - }; + /** + * Updates the number of open documents in the toolbar according to the + * number of items in the menu bar. + */ + OpendocsMenu.updateNumberOfDocs = function() { + var num = $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.openDocumentsItemsSelector).length; + $(OpendocsMenu.options.counterSelector).text(num).toggle(num > 0); + }; - /** - * Closes an open document - * - * @param {String} md5sum - */ - OpendocsMenu.closeDocument = function(md5sum) { - $.ajax({ - url: TYPO3.settings.ajaxUrls['opendocs_closedoc'], - type: 'post', - cache: false, - data: { - md5sum: md5sum - }, - success: function(data) { - $(OpendocsMenu.options.menuContainerSelector, OpendocsMenu.options.containerSelector).html(data); - OpendocsMenu.updateNumberOfDocs(); - // Re-open the menu after closing a document - $(OpendocsMenu.options.containerSelector).toggleClass('open'); - } - }); - }; + /** + * Closes an open document + * + * @param {String} md5sum + */ + OpendocsMenu.closeDocument = function(md5sum) { + $.ajax({ + url: TYPO3.settings.ajaxUrls['opendocs_closedoc'], + type: 'post', + cache: false, + data: { + md5sum: md5sum + }, + success: function(data) { + $(OpendocsMenu.options.menuContainerSelector, OpendocsMenu.options.containerSelector).html(data); + OpendocsMenu.updateNumberOfDocs(); + // Re-open the menu after closing a document + $(OpendocsMenu.options.containerSelector).toggleClass('open'); + } + }); + }; - /** - * closes the menu (e.g. when clicked on an item) - */ - OpendocsMenu.toggleMenu = function() { - $('.scaffold').removeClass('scaffold-toolbar-expanded'); - $(OpendocsMenu.options.containerSelector).toggleClass('open'); - }; + /** + * closes the menu (e.g. when clicked on an item) + */ + OpendocsMenu.toggleMenu = function() { + $('.scaffold').removeClass('scaffold-toolbar-expanded'); + $(OpendocsMenu.options.containerSelector).toggleClass('open'); + }; - Viewport.Topbar.Toolbar.registerEvent(function() { - OpendocsMenu.initializeEvents(); - OpendocsMenu.updateMenu(); - }); + Viewport.Topbar.Toolbar.registerEvent(function() { + OpendocsMenu.initializeEvents(); + OpendocsMenu.updateMenu(); + }); - // expose to global - TYPO3.OpendocsMenu = OpendocsMenu; + // expose to global + TYPO3.OpendocsMenu = OpendocsMenu; - return OpendocsMenu; + return OpendocsMenu; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js index faf54e68f3b60efdccd5fa666831a1e767edf2ee..2ab2f5ebdc5ed89481d6f2abee5707dbfb953f27 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js @@ -17,30 +17,30 @@ * @exports TYPO3/CMS/Recordlist/BrowseDatabase */ define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser'], function($, ElementBrowser) { - 'use strict'; + 'use strict'; - $(function() { - $('[data-close]').on('click', function(event) { - event.preventDefault(); - var data = $(this).parents('span').data(); + $(function() { + $('[data-close]').on('click', function(event) { + event.preventDefault(); + var data = $(this).parents('span').data(); - ElementBrowser.insertElement( - data.table, - data.uid, - 'db', - data.title, - '', - '', - data.icon, - '', - $(this).data('close') - ); - }); + ElementBrowser.insertElement( + data.table, + data.uid, + 'db', + data.title, + '', + '', + data.icon, + '', + $(this).data('close') + ); + }); - // adjust searchbox layout - var searchbox = document.getElementById('db_list-searchbox-toolbar'); - searchbox.style.display = 'block'; - searchbox.style.position = 'relative'; - }); + // adjust searchbox layout + var searchbox = document.getElementById('db_list-searchbox-toolbar'); + searchbox.style.display = 'block'; + searchbox.style.position = 'relative'; + }); }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js index e3da67d73bbd2fe08f490b8b0a1c99f54e9543be..1c1df55b59ca8fb380a7cb3b2a06b821ce56caee 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js @@ -16,96 +16,96 @@ * File selection */ define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/LegacyTree'], function($, ElementBrowser, Tree) { - 'use strict'; + 'use strict'; - /** - * - * @type {{elements: {}}} - * @exports TYPO3/CMS/Recordlist/BrowseFiles - */ - var BrowseFiles = { - elements: {} - }; + /** + * + * @type {{elements: {}}} + * @exports TYPO3/CMS/Recordlist/BrowseFiles + */ + var BrowseFiles = { + elements: {} + }; - /** - * when selecting one or multiple files, this action is called - * - * @type {{insertElement: Function, insertElementMultiple: Function}} - */ - BrowseFiles.File = { - insertElement: function(index, close) { - var result = false; - if (typeof BrowseFiles.elements[index] !== 'undefined') { - var element = BrowseFiles.elements[index]; - result = ElementBrowser.insertElement(element.table, element.uid, element.type, element.fileName, element.filePath, element.fileExt, element.fileIcon, '', close); - } - return result; - }, - insertElementMultiple: function(list) { - var uidList = []; - for (var i = 0, n = list.length; i < n; i++) { - if (typeof BrowseFiles.elements[list[i]] !== 'undefined') { - var element = BrowseFiles.elements[list[i]]; - uidList.push(element.uid); - } - } - ElementBrowser.insertMultiple('sys_file', uidList); - } - }; + /** + * when selecting one or multiple files, this action is called + * + * @type {{insertElement: Function, insertElementMultiple: Function}} + */ + BrowseFiles.File = { + insertElement: function(index, close) { + var result = false; + if (typeof BrowseFiles.elements[index] !== 'undefined') { + var element = BrowseFiles.elements[index]; + result = ElementBrowser.insertElement(element.table, element.uid, element.type, element.fileName, element.filePath, element.fileExt, element.fileIcon, '', close); + } + return result; + }, + insertElementMultiple: function(list) { + var uidList = []; + for (var i = 0, n = list.length; i < n; i++) { + if (typeof BrowseFiles.elements[list[i]] !== 'undefined') { + var element = BrowseFiles.elements[list[i]]; + uidList.push(element.uid); + } + } + ElementBrowser.insertMultiple('sys_file', uidList); + } + }; - /** - * Selector when using "Import selection" and "Toggle selection" - */ - BrowseFiles.Selector = { - // Toggle selection button is pressed - toggle: function(e) { - e.preventDefault(); - var items = BrowseFiles.Selector.getItems(); - if (items.length) { - items.each(function(position, item) { - item.checked = (item.checked ? null : 'checked'); - }); - } - }, - // Import selection button is pressed - handle: function(e) { - e.preventDefault(); - var items = BrowseFiles.Selector.getItems(); - var selectedItems = []; - if (items.length) { - items.each(function(position, item) { - if (item.checked && item.name) { - selectedItems.push(item.name); - } - }); - if (selectedItems.length > 0) { - if (ElementBrowser.hasActionMultipleCode) { - BrowseFiles.File.insertElementMultiple(selectedItems); - } else { - for (var i = 0; i < selectedItems.length; i++) { - BrowseFiles.File.insertElement(selectedItems[i]); - } - } - } - ElementBrowser.focusOpenerAndClose(true); - } - }, - getItems: function() { - return $('#typo3-filelist').find('.typo3-bulk-item'); - } - }; + /** + * Selector when using "Import selection" and "Toggle selection" + */ + BrowseFiles.Selector = { + // Toggle selection button is pressed + toggle: function(e) { + e.preventDefault(); + var items = BrowseFiles.Selector.getItems(); + if (items.length) { + items.each(function(position, item) { + item.checked = (item.checked ? null : 'checked'); + }); + } + }, + // Import selection button is pressed + handle: function(e) { + e.preventDefault(); + var items = BrowseFiles.Selector.getItems(); + var selectedItems = []; + if (items.length) { + items.each(function(position, item) { + if (item.checked && item.name) { + selectedItems.push(item.name); + } + }); + if (selectedItems.length > 0) { + if (ElementBrowser.hasActionMultipleCode) { + BrowseFiles.File.insertElementMultiple(selectedItems); + } else { + for (var i = 0; i < selectedItems.length; i++) { + BrowseFiles.File.insertElement(selectedItems[i]); + } + } + } + ElementBrowser.focusOpenerAndClose(true); + } + }, + getItems: function() { + return $('#typo3-filelist').find('.typo3-bulk-item'); + } + }; - $(function() { - $.extend(BrowseFiles.elements, $('body').data('elements')); + $(function() { + $.extend(BrowseFiles.elements, $('body').data('elements')); - $('[data-close]').on('click', function (e) { - e.preventDefault(); - BrowseFiles.File.insertElement('file_' + $(this).data('fileIndex'), $(this).data('close')); - }); + $('[data-close]').on('click', function(e) { + e.preventDefault(); + BrowseFiles.File.insertElement('file_' + $(this).data('fileIndex'), $(this).data('close')); + }); - $('#t3js-importSelection').on('click', BrowseFiles.Selector.handle); - $('#t3js-toggleSelection').on('click', BrowseFiles.Selector.toggle); - }); + $('#t3js-importSelection').on('click', BrowseFiles.Selector.handle); + $('#t3js-toggleSelection').on('click', BrowseFiles.Selector.toggle); + }); - return BrowseFiles; + return BrowseFiles; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js index e149e294ec882f9d76720b007bb9708a18131916..1b73340a7b4ae2baefd36a2740240b354339e691 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js @@ -16,21 +16,21 @@ * Folder selection * @exports TYPO3/CMS/Recordlist/BrowseFolders */ -define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, ElementBrowser, Modal, Severity) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, ElementBrowser, Modal, Severity) { + 'use strict'; - $(function() { - $('[data-folder-id]').on('click', function (event) { - event.preventDefault(); - var folderId = $(this).data('folderId'); - var close = $(this).data('close'); - ElementBrowser.insertElement('', folderId, 'folder', folderId, folderId, '', '', '', close); - }); + $(function() { + $('[data-folder-id]').on('click', function(event) { + event.preventDefault(); + var folderId = $(this).data('folderId'); + var close = $(this).data('close'); + ElementBrowser.insertElement('', folderId, 'folder', folderId, folderId, '', '', '', close); + }); - $('.t3js-folderIdError').on('click', function (event) { - event.preventDefault(); - Modal.confirm('', $(this).data('message'), Severity.error, [], []); - }); - }); + $('.t3js-folderIdError').on('click', function(event) { + event.preventDefault(); + Modal.confirm('', $(this).data('message'), Severity.error, [], []); + }); + }); }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js index 114f4c8f5976c38b1fda5ec2d92abbaec8a09d89..2f4cd6c2a65cf1f61a67a07553a318043b75a911 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js @@ -16,263 +16,263 @@ * ElementBrowser communication with parent windows */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Modal' + 'jquery', + 'TYPO3/CMS/Backend/Modal' ], function($, Modal) { - 'use strict'; + 'use strict'; - /** - * - * @type {{thisScriptUrl: string, mode: string, formFieldName: string, hasActionMultipleCode: boolean, fieldReference: string, fieldReferenceSlashed: string, rte: {parameters: string, configuration: string}, irre: {objectId: number, checkUniqueAction: string, addAction: string, insertAction: string}}} - * @exports TYPO3/CMS/Recordlist/ElementBrowser - */ - var ElementBrowser = { - thisScriptUrl: '', - mode: '', - formFieldName: '', - hasActionMultipleCode: false, - fieldReference: '', - fieldReferenceSlashed: '', - rte: { - parameters: '', - configuration: '' - }, - irre: { - objectId: 0, - checkUniqueAction: '', - addAction: '', - insertAction: '' - } - }; + /** + * + * @type {{thisScriptUrl: string, mode: string, formFieldName: string, hasActionMultipleCode: boolean, fieldReference: string, fieldReferenceSlashed: string, rte: {parameters: string, configuration: string}, irre: {objectId: number, checkUniqueAction: string, addAction: string, insertAction: string}}} + * @exports TYPO3/CMS/Recordlist/ElementBrowser + */ + var ElementBrowser = { + thisScriptUrl: '', + mode: '', + formFieldName: '', + hasActionMultipleCode: false, + fieldReference: '', + fieldReferenceSlashed: '', + rte: { + parameters: '', + configuration: '' + }, + irre: { + objectId: 0, + checkUniqueAction: '', + addAction: '', + insertAction: '' + } + }; - /** - * - * @returns {Boolean} - */ - ElementBrowser.setReferences = function() { - if ( - ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform - && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName] - ) { - ElementBrowser.targetDoc = ElementBrowser.getParent().content.document; - ElementBrowser.elRef = ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName]; - return true; - } else { - return false; - } - }; + /** + * + * @returns {Boolean} + */ + ElementBrowser.setReferences = function() { + if ( + ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform + && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName] + ) { + ElementBrowser.targetDoc = ElementBrowser.getParent().content.document; + ElementBrowser.elRef = ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName]; + return true; + } else { + return false; + } + }; - /** - * Dynamically calls a function on a given context object. - * - * @param {String} functionName e.g. "inline.somefunc" - * @param {Object} context e.g. window - * @returns {*} - */ - ElementBrowser.executeFunctionByName = function(functionName, context /*, args */) { - var args = Array.prototype.slice.call(arguments, 2); - var namespaces = functionName.split("."); - var func = namespaces.pop(); - for (var i = 0; i < namespaces.length; i++) { - context = context[namespaces[i]]; - } - return context[func].apply(context, args); - }; + /** + * Dynamically calls a function on a given context object. + * + * @param {String} functionName e.g. "inline.somefunc" + * @param {Object} context e.g. window + * @returns {*} + */ + ElementBrowser.executeFunctionByName = function(functionName, context /*, args */) { + var args = Array.prototype.slice.call(arguments, 2); + var namespaces = functionName.split("."); + var func = namespaces.pop(); + for (var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + return context[func].apply(context, args); + }; - /** - * Returns the parent document object - */ - ElementBrowser.getParent = function() { - var opener = null; - if ( - typeof window.parent !== 'undefined' && - typeof window.parent.document.list_frame !== 'undefined' && - window.parent.document.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null - ) { - opener = window.parent.document.list_frame; - } else if ( - typeof window.parent !== 'undefined' && - typeof window.parent.frames.list_frame !== 'undefined' && - window.parent.frames.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null - ) { - opener = window.parent.frames.list_frame; - } else if ( - typeof window.frames !== 'undefined' && - typeof window.frames.frameElement !== 'undefined' && - window.frames.frameElement !== null && - window.frames.frameElement.classList.contains('t3js-modal-iframe') - ) { - opener = window.frames.frameElement.contentWindow.parent; - } else if (window.opener) { - opener = window.opener; - } - return opener; - }; + /** + * Returns the parent document object + */ + ElementBrowser.getParent = function() { + var opener = null; + if ( + typeof window.parent !== 'undefined' && + typeof window.parent.document.list_frame !== 'undefined' && + window.parent.document.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null + ) { + opener = window.parent.document.list_frame; + } else if ( + typeof window.parent !== 'undefined' && + typeof window.parent.frames.list_frame !== 'undefined' && + window.parent.frames.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null + ) { + opener = window.parent.frames.list_frame; + } else if ( + typeof window.frames !== 'undefined' && + typeof window.frames.frameElement !== 'undefined' && + window.frames.frameElement !== null && + window.frames.frameElement.classList.contains('t3js-modal-iframe') + ) { + opener = window.frames.frameElement.contentWindow.parent; + } else if (window.opener) { + opener = window.opener; + } + return opener; + }; - /** - * - * @param {String} table - * @param {Number} uid - * @param {String} type - * @param {String} filename - * @param {String} fp - * @param {String} filetype - * @param {String} imagefile - * @param {String} action - * @param {String} close - * @returns {Boolean} - */ - ElementBrowser.insertElement = function(table, uid, type, filename, fp, filetype, imagefile, action, close) { - var performAction = true; + /** + * + * @param {String} table + * @param {Number} uid + * @param {String} type + * @param {String} filename + * @param {String} fp + * @param {String} filetype + * @param {String} imagefile + * @param {String} action + * @param {String} close + * @returns {Boolean} + */ + ElementBrowser.insertElement = function(table, uid, type, filename, fp, filetype, imagefile, action, close) { + var performAction = true; - // Call a check function in the opener window (e.g. for uniqueness handling): - if (ElementBrowser.irre.objectId && ElementBrowser.irre.checkUniqueAction) { - if (ElementBrowser.getParent()) { - var res = ElementBrowser.executeFunctionByName(ElementBrowser.irre.checkUniqueAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type); - if (!res.passed) { - if (res.message) { - alert(res.message); - } - performAction = false; - } - } else { - alert("Error - reference to main window is not set properly!"); - ElementBrowser.focusOpenerAndClose(); - } - } - // Call performing function and finish this action: - if (performAction) { - // Call helper function to manage data in the opener window: - if (ElementBrowser.irre.objectId && ElementBrowser.irre.addAction) { - if (ElementBrowser.getParent()) { - ElementBrowser.executeFunctionByName(ElementBrowser.irre.addAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type, ElementBrowser.fieldReferenceSlashed); - } else { - alert("Error - reference to main window is not set properly!"); - ElementBrowser.focusOpenerAndClose(); - } - } - if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) { - if (ElementBrowser.getParent()) { - ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type); - if (close) { - ElementBrowser.focusOpenerAndClose(); - } - } else { - alert("Error - reference to main window is not set properly!"); - if (close) { - ElementBrowser.focusOpenerAndClose(); - } - } - } else if (ElementBrowser.fieldReference && !ElementBrowser.rte.parameters && !ElementBrowser.rte.configuration) { - ElementBrowser.addElement(filename, table + "_" + uid, fp, close); - } else { - if ( - ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform - && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName] - ) { - ElementBrowser.getParent().group_change( - "add", - ElementBrowser.fieldReference, - ElementBrowser.rte.parameters, - ElementBrowser.rte.configuration, - ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName], - ElementBrowser.getParent().content.document - ); - } else { - alert("Error - reference to main window is not set properly!"); - } - if (close) { - ElementBrowser.focusOpenerAndClose(); - } - } - } - return false; - }; + // Call a check function in the opener window (e.g. for uniqueness handling): + if (ElementBrowser.irre.objectId && ElementBrowser.irre.checkUniqueAction) { + if (ElementBrowser.getParent()) { + var res = ElementBrowser.executeFunctionByName(ElementBrowser.irre.checkUniqueAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type); + if (!res.passed) { + if (res.message) { + alert(res.message); + } + performAction = false; + } + } else { + alert("Error - reference to main window is not set properly!"); + ElementBrowser.focusOpenerAndClose(); + } + } + // Call performing function and finish this action: + if (performAction) { + // Call helper function to manage data in the opener window: + if (ElementBrowser.irre.objectId && ElementBrowser.irre.addAction) { + if (ElementBrowser.getParent()) { + ElementBrowser.executeFunctionByName(ElementBrowser.irre.addAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type, ElementBrowser.fieldReferenceSlashed); + } else { + alert("Error - reference to main window is not set properly!"); + ElementBrowser.focusOpenerAndClose(); + } + } + if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) { + if (ElementBrowser.getParent()) { + ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type); + if (close) { + ElementBrowser.focusOpenerAndClose(); + } + } else { + alert("Error - reference to main window is not set properly!"); + if (close) { + ElementBrowser.focusOpenerAndClose(); + } + } + } else if (ElementBrowser.fieldReference && !ElementBrowser.rte.parameters && !ElementBrowser.rte.configuration) { + ElementBrowser.addElement(filename, table + "_" + uid, fp, close); + } else { + if ( + ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform + && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName] + ) { + ElementBrowser.getParent().group_change( + "add", + ElementBrowser.fieldReference, + ElementBrowser.rte.parameters, + ElementBrowser.rte.configuration, + ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName], + ElementBrowser.getParent().content.document + ); + } else { + alert("Error - reference to main window is not set properly!"); + } + if (close) { + ElementBrowser.focusOpenerAndClose(); + } + } + } + return false; + }; - /** - * - * @param {String} table - * @param {Number} uid - * @returns {Boolean} - */ - ElementBrowser.insertMultiple = function(table, uid) { - var type = ""; - if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) { - // Call helper function to manage data in the opener window: - if (ElementBrowser.getParent()) { - ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction + 'Multiple', ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type, ElementBrowser.fieldReference); - } else { - alert("Error - reference to main window is not set properly!"); - ElementBrowser.focusOpenerAndClose(); - } - } - return false; - }; + /** + * + * @param {String} table + * @param {Number} uid + * @returns {Boolean} + */ + ElementBrowser.insertMultiple = function(table, uid) { + var type = ""; + if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) { + // Call helper function to manage data in the opener window: + if (ElementBrowser.getParent()) { + ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction + 'Multiple', ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type, ElementBrowser.fieldReference); + } else { + alert("Error - reference to main window is not set properly!"); + ElementBrowser.focusOpenerAndClose(); + } + } + return false; + }; - /** - * - * @param {String} elName - * @param {String} elValue - * @param {String} altElValue - * @param {String} close - */ - ElementBrowser.addElement = function(elName, elValue, altElValue, close) { - if (ElementBrowser.getParent() && ElementBrowser.getParent().setFormValueFromBrowseWin) { - ElementBrowser.getParent().setFormValueFromBrowseWin(ElementBrowser.fieldReference, altElValue ? altElValue : elValue, elName); - if (close) { - ElementBrowser.focusOpenerAndClose(); - } - } else { - alert("Error - reference to main window is not set properly!"); - ElementBrowser.focusOpenerAndClose(); - } - }; + /** + * + * @param {String} elName + * @param {String} elValue + * @param {String} altElValue + * @param {String} close + */ + ElementBrowser.addElement = function(elName, elValue, altElValue, close) { + if (ElementBrowser.getParent() && ElementBrowser.getParent().setFormValueFromBrowseWin) { + ElementBrowser.getParent().setFormValueFromBrowseWin(ElementBrowser.fieldReference, altElValue ? altElValue : elValue, elName); + if (close) { + ElementBrowser.focusOpenerAndClose(); + } + } else { + alert("Error - reference to main window is not set properly!"); + ElementBrowser.focusOpenerAndClose(); + } + }; - /** - * - */ - ElementBrowser.focusOpenerAndClose = function() { - if (ElementBrowser.getParent()) { - ElementBrowser.getParent().focus(); - } - Modal.dismiss(); - close(); - }; + /** + * + */ + ElementBrowser.focusOpenerAndClose = function() { + if (ElementBrowser.getParent()) { + ElementBrowser.getParent().focus(); + } + Modal.dismiss(); + close(); + }; - $(function() { - var data = $('body').data(); + $(function() { + var data = $('body').data(); - ElementBrowser.thisScriptUrl = data.thisScriptUrl; - ElementBrowser.mode = data.mode; - ElementBrowser.formFieldName = data.formFieldName; - ElementBrowser.fieldReference = data.fieldReference; - ElementBrowser.fieldReferenceSlashed = data.fieldReferenceSlashed; - ElementBrowser.rte.parameters = data.rteParameters; - ElementBrowser.rte.configuration = data.rteConfiguration; - ElementBrowser.irre.checkUniqueAction = data.irreCheckUniqueAction; - ElementBrowser.irre.addAction = data.irreAddAction; - ElementBrowser.irre.insertAction = data.irreInsertAction; - ElementBrowser.irre.objectId = data.irreObjectId; - ElementBrowser.hasActionMultipleCode = ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction; - }); + ElementBrowser.thisScriptUrl = data.thisScriptUrl; + ElementBrowser.mode = data.mode; + ElementBrowser.formFieldName = data.formFieldName; + ElementBrowser.fieldReference = data.fieldReference; + ElementBrowser.fieldReferenceSlashed = data.fieldReferenceSlashed; + ElementBrowser.rte.parameters = data.rteParameters; + ElementBrowser.rte.configuration = data.rteConfiguration; + ElementBrowser.irre.checkUniqueAction = data.irreCheckUniqueAction; + ElementBrowser.irre.addAction = data.irreAddAction; + ElementBrowser.irre.insertAction = data.irreInsertAction; + ElementBrowser.irre.objectId = data.irreObjectId; + ElementBrowser.hasActionMultipleCode = ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction; + }); - /** - * Global jumpTo function - * - * Used by tree implementation - * - * @param {String} URL - * @param {String} anchor - * @returns {Boolean} - */ - window.jumpToUrl = function(URL, anchor) { - if (URL.charAt(0) === '?') { - URL = ElementBrowser.thisScriptUrl + URL.substring(1); - } - var add_mode = URL.indexOf("mode=") === -1 ? '&mode=' + encodeURIComponent(ElementBrowser.mode) : ""; - window.location.href = URL + add_mode + (typeof(anchor) === "string" ? anchor : ''); - return false; - }; + /** + * Global jumpTo function + * + * Used by tree implementation + * + * @param {String} URL + * @param {String} anchor + * @returns {Boolean} + */ + window.jumpToUrl = function(URL, anchor) { + if (URL.charAt(0) === '?') { + URL = ElementBrowser.thisScriptUrl + URL.substring(1); + } + var add_mode = URL.indexOf("mode=") === -1 ? '&mode=' + encodeURIComponent(ElementBrowser.mode) : ""; + window.location.href = URL + add_mode + (typeof(anchor) === "string" ? anchor : ''); + return false; + }; - return ElementBrowser; + return ElementBrowser; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js index fef5bf6a6c083a0524753cb985faea1f59fc3823..3d2b2b96c2a659d1b37845fb4d182dbb7d802c8f 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js @@ -17,18 +17,18 @@ * @exports TYPO3/CMS/Recordlist/FieldSelectBox */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - $(function() { - $('.fieldSelectBox .checkAll').change(function() { - var checked = $(this).prop('checked'); - var $checkboxes = $('.fieldSelectBox tbody').find(':checkbox'); - $checkboxes.each(function() { - if (!$(this).prop('disabled')) { - $(this).prop('checked', checked); - } - }); - }); - }); + $(function() { + $('.fieldSelectBox .checkAll').change(function() { + var checked = $(this).prop('checked'); + var $checkboxes = $('.fieldSelectBox tbody').find(':checkbox'); + $checkboxes.each(function() { + if (!$(this).prop('disabled')) { + $(this).prop('checked', checked); + } + }); + }); + }); }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js index ae444a70e38148465f949d2dfc629d61fdae1de2..3a64c0645f87e8d0c5e25998466cbc5177a2bb59 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js @@ -16,40 +16,40 @@ * File link interaction */ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/LegacyTree'], function($, LinkBrowser, Tree) { - 'use strict'; + 'use strict'; - /** - * - * @type {{currentLink: string}} - * @exports TYPO3/CMS/Recordlist/FileLinkHandler - */ - var FileLinkHandler = { - currentLink: '' - }; + /** + * + * @type {{currentLink: string}} + * @exports TYPO3/CMS/Recordlist/FileLinkHandler + */ + var FileLinkHandler = { + currentLink: '' + }; - /** - * - * @param {Event} event - */ - FileLinkHandler.linkFile = function(event) { - event.preventDefault(); - LinkBrowser.finalizeFunction($(this).attr('href')); - }; + /** + * + * @param {Event} event + */ + FileLinkHandler.linkFile = function(event) { + event.preventDefault(); + LinkBrowser.finalizeFunction($(this).attr('href')); + }; - /** - * - * @param {Event} event - */ - FileLinkHandler.linkCurrent = function(event) { - event.preventDefault(); - LinkBrowser.finalizeFunction(FileLinkHandler.currentLink); - }; + /** + * + * @param {Event} event + */ + FileLinkHandler.linkCurrent = function(event) { + event.preventDefault(); + LinkBrowser.finalizeFunction(FileLinkHandler.currentLink); + }; - $(function() { - FileLinkHandler.currentLink = $('body').data('currentLink'); - $('a.t3js-fileLink').on('click', FileLinkHandler.linkFile); - $('input.t3js-linkCurrent').on('click', FileLinkHandler.linkCurrent); - }); + $(function() { + FileLinkHandler.currentLink = $('body').data('currentLink'); + $('a.t3js-fileLink').on('click', FileLinkHandler.linkFile); + $('input.t3js-linkCurrent').on('click', FileLinkHandler.linkCurrent); + }); - return FileLinkHandler; + return FileLinkHandler; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js index 93e1f6adddc71a1a7b78142298ea54a173be6776..a75b9c113f157e8b70f3bd993b6c07dfc39f2876 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js @@ -16,128 +16,130 @@ * LinkBrowser communication with parent window */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - /** - * - * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, additionalLinkAttributes: {}, finalizeFunction: null}} - * @exports TYPO3/CMS/Recordlist/LinkBrowser - */ - var LinkBrowser = { - thisScriptUrl: '', - urlParameters: {}, - parameters: {}, - addOnParams: '', - linkAttributeFields: [], - additionalLinkAttributes: {}, - finalizeFunction: null - }; + /** + * + * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, additionalLinkAttributes: {}, finalizeFunction: null}} + * @exports TYPO3/CMS/Recordlist/LinkBrowser + */ + var LinkBrowser = { + thisScriptUrl: '', + urlParameters: {}, + parameters: {}, + addOnParams: '', + linkAttributeFields: [], + additionalLinkAttributes: {}, + finalizeFunction: null + }; - /** - * Collect the link attributes values as object - * - * @returns {Object} - */ - LinkBrowser.getLinkAttributeValues = function() { - var attributeValues = {}; - $.each(LinkBrowser.linkAttributeFields, function(index, fieldName) { - var val = $('[name="l' + fieldName + '"]').val(); - if (val) { - attributeValues[fieldName] = val; - } - }); - $.extend(attributeValues, LinkBrowser.additionalLinkAttributes); - return attributeValues; - }; + /** + * Collect the link attributes values as object + * + * @returns {Object} + */ + LinkBrowser.getLinkAttributeValues = function() { + var attributeValues = {}; + $.each(LinkBrowser.linkAttributeFields, function(index, fieldName) { + var val = $('[name="l' + fieldName + '"]').val(); + if (val) { + attributeValues[fieldName] = val; + } + }); + $.extend(attributeValues, LinkBrowser.additionalLinkAttributes); + return attributeValues; + }; - /** - * - */ - LinkBrowser.loadTarget = function() { - $('.t3js-linkTarget').val($(this).val()); - this.selectedIndex = 0; - }; + /** + * + */ + LinkBrowser.loadTarget = function() { + $('.t3js-linkTarget').val($(this).val()); + this.selectedIndex = 0; + }; - /** - * Encode objects to GET parameter arrays in PHP notation - * - * @param {Object} obj - * @param {String} prefix - * @param {String} url - * @returns {String} - */ - LinkBrowser.encodeGetParameters = function(obj, prefix, url) { - var str = []; - for(var p in obj) { - if (obj.hasOwnProperty(p)) { - var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; - if (url.indexOf(k + "=") === -1) { - str.push( - typeof v === "object" - ? LinkBrowser.encodeGetParameters(v, k, url) - : encodeURIComponent(k) + "=" + encodeURIComponent(v) - ); - } - } - } - return '&' + str.join("&"); - }; + /** + * Encode objects to GET parameter arrays in PHP notation + * + * @param {Object} obj + * @param {String} prefix + * @param {String} url + * @returns {String} + */ + LinkBrowser.encodeGetParameters = function(obj, prefix, url) { + var str = []; + for (var p in obj) { + if (obj.hasOwnProperty(p)) { + var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p]; + if (url.indexOf(k + "=") === -1) { + str.push( + typeof v === "object" + ? LinkBrowser.encodeGetParameters(v, k, url) + : encodeURIComponent(k) + "=" + encodeURIComponent(v) + ); + } + } + } + return '&' + str.join("&"); + }; - /** - * Set an additional attribute for the link - * - * @param {String} name - * @param value - */ - LinkBrowser.setAdditionalLinkAttribute = function(name, value) { - LinkBrowser.additionalLinkAttributes[name] = value; - }; + /** + * Set an additional attribute for the link + * + * @param {String} name + * @param value + */ + LinkBrowser.setAdditionalLinkAttribute = function(name, value) { + LinkBrowser.additionalLinkAttributes[name] = value; + }; - /** - * Stores the final link - * - * This method MUST be overridden in the actual implementation of the link browser. - * The function is responsible for encoding the link (and possible link attributes) and - * returning it to the caller (e.g. FormEngine, RTE, etc) - * - * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>") - */ - LinkBrowser.finalizeFunction = function(link) { - throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.'; - }; + /** + * Stores the final link + * + * This method MUST be overridden in the actual implementation of the link browser. + * The function is responsible for encoding the link (and possible link attributes) and + * returning it to the caller (e.g. FormEngine, RTE, etc) + * + * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>") + */ + LinkBrowser.finalizeFunction = function(link) { + throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.'; + }; - $(function() { - var data = $('body').data(); + $(function() { + var data = $('body').data(); - LinkBrowser.thisScriptUrl = data.thisScriptUrl; - LinkBrowser.urlParameters = data.urlParameters; - LinkBrowser.parameters = data.parameters; - LinkBrowser.addOnParams = data.addOnParams; - LinkBrowser.linkAttributeFields = data.linkAttributeFields; + LinkBrowser.thisScriptUrl = data.thisScriptUrl; + LinkBrowser.urlParameters = data.urlParameters; + LinkBrowser.parameters = data.parameters; + LinkBrowser.addOnParams = data.addOnParams; + LinkBrowser.linkAttributeFields = data.linkAttributeFields; - $('.t3js-targetPreselect').on('change', LinkBrowser.loadTarget); - $('form.t3js-dummyform').on('submit', function(evt) { evt.preventDefault(); }); - }); + $('.t3js-targetPreselect').on('change', LinkBrowser.loadTarget); + $('form.t3js-dummyform').on('submit', function(evt) { + evt.preventDefault(); + }); + }); - /** - * Global jumpTo function - * - * Used by tree implementation - * - * @param {String} URL - * @param {String} anchor - * @returns {Boolean} - */ - window.jumpToUrl = function(URL, anchor) { - if (URL.charAt(0) === '?') { - URL = LinkBrowser.thisScriptUrl + URL.substring(1); - } - var urlParameters = LinkBrowser.encodeGetParameters(LinkBrowser.urlParameters, '', URL); - var parameters = LinkBrowser.encodeGetParameters(LinkBrowser.getLinkAttributeValues(), 'linkAttributes', ''); + /** + * Global jumpTo function + * + * Used by tree implementation + * + * @param {String} URL + * @param {String} anchor + * @returns {Boolean} + */ + window.jumpToUrl = function(URL, anchor) { + if (URL.charAt(0) === '?') { + URL = LinkBrowser.thisScriptUrl + URL.substring(1); + } + var urlParameters = LinkBrowser.encodeGetParameters(LinkBrowser.urlParameters, '', URL); + var parameters = LinkBrowser.encodeGetParameters(LinkBrowser.getLinkAttributeValues(), 'linkAttributes', ''); - window.location.href = URL + urlParameters + parameters + LinkBrowser.addOnParams + (typeof(anchor) === "string" ? anchor : ''); - return false; - }; + window.location.href = URL + urlParameters + parameters + LinkBrowser.addOnParams + (typeof(anchor) === "string" ? anchor : ''); + return false; + }; - return LinkBrowser; + return LinkBrowser; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js index f4d733d1bdaded323d69999ecd9076791f560d11..8dfff9377c3ed36bcaf7f738362a7369d443b9e4 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js @@ -16,31 +16,31 @@ * Mail link interaction */ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) { - 'use strict'; + 'use strict'; - /** - * - * @type {{}} - * @exports TYPO3/CMS/Recordlist/MailLinkHandler - */ - var MailLinkHandler = {}; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Recordlist/MailLinkHandler + */ + var MailLinkHandler = {}; - $(function() { - $('#lmailform').on('submit', function(event) { - event.preventDefault(); + $(function() { + $('#lmailform').on('submit', function(event) { + event.preventDefault(); - var value = $(this).find('[name="lemail"]').val(); - if (value === 'mailto:') { - return; - } + var value = $(this).find('[name="lemail"]').val(); + if (value === 'mailto:') { + return; + } - while (value.substr(0, 7) === 'mailto:') { - value = value.substr(7); - } + while (value.substr(0, 7) === 'mailto:') { + value = value.substr(7); + } - LinkBrowser.finalizeFunction('mailto:' + value); - }); - }); + LinkBrowser.finalizeFunction('mailto:' + value); + }); + }); - return MailLinkHandler; + return MailLinkHandler; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js index 6e07cb056c2f2a93e3f0995b9b635d4d93ca3df5..f7488ccfde89698aeef795d11d0cc5dc836e9caa 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js @@ -16,57 +16,57 @@ * Page link interaction */ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) { - 'use strict'; + 'use strict'; - /** - * - * @type {{currentLink: string}} - * @exports TYPO3/CMS/Recordlist/PageLinkHandler - */ - var PageLinkHandler = { - currentLink: '' - }; + /** + * + * @type {{currentLink: string}} + * @exports TYPO3/CMS/Recordlist/PageLinkHandler + */ + var PageLinkHandler = { + currentLink: '' + }; - /** - * - * @param {Event} event - */ - PageLinkHandler.linkPage = function(event) { - event.preventDefault(); - LinkBrowser.finalizeFunction($(this).attr('href')); - }; + /** + * + * @param {Event} event + */ + PageLinkHandler.linkPage = function(event) { + event.preventDefault(); + LinkBrowser.finalizeFunction($(this).attr('href')); + }; - /** - * - * @param {Event} event - */ - PageLinkHandler.linkPageByTextfield = function(event) { - event.preventDefault(); + /** + * + * @param {Event} event + */ + PageLinkHandler.linkPageByTextfield = function(event) { + event.preventDefault(); - var value = $('#luid').val(); - if (!value) { - return; - } + var value = $('#luid').val(); + if (!value) { + return; + } - LinkBrowser.finalizeFunction(value); - }; + LinkBrowser.finalizeFunction(value); + }; - /** - * - * @param {Event} event - */ - PageLinkHandler.linkCurrent = function(event) { - event.preventDefault(); - LinkBrowser.finalizeFunction(PageLinkHandler.currentLink); - }; + /** + * + * @param {Event} event + */ + PageLinkHandler.linkCurrent = function(event) { + event.preventDefault(); + LinkBrowser.finalizeFunction(PageLinkHandler.currentLink); + }; - $(function() { - PageLinkHandler.currentLink = $('body').data('currentLink'); + $(function() { + PageLinkHandler.currentLink = $('body').data('currentLink'); - $('a.t3js-pageLink').on('click', PageLinkHandler.linkPage); - $('input.t3js-linkCurrent').on('click', PageLinkHandler.linkCurrent); - $('input.t3js-pageLink').on('click', PageLinkHandler.linkPageByTextfield); - }); + $('a.t3js-pageLink').on('click', PageLinkHandler.linkPage); + $('input.t3js-linkCurrent').on('click', PageLinkHandler.linkCurrent); + $('input.t3js-pageLink').on('click', PageLinkHandler.linkPageByTextfield); + }); - return PageLinkHandler; + return PageLinkHandler; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js index 16a2fa67d0e071ee3c95e6182c2701c8949f4663..f7a904e868f33cd84f0705d4ca137c18a8b5edb7 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js @@ -15,49 +15,49 @@ * Module: TYPO3/CMS/Recordlist/RecordLinkHandler * record link interaction */ -define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function ($, LinkBrowser) { - 'use strict'; - - /** - * @type {{currentLink: string, identifier: string, linkRecord: function, linkCurrent: function}} - */ - var RecordLinkHandler = { - currentLink: '', - identifier: '', - - /** - * @param {Event} event - */ - linkRecord: function (event) { - event.preventDefault(); - - var data = $(this).parents('span').data(); - LinkBrowser.finalizeFunction(RecordLinkHandler.identifier + data.uid); - }, - - /** - * @param {Event} event - */ - linkCurrent: function (event) { - event.preventDefault(); - - LinkBrowser.finalizeFunction(RecordLinkHandler.currentLink); - } - }; - - $(function () { - var body = $('body'); - RecordLinkHandler.currentLink = body.data('currentLink'); - RecordLinkHandler.identifier = body.data('identifier'); - - // adjust searchbox layout - var searchbox = document.getElementById('db_list-searchbox-toolbar'); - searchbox.style.display = 'block'; - searchbox.style.position = 'relative'; - - $('[data-close]').on('click', RecordLinkHandler.linkRecord); - $('input.t3js-linkCurrent').on('click', RecordLinkHandler.linkCurrent); - }); - - return RecordLinkHandler; +define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) { + 'use strict'; + + /** + * @type {{currentLink: string, identifier: string, linkRecord: function, linkCurrent: function}} + */ + var RecordLinkHandler = { + currentLink: '', + identifier: '', + + /** + * @param {Event} event + */ + linkRecord: function(event) { + event.preventDefault(); + + var data = $(this).parents('span').data(); + LinkBrowser.finalizeFunction(RecordLinkHandler.identifier + data.uid); + }, + + /** + * @param {Event} event + */ + linkCurrent: function(event) { + event.preventDefault(); + + LinkBrowser.finalizeFunction(RecordLinkHandler.currentLink); + } + }; + + $(function() { + var body = $('body'); + RecordLinkHandler.currentLink = body.data('currentLink'); + RecordLinkHandler.identifier = body.data('identifier'); + + // adjust searchbox layout + var searchbox = document.getElementById('db_list-searchbox-toolbar'); + searchbox.style.display = 'block'; + searchbox.style.position = 'relative'; + + $('[data-close]').on('click', RecordLinkHandler.linkRecord); + $('input.t3js-linkCurrent').on('click', RecordLinkHandler.linkCurrent); + }); + + return RecordLinkHandler; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js index a6be684f96f27db8debe2f588a9bf10145696190..86f9c5fe436fecb469bd5689aeff23b40780037e 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js @@ -16,112 +16,114 @@ * Usability improvements for the record list */ define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent', 'TYPO3/CMS/Backend/Icons'], function($, PersistentStorage, Icons) { - 'use strict'; - - /** - * @type {Object} - * @exports TYPO3/CMS/Recordlist/Recordlist - */ - var Recordlist = { - identifier: { - entity: '.t3js-entity', - toggle: '.t3js-toggle-recordlist', - icons: { - collapse: 'actions-view-list-collapse', - expand: 'actions-view-list-expand', - editMultiple: '.t3js-record-edit-multiple' - } - } - }; - - /** - * @param {MouseEvent} e - */ - Recordlist.toggleClick = function(e) { - e.preventDefault(); - - var $me = $(this), - table = $me.data('table'), - $target = $($me.data('target')), - isExpanded = $target.data('state') === 'expanded', - $collapseIcon = $me.find('.collapseIcon'), - toggleIcon = isExpanded ? Recordlist.identifier.icons.expand : Recordlist.identifier.icons.collapse; - - Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(toggleIcon) { - $collapseIcon.html(toggleIcon); - }); - - // Store collapse state in UC - var storedModuleDataList = {}; - - if (PersistentStorage.isset('moduleData.list')) { - storedModuleDataList = PersistentStorage.get('moduleData.list'); - } - - var collapseConfig = {}; - collapseConfig[table] = isExpanded ? 1 : 0; - - $.extend(true, storedModuleDataList, collapseConfig); - PersistentStorage.set('moduleData.list', storedModuleDataList).done(function() { - $target.data('state', isExpanded ? 'collapsed' : 'expanded'); - }); - }; - - /** - * Handles editing multiple records. - * - * @param {MouseEvent} event - */ - Recordlist.onEditMultiple = function(event) { - event.preventDefault(); - - var $tableContainer, tableName, entityIdentifiers, uri, patterns; - - $tableContainer = $(this).closest('[data-table]'); - if ($tableContainer.length === 0) { - return; - } - - uri = $(this).data('uri'); - tableName = $tableContainer.data('table'); - entityIdentifiers = $tableContainer - .find(Recordlist.identifier.entity + '[data-uid][data-table="' + tableName + '"]') - .map(function(index, entity) { return $(entity).data('uid'); }) - .toArray() - .join(','); - - patterns = uri.match(/{[^}]+}/g); - $.each(patterns, function(patternIndex, pattern) { - var expression = pattern.substr(1, pattern.length - 2); - var pipes = expression.split(':'); - var name = pipes.shift(); - var value; - - switch (name) { - case 'entityIdentifiers': - value = entityIdentifiers; - break; - case 'T3_THIS_LOCATION': - value = T3_THIS_LOCATION; - break; - default: - return; - } - - $.each(pipes, function(pipeIndex, pipe) { - if (pipe === 'editList') { - value = editList(tableName, value); - } - }); - - uri = uri.replace(pattern, value); - }); - - window.location.href = uri; - }; - - $(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick); - $(document).on('click', Recordlist.identifier.icons.editMultiple, Recordlist.onEditMultiple); - - return Recordlist; + 'use strict'; + + /** + * @type {Object} + * @exports TYPO3/CMS/Recordlist/Recordlist + */ + var Recordlist = { + identifier: { + entity: '.t3js-entity', + toggle: '.t3js-toggle-recordlist', + icons: { + collapse: 'actions-view-list-collapse', + expand: 'actions-view-list-expand', + editMultiple: '.t3js-record-edit-multiple' + } + } + }; + + /** + * @param {MouseEvent} e + */ + Recordlist.toggleClick = function(e) { + e.preventDefault(); + + var $me = $(this), + table = $me.data('table'), + $target = $($me.data('target')), + isExpanded = $target.data('state') === 'expanded', + $collapseIcon = $me.find('.collapseIcon'), + toggleIcon = isExpanded ? Recordlist.identifier.icons.expand : Recordlist.identifier.icons.collapse; + + Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(toggleIcon) { + $collapseIcon.html(toggleIcon); + }); + + // Store collapse state in UC + var storedModuleDataList = {}; + + if (PersistentStorage.isset('moduleData.list')) { + storedModuleDataList = PersistentStorage.get('moduleData.list'); + } + + var collapseConfig = {}; + collapseConfig[table] = isExpanded ? 1 : 0; + + $.extend(true, storedModuleDataList, collapseConfig); + PersistentStorage.set('moduleData.list', storedModuleDataList).done(function() { + $target.data('state', isExpanded ? 'collapsed' : 'expanded'); + }); + }; + + /** + * Handles editing multiple records. + * + * @param {MouseEvent} event + */ + Recordlist.onEditMultiple = function(event) { + event.preventDefault(); + + var $tableContainer, tableName, entityIdentifiers, uri, patterns; + + $tableContainer = $(this).closest('[data-table]'); + if ($tableContainer.length === 0) { + return; + } + + uri = $(this).data('uri'); + tableName = $tableContainer.data('table'); + entityIdentifiers = $tableContainer + .find(Recordlist.identifier.entity + '[data-uid][data-table="' + tableName + '"]') + .map(function(index, entity) { + return $(entity).data('uid'); + }) + .toArray() + .join(','); + + patterns = uri.match(/{[^}]+}/g); + $.each(patterns, function(patternIndex, pattern) { + var expression = pattern.substr(1, pattern.length - 2); + var pipes = expression.split(':'); + var name = pipes.shift(); + var value; + + switch (name) { + case 'entityIdentifiers': + value = entityIdentifiers; + break; + case 'T3_THIS_LOCATION': + value = T3_THIS_LOCATION; + break; + default: + return; + } + + $.each(pipes, function(pipeIndex, pipe) { + if (pipe === 'editList') { + value = editList(tableName, value); + } + }); + + uri = uri.replace(pattern, value); + }); + + window.location.href = uri; + }; + + $(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick); + $(document).on('click', Recordlist.identifier.icons.editMultiple, Recordlist.onEditMultiple); + + return Recordlist; }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js index 4651b8847cf0c303feec5f9da66a6355250d84ca..e7887c3d5f9bee6a953675a53cf2b7c84a6c2c40 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js @@ -17,17 +17,17 @@ * @exports TYPO3/CMS/Recordlist/Tooltip */ define(['jquery', 'TYPO3/CMS/Backend/Tooltip'], function($, Tooltip) { - 'use strict'; + 'use strict'; - $(function() { - Tooltip.initialize('.table-fit a[title]', { - delay: { - show: 500, - hide: 100 - }, - trigger: 'hover', - container: 'body' - }); - }); + $(function() { + Tooltip.initialize('.table-fit a[title]', { + delay: { + show: 500, + hide: 100 + }, + trigger: 'hover', + container: 'body' + }); + }); }); diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js index 7e08ef67acda7925f62f1bc179723ec7e9d367da..e82e0ac9184cfa4b97cb9b8b66813d53ef5730b6 100644 --- a/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js +++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js @@ -16,33 +16,33 @@ * URL link interaction */ define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) { - 'use strict'; + 'use strict'; - /** - * - * @type {{}} - * @exports TYPO3/CMS/Recordlist/UrlLinkHandler - */ - var UrlLinkHandler = {}; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Recordlist/UrlLinkHandler + */ + var UrlLinkHandler = {}; - /** - * - * @param {Event} event - */ - UrlLinkHandler.link = function(event) { - event.preventDefault(); + /** + * + * @param {Event} event + */ + UrlLinkHandler.link = function(event) { + event.preventDefault(); - var value = $(this).find('[name="lurl"]').val(); - if (value === "http://") { - return; - } + var value = $(this).find('[name="lurl"]').val(); + if (value === "http://") { + return; + } - LinkBrowser.finalizeFunction(value); - }; + LinkBrowser.finalizeFunction(value); + }; - $(function() { - $('#lurlform').on('submit', UrlLinkHandler.link); - }); + $(function() { + $('#lurlform').on('submit', UrlLinkHandler.link); + }); - return UrlLinkHandler; + return UrlLinkHandler; }); diff --git a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js index 7d3336a96d5f5589571965eee19222051f4142c2..1128c58e5562b85d63973ad7f53b1bf3c5e2618d 100644 --- a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js +++ b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js @@ -16,587 +16,590 @@ * RequireJS module for Recycler */ define(['jquery', - 'nprogress', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Notification', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/jquery.clearable' - ], function($, NProgress, Modal, Notification, Severity) { - 'use strict'; - - /** - * - * @type {{identifiers: {searchForm: string, searchText: string, searchSubmitBtn: string, depthSelector: string, tableSelector: string, recyclerTable: string, paginator: string, reloadAction: string, massUndo: string, massDelete: string, toggleAll: string}, elements: {}, paging: {currentPage: number, totalPages: number, totalItems: number, itemsPerPage: number}, markedRecordsForMassAction: Array, allToggled: boolean}} - * @exports TYPO3/CMS/Recycler/Recycler - */ - var Recycler = { - identifiers: { - searchForm: '#recycler-form', - searchText: '#recycler-form [name=search-text]', - searchSubmitBtn: '#recycler-form button[type=submit]', - depthSelector: '#recycler-form [name=depth]', - tableSelector: '#recycler-form [name=pages]', - recyclerTable: '#itemsInRecycler', - paginator: '#recycler-index nav', - reloadAction: 'a[data-action=reload]', - massUndo: 'button[data-action=massundo]', - massDelete: 'button[data-action=massdelete]', - toggleAll: '.t3js-toggle-all' - }, - elements: {}, // filled in getElements() - paging: { - currentPage: 1, - totalPages: 1, - totalItems: 0, - itemsPerPage: TYPO3.settings.Recycler.pagingSize - }, - markedRecordsForMassAction: [], - allToggled: false - }; - - /** - * Gets required elements - */ - Recycler.getElements = function() { - Recycler.elements = { - $searchForm: $(Recycler.identifiers.searchForm), - $searchTextField: $(Recycler.identifiers.searchText), - $searchSubmitBtn: $(Recycler.identifiers.searchSubmitBtn), - $depthSelector: $(Recycler.identifiers.depthSelector), - $tableSelector: $(Recycler.identifiers.tableSelector), - $recyclerTable: $(Recycler.identifiers.recyclerTable), - $tableBody: $(Recycler.identifiers.recyclerTable).find('tbody'), - $paginator: $(Recycler.identifiers.paginator), - $reloadAction: $(Recycler.identifiers.reloadAction), - $massUndo: $(Recycler.identifiers.massUndo), - $massDelete: $(Recycler.identifiers.massDelete), - $toggleAll: $(Recycler.identifiers.toggleAll) - }; - }; - - /** - * Register events - */ - Recycler.registerEvents = function() { - // submitting the form - Recycler.elements.$searchForm.on('submit', function(e) { - e.preventDefault(); - if (Recycler.elements.$searchTextField.val() !== '') { - Recycler.loadDeletedElements(); - } - }); - - // changing the search field - Recycler.elements.$searchTextField.on('keyup', function() { - var $me = $(this); - - if ($me.val() !== '') { - Recycler.elements.$searchSubmitBtn.removeClass('disabled'); - } else { - Recycler.elements.$searchSubmitBtn.addClass('disabled'); - Recycler.loadDeletedElements(); - } - }).clearable( - { - onClear: function() { - Recycler.elements.$searchSubmitBtn.addClass('disabled'); - Recycler.loadDeletedElements(); - } - } - ); - - // changing "depth" - Recycler.elements.$depthSelector.on('change', function() { - $.when(Recycler.loadAvailableTables()).done(function() { - Recycler.loadDeletedElements(); - }); - }); - - // changing "table" - Recycler.elements.$tableSelector.on('change', function() { - Recycler.paging.currentPage = 1; - Recycler.loadDeletedElements(); - }); - - // clicking "recover" in single row - Recycler.elements.$recyclerTable.on('click', '[data-action=undo]', Recycler.undoRecord); - - // clicking "delete" in single row - Recycler.elements.$recyclerTable.on('click', '[data-action=delete]', Recycler.deleteRecord); - - Recycler.elements.$reloadAction.on('click', function(e) { - e.preventDefault(); - $.when(Recycler.loadAvailableTables()).done(function() { - Recycler.loadDeletedElements(); - }); - }); - - // clicking an action in the paginator - Recycler.elements.$paginator.on('click', 'a[data-action]', function(e) { - e.preventDefault(); - - var $el = $(this), - reload = false; - - switch ($el.data('action')) { - case 'previous': - if (Recycler.paging.currentPage > 1) { - Recycler.paging.currentPage--; - reload = true; - } - break; - case 'next': - if (Recycler.paging.currentPage < Recycler.paging.totalPages) { - Recycler.paging.currentPage++; - reload = true; - } - break; - case 'page': - Recycler.paging.currentPage = parseInt($el.find('span').text()); - reload = true; - break; - } - - if (reload) { - Recycler.loadDeletedElements(); - } - }); - - if (!TYPO3.settings.Recycler.deleteDisable) { - Recycler.elements.$massDelete.show(); - } else { - Recycler.elements.$massDelete.remove(); - } - - Recycler.elements.$recyclerTable.on('show.bs.collapse hide.bs.collapse', 'tr.collapse', function(e) { - var $trigger = $(e.currentTarget).prev('tr').find('[data-action=expand]'), - $iconEl = $trigger.find('.t3-icon'), - removeClass, - addClass; - - switch (e.type) { - case 'show': - removeClass = 't3-icon-pagetree-collapse'; - addClass = 't3-icon-pagetree-expand'; - break; - case 'hide': - removeClass = 't3-icon-pagetree-expand'; - addClass = 't3-icon-pagetree-collapse'; - break; - } - - $iconEl.removeClass(removeClass).addClass(addClass); - }); - - // checkboxes in the table - Recycler.elements.$toggleAll.on('click', function() { - Recycler.allToggled = !Recycler.allToggled; - $('input[type="checkbox"]').prop('checked', Recycler.allToggled).trigger('change'); - }); - Recycler.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', Recycler.handleCheckboxSelects); - - Recycler.elements.$massUndo.on('click', Recycler.undoRecord); - Recycler.elements.$massDelete.on('click', Recycler.deleteRecord); - }; - - /** - * Initialize the recycler module - */ - Recycler.initialize = function() { - NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); - - Recycler.getElements(); - Recycler.registerEvents(); - - if (TYPO3.settings.Recycler.depthSelection > 0) { - Recycler.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger('change'); - } else { - $.when(Recycler.loadAvailableTables()).done(function() { - Recycler.loadDeletedElements(); - }); - } - }; - - /** - * Handles the clicks on checkboxes in the records table - */ - Recycler.handleCheckboxSelects = function() { - var $checkbox = $(this), - $tr = $checkbox.parents('tr'), - table = $tr.data('table'), - uid = $tr.data('uid'), - record = table + ':' + uid; - - if ($checkbox.prop('checked')) { - Recycler.markedRecordsForMassAction.push(record); - $tr.addClass('warning'); - } else { - var index = Recycler.markedRecordsForMassAction.indexOf(record); - if (index > -1) { - Recycler.markedRecordsForMassAction.splice(index, 1); - } - $tr.removeClass('warning'); - } - - if (Recycler.markedRecordsForMassAction.length > 0) { - if (Recycler.elements.$massUndo.hasClass('disabled')) { - Recycler.elements.$massUndo.removeClass('disabled'); - } - if (Recycler.elements.$massDelete.hasClass('disabled')) { - Recycler.elements.$massDelete.removeClass('disabled'); - } - - var btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [Recycler.markedRecordsForMassAction.length]), - btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [Recycler.markedRecordsForMassAction.length]); - - Recycler.elements.$massUndo.find('span.text').text(btnTextUndo); - Recycler.elements.$massDelete.find('span.text').text(btnTextDelete); - - } else { - Recycler.resetMassActionButtons(); - } - }; - - /** - * Resets the mass action state - */ - Recycler.resetMassActionButtons = function() { - Recycler.markedRecordsForMassAction = []; - Recycler.elements.$massUndo.addClass('disabled'); - Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']); - Recycler.elements.$massDelete.addClass('disabled'); - Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']); - }; - - /** - * Loads all tables which contain deleted records. - * - * @returns {Promise} - */ - Recycler.loadAvailableTables = function() { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['recycler'], - dataType: 'json', - data: { - action: 'getTables', - startUid: TYPO3.settings.Recycler.startUid, - depth: Recycler.elements.$depthSelector.find('option:selected').val() - }, - beforeSend: function() { - NProgress.start(); - Recycler.elements.$tableSelector.val(''); - Recycler.paging.currentPage = 1; - }, - success: function(data) { - var tables = []; - Recycler.elements.$tableSelector.children().remove(); - $.each(data, function(_, value) { - var tableName = value[0], - deletedRecords = value[1], - tableDescription = value[2]; - - if (tableDescription === '') { - tableDescription = TYPO3.lang['label_allrecordtypes']; - } - var optionText = tableDescription + ' (' + deletedRecords + ')'; - tables.push($('<option />').val(tableName).text(optionText)) - }); - - if (tables.length > 0) { - Recycler.elements.$tableSelector.append(tables); - if (TYPO3.settings.Recycler.tableSelection !== '') { - Recycler.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection); - } - } - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * Loads the deleted elements, based on the filters - * - * @returns {Promise} - */ - Recycler.loadDeletedElements = function() { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['recycler'], - dataType: 'json', - data: { - action: 'getDeletedRecords', - depth: Recycler.elements.$depthSelector.find('option:selected').val(), - startUid: TYPO3.settings.Recycler.startUid, - table: Recycler.elements.$tableSelector.find('option:selected').val(), - filterTxt: Recycler.elements.$searchTextField.val(), - start: (Recycler.paging.currentPage -1) * Recycler.paging.itemsPerPage, - limit: Recycler.paging.itemsPerPage - }, - beforeSend: function() { - NProgress.start(); - Recycler.resetMassActionButtons(); - }, - success: function(data) { - Recycler.elements.$tableBody.html(data.rows); - Recycler.buildPaginator(data.totalItems); - }, - complete: function() { - NProgress.done(); - } - }); - }; - - /** - * - */ - Recycler.deleteRecord = function() { - if (TYPO3.settings.Recycler.deleteDisable) { - return; - } - - var $tr = $(this).parents('tr'), - isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button - - var records, message; - if (isMassDelete) { - records = Recycler.markedRecordsForMassAction; - message = TYPO3.lang['modal.massdelete.text']; - } else { - var uid = $tr.data('uid'), - table = $tr.data('table'), - recordTitle = $tr.data('recordtitle'); - records = table + ':' + uid; - message = table === 'pages' ? TYPO3.lang['modal.deletepage.text'] : TYPO3.lang['modal.deletecontent.text']; - message = Recycler.createMessage(message, [recordTitle, '[' + records + ']']); - } - - Modal.confirm(TYPO3.lang['modal.delete.header'], message, Severity.error, [ - { - text: TYPO3.lang['button.cancel'], - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.delete'], - btnClass: 'btn-danger', - trigger: function() { - Recycler.callAjaxAction('delete', typeof records === 'object' ? records : [records], isMassDelete); - } - } - ]); - }; - - /** - * - */ - Recycler.undoRecord = function() { - var $tr = $(this).parents('tr'), - isMassUndo = $tr.parent().prop('tagName') !== 'TBODY'; // undoRecord() was invoked by the mass delete button - - var records, messageText, recoverPages; - if (isMassUndo) { - records = Recycler.markedRecordsForMassAction; - messageText = TYPO3.lang['modal.massundo.text']; - recoverPages = true; - } else { - var uid = $tr.data('uid'), - table = $tr.data('table'), - recordTitle = $tr.data('recordtitle'); - - records = table + ':' + uid; - recoverPages = table === 'pages'; - messageText = recoverPages ? TYPO3.lang['modal.undopage.text'] : TYPO3.lang['modal.undocontent.text']; - messageText = Recycler.createMessage(messageText, [recordTitle, '[' + records + ']']); - - if (recoverPages && $tr.data('parentDeleted')) { - messageText += TYPO3.lang['modal.undo.parentpages']; - } - } - - var $message = null; - if (recoverPages) { - $message = $('<div />').append( - $('<p />').text(messageText), - $('<div />', {class: 'checkbox'}).append( - $('<label />').append(TYPO3.lang['modal.undo.recursive']).prepend($('<input />', {id: 'undo-recursive', type: 'checkbox'})) - ) - ); - } else { - $message = messageText; - } - - Modal.confirm(TYPO3.lang['modal.undo.header'], $message, Severity.ok, [ - { - text: TYPO3.lang['button.cancel'], - btnClass: 'btn-default', - trigger: function() { - Modal.dismiss(); - } - }, { - text: TYPO3.lang['button.undo'], - btnClass: 'btn-success', - trigger: function() { - Recycler.callAjaxAction('undo', typeof records === 'object' ? records : [records], isMassUndo, $message.find('#undo-recursive').prop('checked') ? 1 : 0); - } - } - ]); - }; - - /** - * - * @param {String} action - * @param {Object} records - * @param {Boolean} isMassAction - * @param {Boolean} recursive - */ - Recycler.callAjaxAction = function(action, records, isMassAction, recursive) { - var data = { - records: records, - action: '' - }, - reloadPageTree = false; - if (action === 'undo') { - data.action = 'undoRecords'; - data.recursive = recursive ? 1 : 0; - reloadPageTree = true; - } else if (action === 'delete') { - data.action = 'deleteRecords'; - } else { - return; - } - - $.ajax({ - url: TYPO3.settings.ajaxUrls['recycler'], - dataType: 'json', - data: data, - beforeSend: function() { - NProgress.start(); - }, - success: function(data) { - if (data.success) { - Notification.success('', data.message); - } else { - Notification.error('', data.message); - } - - // reload recycler data - Recycler.paging.currentPage = 1; - - $.when(Recycler.loadAvailableTables()).done(function() { - Recycler.loadDeletedElements(); - if (isMassAction) { - Recycler.resetMassActionButtons(); - } - - if (reloadPageTree) { - Recycler.refreshPageTree(); - } - - // Reset toggle state - Recycler.allToggled = false; - }); - }, - complete: function() { - Modal.dismiss(); - NProgress.done(); - } - }); - }; - - /** - * Replaces the placeholders with actual values - * - * @param {String} message - * @param {Array} placeholders - * @returns {*} - */ - Recycler.createMessage = function(message, placeholders) { - if (typeof message === 'undefined') { - return ''; - } - - return message.replace( - /\{([0-9]+)\}/g, - function(_, index) { - return placeholders[index]; - } - ); - }; - - /** - * Reloads the page tree - */ - Recycler.refreshPageTree = function() { - if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - }; - - /** - * Build the paginator - * - * @param {Number} totalItems - */ - Recycler.buildPaginator = function(totalItems) { - if (totalItems === 0) { - Recycler.elements.$paginator.contents().remove(); - return; - } - - Recycler.paging.totalItems = totalItems; - Recycler.paging.totalPages = Math.ceil(totalItems / Recycler.paging.itemsPerPage); - - if (Recycler.paging.totalPages === 1) { - // early abort if only one page is available - Recycler.elements.$paginator.contents().remove(); - return; - } - - var $ul = $('<ul />', {class: 'pagination pagination-block'}), - liElements = [], - $controlFirstPage = $('<li />').append( - $('<a />', {'data-action': 'previous'}).append( - $('<span />', {class: 't3-icon fa fa-arrow-left'}) - ) - ), - $controlLastPage = $('<li />').append( - $('<a />', {'data-action': 'next'}).append( - $('<span />', {class: 't3-icon fa fa-arrow-right'}) - ) - ); - - if (Recycler.paging.currentPage === 1) { - $controlFirstPage.disablePagingAction(); - } - - if (Recycler.paging.currentPage === Recycler.paging.totalPages) { - $controlLastPage.disablePagingAction(); - } - - for (var i = 1; i <= Recycler.paging.totalPages; i++) { - var $li = $('<li />', {class: Recycler.paging.currentPage === i ? 'active' : ''}); - $li.append( - $('<a />', {'data-action': 'page'}).append( - $('<span />').text(i) - ) - ); - liElements.push($li); - } - - $ul.append($controlFirstPage, liElements, $controlLastPage); - Recycler.elements.$paginator.html($ul); - }; - - /** - * Changes the markup of a pagination action being disabled - */ - $.fn.disablePagingAction = function() { - $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />')); - }; - - $(Recycler.initialize); - - return Recycler; + 'nprogress', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Notification', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/jquery.clearable' +], function($, NProgress, Modal, Notification, Severity) { + 'use strict'; + + /** + * + * @type {{identifiers: {searchForm: string, searchText: string, searchSubmitBtn: string, depthSelector: string, tableSelector: string, recyclerTable: string, paginator: string, reloadAction: string, massUndo: string, massDelete: string, toggleAll: string}, elements: {}, paging: {currentPage: number, totalPages: number, totalItems: number, itemsPerPage: number}, markedRecordsForMassAction: Array, allToggled: boolean}} + * @exports TYPO3/CMS/Recycler/Recycler + */ + var Recycler = { + identifiers: { + searchForm: '#recycler-form', + searchText: '#recycler-form [name=search-text]', + searchSubmitBtn: '#recycler-form button[type=submit]', + depthSelector: '#recycler-form [name=depth]', + tableSelector: '#recycler-form [name=pages]', + recyclerTable: '#itemsInRecycler', + paginator: '#recycler-index nav', + reloadAction: 'a[data-action=reload]', + massUndo: 'button[data-action=massundo]', + massDelete: 'button[data-action=massdelete]', + toggleAll: '.t3js-toggle-all' + }, + elements: {}, // filled in getElements() + paging: { + currentPage: 1, + totalPages: 1, + totalItems: 0, + itemsPerPage: TYPO3.settings.Recycler.pagingSize + }, + markedRecordsForMassAction: [], + allToggled: false + }; + + /** + * Gets required elements + */ + Recycler.getElements = function() { + Recycler.elements = { + $searchForm: $(Recycler.identifiers.searchForm), + $searchTextField: $(Recycler.identifiers.searchText), + $searchSubmitBtn: $(Recycler.identifiers.searchSubmitBtn), + $depthSelector: $(Recycler.identifiers.depthSelector), + $tableSelector: $(Recycler.identifiers.tableSelector), + $recyclerTable: $(Recycler.identifiers.recyclerTable), + $tableBody: $(Recycler.identifiers.recyclerTable).find('tbody'), + $paginator: $(Recycler.identifiers.paginator), + $reloadAction: $(Recycler.identifiers.reloadAction), + $massUndo: $(Recycler.identifiers.massUndo), + $massDelete: $(Recycler.identifiers.massDelete), + $toggleAll: $(Recycler.identifiers.toggleAll) + }; + }; + + /** + * Register events + */ + Recycler.registerEvents = function() { + // submitting the form + Recycler.elements.$searchForm.on('submit', function(e) { + e.preventDefault(); + if (Recycler.elements.$searchTextField.val() !== '') { + Recycler.loadDeletedElements(); + } + }); + + // changing the search field + Recycler.elements.$searchTextField.on('keyup', function() { + var $me = $(this); + + if ($me.val() !== '') { + Recycler.elements.$searchSubmitBtn.removeClass('disabled'); + } else { + Recycler.elements.$searchSubmitBtn.addClass('disabled'); + Recycler.loadDeletedElements(); + } + }).clearable( + { + onClear: function() { + Recycler.elements.$searchSubmitBtn.addClass('disabled'); + Recycler.loadDeletedElements(); + } + } + ); + + // changing "depth" + Recycler.elements.$depthSelector.on('change', function() { + $.when(Recycler.loadAvailableTables()).done(function() { + Recycler.loadDeletedElements(); + }); + }); + + // changing "table" + Recycler.elements.$tableSelector.on('change', function() { + Recycler.paging.currentPage = 1; + Recycler.loadDeletedElements(); + }); + + // clicking "recover" in single row + Recycler.elements.$recyclerTable.on('click', '[data-action=undo]', Recycler.undoRecord); + + // clicking "delete" in single row + Recycler.elements.$recyclerTable.on('click', '[data-action=delete]', Recycler.deleteRecord); + + Recycler.elements.$reloadAction.on('click', function(e) { + e.preventDefault(); + $.when(Recycler.loadAvailableTables()).done(function() { + Recycler.loadDeletedElements(); + }); + }); + + // clicking an action in the paginator + Recycler.elements.$paginator.on('click', 'a[data-action]', function(e) { + e.preventDefault(); + + var $el = $(this), + reload = false; + + switch ($el.data('action')) { + case 'previous': + if (Recycler.paging.currentPage > 1) { + Recycler.paging.currentPage--; + reload = true; + } + break; + case 'next': + if (Recycler.paging.currentPage < Recycler.paging.totalPages) { + Recycler.paging.currentPage++; + reload = true; + } + break; + case 'page': + Recycler.paging.currentPage = parseInt($el.find('span').text()); + reload = true; + break; + } + + if (reload) { + Recycler.loadDeletedElements(); + } + }); + + if (!TYPO3.settings.Recycler.deleteDisable) { + Recycler.elements.$massDelete.show(); + } else { + Recycler.elements.$massDelete.remove(); + } + + Recycler.elements.$recyclerTable.on('show.bs.collapse hide.bs.collapse', 'tr.collapse', function(e) { + var $trigger = $(e.currentTarget).prev('tr').find('[data-action=expand]'), + $iconEl = $trigger.find('.t3-icon'), + removeClass, + addClass; + + switch (e.type) { + case 'show': + removeClass = 't3-icon-pagetree-collapse'; + addClass = 't3-icon-pagetree-expand'; + break; + case 'hide': + removeClass = 't3-icon-pagetree-expand'; + addClass = 't3-icon-pagetree-collapse'; + break; + } + + $iconEl.removeClass(removeClass).addClass(addClass); + }); + + // checkboxes in the table + Recycler.elements.$toggleAll.on('click', function() { + Recycler.allToggled = !Recycler.allToggled; + $('input[type="checkbox"]').prop('checked', Recycler.allToggled).trigger('change'); + }); + Recycler.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', Recycler.handleCheckboxSelects); + + Recycler.elements.$massUndo.on('click', Recycler.undoRecord); + Recycler.elements.$massDelete.on('click', Recycler.deleteRecord); + }; + + /** + * Initialize the recycler module + */ + Recycler.initialize = function() { + NProgress.configure({parent: '.module-loading-indicator', showSpinner: false}); + + Recycler.getElements(); + Recycler.registerEvents(); + + if (TYPO3.settings.Recycler.depthSelection > 0) { + Recycler.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger('change'); + } else { + $.when(Recycler.loadAvailableTables()).done(function() { + Recycler.loadDeletedElements(); + }); + } + }; + + /** + * Handles the clicks on checkboxes in the records table + */ + Recycler.handleCheckboxSelects = function() { + var $checkbox = $(this), + $tr = $checkbox.parents('tr'), + table = $tr.data('table'), + uid = $tr.data('uid'), + record = table + ':' + uid; + + if ($checkbox.prop('checked')) { + Recycler.markedRecordsForMassAction.push(record); + $tr.addClass('warning'); + } else { + var index = Recycler.markedRecordsForMassAction.indexOf(record); + if (index > -1) { + Recycler.markedRecordsForMassAction.splice(index, 1); + } + $tr.removeClass('warning'); + } + + if (Recycler.markedRecordsForMassAction.length > 0) { + if (Recycler.elements.$massUndo.hasClass('disabled')) { + Recycler.elements.$massUndo.removeClass('disabled'); + } + if (Recycler.elements.$massDelete.hasClass('disabled')) { + Recycler.elements.$massDelete.removeClass('disabled'); + } + + var btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [Recycler.markedRecordsForMassAction.length]), + btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [Recycler.markedRecordsForMassAction.length]); + + Recycler.elements.$massUndo.find('span.text').text(btnTextUndo); + Recycler.elements.$massDelete.find('span.text').text(btnTextDelete); + + } else { + Recycler.resetMassActionButtons(); + } + }; + + /** + * Resets the mass action state + */ + Recycler.resetMassActionButtons = function() { + Recycler.markedRecordsForMassAction = []; + Recycler.elements.$massUndo.addClass('disabled'); + Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']); + Recycler.elements.$massDelete.addClass('disabled'); + Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']); + }; + + /** + * Loads all tables which contain deleted records. + * + * @returns {Promise} + */ + Recycler.loadAvailableTables = function() { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['recycler'], + dataType: 'json', + data: { + action: 'getTables', + startUid: TYPO3.settings.Recycler.startUid, + depth: Recycler.elements.$depthSelector.find('option:selected').val() + }, + beforeSend: function() { + NProgress.start(); + Recycler.elements.$tableSelector.val(''); + Recycler.paging.currentPage = 1; + }, + success: function(data) { + var tables = []; + Recycler.elements.$tableSelector.children().remove(); + $.each(data, function(_, value) { + var tableName = value[0], + deletedRecords = value[1], + tableDescription = value[2]; + + if (tableDescription === '') { + tableDescription = TYPO3.lang['label_allrecordtypes']; + } + var optionText = tableDescription + ' (' + deletedRecords + ')'; + tables.push($('<option />').val(tableName).text(optionText)) + }); + + if (tables.length > 0) { + Recycler.elements.$tableSelector.append(tables); + if (TYPO3.settings.Recycler.tableSelection !== '') { + Recycler.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection); + } + } + }, + complete: function() { + NProgress.done(); + } + }); + }; + + /** + * Loads the deleted elements, based on the filters + * + * @returns {Promise} + */ + Recycler.loadDeletedElements = function() { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['recycler'], + dataType: 'json', + data: { + action: 'getDeletedRecords', + depth: Recycler.elements.$depthSelector.find('option:selected').val(), + startUid: TYPO3.settings.Recycler.startUid, + table: Recycler.elements.$tableSelector.find('option:selected').val(), + filterTxt: Recycler.elements.$searchTextField.val(), + start: (Recycler.paging.currentPage - 1) * Recycler.paging.itemsPerPage, + limit: Recycler.paging.itemsPerPage + }, + beforeSend: function() { + NProgress.start(); + Recycler.resetMassActionButtons(); + }, + success: function(data) { + Recycler.elements.$tableBody.html(data.rows); + Recycler.buildPaginator(data.totalItems); + }, + complete: function() { + NProgress.done(); + } + }); + }; + + /** + * + */ + Recycler.deleteRecord = function() { + if (TYPO3.settings.Recycler.deleteDisable) { + return; + } + + var $tr = $(this).parents('tr'), + isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button + + var records, message; + if (isMassDelete) { + records = Recycler.markedRecordsForMassAction; + message = TYPO3.lang['modal.massdelete.text']; + } else { + var uid = $tr.data('uid'), + table = $tr.data('table'), + recordTitle = $tr.data('recordtitle'); + records = table + ':' + uid; + message = table === 'pages' ? TYPO3.lang['modal.deletepage.text'] : TYPO3.lang['modal.deletecontent.text']; + message = Recycler.createMessage(message, [recordTitle, '[' + records + ']']); + } + + Modal.confirm(TYPO3.lang['modal.delete.header'], message, Severity.error, [ + { + text: TYPO3.lang['button.cancel'], + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.delete'], + btnClass: 'btn-danger', + trigger: function() { + Recycler.callAjaxAction('delete', typeof records === 'object' ? records : [records], isMassDelete); + } + } + ]); + }; + + /** + * + */ + Recycler.undoRecord = function() { + var $tr = $(this).parents('tr'), + isMassUndo = $tr.parent().prop('tagName') !== 'TBODY'; // undoRecord() was invoked by the mass delete button + + var records, messageText, recoverPages; + if (isMassUndo) { + records = Recycler.markedRecordsForMassAction; + messageText = TYPO3.lang['modal.massundo.text']; + recoverPages = true; + } else { + var uid = $tr.data('uid'), + table = $tr.data('table'), + recordTitle = $tr.data('recordtitle'); + + records = table + ':' + uid; + recoverPages = table === 'pages'; + messageText = recoverPages ? TYPO3.lang['modal.undopage.text'] : TYPO3.lang['modal.undocontent.text']; + messageText = Recycler.createMessage(messageText, [recordTitle, '[' + records + ']']); + + if (recoverPages && $tr.data('parentDeleted')) { + messageText += TYPO3.lang['modal.undo.parentpages']; + } + } + + var $message = null; + if (recoverPages) { + $message = $('<div />').append( + $('<p />').text(messageText), + $('<div />', {class: 'checkbox'}).append( + $('<label />').append(TYPO3.lang['modal.undo.recursive']).prepend($('<input />', { + id: 'undo-recursive', + type: 'checkbox' + })) + ) + ); + } else { + $message = messageText; + } + + Modal.confirm(TYPO3.lang['modal.undo.header'], $message, Severity.ok, [ + { + text: TYPO3.lang['button.cancel'], + btnClass: 'btn-default', + trigger: function() { + Modal.dismiss(); + } + }, { + text: TYPO3.lang['button.undo'], + btnClass: 'btn-success', + trigger: function() { + Recycler.callAjaxAction('undo', typeof records === 'object' ? records : [records], isMassUndo, $message.find('#undo-recursive').prop('checked') ? 1 : 0); + } + } + ]); + }; + + /** + * + * @param {String} action + * @param {Object} records + * @param {Boolean} isMassAction + * @param {Boolean} recursive + */ + Recycler.callAjaxAction = function(action, records, isMassAction, recursive) { + var data = { + records: records, + action: '' + }, + reloadPageTree = false; + if (action === 'undo') { + data.action = 'undoRecords'; + data.recursive = recursive ? 1 : 0; + reloadPageTree = true; + } else if (action === 'delete') { + data.action = 'deleteRecords'; + } else { + return; + } + + $.ajax({ + url: TYPO3.settings.ajaxUrls['recycler'], + dataType: 'json', + data: data, + beforeSend: function() { + NProgress.start(); + }, + success: function(data) { + if (data.success) { + Notification.success('', data.message); + } else { + Notification.error('', data.message); + } + + // reload recycler data + Recycler.paging.currentPage = 1; + + $.when(Recycler.loadAvailableTables()).done(function() { + Recycler.loadDeletedElements(); + if (isMassAction) { + Recycler.resetMassActionButtons(); + } + + if (reloadPageTree) { + Recycler.refreshPageTree(); + } + + // Reset toggle state + Recycler.allToggled = false; + }); + }, + complete: function() { + Modal.dismiss(); + NProgress.done(); + } + }); + }; + + /** + * Replaces the placeholders with actual values + * + * @param {String} message + * @param {Array} placeholders + * @returns {*} + */ + Recycler.createMessage = function(message, placeholders) { + if (typeof message === 'undefined') { + return ''; + } + + return message.replace( + /\{([0-9]+)\}/g, + function(_, index) { + return placeholders[index]; + } + ); + }; + + /** + * Reloads the page tree + */ + Recycler.refreshPageTree = function() { + if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } + }; + + /** + * Build the paginator + * + * @param {Number} totalItems + */ + Recycler.buildPaginator = function(totalItems) { + if (totalItems === 0) { + Recycler.elements.$paginator.contents().remove(); + return; + } + + Recycler.paging.totalItems = totalItems; + Recycler.paging.totalPages = Math.ceil(totalItems / Recycler.paging.itemsPerPage); + + if (Recycler.paging.totalPages === 1) { + // early abort if only one page is available + Recycler.elements.$paginator.contents().remove(); + return; + } + + var $ul = $('<ul />', {class: 'pagination pagination-block'}), + liElements = [], + $controlFirstPage = $('<li />').append( + $('<a />', {'data-action': 'previous'}).append( + $('<span />', {class: 't3-icon fa fa-arrow-left'}) + ) + ), + $controlLastPage = $('<li />').append( + $('<a />', {'data-action': 'next'}).append( + $('<span />', {class: 't3-icon fa fa-arrow-right'}) + ) + ); + + if (Recycler.paging.currentPage === 1) { + $controlFirstPage.disablePagingAction(); + } + + if (Recycler.paging.currentPage === Recycler.paging.totalPages) { + $controlLastPage.disablePagingAction(); + } + + for (var i = 1; i <= Recycler.paging.totalPages; i++) { + var $li = $('<li />', {class: Recycler.paging.currentPage === i ? 'active' : ''}); + $li.append( + $('<a />', {'data-action': 'page'}).append( + $('<span />').text(i) + ) + ); + liElements.push($li); + } + + $ul.append($controlFirstPage, liElements, $controlLastPage); + Recycler.elements.$paginator.html($ul); + }; + + /** + * Changes the markup of a pagination action being disabled + */ + $.fn.disablePagingAction = function() { + $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />')); + }; + + $(Recycler.initialize); + + return Recycler; }); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js index 05024e8ce64dc7029cc6d61c346ecb9d4b0b2098..ab660653269a08a9da33f436b212793cb72f556b 100644 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js @@ -1,181 +1,181 @@ (function() { - 'use strict'; - - /** - * Prevent calling the function multiple times - */ - var documentReadyFunctionCalled = false; - - var rsaEncryption = function(form) { - - /** - * Submitted form element - */ - this.form = form; - - /** - * Store found fields in an array - */ - this.fields = []; - - /** - * XMLHttpRequest - */ - this.xhr = null; - - /** - * Remember if we fetched the RSA key already - */ - this.fetchedRsaKey = false; - - /** - * Fetches a new public key by Ajax and encrypts the password for transmission - */ - this.handleFormSubmitRequest = function(event) { - if (event.cancelBubble) { - return; - } - - var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption; - if (!rsaEncryption) { - return; - } - if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) { - rsaEncryption.fetchedRsaKey = true; - rsaEncryption.ajaxCall( - TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP - rsaEncryption, - function(response) { - rsaEncryption.handlePublicKeyResponse(response, rsaEncryption); - } - ); - - if (event.preventDefault) { - event.preventDefault(); - } else if (window.event) { - window.event.returnValue = false; - } - } - }; - - this.ajaxCall = function(url, rsaEncryption, callback) { - // Abort previous request, only last request/generated key pair can be used - if (rsaEncryption.xhr) { - rsaEncryption.xhr.abort(); - } - - if (typeof XMLHttpRequest !== 'undefined') { - rsaEncryption.xhr = new XMLHttpRequest(); - } else { - var versions = [ - 'MSXML2.XmlHttp.5.0', - 'MSXML2.XmlHttp.4.0', - 'MSXML2.XmlHttp.3.0', - 'MSXML2.XmlHttp.2.0', - 'Microsoft.XmlHttp' - ]; - for (var i = 0, count = versions.length; i < count; i++) { - try { - rsaEncryption.xhr = new ActiveXObject(versions[i]); - break; - } catch (e) { - } - } - } - - rsaEncryption.xhr.onreadystatechange = function() { - // Only process requests that are ready and have a status (not aborted) - if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) { - callback(rsaEncryption.xhr); - } - }; - - rsaEncryption.xhr.open('GET', url, true); - rsaEncryption.xhr.send(''); - }; - - this.handlePublicKeyResponse = function(response, rsaEncryption) { - var publicKey = response.responseText.split(':'); - if (!publicKey[0] || !publicKey[1]) { - alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); - return false; - } - - var rsa = new RSAKey(); - rsa.setPublic(publicKey[0], publicKey[1]); - for (var i = rsaEncryption.fields.length; i--;) { - var field = rsaEncryption.fields[i]; - var encryptedValue = rsa.encrypt(field.value); - // Replace value with encrypted value - field.value = 'rsa:' + hex2b64(encryptedValue); - } - - // Submit the form again but now with encrypted values - var form = document.createElement('form'); - if (form.submit.call) { - form.submit.call(rsaEncryption.form); - } else { - for (var j = rsaEncryption.form.elements.length; j--;) { - var submitField = rsaEncryption.form.elements[j]; - if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") { - submitField.click(); - } - } - } - }; - }; - - /** - * Bind submit handler to all forms with input:data-rsa-encryption fields - */ - function ready() { - if (documentReadyFunctionCalled) { - return; - } - - documentReadyFunctionCalled = true; - rng_seed_time(); - for (var i = document.forms.length; i--;) { - var form = document.forms[i]; - for (var j = form.elements.length; j--;) { - var field = form.elements[j]; - if (field.nodeName.toLowerCase() === 'input') { - var dataAttribute = field.getAttribute('data-rsa-encryption'); - if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) { - if (!form.rsaEncryption) { - form.rsaEncryption = new rsaEncryption(form); - if (form.addEventListener) { - form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false); - } else if (form.attachEvent) { - form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest); - } - } - form.rsaEncryption.fields.push(field); - } - } - } - } - } - - // If the document is ready, callback function can be called - if (document.readyState === 'complete') { - setTimeout(ready, 1); - } else { - // Install event handlers for older browsers - if (document.addEventListener) { - // First register DOMContentLoaded event - document.addEventListener('DOMContentLoaded', ready, false); - // Register backup on windows object - window.addEventListener('load', ready, false); - } else { - // Fallback for Internet Explorer - document.attachEvent('onreadystatechange', function() { - if (document.readyState === 'complete') { - ready(); - } - }); - window.attachEvent('onload', ready); - } - } + 'use strict'; + + /** + * Prevent calling the function multiple times + */ + var documentReadyFunctionCalled = false; + + var rsaEncryption = function(form) { + + /** + * Submitted form element + */ + this.form = form; + + /** + * Store found fields in an array + */ + this.fields = []; + + /** + * XMLHttpRequest + */ + this.xhr = null; + + /** + * Remember if we fetched the RSA key already + */ + this.fetchedRsaKey = false; + + /** + * Fetches a new public key by Ajax and encrypts the password for transmission + */ + this.handleFormSubmitRequest = function(event) { + if (event.cancelBubble) { + return; + } + + var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption; + if (!rsaEncryption) { + return; + } + if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) { + rsaEncryption.fetchedRsaKey = true; + rsaEncryption.ajaxCall( + TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP + rsaEncryption, + function(response) { + rsaEncryption.handlePublicKeyResponse(response, rsaEncryption); + } + ); + + if (event.preventDefault) { + event.preventDefault(); + } else if (window.event) { + window.event.returnValue = false; + } + } + }; + + this.ajaxCall = function(url, rsaEncryption, callback) { + // Abort previous request, only last request/generated key pair can be used + if (rsaEncryption.xhr) { + rsaEncryption.xhr.abort(); + } + + if (typeof XMLHttpRequest !== 'undefined') { + rsaEncryption.xhr = new XMLHttpRequest(); + } else { + var versions = [ + 'MSXML2.XmlHttp.5.0', + 'MSXML2.XmlHttp.4.0', + 'MSXML2.XmlHttp.3.0', + 'MSXML2.XmlHttp.2.0', + 'Microsoft.XmlHttp' + ]; + for (var i = 0, count = versions.length; i < count; i++) { + try { + rsaEncryption.xhr = new ActiveXObject(versions[i]); + break; + } catch (e) { + } + } + } + + rsaEncryption.xhr.onreadystatechange = function() { + // Only process requests that are ready and have a status (not aborted) + if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) { + callback(rsaEncryption.xhr); + } + }; + + rsaEncryption.xhr.open('GET', url, true); + rsaEncryption.xhr.send(''); + }; + + this.handlePublicKeyResponse = function(response, rsaEncryption) { + var publicKey = response.responseText.split(':'); + if (!publicKey[0] || !publicKey[1]) { + alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); + return false; + } + + var rsa = new RSAKey(); + rsa.setPublic(publicKey[0], publicKey[1]); + for (var i = rsaEncryption.fields.length; i--;) { + var field = rsaEncryption.fields[i]; + var encryptedValue = rsa.encrypt(field.value); + // Replace value with encrypted value + field.value = 'rsa:' + hex2b64(encryptedValue); + } + + // Submit the form again but now with encrypted values + var form = document.createElement('form'); + if (form.submit.call) { + form.submit.call(rsaEncryption.form); + } else { + for (var j = rsaEncryption.form.elements.length; j--;) { + var submitField = rsaEncryption.form.elements[j]; + if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") { + submitField.click(); + } + } + } + }; + }; + + /** + * Bind submit handler to all forms with input:data-rsa-encryption fields + */ + function ready() { + if (documentReadyFunctionCalled) { + return; + } + + documentReadyFunctionCalled = true; + rng_seed_time(); + for (var i = document.forms.length; i--;) { + var form = document.forms[i]; + for (var j = form.elements.length; j--;) { + var field = form.elements[j]; + if (field.nodeName.toLowerCase() === 'input') { + var dataAttribute = field.getAttribute('data-rsa-encryption'); + if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) { + if (!form.rsaEncryption) { + form.rsaEncryption = new rsaEncryption(form); + if (form.addEventListener) { + form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false); + } else if (form.attachEvent) { + form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest); + } + } + form.rsaEncryption.fields.push(field); + } + } + } + } + } + + // If the document is ready, callback function can be called + if (document.readyState === 'complete') { + setTimeout(ready, 1); + } else { + // Install event handlers for older browsers + if (document.addEventListener) { + // First register DOMContentLoaded event + document.addEventListener('DOMContentLoaded', ready, false); + // Register backup on windows object + window.addEventListener('load', ready, false); + } else { + // Fallback for Internet Explorer + document.attachEvent('onreadystatechange', function() { + if (document.readyState === 'complete') { + ready(); + } + }); + window.attachEvent('onload', ready); + } + } })(); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js index 6ae8daf5c2324ddbab2e7f6c78feb48a9ca61991..68ac12e40bfd9b89262eb49d91e362f84cd3747b 100644 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js @@ -16,138 +16,138 @@ * Object that handles RSA encryption and submission of the form */ define(['jquery', './RsaLibrary'], function($) { - 'use strict'; - - /** - * @type {{$currentForm: null, fetchedRsaKey: boolean, initialize: Function, registerForm: Function, handleFormSubmitRequest: Function, handlePublicKeyResponse: Function}} - * @exports TYPO3/CMS/Rsaauth/RsaEncryptionModule - */ - var RsaEncryption = { - - /** - * Remember the form which was submitted - */ - $currentForm: null, - - /** - * Remember if we fetched the RSA key already - */ - fetchedRsaKey: false, - - /** - * Replace event handler of submit button for given form - * - * @param {Form} form Form DOM object - */ - registerForm: function(form) { - var $form = $(form); - - if ($form.data('rsaRegistered')) { - // Do not register form twice - return; - } - // Mark form as registered - $form.data('rsaRegistered', true); - - // Store the original submit handler that is executed later - $form.data('original-onsubmit', $form.attr('onsubmit')); - - // Remove the original submit handler and register RsaEncryption.handleFormSubmitRequest instead - $form.removeAttr('onsubmit').on('submit', RsaEncryption.handleFormSubmitRequest); - - // Bind submit event first (this is a dirty hack with jquery internals, but there is no way around that) - var handlers = $._data(form, 'events').submit; - var handler = handlers.pop(); - handlers.unshift(handler); - }, - - /** - * Fetches a new public key by Ajax and encrypts the password for transmission - * - * @param {Event} event - */ - handleFormSubmitRequest: function(event) { - if (!RsaEncryption.fetchedRsaKey) { - event.stopImmediatePropagation(); - - RsaEncryption.fetchedRsaKey = true; - RsaEncryption.$currentForm = $(this); - - $.ajax({ - url: TYPO3.settings.ajaxUrls['rsa_publickey'], - success: RsaEncryption.handlePublicKeyResponse - }); - - return false; - } else { - // we come here again when the submit is triggered below - // reset the variable to fetch a new key for next attempt - RsaEncryption.fetchedRsaKey = false; - } - }, - - /** - * Parses the Json response and triggers submission of the form - * - * @param {Object} response Ajax response object - */ - handlePublicKeyResponse: function(response) { - var publicKey = response.split(':'); - if (!publicKey[0] || !publicKey[1]) { - alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); - return; - } - - var rsa = new RSAKey(); - rsa.setPublic(publicKey[0], publicKey[1]); - RsaEncryption.$currentForm.find(':input[data-rsa-encryption]').each(function() { - var $this = $(this); - var encryptedValue = rsa.encrypt($this.val()); - var dataAttribute = $this.data('rsa-encryption'); - var rsaValue = 'rsa:' + hex2b64(encryptedValue); - - if (!dataAttribute) { - $this.val(rsaValue); - } else { - var $typo3Field = $('#' + dataAttribute); - $typo3Field.val(rsaValue); - // Reset user password field to prevent it from being submitted - $this.val(''); - } - }); - - // Try to fetch the field which submitted the form - var $currentField = RsaEncryption.$currentForm.find('input[type=submit]:focus,input[type=image]:focus'); - if ($currentField.length === 1) { - $currentField.trigger('click'); - } else { - // Create a hidden input field to fake pressing the submit button - RsaEncryption.$currentForm.append('<input type="hidden" name="commandLI" value="Submit">'); - - // Restore the original submit handler - var originalOnSubmit = RsaEncryption.$currentForm.data('original-onsubmit'); - if (typeof originalOnSubmit === 'string' && originalOnSubmit.length > 0) { - RsaEncryption.$currentForm.attr('onsubmit', originalOnSubmit); - RsaEncryption.$currentForm.removeData('original-onsubmit'); - } - - // Submit the form - RsaEncryption.$currentForm.trigger('submit'); - } - } - }; - - /** - * Search for forms and add event handler - */ - RsaEncryption.initialize = function() { - $(':input[data-rsa-encryption]').closest('form').each(function() { - RsaEncryption.registerForm(this); - }); - rng_seed_time(); - }; - - $(RsaEncryption.initialize); - - return RsaEncryption; + 'use strict'; + + /** + * @type {{$currentForm: null, fetchedRsaKey: boolean, initialize: Function, registerForm: Function, handleFormSubmitRequest: Function, handlePublicKeyResponse: Function}} + * @exports TYPO3/CMS/Rsaauth/RsaEncryptionModule + */ + var RsaEncryption = { + + /** + * Remember the form which was submitted + */ + $currentForm: null, + + /** + * Remember if we fetched the RSA key already + */ + fetchedRsaKey: false, + + /** + * Replace event handler of submit button for given form + * + * @param {Form} form Form DOM object + */ + registerForm: function(form) { + var $form = $(form); + + if ($form.data('rsaRegistered')) { + // Do not register form twice + return; + } + // Mark form as registered + $form.data('rsaRegistered', true); + + // Store the original submit handler that is executed later + $form.data('original-onsubmit', $form.attr('onsubmit')); + + // Remove the original submit handler and register RsaEncryption.handleFormSubmitRequest instead + $form.removeAttr('onsubmit').on('submit', RsaEncryption.handleFormSubmitRequest); + + // Bind submit event first (this is a dirty hack with jquery internals, but there is no way around that) + var handlers = $._data(form, 'events').submit; + var handler = handlers.pop(); + handlers.unshift(handler); + }, + + /** + * Fetches a new public key by Ajax and encrypts the password for transmission + * + * @param {Event} event + */ + handleFormSubmitRequest: function(event) { + if (!RsaEncryption.fetchedRsaKey) { + event.stopImmediatePropagation(); + + RsaEncryption.fetchedRsaKey = true; + RsaEncryption.$currentForm = $(this); + + $.ajax({ + url: TYPO3.settings.ajaxUrls['rsa_publickey'], + success: RsaEncryption.handlePublicKeyResponse + }); + + return false; + } else { + // we come here again when the submit is triggered below + // reset the variable to fetch a new key for next attempt + RsaEncryption.fetchedRsaKey = false; + } + }, + + /** + * Parses the Json response and triggers submission of the form + * + * @param {Object} response Ajax response object + */ + handlePublicKeyResponse: function(response) { + var publicKey = response.split(':'); + if (!publicKey[0] || !publicKey[1]) { + alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.'); + return; + } + + var rsa = new RSAKey(); + rsa.setPublic(publicKey[0], publicKey[1]); + RsaEncryption.$currentForm.find(':input[data-rsa-encryption]').each(function() { + var $this = $(this); + var encryptedValue = rsa.encrypt($this.val()); + var dataAttribute = $this.data('rsa-encryption'); + var rsaValue = 'rsa:' + hex2b64(encryptedValue); + + if (!dataAttribute) { + $this.val(rsaValue); + } else { + var $typo3Field = $('#' + dataAttribute); + $typo3Field.val(rsaValue); + // Reset user password field to prevent it from being submitted + $this.val(''); + } + }); + + // Try to fetch the field which submitted the form + var $currentField = RsaEncryption.$currentForm.find('input[type=submit]:focus,input[type=image]:focus'); + if ($currentField.length === 1) { + $currentField.trigger('click'); + } else { + // Create a hidden input field to fake pressing the submit button + RsaEncryption.$currentForm.append('<input type="hidden" name="commandLI" value="Submit">'); + + // Restore the original submit handler + var originalOnSubmit = RsaEncryption.$currentForm.data('original-onsubmit'); + if (typeof originalOnSubmit === 'string' && originalOnSubmit.length > 0) { + RsaEncryption.$currentForm.attr('onsubmit', originalOnSubmit); + RsaEncryption.$currentForm.removeData('original-onsubmit'); + } + + // Submit the form + RsaEncryption.$currentForm.trigger('submit'); + } + } + }; + + /** + * Search for forms and add event handler + */ + RsaEncryption.initialize = function() { + $(':input[data-rsa-encryption]').closest('form').each(function() { + RsaEncryption.registerForm(this); + }); + rng_seed_time(); + }; + + $(RsaEncryption.initialize); + + return RsaEncryption; }); diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js index 96244d0412cc74e4f3755807d8fcfc08b2aa8a49..9a0a2050fc6b9005b2773757eabb0309dffdd7c3 100644 --- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js +++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js @@ -1,76 +1,76 @@ // // base64.js // -var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -var b64padchar="="; +var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +var b64padchar = "="; function hex2b64(h) { - var i; - var c; - var ret = ""; - for(i = 0; i+3 <= h.length; i+=3) { - c = parseInt(h.substring(i,i+3),16); - ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); - } - if(i+1 == h.length) { - c = parseInt(h.substring(i,i+1),16); - ret += b64map.charAt(c << 2); - } - else if(i+2 == h.length) { - c = parseInt(h.substring(i,i+2),16); - ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); - } - while((ret.length & 3) > 0) ret += b64padchar; - return ret; + var i; + var c; + var ret = ""; + for (i = 0; i + 3 <= h.length; i += 3) { + c = parseInt(h.substring(i, i + 3), 16); + ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63); + } + if (i + 1 == h.length) { + c = parseInt(h.substring(i, i + 1), 16); + ret += b64map.charAt(c << 2); + } + else if (i + 2 == h.length) { + c = parseInt(h.substring(i, i + 2), 16); + ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4); + } + while ((ret.length & 3) > 0) ret += b64padchar; + return ret; } // convert a base64 string to hex function b64tohex(s) { - var ret = ""; - var i; - var k = 0; // b64 state, 0-3 - var slop; - for(i = 0; i < s.length; ++i) { - if(s.charAt(i) == b64padchar) break; - v = b64map.indexOf(s.charAt(i)); - if(v < 0) continue; - if(k == 0) { - ret += int2char(v >> 2); - slop = v & 3; - k = 1; - } - else if(k == 1) { - ret += int2char((slop << 2) | (v >> 4)); - slop = v & 0xf; - k = 2; - } - else if(k == 2) { - ret += int2char(slop); - ret += int2char(v >> 2); - slop = v & 3; - k = 3; - } - else { - ret += int2char((slop << 2) | (v >> 4)); - ret += int2char(v & 0xf); - k = 0; - } - } - if(k == 1) - ret += int2char(slop << 2); - return ret; + var ret = ""; + var i; + var k = 0; // b64 state, 0-3 + var slop; + for (i = 0; i < s.length; ++i) { + if (s.charAt(i) == b64padchar) break; + v = b64map.indexOf(s.charAt(i)); + if (v < 0) continue; + if (k == 0) { + ret += int2char(v >> 2); + slop = v & 3; + k = 1; + } + else if (k == 1) { + ret += int2char((slop << 2) | (v >> 4)); + slop = v & 0xf; + k = 2; + } + else if (k == 2) { + ret += int2char(slop); + ret += int2char(v >> 2); + slop = v & 3; + k = 3; + } + else { + ret += int2char((slop << 2) | (v >> 4)); + ret += int2char(v & 0xf); + k = 0; + } + } + if (k == 1) + ret += int2char(slop << 2); + return ret; } // convert a base64 string to a byte/number array function b64toBA(s) { - //piggyback on b64tohex for now, optimize later - var h = b64tohex(s); - var i; - var a = new Array(); - for(i = 0; 2*i < h.length; ++i) { - a[i] = parseInt(h.substring(2*i,2*i+2),16); - } - return a; + //piggyback on b64tohex for now, optimize later + var h = b64tohex(s); + var i; + var a = new Array(); + for (i = 0; 2 * i < h.length; ++i) { + a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16); + } + return a; } // @@ -88,18 +88,20 @@ var dbits; // JavaScript engine analysis var canary = 0xdeadbeefcafe; -var j_lm = ((canary&0xffffff)==0xefcafe); +var j_lm = ((canary & 0xffffff) == 0xefcafe); // (public) Constructor -function BigInteger(a,b,c) { - if(a != null) - if("number" == typeof a) this.fromNumber(a,b,c); - else if(b == null && "string" != typeof a) this.fromString(a,256); - else this.fromString(a,b); +function BigInteger(a, b, c) { + if (a != null) + if ("number" == typeof a) this.fromNumber(a, b, c); + else if (b == null && "string" != typeof a) this.fromString(a, 256); + else this.fromString(a, b); } // return new, unset BigInteger -function nbi() { return new BigInteger(null); } +function nbi() { + return new BigInteger(null); +} // am: Compute w_j += (x*this_i), propagate carries, // c is initial carry, returns final carry. @@ -109,391 +111,457 @@ function nbi() { return new BigInteger(null); } // am1: use a single mult and divide to get the high bits, // max digit bits should be 26 because // max internal value = 2*dvalue^2-2*dvalue (< 2^53) -function am1(i,x,w,j,c,n) { - while(--n >= 0) { - var v = x*this[i++]+w[j]+c; - c = Math.floor(v/0x4000000); - w[j++] = v&0x3ffffff; - } - return c; +function am1(i, x, w, j, c, n) { + while (--n >= 0) { + var v = x * this[i++] + w[j] + c; + c = Math.floor(v / 0x4000000); + w[j++] = v & 0x3ffffff; + } + return c; } + // am2 avoids a big mult-and-extract completely. // Max digit bits should be <= 30 because we do bitwise ops // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) -function am2(i,x,w,j,c,n) { - var xl = x&0x7fff, xh = x>>15; - while(--n >= 0) { - var l = this[i]&0x7fff; - var h = this[i++]>>15; - var m = xh*l+h*xl; - l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff); - c = (l>>>30)+(m>>>15)+xh*h+(c>>>30); - w[j++] = l&0x3fffffff; - } - return c; +function am2(i, x, w, j, c, n) { + var xl = x & 0x7fff, xh = x >> 15; + while (--n >= 0) { + var l = this[i] & 0x7fff; + var h = this[i++] >> 15; + var m = xh * l + h * xl; + l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff); + c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30); + w[j++] = l & 0x3fffffff; + } + return c; } + // Alternately, set max digit bits to 28 since some // browsers slow down when dealing with 32-bit numbers. -function am3(i,x,w,j,c,n) { - var xl = x&0x3fff, xh = x>>14; - while(--n >= 0) { - var l = this[i]&0x3fff; - var h = this[i++]>>14; - var m = xh*l+h*xl; - l = xl*l+((m&0x3fff)<<14)+w[j]+c; - c = (l>>28)+(m>>14)+xh*h; - w[j++] = l&0xfffffff; - } - return c; -} -if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) { - BigInteger.prototype.am = am2; - dbits = 30; -} -else if(j_lm && (navigator.appName != "Netscape")) { - BigInteger.prototype.am = am1; - dbits = 26; +function am3(i, x, w, j, c, n) { + var xl = x & 0x3fff, xh = x >> 14; + while (--n >= 0) { + var l = this[i] & 0x3fff; + var h = this[i++] >> 14; + var m = xh * l + h * xl; + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c; + c = (l >> 28) + (m >> 14) + xh * h; + w[j++] = l & 0xfffffff; + } + return c; +} + +if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) { + BigInteger.prototype.am = am2; + dbits = 30; +} +else if (j_lm && (navigator.appName != "Netscape")) { + BigInteger.prototype.am = am1; + dbits = 26; } else { // Mozilla/Netscape seems to prefer am3 - BigInteger.prototype.am = am3; - dbits = 28; + BigInteger.prototype.am = am3; + dbits = 28; } BigInteger.prototype.DB = dbits; -BigInteger.prototype.DM = ((1<<dbits)-1); -BigInteger.prototype.DV = (1<<dbits); +BigInteger.prototype.DM = ((1 << dbits) - 1); +BigInteger.prototype.DV = (1 << dbits); var BI_FP = 52; -BigInteger.prototype.FV = Math.pow(2,BI_FP); -BigInteger.prototype.F1 = BI_FP-dbits; -BigInteger.prototype.F2 = 2*dbits-BI_FP; +BigInteger.prototype.FV = Math.pow(2, BI_FP); +BigInteger.prototype.F1 = BI_FP - dbits; +BigInteger.prototype.F2 = 2 * dbits - BI_FP; // Digit conversions var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"; var BI_RC = new Array(); -var rr,vv; +var rr, vv; rr = "0".charCodeAt(0); -for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; +for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv; rr = "a".charCodeAt(0); -for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; rr = "A".charCodeAt(0); -for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv; -function int2char(n) { return BI_RM.charAt(n); } -function intAt(s,i) { - var c = BI_RC[s.charCodeAt(i)]; - return (c==null)?-1:c; +function int2char(n) { + return BI_RM.charAt(n); +} + +function intAt(s, i) { + var c = BI_RC[s.charCodeAt(i)]; + return (c == null) ? -1 : c; } // (protected) copy this to r function bnpCopyTo(r) { - for(var i = this.t-1; i >= 0; --i) r[i] = this[i]; - r.t = this.t; - r.s = this.s; + for (var i = this.t - 1; i >= 0; --i) r[i] = this[i]; + r.t = this.t; + r.s = this.s; } // (protected) set from integer value x, -DV <= x < DV function bnpFromInt(x) { - this.t = 1; - this.s = (x<0)?-1:0; - if(x > 0) this[0] = x; - else if(x < -1) this[0] = x+this.DV; - else this.t = 0; + this.t = 1; + this.s = (x < 0) ? -1 : 0; + if (x > 0) this[0] = x; + else if (x < -1) this[0] = x + this.DV; + else this.t = 0; } // return bigint initialized to value -function nbv(i) { var r = nbi(); r.fromInt(i); return r; } +function nbv(i) { + var r = nbi(); + r.fromInt(i); + return r; +} // (protected) set from string and radix -function bnpFromString(s,b) { - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 256) k = 8; // byte array - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else { this.fromRadix(s,b); return; } - this.t = 0; - this.s = 0; - var i = s.length, mi = false, sh = 0; - while(--i >= 0) { - var x = (k==8)?s[i]&0xff:intAt(s,i); - if(x < 0) { - if(s.charAt(i) == "-") mi = true; - continue; - } - mi = false; - if(sh == 0) - this[this.t++] = x; - else if(sh+k > this.DB) { - this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh; - this[this.t++] = (x>>(this.DB-sh)); - } - else - this[this.t-1] |= x<<sh; - sh += k; - if(sh >= this.DB) sh -= this.DB; - } - if(k == 8 && (s[0]&0x80) != 0) { - this.s = -1; - if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh; - } - this.clamp(); - if(mi) BigInteger.ZERO.subTo(this,this); +function bnpFromString(s, b) { + var k; + if (b == 16) k = 4; + else if (b == 8) k = 3; + else if (b == 256) k = 8; // byte array + else if (b == 2) k = 1; + else if (b == 32) k = 5; + else if (b == 4) k = 2; + else { + this.fromRadix(s, b); + return; + } + this.t = 0; + this.s = 0; + var i = s.length, mi = false, sh = 0; + while (--i >= 0) { + var x = (k == 8) ? s[i] & 0xff : intAt(s, i); + if (x < 0) { + if (s.charAt(i) == "-") mi = true; + continue; + } + mi = false; + if (sh == 0) + this[this.t++] = x; + else if (sh + k > this.DB) { + this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh; + this[this.t++] = (x >> (this.DB - sh)); + } + else + this[this.t - 1] |= x << sh; + sh += k; + if (sh >= this.DB) sh -= this.DB; + } + if (k == 8 && (s[0] & 0x80) != 0) { + this.s = -1; + if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh; + } + this.clamp(); + if (mi) BigInteger.ZERO.subTo(this, this); } // (protected) clamp off excess high words function bnpClamp() { - var c = this.s&this.DM; - while(this.t > 0 && this[this.t-1] == c) --this.t; + var c = this.s & this.DM; + while (this.t > 0 && this[this.t - 1] == c) --this.t; } // (public) return string representation in given radix function bnToString(b) { - if(this.s < 0) return "-"+this.negate().toString(b); - var k; - if(b == 16) k = 4; - else if(b == 8) k = 3; - else if(b == 2) k = 1; - else if(b == 32) k = 5; - else if(b == 4) k = 2; - else return this.toRadix(b); - var km = (1<<k)-1, d, m = false, r = "", i = this.t; - var p = this.DB-(i*this.DB)%k; - if(i-- > 0) { - if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); } - while(i >= 0) { - if(p < k) { - d = (this[i]&((1<<p)-1))<<(k-p); - d |= this[--i]>>(p+=this.DB-k); - } - else { - d = (this[i]>>(p-=k))&km; - if(p <= 0) { p += this.DB; --i; } - } - if(d > 0) m = true; - if(m) r += int2char(d); - } - } - return m?r:"0"; + if (this.s < 0) return "-" + this.negate().toString(b); + var k; + if (b == 16) k = 4; + else if (b == 8) k = 3; + else if (b == 2) k = 1; + else if (b == 32) k = 5; + else if (b == 4) k = 2; + else return this.toRadix(b); + var km = (1 << k) - 1, d, m = false, r = "", i = this.t; + var p = this.DB - (i * this.DB) % k; + if (i-- > 0) { + if (p < this.DB && (d = this[i] >> p) > 0) { + m = true; + r = int2char(d); + } + while (i >= 0) { + if (p < k) { + d = (this[i] & ((1 << p) - 1)) << (k - p); + d |= this[--i] >> (p += this.DB - k); + } + else { + d = (this[i] >> (p -= k)) & km; + if (p <= 0) { + p += this.DB; + --i; + } + } + if (d > 0) m = true; + if (m) r += int2char(d); + } + } + return m ? r : "0"; } // (public) -this -function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; } +function bnNegate() { + var r = nbi(); + BigInteger.ZERO.subTo(this, r); + return r; +} // (public) |this| -function bnAbs() { return (this.s<0)?this.negate():this; } +function bnAbs() { + return (this.s < 0) ? this.negate() : this; +} // (public) return + if this > a, - if this < a, 0 if equal function bnCompareTo(a) { - var r = this.s-a.s; - if(r != 0) return r; - var i = this.t; - r = i-a.t; - if(r != 0) return (this.s<0)?-r:r; - while(--i >= 0) if((r=this[i]-a[i]) != 0) return r; - return 0; + var r = this.s - a.s; + if (r != 0) return r; + var i = this.t; + r = i - a.t; + if (r != 0) return (this.s < 0) ? -r : r; + while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r; + return 0; } // returns bit length of the integer x function nbits(x) { - var r = 1, t; - if((t=x>>>16) != 0) { x = t; r += 16; } - if((t=x>>8) != 0) { x = t; r += 8; } - if((t=x>>4) != 0) { x = t; r += 4; } - if((t=x>>2) != 0) { x = t; r += 2; } - if((t=x>>1) != 0) { x = t; r += 1; } - return r; + var r = 1, t; + if ((t = x >>> 16) != 0) { + x = t; + r += 16; + } + if ((t = x >> 8) != 0) { + x = t; + r += 8; + } + if ((t = x >> 4) != 0) { + x = t; + r += 4; + } + if ((t = x >> 2) != 0) { + x = t; + r += 2; + } + if ((t = x >> 1) != 0) { + x = t; + r += 1; + } + return r; } // (public) return the number of bits in "this" function bnBitLength() { - if(this.t <= 0) return 0; - return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM)); + if (this.t <= 0) return 0; + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)); } // (protected) r = this << n*DB -function bnpDLShiftTo(n,r) { - var i; - for(i = this.t-1; i >= 0; --i) r[i+n] = this[i]; - for(i = n-1; i >= 0; --i) r[i] = 0; - r.t = this.t+n; - r.s = this.s; +function bnpDLShiftTo(n, r) { + var i; + for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i]; + for (i = n - 1; i >= 0; --i) r[i] = 0; + r.t = this.t + n; + r.s = this.s; } // (protected) r = this >> n*DB -function bnpDRShiftTo(n,r) { - for(var i = n; i < this.t; ++i) r[i-n] = this[i]; - r.t = Math.max(this.t-n,0); - r.s = this.s; +function bnpDRShiftTo(n, r) { + for (var i = n; i < this.t; ++i) r[i - n] = this[i]; + r.t = Math.max(this.t - n, 0); + r.s = this.s; } // (protected) r = this << n -function bnpLShiftTo(n,r) { - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<<cbs)-1; - var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i; - for(i = this.t-1; i >= 0; --i) { - r[i+ds+1] = (this[i]>>cbs)|c; - c = (this[i]&bm)<<bs; - } - for(i = ds-1; i >= 0; --i) r[i] = 0; - r[ds] = c; - r.t = this.t+ds+1; - r.s = this.s; - r.clamp(); +function bnpLShiftTo(n, r) { + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << cbs) - 1; + var ds = Math.floor(n / this.DB), c = (this.s << bs) & this.DM, i; + for (i = this.t - 1; i >= 0; --i) { + r[i + ds + 1] = (this[i] >> cbs) | c; + c = (this[i] & bm) << bs; + } + for (i = ds - 1; i >= 0; --i) r[i] = 0; + r[ds] = c; + r.t = this.t + ds + 1; + r.s = this.s; + r.clamp(); } // (protected) r = this >> n -function bnpRShiftTo(n,r) { - r.s = this.s; - var ds = Math.floor(n/this.DB); - if(ds >= this.t) { r.t = 0; return; } - var bs = n%this.DB; - var cbs = this.DB-bs; - var bm = (1<<bs)-1; - r[0] = this[ds]>>bs; - for(var i = ds+1; i < this.t; ++i) { - r[i-ds-1] |= (this[i]&bm)<<cbs; - r[i-ds] = this[i]>>bs; - } - if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs; - r.t = this.t-ds; - r.clamp(); +function bnpRShiftTo(n, r) { + r.s = this.s; + var ds = Math.floor(n / this.DB); + if (ds >= this.t) { + r.t = 0; + return; + } + var bs = n % this.DB; + var cbs = this.DB - bs; + var bm = (1 << bs) - 1; + r[0] = this[ds] >> bs; + for (var i = ds + 1; i < this.t; ++i) { + r[i - ds - 1] |= (this[i] & bm) << cbs; + r[i - ds] = this[i] >> bs; + } + if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs; + r.t = this.t - ds; + r.clamp(); } // (protected) r = this - a -function bnpSubTo(a,r) { - var i = 0, c = 0, m = Math.min(a.t,this.t); - while(i < m) { - c += this[i]-a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - if(a.t < this.t) { - c -= a.s; - while(i < this.t) { - c += this[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c += this.s; - } - else { - c += this.s; - while(i < a.t) { - c -= a[i]; - r[i++] = c&this.DM; - c >>= this.DB; - } - c -= a.s; - } - r.s = (c<0)?-1:0; - if(c < -1) r[i++] = this.DV+c; - else if(c > 0) r[i++] = c; - r.t = i; - r.clamp(); +function bnpSubTo(a, r) { + var i = 0, c = 0, m = Math.min(a.t, this.t); + while (i < m) { + c += this[i] - a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + if (a.t < this.t) { + c -= a.s; + while (i < this.t) { + c += this[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c += this.s; + } + else { + c += this.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & this.DM; + c >>= this.DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) r[i++] = this.DV + c; + else if (c > 0) r[i++] = c; + r.t = i; + r.clamp(); } // (protected) r = this * a, r != this,a (HAC 14.12) // "this" should be the larger one if appropriate. -function bnpMultiplyTo(a,r) { - var x = this.abs(), y = a.abs(); - var i = x.t; - r.t = i+y.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t); - r.s = 0; - r.clamp(); - if(this.s != a.s) BigInteger.ZERO.subTo(r,r); +function bnpMultiplyTo(a, r) { + var x = this.abs(), y = a.abs(); + var i = x.t; + r.t = i + y.t; + while (--i >= 0) r[i] = 0; + for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t); + r.s = 0; + r.clamp(); + if (this.s != a.s) BigInteger.ZERO.subTo(r, r); } // (protected) r = this^2, r != this (HAC 14.16) function bnpSquareTo(r) { - var x = this.abs(); - var i = r.t = 2*x.t; - while(--i >= 0) r[i] = 0; - for(i = 0; i < x.t-1; ++i) { - var c = x.am(i,x[i],r,2*i,0,1); - if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) { - r[i+x.t] -= x.DV; - r[i+x.t+1] = 1; - } - } - if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1); - r.s = 0; - r.clamp(); + var x = this.abs(); + var i = r.t = 2 * x.t; + while (--i >= 0) r[i] = 0; + for (i = 0; i < x.t - 1; ++i) { + var c = x.am(i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1); + r.s = 0; + r.clamp(); } // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) // r != q, this != m. q or r may be null. -function bnpDivRemTo(m,q,r) { - var pm = m.abs(); - if(pm.t <= 0) return; - var pt = this.abs(); - if(pt.t < pm.t) { - if(q != null) q.fromInt(0); - if(r != null) this.copyTo(r); - return; - } - if(r == null) r = nbi(); - var y = nbi(), ts = this.s, ms = m.s; - var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus - if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); } - else { pm.copyTo(y); pt.copyTo(r); } - var ys = y.t; - var y0 = y[ys-1]; - if(y0 == 0) return; - var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0); - var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2; - var i = r.t, j = i-ys, t = (q==null)?nbi():q; - y.dlShiftTo(j,t); - if(r.compareTo(t) >= 0) { - r[r.t++] = 1; - r.subTo(t,r); - } - BigInteger.ONE.dlShiftTo(ys,t); - t.subTo(y,y); // "negative" y so we can replace sub with am later - while(y.t < ys) y[y.t++] = 0; - while(--j >= 0) { - // Estimate quotient digit - var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2); - if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out - y.dlShiftTo(j,t); - r.subTo(t,r); - while(r[i] < --qd) r.subTo(t,r); - } - } - if(q != null) { - r.drShiftTo(ys,q); - if(ts != ms) BigInteger.ZERO.subTo(q,q); - } - r.t = ys; - r.clamp(); - if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder - if(ts < 0) BigInteger.ZERO.subTo(r,r); +function bnpDivRemTo(m, q, r) { + var pm = m.abs(); + if (pm.t <= 0) return; + var pt = this.abs(); + if (pt.t < pm.t) { + if (q != null) q.fromInt(0); + if (r != null) this.copyTo(r); + return; + } + if (r == null) r = nbi(); + var y = nbi(), ts = this.s, ms = m.s; + var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y); + pt.lShiftTo(nsh, r); + } + else { + pm.copyTo(y); + pt.copyTo(r); + } + var ys = y.t; + var y0 = y[ys - 1]; + if (y0 == 0) return; + var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0); + var d1 = this.FV / yt, d2 = (1 << this.F1) / yt, e = 1 << this.F2; + var i = r.t, j = i - ys, t = (q == null) ? nbi() : q; + y.dlShiftTo(j, t); + if (r.compareTo(t) >= 0) { + r[r.t++] = 1; + r.subTo(t, r); + } + BigInteger.ONE.dlShiftTo(ys, t); + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) y[y.t++] = 0; + while (--j >= 0) { + // Estimate quotient digit + var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t); + r.subTo(t, r); + while (r[i] < --qd) r.subTo(t, r); + } + } + if (q != null) { + r.drShiftTo(ys, q); + if (ts != ms) BigInteger.ZERO.subTo(q, q); + } + r.t = ys; + r.clamp(); + if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder + if (ts < 0) BigInteger.ZERO.subTo(r, r); } // (public) this mod a function bnMod(a) { - var r = nbi(); - this.abs().divRemTo(a,null,r); - if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r); - return r; + var r = nbi(); + this.abs().divRemTo(a, null, r); + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r); + return r; } // Modular reduction using "classic" algorithm -function Classic(m) { this.m = m; } +function Classic(m) { + this.m = m; +} + function cConvert(x) { - if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); - else return x; + if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m); + else return x; +} + +function cRevert(x) { + return x; +} + +function cReduce(x) { + x.divRemTo(this.m, null, x); +} + +function cMulTo(x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); +} + +function cSqrTo(x, r) { + x.squareTo(r); + this.reduce(r); } -function cRevert(x) { return x; } -function cReduce(x) { x.divRemTo(this.m,null,x); } -function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } -function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); } Classic.prototype.convert = cConvert; Classic.prototype.revert = cRevert; @@ -512,71 +580,80 @@ Classic.prototype.sqrTo = cSqrTo; // should reduce x and y(2-xy) by m^2 at each step to keep size bounded. // JS multiply "overflows" differently from C/C++, so care is needed here. function bnpInvDigit() { - if(this.t < 1) return 0; - var x = this[0]; - if((x&1) == 0) return 0; - var y = x&3; // y == 1/x mod 2^2 - y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4 - y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8 - y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16 - // last step - calculate inverse mod DV directly; - // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints - y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits - // we really want the negative inverse, and -DV < y < DV - return (y>0)?this.DV-y:-y; + if (this.t < 1) return 0; + var x = this[0]; + if ((x & 1) == 0) return 0; + var y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly; + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y; } // Montgomery reduction function Montgomery(m) { - this.m = m; - this.mp = m.invDigit(); - this.mpl = this.mp&0x7fff; - this.mph = this.mp>>15; - this.um = (1<<(m.DB-15))-1; - this.mt2 = 2*m.t; + this.m = m; + this.mp = m.invDigit(); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (m.DB - 15)) - 1; + this.mt2 = 2 * m.t; } // xR mod m function montConvert(x) { - var r = nbi(); - x.abs().dlShiftTo(this.m.t,r); - r.divRemTo(this.m,null,r); - if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r); - return r; + var r = nbi(); + x.abs().dlShiftTo(this.m.t, r); + r.divRemTo(this.m, null, r); + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r); + return r; } // x/R mod m function montRevert(x) { - var r = nbi(); - x.copyTo(r); - this.reduce(r); - return r; + var r = nbi(); + x.copyTo(r); + this.reduce(r); + return r; } // x = x/R mod m (HAC 14.32) function montReduce(x) { - while(x.t <= this.mt2) // pad x so am has enough room later - x[x.t++] = 0; - for(var i = 0; i < this.m.t; ++i) { - // faster way of calculating u0 = x[i]*mp mod DV - var j = x[i]&0x7fff; - var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM; - // use am to combine the multiply-shift-add into one call - j = i+this.m.t; - x[j] += this.m.am(0,u0,x,i,0,this.m.t); - // propagate carry - while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; } - } - x.clamp(); - x.drShiftTo(this.m.t,x); - if(x.compareTo(this.m) >= 0) x.subTo(this.m,x); + while (x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0; + for (var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i] & 0x7fff; + var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM; + // use am to combine the multiply-shift-add into one call + j = i + this.m.t; + x[j] += this.m.am(0, u0, x, i, 0, this.m.t); + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV; + x[++j]++; + } + } + x.clamp(); + x.drShiftTo(this.m.t, x); + if (x.compareTo(this.m) >= 0) x.subTo(this.m, x); } // r = "x^2/R mod m"; x != r -function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); } +function montSqrTo(x, r) { + x.squareTo(r); + this.reduce(r); +} // r = "xy/R mod m"; x,y != r -function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); } +function montMulTo(x, y, r) { + x.multiplyTo(y, r); + this.reduce(r); +} Montgomery.prototype.convert = montConvert; Montgomery.prototype.revert = montRevert; @@ -585,26 +662,32 @@ Montgomery.prototype.mulTo = montMulTo; Montgomery.prototype.sqrTo = montSqrTo; // (protected) true iff this is even -function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; } +function bnpIsEven() { + return ((this.t > 0) ? (this[0] & 1) : this.s) == 0; +} // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) -function bnpExp(e,z) { - if(e > 0xffffffff || e < 1) return BigInteger.ONE; - var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1; - g.copyTo(r); - while(--i >= 0) { - z.sqrTo(r,r2); - if((e&(1<<i)) > 0) z.mulTo(r2,g,r); - else { var t = r; r = r2; r2 = t; } - } - return z.revert(r); +function bnpExp(e, z) { + if (e > 0xffffffff || e < 1) return BigInteger.ONE; + var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e) - 1; + g.copyTo(r); + while (--i >= 0) { + z.sqrTo(r, r2); + if ((e & (1 << i)) > 0) z.mulTo(r2, g, r); + else { + var t = r; + r = r2; + r2 = t; + } + } + return z.revert(r); } // (public) this^e % m, 0 <= e < 2^32 -function bnModPowInt(e,m) { - var z; - if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); - return this.exp(e,z); +function bnModPowInt(e, m) { + var z; + if (e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m); + return this.exp(e, z); } // protected @@ -642,35 +725,35 @@ BigInteger.ONE = nbv(1); // function Arcfour() { - this.i = 0; - this.j = 0; - this.S = new Array(); + this.i = 0; + this.j = 0; + this.S = new Array(); } // Initialize arcfour context from key, an array of ints, each from [0..255] function ARC4init(key) { - var i, j, t; - for(i = 0; i < 256; ++i) - this.S[i] = i; - j = 0; - for(i = 0; i < 256; ++i) { - j = (j + this.S[i] + key[i % key.length]) & 255; - t = this.S[i]; - this.S[i] = this.S[j]; - this.S[j] = t; - } - this.i = 0; - this.j = 0; + var i, j, t; + for (i = 0; i < 256; ++i) + this.S[i] = i; + j = 0; + for (i = 0; i < 256; ++i) { + j = (j + this.S[i] + key[i % key.length]) & 255; + t = this.S[i]; + this.S[i] = this.S[j]; + this.S[j] = t; + } + this.i = 0; + this.j = 0; } function ARC4next() { - var t; - this.i = (this.i + 1) & 255; - this.j = (this.j + this.S[this.i]) & 255; - t = this.S[this.i]; - this.S[this.i] = this.S[this.j]; - this.S[this.j] = t; - return this.S[(t + this.S[this.i]) & 255]; + var t; + this.i = (this.i + 1) & 255; + this.j = (this.j + this.S[this.i]) & 255; + t = this.S[this.i]; + this.S[this.i] = this.S[this.j]; + this.S[this.j] = t; + return this.S[(t + this.S[this.i]) & 255]; } Arcfour.prototype.init = ARC4init; @@ -678,7 +761,7 @@ Arcfour.prototype.next = ARC4next; // Plug in your RNG constructor here function prng_newstate() { - return new Arcfour(); + return new Arcfour(); } // Pool size must be a multiple of 4 and greater than 32. @@ -702,67 +785,68 @@ var rng_pptr; // Mix in a 32-bit integer into the pool function rng_seed_int(x) { - rng_pool[rng_pptr++] ^= x & 255; - rng_pool[rng_pptr++] ^= (x >> 8) & 255; - rng_pool[rng_pptr++] ^= (x >> 16) & 255; - rng_pool[rng_pptr++] ^= (x >> 24) & 255; - if(rng_pptr >= rng_psize) rng_pptr -= rng_psize; + rng_pool[rng_pptr++] ^= x & 255; + rng_pool[rng_pptr++] ^= (x >> 8) & 255; + rng_pool[rng_pptr++] ^= (x >> 16) & 255; + rng_pool[rng_pptr++] ^= (x >> 24) & 255; + if (rng_pptr >= rng_psize) rng_pptr -= rng_psize; } // Mix in the current time (w/milliseconds) into the pool function rng_seed_time() { - rng_seed_int(new Date().getTime()); + rng_seed_int(new Date().getTime()); } // Initialize the pool with junk if needed. -if(rng_pool == null) { - rng_pool = new Array(); - rng_pptr = 0; - var t; - if(window.crypto && window.crypto.getRandomValues) { - // Use webcrypto if available - var ua = new Uint8Array(32); - window.crypto.getRandomValues(ua); - for(t = 0; t < 32; ++t) - rng_pool[rng_pptr++] = ua[t]; - } - if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { - // Extract entropy (256 bits) from NS4 RNG if available - var z = window.crypto.random(32); - for(t = 0; t < z.length; ++t) - rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; - } - while(rng_pptr < rng_psize) { // extract some randomness from Math.random() - t = Math.floor(65536 * Math.random()); - rng_pool[rng_pptr++] = t >>> 8; - rng_pool[rng_pptr++] = t & 255; - } - rng_pptr = 0; - rng_seed_time(); - //rng_seed_int(window.screenX); - //rng_seed_int(window.screenY); +if (rng_pool == null) { + rng_pool = new Array(); + rng_pptr = 0; + var t; + if (window.crypto && window.crypto.getRandomValues) { + // Use webcrypto if available + var ua = new Uint8Array(32); + window.crypto.getRandomValues(ua); + for (t = 0; t < 32; ++t) + rng_pool[rng_pptr++] = ua[t]; + } + if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { + // Extract entropy (256 bits) from NS4 RNG if available + var z = window.crypto.random(32); + for (t = 0; t < z.length; ++t) + rng_pool[rng_pptr++] = z.charCodeAt(t) & 255; + } + while (rng_pptr < rng_psize) { // extract some randomness from Math.random() + t = Math.floor(65536 * Math.random()); + rng_pool[rng_pptr++] = t >>> 8; + rng_pool[rng_pptr++] = t & 255; + } + rng_pptr = 0; + rng_seed_time(); + //rng_seed_int(window.screenX); + //rng_seed_int(window.screenY); } function rng_get_byte() { - if(rng_state == null) { - rng_seed_time(); - rng_state = prng_newstate(); - rng_state.init(rng_pool); - for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) - rng_pool[rng_pptr] = 0; - rng_pptr = 0; - //rng_pool = null; - } - // TODO: allow reseeding after first request - return rng_state.next(); + if (rng_state == null) { + rng_seed_time(); + rng_state = prng_newstate(); + rng_state.init(rng_pool); + for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr) + rng_pool[rng_pptr] = 0; + rng_pptr = 0; + //rng_pool = null; + } + // TODO: allow reseeding after first request + return rng_state.next(); } function rng_get_bytes(ba) { - var i; - for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); + var i; + for (i = 0; i < ba.length; ++i) ba[i] = rng_get_byte(); } -function SecureRandom() {} +function SecureRandom() { +} SecureRandom.prototype.nextBytes = rng_get_bytes; @@ -775,98 +859,98 @@ SecureRandom.prototype.nextBytes = rng_get_bytes; // Version 1.1: support utf-8 encoding in pkcs1pad2 // convert a (hex) string to a bignum object -function parseBigInt(str,r) { - return new BigInteger(str,r); +function parseBigInt(str, r) { + return new BigInteger(str, r); } -function linebrk(s,n) { - var ret = ""; - var i = 0; - while(i + n < s.length) { - ret += s.substring(i,i+n) + "\n"; - i += n; - } - return ret + s.substring(i,s.length); +function linebrk(s, n) { + var ret = ""; + var i = 0; + while (i + n < s.length) { + ret += s.substring(i, i + n) + "\n"; + i += n; + } + return ret + s.substring(i, s.length); } function byte2Hex(b) { - if(b < 0x10) - return "0" + b.toString(16); - else - return b.toString(16); + if (b < 0x10) + return "0" + b.toString(16); + else + return b.toString(16); } // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint -function pkcs1pad2(s,n) { - if(n < s.length + 11) { // TODO: fix for utf-8 - alert("Message too long for RSA"); - return null; - } - var ba = new Array(); - var i = s.length - 1; - while(i >= 0 && n > 0) { - var c = s.charCodeAt(i--); - if(c < 128) { // encode using utf-8 - ba[--n] = c; - } - else if((c > 127) && (c < 2048)) { - ba[--n] = (c & 63) | 128; - ba[--n] = (c >> 6) | 192; - } - else { - ba[--n] = (c & 63) | 128; - ba[--n] = ((c >> 6) & 63) | 128; - ba[--n] = (c >> 12) | 224; - } - } - ba[--n] = 0; - var rng = new SecureRandom(); - var x = new Array(); - while(n > 2) { // random non-zero pad - x[0] = 0; - while(x[0] == 0) rng.nextBytes(x); - ba[--n] = x[0]; - } - ba[--n] = 2; - ba[--n] = 0; - return new BigInteger(ba); +function pkcs1pad2(s, n) { + if (n < s.length + 11) { // TODO: fix for utf-8 + alert("Message too long for RSA"); + return null; + } + var ba = new Array(); + var i = s.length - 1; + while (i >= 0 && n > 0) { + var c = s.charCodeAt(i--); + if (c < 128) { // encode using utf-8 + ba[--n] = c; + } + else if ((c > 127) && (c < 2048)) { + ba[--n] = (c & 63) | 128; + ba[--n] = (c >> 6) | 192; + } + else { + ba[--n] = (c & 63) | 128; + ba[--n] = ((c >> 6) & 63) | 128; + ba[--n] = (c >> 12) | 224; + } + } + ba[--n] = 0; + var rng = new SecureRandom(); + var x = new Array(); + while (n > 2) { // random non-zero pad + x[0] = 0; + while (x[0] == 0) rng.nextBytes(x); + ba[--n] = x[0]; + } + ba[--n] = 2; + ba[--n] = 0; + return new BigInteger(ba); } // "empty" RSA key constructor function RSAKey() { - this.n = null; - this.e = 0; - this.d = null; - this.p = null; - this.q = null; - this.dmp1 = null; - this.dmq1 = null; - this.coeff = null; + this.n = null; + this.e = 0; + this.d = null; + this.p = null; + this.q = null; + this.dmp1 = null; + this.dmq1 = null; + this.coeff = null; } // Set the public key fields N and e from hex strings -function RSASetPublic(N,E) { - if(N != null && E != null && N.length > 0 && E.length > 0) { - this.n = parseBigInt(N,16); - this.e = parseInt(E,16); - } - else - alert("Invalid RSA public key"); +function RSASetPublic(N, E) { + if (N != null && E != null && N.length > 0 && E.length > 0) { + this.n = parseBigInt(N, 16); + this.e = parseInt(E, 16); + } + else + alert("Invalid RSA public key"); } // Perform raw public operation on "x": return x^e (mod n) function RSADoPublic(x) { - return x.modPowInt(this.e, this.n); + return x.modPowInt(this.e, this.n); } // Return the PKCS#1 RSA encryption of "text" as an even-length hex string function RSAEncrypt(text) { - var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3); - if(m == null) return null; - var c = this.doPublic(m); - if(c == null) return null; - var h = c.toString(16); - if((h.length & 1) == 0) return h; else return "0" + h; + var m = pkcs1pad2(text, (this.n.bitLength() + 7) >> 3); + if (m == null) return null; + var c = this.doPublic(m); + if (c == null) return null; + var h = c.toString(16); + if ((h.length & 1) == 0) return h; else return "0" + h; } // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js index 409bc9c41492e4dad8c5784604c62245ddb2681b..43a97a54b14f54e9786f4dbfc9060fb9a8cf01a8 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js @@ -5,126 +5,126 @@ * Inspired by https://github.com/Gnodiah/ckeditor-autolink */ CKEDITOR.plugins.add('autolinking', { - init: function(editor) { - var spaceChar = 32, enterChar = 13, tabChar = 9, fillChar = ' '; - var isFillChar = function (node, isInStart) { - return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '' ) + ' '), '').length; - }; - var isBodyTag = function (node) { - return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body'; - }; - var isAnchorTag = function (node) { - return node && node.nodeType == 1 && node.tagName.toLowerCase() === 'a'; - }; - var html = function (str) { - return str ? str.replace(/&((g|l|quo)t|amp|#39);/g, function (m) { - return { - '<':'<', - '&':'&', - '"':'"', - '>':'>', - ''':"'" - }[m] - }) : ''; - }; + init: function(editor) { + var spaceChar = 32, enterChar = 13, tabChar = 9, fillChar = ' '; + var isFillChar = function(node, isInStart) { + return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '') + ' '), '').length; + }; + var isBodyTag = function(node) { + return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body'; + }; + var isAnchorTag = function(node) { + return node && node.nodeType == 1 && node.tagName.toLowerCase() === 'a'; + }; + var html = function(str) { + return str ? str.replace(/&((g|l|quo)t|amp|#39);/g, function(m) { + return { + '<': '<', + '&': '&', + '"': '"', + '>': '>', + ''': "'" + }[m] + }) : ''; + }; - var hasParentAnchorTag = function (node) { - if (node && !isBodyTag(node)) { - while (node) { - if (isBodyTag(node)) { - return false; - } else if (isAnchorTag(node)) { - return true; - } - node = node.parentNode; - } - } - return false; - }; + var hasParentAnchorTag = function(node) { + if (node && !isBodyTag(node)) { + while (node) { + if (isBodyTag(node)) { + return false; + } else if (isAnchorTag(node)) { + return true; + } + node = node.parentNode; + } + } + return false; + }; - editor.on('instanceReady', function() { - editor.autolinking = function(evt) { - var sel = editor.getSelection().getNative(), - range = sel.getRangeAt(0).cloneRange(), - offset, - charCode; + editor.on('instanceReady', function() { + editor.autolinking = function(evt) { + var sel = editor.getSelection().getNative(), + range = sel.getRangeAt(0).cloneRange(), + offset, + charCode; - var start = range.startContainer; - while (start.nodeType == 1 && range.startOffset > 0) { - start = range.startContainer.childNodes[range.startOffset - 1]; - if (!start) break; + var start = range.startContainer; + while (start.nodeType == 1 && range.startOffset > 0) { + start = range.startContainer.childNodes[range.startOffset - 1]; + if (!start) break; - range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length); - range.collapse(true); - start = range.startContainer; - } + range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length); + range.collapse(true); + start = range.startContainer; + } - do { - if (range.startOffset == 0) { - start = range.startContainer.previousSibling; + do { + if (range.startOffset == 0) { + start = range.startContainer.previousSibling; - while (start && start.nodeType == 1) { - if (CKEDITOR.env.gecko && start.firstChild) - start = start.firstChild; - else - start = start.lastChild; - } - if (!start || isFillChar(start)) break; - offset = start.nodeValue.length; - } else { - start = range.startContainer; - offset = range.startOffset; - } - range.setStart(start, offset - 1); - charCode = range.toString().charCodeAt(0); - } while (charCode != 160 && charCode != spaceChar); + while (start && start.nodeType == 1) { + if (CKEDITOR.env.gecko && start.firstChild) + start = start.firstChild; + else + start = start.lastChild; + } + if (!start || isFillChar(start)) break; + offset = start.nodeValue.length; + } else { + start = range.startContainer; + offset = range.startOffset; + } + range.setStart(start, offset - 1); + charCode = range.toString().charCodeAt(0); + } while (charCode != 160 && charCode != spaceChar); - if (range.toString().replace(new RegExp(fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { - while (range.toString().length) { - if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) break; + if (range.toString().replace(new RegExp(fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) { + while (range.toString().length) { + if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) break; - try { - range.setStart(range.startContainer, range.startOffset+1); - } catch (e) { - var startChar = range.startContainer; - while (!(next = startChar.nextSibling)) { - if (isBodyTag(startChar)) { - return; - } - startChar = startChar.parentNode; - } - range.setStart(next, 0); - } - } + try { + range.setStart(range.startContainer, range.startOffset + 1); + } catch (e) { + var startChar = range.startContainer; + while (!(next = startChar.nextSibling)) { + if (isBodyTag(startChar)) { + return; + } + startChar = startChar.parentNode; + } + range.setStart(next, 0); + } + } - if (hasParentAnchorTag(range.startContainer)) { - return; - } + if (hasParentAnchorTag(range.startContainer)) { + return; + } - var a = document.createElement('a'), - href; + var a = document.createElement('a'), + href; - editor.undoManger && editor.undoManger.save(); - a.appendChild(range.extractContents()); - a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, ''); - href = a.getAttribute('href').replace(new RegExp(fillChar,'g'), ''); - href = /^(?:https?:\/\/)/ig.test(href) ? href : 'http://' + href; - a.href = html(href); + editor.undoManger && editor.undoManger.save(); + a.appendChild(range.extractContents()); + a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, ''); + href = a.getAttribute('href').replace(new RegExp(fillChar, 'g'), ''); + href = /^(?:https?:\/\/)/ig.test(href) ? href : 'http://' + href; + a.href = html(href); - range.insertNode(a); - range.setStart(a.nextSibling, 0); - range.collapse(true); - sel.removeAllRanges(); - sel.addRange(range); - editor.undoManger && editor.undoManger.save(); - } - }; + range.insertNode(a); + range.setStart(a.nextSibling, 0); + range.collapse(true); + sel.removeAllRanges(); + sel.addRange(range); + editor.undoManger && editor.undoManger.save(); + } + }; - editor.on('key', function(evt) { - if (evt.data.keyCode === spaceChar || evt.data.keyCode === tabChar || evt.data.keyCode === enterChar) { - editor.autolinking(evt); - } - }); - }); - } + editor.on('key', function(evt) { + if (evt.data.keyCode === spaceChar || evt.data.keyCode === tabChar || evt.data.keyCode === enterChar) { + editor.autolinking(evt); + } + }); + }); + } }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js index c09547a75b1956fdd53e6be8be8b730b501abedb..b62ca196efedaf09f460866b44015d29f63b022d 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'af', { - more: 'Meer...' -}); \ No newline at end of file +CKEDITOR.plugins.setLang('quicktable', 'af', { + more: 'Meer...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js index dd31fb8d512d385013a38a7b4832007029fb5e00..15d7ea9a0ca099de484aff01e621da1f0d885a1a 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ar', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ar', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js index 8a571d8745292082eb060143d4f1b8cea058ec07..db3491537817e4de771158dd2e109a9512ed7bde 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'bg', { - more: 'Още...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'bg', { + more: 'Още...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js index 7ad52caac3e319392e8462aaac09aa3ebdbff72d..1f38df622c5bb54d1aab4bc74eba7fbc1c6293db 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'bn', { - more: 'আরও...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'bn', { + more: 'আরও...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js index 2254758c3f61b5080ad785da19a7634955fdcf82..c1c1d7b462e9a1bbe5927da3994118a121158897 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'bs', { - more: 'ViÅ¡e...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'bs', { + more: 'ViÅ¡e...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js index 535f8c383ad2069c50a496bf5ab1c6166ee02ae3..32b03e164e53bf4134013c9fd5ff6db879bc29bf 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ca', { - more: 'Més...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ca', { + more: 'Més...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js index 39a11fab0d309ce255bc56d00bc25b5310b415a2..6b111cb93351a7d0dacfa920e19589bbb3d9c8d8 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'cs', { - more: 'VÃce...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'cs', { + more: 'VÃce...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js index 337bfa1bea57ef4f2133ebf3afcbc562133d69e8..2b5e968fe56bbc5239d70a7730cfa10414545a2b 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'cy', { - more: 'Mwy...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'cy', { + more: 'Mwy...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js index d10c3ce308c17a25e2a31aeb92925ae84d3e3e00..46979974f3361c320bfae380369a52d46ec28cd2 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'da', { - more: 'Flere...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'da', { + more: 'Flere...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js index 0bfba045f0266cc1117ae62e3210d9f14f1ee8c9..4fa1cb34afa6ca8687e02a9166044472d335c01a 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'de', { - more: 'Mehr...' -}); \ No newline at end of file +CKEDITOR.plugins.setLang('quicktable', 'de', { + more: 'Mehr...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js index be6eef1a014841cce5dc7f39e5026ca12f19f4b2..d63aadd94b98393470687dd98b2d5a8877d9a48b 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'el', { - more: 'ΠεÏισσότεÏα...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'el', { + more: 'ΠεÏισσότεÏα...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js index df0052571b99a2f4794f1cb67bfb1f4d68322374..ffa8eebf85343582ffd6e68e2e2b79f4e0c96e88 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'en-au', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'en-au', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js index e796c59528602153658228ec65238703965f121c..09d3a3303f0df718d9a4332d4c3752e31ee8f353 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'en-ca', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'en-ca', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js index e6aa66b669a3cd8c365c358c13ed74b6306e540f..2b5d97511cabc30d754e3c0345614b4e71591f78 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'en-gb', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'en-gb', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js index 8ffbf411b6c58784cff40ea3c421d57ee6470c27..f7fc9e78aeff41cfdf598d522642ec46d5499013 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'en', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'en', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js index 618bc2ba6b4319609c32496ee670e2599419ad3e..436aa36c6d563ad2375e95479362fef4a234f663 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'eo', { - more: 'Pli...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'eo', { + more: 'Pli...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js index d3771d453ce207084a1bf55c22953d056a93f29a..87f00d36c415db1b0a055a039c9428527f1087e0 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'es', { - more: 'Más...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'es', { + more: 'Más...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js index 6dc2712bc4f97a107ce4a0c9f49588156bf16fa3..9eeaac53e4c5c18c47a634114dd94f0db7018061 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'et', { - more: 'Rohkem...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'et', { + more: 'Rohkem...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js index b99b2fc0118208cdf05101cbc4ca8cff8c56dabc..637cd59a50a17f5f9214c9bcd6839b22cda24afa 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'eu', { - more: 'Gehiago...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'eu', { + more: 'Gehiago...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js index b4bf3696ea7a386cf77dc8775efef52d1b663e9f..335bee6a71c3e4b41f22457eeefeab5f5f6faa06 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'fa', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'fa', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js index 36cc0bef6a02f777e8d9295e715eff20469c9a97..78ebe8045304c27e818fdfb8028cb89646e0b8e6 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'fi', { - more: 'Lisää...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'fi', { + more: 'Lisää...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js index 7ce2604056acbc9997e8a549f840ec0fa5732526..7d95e5a9f10900445929dbeeb45a484537ce50e5 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'fo', { - more: 'Fleiri...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'fo', { + more: 'Fleiri...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js index 6f5f44bc8319e5a80b3f5496c9f2f4c43ef8a725..042c8317e52354f016e9de3bb7a61b5c6d50cc27 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'fr-ca', { - more: 'Plus...' +CKEDITOR.plugins.setLang('quicktable', 'fr-ca', { + more: 'Plus...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js index b5c4dff0ddf6e10f018ae6cd28c71fcf52dc2067..293e065a6611e712378a2e88e8220431d304cb30 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'fr', { - more: 'Plus...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'fr', { + more: 'Plus...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js index 7f53d09a7e49fd715882b1ebed8933a3c9b69cf6..bc61925270577efa1ade4c3139deac1b8d1a330c 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'gl', { - more: 'Máis...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'gl', { + more: 'Máis...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js index 9fe93d49ead9c3eb850ee4eee6e3f2a6d104adbd..5cdc776e91ecf1247ac59707342d8338eb3637ab 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'gu', { - more: 'ઔર...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'gu', { + more: 'ઔર...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js index 9027aaecc00022ce05055255d1e04962323b220d..54820070712e863f56aefc87a1852364d5148bfd 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'he', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'he', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js index 7f2284bcee8f07f7161ada386afca391334278a4..730e41b10505f301832c9477a82fdb042a0422d6 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'hi', { - more: 'और...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'hi', { + more: 'और...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js index 020820207260beb1542954f854b890ee83b76d4f..c7cad9c1c0d015b364459bcb80ef10bdd584497a 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'hr', { - more: 'ViÅ¡e...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'hr', { + more: 'ViÅ¡e...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js index 4113694c44d2c7b6fd99a4d56b07c6f4f98fe255..053530ecd7297ab9e6449469e2cb6f3162319ceb 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'hu', { - more: 'További...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'hu', { + more: 'További...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js index 25c9dcc845e2c4c109c80e49ebb9bc39abbe85b4..af225faed2d646cceee1ca69448c8516275fe074 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'id', { - more: 'More...' // MISSING -} ); +CKEDITOR.plugins.setLang('quicktable', 'id', { + more: 'More...' // MISSING +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js index a68b85c229facea8e8cc1f8e3e9d58cb65f1bbc7..3b74e768c40e0c870d555fb5e32521db329f3b87 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'is', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'is', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js index 2c971d6a1ce56d8fb9909689d79d3d26e4676365..0fb0976ed9366cb811bf8d6fb1d049ba3f9ca549 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'it', { - more: 'Altri...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'it', { + more: 'Altri...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js index 180129ecd6420f524942c862cfd4792571764574..b25abc6db94884e4d3e838cae68a3ed274f1053c 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ja', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ja', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js index 506c2d7e117adca94f1e1b10f457df44b90cd982..3906577914d06895fc7ae8114a7a5f1e799f8fbe 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ka', { - more: 'მეტი...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ka', { + more: 'მეტი...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js index d959ec17babaf1ea1fd02a35270dff77a7d4f143..0086fae67603a0f3c8466a8fe8659cbb5ca4ef59 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'km', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'km', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js index b8f284e0255e93197c7f92112467c92c36af0085..f20bf6a213c4ed877b5152e0b7226c5e4208db3c 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ko', { - more: 'More...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ko', { + more: 'More...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js index c5c058e1a0e0b462ae81800c9225c551bb589763..48cb3ef6f5228a0dc1260a7214bc22bf22da0a7b 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ku', { - more: 'بیشتر...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ku', { + more: 'بیشتر...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js index 7378735621aa2e69df5471d9b95d910d02ee408d..aeb8fbe90fa16c6931da41e790190f43cf6db750 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'lt', { - more: 'Daugiau...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'lt', { + more: 'Daugiau...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js index 1476f656aa0bf672ae4ad7a31ec9a956f555e02e..fcd4de8da18c04fcbd64a51c6494c8d319149d87 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'lv', { - more: 'PlaÅ¡Äka...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'lv', { + more: 'PlaÅ¡Äka...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js index e3b6727d650f0e100052840106c1a0e4cd540946..bafb9fe616bad4226e2f8f1499833602ba41769e 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'mk', { - more: 'More...' // MISSING +CKEDITOR.plugins.setLang('quicktable', 'mk', { + more: 'More...' // MISSING }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js index 8a8563834f973c91bd4b33b2ff859d75ba2116ef..1ebd42c20e89d7519468f0a10dff9d9ff0cfe5a7 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'mn', { - more: 'ÐÑмÑлт...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'mn', { + more: 'ÐÑмÑлт...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js index 4e5ef758f16f645c07d26d3d3280bcd314ee1ecb..fd2c933acc4f144696e20cd0bf40cceff175f54d 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ms', { - more: 'Lebih...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ms', { + more: 'Lebih...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js index 3bccbab4810d5ea55551fe5148778ddd80f5d3fc..911f52f8cb73bff1979ccc33ad0277cc96500491 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'nb', { - more: 'Flere...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'nb', { + more: 'Flere...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js index ba2d6ffc0b0bc8204043662f3501685298035e7e..b6a2e7a6ea217ce7f2fdd4399f508d0cc805b23d 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'nl', { - more: 'Meer...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'nl', { + more: 'Meer...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js index eb4de1f7be51699fcdb3713c355dc1a3c17b1b47..5cf4c77fa275596e22c2f127aa5d88044d2e45f3 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'no', { - more: 'Flere...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'no', { + more: 'Flere...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js index b92d7fb68b85fe883c025b46c74ba8aadf7fd785..f3b9fb71ff78f849c37dfefe8aae295587460902 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'pl', { - more: 'WiÄ™cej...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'pl', { + more: 'WiÄ™cej...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js index d12595b4691ee55f02ab2d40adcd9bc82865d0d6..8475c5b13e069d62aecd31994cad81898e131d9b 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'pt-br', { - more: 'Mais...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'pt-br', { + more: 'Mais...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js index 9d301095ded6e9ec52155277ba4050497ac3cc48..aaaa44a3ff729fc1c1490f4bf21090982e026a84 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'pt', { - more: 'Mais...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'pt', { + more: 'Mais...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js index 4219d3ac3be742260a1164640fee32f37d2ca133..380f326d0ae097e6bbdb4dc0580e3f686103be8e 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ro', { - more: 'Mai multe...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ro', { + more: 'Mai multe...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js index 87200067a27ea089bb4544f9415ea51dd73d1c19..e7bfceee2494731ba49688f8ac8ad3d8f641191d 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ru', { - more: 'Ещё...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ru', { + more: 'Ещё...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js index b03f7bf377629f158ae906e33eefa1d806dee866..de1d5ccc0d41aecbf22d19b3cc3dfd5c3ebc3650 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'si', { - more: 'More...' // MISSING +CKEDITOR.plugins.setLang('quicktable', 'si', { + more: 'More...' // MISSING }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js index 52912fccbc548b7f882e08d076ee632cda5f514a..5283fcc9a9d4da67f93b0ee1a00e75cec6170a3f 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sk', { - more: 'Viac...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'sk', { + more: 'Viac...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js index 14166c6fb0edb396eadfec3e0ff6e18da3ca6ee6..0e68bd1e894ad7b9cea1db8503b553f80f4e4648 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sl', { - more: 'VeÄ...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'sl', { + more: 'VeÄ...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js index 4d1eb3bedfb52d46da26442b8adc63d0bd84e5bc..dd67d79ee66c8eab9aa5fa41ecfd255642b0ca8a 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sq', { - more: 'Më Shumë...' +CKEDITOR.plugins.setLang('quicktable', 'sq', { + more: 'Më Shumë...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js index 8731c80033a216c99beacef540f0375b965d955b..6f37510503c9d232bbced802c3f12888aab0c110 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sr-latn', { - more: 'ViÅ¡e...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'sr-latn', { + more: 'ViÅ¡e...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js index facee051958b39ce4cc237de05c893181c1081a8..b958a34720086810421535379827c8b119e31b5e 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sr', { - more: 'Више...' +CKEDITOR.plugins.setLang('quicktable', 'sr', { + more: 'Више...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js index 644ac96b95364305c6d2a6f9aba620207b3729b1..40751f4aefef03eecc45c98f8a86ee47558cfefe 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'sv', { - more: 'Fler...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'sv', { + more: 'Fler...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js index 32443498bd2f9cb77a26c4d36c8d6918d208184b..b4acbc339c933cf0b56d59694bff878ca8645c60 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'th', { - more: ' เลืà¸à¸à¸à¸·à¹ˆà¸™à¹†...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'th', { + more: ' เลืà¸à¸à¸à¸·à¹ˆà¸™à¹†...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js index 9f8d0041bb4f4da6acaf82de7719e11d1944ada3..5efb5c520fcf702b8be0ac350b5c82f44755c964 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'tr', { - more: 'DiÄŸer...' -} ); +CKEDITOR.plugins.setLang('quicktable', 'tr', { + more: 'DiÄŸer...' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js index 5a7e888e3f31ea7938f5993f232fedd5821963b5..8574d45dd6b2c10cde1fce711f08a3eb95b8f277 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'tt', { - more: 'Башка' -} ); +CKEDITOR.plugins.setLang('quicktable', 'tt', { + more: 'Башка' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js index 9ea2ef710e4f5974ba8d4fdeb5cf3565976d3443..945fb7e890561271c795c2dedb60567c90dece99 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'ug', { - more: 'ا رەÚ' -} ); +CKEDITOR.plugins.setLang('quicktable', 'ug', { + more: 'ا رەÚ' +}); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js index e487676a866e855b5f39458051bde17f4e408d4c..57b29963a87cf4f36727a9f9df008b986fa5382d 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'uk', { - more: 'більш...' +CKEDITOR.plugins.setLang('quicktable', 'uk', { + more: 'більш...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js index f2e6fc88e69f9c35f4852f6df6b2711b90cf03f9..36d1db5927cb7a340401132799347be11283efad 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'vi', { - more: 'Mà u...' +CKEDITOR.plugins.setLang('quicktable', 'vi', { + more: 'Mà u...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js index 6167d556d20b5bf0f53d37be21b87d0aeee48690..4b8f7d5d79e40c531da5871e910ef0b90b177ad5 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'zh-cn', { - more: '其它...' +CKEDITOR.plugins.setLang('quicktable', 'zh-cn', { + more: '其它...' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js index a986d5ebbb8bcbd02612d8606a05add532d4443a..ca117e22d25df12d8f0772ef1f39371914fab781 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js @@ -2,6 +2,6 @@ Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.md or http://ckeditor.com/license */ -CKEDITOR.plugins.setLang( 'quicktable', 'zh', { - more: '更多' +CKEDITOR.plugins.setLang('quicktable', 'zh', { + more: '更多' }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js index 4c4944c84cbc0d77a8217f3b4905a3059e930462..1918b204b7dcc3a883f6a998de81372c2cdbaf71 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js @@ -6,190 +6,191 @@ * Removed the "more" button * Removed styling / border options that would be set etc. */ -CKEDITOR.plugins.add( 'quicktable', { - requires: 'table,panelbutton,floatpanel', - lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% - afterInit: function( editor ) { - var conf = editor.config, - quickRows = conf.qtRows || 4, - quickColumns = conf.qtColumns || 6, - quickClass = conf.qtClass || '', - quickPreviewSize = conf.qtPreviewSize || '14px', - quickPreviewBorder = conf.qtPreviewBorder || '1px solid #aaa', - quickPreviewBackground = conf.qtPreviewBackground || '#e5e5e5'; - - function makeElement( name ) { - return new CKEDITOR.dom.element( name, editor.document ); - } - - function insertTable( rowCount, columnCount ) { - var table = makeElement( 'table' ); - var tbody = table.append( makeElement( 'tbody' ) ); - - for ( var i = 0; i < rowCount; i++ ) { - var row = tbody.append( makeElement( 'tr' ) ); - for ( var j = 0; j < columnCount; j++ ) { - var cell = row.append( makeElement( 'td' ) ); - cell.appendBogus(); - } - } - - table.setAttribute( 'class', quickClass ); - editor.insertElement( table ); - - // Fire event for showborders plugin (so hidden borders are visible) - editor.fire('removeFormatCleanup', table); - } - - function renderQuickTable(panel) { - var output = []; - - var clickFn = CKEDITOR.tools.addFunction( function( i, j ) { - insertTable( parseInt( i, 10 ) + 1, parseInt( j, 10 ) + 1 ); - panel.hide(); - } ); - - output.push( '<a style="display:block" _cke_focus=1 hidefocus=true href="javascript:void(1)">' + - '<table role="presentation" cellspacing=1 cellpadding=1 style="width: 100%; margin: 0 auto 3px;table-layout:fixed;">' ); - - for ( var i = 0; i < quickRows; i++ ) { - output.push( '<tr>' ); - for ( var j = 0; j < quickColumns; j++ ) { - output.push( '<td style="border: ' + quickPreviewBorder + ';width:'+quickPreviewSize+';height:'+quickPreviewSize+';" data-i="' + i + '" data-j="' + j + '"' + - ' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', i, '\',\'', j, '\'); return false;"' + - '></td>' ); - } - output.push('</tr>'); - } - - output.push( '</table></a>' ); - - return output.join( '' ); - } - - var selection = {row: -1, column: -1}; - function select( label, table, rowCount, columnCount ) { - var rows = table.$.tBodies[0].rows; - for ( var i = 0; i < rows.length; i++ ) { - var cells = rows[i].cells; - for ( var j = 0; j < cells.length; j++ ) { - var cell = cells[j]; - if ( i < rowCount && j < columnCount ) { - cell.style.background = quickPreviewBackground; - } else { - cell.style.background = ''; - } - } - } - selection.row = rowCount - 1; - selection.column = columnCount - 1; - label.setText( rowCount + ' × ' + columnCount + ' ' + editor.lang.table.toolbar ); - } - - editor.ui.add( 'Table', CKEDITOR.UI_PANELBUTTON, { - label: editor.lang.table.toolbar, - command: 'table', - modes: { wysiwyg: 1 }, - editorFocus: 0, - toolbar: 'insert,30', - - caption: null, - table: null, - - panel: { - css: CKEDITOR.skin.getPath( 'editor' ), - attributes: { role: 'listbox', 'aria-label': editor.lang.table.toolbar } - }, - - onBlock: function( panel, block ) { - block.autoSize = true; - block.element.addClass( 'cke_colorblock' ); - - var caption = new CKEDITOR.dom.element( 'div' ); - caption.setStyles( { 'text-align': 'center', 'margin': '3px 0' } ); - block.element.append( caption ); - this.caption = caption; - - var tableWrapper = CKEDITOR.dom.element.createFromHtml( renderQuickTable(panel) ); - this.table = this.addEvents(tableWrapper); - block.element.append( tableWrapper ); - - CKEDITOR.ui.fire( 'ready', this ); - - block.keys = this.assignKeys(block.keys); - }, - - assignKeys: function(keys){ - var rtl = editor.lang.dir == 'rtl'; - keys[ rtl ? 37 : 39 ] = 'next'; // ARROW-RIGHT - keys[ 40 ] = 'next'; // ARROW-DOWN - keys[ 9 ] = 'next'; // TAB - keys[ rtl ? 39 : 37 ] = 'prev'; // ARROW-LEFT - keys[ 38 ] = 'prev'; // ARROW-UP - keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB - keys[ 32 ] = 'click'; // SPACE - return keys; - }, - - addEvents: function(tableWrapper){ - var table = this.table = tableWrapper.getFirst(); - var caption = this.caption; - table.on( 'mouseleave', function( evt ) { - select( caption, table, 1, 1 ); - } ); - table.on( 'mousemove', function( evt ) { - var target = evt.data.getTarget(); - if ( target.getName() == 'td' ) { - var i = parseInt( target.getAttribute( 'data-i' ), 10 ); - var j = parseInt( target.getAttribute( 'data-j' ), 10 ); - select( caption, table, i + 1, j + 1 ); - } - } ); - tableWrapper.on( 'keydown', function( evt ) { - var keystroke = evt.data.getKeystroke(), - row = selection.row, - column = selection.column; - - switch ( keystroke ) { - case 37: // ARROW-LEFT - column--; - break; - case 39: // ARROW-RIGHT - column++; - break; - case 40: // ARROW-DOWN - row++; - break; - case 38: // ARROW-UP - row--; - break; - case 13: // ENTER - case 32: // SPACE - insertTable( row + 1, column + 1 ); - return; - default: - return; - } - - if ( row < 0 || column < 0 ) { - this.panel.hide(); - return; - } - - if ( row > quickRows - 1 || column > quickColumns - 1 ) { - editor.execCommand( 'table' ); - } - select( caption, table, row + 1, column + 1 ); - evt.data.preventDefault(); - evt.data.stopPropagation(); - }); - - return table; - }, - - onOpen: function() { - select( this.caption, this.table, 1, 1 ); - } - } ); - } +CKEDITOR.plugins.add('quicktable', { + requires: 'table,panelbutton,floatpanel', + lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE% + afterInit: function(editor) { + var conf = editor.config, + quickRows = conf.qtRows || 4, + quickColumns = conf.qtColumns || 6, + quickClass = conf.qtClass || '', + quickPreviewSize = conf.qtPreviewSize || '14px', + quickPreviewBorder = conf.qtPreviewBorder || '1px solid #aaa', + quickPreviewBackground = conf.qtPreviewBackground || '#e5e5e5'; + + function makeElement(name) { + return new CKEDITOR.dom.element(name, editor.document); + } + + function insertTable(rowCount, columnCount) { + var table = makeElement('table'); + var tbody = table.append(makeElement('tbody')); + + for (var i = 0; i < rowCount; i++) { + var row = tbody.append(makeElement('tr')); + for (var j = 0; j < columnCount; j++) { + var cell = row.append(makeElement('td')); + cell.appendBogus(); + } + } + + table.setAttribute('class', quickClass); + editor.insertElement(table); + + // Fire event for showborders plugin (so hidden borders are visible) + editor.fire('removeFormatCleanup', table); + } + + function renderQuickTable(panel) { + var output = []; + + var clickFn = CKEDITOR.tools.addFunction(function(i, j) { + insertTable(parseInt(i, 10) + 1, parseInt(j, 10) + 1); + panel.hide(); + }); + + output.push('<a style="display:block" _cke_focus=1 hidefocus=true href="javascript:void(1)">' + + '<table role="presentation" cellspacing=1 cellpadding=1 style="width: 100%; margin: 0 auto 3px;table-layout:fixed;">'); + + for (var i = 0; i < quickRows; i++) { + output.push('<tr>'); + for (var j = 0; j < quickColumns; j++) { + output.push('<td style="border: ' + quickPreviewBorder + ';width:' + quickPreviewSize + ';height:' + quickPreviewSize + ';" data-i="' + i + '" data-j="' + j + '"' + + ' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', i, '\',\'', j, '\'); return false;"' + + '></td>'); + } + output.push('</tr>'); + } + + output.push('</table></a>'); + + return output.join(''); + } + + var selection = {row: -1, column: -1}; + + function select(label, table, rowCount, columnCount) { + var rows = table.$.tBodies[0].rows; + for (var i = 0; i < rows.length; i++) { + var cells = rows[i].cells; + for (var j = 0; j < cells.length; j++) { + var cell = cells[j]; + if (i < rowCount && j < columnCount) { + cell.style.background = quickPreviewBackground; + } else { + cell.style.background = ''; + } + } + } + selection.row = rowCount - 1; + selection.column = columnCount - 1; + label.setText(rowCount + ' × ' + columnCount + ' ' + editor.lang.table.toolbar); + } + + editor.ui.add('Table', CKEDITOR.UI_PANELBUTTON, { + label: editor.lang.table.toolbar, + command: 'table', + modes: {wysiwyg: 1}, + editorFocus: 0, + toolbar: 'insert,30', + + caption: null, + table: null, + + panel: { + css: CKEDITOR.skin.getPath('editor'), + attributes: {role: 'listbox', 'aria-label': editor.lang.table.toolbar} + }, + + onBlock: function(panel, block) { + block.autoSize = true; + block.element.addClass('cke_colorblock'); + + var caption = new CKEDITOR.dom.element('div'); + caption.setStyles({'text-align': 'center', 'margin': '3px 0'}); + block.element.append(caption); + this.caption = caption; + + var tableWrapper = CKEDITOR.dom.element.createFromHtml(renderQuickTable(panel)); + this.table = this.addEvents(tableWrapper); + block.element.append(tableWrapper); + + CKEDITOR.ui.fire('ready', this); + + block.keys = this.assignKeys(block.keys); + }, + + assignKeys: function(keys) { + var rtl = editor.lang.dir == 'rtl'; + keys[rtl ? 37 : 39] = 'next'; // ARROW-RIGHT + keys[40] = 'next'; // ARROW-DOWN + keys[9] = 'next'; // TAB + keys[rtl ? 39 : 37] = 'prev'; // ARROW-LEFT + keys[38] = 'prev'; // ARROW-UP + keys[CKEDITOR.SHIFT + 9] = 'prev'; // SHIFT + TAB + keys[32] = 'click'; // SPACE + return keys; + }, + + addEvents: function(tableWrapper) { + var table = this.table = tableWrapper.getFirst(); + var caption = this.caption; + table.on('mouseleave', function(evt) { + select(caption, table, 1, 1); + }); + table.on('mousemove', function(evt) { + var target = evt.data.getTarget(); + if (target.getName() == 'td') { + var i = parseInt(target.getAttribute('data-i'), 10); + var j = parseInt(target.getAttribute('data-j'), 10); + select(caption, table, i + 1, j + 1); + } + }); + tableWrapper.on('keydown', function(evt) { + var keystroke = evt.data.getKeystroke(), + row = selection.row, + column = selection.column; + + switch (keystroke) { + case 37: // ARROW-LEFT + column--; + break; + case 39: // ARROW-RIGHT + column++; + break; + case 40: // ARROW-DOWN + row++; + break; + case 38: // ARROW-UP + row--; + break; + case 13: // ENTER + case 32: // SPACE + insertTable(row + 1, column + 1); + return; + default: + return; + } + + if (row < 0 || column < 0) { + this.panel.hide(); + return; + } + + if (row > quickRows - 1 || column > quickColumns - 1) { + editor.execCommand('table'); + } + select(caption, table, row + 1, column + 1); + evt.data.preventDefault(); + evt.data.stopPropagation(); + }); + + return table; + }, + + onOpen: function() { + select(this.caption, this.table, 1, 1); + } + }); + } }); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js index 0c338bbd1b6d23bd5c77c16fc75157194e01271a..5cfa2e494641cb9e1ba151bdd5e0e6ca4f34f26a 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js @@ -13,141 +13,141 @@ 'use strict'; -(function () { - - CKEDITOR.plugins.add('typo3link', { - elementBrowser: null, - init: function (editor) { - var allowedAttributes = ['!href', 'title', 'class', 'target', 'rel'], - required = 'a[href]'; - - var additionalAttributes = getAdditionalAttributes(editor); - if (additionalAttributes.length) { - allowedAttributes.push.apply(allowedAttributes, additionalAttributes); - } - - // Override link command - editor.addCommand('link', { - exec: openLinkBrowser, - allowedContent: 'a[' + allowedAttributes.join(',') + ']', - requiredContent: required - }); - - // Override doubleclick opening default link dialog - editor.on('doubleclick', function (evt) { - var element = CKEDITOR.plugins.link.getSelectedLink(editor) || evt.data.element; - if (!element.isReadOnly() && element.is('a') && element.getAttribute('href')) { - evt.stop(); - openLinkBrowser(editor, element); - } - }, null, null, 30); - - } - }); - - /** - * Open link browser - * - * @param {Object} editor CKEditor object - * @param {Object} element Selected link element - */ - function openLinkBrowser(editor, element) { - var additionalParameters = ''; - - if ($.isEmptyObject(element)) { - element = CKEDITOR.plugins.link.getSelectedLink(editor); - } - if (element) { - additionalParameters = '&curUrl[url]=' + encodeURIComponent(element.getAttribute('href')); - var i = 0, - attributeNames = ["target", "class", "title", "rel"]; - for (i = 0; i < attributeNames.length; ++i) { - if (element.getAttribute(attributeNames[i])) { - additionalParameters += '&curUrl[' + attributeNames[i] + ']='; - additionalParameters += encodeURIComponent(element.getAttribute(attributeNames[i])); - } - } - - var additionalAttributes = getAdditionalAttributes(editor); - for (i = additionalAttributes.length; --i >= 0;) { - if (element.hasAttribute(additionalAttributes[i])) { - additionalParameters += '&curUrl[' + additionalAttributes[i] + ']='; - additionalParameters += encodeURIComponent(element.getAttribute(additionalAttributes[i])); - } - } - } - - openElementBrowser( - editor, - editor.lang.link.toolbar, - TYPO3.settings.Textarea.RTEPopupWindow.height, - makeUrlFromModulePath( - editor, - editor.config.typo3link.routeUrl, - additionalParameters - )); - } - - /** - * Make url from url - * - * @param {Object} editor CKEditor object - * @param {String} routeUrl URL - * @param {String} parameters Additional parameters - * - * @return {String} The url - */ - function makeUrlFromModulePath(editor, routeUrl, parameters) { - - return routeUrl - + (routeUrl.indexOf('?') === -1 ? '?' : '&') - + '&contentsLanguage=' + editor.config.contentsLanguage - + '&editorId=' + editor.id - + (parameters ? parameters : ''); - } - - /** - * Open a window with container iframe - * - * @param {Object} editor The CKEditor instance - * @param {String} title The window title (will be localized here) - * @param {Integer} height The height of the containing iframe - * @param {String} url The url to load ino the iframe - */ - function openElementBrowser(editor, title, height, url) { - require([ - 'jquery', - 'TYPO3/CMS/Backend/Modal' - ], function ($, Modal) { - - Modal.advanced({ - type: Modal.types.iframe, - title: title, - content: url, - size: Modal.sizes.large, - callback: function(currentModal) { - // Add the instance to the iframe itself - currentModal.data('ckeditor', editor); - currentModal.find('.t3js-modal-body') - .addClass('rte-ckeditor-window') - .attr('id', editor.id); - } - }); - }); - } - - /** - * Fetch attributes for the <a> tag which are allowed additionally - * @param {Object} editor The CKEditor instance - * - * @return {Array} registered attributes available for the link - */ - function getAdditionalAttributes(editor) { - if (editor.config.typo3link.additionalAttributes && editor.config.typo3link.additionalAttributes.length) { - return editor.config.typo3link.additionalAttributes; - } else { - return []; - } - } +(function() { + + CKEDITOR.plugins.add('typo3link', { + elementBrowser: null, + init: function(editor) { + var allowedAttributes = ['!href', 'title', 'class', 'target', 'rel'], + required = 'a[href]'; + + var additionalAttributes = getAdditionalAttributes(editor); + if (additionalAttributes.length) { + allowedAttributes.push.apply(allowedAttributes, additionalAttributes); + } + + // Override link command + editor.addCommand('link', { + exec: openLinkBrowser, + allowedContent: 'a[' + allowedAttributes.join(',') + ']', + requiredContent: required + }); + + // Override doubleclick opening default link dialog + editor.on('doubleclick', function(evt) { + var element = CKEDITOR.plugins.link.getSelectedLink(editor) || evt.data.element; + if (!element.isReadOnly() && element.is('a') && element.getAttribute('href')) { + evt.stop(); + openLinkBrowser(editor, element); + } + }, null, null, 30); + + } + }); + + /** + * Open link browser + * + * @param {Object} editor CKEditor object + * @param {Object} element Selected link element + */ + function openLinkBrowser(editor, element) { + var additionalParameters = ''; + + if ($.isEmptyObject(element)) { + element = CKEDITOR.plugins.link.getSelectedLink(editor); + } + if (element) { + additionalParameters = '&curUrl[url]=' + encodeURIComponent(element.getAttribute('href')); + var i = 0, + attributeNames = ["target", "class", "title", "rel"]; + for (i = 0; i < attributeNames.length; ++i) { + if (element.getAttribute(attributeNames[i])) { + additionalParameters += '&curUrl[' + attributeNames[i] + ']='; + additionalParameters += encodeURIComponent(element.getAttribute(attributeNames[i])); + } + } + + var additionalAttributes = getAdditionalAttributes(editor); + for (i = additionalAttributes.length; --i >= 0;) { + if (element.hasAttribute(additionalAttributes[i])) { + additionalParameters += '&curUrl[' + additionalAttributes[i] + ']='; + additionalParameters += encodeURIComponent(element.getAttribute(additionalAttributes[i])); + } + } + } + + openElementBrowser( + editor, + editor.lang.link.toolbar, + TYPO3.settings.Textarea.RTEPopupWindow.height, + makeUrlFromModulePath( + editor, + editor.config.typo3link.routeUrl, + additionalParameters + )); + } + + /** + * Make url from url + * + * @param {Object} editor CKEditor object + * @param {String} routeUrl URL + * @param {String} parameters Additional parameters + * + * @return {String} The url + */ + function makeUrlFromModulePath(editor, routeUrl, parameters) { + + return routeUrl + + (routeUrl.indexOf('?') === -1 ? '?' : '&') + + '&contentsLanguage=' + editor.config.contentsLanguage + + '&editorId=' + editor.id + + (parameters ? parameters : ''); + } + + /** + * Open a window with container iframe + * + * @param {Object} editor The CKEditor instance + * @param {String} title The window title (will be localized here) + * @param {Integer} height The height of the containing iframe + * @param {String} url The url to load ino the iframe + */ + function openElementBrowser(editor, title, height, url) { + require([ + 'jquery', + 'TYPO3/CMS/Backend/Modal' + ], function($, Modal) { + + Modal.advanced({ + type: Modal.types.iframe, + title: title, + content: url, + size: Modal.sizes.large, + callback: function(currentModal) { + // Add the instance to the iframe itself + currentModal.data('ckeditor', editor); + currentModal.find('.t3js-modal-body') + .addClass('rte-ckeditor-window') + .attr('id', editor.id); + } + }); + }); + } + + /** + * Fetch attributes for the <a> tag which are allowed additionally + * @param {Object} editor The CKEditor instance + * + * @return {Array} registered attributes available for the link + */ + function getAdditionalAttributes(editor) { + if (editor.config.typo3link.additionalAttributes && editor.config.typo3link.additionalAttributes.length) { + return editor.config.typo3link.additionalAttributes; + } else { + return []; + } + } })(); diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js index d7eb3f8fd84b297342dd20200242fba0ec95fda0..ff22f335c0bc84a68e87e54af7f22d70e7b47ef5 100644 --- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js +++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js @@ -15,102 +15,102 @@ * Module: TYPO3/CMS/RteCkeditor/RteLinkBrowser * LinkBrowser communication with parent window */ -define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/Modal'], function ($, LinkBrowser, Modal) { - 'use strict'; +define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/Modal'], function($, LinkBrowser, Modal) { + 'use strict'; - /** - * - * @type {{plugin: null, CKEditor: null, siteUrl: string}} - * @exports TYPO3/CMS/RteCkeditor/RteLinkBrowser - */ - var RteLinkBrowser = { - plugin: null, - CKEditor: null, - siteUrl: '' - }; + /** + * + * @type {{plugin: null, CKEditor: null, siteUrl: string}} + * @exports TYPO3/CMS/RteCkeditor/RteLinkBrowser + */ + var RteLinkBrowser = { + plugin: null, + CKEditor: null, + siteUrl: '' + }; - /** - * @param {String} editorId Id of CKEditor - */ - RteLinkBrowser.initialize = function (editorId) { - var editor = Modal.currentModal.data('ckeditor'); - if (typeof editor !== 'undefined') { - RteLinkBrowser.CKEditor = editor; - } else { - var callerWindow; - if (typeof top.TYPO3.Backend !== 'undefined' && typeof top.TYPO3.Backend.ContentContainer.get() !== 'undefined') { - callerWindow = top.TYPO3.Backend.ContentContainer.get(); - } else { - callerWindow = window.parent; - } + /** + * @param {String} editorId Id of CKEditor + */ + RteLinkBrowser.initialize = function(editorId) { + var editor = Modal.currentModal.data('ckeditor'); + if (typeof editor !== 'undefined') { + RteLinkBrowser.CKEditor = editor; + } else { + var callerWindow; + if (typeof top.TYPO3.Backend !== 'undefined' && typeof top.TYPO3.Backend.ContentContainer.get() !== 'undefined') { + callerWindow = top.TYPO3.Backend.ContentContainer.get(); + } else { + callerWindow = window.parent; + } - $.each(callerWindow.CKEDITOR.instances, function (name, editor) { - if (editor.id === editorId) { - RteLinkBrowser.CKEditor = editor; - } - }); - } + $.each(callerWindow.CKEDITOR.instances, function(name, editor) { + if (editor.id === editorId) { + RteLinkBrowser.CKEditor = editor; + } + }); + } - // siteUrl etc are added as data attributes to the body tag - $.extend(RteLinkBrowser, $('body').data()); + // siteUrl etc are added as data attributes to the body tag + $.extend(RteLinkBrowser, $('body').data()); - $('.t3js-class-selector').on('change', function () { - if ($('option:selected', this).data('linkTitle')) { - $('.t3js-linkTitle').val($('option:selected', this).data('linkTitle')); - } - }); + $('.t3js-class-selector').on('change', function() { + if ($('option:selected', this).data('linkTitle')) { + $('.t3js-linkTitle').val($('option:selected', this).data('linkTitle')); + } + }); - $('.t3js-removeCurrentLink').on('click', function (event) { - event.preventDefault(); - RteLinkBrowser.CKEditor.execCommand('unlink'); - Modal.dismiss(); - }); - }; + $('.t3js-removeCurrentLink').on('click', function(event) { + event.preventDefault(); + RteLinkBrowser.CKEditor.execCommand('unlink'); + Modal.dismiss(); + }); + }; - /** - * Store the final link - * - * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>") - */ - LinkBrowser.finalizeFunction = function (link) { + /** + * Store the final link + * + * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>") + */ + LinkBrowser.finalizeFunction = function(link) { - var linkElement = RteLinkBrowser.CKEditor.document.createElement('a'); - var attributes = LinkBrowser.getLinkAttributeValues(); - var params = attributes.params ? attributes.params : ''; + var linkElement = RteLinkBrowser.CKEditor.document.createElement('a'); + var attributes = LinkBrowser.getLinkAttributeValues(); + var params = attributes.params ? attributes.params : ''; - if (attributes.target) { - linkElement.setAttribute('target', attributes.target); - } - if (attributes.class) { - linkElement.setAttribute('class', attributes.class); - } - if (attributes.title) { - linkElement.setAttribute('title', attributes.title); - } - delete attributes.title; - delete attributes.class; - delete attributes.target; - delete attributes.params; + if (attributes.target) { + linkElement.setAttribute('target', attributes.target); + } + if (attributes.class) { + linkElement.setAttribute('class', attributes.class); + } + if (attributes.title) { + linkElement.setAttribute('title', attributes.title); + } + delete attributes.title; + delete attributes.class; + delete attributes.target; + delete attributes.params; - $.each(attributes, function (attrName, attrValue) { - linkElement.setAttribute(attrName, attrValue); - }); + $.each(attributes, function(attrName, attrValue) { + linkElement.setAttribute(attrName, attrValue); + }); - linkElement.setAttribute('href', link + params); + linkElement.setAttribute('href', link + params); - var selection = RteLinkBrowser.CKEditor.getSelection(); - if (selection && selection.getSelectedText() === '') { - selection.selectElement(selection.getStartElement()); - } - if (selection && selection.getSelectedText()) { - linkElement.setText(selection.getSelectedText()); - } else { - linkElement.setText(linkElement.getAttribute('href')); - } - RteLinkBrowser.CKEditor.insertElement(linkElement); + var selection = RteLinkBrowser.CKEditor.getSelection(); + if (selection && selection.getSelectedText() === '') { + selection.selectElement(selection.getStartElement()); + } + if (selection && selection.getSelectedText()) { + linkElement.setText(selection.getSelectedText()); + } else { + linkElement.setText(linkElement.getAttribute('href')); + } + RteLinkBrowser.CKEditor.insertElement(linkElement); - Modal.dismiss(); - }; + Modal.dismiss(); + }; - return RteLinkBrowser; + return RteLinkBrowser; }); diff --git a/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js b/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js index 018f7a39acfd3ec27f45c89035c0863a394f482d..e89f52d064578fda449019a8b20128c7753cde3b 100644 --- a/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js +++ b/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js @@ -16,15 +16,15 @@ * Javascript for adding links for calling the page browser pop up */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - $(document).on('click', '.t3js-pageBrowser', function() { - var $this = $(this), - browserWin = "", - pageUrl = $this.data('url'); + $(document).on('click', '.t3js-pageBrowser', function() { + var $this = $(this), + browserWin = "", + pageUrl = $this.data('url'); - browserWin = window.open(pageUrl,"Typo3WinBrowser","height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1"); - browserWin.focus(); - }); + browserWin = window.open(pageUrl, "Typo3WinBrowser", "height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1"); + browserWin.focus(); + }); }); diff --git a/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js b/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js index 3af13bbab617ae9f29f34a5bd83b57a3f2e125b2..ed6ccfa47e8d5b359944a4a7319f8fd6fefef2fa 100644 --- a/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js +++ b/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js @@ -15,179 +15,178 @@ * Module: TYPO3/CMS/Scheduler/Scheduler */ define(['jquery', - 'TYPO3/CMS/Backend/SplitButtons', - 'datatables' - ], function($, SplitButtons) { - - /** - * - * @type {{}} - * @exports TYPO3/CMS/Scheduler/Scheduler - */ - var Scheduler = { - }; - - var allCheckedStatus = false; - - /** - * This method reacts on changes to the task class - * It switches on or off the relevant extra fields - * - * @param {Object} theSelector - */ - Scheduler.actOnChangedTaskClass = function(theSelector) { - var taskClass = theSelector.val(); - taskClass = taskClass.toLowerCase().replace(/\\/g, '-'); - - // Hide all extra fields - $('.extraFields').hide(); - // Show only relevant extra fields - $('.extra_fields_' + taskClass).show(); - }; - - /** - * This method reacts on changes to the type of a task, i.e. single or recurring - */ - Scheduler.actOnChangedTaskType = function() { - Scheduler.toggleFieldsByTaskType($(this).val()); - }; - - /** - * This method reacts on field changes of all table field for table garbage collection task - * - * @param {Object} theCheckbox - */ - Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables = function(theCheckbox) { - var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays'); - var $taskTableGarbageCollectionTable = $('#task_tableGarbageCollection_table'); - if (theCheckbox.prop('checked')) { - $taskTableGarbageCollectionTable.prop('disabled', true); - $numberOfDays.prop('disabled', true); - } else { - // Get number of days for selected table - var numberOfDays = parseInt($numberOfDays.val()); - if (numberOfDays < 1) { - var selectedTable = $taskTableGarbageCollectionTable.val(); - if (typeof(defaultNumberOfDays[selectedTable]) !== 'undefined') { - numberOfDays = defaultNumberOfDays[selectedTable]; - } - } - - $taskTableGarbageCollectionTable.prop('disabled', false); - if (numberOfDays > 0) { - $numberOfDays.prop('disabled', false); - } - } - }; - - /** - * This methods set the 'number of days' field to the default expire period - * of the selected table - * - * @param {Object} theSelector - */ - Scheduler.actOnChangeSchedulerTableGarbageCollectionTable = function(theSelector) { - var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays'); - if (defaultNumberOfDays[theSelector.val()] > 0) { - $numberOfDays.prop('disabled', false); - $numberOfDays.val(defaultNumberOfDays[theSelector.val()]); - } else { - $numberOfDays.prop('disabled', true); - $numberOfDays.val(0); - } - }; - - /** - * Check or uncheck all checkboxes - * - * @param {Object} theSelector - * @returns {Boolean} - */ - Scheduler.checkOrUncheckAllCheckboxes = function(theSelector) { - theSelector.parents('.tx_scheduler_mod1_table').find(':checkbox').prop('checked', !allCheckedStatus); - allCheckedStatus = !allCheckedStatus; - return false; - }; - - /** - * Toggle the relevant form fields by task type - * - * @param {Integer} taskType - */ - Scheduler.toggleFieldsByTaskType = function(taskType) { - // Single task option = 1, Recurring task option = 2 - taskType = parseInt(taskType); - $('#task_end_col').toggle(taskType === 2); - $('#task_frequency_row').toggle(taskType === 2); - }; - - /** - * Toggle the visibility of task groups - * - * @param {Object} theSelector - */ - Scheduler.toggleTaskGroups = function(theSelector) { - var taskGroup = theSelector.data('task-group-id'); - var taskGroupClass= '.taskGroup_' + taskGroup; - $(taskGroupClass).toggleClass('taskGroup--close'); - }; - - /** - * Registers listeners - */ - Scheduler.initializeEvents = function() { - $('.checkall').on('click', function() { - Scheduler.checkOrUncheckAllCheckboxes($(this)); - }); - - $('#task_class').change(function() { - Scheduler.actOnChangedTaskClass($(this)); - }); - - $('#task_type').change(Scheduler.actOnChangedTaskType); - - $('#task_tableGarbageCollection_allTables').change(function() { - Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables($(this)); - }); - - $('#task_tableGarbageCollection_table').change(function() { - Scheduler.actOnChangeSchedulerTableGarbageCollectionTable($(this)); - }); - - $('.taskGroup').on('click', function() { - Scheduler.toggleTaskGroups($(this)); - }); - - $('table.display').DataTable( { - "paging": false, - "searching": false - } ); - }; - - /** - * Initialize default states - */ - Scheduler.initializeDefaultStates = function() { - var $taskType = $('#task_type'); - if ($taskType.length) { - Scheduler.toggleFieldsByTaskType($taskType.val()); - } - var $taskClass = $('#task_class'); - if ($taskClass.length) { - Scheduler.actOnChangedTaskClass($taskClass); + 'TYPO3/CMS/Backend/SplitButtons', + 'datatables' +], function($, SplitButtons) { + + /** + * + * @type {{}} + * @exports TYPO3/CMS/Scheduler/Scheduler + */ + var Scheduler = {}; + + var allCheckedStatus = false; + + /** + * This method reacts on changes to the task class + * It switches on or off the relevant extra fields + * + * @param {Object} theSelector + */ + Scheduler.actOnChangedTaskClass = function(theSelector) { + var taskClass = theSelector.val(); + taskClass = taskClass.toLowerCase().replace(/\\/g, '-'); + + // Hide all extra fields + $('.extraFields').hide(); + // Show only relevant extra fields + $('.extra_fields_' + taskClass).show(); + }; + + /** + * This method reacts on changes to the type of a task, i.e. single or recurring + */ + Scheduler.actOnChangedTaskType = function() { + Scheduler.toggleFieldsByTaskType($(this).val()); + }; + + /** + * This method reacts on field changes of all table field for table garbage collection task + * + * @param {Object} theCheckbox + */ + Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables = function(theCheckbox) { + var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays'); + var $taskTableGarbageCollectionTable = $('#task_tableGarbageCollection_table'); + if (theCheckbox.prop('checked')) { + $taskTableGarbageCollectionTable.prop('disabled', true); + $numberOfDays.prop('disabled', true); + } else { + // Get number of days for selected table + var numberOfDays = parseInt($numberOfDays.val()); + if (numberOfDays < 1) { + var selectedTable = $taskTableGarbageCollectionTable.val(); + if (typeof(defaultNumberOfDays[selectedTable]) !== 'undefined') { + numberOfDays = defaultNumberOfDays[selectedTable]; } - }; - - $(Scheduler.initializeEvents); - $(Scheduler.initializeDefaultStates); - - SplitButtons.addPreSubmitCallback(function() { - var taskClass = $('#task_class').val(); - taskClass = taskClass.toLowerCase().replace(/\\/g, '-'); - - $('.extraFields').appendTo($('#extraFieldsHidden')); - $('.extra_fields_' + taskClass).appendTo($('#extraFieldsSection')); - }); - - return Scheduler; + } + + $taskTableGarbageCollectionTable.prop('disabled', false); + if (numberOfDays > 0) { + $numberOfDays.prop('disabled', false); + } + } + }; + + /** + * This methods set the 'number of days' field to the default expire period + * of the selected table + * + * @param {Object} theSelector + */ + Scheduler.actOnChangeSchedulerTableGarbageCollectionTable = function(theSelector) { + var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays'); + if (defaultNumberOfDays[theSelector.val()] > 0) { + $numberOfDays.prop('disabled', false); + $numberOfDays.val(defaultNumberOfDays[theSelector.val()]); + } else { + $numberOfDays.prop('disabled', true); + $numberOfDays.val(0); + } + }; + + /** + * Check or uncheck all checkboxes + * + * @param {Object} theSelector + * @returns {Boolean} + */ + Scheduler.checkOrUncheckAllCheckboxes = function(theSelector) { + theSelector.parents('.tx_scheduler_mod1_table').find(':checkbox').prop('checked', !allCheckedStatus); + allCheckedStatus = !allCheckedStatus; + return false; + }; + + /** + * Toggle the relevant form fields by task type + * + * @param {Integer} taskType + */ + Scheduler.toggleFieldsByTaskType = function(taskType) { + // Single task option = 1, Recurring task option = 2 + taskType = parseInt(taskType); + $('#task_end_col').toggle(taskType === 2); + $('#task_frequency_row').toggle(taskType === 2); + }; + + /** + * Toggle the visibility of task groups + * + * @param {Object} theSelector + */ + Scheduler.toggleTaskGroups = function(theSelector) { + var taskGroup = theSelector.data('task-group-id'); + var taskGroupClass = '.taskGroup_' + taskGroup; + $(taskGroupClass).toggleClass('taskGroup--close'); + }; + + /** + * Registers listeners + */ + Scheduler.initializeEvents = function() { + $('.checkall').on('click', function() { + Scheduler.checkOrUncheckAllCheckboxes($(this)); + }); + + $('#task_class').change(function() { + Scheduler.actOnChangedTaskClass($(this)); + }); + + $('#task_type').change(Scheduler.actOnChangedTaskType); + + $('#task_tableGarbageCollection_allTables').change(function() { + Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables($(this)); + }); + + $('#task_tableGarbageCollection_table').change(function() { + Scheduler.actOnChangeSchedulerTableGarbageCollectionTable($(this)); + }); + + $('.taskGroup').on('click', function() { + Scheduler.toggleTaskGroups($(this)); + }); + + $('table.display').DataTable({ + "paging": false, + "searching": false + }); + }; + + /** + * Initialize default states + */ + Scheduler.initializeDefaultStates = function() { + var $taskType = $('#task_type'); + if ($taskType.length) { + Scheduler.toggleFieldsByTaskType($taskType.val()); + } + var $taskClass = $('#task_class'); + if ($taskClass.length) { + Scheduler.actOnChangedTaskClass($taskClass); + } + }; + + $(Scheduler.initializeEvents); + $(Scheduler.initializeDefaultStates); + + SplitButtons.addPreSubmitCallback(function() { + var taskClass = $('#task_class').val(); + taskClass = taskClass.toLowerCase().replace(/\\/g, '-'); + + $('.extraFields').appendTo($('#extraFieldsHidden')); + $('.extra_fields_' + taskClass).appendTo($('#extraFieldsSection')); + }); + + return Scheduler; }); diff --git a/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js b/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js index a679c578ae52ecf65a4fa7870c9f0928337ffcec..eb7598348a072b7e8a824b3b927252d2626fde3b 100644 --- a/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js +++ b/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js @@ -16,20 +16,20 @@ * JavaScript to handle confirm windows in the task center module * @exports TYPO3/CMS/SysAction/ActionTask */ -define(['jquery', 'TYPO3/CMS/Backend/Modal'], function ($, Modal) { - $(function() { - $(document).on('click', '.t3js-confirm-trigger', function(e) { - e.preventDefault(); - var $link = $(this); - Modal.confirm($link.data('title'), $link.data('message')) - .on('confirm.button.ok', function() { - self.location.href = $link.attr('href'); - Modal.currentModal.trigger('modal-dismiss'); - }) - .on('confirm.button.cancel', function() { - Modal.currentModal.trigger('modal-dismiss'); - }); - return false; - }); - }); +define(['jquery', 'TYPO3/CMS/Backend/Modal'], function($, Modal) { + $(function() { + $(document).on('click', '.t3js-confirm-trigger', function(e) { + e.preventDefault(); + var $link = $(this); + Modal.confirm($link.data('title'), $link.data('message')) + .on('confirm.button.ok', function() { + self.location.href = $link.attr('href'); + Modal.currentModal.trigger('modal-dismiss'); + }) + .on('confirm.button.cancel', function() { + Modal.currentModal.trigger('modal-dismiss'); + }); + return false; + }); + }); }); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js index d3a550c098dae3fece365de51886a940815ea272..f9b34f88ae386041a3387a4e193bf39d80857b5b 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js @@ -15,106 +15,106 @@ * Module: TYPO3/CMS/T3editor/Addon/Hint/CompletionResult * Contains the CompletionResult class */ -define(['jquery'], function ($) { - /** - * - * @type {{tsRef: null, tsTreeNode: null}} - * @exports TYPO3/CMS/T3editor/Addon/Hint/CompletionResult - */ - var CompletionResult = { - tsRef: null, - tsTreeNode: null - }; +define(['jquery'], function($) { + /** + * + * @type {{tsRef: null, tsTreeNode: null}} + * @exports TYPO3/CMS/T3editor/Addon/Hint/CompletionResult + */ + var CompletionResult = { + tsRef: null, + tsTreeNode: null + }; - /** - * - * @param {Object} config - * @returns {{tsRef: null, tsTreeNode: null}} - */ - CompletionResult.init = function(config) { - CompletionResult.tsRef = config.tsRef; - CompletionResult.tsTreeNode = config.tsTreeNode; + /** + * + * @param {Object} config + * @returns {{tsRef: null, tsTreeNode: null}} + */ + CompletionResult.init = function(config) { + CompletionResult.tsRef = config.tsRef; + CompletionResult.tsTreeNode = config.tsTreeNode; - return CompletionResult; - }; + return CompletionResult; + }; - /** - * returns the type of the currentTsTreeNode - * - * @returns {*} - */ - CompletionResult.getType = function() { - var val = CompletionResult.tsTreeNode.getValue(); - if (CompletionResult.tsRef.isType(val)) { - return CompletionResult.tsRef.getType(val); - } - return null; - }; + /** + * returns the type of the currentTsTreeNode + * + * @returns {*} + */ + CompletionResult.getType = function() { + var val = CompletionResult.tsTreeNode.getValue(); + if (CompletionResult.tsRef.isType(val)) { + return CompletionResult.tsRef.getType(val); + } + return null; + }; - /** - * returns a list of possible path completions (proposals), which is: - * a list of the children of the current TsTreeNode (= userdefined properties) - * and a list of properties allowed for the current object in the TsRef - * remove all words from list that don't start with the string in filter - * - * @param {String} filter beginning of the words contained in the proposal list - * @return {Array} an Array of Proposals - */ - CompletionResult.getFilteredProposals = function(filter) { - var defined = [], - propArr = [], - childNodes = CompletionResult.tsTreeNode.getChildNodes(), - value = CompletionResult.tsTreeNode.getValue(); + /** + * returns a list of possible path completions (proposals), which is: + * a list of the children of the current TsTreeNode (= userdefined properties) + * and a list of properties allowed for the current object in the TsRef + * remove all words from list that don't start with the string in filter + * + * @param {String} filter beginning of the words contained in the proposal list + * @return {Array} an Array of Proposals + */ + CompletionResult.getFilteredProposals = function(filter) { + var defined = [], + propArr = [], + childNodes = CompletionResult.tsTreeNode.getChildNodes(), + value = CompletionResult.tsTreeNode.getValue(); - // first get the childNodes of the Node (=properties defined by the user) - for (var key in childNodes) { - if (typeof childNodes[key].value !== 'undefined' && childNodes[key].value !== null) { - var propObj = {}; - propObj.word = key; - if (CompletionResult.tsRef.typeHasProperty(value, childNodes[key].name)) { - CompletionResult.tsRef.cssClass = 'definedTSREFProperty'; - propObj.type = childNodes[key].value; - } else { - propObj.cssClass = 'userProperty'; - if (CompletionResult.tsRef.isType(childNodes[key].value)) { - propObj.type = childNodes[key].value; - } else { - propObj.type = ''; - } - } - propArr.push(propObj); - defined[key] = true; - } - } + // first get the childNodes of the Node (=properties defined by the user) + for (var key in childNodes) { + if (typeof childNodes[key].value !== 'undefined' && childNodes[key].value !== null) { + var propObj = {}; + propObj.word = key; + if (CompletionResult.tsRef.typeHasProperty(value, childNodes[key].name)) { + CompletionResult.tsRef.cssClass = 'definedTSREFProperty'; + propObj.type = childNodes[key].value; + } else { + propObj.cssClass = 'userProperty'; + if (CompletionResult.tsRef.isType(childNodes[key].value)) { + propObj.type = childNodes[key].value; + } else { + propObj.type = ''; + } + } + propArr.push(propObj); + defined[key] = true; + } + } - // then get the tsref properties - var props = CompletionResult.tsRef.getPropertiesFromTypeId(CompletionResult.tsTreeNode.getValue()); - for (var key in props) { - // show just the TSREF properties - no properties of the array-prototype and no properties which have been defined by the user - if (typeof props[key].value !== 'undefined' && defined[key] !== true) { - var propObj = {}; - propObj.word = key; - propObj.cssClass = 'undefinedTSREFProperty'; - propObj.type = props[key].value; - propArr.push(propObj); - } - } + // then get the tsref properties + var props = CompletionResult.tsRef.getPropertiesFromTypeId(CompletionResult.tsTreeNode.getValue()); + for (var key in props) { + // show just the TSREF properties - no properties of the array-prototype and no properties which have been defined by the user + if (typeof props[key].value !== 'undefined' && defined[key] !== true) { + var propObj = {}; + propObj.word = key; + propObj.cssClass = 'undefinedTSREFProperty'; + propObj.type = props[key].value; + propArr.push(propObj); + } + } - var result = [], - wordBeginning = ''; + var result = [], + wordBeginning = ''; - for (var i = 0; i < propArr.length; i++) { - if (filter.length === 0) { - result.push(propArr[i]); - continue; - } - wordBeginning = propArr[i].word.substring(0, filter.length); - if (wordBeginning.toLowerCase() === filter.toLowerCase()) { - result.push(propArr[i]); - } - } - return result; - }; + for (var i = 0; i < propArr.length; i++) { + if (filter.length === 0) { + result.push(propArr[i]); + continue; + } + wordBeginning = propArr[i].word.substring(0, filter.length); + if (wordBeginning.toLowerCase() === filter.toLowerCase()) { + result.push(propArr[i]); + } + } + return result; + }; - return CompletionResult; -}); \ No newline at end of file + return CompletionResult; +}); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js index be5a31488a27b48397d013e34bfe03e09863f189..c6c3a2595fd2c2ae5cb4b79398760d44d977d7b3 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js @@ -16,157 +16,157 @@ * Contains the TsCodeCompletion class */ define([ - 'jquery', - 'TYPO3/CMS/T3editor/Addon/Hint/TsRef', - 'TYPO3/CMS/T3editor/Addon/Hint/TsParser', - 'TYPO3/CMS/T3editor/Addon/Hint/CompletionResult' -], function ($, TsRef, TsParser, CompletionResult) { - /** - * - * @type {{tsRef: *, proposals: null, compResult: null, currentCursorPosition: null, extTsObjTree: {}, codemirror: null, parser: null, plugins: string[]}} - * @exports TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion - */ - var TsCodeCompletion = { - tsRef: TsRef, - proposals: null, - compResult: null, - currentCursorPosition: null, - extTsObjTree: {}, - codemirror: null, - parser: null - }; - - /** - * All external templates along the rootline have to be loaded, - * this function retrieves the JSON code by committing a AJAX request - * - * @param {number} id - */ - TsCodeCompletion.loadExtTemplatesAsync = function(id) { - // Ensure id is an integer - id *= 1; - if (isNaN(id) || id === 0) { - return null; - } - $.ajax({ - url: TYPO3.settings.ajaxUrls['t3editor_codecompletion_loadtemplates'], - data: { - pageId: id - }, - dataType: 'json', - success: function(response) { - TsCodeCompletion.extTsObjTree.c = response; - TsCodeCompletion.resolveExtReferencesRec(TsCodeCompletion.extTsObjTree.c); - } - }); - }; - - /** - * Since the references are not resolved server side we have to do it client-side - * Benefit: less loading time due to less data which has to be transmitted - * - * @param {Array} childNodes - */ - TsCodeCompletion.resolveExtReferencesRec = function(childNodes) { - for (var key in childNodes) { - var childNode; - // if the childnode has a value and there is a part of a reference operator ('<') - // and it does not look like a html tag ('>') - if (childNodes[key].v && childNodes[key].v[0] === '<' && childNodes[key].v.indexOf('>') === -1 ) { - var path = $.trim(childNodes[key].v.replace(/</, '')); - // if there are still whitespaces it's no path - if (path.indexOf(' ') === -1) { - childNode = TsCodeCompletion.getExtChildNode(path); - // if the node was found - reference it - if (childNode !== null) { - childNodes[key] = childNode; - } - } - } - // if there was no reference-resolving then we go deeper into the tree - if (!childNode && childNodes[key].c) { - TsCodeCompletion.resolveExtReferencesRec(childNodes[key].c); - } - } - }; - - /** - * Get the child node of given path - * - * @param {String} path - * @returns {Object} - */ - TsCodeCompletion.getExtChildNode = function(path) { - var extTree = TsCodeCompletion.extTsObjTree, - path = path.split('.'), - pathSeg; - - for (var i = 0; i < path.length; i++) { - pathSeg = path[i]; - if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') { - return null; - } - extTree = extTree.c[pathSeg]; - } - return extTree; - }; - - /** - * - * @returns {String} - */ - TsCodeCompletion.getFilter = function() { - var currentLine = TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string; - if (currentLine) { - var filter = currentLine.replace('.', ''); - return filter.replace(/\s/g, ''); - } - return ''; - }; - - /** - * Refreshes the code completion list based on the cursor's position - */ - TsCodeCompletion.refreshCodeCompletion = function(codemirror) { - TsCodeCompletion.codemirror = codemirror; - - // retrieves the node right to the cursor - TsCodeCompletion.currentCursorPosition = TsCodeCompletion.codemirror.doc.getCursor(); - - // the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active - var filter = TsCodeCompletion.getFilter(); - - if (TsCodeCompletion.compResult === null || TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string === '.') { - // TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults()) - var currentTsTreeNode = TsCodeCompletion.parser.buildTsObjTree(TsCodeCompletion.codemirror); - TsCodeCompletion.compResult = CompletionResult.init({ - tsRef: TsRef, - tsTreeNode: currentTsTreeNode - }); - } - - TsCodeCompletion.proposals = TsCodeCompletion.compResult.getFilteredProposals(filter); - - var proposals = []; - for (var i = 0; i < TsCodeCompletion.proposals.length; i++) { - proposals[i] = TsCodeCompletion.proposals[i].word; - } - - return proposals; - }; - - /** - * Resets the completion list - */ - TsCodeCompletion.resetCompList = function() { - TsCodeCompletion.compResult = null; - }; - - $(function() { - TsCodeCompletion.parser = TsParser.init(TsCodeCompletion.tsRef, TsCodeCompletion.extTsObjTree); - TsCodeCompletion.tsRef.loadTsrefAsync(); - TsCodeCompletion.loadExtTemplatesAsync($('input[name="effectivePid"]').first().val()); - }); - - return TsCodeCompletion; + 'jquery', + 'TYPO3/CMS/T3editor/Addon/Hint/TsRef', + 'TYPO3/CMS/T3editor/Addon/Hint/TsParser', + 'TYPO3/CMS/T3editor/Addon/Hint/CompletionResult' +], function($, TsRef, TsParser, CompletionResult) { + /** + * + * @type {{tsRef: *, proposals: null, compResult: null, currentCursorPosition: null, extTsObjTree: {}, codemirror: null, parser: null, plugins: string[]}} + * @exports TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion + */ + var TsCodeCompletion = { + tsRef: TsRef, + proposals: null, + compResult: null, + currentCursorPosition: null, + extTsObjTree: {}, + codemirror: null, + parser: null + }; + + /** + * All external templates along the rootline have to be loaded, + * this function retrieves the JSON code by committing a AJAX request + * + * @param {number} id + */ + TsCodeCompletion.loadExtTemplatesAsync = function(id) { + // Ensure id is an integer + id *= 1; + if (isNaN(id) || id === 0) { + return null; + } + $.ajax({ + url: TYPO3.settings.ajaxUrls['t3editor_codecompletion_loadtemplates'], + data: { + pageId: id + }, + dataType: 'json', + success: function(response) { + TsCodeCompletion.extTsObjTree.c = response; + TsCodeCompletion.resolveExtReferencesRec(TsCodeCompletion.extTsObjTree.c); + } + }); + }; + + /** + * Since the references are not resolved server side we have to do it client-side + * Benefit: less loading time due to less data which has to be transmitted + * + * @param {Array} childNodes + */ + TsCodeCompletion.resolveExtReferencesRec = function(childNodes) { + for (var key in childNodes) { + var childNode; + // if the childnode has a value and there is a part of a reference operator ('<') + // and it does not look like a html tag ('>') + if (childNodes[key].v && childNodes[key].v[0] === '<' && childNodes[key].v.indexOf('>') === -1) { + var path = $.trim(childNodes[key].v.replace(/</, '')); + // if there are still whitespaces it's no path + if (path.indexOf(' ') === -1) { + childNode = TsCodeCompletion.getExtChildNode(path); + // if the node was found - reference it + if (childNode !== null) { + childNodes[key] = childNode; + } + } + } + // if there was no reference-resolving then we go deeper into the tree + if (!childNode && childNodes[key].c) { + TsCodeCompletion.resolveExtReferencesRec(childNodes[key].c); + } + } + }; + + /** + * Get the child node of given path + * + * @param {String} path + * @returns {Object} + */ + TsCodeCompletion.getExtChildNode = function(path) { + var extTree = TsCodeCompletion.extTsObjTree, + path = path.split('.'), + pathSeg; + + for (var i = 0; i < path.length; i++) { + pathSeg = path[i]; + if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') { + return null; + } + extTree = extTree.c[pathSeg]; + } + return extTree; + }; + + /** + * + * @returns {String} + */ + TsCodeCompletion.getFilter = function() { + var currentLine = TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string; + if (currentLine) { + var filter = currentLine.replace('.', ''); + return filter.replace(/\s/g, ''); + } + return ''; + }; + + /** + * Refreshes the code completion list based on the cursor's position + */ + TsCodeCompletion.refreshCodeCompletion = function(codemirror) { + TsCodeCompletion.codemirror = codemirror; + + // retrieves the node right to the cursor + TsCodeCompletion.currentCursorPosition = TsCodeCompletion.codemirror.doc.getCursor(); + + // the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active + var filter = TsCodeCompletion.getFilter(); + + if (TsCodeCompletion.compResult === null || TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string === '.') { + // TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults()) + var currentTsTreeNode = TsCodeCompletion.parser.buildTsObjTree(TsCodeCompletion.codemirror); + TsCodeCompletion.compResult = CompletionResult.init({ + tsRef: TsRef, + tsTreeNode: currentTsTreeNode + }); + } + + TsCodeCompletion.proposals = TsCodeCompletion.compResult.getFilteredProposals(filter); + + var proposals = []; + for (var i = 0; i < TsCodeCompletion.proposals.length; i++) { + proposals[i] = TsCodeCompletion.proposals[i].word; + } + + return proposals; + }; + + /** + * Resets the completion list + */ + TsCodeCompletion.resetCompList = function() { + TsCodeCompletion.compResult = null; + }; + + $(function() { + TsCodeCompletion.parser = TsParser.init(TsCodeCompletion.tsRef, TsCodeCompletion.extTsObjTree); + TsCodeCompletion.tsRef.loadTsrefAsync(); + TsCodeCompletion.loadExtTemplatesAsync($('input[name="effectivePid"]').first().val()); + }); + + return TsCodeCompletion; }); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js index 1ba5181ab1d4ce30c9f62e3b304bfdaef6d4f3a8..44876480ef30d617b7aceec8e0a021b557794a39 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js @@ -16,502 +16,503 @@ * Contains the TsCodeCompletion class */ define([ - 'jquery', 'TYPO3/CMS/T3editor/Addon/Hint/TsRef' -], function ($) { - /** - * - * @type {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}} - * @exports TYPO3/CMS/T3editor/Addon/Hint/TsParser - */ - var TsParser = { - typeId: null, - properties: null, - typeTree: [], - doc: null, - tsRef: null, - extTsObjTree: [], - tsTree: null - }; - - /** - * - * @param {Object} tsRef - * @param {Object} extTsObjTree - * @returns {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}} - */ - TsParser.init = function(tsRef, extTsObjTree) { - TsParser.tsRef = tsRef; - TsParser.extTsObjTree = extTsObjTree; - TsParser.tsTree = new TsParser.treeNode('_L_'); - - return TsParser; - }; - - /** - * - * @param {String} nodeName - */ - TsParser.treeNode = function(nodeName) { - this.name = nodeName; - this.childNodes = []; - this.extPath = ''; - this.value = ''; - this.isExternal = false; - - /** - * Returns local properties and the properties of the external templates - * - * @return {Array} - */ - this.getChildNodes = function() { - var node = this.getExtNode(); - if (node !== null && typeof node.c === 'object') { - for (key in node.c) { - var tn = new TsParser.treeNode(key, this.tsObjTree); - tn.global = true; - tn.value = (node.c[key].v)? node.c[key].v : ""; - tn.isExternal = true; - this.childNodes[key] = tn; - } - } - return this.childNodes; - }; - - /** - * Returns the value of a node - * - * @returns {String} - */ - this.getValue = function() { - if (this.value) { - return this.value; - } - var node = this.getExtNode(); - if (node && node.v) { - return node.v; - } - - var type = this.getNodeTypeFromTsref(); - if (type) { - return type; - } - return ''; - }; - - /** - * This method will try to resolve the properties recursively from right - * to left. If the node's value property is not set, it will look for the - * value of its parent node, and if there is a matching childProperty - * (according to the TSREF) it will return the childProperties value. - * If there is no value in the parent node it will go one step further - * and look into the parent node of the parent node,... - * - * @return {String} - */ - this.getNodeTypeFromTsref = function() { - var path = this.extPath.split('.'), - lastSeg = path.pop(); - - // attention: there will be recursive calls if necessary - var parentValue = this.parent.getValue(); - if (parentValue) { - if (TsParser.tsRef.typeHasProperty(parentValue, lastSeg)) { - var type = TsParser.tsRef.getType(parentValue); - return type.properties[lastSeg].value; - } - } - return ''; - }; - - /** - * Will look in the external ts-tree (static templates, templates on other pages) - * if there is a value or childproperties assigned to the current node. - * The method uses the extPath of the current node to navigate to the corresponding - * node in the external tree - * - * @return {Object} - */ - this.getExtNode = function() { - var extTree = TsParser.extTsObjTree, - path, - pathSeg; - - if (this.extPath === '') { - return extTree; - } - path = this.extPath.split('.'); - - for (var i = 0; i < path.length; i++) { - pathSeg = path[i]; - if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') { - return null; - } - extTree = extTree.c[pathSeg]; - } - return extTree; - }; - }; - - /** - * Check if there is an operator in the line and return it - * if there is none, return -1 - * - * @return {(String|Number)} - */ - TsParser.getOperator = function(line) { - var operators = [':=', '=<', '<', '>', '=']; - for (var i = 0; i < operators.length; i++) { - var op = operators[i]; - if (line.indexOf(op) !== -1) { - // check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML) - // we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder" - if ((op === '=<' || op === '<') && line.indexOf('>') > -1) { - // if there is a ">" in the line suppose there's some HTML - return '='; - } - return op; - } - } - return -1; - }; - - /** - * Build the TypoScript object tree - */ - TsParser.buildTsObjTree = function(codemirror) { - TsParser.tsTree = new TsParser.treeNode(''); - TsParser.tsTree.value = 'TLO'; - - function Stack() { - } - Stack.prototype = []; - Stack.prototype.lastElementEquals = function(str) { - return this.length > 0 && this[this.length-1] === str; - }; - - Stack.prototype.popIfLastElementEquals = function(str) { - if (this.lastElementEquals(str)) { - this.pop(); - return true; - } - return false; - }; - - var currentLine = 0, - cursorPosition = codemirror.getCursor(), - line = '', - stack = new Stack(), - prefixes = [], - ignoreLine = false, - insideCondition = false; - - while (currentLine <= cursorPosition.line) { - line = ''; - var tokens = codemirror.getLineTokens(currentLine); - for (var i = 0; i <= tokens.length; ++i) { - if (i < tokens.length && tokens[i].string.length > 0) { - var tokenValue = tokens[i].string; - - if (tokenValue[0] === '#') { - stack.push('#'); - } else if (tokenValue === '(') { - stack.push('('); - } else if (tokenValue[0] === '/' && tokenValue[1] === '*') { - stack.push('/*'); - } else if (tokenValue === '{') { - // TODO: ignore whole block if wrong whitespaces in this line - if (TsParser.getOperator(line) === -1) { - stack.push('{'); - prefixes.push($.trim(line)); - ignoreLine = true; - } - } - // TODO: conditions - // if condition starts -> ignore everything until end of condition - if (tokenValue.search(/^\s*\[.*\]/) !== -1 - && line.search(/\S/) === -1 - && tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) === -1 - && !stack.lastElementEquals('#') - && !stack.lastElementEquals('/*') - && !stack.lastElementEquals('{') - && !stack.lastElementEquals('(') - ) { - insideCondition = true; - ignoreLine = true; - } - - // if end of condition reached - if (line.search(/\S/) === -1 - && !stack.lastElementEquals('#') - && !stack.lastElementEquals('/*') - && !stack.lastElementEquals('(') - && ( - (tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) !== -1 - && !stack.lastElementEquals('{')) - || (tokenValue.search(/^\s*\[(global|GLOBAL)\]/) !== -1) - ) - ) { - insideCondition = false; - ignoreLine = true; - } - - if (tokenValue === ')') { - stack.popIfLastElementEquals('('); - } - if (tokenValue[0] === '*' && tokenValue[1] === '/') { - stack.popIfLastElementEquals('/*'); - ignoreLine = true; - } - if (tokenValue === '}') { - //no characters except whitespace allowed before closing bracket - var trimmedLine = line.replace(/\s/g, ''); - if (trimmedLine === '') { - stack.popIfLastElementEquals('{'); - if (prefixes.length > 0) { - prefixes.pop(); - } - ignoreLine = true; - } - } - if (!stack.lastElementEquals('#')) { - line += tokenValue; - } - } else { - // ignore comments, ... - if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) { - line = $.trim(line); - // check if there is any operator in this line - var op = TsParser.getOperator(line); - if (op !== -1) { - // figure out the position of the operator - var pos = line.indexOf(op); - // the target objectpath should be left to the operator - var path = line.substring(0, pos); - // if we are in between curly brackets: add prefixes to object path - if (prefixes.length > 0) { - path = prefixes.join('.') + '.' + path; - } - // the type or value should be right to the operator - var str = line.substring(pos + op.length, line.length); - path = $.trim(path); - str = $.trim(str); - switch (op) { // set a value or create a new object - case '=': - //ignore if path is empty or contains whitespace - if (path.search(/\s/g) === -1 && path.length > 0) { - TsParser.setTreeNodeValue(path, str); - } - break; - case '=<': // reference to another object in the tree - // resolve relative path - if (prefixes.length > 0 && str.substr(0, 1) === '.') { - str = prefixes.join('.') + str; - } - //ignore if either path or str is empty or contains whitespace - if (path.search(/\s/g) === -1 - && path.length > 0 - && str.search(/\s/g) === -1 - && str.length > 0 - ) { - TsParser.setReference(path, str); - } - break; - case '<': // copy from another object in the tree - // resolve relative path - if (prefixes.length > 0 && str.substr(0, 1) === '.') { - str = prefixes.join('.') + str; - } - //ignore if either path or str is empty or contains whitespace - if (path.search(/\s/g) === -1 - && path.length > 0 - && str.search(/\s/g) === -1 - && str.length > 0 - ) { - TsParser.setCopy(path, str); - } - break; - case '>': // delete object value and properties - TsParser.deleteTreeNodeValue(path); - break; - case ':=': // function operator - // TODO: function-operator - break; - } - } - } - stack.popIfLastElementEquals('#'); - ignoreLine = false; - } - } - currentLine++; - } - // when node at cursorPos is reached: - // save currentLine, currentTsTreeNode and filter if necessary - // if there is a reference or copy operator ('<' or '=<') - // return the treeNode of the path right to the operator, - // else try to build a path from the whole line - if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) { - var i = line.indexOf('<'); - - if (i !== -1) { - var path = line.substring(i+1, line.length); - path = $.trim(path); - if (prefixes.length > 0 && path.substr(0, 1) === '.') { - path = prefixes.join('.') + path; - } - } else { - var path = line; - if (prefixes.length > 0) { - path = prefixes.join('.') + '.' + path; - path = path.replace(/\s/g, ''); - } - } - var lastDot = path.lastIndexOf('.'); - path = path.substring(0, lastDot); - } - return TsParser.getTreeNode(path); - }; - - /** - * Iterates through the object tree, and creates treenodes - * along the path, if necessary - * - * @param {String} path - * @returns {Object} - */ - TsParser.getTreeNode = function(path) { - path = $.trim(path); - if (path.length === 0) { - return TsParser.tsTree; - } - var aPath = path.split('.'); - - var subTree = TsParser.tsTree.childNodes, - pathSeg, - parent = TsParser.tsTree; - - // step through the path from left to right - for (var i = 0; i < aPath.length; i++) { - pathSeg = aPath[i]; - - // if there isn't already a treenode - if (typeof subTree[pathSeg] === 'undefined' || typeof subTree[pathSeg].childNodes === 'undefined') { // if this subpath is not defined in the code - // create a new treenode - subTree[pathSeg] = new TsParser.treeNode(pathSeg); - subTree[pathSeg].parent = parent; - // the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates - var extPath = parent.extPath; - if (extPath) { - extPath += '.'; - } - extPath += pathSeg; - subTree[pathSeg].extPath = extPath; - } - if (i === aPath.length - 1) { - return subTree[pathSeg]; - } - parent = subTree[pathSeg]; - subTree = subTree[pathSeg].childNodes; - } - }; - - /** - * Navigates to the respecting treenode, - * create nodes in the path, if necessary, and sets the value - * - * @param {String} path - * @param {String} value - */ - TsParser.setTreeNodeValue = function(path, value) { - var treeNode = TsParser.getTreeNode(path); - // if we are inside a GIFBUILDER Object - if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "TEXT") { - value = 'GB_TEXT'; - } - if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "IMAGE") { - value = 'GB_IMAGE'; - } - - // just override if it is a real objecttype - if (TsParser.tsRef.isType(value)) { - treeNode.value = value; - } - }; - - /** - * Navigates to the respecting treenode, - * creates nodes if necessary, empties the value and childNodes-Array - * - * @param {String} path - */ - TsParser.deleteTreeNodeValue = function(path) { - var treeNode = TsParser.getTreeNode(path); - // currently the node is not deleted really, it's just not displayed cause value == null - // deleting it would be a cleaner solution - treeNode.value = null; - treeNode.childNodes = {}; - }; - - /** - * Copies a reference of the treeNode specified by path2 - * to the location specified by path1 - * - * @param {String} path1 - * @param {String} path2 - */ - TsParser.setReference = function(path1, path2) { - var path1arr = path1.split('.'), - lastNodeName = path1arr[path1arr.length - 1], - treeNode1 = TsParser.getTreeNode(path1), - treeNode2 = TsParser.getTreeNode(path2); - - if (treeNode1.parent !== null) { - treeNode1.parent.childNodes[lastNodeName] = treeNode2; - } else { - TsParser.tsTree.childNodes[lastNodeName] = treeNode2; - } - }; - - /** - * copies a treeNode specified by path2 - * to the location specified by path1 - * - * @param {String} path1 - * @param {String} path2 - */ - TsParser.setCopy = function(path1, path2) { - this.clone = function(myObj) { - if (typeof myObj !== 'object') { - return myObj; - } - - var myNewObj = {}; - for (var i in myObj) { - // disable recursive cloning for parent object -> copy by reference - if (i !== 'parent') { - if (typeof myObj[i] === 'object') { - myNewObj[i] = this.clone(myObj[i]); - } else { - myNewObj[i] = myObj[i]; - } - } else { - myNewObj.parent = myObj.parent; - } - } - return myNewObj; - }; - - var path1arr = path1.split('.'), - lastNodeName = path1arr[path1arr.length - 1], - treeNode1 = TsParser.getTreeNode(path1), - treeNode2 = TsParser.getTreeNode(path2); - - if (treeNode1.parent !== null) { - treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2); - } else { - TsParser.tsTree.childNodes[lastNodeName] = this.clone(treeNode2); - } - }; - - return TsParser; -}); \ No newline at end of file + 'jquery', 'TYPO3/CMS/T3editor/Addon/Hint/TsRef' +], function($) { + /** + * + * @type {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}} + * @exports TYPO3/CMS/T3editor/Addon/Hint/TsParser + */ + var TsParser = { + typeId: null, + properties: null, + typeTree: [], + doc: null, + tsRef: null, + extTsObjTree: [], + tsTree: null + }; + + /** + * + * @param {Object} tsRef + * @param {Object} extTsObjTree + * @returns {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}} + */ + TsParser.init = function(tsRef, extTsObjTree) { + TsParser.tsRef = tsRef; + TsParser.extTsObjTree = extTsObjTree; + TsParser.tsTree = new TsParser.treeNode('_L_'); + + return TsParser; + }; + + /** + * + * @param {String} nodeName + */ + TsParser.treeNode = function(nodeName) { + this.name = nodeName; + this.childNodes = []; + this.extPath = ''; + this.value = ''; + this.isExternal = false; + + /** + * Returns local properties and the properties of the external templates + * + * @return {Array} + */ + this.getChildNodes = function() { + var node = this.getExtNode(); + if (node !== null && typeof node.c === 'object') { + for (key in node.c) { + var tn = new TsParser.treeNode(key, this.tsObjTree); + tn.global = true; + tn.value = (node.c[key].v) ? node.c[key].v : ""; + tn.isExternal = true; + this.childNodes[key] = tn; + } + } + return this.childNodes; + }; + + /** + * Returns the value of a node + * + * @returns {String} + */ + this.getValue = function() { + if (this.value) { + return this.value; + } + var node = this.getExtNode(); + if (node && node.v) { + return node.v; + } + + var type = this.getNodeTypeFromTsref(); + if (type) { + return type; + } + return ''; + }; + + /** + * This method will try to resolve the properties recursively from right + * to left. If the node's value property is not set, it will look for the + * value of its parent node, and if there is a matching childProperty + * (according to the TSREF) it will return the childProperties value. + * If there is no value in the parent node it will go one step further + * and look into the parent node of the parent node,... + * + * @return {String} + */ + this.getNodeTypeFromTsref = function() { + var path = this.extPath.split('.'), + lastSeg = path.pop(); + + // attention: there will be recursive calls if necessary + var parentValue = this.parent.getValue(); + if (parentValue) { + if (TsParser.tsRef.typeHasProperty(parentValue, lastSeg)) { + var type = TsParser.tsRef.getType(parentValue); + return type.properties[lastSeg].value; + } + } + return ''; + }; + + /** + * Will look in the external ts-tree (static templates, templates on other pages) + * if there is a value or childproperties assigned to the current node. + * The method uses the extPath of the current node to navigate to the corresponding + * node in the external tree + * + * @return {Object} + */ + this.getExtNode = function() { + var extTree = TsParser.extTsObjTree, + path, + pathSeg; + + if (this.extPath === '') { + return extTree; + } + path = this.extPath.split('.'); + + for (var i = 0; i < path.length; i++) { + pathSeg = path[i]; + if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') { + return null; + } + extTree = extTree.c[pathSeg]; + } + return extTree; + }; + }; + + /** + * Check if there is an operator in the line and return it + * if there is none, return -1 + * + * @return {(String|Number)} + */ + TsParser.getOperator = function(line) { + var operators = [':=', '=<', '<', '>', '=']; + for (var i = 0; i < operators.length; i++) { + var op = operators[i]; + if (line.indexOf(op) !== -1) { + // check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML) + // we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder" + if ((op === '=<' || op === '<') && line.indexOf('>') > -1) { + // if there is a ">" in the line suppose there's some HTML + return '='; + } + return op; + } + } + return -1; + }; + + /** + * Build the TypoScript object tree + */ + TsParser.buildTsObjTree = function(codemirror) { + TsParser.tsTree = new TsParser.treeNode(''); + TsParser.tsTree.value = 'TLO'; + + function Stack() { + } + + Stack.prototype = []; + Stack.prototype.lastElementEquals = function(str) { + return this.length > 0 && this[this.length - 1] === str; + }; + + Stack.prototype.popIfLastElementEquals = function(str) { + if (this.lastElementEquals(str)) { + this.pop(); + return true; + } + return false; + }; + + var currentLine = 0, + cursorPosition = codemirror.getCursor(), + line = '', + stack = new Stack(), + prefixes = [], + ignoreLine = false, + insideCondition = false; + + while (currentLine <= cursorPosition.line) { + line = ''; + var tokens = codemirror.getLineTokens(currentLine); + for (var i = 0; i <= tokens.length; ++i) { + if (i < tokens.length && tokens[i].string.length > 0) { + var tokenValue = tokens[i].string; + + if (tokenValue[0] === '#') { + stack.push('#'); + } else if (tokenValue === '(') { + stack.push('('); + } else if (tokenValue[0] === '/' && tokenValue[1] === '*') { + stack.push('/*'); + } else if (tokenValue === '{') { + // TODO: ignore whole block if wrong whitespaces in this line + if (TsParser.getOperator(line) === -1) { + stack.push('{'); + prefixes.push($.trim(line)); + ignoreLine = true; + } + } + // TODO: conditions + // if condition starts -> ignore everything until end of condition + if (tokenValue.search(/^\s*\[.*\]/) !== -1 + && line.search(/\S/) === -1 + && tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) === -1 + && !stack.lastElementEquals('#') + && !stack.lastElementEquals('/*') + && !stack.lastElementEquals('{') + && !stack.lastElementEquals('(') + ) { + insideCondition = true; + ignoreLine = true; + } + + // if end of condition reached + if (line.search(/\S/) === -1 + && !stack.lastElementEquals('#') + && !stack.lastElementEquals('/*') + && !stack.lastElementEquals('(') + && ( + (tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) !== -1 + && !stack.lastElementEquals('{')) + || (tokenValue.search(/^\s*\[(global|GLOBAL)\]/) !== -1) + ) + ) { + insideCondition = false; + ignoreLine = true; + } + + if (tokenValue === ')') { + stack.popIfLastElementEquals('('); + } + if (tokenValue[0] === '*' && tokenValue[1] === '/') { + stack.popIfLastElementEquals('/*'); + ignoreLine = true; + } + if (tokenValue === '}') { + //no characters except whitespace allowed before closing bracket + var trimmedLine = line.replace(/\s/g, ''); + if (trimmedLine === '') { + stack.popIfLastElementEquals('{'); + if (prefixes.length > 0) { + prefixes.pop(); + } + ignoreLine = true; + } + } + if (!stack.lastElementEquals('#')) { + line += tokenValue; + } + } else { + // ignore comments, ... + if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) { + line = $.trim(line); + // check if there is any operator in this line + var op = TsParser.getOperator(line); + if (op !== -1) { + // figure out the position of the operator + var pos = line.indexOf(op); + // the target objectpath should be left to the operator + var path = line.substring(0, pos); + // if we are in between curly brackets: add prefixes to object path + if (prefixes.length > 0) { + path = prefixes.join('.') + '.' + path; + } + // the type or value should be right to the operator + var str = line.substring(pos + op.length, line.length); + path = $.trim(path); + str = $.trim(str); + switch (op) { // set a value or create a new object + case '=': + //ignore if path is empty or contains whitespace + if (path.search(/\s/g) === -1 && path.length > 0) { + TsParser.setTreeNodeValue(path, str); + } + break; + case '=<': // reference to another object in the tree + // resolve relative path + if (prefixes.length > 0 && str.substr(0, 1) === '.') { + str = prefixes.join('.') + str; + } + //ignore if either path or str is empty or contains whitespace + if (path.search(/\s/g) === -1 + && path.length > 0 + && str.search(/\s/g) === -1 + && str.length > 0 + ) { + TsParser.setReference(path, str); + } + break; + case '<': // copy from another object in the tree + // resolve relative path + if (prefixes.length > 0 && str.substr(0, 1) === '.') { + str = prefixes.join('.') + str; + } + //ignore if either path or str is empty or contains whitespace + if (path.search(/\s/g) === -1 + && path.length > 0 + && str.search(/\s/g) === -1 + && str.length > 0 + ) { + TsParser.setCopy(path, str); + } + break; + case '>': // delete object value and properties + TsParser.deleteTreeNodeValue(path); + break; + case ':=': // function operator + // TODO: function-operator + break; + } + } + } + stack.popIfLastElementEquals('#'); + ignoreLine = false; + } + } + currentLine++; + } + // when node at cursorPos is reached: + // save currentLine, currentTsTreeNode and filter if necessary + // if there is a reference or copy operator ('<' or '=<') + // return the treeNode of the path right to the operator, + // else try to build a path from the whole line + if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) { + var i = line.indexOf('<'); + + if (i !== -1) { + var path = line.substring(i + 1, line.length); + path = $.trim(path); + if (prefixes.length > 0 && path.substr(0, 1) === '.') { + path = prefixes.join('.') + path; + } + } else { + var path = line; + if (prefixes.length > 0) { + path = prefixes.join('.') + '.' + path; + path = path.replace(/\s/g, ''); + } + } + var lastDot = path.lastIndexOf('.'); + path = path.substring(0, lastDot); + } + return TsParser.getTreeNode(path); + }; + + /** + * Iterates through the object tree, and creates treenodes + * along the path, if necessary + * + * @param {String} path + * @returns {Object} + */ + TsParser.getTreeNode = function(path) { + path = $.trim(path); + if (path.length === 0) { + return TsParser.tsTree; + } + var aPath = path.split('.'); + + var subTree = TsParser.tsTree.childNodes, + pathSeg, + parent = TsParser.tsTree; + + // step through the path from left to right + for (var i = 0; i < aPath.length; i++) { + pathSeg = aPath[i]; + + // if there isn't already a treenode + if (typeof subTree[pathSeg] === 'undefined' || typeof subTree[pathSeg].childNodes === 'undefined') { // if this subpath is not defined in the code + // create a new treenode + subTree[pathSeg] = new TsParser.treeNode(pathSeg); + subTree[pathSeg].parent = parent; + // the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates + var extPath = parent.extPath; + if (extPath) { + extPath += '.'; + } + extPath += pathSeg; + subTree[pathSeg].extPath = extPath; + } + if (i === aPath.length - 1) { + return subTree[pathSeg]; + } + parent = subTree[pathSeg]; + subTree = subTree[pathSeg].childNodes; + } + }; + + /** + * Navigates to the respecting treenode, + * create nodes in the path, if necessary, and sets the value + * + * @param {String} path + * @param {String} value + */ + TsParser.setTreeNodeValue = function(path, value) { + var treeNode = TsParser.getTreeNode(path); + // if we are inside a GIFBUILDER Object + if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "TEXT") { + value = 'GB_TEXT'; + } + if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "IMAGE") { + value = 'GB_IMAGE'; + } + + // just override if it is a real objecttype + if (TsParser.tsRef.isType(value)) { + treeNode.value = value; + } + }; + + /** + * Navigates to the respecting treenode, + * creates nodes if necessary, empties the value and childNodes-Array + * + * @param {String} path + */ + TsParser.deleteTreeNodeValue = function(path) { + var treeNode = TsParser.getTreeNode(path); + // currently the node is not deleted really, it's just not displayed cause value == null + // deleting it would be a cleaner solution + treeNode.value = null; + treeNode.childNodes = {}; + }; + + /** + * Copies a reference of the treeNode specified by path2 + * to the location specified by path1 + * + * @param {String} path1 + * @param {String} path2 + */ + TsParser.setReference = function(path1, path2) { + var path1arr = path1.split('.'), + lastNodeName = path1arr[path1arr.length - 1], + treeNode1 = TsParser.getTreeNode(path1), + treeNode2 = TsParser.getTreeNode(path2); + + if (treeNode1.parent !== null) { + treeNode1.parent.childNodes[lastNodeName] = treeNode2; + } else { + TsParser.tsTree.childNodes[lastNodeName] = treeNode2; + } + }; + + /** + * copies a treeNode specified by path2 + * to the location specified by path1 + * + * @param {String} path1 + * @param {String} path2 + */ + TsParser.setCopy = function(path1, path2) { + this.clone = function(myObj) { + if (typeof myObj !== 'object') { + return myObj; + } + + var myNewObj = {}; + for (var i in myObj) { + // disable recursive cloning for parent object -> copy by reference + if (i !== 'parent') { + if (typeof myObj[i] === 'object') { + myNewObj[i] = this.clone(myObj[i]); + } else { + myNewObj[i] = myObj[i]; + } + } else { + myNewObj.parent = myObj.parent; + } + } + return myNewObj; + }; + + var path1arr = path1.split('.'), + lastNodeName = path1arr[path1arr.length - 1], + treeNode1 = TsParser.getTreeNode(path1), + treeNode2 = TsParser.getTreeNode(path2); + + if (treeNode1.parent !== null) { + treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2); + } else { + TsParser.tsTree.childNodes[lastNodeName] = this.clone(treeNode2); + } + }; + + return TsParser; +}); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js index 7a0343b8782d679baf37b74d532c109bedfeadf8..37c2392161e0a46f501b426d59e348dfd187168e 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js @@ -15,162 +15,162 @@ * Module: TYPO3/CMS/T3editor/CodeCompletion/TsRef * Contains the TsCodeCompletion class */ -define(['jquery'], function ($) { - /** - * - * @type {{typeId: null, properties: null, typeTree: Array, doc: null}} - * @exports TYPO3/CMS/T3editor/CodeCompletion/TsRef - */ - var TsRef = { - typeId: null, - properties: null, - typeTree: [], - doc: null - }; +define(['jquery'], function($) { + /** + * + * @type {{typeId: null, properties: null, typeTree: Array, doc: null}} + * @exports TYPO3/CMS/T3editor/CodeCompletion/TsRef + */ + var TsRef = { + typeId: null, + properties: null, + typeTree: [], + doc: null + }; - /** - * Prototypes a TS reference type object - * - * @param {String} typeId - */ - TsRef.TsRefType = function(typeId) { - this.typeId = typeId; - this.properties = []; - }; + /** + * Prototypes a TS reference type object + * + * @param {String} typeId + */ + TsRef.TsRefType = function(typeId) { + this.typeId = typeId; + this.properties = []; + }; - /** - * Prototypes a TS reference property object - * - * @param {String} parentType - * @param {String} name - * @param {String} value - * @constructor - */ - TsRef.TsRefProperty = function(parentType, name, value) { - this.parentType = parentType; - this.name = name; - this.value = value; - }; + /** + * Prototypes a TS reference property object + * + * @param {String} parentType + * @param {String} name + * @param {String} value + * @constructor + */ + TsRef.TsRefProperty = function(parentType, name, value) { + this.parentType = parentType; + this.name = name; + this.value = value; + }; - /** - * Load available TypoScript reference - */ - TsRef.loadTsrefAsync = function() { - $.ajax({ - url: TYPO3.settings.ajaxUrls['t3editor_tsref'], - success: function(response) { - TsRef.doc = response; - TsRef.buildTree(); - } - }); - }; + /** + * Load available TypoScript reference + */ + TsRef.loadTsrefAsync = function() { + $.ajax({ + url: TYPO3.settings.ajaxUrls['t3editor_tsref'], + success: function(response) { + TsRef.doc = response; + TsRef.buildTree(); + } + }); + }; - /** - * Build the TypoScript reference tree - */ - TsRef.buildTree = function() { - for (var typeId in TsRef.doc) { - var arr = TsRef.doc[typeId]; - TsRef.typeTree[typeId] = new TsRef.TsRefType(typeId); + /** + * Build the TypoScript reference tree + */ + TsRef.buildTree = function() { + for (var typeId in TsRef.doc) { + var arr = TsRef.doc[typeId]; + TsRef.typeTree[typeId] = new TsRef.TsRefType(typeId); - if (typeof arr['extends'] !== 'undefined') { - TsRef.typeTree[typeId]['extends'] = arr['extends']; - } - for (var propName in arr.properties) { - var propType = arr.properties[propName].type; - TsRef.typeTree[typeId].properties[propName] = new TsRef.TsRefProperty(typeId, propName, propType); - } - } - for (var typeId in TsRef.typeTree) { - if (typeof TsRef.typeTree[typeId]['extends'] !== 'undefined') { - TsRef.addPropertiesToType(TsRef.typeTree[typeId], TsRef.typeTree[typeId]['extends'], 100); - } - } - }; + if (typeof arr['extends'] !== 'undefined') { + TsRef.typeTree[typeId]['extends'] = arr['extends']; + } + for (var propName in arr.properties) { + var propType = arr.properties[propName].type; + TsRef.typeTree[typeId].properties[propName] = new TsRef.TsRefProperty(typeId, propName, propType); + } + } + for (var typeId in TsRef.typeTree) { + if (typeof TsRef.typeTree[typeId]['extends'] !== 'undefined') { + TsRef.addPropertiesToType(TsRef.typeTree[typeId], TsRef.typeTree[typeId]['extends'], 100); + } + } + }; - /** - * Adds properties to TypoScript types - * - * @param {String} addToType - * @param {String} addFromTypeNames - * @param {Number} maxRecDepth - */ - TsRef.addPropertiesToType = function(addToType, addFromTypeNames, maxRecDepth) { - if (maxRecDepth < 0) { - throw "Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!"; - return; - } - var exts = addFromTypeNames.split(','), - i; - for (i = 0; i < exts.length; i++) { - // "Type 'array' which is used to extend 'undefined', was not found in the TSREF!" - if (typeof TsRef.typeTree[exts[i]] !== 'undefined') { - if (typeof TsRef.typeTree[exts[i]]['extends'] !== 'undefined') { - TsRef.addPropertiesToType(TsRef.typeTree[exts[i]], TsRef.typeTree[exts[i]]['extends'], maxRecDepth-1); - } - var properties = TsRef.typeTree[exts[i]].properties; - for (var propName in properties) { - // only add this property if it was not already added by a supertype (subtypes override supertypes) - if (typeof addToType.properties[propName] === 'undefined') { - addToType.properties[propName] = properties[propName]; - } - } - } - } - }; + /** + * Adds properties to TypoScript types + * + * @param {String} addToType + * @param {String} addFromTypeNames + * @param {Number} maxRecDepth + */ + TsRef.addPropertiesToType = function(addToType, addFromTypeNames, maxRecDepth) { + if (maxRecDepth < 0) { + throw "Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!"; + return; + } + var exts = addFromTypeNames.split(','), + i; + for (i = 0; i < exts.length; i++) { + // "Type 'array' which is used to extend 'undefined', was not found in the TSREF!" + if (typeof TsRef.typeTree[exts[i]] !== 'undefined') { + if (typeof TsRef.typeTree[exts[i]]['extends'] !== 'undefined') { + TsRef.addPropertiesToType(TsRef.typeTree[exts[i]], TsRef.typeTree[exts[i]]['extends'], maxRecDepth - 1); + } + var properties = TsRef.typeTree[exts[i]].properties; + for (var propName in properties) { + // only add this property if it was not already added by a supertype (subtypes override supertypes) + if (typeof addToType.properties[propName] === 'undefined') { + addToType.properties[propName] = properties[propName]; + } + } + } + } + }; - /** - * Get properties from given TypoScript type id - * - * @param {String} tId - * @return {Array} - */ - TsRef.getPropertiesFromTypeId = function(tId) { - if (typeof TsRef.typeTree[tId] !== 'undefined') { - // clone is needed to assure that nothing of the tsref is overwritten by user setup - TsRef.typeTree[tId].properties.clone = function() { - var result = []; - for (key in this) { - result[key] = new TsRef.TsRefProperty(this[key].parentType, this[key].name, this[key].value); - } - return result; - } - return TsRef.typeTree[tId].properties; - } - return []; - }; + /** + * Get properties from given TypoScript type id + * + * @param {String} tId + * @return {Array} + */ + TsRef.getPropertiesFromTypeId = function(tId) { + if (typeof TsRef.typeTree[tId] !== 'undefined') { + // clone is needed to assure that nothing of the tsref is overwritten by user setup + TsRef.typeTree[tId].properties.clone = function() { + var result = []; + for (key in this) { + result[key] = new TsRef.TsRefProperty(this[key].parentType, this[key].name, this[key].value); + } + return result; + } + return TsRef.typeTree[tId].properties; + } + return []; + }; - /** - * Check if a property of a type exists - * - * @param {String} typeId - * @param {String} propertyName - * @return {Boolean} - */ - TsRef.typeHasProperty = function(typeId, propertyName) { - return typeof TsRef.typeTree[typeId] !== 'undefined' - && typeof TsRef.typeTree[typeId].properties[propertyName] !== 'undefined'; - }; + /** + * Check if a property of a type exists + * + * @param {String} typeId + * @param {String} propertyName + * @return {Boolean} + */ + TsRef.typeHasProperty = function(typeId, propertyName) { + return typeof TsRef.typeTree[typeId] !== 'undefined' + && typeof TsRef.typeTree[typeId].properties[propertyName] !== 'undefined'; + }; - /** - * Get the type - * - * @param {String} typeId - * @return {Object} - */ - TsRef.getType = function(typeId) { - return TsRef.typeTree[typeId]; - }; + /** + * Get the type + * + * @param {String} typeId + * @return {Object} + */ + TsRef.getType = function(typeId) { + return TsRef.typeTree[typeId]; + }; - /** - * Check if type exists in the type tree - * - * @param {String} typeId - * @return {Boolean} - */ - TsRef.isType = function(typeId) { - return typeof TsRef.typeTree[typeId] !== 'undefined'; - }; + /** + * Check if type exists in the type tree + * + * @param {String} typeId + * @return {Boolean} + */ + TsRef.isType = function(typeId) { + return typeof TsRef.typeTree[typeId] !== 'undefined'; + }; - return TsRef; -}); \ No newline at end of file + return TsRef; +}); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js index 29019c4137eacd41b74fb096f71eb33fcd85db87..9085650bcac563ce17315191b7c26f2035105d6b 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js @@ -1,105 +1,105 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function (mod) { - if (typeof exports === 'object' && typeof module === 'object') // CommonJS - mod(require('cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion')); - else if (typeof define === 'function' && define.amd) // AMD - define(['cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'], mod); - else // Plain browser env - mod(CodeMirror); -})(function (CodeMirror, TsCodeCompletion) { - var Pos = CodeMirror.Pos; - - CodeMirror.registerHelper('hint', 'typoscript', function (editor, options) { - return typoScriptHint(editor, function (e, cur) { - return e.getTokenAt(cur); - }, options); - }); - - function arrayContains(arr, item) { - if (!Array.prototype.indexOf) { - var i = arr.length; - while (i--) { - if (arr[i] === item) { - return true; - } - } - return false; - } - return arr.indexOf(item) !== -1; - } - - function typoScriptHint(editor, getToken) { - var keywords = TsCodeCompletion.refreshCodeCompletion(editor); - - // Find the token at the cursor - var cur = editor.getCursor(), - token = getToken(editor, cur); - - if (/\b(?:string|comment)\b/.test(token.type) && tokenIsSubStringOfKeywords(token, keywords)) { - return; - } - token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; - - // If it's not a 'word-style' token, ignore the token. - if (!/^[\w$_]*$/.test(token.string)) { - token = { - start: cur.ch, end: cur.ch, string: '', state: token.state, - type: token.string === '.' ? 'property' : null - }; - } else if (token.end > cur.ch) { - token.end = cur.ch; - token.string = token.string.slice(0, cur.ch - token.start); - } - - var completions = { - list: getCompletions(token, keywords), - from: Pos(cur.line, token.start), - to: Pos(cur.line, token.end) - }; - - CodeMirror.on(completions, 'pick', function() { - TsCodeCompletion.resetCompList(); - }); - - return completions; - } - - function tokenIsSubStringOfKeywords(token, keywords) { - var tokenLength = token.string.length; - for (var i = 0; i < keywords.length; ++i) { - if (token.string === keywords[i].substr(tokenLength)) { - return true; - } - } - - return false; - } - - function getCompletions(token, keywords) { - var found = [], - start = token.string; - - function maybeAdd(str) { - if (str.lastIndexOf(start, 0) === 0 && !arrayContains(found, str)) { - found.push(str); - } - } - - // If not, just look in the global object and any local scope - // (reading into JS mode internals to get at the local and global variables) - for (var v = token.state.localVars; v; v = v.next) { - maybeAdd(v.name); - } - for (var v = token.state.globalVars; v; v = v.next) { - maybeAdd(v.name); - } - for (var i = 0, e = keywords.length; i < e; ++i) { - maybeAdd(keywords[i]); - } - found.sort(); - - return found; - } +(function(mod) { + if (typeof exports === 'object' && typeof module === 'object') // CommonJS + mod(require('cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion')); + else if (typeof define === 'function' && define.amd) // AMD + define(['cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror, TsCodeCompletion) { + var Pos = CodeMirror.Pos; + + CodeMirror.registerHelper('hint', 'typoscript', function(editor, options) { + return typoScriptHint(editor, function(e, cur) { + return e.getTokenAt(cur); + }, options); + }); + + function arrayContains(arr, item) { + if (!Array.prototype.indexOf) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + return true; + } + } + return false; + } + return arr.indexOf(item) !== -1; + } + + function typoScriptHint(editor, getToken) { + var keywords = TsCodeCompletion.refreshCodeCompletion(editor); + + // Find the token at the cursor + var cur = editor.getCursor(), + token = getToken(editor, cur); + + if (/\b(?:string|comment)\b/.test(token.type) && tokenIsSubStringOfKeywords(token, keywords)) { + return; + } + token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; + + // If it's not a 'word-style' token, ignore the token. + if (!/^[\w$_]*$/.test(token.string)) { + token = { + start: cur.ch, end: cur.ch, string: '', state: token.state, + type: token.string === '.' ? 'property' : null + }; + } else if (token.end > cur.ch) { + token.end = cur.ch; + token.string = token.string.slice(0, cur.ch - token.start); + } + + var completions = { + list: getCompletions(token, keywords), + from: Pos(cur.line, token.start), + to: Pos(cur.line, token.end) + }; + + CodeMirror.on(completions, 'pick', function() { + TsCodeCompletion.resetCompList(); + }); + + return completions; + } + + function tokenIsSubStringOfKeywords(token, keywords) { + var tokenLength = token.string.length; + for (var i = 0; i < keywords.length; ++i) { + if (token.string === keywords[i].substr(tokenLength)) { + return true; + } + } + + return false; + } + + function getCompletions(token, keywords) { + var found = [], + start = token.string; + + function maybeAdd(str) { + if (str.lastIndexOf(start, 0) === 0 && !arrayContains(found, str)) { + found.push(str); + } + } + + // If not, just look in the global object and any local scope + // (reading into JS mode internals to get at the local and global variables) + for (var v = token.state.localVars; v; v = v.next) { + maybeAdd(v.name); + } + for (var v = token.state.globalVars; v; v = v.next) { + maybeAdd(v.name); + } + for (var i = 0, e = keywords.length; i < e; ++i) { + maybeAdd(keywords[i]); + } + found.sort(); + + return found; + } }); diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js index 261b1247c8bcdd52c20259a7d26c342654475794..15f0c72e8fb93f3cd17417eb0d553dc7f3980c8e 100644 --- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js +++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js @@ -1,1825 +1,1825 @@ -(function (mod) { - if (typeof exports === "object" && typeof module === "object") // CommonJS - mod(require("cm/lib/codemirror")); - else if (typeof define === "function" && define.amd) // AMD - define(["cm/lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function (CodeMirror) { - "use strict"; - - function expressionAllowed(stream, state, backUp) { - return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || - (state.lastType === "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) - } - - CodeMirror.defineMode("typoscript", function (config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; - - // Tokenizer - - var keywords = function () { - function kw(type) { - return {type: type, style: "keyword"}; - } - - var A = kw("keyword a"), B = kw("keyword b"); - - return { - '_CSS_DEFAULT_STYLE': kw('_CSS_DEFAULT_STYLE'), - '_DEFAULT_PI_VARS': kw('_DEFAULT_PI_VARS'), - '_GIFBUILDER': kw('_GIFBUILDER'), - '_LOCAL_LANG': kw('_LOCAL_LANG'), - '_offset': kw('_offset'), - 'absRefPrefix': kw('absRefPrefix'), - 'accessibility': kw('accessibility'), - 'accessKey': kw('accessKey'), - 'ACT': B, - 'ACTIFSUB': B, - 'ACTIFSUBRO': kw('ACTIFSUBRO'), - 'ACTRO': B, - 'addAttributes': kw('addAttributes'), - 'addExtUrlsAndShortCuts': kw('addExtUrlsAndShortCuts'), - 'addItems': kw('addItems'), - 'additionalHeaders': kw('additionalHeaders'), - 'additionalParams': kw('additionalParams'), - 'addParams': kw('addParams'), - 'addQueryString': kw('addQueryString'), - 'adjustItemsH': kw('adjustItemsH'), - 'adjustSubItemsH': kw('adjustSubItemsH'), - 'admPanel': A, - 'after': kw('after'), - 'afterImg': kw('afterImg'), - 'afterImgLink': kw('afterImgLink'), - 'afterImgTagParams': kw('afterImgTagParams'), - 'afterROImg': kw('afterROImg'), - 'afterWrap': kw('afterWrap'), - 'age': kw('age'), - 'alertPopups': kw('alertPopups'), - 'align': kw('align'), - 'all': B, - 'allow': kw('allow'), - 'allowCaching': kw('allowCaching'), - 'allowedAttribs': kw('allowedAttribs'), - 'allowedClasses': kw('allowedClasses'), - 'allowedCols': kw('allowedCols'), - 'allowedNewTables': kw('allowedNewTables'), - 'allowTags': kw('allowTags'), - 'allStdWrap': kw('allStdWrap'), - 'allWrap': kw('allWrap'), - 'alt_print': A, - 'alternativeSortingField': kw('alternativeSortingField'), - 'alternativeTempPath': kw('alternativeTempPath'), - 'altIcons': kw('altIcons'), - 'altImgResource': kw('altImgResource'), - 'altLabels': kw('altLabels'), - 'altTarget': kw('altTarget'), - 'altText': kw('altText'), - 'altUrl': kw('altUrl'), - 'altUrl_noDefaultParams': kw('altUrl_noDefaultParams'), - 'altWrap': kw('altWrap'), - 'always': kw('always'), - 'alwaysActivePIDlist': kw('alwaysActivePIDlist'), - 'alwaysLink': kw('alwaysLink'), - 'andWhere': kw('andWhere'), - 'angle': kw('angle'), - 'antiAlias': kw('antiAlias'), - 'append': kw('append'), - 'applyTotalH': kw('applyTotalH'), - 'applyTotalW': kw('applyTotalW'), - 'archive': kw('archive'), - 'ascii': B, - 'ATagAfterWrap': kw('ATagAfterWrap'), - 'ATagBeforeWrap': kw('ATagBeforeWrap'), - 'ATagParams': kw('ATagParams'), - 'ATagTitle': kw('ATagTitle'), - 'atLeast': B, - 'atMost': B, - 'attribute': kw('attribute'), - 'auth': A, - 'autoLevels': kw('autoLevels'), - 'autonumber': kw('autonumber'), - 'backColor': kw('backColor'), - 'background': kw('background'), - 'baseURL': kw('baseURL'), - 'BE': B, - 'be_groups': B, - 'be_users': B, - 'before': kw('before'), - 'beforeImg': kw('beforeImg'), - 'beforeImgLink': kw('beforeImgLink'), - 'beforeImgTagParams': kw('beforeImgTagParams'), - 'beforeROImg': kw('beforeROImg'), - 'beforeWrap': kw('beforeWrap'), - 'begin': kw('begin'), - 'bgCol': kw('bgCol'), - 'bgImg': kw('bgImg'), - 'blur': kw('blur'), - 'bm': kw('bm'), - 'bodyTag': kw('bodyTag'), - 'bodyTagAdd': kw('bodyTagAdd'), - 'bodyTagCObject': kw('bodyTagCObject'), - 'bodytext': kw('bodytext'), - 'border': kw('border'), - 'borderCol': kw('borderCol'), - 'borderThick': kw('borderThick'), - 'bottomBackColor': kw('bottomBackColor'), - 'bottomContent': kw('bottomContent'), - 'bottomHeight': kw('bottomHeight'), - 'bottomImg': kw('bottomImg'), - 'bottomImg_mask': kw('bottomImg_mask'), - 'BOX': B, - 'br': kw('br'), - 'browse': B, - 'browser': A, - 'brTag': kw('brTag'), - 'bullet': kw('bullet'), - 'bulletlist': kw('bulletlist'), - 'bullets': B, - 'bytes': kw('bytes'), - 'cache': A, - 'cache_clearAtMidnight': kw('cache_clearAtMidnight'), - 'cache_period': kw('cache_period'), - 'caption': kw('caption'), - 'caption_stdWrap': kw('caption_stdWrap'), - 'captionHeader': kw('captionHeader'), - 'captionSplit': kw('captionSplit'), - 'CARRAY': kw('CARRAY'), - 'CASE': kw('CASE'), - 'case': kw('case'), - 'casesensitiveComp': kw('casesensitiveComp'), - 'cellpadding': kw('cellpadding'), - 'cellspacing': kw('cellspacing'), - 'char': kw('char'), - 'charcoal': kw('charcoal'), - 'charMapConfig': kw('charMapConfig'), - 'CHECK': A, - 'check': kw('check'), - 'class': kw('class'), - 'classesAnchor': kw('classesAnchor'), - 'classesCharacter': kw('classesCharacter'), - 'classesImage': kw('classesImage'), - 'classesParagraph': kw('classesParagraph'), - 'clear': kw('clear'), - 'clearCache': kw('clearCache'), - 'clearCache_disable': kw('clearCache_disable'), - 'clearCache_pageGrandParent': kw('clearCache_pageGrandParent'), - 'clearCache_pageSiblingChildren': kw('clearCache_pageSiblingChildren'), - 'clearCacheCmd': kw('clearCacheCmd'), - 'clearCacheLevels': kw('clearCacheLevels'), - 'clearCacheOfPages': kw('clearCacheOfPages'), - 'clickTitleMode': kw('clickTitleMode'), - 'clipboardNumberPads': kw('clipboardNumberPads'), - 'cMargins': kw('cMargins'), - 'COA': kw('COA'), - 'COA_INT': kw('COA_INT'), - 'cObj': A, - 'COBJ_ARRAY': kw('COBJ_ARRAY'), - 'cObject': A, - 'cObjNum': kw('cObjNum'), - 'collapse': kw('collapse'), - 'collections': kw('collections'), - 'color': kw('color'), - 'color1': kw('color1'), - 'color2': kw('color2'), - 'color3': kw('color3'), - 'color4': kw('color4'), - 'colors': kw('colors'), - 'colour': kw('colour'), - 'colPos_list': kw('colPos_list'), - 'colRelations': kw('colRelations'), - 'cols': kw('cols'), - 'colSpace': kw('colSpace'), - 'COMMENT': A, - 'comment_auto': kw('comment_auto'), - 'commentWrap': kw('commentWrap'), - 'compX': kw('compX'), - 'compY': kw('compY'), - 'conf': kw('conf'), - 'CONFIG': kw('CONFIG'), - 'config': A, - 'CONSTANTS': kw('CONSTANTS'), - 'constants': kw('constants'), - 'CONTENT': kw('CONTENT'), - 'content': A, - 'content_from_pid_allowOutsideDomain': kw('content_from_pid_allowOutsideDomain'), - 'contextMenu': kw('contextMenu'), - 'copy': A, - 'copyLevels': kw('copyLevels'), - 'count_HMENU_MENUOBJ': kw('count_HMENU_MENUOBJ'), - 'count_menuItems': kw('count_menuItems'), - 'count_MENUOBJ': kw('count_MENUOBJ'), - 'create': kw('create'), - 'createFoldersInEB': kw('createFoldersInEB'), - 'crop': kw('crop'), - 'csConv': kw('csConv'), - 'CSS_inlineStyle': A, - 'CType': kw('CType'), - 'CUR': B, - 'CURIFSUB': B, - 'CURIFSUBRO': B, - 'current': kw('current'), - 'CURRO': B, - 'curUid': kw('curUid'), - 'cut': A, - 'cWidth': kw('cWidth'), - 'data': kw('data'), - 'dataArray': A, - 'dataWrap': kw('dataWrap'), - 'date': kw('date'), - 'date_stdWrap': kw('date_stdWrap'), - 'datePrefix': kw('datePrefix'), - 'dayofmonth': A, - 'dayofweek': A, - 'DB': kw('DB'), - 'db_list': A, - 'debug': kw('debug'), - 'debugData': kw('debugData'), - 'debugFunc': kw('debugFunc'), - 'debugItemConf': kw('debugItemConf'), - 'debugRenumberedObject': kw('debugRenumberedObject'), - 'default': B, - 'defaultAlign': kw('defaultAlign'), - 'defaultCmd': kw('defaultCmd'), - 'defaultFileUploads': kw('defaultFileUploads'), - 'defaultHeaderType': kw('defaultHeaderType'), - 'defaultOutput': kw('defaultOutput'), - 'defaults': kw('defaults'), - 'defaultType': kw('defaultType'), - 'delete': kw('delete'), - 'denyTags': kw('denyTags'), - 'depth': kw('depth'), - 'DESC': kw('DESC'), - 'description': B, - 'dimensions': kw('dimensions'), - 'direction': kw('direction'), - 'directory': B, - 'directReturn': B, - 'disableAdvanced': kw('disableAdvanced'), - 'disableAllHeaderCode': kw('disableAllHeaderCode'), - 'disableAltText': kw('disableAltText'), - 'disableBodyTag': kw('disableBodyTag'), - 'disableCacheSelector': kw('disableCacheSelector'), - 'disableCharsetHeader': kw('disableCharsetHeader'), - 'disabled': kw('disabled'), - 'disableDelete': kw('disableDelete'), - 'disableDocSelector': kw('disableDocSelector'), - 'disableHideAtCopy': kw('disableHideAtCopy'), - 'disableItems': kw('disableItems'), - 'disableNewContentElementWizard': kw('disableNewContentElementWizard'), - 'disableNoMatchingValueElement': kw('disableNoMatchingValueElement'), - 'disablePageExternalUrl': kw('disablePageExternalUrl'), - 'disablePrefixComment': kw('disablePrefixComment'), - 'disablePrependAtCopy': kw('disablePrependAtCopy'), - 'disableSearchBox': kw('disableSearchBox'), - 'disableSingleTableView': kw('disableSingleTableView'), - 'displayContent': kw('displayContent'), - 'displayFieldIcons': kw('displayFieldIcons'), - 'displayIcons': kw('displayIcons'), - 'displayMessages': kw('displayMessages'), - 'displayRecord': kw('displayRecord'), - 'displayTimes': kw('displayTimes'), - 'distributeX': kw('distributeX'), - 'distributeY': kw('distributeY'), - 'div': B, - 'DIV': kw('DIV'), - 'doctype': kw('doctype'), - 'doctypeSwitch': kw('doctypeSwitch'), - 'DOCUMENT_BODY': kw('DOCUMENT_BODY'), - 'doktype': kw('doktype'), - 'doNotLinkIt': kw('doNotLinkIt'), - 'doNotShowLink': kw('doNotShowLink'), - 'doNotStripHTML': kw('doNotStripHTML'), - 'dontCheckPid': kw('dontCheckPid'), - 'dontLinkIfSubmenu': kw('dontLinkIfSubmenu'), - 'dontWrapInTable': kw('dontWrapInTable'), - 'doubleBrTag': kw('doubleBrTag'), - 'dWorkArea': kw('dWorkArea'), - 'dynCSS': A, - 'edge': kw('edge'), - 'edit': A, - 'edit_access': A, - 'edit_docModuleUpload': kw('edit_docModuleUpload'), - 'edit_pageheader': A, - 'edit_RTE': kw('edit_RTE'), - 'editFieldsAtATime': kw('editFieldsAtATime'), - 'editFormsOnPage': kw('editFormsOnPage'), - 'editIcons': kw('editIcons'), - 'editNoPopup': kw('editNoPopup'), - 'EDITPANEL': kw('EDITPANEL'), - 'editPanel': kw('editPanel'), - 'EFFECT': kw('EFFECT'), - 'elements': kw('elements'), - 'else': B, - 'email': B, - 'emailMeAtLogin': kw('emailMeAtLogin'), - 'emailMess': kw('emailMess'), - 'emboss': kw('emboss'), - 'enable': kw('enable'), - 'encapsLines': kw('encapsLines'), - 'encapsLinesStdWrap': kw('encapsLinesStdWrap'), - 'encapsTagList': kw('encapsTagList'), - 'end': B, - 'entryLevel': kw('entryLevel'), - 'equalH': kw('equalH'), - 'equals': B, - 'everybody': kw('everybody'), - 'excludeDoktypes': kw('excludeDoktypes'), - 'excludeUidList': kw('excludeUidList'), - 'expAll': kw('expAll'), - 'expand': kw('expand'), - 'explode': kw('explode'), - 'ext': kw('ext'), - 'external': B, - 'externalBlocks': kw('externalBlocks'), - 'extTarget': kw('extTarget'), - 'face': kw('face'), - 'false': B, - 'FE': B, - 'fe_adminLib': kw('fe_adminLib'), - 'fe_groups': B, - 'fe_users': B, - 'feadmin': B, - 'field': kw('field'), - 'fieldName': kw('fieldName'), - 'fieldOrder': kw('fieldOrder'), - 'fieldRequired': kw('fieldRequired'), - 'fields': kw('fields'), - 'fieldWrap': kw('fieldWrap'), - 'FILE': kw('FILE'), - 'file': kw('file'), - 'file1': kw('file1'), - 'file2': kw('file2'), - 'file3': kw('file3'), - 'file4': kw('file4'), - 'file5': kw('file5'), - 'filelink': kw('filelink'), - 'filelist': kw('filelist'), - 'FILES': kw('FILES'), - 'files': kw('files'), - 'firstLabel': kw('firstLabel'), - 'firstLabelGeneral': kw('firstLabelGeneral'), - 'fixAttrib': kw('fixAttrib'), - 'flip': kw('flip'), - 'flop': kw('flop'), - 'FLUIDTEMPLATE': kw('FLUIDTEMPLATE'), - 'folder': A, - 'folders': kw('folders'), - 'folderTree': A, - 'foldoutMenu': A, - 'fontColor': kw('fontColor'), - 'fontFile': kw('fontFile'), - 'fontOffset': kw('fontOffset'), - 'fontSize': kw('fontSize'), - 'fontSizeMultiplicator': kw('fontSizeMultiplicator'), - 'forceDisplayFieldIcons': kw('forceDisplayFieldIcons'), - 'forceDisplayIcons': kw('forceDisplayIcons'), - 'forceTemplateParsing': kw('forceTemplateParsing'), - 'forceTypeValue': kw('forceTypeValue'), - 'FORM': kw('FORM'), - 'format': kw('format'), - 'ftu': kw('ftu'), - 'function': kw('function'), - 'Functions': A, - 'gamma': kw('gamma'), - 'gapBgCol': kw('gapBgCol'), - 'gapLineCol': kw('gapLineCol'), - 'gapLineThickness': kw('gapLineThickness'), - 'gapWidth': kw('gapWidth'), - 'get': kw('get'), - 'getBorder': kw('getBorder'), - 'getLeft': kw('getLeft'), - 'getRight': kw('getRight'), - 'GIFBUILDER': kw('GIFBUILDER'), - 'global': kw('global'), - 'globalNesting': kw('globalNesting'), - 'globalString': kw('globalString'), - 'globalVar': kw('globalVar'), - 'GMENU': kw('GMENU'), - 'GP': kw('GP'), - 'gray': kw('gray'), - 'group': kw('group'), - 'groupBy': kw('groupBy'), - 'groupid': kw('groupid'), - 'header': B, - 'header_layout': kw('header_layout'), - 'headerComment': kw('headerComment'), - 'headerData': kw('headerData'), - 'headerSpace': kw('headerSpace'), - 'headTag': kw('headTag'), - 'height': kw('height'), - 'helpText': kw('helpText'), - 'hidden': kw('hidden'), - 'hiddenFields': kw('hiddenFields'), - 'hide': kw('hide'), - 'hideButCreateMap': kw('hideButCreateMap'), - 'hidePStyleItems': kw('hidePStyleItems'), - 'hideRecords': kw('hideRecords'), - 'highColor': kw('highColor'), - 'history': kw('history'), - 'HMENU': kw('HMENU'), - 'hostname': A, - 'hour': A, - 'HTML': kw('HTML'), - 'html': B, - 'HTMLparser': kw('HTMLparser'), - 'HTMLparser_tags': kw('HTMLparser_tags'), - 'htmlSpecialChars': kw('htmlSpecialChars'), - 'htmlTag_dir': kw('htmlTag_dir'), - 'htmlTag_langKey': kw('htmlTag_langKey'), - 'htmlTag_setParams': kw('htmlTag_setParams'), - 'http': kw('http'), - 'icon': kw('icon'), - 'icon_image_ext_list': kw('icon_image_ext_list'), - 'icon_link': kw('icon_link'), - 'iconCObject': kw('iconCObject'), - 'id': B, - 'IENV': kw('IENV'), - 'if': B, - 'ifEmpty': B, - 'IFSUB': B, - 'IFSUBRO': B, - 'IMAGE': kw('IMAGE'), - 'image': B, - 'image_frames': kw('image_frames'), - 'imageLinkWrap': kw('imageLinkWrap'), - 'imagePath': kw('imagePath'), - 'images': kw('images'), - 'imageWrapIfAny': kw('imageWrapIfAny'), - 'IMG_RESOURCE': kw('IMG_RESOURCE'), - 'imgList': A, - 'imgMap': kw('imgMap'), - 'imgMapExtras': kw('imgMapExtras'), - 'imgMax': kw('imgMax'), - 'IMGMENU': kw('IMGMENU'), - 'IMGMENUITEM': kw('IMGMENUITEM'), - 'imgNameNotRandom': kw('imgNameNotRandom'), - 'imgNamePrefix': kw('imgNamePrefix'), - 'imgObjNum': kw('imgObjNum'), - 'imgParams': kw('imgParams'), - 'imgPath': kw('imgPath'), - 'imgResource': A, - 'imgStart': kw('imgStart'), - 'IMGTEXT': kw('IMGTEXT'), - 'imgText': A, - 'import': kw('import'), - 'inBranch': B, - 'inc': kw('inc'), - 'INCLUDE_TYPOSCRIPT': kw('INCLUDE_TYPOSCRIPT'), - 'includeCSS': kw('includeCSS'), - 'includeLibrary': kw('includeLibrary'), - 'includeNotInMenu': kw('includeNotInMenu'), - 'index': kw('index'), - 'index_descrLgd': kw('index_descrLgd'), - 'index_enable': kw('index_enable'), - 'index_externals': kw('index_externals'), - 'info': A, - 'inlineStyle2TempFile': kw('inlineStyle2TempFile'), - 'innerStdWrap': kw('innerStdWrap'), - 'innerStdWrap_all': kw('innerStdWrap_all'), - 'innerWrap': kw('innerWrap'), - 'innerWrap2': kw('innerWrap2'), - 'input': kw('input'), - 'inputLevels': kw('inputLevels'), - 'insertData': kw('insertData'), - 'intensity': kw('intensity'), - 'intTarget': kw('intTarget'), - 'intval': kw('intval'), - 'invert': kw('invert'), - 'IP': A, - 'IProcFunc': kw('IProcFunc'), - 'isFalse': B, - 'isGreaterThan': B, - 'isInList': B, - 'isLessThan': B, - 'isPositive': B, - 'isTrue': B, - 'itemArrayProcFunc': kw('itemArrayProcFunc'), - 'itemH': kw('itemH'), - 'items': kw('items'), - 'itemsProcFunc': kw('itemsProcFunc'), - 'iterations': kw('iterations'), - 'join': kw('join'), - 'JSwindow': A, - 'JSWindow': kw('JSWindow'), - 'JSwindow_params': kw('JSwindow_params'), - 'keep': kw('keep'), - 'keepEntries': kw('keepEntries'), - 'keepNonMatchedTags': kw('keepNonMatchedTags'), - 'key': kw('key'), - 'keyword3': B, - 'LABEL': A, - 'label': kw('label'), - 'labelStdWrap': kw('labelStdWrap'), - 'labelWrap': kw('labelWrap'), - 'lang': kw('lang'), - 'language': B, - 'language_alt': kw('language_alt'), - 'languageField': kw('languageField'), - 'layout': A, - 'left': kw('left'), - 'leftjoin': kw('leftjoin'), - 'levels': kw('levels'), - 'leveltitle': B, - 'leveluid': kw('leveluid'), - 'lib': A, - 'limit': kw('limit'), - 'line': kw('line'), - 'lineColor': kw('lineColor'), - 'lineThickness': kw('lineThickness'), - 'linkPrefix': kw('linkPrefix'), - 'linkTitleToSelf': kw('linkTitleToSelf'), - 'linkVars': kw('linkVars'), - 'linkWrap': kw('linkWrap'), - 'list': B, - 'listNum': kw('listNum'), - 'listOnlyInSingleTableView': kw('listOnlyInSingleTableView'), - 'LIT': kw('LIT'), - 'lm': kw('lm'), - 'LOAD_REGISTER': kw('LOAD_REGISTER'), - 'locale_all': kw('locale_all'), - 'localNesting': kw('localNesting'), - 'locationData': kw('locationData'), - 'lockToIP': kw('lockToIP'), - 'login': B, - 'loginUser': A, - 'longdescURL': kw('longdescURL'), - 'lowColor': kw('lowColor'), - 'lower': kw('lower'), - 'LR': kw('LR'), - 'mailform': B, - 'mailto': kw('mailto'), - 'main': kw('main'), - 'makelinks': kw('makelinks'), - 'markerWrap': kw('markerWrap'), - 'marks': A, - 'mask': kw('mask'), - 'max': kw('max'), - 'maxAge': kw('maxAge'), - 'maxChars': kw('maxChars'), - 'maxH': kw('maxH'), - 'maxHeight': kw('maxHeight'), - 'maxItems': kw('maxItems'), - 'maxW': kw('maxW'), - 'maxWidth': kw('maxWidth'), - 'maxWInText': kw('maxWInText'), - 'media': B, - 'menu': B, - 'menu_type': kw('menu_type'), - 'menuHeight': kw('menuHeight'), - 'menuName': kw('menuName'), - 'menuOffset': kw('menuOffset'), - 'menuWidth': kw('menuWidth'), - 'message_page_is_being_generated': kw('message_page_is_being_generated'), - 'message_preview': kw('message_preview'), - 'META': kw('META'), - 'meta': kw('meta'), - 'metaCharset': kw('metaCharset'), - 'method': kw('method'), - 'min': kw('min'), - 'minH': kw('minH'), - 'minItems': kw('minItems'), - 'minute': A, - 'minW': kw('minW'), - 'mod': B, - 'mode': kw('mode'), - 'module': A, - 'month': A, - 'move_wizard': A, - 'MP_defaults': kw('MP_defaults'), - 'MP_disableTypolinkClosestMPvalue': kw('MP_disableTypolinkClosestMPvalue'), - 'MP_mapRootPoints': kw('MP_mapRootPoints'), - 'MULTIMEDIA': kw('MULTIMEDIA'), - 'multimedia': B, - 'name': kw('name'), - 'negate': B, - 'nesting': kw('nesting'), - 'neverHideAtCopy': kw('neverHideAtCopy'), - 'new': A, - 'NEW': B, - 'new_wizard': A, - 'newPageWiz': kw('newPageWiz'), - 'newRecordFromTable': kw('newRecordFromTable'), - 'newWindow': kw('newWindow'), - 'newWizards': kw('newWizards'), - 'next': kw('next'), - 'niceText': kw('niceText'), - 'nicetext': kw('nicetext'), - 'NO': B, - 'no_cache': kw('no_cache'), - 'no_search': kw('no_search'), - 'noAttrib': kw('noAttrib'), - 'noCache': kw('noCache'), - 'noCreateRecordsLink': kw('noCreateRecordsLink'), - 'noLink': kw('noLink'), - 'noMatchingValue_label': kw('noMatchingValue_label'), - 'nonCachedSubst': kw('nonCachedSubst'), - 'none': B, - 'nonTypoTagStdWrap': kw('nonTypoTagStdWrap'), - 'nonTypoTagUserFunc': kw('nonTypoTagUserFunc'), - 'nonWrappedTag': kw('nonWrappedTag'), - 'noOrderBy': kw('noOrderBy'), - 'noPageTitle': kw('noPageTitle'), - 'noResultObj': A, - 'noThumbsInEB': kw('noThumbsInEB'), - 'noThumbsInRTEimageSelect': kw('noThumbsInRTEimageSelect'), - 'noTrimWrap': kw('noTrimWrap'), - 'noValueInsert': kw('noValueInsert'), - 'numRows': A, - 'obj': kw('obj'), - 'offset': kw('offset'), - 'onlineWorkspaceInfo': kw('onlineWorkspaceInfo'), - 'onlyCurrentPid': kw('onlyCurrentPid'), - 'opacity': kw('opacity'), - 'options': A, - 'orderBy': kw('orderBy'), - 'outerWrap': kw('outerWrap'), - 'outline': kw('outline'), - 'outputLevels': kw('outputLevels'), - 'override': kw('override'), - 'overrideAttribs': kw('overrideAttribs'), - 'overrideId': kw('overrideId'), - 'overridePageModule': kw('overridePageModule'), - 'overrideWithExtension': kw('overrideWithExtension'), - 'PAGE': kw('PAGE'), - 'page': A, - 'PAGE_TARGET': kw('PAGE_TARGET'), - 'PAGE_TSCONFIG_ID': kw('PAGE_TSCONFIG_ID'), - 'PAGE_TSCONFIG_IDLIST': kw('PAGE_TSCONFIG_IDLIST'), - 'PAGE_TSCONFIG_STR': kw('PAGE_TSCONFIG_STR'), - 'pageFrameObj': kw('pageFrameObj'), - 'pages': B, - 'pages_language_overlay': B, - 'pageTitleFirst': kw('pageTitleFirst'), - 'pageTree': A, - 'parameter': kw('parameter'), - 'params': kw('params'), - 'parseFunc': kw('parseFunc'), - 'parseFunc_RTE': B, - 'parser': kw('parser'), - 'password': kw('password'), - 'paste': A, - 'path': kw('path'), - 'permissions': kw('permissions'), - 'perms': A, - 'pid': B, - 'pid_list': kw('pid_list'), - 'pidInList': kw('pidInList'), - 'PIDinRootline': A, - 'PIDupinRootline': A, - 'pixelSpaceFontSizeRef': kw('pixelSpaceFontSizeRef'), - 'plaintextLib': kw('plaintextLib'), - 'plainTextStdWrap': kw('plainTextStdWrap'), - 'plugin': A, - 'postCObject': kw('postCObject'), - 'postLineBlanks': kw('postLineBlanks'), - 'postLineChar': kw('postLineChar'), - 'postLineLen': kw('postLineLen'), - 'postUserFunc': kw('postUserFunc'), - 'postUserFuncInt': kw('postUserFuncInt'), - 'preBlanks': kw('preBlanks'), - 'preCObject': kw('preCObject'), - 'prefix': kw('prefix'), - 'prefixComment': kw('prefixComment'), - 'prefixLocalAnchors': kw('prefixLocalAnchors'), - 'prefixRelPathWith': kw('prefixRelPathWith'), - 'preIfEmptyListNum': kw('preIfEmptyListNum'), - 'preLineBlanks': kw('preLineBlanks'), - 'preLineChar': kw('preLineChar'), - 'preLineLen': kw('preLineLen'), - 'prepend': kw('prepend'), - 'preserveEntities': kw('preserveEntities'), - 'preUserFunc': kw('preUserFunc'), - 'prev': kw('prev'), - 'preview': A, - 'previewBorder': kw('previewBorder'), - 'prevnextToSection': kw('prevnextToSection'), - 'prioriCalc': kw('prioriCalc'), - 'proc': kw('proc'), - 'processor_allowUpscaling': kw('processor_allowUpscaling'), - 'properties': kw('properties'), - 'protect': kw('protect'), - 'protectLvar': kw('protectLvar'), - 'publish': A, - 'publish_levels': kw('publish_levels'), - 'QEisDefault': kw('QEisDefault'), - 'quality': kw('quality'), - 'RADIO': A, - 'radio': kw('radio'), - 'radioWrap': kw('radioWrap'), - 'range': kw('range'), - 'rawUrlEncode': kw('rawUrlEncode'), - 'recipient': kw('recipient'), - 'RECORDS': kw('RECORDS'), - 'recursive': kw('recursive'), - 'recursiveDelete': kw('recursiveDelete'), - 'redirect': kw('redirect'), - 'redirectToURL': kw('redirectToURL'), - 'reduceColors': kw('reduceColors'), - 'references': kw('references'), - 'register': kw('register'), - 'relPathPrefix': kw('relPathPrefix'), - 'remap': kw('remap'), - 'remapTag': kw('remapTag'), - 'REMOTE_ADDR': kw('REMOTE_ADDR'), - 'removeDefaultJS': kw('removeDefaultJS'), - 'removeIfEquals': kw('removeIfEquals'), - 'removeIfFalse': kw('removeIfFalse'), - 'removeItems': kw('removeItems'), - 'removeObjectsOfDummy': kw('removeObjectsOfDummy'), - 'removePrependedNumbers': kw('removePrependedNumbers'), - 'removeTags': kw('removeTags'), - 'removeWrapping': kw('removeWrapping'), - 'renderObj': A, - 'renderWrap': kw('renderWrap'), - 'REQ': A, - 'required': B, - 'reset': kw('reset'), - 'resources': kw('resources'), - 'RESTORE_REGISTER': kw('RESTORE_REGISTER'), - 'resultObj': kw('resultObj'), - 'returnLast': kw('returnLast'), - 'returnUrl': kw('returnUrl'), - 'rightjoin': kw('rightjoin'), - 'rm': kw('rm'), - 'rmTagIfNoAttrib': kw('rmTagIfNoAttrib'), - 'RO': B, - 'rootline': B, - 'rotate': kw('rotate'), - 'rows': kw('rows'), - 'rowSpace': kw('rowSpace'), - 'RTE': A, - 'RTE_compliant': A, - 'RTEfullScreenWidth': kw('RTEfullScreenWidth'), - 'rules': kw('rules'), - 'sample': kw('sample'), - 'saveClipboard': kw('saveClipboard'), - 'saveDocNew': kw('saveDocNew'), - 'script': B, - 'search': B, - 'SEARCHRESULT': kw('SEARCHRESULT'), - 'secondRow': kw('secondRow'), - 'section': kw('section'), - 'sectionIndex': kw('sectionIndex'), - 'select': A, - 'selectFields': kw('selectFields'), - 'separator': kw('separator'), - 'set': kw('set'), - 'setContentToCurrent': kw('setContentToCurrent'), - 'setCurrent': kw('setCurrent'), - 'setfixed': kw('setfixed'), - 'setOnly': kw('setOnly'), - 'setup': A, - 'shadow': kw('shadow'), - 'SHARED': kw('SHARED'), - 'sharpen': kw('sharpen'), - 'shear': kw('shear'), - 'short': kw('short'), - 'shortcut': B, - 'shortcutFrame': kw('shortcutFrame'), - 'shortcutIcon': kw('shortcutIcon'), - 'show': kw('show'), - 'showAccessRestrictedPages': kw('showAccessRestrictedPages'), - 'showActive': kw('showActive'), - 'showClipControlPanelsDespiteOfCMlayers': kw('showClipControlPanelsDespiteOfCMlayers'), - 'showFirst': kw('showFirst'), - 'showHiddenPages': kw('showHiddenPages'), - 'showHiddenRecords': kw('showHiddenRecords'), - 'showHistory': kw('showHistory'), - 'showPageIdWithTitle': kw('showPageIdWithTitle'), - 'showTagFreeClasses': kw('showTagFreeClasses'), - 'simulateDate': kw('simulateDate'), - 'simulateUserGroup': kw('simulateUserGroup'), - 'singlePid': kw('singlePid'), - 'site_author': kw('site_author'), - 'site_reserved': kw('site_reserved'), - 'sitemap': B, - 'sitetitle': kw('sitetitle'), - 'siteUrl': kw('siteUrl'), - 'size': kw('size'), - 'solarize': kw('solarize'), - 'sorting': kw('sorting'), - 'source': kw('source'), - 'space': kw('space'), - 'spaceAfter': kw('spaceAfter'), - 'spaceBefore': kw('spaceBefore'), - 'spaceBelowAbove': kw('spaceBelowAbove'), - 'spaceLeft': kw('spaceLeft'), - 'spaceRight': kw('spaceRight'), - 'spacing': kw('spacing'), - 'spamProtectEmailAddresses': kw('spamProtectEmailAddresses'), - 'spamProtectEmailAddresses_atSubst': kw('spamProtectEmailAddresses_atSubst'), - 'spamProtectEmailAddresses_lastDotSubst': kw('spamProtectEmailAddresses_lastDotSubst'), - 'SPC': B, - 'special': kw('special'), - 'split': A, - 'splitChar': kw('splitChar'), - 'splitRendering': kw('splitRendering'), - 'src': kw('src'), - 'stdheader': kw('stdheader'), - 'stdWrap': A, - 'stdWrap2': kw('stdWrap2'), - 'strftime': kw('strftime'), - 'stripHtml': kw('stripHtml'), - 'styles': kw('styles'), - 'submenuObjSuffixes': kw('submenuObjSuffixes'), - 'subMenuOffset': kw('subMenuOffset'), - 'submit': kw('submit'), - 'subparts': A, - 'subst_elementUid': kw('subst_elementUid'), - 'substMarksSeparately': kw('substMarksSeparately'), - 'substring': kw('substring'), - 'swirl': kw('swirl'), - 'sword': kw('sword'), - 'sword_noMixedCase': kw('sword_noMixedCase'), - 'SWORD_PARAMS': kw('SWORD_PARAMS'), - 'sword_standAlone': kw('sword_standAlone'), - 'sys_dmail': B, - 'sys_domain': B, - 'sys_filemounts': B, - 'sys_language_mode': kw('sys_language_mode'), - 'sys_language_overlay': kw('sys_language_overlay'), - 'sys_language_uid': kw('sys_language_uid'), - 'sys_note': B, - 'sys_template': B, - 'system': A, - 'table': B, - 'tableCellColor': kw('tableCellColor'), - 'tableParams': kw('tableParams'), - 'tables': kw('tables'), - 'tableStdWrap': kw('tableStdWrap'), - 'tableWidth': kw('tableWidth'), - 'tags': kw('tags'), - 'target': kw('target'), - 'TCAdefaults': kw('TCAdefaults'), - 'TCEFORM': kw('TCEFORM'), - 'TCEMAIN': kw('TCEMAIN'), - 'TDparams': kw('TDparams'), - 'temp': A, - 'TEMPLATE': kw('TEMPLATE'), - 'template': A, - 'templateContent': kw('templateContent'), - 'templateFile': kw('templateFile'), - 'TEXT': kw('TEXT'), - 'text': B, - 'textarea': kw('textarea'), - 'textMargin': kw('textMargin'), - 'textMargin_outOfText': kw('textMargin_outOfText'), - 'textMaxLength': kw('textMaxLength'), - 'textObjNum': kw('textObjNum'), - 'textpic': B, - 'textPos': kw('textPos'), - 'thickness': kw('thickness'), - 'this': B, - 'thumbnailsByDefault': kw('thumbnailsByDefault'), - 'tile': kw('tile'), - 'time_stdWrap': kw('time_stdWrap'), - 'tipafriendLib': kw('tipafriendLib'), - 'title': kw('title'), - 'titleLen': kw('titleLen'), - 'titleTagFunction': kw('titleTagFunction'), - 'titleText': kw('titleText'), - 'tm': kw('tm'), - 'TMENU': kw('TMENU'), - 'TMENUITEM': kw('TMENUITEM'), - 'token': kw('token'), - 'top': B, - 'totalWidth': kw('totalWidth'), - 'transparentBackground': kw('transparentBackground'), - 'transparentColor': kw('transparentColor'), - 'treeLevel': A, - 'trim': kw('trim'), - 'true': B, - 'tsdebug': A, - 'tsdebug_tree': kw('tsdebug_tree'), - 'TSFE': kw('TSFE'), - 'type': kw('type'), - 'typeNum': kw('typeNum'), - 'types': kw('types'), - 'typolink': A, - 'uid': B, - 'uidInList': kw('uidInList'), - 'uniqueGlobal': B, - 'uniqueLocal': B, - 'unset': kw('unset'), - 'unsetEmpty': B, - 'updated': B, - 'uploadFieldsInTopOfEB': kw('uploadFieldsInTopOfEB'), - 'uploads': B, - 'upper': kw('upper'), - 'url': A, - 'us': B, - 'useCacheHash': kw('useCacheHash'), - 'useLargestItemX': kw('useLargestItemX'), - 'useLargestItemY': kw('useLargestItemY'), - 'USER': kw('USER'), - 'user': kw('user'), - 'USER_INT': kw('USER_INT'), - 'user_task': B, - 'useragent': A, - 'USERDEF1': B, - 'USERDEF1RO': B, - 'USERDEF2': B, - 'USERDEF2RO': B, - 'userdefined': kw('userdefined'), - 'userFunc': A, - 'userfunction': kw('userfunction'), - 'usergroup': B, - 'userid': kw('userid'), - 'USERNAME_substToken': kw('USERNAME_substToken'), - 'userProc': kw('userProc'), - 'USR': B, - 'USRRO': B, - 'value': kw('value'), - 'valueArray': kw('valueArray'), - 'version': A, - 'view': A, - 'wave': kw('wave'), - 'web_func': B, - 'web_info': B, - 'web_layout': B, - 'web_list': B, - 'web_ts': kw('web_ts'), - 'where': kw('where'), - 'width': kw('width'), - 'wiz': kw('wiz'), - 'wordSpacing': kw('wordSpacing'), - 'workArea': kw('workArea'), - 'workOnSubpart': A, - 'wrap': kw('wrap'), - 'wrap1': kw('wrap1'), - 'wrap2': kw('wrap2'), - 'wrap3': kw('wrap3'), - 'wrapAfterTags': kw('wrapAfterTags'), - 'wrapAlign': kw('wrapAlign'), - 'wrapFieldName': kw('wrapFieldName'), - 'wrapItemAndSub': kw('wrapItemAndSub'), - 'wrapNonWrappedLines': kw('wrapNonWrappedLines'), - 'wraps': kw('wraps'), - 'xhtml_cleaning': kw('xhtml_cleaning'), - 'xhtml_strict': B, - 'xhtml_trans': B, - 'xmlprologue': kw('xmlprologue'), - 'XY': B - }; - }(); - - var isOperatorChar = /[\+\-\*\&\%\/=<>!\?]/; - var inValue = false; - - function readRegexp(stream) { - var escaped = false, next, inSet = false; - while ((next = stream.next()) != null) { - if (!escaped) { - if (next === "/" && !inSet) return; - if (next === "[") inSet = true; - else if (inSet && next === "]") inSet = false; - } - escaped = !escaped && next === "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - - function ret(tp, style, cont) { - type = tp; - content = cont; - return style; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch === "\n") { - inValue = false; - } - - if (ch === "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { - return ret("number", "number"); - } - if (ch === "." && stream.match("..")) { - return ret("spread", "meta"); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } - if ((ch === '<' || ch === '>' || ch === '.' || (ch === '=' && stream.peek() !== '<'))) { - inValue = true; - return ret(ch, 'operator') - } - if (!inValue && /[\[\]\(\),;\:\.\<\>\=]/.test(ch)) { - return ret(ch, 'operator') - } - if (ch === "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } - if (ch === "0" && stream.eat(/o/i)) { - stream.eatWhile(/[0-7]/i); - return ret("number", "number"); - } - if (ch === "0" && stream.eat(/b/i)) { - stream.eatWhile(/[01]/i); - return ret("number", "number"); - } - if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d+)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } - if (ch === "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } - if (expressionAllowed(stream, state, 1)) { - readRegexp(stream); - stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); - return ret("regexp", "string-2"); - } - - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } - if (ch === "`") { - state.tokenize = tokenQuasi; - return tokenQuasi(stream, state); - } - if (ch === "#") { - stream.skipToEnd(); - return ret("comment", "comment"); - } - if (isOperatorChar.test(ch)) { - if (ch !== ">" || !state.lexical || state.lexical.type !== ">") { - stream.eatWhile(isOperatorChar); - } - return ret("operator", "operator", stream.current()); - } - if (wordRE.test(ch)) { - stream.eatWhile(wordRE); - var word = stream.current(); - if (keywords.propertyIsEnumerable(word)) { - var kw = keywords[word]; - return ret(kw.type, kw.style, word); - } - if (word === "async" && stream.match(/^\s*[\(\w]/, false)) { - return ret("async", "keyword", word); - } - if (inValue) { - return ret('string', 'string', word); - } - return ret("variable", "other", word); - } - } - - function tokenString(quote) { - return function (stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next === "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch === "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch === "*"); - } - return ret("comment", "comment"); - } - - function tokenQuasi(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (!escaped && (next === "`" || next === "$" && stream.eat("{"))) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && next === "\\"; - } - return ret("quasi", "string-2", stream.current()); - } - - var brackets = "([{}])"; - // This is a crude lookahead trick to try and notice that we're - // parsing the argument patterns for a fat-arrow function before we - // actually hit the arrow token. It only works if the arrow is on - // the same line as the arguments and there's no strange noise - // (comments) in between. Fallback is to only notice when we hit the - // arrow, and not declare the arguments as locals for the arrow - // body. - function findFatArrow(stream, state) { - if (state.fatArrowAt) state.fatArrowAt = null; - var arrow = stream.string.indexOf("=>", stream.start); - if (arrow < 0) return; - - var depth = 0, sawSomething = false; - for (var pos = arrow - 1; pos >= 0; --pos) { - var ch = stream.string.charAt(pos); - var bracket = brackets.indexOf(ch); - if (bracket >= 0 && bracket < 3) { - if (!depth) { - ++pos; - break; - } - if (--depth == 0) { - if (ch === "(") sawSomething = true; - break; - } - } else if (bracket >= 3 && bracket < 6) { - ++depth; - } else if (wordRE.test(ch)) { - sawSomething = true; - } else if (/["'\/]/.test(ch)) { - return; - } else if (sawSomething && !depth) { - ++pos; - break; - } - } - if (sawSomething && !depth) state.fatArrowAt = pos; - } - - // Parser - - var atomicTypes = { - "atom": true, - "number": true, - "variable": true, - "string": true, - "regexp": true - }; - - function TSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - for (var cx = state.context; cx; cx = cx.prev) { - for (var v = cx.vars; v; v = v.next) - if (v.name == varname) return true; - } - } - - function parseTS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; - cx.stream = stream; - cx.marked = null, cx.cc = cc; - cx.style = style; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while (true) { - var combinator = cc.length ? cc.pop() : statement; - if (combinator(type, content)) { - while (cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type === "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - - function cont() { - pass.apply(null, arguments); - return true; - } - - function register(varname) { - function inList(list) { - for (var v = list; v; v = v.next) - if (v.name == varname) return true; - return false; - } - - var state = cx.state; - cx.marked = "def"; - if (state.context) { - if (inList(state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else { - if (inList(state.globalVars)) return; - if (parserConfig.globalVars) - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - - function pushcontext() { - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - cx.state.localVars = defaultVars; - } - - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - - function pushlex(type, info) { - var result = function () { - var state = cx.state, indent = state.indented; - if (state.lexical.type === "stat") indent = state.lexical.indented; - else for (var outer = state.lexical; outer && outer.type === ")" && outer.align; outer = outer.prev) - indent = outer.indented; - state.lexical = new TSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type === ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - - poplex.lex = true; - - function expect(wanted) { - function exp(type) { - if (type == wanted) return cont(); - else if (wanted === ";") return pass(); - else return cont(exp); - }; - return exp; - } - - function statement(type, value) { - if (type === "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); - if (type === "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); - if (type === "keyword b") return cont(pushlex("form"), statement, poplex); - if (type === "{") return cont(pushlex("}"), block, poplex); - if (type === ";") return cont(); - if (type === "if") { - if (cx.state.lexical.info === "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) { - cx.state.cc.pop()(); - } - return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); - } - if (type === "function") return cont(functiondef); - if (type === "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type === "variable") { - return cont(pushlex("stat"), maybelabel); - } - if (type === "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), - block, poplex, poplex); - if (type === "case") return cont(expression, expect(":")); - if (type === "default") return cont(expect(":")); - if (type === "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type === "class") return cont(pushlex("form"), className, poplex); - if (type === "export") return cont(pushlex("stat"), afterExport, poplex); - if (type === "import") return cont(pushlex("stat"), afterImport, poplex); - if (type === "module") return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) - if (type === "async") return cont(statement) - if (value === "@") return cont(expression, statement) - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - - function expression(type) { - return expressionInner(type, false); - } - - function expressionNoComma(type) { - return expressionInner(type, true); - } - - function parenExpr(type) { - if (type !== "(") return pass() - return cont(pushlex(")"), expression, expect(")"), poplex) - } - - function expressionInner(type, noComma) { - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) { - return cont(maybeop); - } - if (type === "keyword c") { - return cont(noComma ? maybeexpressionNoComma : maybeexpression); - } - if (type === "(") { - return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - } - if (type === "operator" || type === "spread") { - return cont(noComma ? expressionNoComma : expression); - } - if (type === "[") { - return cont(pushlex("]"), arrayLiteral, poplex, maybeop); - } - if (type === "{") { - return contCommasep(objprop, "}", null, maybeop); - } - return cont(); - } - - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } - - function maybeoperatorComma(type, value) { - if (type === ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type === "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); - if (type === "operator") { - if (/\+\+|--/.test(value)) return cont(me); - if (value === "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type === "quasi") { - return pass(quasi, me); - } - if (type === ";") return; - if (type === "(") return contCommasep(expressionNoComma, ")", "call", me); - if (type === ".") return cont(property, me); - if (type === "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - } - - function quasi(type, value) { - if (type !== "quasi") return pass(); - if (value.slice(value.length - 2) !== "${") return cont(quasi); - return cont(expression, continueQuasi); - } - - function continueQuasi(type) { - if (type === "}") { - cx.marked = "string-2"; - cx.state.tokenize = tokenQuasi; - return cont(quasi); - } - } - - function arrowBody(type) { - findFatArrow(cx.stream, cx.state); - return pass(type === "{" ? statement : expression); - } - - function arrowBodyNoComma(type) { - findFatArrow(cx.stream, cx.state); - return pass(type === "{" ? statement : expressionNoComma); - } - - function maybeTarget(noComma) { - return function (type) { - if (type === ".") return cont(noComma ? targetNoComma : target); - else return pass(noComma ? expressionNoComma : expression); - }; - } - - function target(_, value) { - if (value === "target") { - cx.marked = "keyword"; - return cont(maybeoperatorComma); - } - } - - function targetNoComma(_, value) { - if (value === "target") { - cx.marked = "keyword"; - return cont(maybeoperatorNoComma); - } - } - - function maybelabel(type) { - if (type === ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - - function property(type) { - if (type === "variable") { - cx.marked = "property"; - return cont(); - } - } - - function objprop(type, value) { - if (type === "async") { - cx.marked = "property"; - return cont(objprop); - } else if (type === "variable" || cx.style === "keyword") { - cx.marked = "property"; - if (value === "get" || value === "set") return cont(getterSetter); - return cont(afterprop); - } else if (type === "number" || type === "string") { - cx.marked = cx.style + " property"; - return cont(afterprop); - } else if (type === "jsonld-keyword") { - return cont(afterprop); - } else if (type === "modifier") { - return cont(objprop) - } else if (type === "[") { - return cont(expression, expect("]"), afterprop); - } else if (type === "spread") { - return cont(expression, afterprop); - } else if (type === ":") { - return pass(afterprop) - } - } - - function getterSetter(type) { - if (type !== "variable") return pass(afterprop); - cx.marked = "property"; - return cont(functiondef); - } - - function afterprop(type) { - if (type === ":") return cont(expressionNoComma); - if (type === "(") return pass(functiondef); - } - - function commasep(what, end, sep) { - function proceed(type, value) { - if (sep ? sep.indexOf(type) > -1 : type === ",") { - var lex = cx.state.lexical; - if (lex.info === "call") lex.pos = (lex.pos || 0) + 1; - return cont(function (type, value) { - if (type == end || value == end) return pass() - return pass(what) - }, proceed); - } - if (type == end || value == end) return cont(); - return cont(expect(end)); - } - - return function (type, value) { - if (type == end || value == end) return cont(); - return pass(what, proceed); - }; - } - - function contCommasep(what, end, info) { - for (var i = 3; i < arguments.length; i++) - cx.cc.push(arguments[i]); - return cont(pushlex(end, info), commasep(what, end), poplex); - } - - function block(type) { - if (type === "}") return cont(); - return pass(statement, block); - } - - function typeexpr(type) { - if (type === "variable") { - cx.marked = "type"; - return cont(afterType); - } - if (type === "string" || type === "number" || type === "atom") return cont(afterType); - if (type === "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) - if (type === "(") return cont(commasep(typearg, ")"), maybeReturnType) - } - - function maybeReturnType(type) { - if (type === "=>") return cont(typeexpr) - } - - function typeprop(type, value) { - if (type === "variable" || cx.style === "keyword") { - cx.marked = "property" - return cont(typeprop) - } else if (value === "?") { - return cont(typeprop) - } else if (type === ":") { - return cont(typeexpr) - } else if (type === "[") { - return cont(expression, null, expect("]"), typeprop) - } - } - - function typearg(type) { - if (type === "variable") return cont(typearg) - else if (type === ":") return cont(typeexpr) - } - - function afterType(type, value) { - if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) - if (value === "|" || type === ".") return cont(typeexpr) - if (type === "[") return cont(expect("]"), afterType) - if (value === "extends") return cont(typeexpr) - } - - function vardef() { - return pass(pattern, null, maybeAssign, vardefCont); - } - - function pattern(type, value) { - if (type === "modifier") return cont(pattern) - if (type === "variable") { - register(value); - return cont(); - } - if (type === "spread") return cont(pattern); - if (type === "[") return contCommasep(pattern, "]"); - if (type === "{") return contCommasep(proppattern, "}"); - } - - function proppattern(type, value) { - if (type === "variable" && !cx.stream.match(/^\s*:/, false)) { - register(value); - return cont(maybeAssign); - } - if (type === "variable") cx.marked = "property"; - if (type === "spread") return cont(pattern); - if (type === "}") return pass(); - return cont(expect(":"), pattern, maybeAssign); - } - - function maybeAssign(_type, value) { - if (value === "=") return cont(expressionNoComma); - } - - function vardefCont(type) { - if (type === ",") return cont(vardef); - } - - function maybeelse(type, value) { - if (type === "keyword b" && value === "else") return cont(pushlex("form", "else"), statement, poplex); - } - - function forspec(type) { - if (type === "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); - } - - function forspec1(type) { - if (type === "var") return cont(vardef, expect(";"), forspec2); - if (type === ";") return cont(forspec2); - if (type === "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - - function formaybeinof(_type, value) { - if (value === "in" || value === "of") { - cx.marked = "keyword"; - return cont(expression); - } - return cont(maybeoperatorComma, forspec2); - } - - function forspec2(type, value) { - if (type === ";") return cont(forspec3); - if (value === "in" || value === "of") { - cx.marked = "keyword"; - return cont(expression); - } - return pass(expression, expect(";"), forspec3); - } - - function forspec3(type) { - if (type !== ")") cont(expression); - } - - function functiondef(type, value) { - if (value === "*") { - cx.marked = "keyword"; - return cont(functiondef); - } - if (type === "variable") { - register(value); - return cont(functiondef); - } - if (type === "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, null, statement, popcontext); - } - - function funarg(type) { - if (type === "spread") return cont(funarg); - return pass(pattern, null, maybeAssign); - } - - function classExpression(type, value) { - // Class expressions may have an optional name. - if (type === "variable") return className(type, value); - return classNameAfter(type, value); - } - - function className(type, value) { - if (type === "variable") { - register(value); - return cont(classNameAfter); - } - } - - function classNameAfter(type, value) { - if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, classNameAfter) - if (value === "extends" || value === "implements") - return cont(expression, classNameAfter); - if (type === "{") return cont(pushlex("}"), classBody, poplex); - } - - function classBody(type, value) { - if (type === "variable" || cx.style === "keyword") { - if ((value === "async" || value === "static" || value === "get" || value === "set") && - cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) { - cx.marked = "keyword"; - return cont(classBody); - } - cx.marked = "property"; - return cont(functiondef, classBody); - } - if (type === "[") - return cont(expression, expect("]"), functiondef, classBody) - if (value === "*") { - cx.marked = "keyword"; - return cont(classBody); - } - if (type === ";") return cont(classBody); - if (type === "}") return cont(); - if (value === "@") return cont(expression, classBody) - } - - function classfield(type, value) { - if (value === "?") return cont(classfield) - if (type === ":") return cont(typeexpr, maybeAssign) - if (value === "=") return cont(expressionNoComma) - return pass(functiondef) - } - - function afterExport(type, value) { - if (value === "*") { - cx.marked = "keyword"; - return cont(maybeFrom, expect(";")); - } - if (value === "default") { - cx.marked = "keyword"; - return cont(expression, expect(";")); - } - if (type === "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); - return pass(statement); - } - - function exportField(type, value) { - if (value === "as") { - cx.marked = "keyword"; - return cont(expect("variable")); - } - if (type === "variable") return pass(expressionNoComma, exportField); - } - - function afterImport(type) { - if (type === "string") return cont(); - return pass(importSpec, maybeMoreImports, maybeFrom); - } - - function importSpec(type, value) { - if (type === "{") return contCommasep(importSpec, "}"); - if (type === "variable") register(value); - if (value === "*") cx.marked = "keyword"; - return cont(maybeAs); - } - - function maybeMoreImports(type) { - if (type === ",") return cont(importSpec, maybeMoreImports) - } - - function maybeAs(_type, value) { - if (value === "as") { - cx.marked = "keyword"; - return cont(importSpec); - } - } - - function maybeFrom(_type, value) { - if (value === "from") { - cx.marked = "keyword"; - return cont(expression); - } - } - - function arrayLiteral(type) { - if (type === "]") return cont(); - return pass(commasep(expressionNoComma, "]")); - } - - function isContinuedStatement(state, textAfter) { - return state.lastType === "operator" || state.lastType === "," || - isOperatorChar.test(textAfter.charAt(0)) || - /[,.]/.test(textAfter.charAt(0)); - } - - // Interface - - return { - startState: function (basecolumn) { - var state = { - tokenize: tokenBase, - lastType: "sof", - cc: [], - lexical: new TSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: basecolumn || 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars === "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function (stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - findFatArrow(stream, state); - } - if (state.tokenize != tokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type === "comment") return style; - state.lastType = type === "operator" && (content === "++" || content === "--") ? "incdec" : type; - return parseTS(state, style, type, content, stream); - }, - - indent: function (state, textAfter) { - if (state.tokenize == tokenComment) return CodeMirror.Pass; - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top - // Kludge to prevent 'maybelse' from blocking lexical scope pops - if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; - } - while ((lexical.type === "stat" || lexical.type === "form") && - (firstChar === "}" || ((top = state.cc[state.cc.length - 1]) && - (top == maybeoperatorComma || top == maybeoperatorNoComma) && - !/^[,\.=+\-*:?[\(]/.test(textAfter)))) - lexical = lexical.prev; - if (statementIndent && lexical.type === ")" && lexical.prev.type === "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type === "vardef") return lexical.indented + (state.lastType === "operator" || state.lastType === "," ? lexical.info + 1 : 0); - else if (type === "form" && firstChar === "{") return lexical.indented; - else if (type === "form") return lexical.indented + indentUnit; - else if (type === "stat") - return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); - else if (lexical.info === "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "#", - fold: "brace", - closeBrackets: "()[]{}''\"\"``", - - helperType: "typoscript", - - expressionAllowed: expressionAllowed, - skipExpression: function (state) { - var top = state.cc[state.cc.length - 1]; - if (top == expression || top == expressionNoComma) state.cc.pop() - } - }; - }); +(function(mod) { + if (typeof exports === "object" && typeof module === "object") // CommonJS + mod(require("cm/lib/codemirror")); + else if (typeof define === "function" && define.amd) // AMD + define(["cm/lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { + "use strict"; + + function expressionAllowed(stream, state, backUp) { + return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || + (state.lastType === "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) + } + + CodeMirror.defineMode("typoscript", function(config, parserConfig) { + var indentUnit = config.indentUnit; + var statementIndent = parserConfig.statementIndent; + var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; + + // Tokenizer + + var keywords = function() { + function kw(type) { + return {type: type, style: "keyword"}; + } + + var A = kw("keyword a"), B = kw("keyword b"); + + return { + '_CSS_DEFAULT_STYLE': kw('_CSS_DEFAULT_STYLE'), + '_DEFAULT_PI_VARS': kw('_DEFAULT_PI_VARS'), + '_GIFBUILDER': kw('_GIFBUILDER'), + '_LOCAL_LANG': kw('_LOCAL_LANG'), + '_offset': kw('_offset'), + 'absRefPrefix': kw('absRefPrefix'), + 'accessibility': kw('accessibility'), + 'accessKey': kw('accessKey'), + 'ACT': B, + 'ACTIFSUB': B, + 'ACTIFSUBRO': kw('ACTIFSUBRO'), + 'ACTRO': B, + 'addAttributes': kw('addAttributes'), + 'addExtUrlsAndShortCuts': kw('addExtUrlsAndShortCuts'), + 'addItems': kw('addItems'), + 'additionalHeaders': kw('additionalHeaders'), + 'additionalParams': kw('additionalParams'), + 'addParams': kw('addParams'), + 'addQueryString': kw('addQueryString'), + 'adjustItemsH': kw('adjustItemsH'), + 'adjustSubItemsH': kw('adjustSubItemsH'), + 'admPanel': A, + 'after': kw('after'), + 'afterImg': kw('afterImg'), + 'afterImgLink': kw('afterImgLink'), + 'afterImgTagParams': kw('afterImgTagParams'), + 'afterROImg': kw('afterROImg'), + 'afterWrap': kw('afterWrap'), + 'age': kw('age'), + 'alertPopups': kw('alertPopups'), + 'align': kw('align'), + 'all': B, + 'allow': kw('allow'), + 'allowCaching': kw('allowCaching'), + 'allowedAttribs': kw('allowedAttribs'), + 'allowedClasses': kw('allowedClasses'), + 'allowedCols': kw('allowedCols'), + 'allowedNewTables': kw('allowedNewTables'), + 'allowTags': kw('allowTags'), + 'allStdWrap': kw('allStdWrap'), + 'allWrap': kw('allWrap'), + 'alt_print': A, + 'alternativeSortingField': kw('alternativeSortingField'), + 'alternativeTempPath': kw('alternativeTempPath'), + 'altIcons': kw('altIcons'), + 'altImgResource': kw('altImgResource'), + 'altLabels': kw('altLabels'), + 'altTarget': kw('altTarget'), + 'altText': kw('altText'), + 'altUrl': kw('altUrl'), + 'altUrl_noDefaultParams': kw('altUrl_noDefaultParams'), + 'altWrap': kw('altWrap'), + 'always': kw('always'), + 'alwaysActivePIDlist': kw('alwaysActivePIDlist'), + 'alwaysLink': kw('alwaysLink'), + 'andWhere': kw('andWhere'), + 'angle': kw('angle'), + 'antiAlias': kw('antiAlias'), + 'append': kw('append'), + 'applyTotalH': kw('applyTotalH'), + 'applyTotalW': kw('applyTotalW'), + 'archive': kw('archive'), + 'ascii': B, + 'ATagAfterWrap': kw('ATagAfterWrap'), + 'ATagBeforeWrap': kw('ATagBeforeWrap'), + 'ATagParams': kw('ATagParams'), + 'ATagTitle': kw('ATagTitle'), + 'atLeast': B, + 'atMost': B, + 'attribute': kw('attribute'), + 'auth': A, + 'autoLevels': kw('autoLevels'), + 'autonumber': kw('autonumber'), + 'backColor': kw('backColor'), + 'background': kw('background'), + 'baseURL': kw('baseURL'), + 'BE': B, + 'be_groups': B, + 'be_users': B, + 'before': kw('before'), + 'beforeImg': kw('beforeImg'), + 'beforeImgLink': kw('beforeImgLink'), + 'beforeImgTagParams': kw('beforeImgTagParams'), + 'beforeROImg': kw('beforeROImg'), + 'beforeWrap': kw('beforeWrap'), + 'begin': kw('begin'), + 'bgCol': kw('bgCol'), + 'bgImg': kw('bgImg'), + 'blur': kw('blur'), + 'bm': kw('bm'), + 'bodyTag': kw('bodyTag'), + 'bodyTagAdd': kw('bodyTagAdd'), + 'bodyTagCObject': kw('bodyTagCObject'), + 'bodytext': kw('bodytext'), + 'border': kw('border'), + 'borderCol': kw('borderCol'), + 'borderThick': kw('borderThick'), + 'bottomBackColor': kw('bottomBackColor'), + 'bottomContent': kw('bottomContent'), + 'bottomHeight': kw('bottomHeight'), + 'bottomImg': kw('bottomImg'), + 'bottomImg_mask': kw('bottomImg_mask'), + 'BOX': B, + 'br': kw('br'), + 'browse': B, + 'browser': A, + 'brTag': kw('brTag'), + 'bullet': kw('bullet'), + 'bulletlist': kw('bulletlist'), + 'bullets': B, + 'bytes': kw('bytes'), + 'cache': A, + 'cache_clearAtMidnight': kw('cache_clearAtMidnight'), + 'cache_period': kw('cache_period'), + 'caption': kw('caption'), + 'caption_stdWrap': kw('caption_stdWrap'), + 'captionHeader': kw('captionHeader'), + 'captionSplit': kw('captionSplit'), + 'CARRAY': kw('CARRAY'), + 'CASE': kw('CASE'), + 'case': kw('case'), + 'casesensitiveComp': kw('casesensitiveComp'), + 'cellpadding': kw('cellpadding'), + 'cellspacing': kw('cellspacing'), + 'char': kw('char'), + 'charcoal': kw('charcoal'), + 'charMapConfig': kw('charMapConfig'), + 'CHECK': A, + 'check': kw('check'), + 'class': kw('class'), + 'classesAnchor': kw('classesAnchor'), + 'classesCharacter': kw('classesCharacter'), + 'classesImage': kw('classesImage'), + 'classesParagraph': kw('classesParagraph'), + 'clear': kw('clear'), + 'clearCache': kw('clearCache'), + 'clearCache_disable': kw('clearCache_disable'), + 'clearCache_pageGrandParent': kw('clearCache_pageGrandParent'), + 'clearCache_pageSiblingChildren': kw('clearCache_pageSiblingChildren'), + 'clearCacheCmd': kw('clearCacheCmd'), + 'clearCacheLevels': kw('clearCacheLevels'), + 'clearCacheOfPages': kw('clearCacheOfPages'), + 'clickTitleMode': kw('clickTitleMode'), + 'clipboardNumberPads': kw('clipboardNumberPads'), + 'cMargins': kw('cMargins'), + 'COA': kw('COA'), + 'COA_INT': kw('COA_INT'), + 'cObj': A, + 'COBJ_ARRAY': kw('COBJ_ARRAY'), + 'cObject': A, + 'cObjNum': kw('cObjNum'), + 'collapse': kw('collapse'), + 'collections': kw('collections'), + 'color': kw('color'), + 'color1': kw('color1'), + 'color2': kw('color2'), + 'color3': kw('color3'), + 'color4': kw('color4'), + 'colors': kw('colors'), + 'colour': kw('colour'), + 'colPos_list': kw('colPos_list'), + 'colRelations': kw('colRelations'), + 'cols': kw('cols'), + 'colSpace': kw('colSpace'), + 'COMMENT': A, + 'comment_auto': kw('comment_auto'), + 'commentWrap': kw('commentWrap'), + 'compX': kw('compX'), + 'compY': kw('compY'), + 'conf': kw('conf'), + 'CONFIG': kw('CONFIG'), + 'config': A, + 'CONSTANTS': kw('CONSTANTS'), + 'constants': kw('constants'), + 'CONTENT': kw('CONTENT'), + 'content': A, + 'content_from_pid_allowOutsideDomain': kw('content_from_pid_allowOutsideDomain'), + 'contextMenu': kw('contextMenu'), + 'copy': A, + 'copyLevels': kw('copyLevels'), + 'count_HMENU_MENUOBJ': kw('count_HMENU_MENUOBJ'), + 'count_menuItems': kw('count_menuItems'), + 'count_MENUOBJ': kw('count_MENUOBJ'), + 'create': kw('create'), + 'createFoldersInEB': kw('createFoldersInEB'), + 'crop': kw('crop'), + 'csConv': kw('csConv'), + 'CSS_inlineStyle': A, + 'CType': kw('CType'), + 'CUR': B, + 'CURIFSUB': B, + 'CURIFSUBRO': B, + 'current': kw('current'), + 'CURRO': B, + 'curUid': kw('curUid'), + 'cut': A, + 'cWidth': kw('cWidth'), + 'data': kw('data'), + 'dataArray': A, + 'dataWrap': kw('dataWrap'), + 'date': kw('date'), + 'date_stdWrap': kw('date_stdWrap'), + 'datePrefix': kw('datePrefix'), + 'dayofmonth': A, + 'dayofweek': A, + 'DB': kw('DB'), + 'db_list': A, + 'debug': kw('debug'), + 'debugData': kw('debugData'), + 'debugFunc': kw('debugFunc'), + 'debugItemConf': kw('debugItemConf'), + 'debugRenumberedObject': kw('debugRenumberedObject'), + 'default': B, + 'defaultAlign': kw('defaultAlign'), + 'defaultCmd': kw('defaultCmd'), + 'defaultFileUploads': kw('defaultFileUploads'), + 'defaultHeaderType': kw('defaultHeaderType'), + 'defaultOutput': kw('defaultOutput'), + 'defaults': kw('defaults'), + 'defaultType': kw('defaultType'), + 'delete': kw('delete'), + 'denyTags': kw('denyTags'), + 'depth': kw('depth'), + 'DESC': kw('DESC'), + 'description': B, + 'dimensions': kw('dimensions'), + 'direction': kw('direction'), + 'directory': B, + 'directReturn': B, + 'disableAdvanced': kw('disableAdvanced'), + 'disableAllHeaderCode': kw('disableAllHeaderCode'), + 'disableAltText': kw('disableAltText'), + 'disableBodyTag': kw('disableBodyTag'), + 'disableCacheSelector': kw('disableCacheSelector'), + 'disableCharsetHeader': kw('disableCharsetHeader'), + 'disabled': kw('disabled'), + 'disableDelete': kw('disableDelete'), + 'disableDocSelector': kw('disableDocSelector'), + 'disableHideAtCopy': kw('disableHideAtCopy'), + 'disableItems': kw('disableItems'), + 'disableNewContentElementWizard': kw('disableNewContentElementWizard'), + 'disableNoMatchingValueElement': kw('disableNoMatchingValueElement'), + 'disablePageExternalUrl': kw('disablePageExternalUrl'), + 'disablePrefixComment': kw('disablePrefixComment'), + 'disablePrependAtCopy': kw('disablePrependAtCopy'), + 'disableSearchBox': kw('disableSearchBox'), + 'disableSingleTableView': kw('disableSingleTableView'), + 'displayContent': kw('displayContent'), + 'displayFieldIcons': kw('displayFieldIcons'), + 'displayIcons': kw('displayIcons'), + 'displayMessages': kw('displayMessages'), + 'displayRecord': kw('displayRecord'), + 'displayTimes': kw('displayTimes'), + 'distributeX': kw('distributeX'), + 'distributeY': kw('distributeY'), + 'div': B, + 'DIV': kw('DIV'), + 'doctype': kw('doctype'), + 'doctypeSwitch': kw('doctypeSwitch'), + 'DOCUMENT_BODY': kw('DOCUMENT_BODY'), + 'doktype': kw('doktype'), + 'doNotLinkIt': kw('doNotLinkIt'), + 'doNotShowLink': kw('doNotShowLink'), + 'doNotStripHTML': kw('doNotStripHTML'), + 'dontCheckPid': kw('dontCheckPid'), + 'dontLinkIfSubmenu': kw('dontLinkIfSubmenu'), + 'dontWrapInTable': kw('dontWrapInTable'), + 'doubleBrTag': kw('doubleBrTag'), + 'dWorkArea': kw('dWorkArea'), + 'dynCSS': A, + 'edge': kw('edge'), + 'edit': A, + 'edit_access': A, + 'edit_docModuleUpload': kw('edit_docModuleUpload'), + 'edit_pageheader': A, + 'edit_RTE': kw('edit_RTE'), + 'editFieldsAtATime': kw('editFieldsAtATime'), + 'editFormsOnPage': kw('editFormsOnPage'), + 'editIcons': kw('editIcons'), + 'editNoPopup': kw('editNoPopup'), + 'EDITPANEL': kw('EDITPANEL'), + 'editPanel': kw('editPanel'), + 'EFFECT': kw('EFFECT'), + 'elements': kw('elements'), + 'else': B, + 'email': B, + 'emailMeAtLogin': kw('emailMeAtLogin'), + 'emailMess': kw('emailMess'), + 'emboss': kw('emboss'), + 'enable': kw('enable'), + 'encapsLines': kw('encapsLines'), + 'encapsLinesStdWrap': kw('encapsLinesStdWrap'), + 'encapsTagList': kw('encapsTagList'), + 'end': B, + 'entryLevel': kw('entryLevel'), + 'equalH': kw('equalH'), + 'equals': B, + 'everybody': kw('everybody'), + 'excludeDoktypes': kw('excludeDoktypes'), + 'excludeUidList': kw('excludeUidList'), + 'expAll': kw('expAll'), + 'expand': kw('expand'), + 'explode': kw('explode'), + 'ext': kw('ext'), + 'external': B, + 'externalBlocks': kw('externalBlocks'), + 'extTarget': kw('extTarget'), + 'face': kw('face'), + 'false': B, + 'FE': B, + 'fe_adminLib': kw('fe_adminLib'), + 'fe_groups': B, + 'fe_users': B, + 'feadmin': B, + 'field': kw('field'), + 'fieldName': kw('fieldName'), + 'fieldOrder': kw('fieldOrder'), + 'fieldRequired': kw('fieldRequired'), + 'fields': kw('fields'), + 'fieldWrap': kw('fieldWrap'), + 'FILE': kw('FILE'), + 'file': kw('file'), + 'file1': kw('file1'), + 'file2': kw('file2'), + 'file3': kw('file3'), + 'file4': kw('file4'), + 'file5': kw('file5'), + 'filelink': kw('filelink'), + 'filelist': kw('filelist'), + 'FILES': kw('FILES'), + 'files': kw('files'), + 'firstLabel': kw('firstLabel'), + 'firstLabelGeneral': kw('firstLabelGeneral'), + 'fixAttrib': kw('fixAttrib'), + 'flip': kw('flip'), + 'flop': kw('flop'), + 'FLUIDTEMPLATE': kw('FLUIDTEMPLATE'), + 'folder': A, + 'folders': kw('folders'), + 'folderTree': A, + 'foldoutMenu': A, + 'fontColor': kw('fontColor'), + 'fontFile': kw('fontFile'), + 'fontOffset': kw('fontOffset'), + 'fontSize': kw('fontSize'), + 'fontSizeMultiplicator': kw('fontSizeMultiplicator'), + 'forceDisplayFieldIcons': kw('forceDisplayFieldIcons'), + 'forceDisplayIcons': kw('forceDisplayIcons'), + 'forceTemplateParsing': kw('forceTemplateParsing'), + 'forceTypeValue': kw('forceTypeValue'), + 'FORM': kw('FORM'), + 'format': kw('format'), + 'ftu': kw('ftu'), + 'function': kw('function'), + 'Functions': A, + 'gamma': kw('gamma'), + 'gapBgCol': kw('gapBgCol'), + 'gapLineCol': kw('gapLineCol'), + 'gapLineThickness': kw('gapLineThickness'), + 'gapWidth': kw('gapWidth'), + 'get': kw('get'), + 'getBorder': kw('getBorder'), + 'getLeft': kw('getLeft'), + 'getRight': kw('getRight'), + 'GIFBUILDER': kw('GIFBUILDER'), + 'global': kw('global'), + 'globalNesting': kw('globalNesting'), + 'globalString': kw('globalString'), + 'globalVar': kw('globalVar'), + 'GMENU': kw('GMENU'), + 'GP': kw('GP'), + 'gray': kw('gray'), + 'group': kw('group'), + 'groupBy': kw('groupBy'), + 'groupid': kw('groupid'), + 'header': B, + 'header_layout': kw('header_layout'), + 'headerComment': kw('headerComment'), + 'headerData': kw('headerData'), + 'headerSpace': kw('headerSpace'), + 'headTag': kw('headTag'), + 'height': kw('height'), + 'helpText': kw('helpText'), + 'hidden': kw('hidden'), + 'hiddenFields': kw('hiddenFields'), + 'hide': kw('hide'), + 'hideButCreateMap': kw('hideButCreateMap'), + 'hidePStyleItems': kw('hidePStyleItems'), + 'hideRecords': kw('hideRecords'), + 'highColor': kw('highColor'), + 'history': kw('history'), + 'HMENU': kw('HMENU'), + 'hostname': A, + 'hour': A, + 'HTML': kw('HTML'), + 'html': B, + 'HTMLparser': kw('HTMLparser'), + 'HTMLparser_tags': kw('HTMLparser_tags'), + 'htmlSpecialChars': kw('htmlSpecialChars'), + 'htmlTag_dir': kw('htmlTag_dir'), + 'htmlTag_langKey': kw('htmlTag_langKey'), + 'htmlTag_setParams': kw('htmlTag_setParams'), + 'http': kw('http'), + 'icon': kw('icon'), + 'icon_image_ext_list': kw('icon_image_ext_list'), + 'icon_link': kw('icon_link'), + 'iconCObject': kw('iconCObject'), + 'id': B, + 'IENV': kw('IENV'), + 'if': B, + 'ifEmpty': B, + 'IFSUB': B, + 'IFSUBRO': B, + 'IMAGE': kw('IMAGE'), + 'image': B, + 'image_frames': kw('image_frames'), + 'imageLinkWrap': kw('imageLinkWrap'), + 'imagePath': kw('imagePath'), + 'images': kw('images'), + 'imageWrapIfAny': kw('imageWrapIfAny'), + 'IMG_RESOURCE': kw('IMG_RESOURCE'), + 'imgList': A, + 'imgMap': kw('imgMap'), + 'imgMapExtras': kw('imgMapExtras'), + 'imgMax': kw('imgMax'), + 'IMGMENU': kw('IMGMENU'), + 'IMGMENUITEM': kw('IMGMENUITEM'), + 'imgNameNotRandom': kw('imgNameNotRandom'), + 'imgNamePrefix': kw('imgNamePrefix'), + 'imgObjNum': kw('imgObjNum'), + 'imgParams': kw('imgParams'), + 'imgPath': kw('imgPath'), + 'imgResource': A, + 'imgStart': kw('imgStart'), + 'IMGTEXT': kw('IMGTEXT'), + 'imgText': A, + 'import': kw('import'), + 'inBranch': B, + 'inc': kw('inc'), + 'INCLUDE_TYPOSCRIPT': kw('INCLUDE_TYPOSCRIPT'), + 'includeCSS': kw('includeCSS'), + 'includeLibrary': kw('includeLibrary'), + 'includeNotInMenu': kw('includeNotInMenu'), + 'index': kw('index'), + 'index_descrLgd': kw('index_descrLgd'), + 'index_enable': kw('index_enable'), + 'index_externals': kw('index_externals'), + 'info': A, + 'inlineStyle2TempFile': kw('inlineStyle2TempFile'), + 'innerStdWrap': kw('innerStdWrap'), + 'innerStdWrap_all': kw('innerStdWrap_all'), + 'innerWrap': kw('innerWrap'), + 'innerWrap2': kw('innerWrap2'), + 'input': kw('input'), + 'inputLevels': kw('inputLevels'), + 'insertData': kw('insertData'), + 'intensity': kw('intensity'), + 'intTarget': kw('intTarget'), + 'intval': kw('intval'), + 'invert': kw('invert'), + 'IP': A, + 'IProcFunc': kw('IProcFunc'), + 'isFalse': B, + 'isGreaterThan': B, + 'isInList': B, + 'isLessThan': B, + 'isPositive': B, + 'isTrue': B, + 'itemArrayProcFunc': kw('itemArrayProcFunc'), + 'itemH': kw('itemH'), + 'items': kw('items'), + 'itemsProcFunc': kw('itemsProcFunc'), + 'iterations': kw('iterations'), + 'join': kw('join'), + 'JSwindow': A, + 'JSWindow': kw('JSWindow'), + 'JSwindow_params': kw('JSwindow_params'), + 'keep': kw('keep'), + 'keepEntries': kw('keepEntries'), + 'keepNonMatchedTags': kw('keepNonMatchedTags'), + 'key': kw('key'), + 'keyword3': B, + 'LABEL': A, + 'label': kw('label'), + 'labelStdWrap': kw('labelStdWrap'), + 'labelWrap': kw('labelWrap'), + 'lang': kw('lang'), + 'language': B, + 'language_alt': kw('language_alt'), + 'languageField': kw('languageField'), + 'layout': A, + 'left': kw('left'), + 'leftjoin': kw('leftjoin'), + 'levels': kw('levels'), + 'leveltitle': B, + 'leveluid': kw('leveluid'), + 'lib': A, + 'limit': kw('limit'), + 'line': kw('line'), + 'lineColor': kw('lineColor'), + 'lineThickness': kw('lineThickness'), + 'linkPrefix': kw('linkPrefix'), + 'linkTitleToSelf': kw('linkTitleToSelf'), + 'linkVars': kw('linkVars'), + 'linkWrap': kw('linkWrap'), + 'list': B, + 'listNum': kw('listNum'), + 'listOnlyInSingleTableView': kw('listOnlyInSingleTableView'), + 'LIT': kw('LIT'), + 'lm': kw('lm'), + 'LOAD_REGISTER': kw('LOAD_REGISTER'), + 'locale_all': kw('locale_all'), + 'localNesting': kw('localNesting'), + 'locationData': kw('locationData'), + 'lockToIP': kw('lockToIP'), + 'login': B, + 'loginUser': A, + 'longdescURL': kw('longdescURL'), + 'lowColor': kw('lowColor'), + 'lower': kw('lower'), + 'LR': kw('LR'), + 'mailform': B, + 'mailto': kw('mailto'), + 'main': kw('main'), + 'makelinks': kw('makelinks'), + 'markerWrap': kw('markerWrap'), + 'marks': A, + 'mask': kw('mask'), + 'max': kw('max'), + 'maxAge': kw('maxAge'), + 'maxChars': kw('maxChars'), + 'maxH': kw('maxH'), + 'maxHeight': kw('maxHeight'), + 'maxItems': kw('maxItems'), + 'maxW': kw('maxW'), + 'maxWidth': kw('maxWidth'), + 'maxWInText': kw('maxWInText'), + 'media': B, + 'menu': B, + 'menu_type': kw('menu_type'), + 'menuHeight': kw('menuHeight'), + 'menuName': kw('menuName'), + 'menuOffset': kw('menuOffset'), + 'menuWidth': kw('menuWidth'), + 'message_page_is_being_generated': kw('message_page_is_being_generated'), + 'message_preview': kw('message_preview'), + 'META': kw('META'), + 'meta': kw('meta'), + 'metaCharset': kw('metaCharset'), + 'method': kw('method'), + 'min': kw('min'), + 'minH': kw('minH'), + 'minItems': kw('minItems'), + 'minute': A, + 'minW': kw('minW'), + 'mod': B, + 'mode': kw('mode'), + 'module': A, + 'month': A, + 'move_wizard': A, + 'MP_defaults': kw('MP_defaults'), + 'MP_disableTypolinkClosestMPvalue': kw('MP_disableTypolinkClosestMPvalue'), + 'MP_mapRootPoints': kw('MP_mapRootPoints'), + 'MULTIMEDIA': kw('MULTIMEDIA'), + 'multimedia': B, + 'name': kw('name'), + 'negate': B, + 'nesting': kw('nesting'), + 'neverHideAtCopy': kw('neverHideAtCopy'), + 'new': A, + 'NEW': B, + 'new_wizard': A, + 'newPageWiz': kw('newPageWiz'), + 'newRecordFromTable': kw('newRecordFromTable'), + 'newWindow': kw('newWindow'), + 'newWizards': kw('newWizards'), + 'next': kw('next'), + 'niceText': kw('niceText'), + 'nicetext': kw('nicetext'), + 'NO': B, + 'no_cache': kw('no_cache'), + 'no_search': kw('no_search'), + 'noAttrib': kw('noAttrib'), + 'noCache': kw('noCache'), + 'noCreateRecordsLink': kw('noCreateRecordsLink'), + 'noLink': kw('noLink'), + 'noMatchingValue_label': kw('noMatchingValue_label'), + 'nonCachedSubst': kw('nonCachedSubst'), + 'none': B, + 'nonTypoTagStdWrap': kw('nonTypoTagStdWrap'), + 'nonTypoTagUserFunc': kw('nonTypoTagUserFunc'), + 'nonWrappedTag': kw('nonWrappedTag'), + 'noOrderBy': kw('noOrderBy'), + 'noPageTitle': kw('noPageTitle'), + 'noResultObj': A, + 'noThumbsInEB': kw('noThumbsInEB'), + 'noThumbsInRTEimageSelect': kw('noThumbsInRTEimageSelect'), + 'noTrimWrap': kw('noTrimWrap'), + 'noValueInsert': kw('noValueInsert'), + 'numRows': A, + 'obj': kw('obj'), + 'offset': kw('offset'), + 'onlineWorkspaceInfo': kw('onlineWorkspaceInfo'), + 'onlyCurrentPid': kw('onlyCurrentPid'), + 'opacity': kw('opacity'), + 'options': A, + 'orderBy': kw('orderBy'), + 'outerWrap': kw('outerWrap'), + 'outline': kw('outline'), + 'outputLevels': kw('outputLevels'), + 'override': kw('override'), + 'overrideAttribs': kw('overrideAttribs'), + 'overrideId': kw('overrideId'), + 'overridePageModule': kw('overridePageModule'), + 'overrideWithExtension': kw('overrideWithExtension'), + 'PAGE': kw('PAGE'), + 'page': A, + 'PAGE_TARGET': kw('PAGE_TARGET'), + 'PAGE_TSCONFIG_ID': kw('PAGE_TSCONFIG_ID'), + 'PAGE_TSCONFIG_IDLIST': kw('PAGE_TSCONFIG_IDLIST'), + 'PAGE_TSCONFIG_STR': kw('PAGE_TSCONFIG_STR'), + 'pageFrameObj': kw('pageFrameObj'), + 'pages': B, + 'pages_language_overlay': B, + 'pageTitleFirst': kw('pageTitleFirst'), + 'pageTree': A, + 'parameter': kw('parameter'), + 'params': kw('params'), + 'parseFunc': kw('parseFunc'), + 'parseFunc_RTE': B, + 'parser': kw('parser'), + 'password': kw('password'), + 'paste': A, + 'path': kw('path'), + 'permissions': kw('permissions'), + 'perms': A, + 'pid': B, + 'pid_list': kw('pid_list'), + 'pidInList': kw('pidInList'), + 'PIDinRootline': A, + 'PIDupinRootline': A, + 'pixelSpaceFontSizeRef': kw('pixelSpaceFontSizeRef'), + 'plaintextLib': kw('plaintextLib'), + 'plainTextStdWrap': kw('plainTextStdWrap'), + 'plugin': A, + 'postCObject': kw('postCObject'), + 'postLineBlanks': kw('postLineBlanks'), + 'postLineChar': kw('postLineChar'), + 'postLineLen': kw('postLineLen'), + 'postUserFunc': kw('postUserFunc'), + 'postUserFuncInt': kw('postUserFuncInt'), + 'preBlanks': kw('preBlanks'), + 'preCObject': kw('preCObject'), + 'prefix': kw('prefix'), + 'prefixComment': kw('prefixComment'), + 'prefixLocalAnchors': kw('prefixLocalAnchors'), + 'prefixRelPathWith': kw('prefixRelPathWith'), + 'preIfEmptyListNum': kw('preIfEmptyListNum'), + 'preLineBlanks': kw('preLineBlanks'), + 'preLineChar': kw('preLineChar'), + 'preLineLen': kw('preLineLen'), + 'prepend': kw('prepend'), + 'preserveEntities': kw('preserveEntities'), + 'preUserFunc': kw('preUserFunc'), + 'prev': kw('prev'), + 'preview': A, + 'previewBorder': kw('previewBorder'), + 'prevnextToSection': kw('prevnextToSection'), + 'prioriCalc': kw('prioriCalc'), + 'proc': kw('proc'), + 'processor_allowUpscaling': kw('processor_allowUpscaling'), + 'properties': kw('properties'), + 'protect': kw('protect'), + 'protectLvar': kw('protectLvar'), + 'publish': A, + 'publish_levels': kw('publish_levels'), + 'QEisDefault': kw('QEisDefault'), + 'quality': kw('quality'), + 'RADIO': A, + 'radio': kw('radio'), + 'radioWrap': kw('radioWrap'), + 'range': kw('range'), + 'rawUrlEncode': kw('rawUrlEncode'), + 'recipient': kw('recipient'), + 'RECORDS': kw('RECORDS'), + 'recursive': kw('recursive'), + 'recursiveDelete': kw('recursiveDelete'), + 'redirect': kw('redirect'), + 'redirectToURL': kw('redirectToURL'), + 'reduceColors': kw('reduceColors'), + 'references': kw('references'), + 'register': kw('register'), + 'relPathPrefix': kw('relPathPrefix'), + 'remap': kw('remap'), + 'remapTag': kw('remapTag'), + 'REMOTE_ADDR': kw('REMOTE_ADDR'), + 'removeDefaultJS': kw('removeDefaultJS'), + 'removeIfEquals': kw('removeIfEquals'), + 'removeIfFalse': kw('removeIfFalse'), + 'removeItems': kw('removeItems'), + 'removeObjectsOfDummy': kw('removeObjectsOfDummy'), + 'removePrependedNumbers': kw('removePrependedNumbers'), + 'removeTags': kw('removeTags'), + 'removeWrapping': kw('removeWrapping'), + 'renderObj': A, + 'renderWrap': kw('renderWrap'), + 'REQ': A, + 'required': B, + 'reset': kw('reset'), + 'resources': kw('resources'), + 'RESTORE_REGISTER': kw('RESTORE_REGISTER'), + 'resultObj': kw('resultObj'), + 'returnLast': kw('returnLast'), + 'returnUrl': kw('returnUrl'), + 'rightjoin': kw('rightjoin'), + 'rm': kw('rm'), + 'rmTagIfNoAttrib': kw('rmTagIfNoAttrib'), + 'RO': B, + 'rootline': B, + 'rotate': kw('rotate'), + 'rows': kw('rows'), + 'rowSpace': kw('rowSpace'), + 'RTE': A, + 'RTE_compliant': A, + 'RTEfullScreenWidth': kw('RTEfullScreenWidth'), + 'rules': kw('rules'), + 'sample': kw('sample'), + 'saveClipboard': kw('saveClipboard'), + 'saveDocNew': kw('saveDocNew'), + 'script': B, + 'search': B, + 'SEARCHRESULT': kw('SEARCHRESULT'), + 'secondRow': kw('secondRow'), + 'section': kw('section'), + 'sectionIndex': kw('sectionIndex'), + 'select': A, + 'selectFields': kw('selectFields'), + 'separator': kw('separator'), + 'set': kw('set'), + 'setContentToCurrent': kw('setContentToCurrent'), + 'setCurrent': kw('setCurrent'), + 'setfixed': kw('setfixed'), + 'setOnly': kw('setOnly'), + 'setup': A, + 'shadow': kw('shadow'), + 'SHARED': kw('SHARED'), + 'sharpen': kw('sharpen'), + 'shear': kw('shear'), + 'short': kw('short'), + 'shortcut': B, + 'shortcutFrame': kw('shortcutFrame'), + 'shortcutIcon': kw('shortcutIcon'), + 'show': kw('show'), + 'showAccessRestrictedPages': kw('showAccessRestrictedPages'), + 'showActive': kw('showActive'), + 'showClipControlPanelsDespiteOfCMlayers': kw('showClipControlPanelsDespiteOfCMlayers'), + 'showFirst': kw('showFirst'), + 'showHiddenPages': kw('showHiddenPages'), + 'showHiddenRecords': kw('showHiddenRecords'), + 'showHistory': kw('showHistory'), + 'showPageIdWithTitle': kw('showPageIdWithTitle'), + 'showTagFreeClasses': kw('showTagFreeClasses'), + 'simulateDate': kw('simulateDate'), + 'simulateUserGroup': kw('simulateUserGroup'), + 'singlePid': kw('singlePid'), + 'site_author': kw('site_author'), + 'site_reserved': kw('site_reserved'), + 'sitemap': B, + 'sitetitle': kw('sitetitle'), + 'siteUrl': kw('siteUrl'), + 'size': kw('size'), + 'solarize': kw('solarize'), + 'sorting': kw('sorting'), + 'source': kw('source'), + 'space': kw('space'), + 'spaceAfter': kw('spaceAfter'), + 'spaceBefore': kw('spaceBefore'), + 'spaceBelowAbove': kw('spaceBelowAbove'), + 'spaceLeft': kw('spaceLeft'), + 'spaceRight': kw('spaceRight'), + 'spacing': kw('spacing'), + 'spamProtectEmailAddresses': kw('spamProtectEmailAddresses'), + 'spamProtectEmailAddresses_atSubst': kw('spamProtectEmailAddresses_atSubst'), + 'spamProtectEmailAddresses_lastDotSubst': kw('spamProtectEmailAddresses_lastDotSubst'), + 'SPC': B, + 'special': kw('special'), + 'split': A, + 'splitChar': kw('splitChar'), + 'splitRendering': kw('splitRendering'), + 'src': kw('src'), + 'stdheader': kw('stdheader'), + 'stdWrap': A, + 'stdWrap2': kw('stdWrap2'), + 'strftime': kw('strftime'), + 'stripHtml': kw('stripHtml'), + 'styles': kw('styles'), + 'submenuObjSuffixes': kw('submenuObjSuffixes'), + 'subMenuOffset': kw('subMenuOffset'), + 'submit': kw('submit'), + 'subparts': A, + 'subst_elementUid': kw('subst_elementUid'), + 'substMarksSeparately': kw('substMarksSeparately'), + 'substring': kw('substring'), + 'swirl': kw('swirl'), + 'sword': kw('sword'), + 'sword_noMixedCase': kw('sword_noMixedCase'), + 'SWORD_PARAMS': kw('SWORD_PARAMS'), + 'sword_standAlone': kw('sword_standAlone'), + 'sys_dmail': B, + 'sys_domain': B, + 'sys_filemounts': B, + 'sys_language_mode': kw('sys_language_mode'), + 'sys_language_overlay': kw('sys_language_overlay'), + 'sys_language_uid': kw('sys_language_uid'), + 'sys_note': B, + 'sys_template': B, + 'system': A, + 'table': B, + 'tableCellColor': kw('tableCellColor'), + 'tableParams': kw('tableParams'), + 'tables': kw('tables'), + 'tableStdWrap': kw('tableStdWrap'), + 'tableWidth': kw('tableWidth'), + 'tags': kw('tags'), + 'target': kw('target'), + 'TCAdefaults': kw('TCAdefaults'), + 'TCEFORM': kw('TCEFORM'), + 'TCEMAIN': kw('TCEMAIN'), + 'TDparams': kw('TDparams'), + 'temp': A, + 'TEMPLATE': kw('TEMPLATE'), + 'template': A, + 'templateContent': kw('templateContent'), + 'templateFile': kw('templateFile'), + 'TEXT': kw('TEXT'), + 'text': B, + 'textarea': kw('textarea'), + 'textMargin': kw('textMargin'), + 'textMargin_outOfText': kw('textMargin_outOfText'), + 'textMaxLength': kw('textMaxLength'), + 'textObjNum': kw('textObjNum'), + 'textpic': B, + 'textPos': kw('textPos'), + 'thickness': kw('thickness'), + 'this': B, + 'thumbnailsByDefault': kw('thumbnailsByDefault'), + 'tile': kw('tile'), + 'time_stdWrap': kw('time_stdWrap'), + 'tipafriendLib': kw('tipafriendLib'), + 'title': kw('title'), + 'titleLen': kw('titleLen'), + 'titleTagFunction': kw('titleTagFunction'), + 'titleText': kw('titleText'), + 'tm': kw('tm'), + 'TMENU': kw('TMENU'), + 'TMENUITEM': kw('TMENUITEM'), + 'token': kw('token'), + 'top': B, + 'totalWidth': kw('totalWidth'), + 'transparentBackground': kw('transparentBackground'), + 'transparentColor': kw('transparentColor'), + 'treeLevel': A, + 'trim': kw('trim'), + 'true': B, + 'tsdebug': A, + 'tsdebug_tree': kw('tsdebug_tree'), + 'TSFE': kw('TSFE'), + 'type': kw('type'), + 'typeNum': kw('typeNum'), + 'types': kw('types'), + 'typolink': A, + 'uid': B, + 'uidInList': kw('uidInList'), + 'uniqueGlobal': B, + 'uniqueLocal': B, + 'unset': kw('unset'), + 'unsetEmpty': B, + 'updated': B, + 'uploadFieldsInTopOfEB': kw('uploadFieldsInTopOfEB'), + 'uploads': B, + 'upper': kw('upper'), + 'url': A, + 'us': B, + 'useCacheHash': kw('useCacheHash'), + 'useLargestItemX': kw('useLargestItemX'), + 'useLargestItemY': kw('useLargestItemY'), + 'USER': kw('USER'), + 'user': kw('user'), + 'USER_INT': kw('USER_INT'), + 'user_task': B, + 'useragent': A, + 'USERDEF1': B, + 'USERDEF1RO': B, + 'USERDEF2': B, + 'USERDEF2RO': B, + 'userdefined': kw('userdefined'), + 'userFunc': A, + 'userfunction': kw('userfunction'), + 'usergroup': B, + 'userid': kw('userid'), + 'USERNAME_substToken': kw('USERNAME_substToken'), + 'userProc': kw('userProc'), + 'USR': B, + 'USRRO': B, + 'value': kw('value'), + 'valueArray': kw('valueArray'), + 'version': A, + 'view': A, + 'wave': kw('wave'), + 'web_func': B, + 'web_info': B, + 'web_layout': B, + 'web_list': B, + 'web_ts': kw('web_ts'), + 'where': kw('where'), + 'width': kw('width'), + 'wiz': kw('wiz'), + 'wordSpacing': kw('wordSpacing'), + 'workArea': kw('workArea'), + 'workOnSubpart': A, + 'wrap': kw('wrap'), + 'wrap1': kw('wrap1'), + 'wrap2': kw('wrap2'), + 'wrap3': kw('wrap3'), + 'wrapAfterTags': kw('wrapAfterTags'), + 'wrapAlign': kw('wrapAlign'), + 'wrapFieldName': kw('wrapFieldName'), + 'wrapItemAndSub': kw('wrapItemAndSub'), + 'wrapNonWrappedLines': kw('wrapNonWrappedLines'), + 'wraps': kw('wraps'), + 'xhtml_cleaning': kw('xhtml_cleaning'), + 'xhtml_strict': B, + 'xhtml_trans': B, + 'xmlprologue': kw('xmlprologue'), + 'XY': B + }; + }(); + + var isOperatorChar = /[\+\-\*\&\%\/=<>!\?]/; + var inValue = false; + + function readRegexp(stream) { + var escaped = false, next, inSet = false; + while ((next = stream.next()) != null) { + if (!escaped) { + if (next === "/" && !inSet) return; + if (next === "[") inSet = true; + else if (inSet && next === "]") inSet = false; + } + escaped = !escaped && next === "\\"; + } + } + + // Used as scratch variables to communicate multiple values without + // consing up tons of objects. + var type, content; + + function ret(tp, style, cont) { + type = tp; + content = cont; + return style; + } + + function tokenBase(stream, state) { + var ch = stream.next(); + if (ch === "\n") { + inValue = false; + } + + if (ch === "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { + return ret("number", "number"); + } + if (ch === "." && stream.match("..")) { + return ret("spread", "meta"); + } + if (/[\[\]{}\(\),;\:\.]/.test(ch)) { + return ret(ch); + } + if ((ch === '<' || ch === '>' || ch === '.' || (ch === '=' && stream.peek() !== '<'))) { + inValue = true; + return ret(ch, 'operator') + } + if (!inValue && /[\[\]\(\),;\:\.\<\>\=]/.test(ch)) { + return ret(ch, 'operator') + } + if (ch === "0" && stream.eat(/x/i)) { + stream.eatWhile(/[\da-f]/i); + return ret("number", "number"); + } + if (ch === "0" && stream.eat(/o/i)) { + stream.eatWhile(/[0-7]/i); + return ret("number", "number"); + } + if (ch === "0" && stream.eat(/b/i)) { + stream.eatWhile(/[01]/i); + return ret("number", "number"); + } + if (/\d/.test(ch)) { + stream.match(/^\d*(?:\.\d+)?(?:[eE][+\-]?\d+)?/); + return ret("number", "number"); + } + if (ch === "/") { + if (stream.eat("*")) { + state.tokenize = tokenComment; + return tokenComment(stream, state); + } + if (stream.eat("/")) { + stream.skipToEnd(); + return ret("comment", "comment"); + } + if (expressionAllowed(stream, state, 1)) { + readRegexp(stream); + stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); + return ret("regexp", "string-2"); + } + + stream.eatWhile(isOperatorChar); + return ret("operator", "operator", stream.current()); + } + if (ch === "`") { + state.tokenize = tokenQuasi; + return tokenQuasi(stream, state); + } + if (ch === "#") { + stream.skipToEnd(); + return ret("comment", "comment"); + } + if (isOperatorChar.test(ch)) { + if (ch !== ">" || !state.lexical || state.lexical.type !== ">") { + stream.eatWhile(isOperatorChar); + } + return ret("operator", "operator", stream.current()); + } + if (wordRE.test(ch)) { + stream.eatWhile(wordRE); + var word = stream.current(); + if (keywords.propertyIsEnumerable(word)) { + var kw = keywords[word]; + return ret(kw.type, kw.style, word); + } + if (word === "async" && stream.match(/^\s*[\(\w]/, false)) { + return ret("async", "keyword", word); + } + if (inValue) { + return ret('string', 'string', word); + } + return ret("variable", "other", word); + } + } + + function tokenString(quote) { + return function(stream, state) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (next == quote && !escaped) break; + escaped = !escaped && next === "\\"; + } + if (!escaped) state.tokenize = tokenBase; + return ret("string", "string"); + }; + } + + function tokenComment(stream, state) { + var maybeEnd = false, ch; + while (ch = stream.next()) { + if (ch === "/" && maybeEnd) { + state.tokenize = tokenBase; + break; + } + maybeEnd = (ch === "*"); + } + return ret("comment", "comment"); + } + + function tokenQuasi(stream, state) { + var escaped = false, next; + while ((next = stream.next()) != null) { + if (!escaped && (next === "`" || next === "$" && stream.eat("{"))) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && next === "\\"; + } + return ret("quasi", "string-2", stream.current()); + } + + var brackets = "([{}])"; + // This is a crude lookahead trick to try and notice that we're + // parsing the argument patterns for a fat-arrow function before we + // actually hit the arrow token. It only works if the arrow is on + // the same line as the arguments and there's no strange noise + // (comments) in between. Fallback is to only notice when we hit the + // arrow, and not declare the arguments as locals for the arrow + // body. + function findFatArrow(stream, state) { + if (state.fatArrowAt) state.fatArrowAt = null; + var arrow = stream.string.indexOf("=>", stream.start); + if (arrow < 0) return; + + var depth = 0, sawSomething = false; + for (var pos = arrow - 1; pos >= 0; --pos) { + var ch = stream.string.charAt(pos); + var bracket = brackets.indexOf(ch); + if (bracket >= 0 && bracket < 3) { + if (!depth) { + ++pos; + break; + } + if (--depth == 0) { + if (ch === "(") sawSomething = true; + break; + } + } else if (bracket >= 3 && bracket < 6) { + ++depth; + } else if (wordRE.test(ch)) { + sawSomething = true; + } else if (/["'\/]/.test(ch)) { + return; + } else if (sawSomething && !depth) { + ++pos; + break; + } + } + if (sawSomething && !depth) state.fatArrowAt = pos; + } + + // Parser + + var atomicTypes = { + "atom": true, + "number": true, + "variable": true, + "string": true, + "regexp": true + }; + + function TSLexical(indented, column, type, align, prev, info) { + this.indented = indented; + this.column = column; + this.type = type; + this.prev = prev; + this.info = info; + if (align != null) this.align = align; + } + + function inScope(state, varname) { + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return true; + for (var cx = state.context; cx; cx = cx.prev) { + for (var v = cx.vars; v; v = v.next) + if (v.name == varname) return true; + } + } + + function parseTS(state, style, type, content, stream) { + var cc = state.cc; + // Communicate our context to the combinators. + // (Less wasteful than consing up a hundred closures on every call.) + cx.state = state; + cx.stream = stream; + cx.marked = null, cx.cc = cc; + cx.style = style; + + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = true; + + while (true) { + var combinator = cc.length ? cc.pop() : statement; + if (combinator(type, content)) { + while (cc.length && cc[cc.length - 1].lex) + cc.pop()(); + if (cx.marked) return cx.marked; + if (type === "variable" && inScope(state, content)) return "variable-2"; + return style; + } + } + } + + // Combinator utils + + var cx = {state: null, column: null, marked: null, cc: null}; + + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); + } + + function cont() { + pass.apply(null, arguments); + return true; + } + + function register(varname) { + function inList(list) { + for (var v = list; v; v = v.next) + if (v.name == varname) return true; + return false; + } + + var state = cx.state; + cx.marked = "def"; + if (state.context) { + if (inList(state.localVars)) return; + state.localVars = {name: varname, next: state.localVars}; + } else { + if (inList(state.globalVars)) return; + if (parserConfig.globalVars) + state.globalVars = {name: varname, next: state.globalVars}; + } + } + + // Combinators + + var defaultVars = {name: "this", next: {name: "arguments"}}; + + function pushcontext() { + cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; + cx.state.localVars = defaultVars; + } + + function popcontext() { + cx.state.localVars = cx.state.context.vars; + cx.state.context = cx.state.context.prev; + } + + function pushlex(type, info) { + var result = function() { + var state = cx.state, indent = state.indented; + if (state.lexical.type === "stat") indent = state.lexical.indented; + else for (var outer = state.lexical; outer && outer.type === ")" && outer.align; outer = outer.prev) + indent = outer.indented; + state.lexical = new TSLexical(indent, cx.stream.column(), type, null, state.lexical, info); + }; + result.lex = true; + return result; + } + + function poplex() { + var state = cx.state; + if (state.lexical.prev) { + if (state.lexical.type === ")") + state.indented = state.lexical.indented; + state.lexical = state.lexical.prev; + } + } + + poplex.lex = true; + + function expect(wanted) { + function exp(type) { + if (type == wanted) return cont(); + else if (wanted === ";") return pass(); + else return cont(exp); + }; + return exp; + } + + function statement(type, value) { + if (type === "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); + if (type === "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); + if (type === "keyword b") return cont(pushlex("form"), statement, poplex); + if (type === "{") return cont(pushlex("}"), block, poplex); + if (type === ";") return cont(); + if (type === "if") { + if (cx.state.lexical.info === "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) { + cx.state.cc.pop()(); + } + return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); + } + if (type === "function") return cont(functiondef); + if (type === "for") return cont(pushlex("form"), forspec, statement, poplex); + if (type === "variable") { + return cont(pushlex("stat"), maybelabel); + } + if (type === "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), + block, poplex, poplex); + if (type === "case") return cont(expression, expect(":")); + if (type === "default") return cont(expect(":")); + if (type === "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), + statement, poplex, popcontext); + if (type === "class") return cont(pushlex("form"), className, poplex); + if (type === "export") return cont(pushlex("stat"), afterExport, poplex); + if (type === "import") return cont(pushlex("stat"), afterImport, poplex); + if (type === "module") return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) + if (type === "async") return cont(statement) + if (value === "@") return cont(expression, statement) + return pass(pushlex("stat"), expression, expect(";"), poplex); + } + + function expression(type) { + return expressionInner(type, false); + } + + function expressionNoComma(type) { + return expressionInner(type, true); + } + + function parenExpr(type) { + if (type !== "(") return pass() + return cont(pushlex(")"), expression, expect(")"), poplex) + } + + function expressionInner(type, noComma) { + var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; + if (atomicTypes.hasOwnProperty(type)) { + return cont(maybeop); + } + if (type === "keyword c") { + return cont(noComma ? maybeexpressionNoComma : maybeexpression); + } + if (type === "(") { + return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); + } + if (type === "operator" || type === "spread") { + return cont(noComma ? expressionNoComma : expression); + } + if (type === "[") { + return cont(pushlex("]"), arrayLiteral, poplex, maybeop); + } + if (type === "{") { + return contCommasep(objprop, "}", null, maybeop); + } + return cont(); + } + + function maybeexpression(type) { + if (type.match(/[;\}\)\],]/)) return pass(); + return pass(expression); + } + + function maybeexpressionNoComma(type) { + if (type.match(/[;\}\)\],]/)) return pass(); + return pass(expressionNoComma); + } + + function maybeoperatorComma(type, value) { + if (type === ",") return cont(expression); + return maybeoperatorNoComma(type, value, false); + } + + function maybeoperatorNoComma(type, value, noComma) { + var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; + var expr = noComma == false ? expression : expressionNoComma; + if (type === "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); + if (type === "operator") { + if (/\+\+|--/.test(value)) return cont(me); + if (value === "?") return cont(expression, expect(":"), expr); + return cont(expr); + } + if (type === "quasi") { + return pass(quasi, me); + } + if (type === ";") return; + if (type === "(") return contCommasep(expressionNoComma, ")", "call", me); + if (type === ".") return cont(property, me); + if (type === "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); + } + + function quasi(type, value) { + if (type !== "quasi") return pass(); + if (value.slice(value.length - 2) !== "${") return cont(quasi); + return cont(expression, continueQuasi); + } + + function continueQuasi(type) { + if (type === "}") { + cx.marked = "string-2"; + cx.state.tokenize = tokenQuasi; + return cont(quasi); + } + } + + function arrowBody(type) { + findFatArrow(cx.stream, cx.state); + return pass(type === "{" ? statement : expression); + } + + function arrowBodyNoComma(type) { + findFatArrow(cx.stream, cx.state); + return pass(type === "{" ? statement : expressionNoComma); + } + + function maybeTarget(noComma) { + return function(type) { + if (type === ".") return cont(noComma ? targetNoComma : target); + else return pass(noComma ? expressionNoComma : expression); + }; + } + + function target(_, value) { + if (value === "target") { + cx.marked = "keyword"; + return cont(maybeoperatorComma); + } + } + + function targetNoComma(_, value) { + if (value === "target") { + cx.marked = "keyword"; + return cont(maybeoperatorNoComma); + } + } + + function maybelabel(type) { + if (type === ":") return cont(poplex, statement); + return pass(maybeoperatorComma, expect(";"), poplex); + } + + function property(type) { + if (type === "variable") { + cx.marked = "property"; + return cont(); + } + } + + function objprop(type, value) { + if (type === "async") { + cx.marked = "property"; + return cont(objprop); + } else if (type === "variable" || cx.style === "keyword") { + cx.marked = "property"; + if (value === "get" || value === "set") return cont(getterSetter); + return cont(afterprop); + } else if (type === "number" || type === "string") { + cx.marked = cx.style + " property"; + return cont(afterprop); + } else if (type === "jsonld-keyword") { + return cont(afterprop); + } else if (type === "modifier") { + return cont(objprop) + } else if (type === "[") { + return cont(expression, expect("]"), afterprop); + } else if (type === "spread") { + return cont(expression, afterprop); + } else if (type === ":") { + return pass(afterprop) + } + } + + function getterSetter(type) { + if (type !== "variable") return pass(afterprop); + cx.marked = "property"; + return cont(functiondef); + } + + function afterprop(type) { + if (type === ":") return cont(expressionNoComma); + if (type === "(") return pass(functiondef); + } + + function commasep(what, end, sep) { + function proceed(type, value) { + if (sep ? sep.indexOf(type) > -1 : type === ",") { + var lex = cx.state.lexical; + if (lex.info === "call") lex.pos = (lex.pos || 0) + 1; + return cont(function(type, value) { + if (type == end || value == end) return pass() + return pass(what) + }, proceed); + } + if (type == end || value == end) return cont(); + return cont(expect(end)); + } + + return function(type, value) { + if (type == end || value == end) return cont(); + return pass(what, proceed); + }; + } + + function contCommasep(what, end, info) { + for (var i = 3; i < arguments.length; i++) + cx.cc.push(arguments[i]); + return cont(pushlex(end, info), commasep(what, end), poplex); + } + + function block(type) { + if (type === "}") return cont(); + return pass(statement, block); + } + + function typeexpr(type) { + if (type === "variable") { + cx.marked = "type"; + return cont(afterType); + } + if (type === "string" || type === "number" || type === "atom") return cont(afterType); + if (type === "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) + if (type === "(") return cont(commasep(typearg, ")"), maybeReturnType) + } + + function maybeReturnType(type) { + if (type === "=>") return cont(typeexpr) + } + + function typeprop(type, value) { + if (type === "variable" || cx.style === "keyword") { + cx.marked = "property" + return cont(typeprop) + } else if (value === "?") { + return cont(typeprop) + } else if (type === ":") { + return cont(typeexpr) + } else if (type === "[") { + return cont(expression, null, expect("]"), typeprop) + } + } + + function typearg(type) { + if (type === "variable") return cont(typearg) + else if (type === ":") return cont(typeexpr) + } + + function afterType(type, value) { + if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) + if (value === "|" || type === ".") return cont(typeexpr) + if (type === "[") return cont(expect("]"), afterType) + if (value === "extends") return cont(typeexpr) + } + + function vardef() { + return pass(pattern, null, maybeAssign, vardefCont); + } + + function pattern(type, value) { + if (type === "modifier") return cont(pattern) + if (type === "variable") { + register(value); + return cont(); + } + if (type === "spread") return cont(pattern); + if (type === "[") return contCommasep(pattern, "]"); + if (type === "{") return contCommasep(proppattern, "}"); + } + + function proppattern(type, value) { + if (type === "variable" && !cx.stream.match(/^\s*:/, false)) { + register(value); + return cont(maybeAssign); + } + if (type === "variable") cx.marked = "property"; + if (type === "spread") return cont(pattern); + if (type === "}") return pass(); + return cont(expect(":"), pattern, maybeAssign); + } + + function maybeAssign(_type, value) { + if (value === "=") return cont(expressionNoComma); + } + + function vardefCont(type) { + if (type === ",") return cont(vardef); + } + + function maybeelse(type, value) { + if (type === "keyword b" && value === "else") return cont(pushlex("form", "else"), statement, poplex); + } + + function forspec(type) { + if (type === "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); + } + + function forspec1(type) { + if (type === "var") return cont(vardef, expect(";"), forspec2); + if (type === ";") return cont(forspec2); + if (type === "variable") return cont(formaybeinof); + return pass(expression, expect(";"), forspec2); + } + + function formaybeinof(_type, value) { + if (value === "in" || value === "of") { + cx.marked = "keyword"; + return cont(expression); + } + return cont(maybeoperatorComma, forspec2); + } + + function forspec2(type, value) { + if (type === ";") return cont(forspec3); + if (value === "in" || value === "of") { + cx.marked = "keyword"; + return cont(expression); + } + return pass(expression, expect(";"), forspec3); + } + + function forspec3(type) { + if (type !== ")") cont(expression); + } + + function functiondef(type, value) { + if (value === "*") { + cx.marked = "keyword"; + return cont(functiondef); + } + if (type === "variable") { + register(value); + return cont(functiondef); + } + if (type === "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, null, statement, popcontext); + } + + function funarg(type) { + if (type === "spread") return cont(funarg); + return pass(pattern, null, maybeAssign); + } + + function classExpression(type, value) { + // Class expressions may have an optional name. + if (type === "variable") return className(type, value); + return classNameAfter(type, value); + } + + function className(type, value) { + if (type === "variable") { + register(value); + return cont(classNameAfter); + } + } + + function classNameAfter(type, value) { + if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, classNameAfter) + if (value === "extends" || value === "implements") + return cont(expression, classNameAfter); + if (type === "{") return cont(pushlex("}"), classBody, poplex); + } + + function classBody(type, value) { + if (type === "variable" || cx.style === "keyword") { + if ((value === "async" || value === "static" || value === "get" || value === "set") && + cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) { + cx.marked = "keyword"; + return cont(classBody); + } + cx.marked = "property"; + return cont(functiondef, classBody); + } + if (type === "[") + return cont(expression, expect("]"), functiondef, classBody) + if (value === "*") { + cx.marked = "keyword"; + return cont(classBody); + } + if (type === ";") return cont(classBody); + if (type === "}") return cont(); + if (value === "@") return cont(expression, classBody) + } + + function classfield(type, value) { + if (value === "?") return cont(classfield) + if (type === ":") return cont(typeexpr, maybeAssign) + if (value === "=") return cont(expressionNoComma) + return pass(functiondef) + } + + function afterExport(type, value) { + if (value === "*") { + cx.marked = "keyword"; + return cont(maybeFrom, expect(";")); + } + if (value === "default") { + cx.marked = "keyword"; + return cont(expression, expect(";")); + } + if (type === "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); + return pass(statement); + } + + function exportField(type, value) { + if (value === "as") { + cx.marked = "keyword"; + return cont(expect("variable")); + } + if (type === "variable") return pass(expressionNoComma, exportField); + } + + function afterImport(type) { + if (type === "string") return cont(); + return pass(importSpec, maybeMoreImports, maybeFrom); + } + + function importSpec(type, value) { + if (type === "{") return contCommasep(importSpec, "}"); + if (type === "variable") register(value); + if (value === "*") cx.marked = "keyword"; + return cont(maybeAs); + } + + function maybeMoreImports(type) { + if (type === ",") return cont(importSpec, maybeMoreImports) + } + + function maybeAs(_type, value) { + if (value === "as") { + cx.marked = "keyword"; + return cont(importSpec); + } + } + + function maybeFrom(_type, value) { + if (value === "from") { + cx.marked = "keyword"; + return cont(expression); + } + } + + function arrayLiteral(type) { + if (type === "]") return cont(); + return pass(commasep(expressionNoComma, "]")); + } + + function isContinuedStatement(state, textAfter) { + return state.lastType === "operator" || state.lastType === "," || + isOperatorChar.test(textAfter.charAt(0)) || + /[,.]/.test(textAfter.charAt(0)); + } + + // Interface + + return { + startState: function(basecolumn) { + var state = { + tokenize: tokenBase, + lastType: "sof", + cc: [], + lexical: new TSLexical((basecolumn || 0) - indentUnit, 0, "block", false), + localVars: parserConfig.localVars, + context: parserConfig.localVars && {vars: parserConfig.localVars}, + indented: basecolumn || 0 + }; + if (parserConfig.globalVars && typeof parserConfig.globalVars === "object") + state.globalVars = parserConfig.globalVars; + return state; + }, + + token: function(stream, state) { + if (stream.sol()) { + if (!state.lexical.hasOwnProperty("align")) + state.lexical.align = false; + state.indented = stream.indentation(); + findFatArrow(stream, state); + } + if (state.tokenize != tokenComment && stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + if (type === "comment") return style; + state.lastType = type === "operator" && (content === "++" || content === "--") ? "incdec" : type; + return parseTS(state, style, type, content, stream); + }, + + indent: function(state, textAfter) { + if (state.tokenize == tokenComment) return CodeMirror.Pass; + if (state.tokenize != tokenBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top + // Kludge to prevent 'maybelse' from blocking lexical scope pops + if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { + var c = state.cc[i]; + if (c == poplex) lexical = lexical.prev; + else if (c != maybeelse) break; + } + while ((lexical.type === "stat" || lexical.type === "form") && + (firstChar === "}" || ((top = state.cc[state.cc.length - 1]) && + (top == maybeoperatorComma || top == maybeoperatorNoComma) && + !/^[,\.=+\-*:?[\(]/.test(textAfter)))) + lexical = lexical.prev; + if (statementIndent && lexical.type === ")" && lexical.prev.type === "stat") + lexical = lexical.prev; + var type = lexical.type, closing = firstChar == type; + + if (type === "vardef") return lexical.indented + (state.lastType === "operator" || state.lastType === "," ? lexical.info + 1 : 0); + else if (type === "form" && firstChar === "{") return lexical.indented; + else if (type === "form") return lexical.indented + indentUnit; + else if (type === "stat") + return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); + else if (lexical.info === "switch" && !closing && parserConfig.doubleIndentSwitch != false) + return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); + else if (lexical.align) return lexical.column + (closing ? 0 : 1); + else return lexical.indented + (closing ? 0 : indentUnit); + }, + + electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, + blockCommentStart: "/*", + blockCommentEnd: "*/", + lineComment: "#", + fold: "brace", + closeBrackets: "()[]{}''\"\"``", + + helperType: "typoscript", + + expressionAllowed: expressionAllowed, + skipExpression: function(state) { + var top = state.cc[state.cc.length - 1]; + if (top == expression || top == expressionNoComma) state.cc.pop() + } + }; + }); }); diff --git a/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js b/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js index 0f074f7183957ce2eee41a0f5b5cd6068c116eb9..9012e9cdf549288a1f4959cc6841a6160bee5f66 100644 --- a/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js +++ b/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js @@ -15,85 +15,85 @@ * Module: TYPO3/CMS/Taskcenter/Taskcenter */ define(['jquery', - 'TYPO3/CMS/Backend/Icons', - 'jquery-ui/sortable' - ], function($, Icons) { - 'use strict'; + 'TYPO3/CMS/Backend/Icons', + 'jquery-ui/sortable' +], function($, Icons) { + 'use strict'; - /** - * - * @type {{}} - * @exports TYPO3/CMS/Taskcenter/Taskcenter - */ - var Taskcenter = {}; + /** + * + * @type {{}} + * @exports TYPO3/CMS/Taskcenter/Taskcenter + */ + var Taskcenter = {}; - /** - * - * @param {Object} element - * @param {Boolean} isCollapsed - */ - Taskcenter.collapse = function(element, isCollapsed) { - var $item = $(element); - var $parent = $item.parent(); - var $icon = $parent.find('.t3js-taskcenter-header-collapse .t3js-icon'); - var isCollapsed = isCollapsed; - var iconName; + /** + * + * @param {Object} element + * @param {Boolean} isCollapsed + */ + Taskcenter.collapse = function(element, isCollapsed) { + var $item = $(element); + var $parent = $item.parent(); + var $icon = $parent.find('.t3js-taskcenter-header-collapse .t3js-icon'); + var isCollapsed = isCollapsed; + var iconName; - if(isCollapsed) { - iconName = 'actions-view-list-expand'; - } else { - iconName = 'actions-view-list-collapse'; - } - Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) { - $icon.replaceWith(icon); - }); + if (isCollapsed) { + iconName = 'actions-view-list-expand'; + } else { + iconName = 'actions-view-list-collapse'; + } + Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) { + $icon.replaceWith(icon); + }); - $.ajax({ - url: TYPO3.settings.ajaxUrls['taskcenter_collapse'], - type: 'post', - cache: false, - data: { - 'item': $parent.data('taskcenterId'), - 'state': isCollapsed - } - }); - }; + $.ajax({ + url: TYPO3.settings.ajaxUrls['taskcenter_collapse'], + type: 'post', + cache: false, + data: { + 'item': $parent.data('taskcenterId'), + 'state': isCollapsed + } + }); + }; - /** - * - */ - Taskcenter.initializeSorting = function() { - $('#task-list').sortable({ - update: function(event, ui) { - $.ajax({ - url: TYPO3.settings.ajaxUrls['taskcenter_sort'], - type: 'post', - cache: false, - data: { - 'data': $(this).sortable('serialize', { - key: 'task-list[]', - expression: /[=_](.+)/ - }) - } - }); - } - }); - }; + /** + * + */ + Taskcenter.initializeSorting = function() { + $('#task-list').sortable({ + update: function(event, ui) { + $.ajax({ + url: TYPO3.settings.ajaxUrls['taskcenter_sort'], + type: 'post', + cache: false, + data: { + 'data': $(this).sortable('serialize', { + key: 'task-list[]', + expression: /[=_](.+)/ + }) + } + }); + } + }); + }; - /** - * Register listeners - */ - Taskcenter.initializeEvents = function() { - $('.t3js-taskcenter-collapse').on('show.bs.collapse', function() { - Taskcenter.collapse($(this), 0); - }); - $('.t3js-taskcenter-collapse').on('hide.bs.collapse', function() { - Taskcenter.collapse($(this), 1); - }); - Taskcenter.initializeSorting(); - }; + /** + * Register listeners + */ + Taskcenter.initializeEvents = function() { + $('.t3js-taskcenter-collapse').on('show.bs.collapse', function() { + Taskcenter.collapse($(this), 0); + }); + $('.t3js-taskcenter-collapse').on('hide.bs.collapse', function() { + Taskcenter.collapse($(this), 1); + }); + Taskcenter.initializeSorting(); + }; - $(Taskcenter.initializeEvents); + $(Taskcenter.initializeEvents); - return Taskcenter; + return Taskcenter; }); diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js index 07ffc30f46a477cb2fc9ee0b2ce2e60b7d3e2ce8..bde86915c945ba065a80c8f9b41783f114b20d70 100644 --- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js +++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js @@ -17,88 +17,88 @@ * e.g. updating the field and working with colors */ define(['jquery'], function($) { - 'use strict'; + 'use strict'; - /** - * - * @type {{options: {editIconSelector: string, colorSelectSelector: string, colorInputSelector: string}}} - * @exports TYPO3/CMS/Tstemplate/ConstantEditor - */ - var ConstantEditor = { - options: { - editIconSelector: '.t3js-toggle', - colorSelectSelector: '.t3js-color-select', - colorInputSelector: '.t3js-color-input' - } - }; + /** + * + * @type {{options: {editIconSelector: string, colorSelectSelector: string, colorInputSelector: string}}} + * @exports TYPO3/CMS/Tstemplate/ConstantEditor + */ + var ConstantEditor = { + options: { + editIconSelector: '.t3js-toggle', + colorSelectSelector: '.t3js-color-select', + colorInputSelector: '.t3js-color-input' + } + }; - /** - * initially register event listeners - * - * @param {Object} $editIcon - */ - ConstantEditor.changeProperty = function($editIcon) { - var constantName = $editIcon.attr('rel'); - var $defaultDiv = $('#defaultTS-' + constantName); - var $userDiv = $('#userTS-' + constantName); - var $checkBox = $('#check-' + constantName); - var toggleState = $editIcon.data('toggle'); + /** + * initially register event listeners + * + * @param {Object} $editIcon + */ + ConstantEditor.changeProperty = function($editIcon) { + var constantName = $editIcon.attr('rel'); + var $defaultDiv = $('#defaultTS-' + constantName); + var $userDiv = $('#userTS-' + constantName); + var $checkBox = $('#check-' + constantName); + var toggleState = $editIcon.data('toggle'); - if (toggleState === 'edit') { - $defaultDiv.hide(); - $userDiv.show(); - $userDiv.find('input').css({background: '#fdf8bd'}); - $checkBox.attr('disabled', false).attr('checked', true); - } else if (toggleState === 'undo') { - $userDiv.hide(); - $defaultDiv.show(); - $checkBox.val('').attr('disabled', true); - } - }; + if (toggleState === 'edit') { + $defaultDiv.hide(); + $userDiv.show(); + $userDiv.find('input').css({background: '#fdf8bd'}); + $checkBox.attr('disabled', false).attr('checked', true); + } else if (toggleState === 'undo') { + $userDiv.hide(); + $defaultDiv.show(); + $checkBox.val('').attr('disabled', true); + } + }; - /** - * updates the color from a dropdown - * - * @param {Object} $colorSelect - */ - ConstantEditor.updateColorFromSelect = function($colorSelect) { - var constantName = $colorSelect.attr('rel'); - var colorValue = $colorSelect.val(); + /** + * updates the color from a dropdown + * + * @param {Object} $colorSelect + */ + ConstantEditor.updateColorFromSelect = function($colorSelect) { + var constantName = $colorSelect.attr('rel'); + var colorValue = $colorSelect.val(); - $('#input-' + constantName).val(colorValue); - $('#colorbox-' + constantName).css({background: colorValue}); - }; + $('#input-' + constantName).val(colorValue); + $('#colorbox-' + constantName).css({background: colorValue}); + }; - /** - * updates the color from an input field - * - * @param {Object} $colorInput - */ - ConstantEditor.updateColorFromInput = function($colorInput) { - var constantName = $colorInput.attr('rel'); - var colorValue = $colorInput.val(); + /** + * updates the color from an input field + * + * @param {Object} $colorInput + */ + ConstantEditor.updateColorFromInput = function($colorInput) { + var constantName = $colorInput.attr('rel'); + var colorValue = $colorInput.val(); - $('#colorbox-' + constantName).css({background: colorValue}); - $('#select-' + constantName).children().each(function(option) { - option.selected = (option.value === colorValue); - }); - }; + $('#colorbox-' + constantName).css({background: colorValue}); + $('#select-' + constantName).children().each(function(option) { + option.selected = (option.value === colorValue); + }); + }; - /** - * Registers listeners - */ - ConstantEditor.initializeEvents = function() { - // no DOMready needed since only events for document are registered - $(document).on('click', ConstantEditor.options.editIconSelector, function() { - ConstantEditor.changeProperty($(this)); - }).on('change', ConstantEditor.options.colorSelectSelector, function() { - ConstantEditor.updateColorFromSelect($(this)); - }).on('blur', ConstantEditor.options.colorInputSelector, function() { - ConstantEditor.updateColorFromInput($(this)); - }); - }; + /** + * Registers listeners + */ + ConstantEditor.initializeEvents = function() { + // no DOMready needed since only events for document are registered + $(document).on('click', ConstantEditor.options.editIconSelector, function() { + ConstantEditor.changeProperty($(this)); + }).on('change', ConstantEditor.options.colorSelectSelector, function() { + ConstantEditor.updateColorFromSelect($(this)); + }).on('blur', ConstantEditor.options.colorInputSelector, function() { + ConstantEditor.updateColorFromInput($(this)); + }); + }; - ConstantEditor.initializeEvents(); + ConstantEditor.initializeEvents(); - return ConstantEditor; + return ConstantEditor; }); diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js index 6891c3c00bebb11a843df4c6aa51ec4d8ff484f7..0850afe2c8bf1c728a47a4dd4c90e2e62f41daa6 100644 --- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js +++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js @@ -18,19 +18,19 @@ */ define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) { - var $searchFields = $('input[name="search_field"]'); - var searchResultShown = ('' !== $searchFields.first().val()); + var $searchFields = $('input[name="search_field"]'); + var searchResultShown = ('' !== $searchFields.first().val()); - // make search field clearable - $searchFields.clearable({ - onClear: function() { - if (searchResultShown) { - $(this).closest('form').submit(); - } - } - }); + // make search field clearable + $searchFields.clearable({ + onClear: function() { + if (searchResultShown) { + $(this).closest('form').submit(); + } + } + }); - if (self.location.hash) { - window.scrollTo(window.pageXOffset, window.pageYOffset - 40); - } + if (self.location.hash) { + window.scrollTo(window.pageXOffset, window.pageYOffset - 40); + } }); diff --git a/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js b/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js index e66ed546c1f3e6257bae28bea903ae457e64217c..590259ab15267251782761df4d2dc5f21dd1209b 100644 --- a/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js +++ b/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js @@ -15,255 +15,255 @@ * Main logic for resizing the view of the frame */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Storage/Persistent', - 'jquery-ui/resizable' + 'jquery', + 'TYPO3/CMS/Backend/Storage/Persistent', + 'jquery-ui/resizable' ], function($, PersistentStorage) { - 'use strict'; - - /** - * @type {{<resizableContainerIdentifier: string, sizeIdentifier: string, moduleBodySelector: string, storagePrefix: string, $iframe: null, $resizableContainer: null, $sizeSelector: null}} - * @exports TYPO3/CMS/Viewpage/Main - */ - var ViewPage = { - - resizableContainerIdentifier: '.t3js-viewpage-resizeable', - sizeIdentifier: ' .t3js-viewpage-size', - moduleBodySelector: '.t3js-module-body', - - defaultLabel: $('.t3js-preset-custom-label').html().trim(), - minimalHeight: 300, - minimalWidth: 300, - - storagePrefix: 'moduleData.web_view.States.', - $iframe: null, - $resizableContainer: null, - $sizeSelector: null, - - customSelector: '.t3js-preset-custom', - customWidthSelector: '.t3js-preset-custom-width', - customHeightSelector: '.t3js-preset-custom-height', - - changeOrientationSelector: '.t3js-change-orientation', - changePresetSelector: '.t3js-change-preset', - - inputWidthSelector: '.t3js-viewpage-input-width', - inputHeightSelector: '.t3js-viewpage-input-height', - - currentLabelSelector: '.t3js-viewpage-current-label', - topbarContainerSelector: '.t3js-viewpage-topbar', - - queue: [], - queueIsRunning: false, - queueDelayTimer: null - - }; - - ViewPage.persistQueue = function() { - if (ViewPage.queueIsRunning === false && ViewPage.queue.length >= 1) { - ViewPage.queueIsRunning = true; - var item = ViewPage.queue.shift(); - PersistentStorage.set(item.storageIdentifier, item.data).done(function() { - ViewPage.queueIsRunning = false; - ViewPage.persistQueue(); - }); - } - } - - ViewPage.addToQueue = function(storageIdentifier, data) { - var item = { - 'storageIdentifier': storageIdentifier, - 'data': data - }; - ViewPage.queue.push(item); - if (ViewPage.queue.length >= 1) { - ViewPage.persistQueue(); - } - } - - ViewPage.setSize = function(width, height) { - if (isNaN(height)) { - height = ViewPage.calculateContainerMaxHeight(); - } - if (height < ViewPage.minimalHeight) { - height = ViewPage.minimalHeight; - } - if (isNaN(width)) { - width = ViewPage.calculateContainerMaxWidth(); - } - if (width < ViewPage.minimalWidth) { - width = ViewPage.minimalWidth; - } - - $(ViewPage.inputWidthSelector).val(width); - $(ViewPage.inputHeightSelector).val(height); - - ViewPage.$resizableContainer.css({ - width: width, - height: height, - left: 0 - }); - } - - ViewPage.getCurrentWidth = function() { - return $(ViewPage.inputWidthSelector).val(); - } - - ViewPage.getCurrentHeight = function() { - return $(ViewPage.inputHeightSelector).val(); - } - - ViewPage.setLabel = function(label) { - $(ViewPage.currentLabelSelector).html(label); - } - - ViewPage.getCurrentLabel = function() { - return $(ViewPage.currentLabelSelector).html().trim(); - } - - ViewPage.persistCurrentPreset = function() { - var data = { - width: ViewPage.getCurrentWidth(), - height: ViewPage.getCurrentHeight(), - label: ViewPage.getCurrentLabel() - } - ViewPage.addToQueue(ViewPage.storagePrefix + 'current', data); - } - - ViewPage.persistCustomPreset = function() { - var data = { - width: ViewPage.getCurrentWidth(), - height: ViewPage.getCurrentHeight() - } - $(ViewPage.customSelector).data("width", data.width); - $(ViewPage.customSelector).data("height", data.height); - $(ViewPage.customWidthSelector).html(data.width); - $(ViewPage.customHeightSelector).html(data.height); - ViewPage.addToQueue(ViewPage.storagePrefix + 'custom', data); - } - - ViewPage.persistCustomPresetAfterChange = function() { - clearTimeout(ViewPage.queueDelayTimer); - ViewPage.queueDelayTimer = setTimeout(function() { - ViewPage.persistCustomPreset(); - }, 1000); - }; - - /** - * Initialize - */ - ViewPage.initialize = function() { - - ViewPage.$iframe = $('#tx_viewpage_iframe'); - ViewPage.$resizableContainer = $(ViewPage.resizableContainerIdentifier); - ViewPage.$sizeSelector = $(ViewPage.sizeIdentifier); - - // Change orientation - $(document).on('click', ViewPage.changeOrientationSelector, function() { - var width = $(ViewPage.inputHeightSelector).val(); - var height = $(ViewPage.inputWidthSelector).val(); - ViewPage.setSize(width, height); - ViewPage.persistCurrentPreset(); - }); - - // On change - $(document).on('change', ViewPage.inputWidthSelector, function() { - var width = $(ViewPage.inputWidthSelector).val(); - var height = $(ViewPage.inputHeightSelector).val(); - ViewPage.setSize(width, height); - ViewPage.setLabel(ViewPage.defaultLabel); - ViewPage.persistCustomPresetAfterChange(); - }); - $(document).on('change', ViewPage.inputHeightSelector, function() { - var width = $(ViewPage.inputWidthSelector).val(); - var height = $(ViewPage.inputHeightSelector).val(); - ViewPage.setSize(width, height); - ViewPage.setLabel(ViewPage.defaultLabel); - ViewPage.persistCustomPresetAfterChange(); - }); - - // Add event to width selector so the container is resized - $(document).on('click', ViewPage.changePresetSelector, function() { - var data = $(this).data(); - ViewPage.setSize(parseInt(data.width), parseInt(data.height)); - ViewPage.setLabel(data.label); - ViewPage.persistCurrentPreset(); - }); - - // Initialize the jQuery UI Resizable plugin - ViewPage.$resizableContainer.resizable({ - handles: 'w, sw, s, se, e' - }); - - ViewPage.$resizableContainer.on('resizestart', function() { - // Add iframe overlay to prevent losing the mouse focus to the iframe while resizing fast - $(this).append('<div id="viewpage-iframe-cover" style="z-index:99;position:absolute;width:100%;top:0;left:0;height:100%;"></div>'); - }); - - ViewPage.$resizableContainer.on('resize', function(evt, ui) { - ui.size.width = ui.originalSize.width + ((ui.size.width - ui.originalSize.width) * 2); - if (ui.size.height < ViewPage.minimalHeight) { - ui.size.height = ViewPage.minimalHeight; - } - if (ui.size.width < ViewPage.minimalWidth) { - ui.size.width = ViewPage.minimalWidth; - } - $(ViewPage.inputWidthSelector).val(ui.size.width); - $(ViewPage.inputHeightSelector).val(ui.size.height); - ViewPage.$resizableContainer.css({ - left: 0 - }); - ViewPage.setLabel(ViewPage.defaultLabel); - }); - - ViewPage.$resizableContainer.on('resizestop', function() { - $('#viewpage-iframe-cover').remove(); - ViewPage.persistCurrentPreset(); - ViewPage.persistCustomPreset(); - }); - }; - - /** - * @returns {Number} - */ - ViewPage.calculateContainerMaxHeight = function() { - ViewPage.$resizableContainer.hide(); - var $moduleBody = $(ViewPage.moduleBodySelector); - var padding = $moduleBody.outerHeight() - $moduleBody.height(), - documentHeight = $(document).height(), - topbarHeight = $(ViewPage.topbarContainerSelector).outerHeight(); - ViewPage.$resizableContainer.show(); - return documentHeight - padding - topbarHeight - 8; - }; - - /** - * @returns {Number} - */ - ViewPage.calculateContainerMaxWidth = function() { - ViewPage.$resizableContainer.hide(); - var $moduleBody = $(ViewPage.moduleBodySelector); - var padding = $moduleBody.outerWidth() - $moduleBody.width(), - documentWidth = $(document).width(); - ViewPage.$resizableContainer.show(); - return parseInt(documentWidth - padding); - }; - - /** - * @param {String} url - * @returns {{}} - */ - ViewPage.getUrlVars = function(url) { - var vars = {}; - var hash; - var hashes = url.slice(url.indexOf('?') + 1).split('&'); - for (var i = 0; i < hashes.length; i ++) { - hash = hashes[i].split('='); - vars[hash[0]] = hash[1]; - } - return vars; - }; - - $(ViewPage.initialize); - - return ViewPage; + 'use strict'; + + /** + * @type {{<resizableContainerIdentifier: string, sizeIdentifier: string, moduleBodySelector: string, storagePrefix: string, $iframe: null, $resizableContainer: null, $sizeSelector: null}} + * @exports TYPO3/CMS/Viewpage/Main + */ + var ViewPage = { + + resizableContainerIdentifier: '.t3js-viewpage-resizeable', + sizeIdentifier: ' .t3js-viewpage-size', + moduleBodySelector: '.t3js-module-body', + + defaultLabel: $('.t3js-preset-custom-label').html().trim(), + minimalHeight: 300, + minimalWidth: 300, + + storagePrefix: 'moduleData.web_view.States.', + $iframe: null, + $resizableContainer: null, + $sizeSelector: null, + + customSelector: '.t3js-preset-custom', + customWidthSelector: '.t3js-preset-custom-width', + customHeightSelector: '.t3js-preset-custom-height', + + changeOrientationSelector: '.t3js-change-orientation', + changePresetSelector: '.t3js-change-preset', + + inputWidthSelector: '.t3js-viewpage-input-width', + inputHeightSelector: '.t3js-viewpage-input-height', + + currentLabelSelector: '.t3js-viewpage-current-label', + topbarContainerSelector: '.t3js-viewpage-topbar', + + queue: [], + queueIsRunning: false, + queueDelayTimer: null + + }; + + ViewPage.persistQueue = function() { + if (ViewPage.queueIsRunning === false && ViewPage.queue.length >= 1) { + ViewPage.queueIsRunning = true; + var item = ViewPage.queue.shift(); + PersistentStorage.set(item.storageIdentifier, item.data).done(function() { + ViewPage.queueIsRunning = false; + ViewPage.persistQueue(); + }); + } + } + + ViewPage.addToQueue = function(storageIdentifier, data) { + var item = { + 'storageIdentifier': storageIdentifier, + 'data': data + }; + ViewPage.queue.push(item); + if (ViewPage.queue.length >= 1) { + ViewPage.persistQueue(); + } + } + + ViewPage.setSize = function(width, height) { + if (isNaN(height)) { + height = ViewPage.calculateContainerMaxHeight(); + } + if (height < ViewPage.minimalHeight) { + height = ViewPage.minimalHeight; + } + if (isNaN(width)) { + width = ViewPage.calculateContainerMaxWidth(); + } + if (width < ViewPage.minimalWidth) { + width = ViewPage.minimalWidth; + } + + $(ViewPage.inputWidthSelector).val(width); + $(ViewPage.inputHeightSelector).val(height); + + ViewPage.$resizableContainer.css({ + width: width, + height: height, + left: 0 + }); + } + + ViewPage.getCurrentWidth = function() { + return $(ViewPage.inputWidthSelector).val(); + } + + ViewPage.getCurrentHeight = function() { + return $(ViewPage.inputHeightSelector).val(); + } + + ViewPage.setLabel = function(label) { + $(ViewPage.currentLabelSelector).html(label); + } + + ViewPage.getCurrentLabel = function() { + return $(ViewPage.currentLabelSelector).html().trim(); + } + + ViewPage.persistCurrentPreset = function() { + var data = { + width: ViewPage.getCurrentWidth(), + height: ViewPage.getCurrentHeight(), + label: ViewPage.getCurrentLabel() + } + ViewPage.addToQueue(ViewPage.storagePrefix + 'current', data); + } + + ViewPage.persistCustomPreset = function() { + var data = { + width: ViewPage.getCurrentWidth(), + height: ViewPage.getCurrentHeight() + } + $(ViewPage.customSelector).data("width", data.width); + $(ViewPage.customSelector).data("height", data.height); + $(ViewPage.customWidthSelector).html(data.width); + $(ViewPage.customHeightSelector).html(data.height); + ViewPage.addToQueue(ViewPage.storagePrefix + 'custom', data); + } + + ViewPage.persistCustomPresetAfterChange = function() { + clearTimeout(ViewPage.queueDelayTimer); + ViewPage.queueDelayTimer = setTimeout(function() { + ViewPage.persistCustomPreset(); + }, 1000); + }; + + /** + * Initialize + */ + ViewPage.initialize = function() { + + ViewPage.$iframe = $('#tx_viewpage_iframe'); + ViewPage.$resizableContainer = $(ViewPage.resizableContainerIdentifier); + ViewPage.$sizeSelector = $(ViewPage.sizeIdentifier); + + // Change orientation + $(document).on('click', ViewPage.changeOrientationSelector, function() { + var width = $(ViewPage.inputHeightSelector).val(); + var height = $(ViewPage.inputWidthSelector).val(); + ViewPage.setSize(width, height); + ViewPage.persistCurrentPreset(); + }); + + // On change + $(document).on('change', ViewPage.inputWidthSelector, function() { + var width = $(ViewPage.inputWidthSelector).val(); + var height = $(ViewPage.inputHeightSelector).val(); + ViewPage.setSize(width, height); + ViewPage.setLabel(ViewPage.defaultLabel); + ViewPage.persistCustomPresetAfterChange(); + }); + $(document).on('change', ViewPage.inputHeightSelector, function() { + var width = $(ViewPage.inputWidthSelector).val(); + var height = $(ViewPage.inputHeightSelector).val(); + ViewPage.setSize(width, height); + ViewPage.setLabel(ViewPage.defaultLabel); + ViewPage.persistCustomPresetAfterChange(); + }); + + // Add event to width selector so the container is resized + $(document).on('click', ViewPage.changePresetSelector, function() { + var data = $(this).data(); + ViewPage.setSize(parseInt(data.width), parseInt(data.height)); + ViewPage.setLabel(data.label); + ViewPage.persistCurrentPreset(); + }); + + // Initialize the jQuery UI Resizable plugin + ViewPage.$resizableContainer.resizable({ + handles: 'w, sw, s, se, e' + }); + + ViewPage.$resizableContainer.on('resizestart', function() { + // Add iframe overlay to prevent losing the mouse focus to the iframe while resizing fast + $(this).append('<div id="viewpage-iframe-cover" style="z-index:99;position:absolute;width:100%;top:0;left:0;height:100%;"></div>'); + }); + + ViewPage.$resizableContainer.on('resize', function(evt, ui) { + ui.size.width = ui.originalSize.width + ((ui.size.width - ui.originalSize.width) * 2); + if (ui.size.height < ViewPage.minimalHeight) { + ui.size.height = ViewPage.minimalHeight; + } + if (ui.size.width < ViewPage.minimalWidth) { + ui.size.width = ViewPage.minimalWidth; + } + $(ViewPage.inputWidthSelector).val(ui.size.width); + $(ViewPage.inputHeightSelector).val(ui.size.height); + ViewPage.$resizableContainer.css({ + left: 0 + }); + ViewPage.setLabel(ViewPage.defaultLabel); + }); + + ViewPage.$resizableContainer.on('resizestop', function() { + $('#viewpage-iframe-cover').remove(); + ViewPage.persistCurrentPreset(); + ViewPage.persistCustomPreset(); + }); + }; + + /** + * @returns {Number} + */ + ViewPage.calculateContainerMaxHeight = function() { + ViewPage.$resizableContainer.hide(); + var $moduleBody = $(ViewPage.moduleBodySelector); + var padding = $moduleBody.outerHeight() - $moduleBody.height(), + documentHeight = $(document).height(), + topbarHeight = $(ViewPage.topbarContainerSelector).outerHeight(); + ViewPage.$resizableContainer.show(); + return documentHeight - padding - topbarHeight - 8; + }; + + /** + * @returns {Number} + */ + ViewPage.calculateContainerMaxWidth = function() { + ViewPage.$resizableContainer.hide(); + var $moduleBody = $(ViewPage.moduleBodySelector); + var padding = $moduleBody.outerWidth() - $moduleBody.width(), + documentWidth = $(document).width(); + ViewPage.$resizableContainer.show(); + return parseInt(documentWidth - padding); + }; + + /** + * @param {String} url + * @returns {{}} + */ + ViewPage.getUrlVars = function(url) { + var vars = {}; + var hash; + var hashes = url.slice(url.indexOf('?') + 1).split('&'); + for (var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars[hash[0]] = hash[1]; + } + return vars; + }; + + $(ViewPage.initialize); + + return ViewPage; }); diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js index bd3dfd54274765fac3cb06993152e3915f1d7315..b5f344f540c09cfd490562a3a1a92e11874c4309 100644 --- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js +++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js @@ -16,1176 +16,1213 @@ * RequireJS module for the workspace backend module */ define([ - 'jquery', - 'TYPO3/CMS/Workspaces/Workspaces', - 'TYPO3/CMS/Backend/Tooltip', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Modal', - 'TYPO3/CMS/Backend/Wizard', - 'nprogress', - 'TYPO3/CMS/Backend/jquery.clearable' + 'jquery', + 'TYPO3/CMS/Workspaces/Workspaces', + 'TYPO3/CMS/Backend/Tooltip', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Modal', + 'TYPO3/CMS/Backend/Wizard', + 'nprogress', + 'TYPO3/CMS/Backend/jquery.clearable' ], function($, Workspaces, Tooltip, Severity, Modal, Wizard, NProgress) { - 'use strict'; - - var Backend = { - workspaceTitle: '', - identifiers: { - searchForm: '#workspace-settings-form', - searchTextField: '#workspace-settings-form input[name="search-text"]', - searchSubmitBtn: '#workspace-settings-form button[type="submit"]', - depthSelector: '#workspace-settings-form [name="depth"]', - languageSelector: '#workspace-settings-form select[name="languages"]', - actionForm: '#workspace-actions-form', - chooseStageAction: '#workspace-actions-form [name="stage-action"]', - chooseSelectionAction: '#workspace-actions-form [name="selection-action"]', - chooseMassAction: '#workspace-actions-form [name="mass-action"]', - container: '#workspace-panel', - actionIcons: '#workspace-action-icons', - toggleAll: '.t3js-toggle-all', - previewLinksButton: '.t3js-preview-link', - pagination: '#workspace-pagination' - }, - settings: { - depth: TYPO3.settings.Workspaces.depth, - dir: 'ASC', - id: TYPO3.settings.Workspaces.id, - language: TYPO3.settings.Workspaces.language, - limit: 30, - query: '', - sort: 'label_Live', - start: 0, - filterTxt: '' - }, - paging: { - currentPage: 1, - totalPages: 1, - totalItems: 0 - }, - allToggled: false, - elements: {}, // filled in Backend.getElements() - latestPath: '', - markedRecordsForMassAction: [], - indentationPadding: 26 - }; - - Backend.initialize = function() { - Backend.getElements(); - Backend.registerEvents(); - - if (TYPO3.settings.Workspaces.depth > 0) { - Backend.elements.$depthSelector.val(TYPO3.settings.Workspaces.depth); - } - - Backend.loadWorkspaceComponents(); - }; - - Backend.getElements = function() { - Backend.elements.$searchForm = $(Backend.identifiers.searchForm); - Backend.elements.$searchTextField = $(Backend.identifiers.searchTextField); - Backend.elements.$searchSubmitBtn = $(Backend.identifiers.searchSubmitBtn); - Backend.elements.$depthSelector = $(Backend.identifiers.depthSelector); - Backend.elements.$languageSelector = $(Backend.identifiers.languageSelector); - Backend.elements.$container = $(Backend.identifiers.container); - Backend.elements.$tableBody = Backend.elements.$container.find('tbody'); - Backend.elements.$actionIcons = $(Backend.identifiers.actionIcons); - Backend.elements.$toggleAll = $(Backend.identifiers.toggleAll); - Backend.elements.$chooseStageAction = $(Backend.identifiers.chooseStageAction); - Backend.elements.$chooseSelectionAction = $(Backend.identifiers.chooseSelectionAction); - Backend.elements.$chooseMassAction = $(Backend.identifiers.chooseMassAction); - Backend.elements.$previewLinksButton = $(Backend.identifiers.previewLinksButton); - Backend.elements.$pagination = $(Backend.identifiers.pagination); - }; - - Backend.registerEvents = function() { - $(document).on('click', '[data-action="swap"]', function(e) { - var $tr = $(e.target).closest('tr'); - Workspaces.checkIntegrity( - { - selection: [ - { - liveId: $tr.data('uid'), - versionId: $tr.data('t3ver_oid'), - table: $tr.data('table') - } - ], - type: 'selection' - } - ).done(function(response) { - if (response[0].result.result === 'warning') { - Backend.addIntegrityCheckWarningToWizard(); - } - - Wizard.setup.forceSelection = false; - Wizard.addSlide( - 'swap-confirm', - 'Swap', - TYPO3.lang['window.swap.message'], - Severity.info - ); - Wizard.addFinalProcessingSlide(function() { - // We passed this slide, swap the record now - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload('swapSingleRecord', [ - $tr.data('table'), - $tr.data('t3ver_oid'), - $tr.data('uid') - ]) - ).done(function() { - Wizard.dismiss(); - Backend.getWorkspaceInfos(); - Backend.refreshPageTree(); - }); - }).done(function() { - Wizard.show(); - }); - }); - }).on('click', '[data-action="prevstage"]', function(e) { - Backend.sendToStage($(e.target).closest('tr'), 'prev'); - }).on('click', '[data-action="nextstage"]', function(e) { - Backend.sendToStage($(e.target).closest('tr'), 'next'); - }).on('click', '[data-action="changes"]', Backend.viewChanges - ).on('click', '[data-action="preview"]', Backend.openPreview - ).on('click', '[data-action="open"]', function(e) { - var $tr = $(e.target).closest('tr'), - newUrl = TYPO3.settings.FormEngine.moduleUrl + '&returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + $tr.data('table') + '][' + $tr.data('uid') + ']=edit'; - - // Append workspace of record in all-workspaces view - if (TYPO3.settings.Workspaces.allView) { - newUrl += '&workspace=' + $tr.data('t3ver_wsid'); - } - window.location.href = newUrl; - }).on('click', '[data-action="version"]', function(e) { - var $tr = $(e.target).closest('tr'); - if ($tr.data('table') === 'pages') { - top.loadEditId($tr.data('t3ver_oid')); - } else { - top.loadEditId($tr.data('pid')); - } - }).on('click', '[data-action="remove"]', Backend.confirmDeleteRecordFromWorkspace - ).on('click', '[data-action="expand"]', function(e) { - var $me = $(this), - $target = Backend.elements.$tableBody.find($me.data('target')), - iconIdentifier; - - if ($target.first().attr('aria-expanded') === 'true') { - iconIdentifier = 'apps-pagetree-expand'; - } else { - iconIdentifier = 'apps-pagetree-collapse'; - } - - $me.html(Backend.getPreRenderedIcon(iconIdentifier)); - }); - - Backend.elements.$searchForm.on('submit', function(e) { - e.preventDefault(); - Backend.settings.filterTxt = Backend.elements.$searchTextField.val(); - Backend.getWorkspaceInfos(); - }); - - Backend.elements.$searchTextField.on('keyup', function() { - var $me = $(this); - - if ($me.val() !== '') { - Backend.elements.$searchSubmitBtn.removeClass('disabled'); - } else { - Backend.elements.$searchSubmitBtn.addClass('disabled'); - Backend.getWorkspaceInfos(); - } - }).clearable( - { - onClear: function() { - Backend.elements.$searchSubmitBtn.addClass('disabled'); - Backend.settings.filterTxt = ''; - Backend.getWorkspaceInfos(); - } - } - ); - - // checkboxes in the table - Backend.elements.$toggleAll.on('click', function() { - Backend.allToggled = !Backend.allToggled; - Backend.elements.$tableBody.find('input[type="checkbox"]').prop('checked', Backend.allToggled).trigger('change'); - }); - Backend.elements.$tableBody.on('change', 'tr input[type=checkbox]', Backend.handleCheckboxChange); - - // Listen for depth changes - Backend.elements.$depthSelector.on('change', function(e) { - var $me = $(this); - Backend.settings.depth = $me.val(); - - Backend.getWorkspaceInfos(); - }); - - // Generate preview links - Backend.elements.$previewLinksButton.on('click', Backend.generatePreviewLinks); - - // Listen for language changes - Backend.elements.$languageSelector.on('change', function(e) { - var $me = $(this); - Backend.settings.language = $me.val(); - - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload('saveLanguageSelection', [$me.val()]), - Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) - ]).done(function(response) { - Backend.elements.$languageSelector.prev().html($me.find(':selected').data('icon')); - Backend.renderWorkspaceInfos(response[1].result); - }); - }); - - // Listen for actions - Backend.elements.$chooseStageAction.on('change', Backend.sendToSpecificStageAction); - Backend.elements.$chooseSelectionAction.on('change', Backend.runSelectionAction); - Backend.elements.$chooseMassAction.on('change', Backend.runMassAction); - - // clicking an action in the paginator - Backend.elements.$pagination.on('click', 'a[data-action]', function(e) { - e.preventDefault(); - - var $el = $(this), - reload = false; - - switch ($el.data('action')) { - case 'previous': - if (Backend.paging.currentPage > 1) { - Backend.paging.currentPage--; - reload = true; - } - break; - case 'next': - if (Backend.paging.currentPage < Backend.paging.totalPages) { - Backend.paging.currentPage++; - reload = true; - } - break; - case 'page': - Backend.paging.currentPage = parseInt($el.data('page')); - reload = true; - break; - } - - if (reload) { - // Adjust settings - Backend.settings.start = Backend.settings.limit * (Backend.paging.currentPage - 1); - Backend.getWorkspaceInfos(); - } - }); - }; - - Backend.handleCheckboxChange = function(e) { - var $checkbox = $(this), - $tr = $checkbox.parents('tr'), - table = $tr.data('table'), - uid = $tr.data('uid'), - t3ver_oid = $tr.data('t3ver_oid'), - record = table + ':' + uid + ':' + t3ver_oid; - - if ($checkbox.prop('checked')) { - Backend.markedRecordsForMassAction.push(record); - $tr.addClass('warning'); - } else { - var index = Backend.markedRecordsForMassAction.indexOf(record); - if (index > -1) { - Backend.markedRecordsForMassAction.splice(index, 1); - } - $tr.removeClass('warning'); - } - - Backend.elements.$chooseStageAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0); - Backend.elements.$chooseSelectionAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0); - Backend.elements.$chooseMassAction.prop('disabled', Backend.markedRecordsForMassAction.length > 0); - }; - - /** - * Generates the diff view of a record - * - * @param {Object} diff - * @return {$} - */ - Backend.generateDiffView = function(diff) { - var $diff = $('<div />', {class: 'diff'}); - - for (var i = 0; i < diff.length; ++i) { - $diff.append( - $('<div />', {class: 'diff-item'}).append( - $('<div />', {class: 'diff-item-title'}).text(diff[i].label), - $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(diff[i].content) - ) - ); - } - return $diff; - }; - - /** - * Generates the comments view of a record - * - * @param {Object} comments - * @return {$} - */ - Backend.generateCommentView = function(comments) { - var $comments = $('<div />'); - - for (var i = 0; i < comments.length; ++i) { - var $panel = $('<div />', {class: 'panel panel-default'}); - - if (comments[i].user_comment.length > 0) { - $panel.append( - $('<div />', {class: 'panel-body'}).html(comments[i].user_comment) - ); - } - - $panel.append( - $('<div />', {class: 'panel-footer'}).append( - $('<span />', {class: 'label label-success'}).text(comments[i].stage_title), - $('<span />', {class: 'label label-info'}).text(comments[i].tstamp) - ) - ); - - $comments.append( - $('<div />', {class: 'media'}).append( - $('<div />', {class: 'media-left text-center'}).text(comments[i].user_username).prepend( - $('<div />').html(comments[i].user_avatar) - ), - $('<div />', {class: 'media-body'}).append($panel) - ) - ); - } - - return $comments; - }; - - /** - * Sends a record to a stage - * - * @param {Object} $row - * @param {String} direction - */ - Backend.sendToStage = function($row, direction) { - var nextStage, - stageWindowAction, - stageExecuteAction; - - if (direction === 'next') { - nextStage = $row.data('nextStage'); - stageWindowAction = 'sendToNextStageWindow'; - stageExecuteAction = 'sendToNextStageExecute'; - } else if (direction === 'prev') { - nextStage = $row.data('prevStage'); - stageWindowAction = 'sendToPrevStageWindow'; - stageExecuteAction = 'sendToPrevStageExecute'; - } else { - throw 'Invalid direction given.'; - } - - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload(stageWindowAction, [ - $row.data('uid'), $row.data('table'), $row.data('t3ver_oid') - ]) - ).done(function(response) { - var $modal = Workspaces.renderSendToStageWindow(response); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'ok') { - var $form = $(e.currentTarget).find('form'), - serializedForm = $form.serializeObject(); - - serializedForm.affects = { - table: $row.data('table'), - nextStage: nextStage, - t3ver_oid: $row.data('t3ver_oid'), - uid: $row.data('uid'), - elements: [] - }; - - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload(stageExecuteAction, [serializedForm]), - Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) - ]).done(function(response) { - $modal.modal('hide'); - Backend.renderWorkspaceInfos(response[1].result); - Backend.refreshPageTree(); - }); - } - }); - }); - }; - - /** - * Loads the workspace components, like available stage actions and items of the workspace - */ - Backend.loadWorkspaceComponents = function() { - Workspaces.sendRemoteRequest([ - Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings), - Workspaces.generateRemotePayload('getStageActions', {}), - Workspaces.generateRemoteMassActionsPayload('getMassStageActions', {}), - Workspaces.generateRemotePayload('getSystemLanguages', {}) - ]).done(function(response) { - Backend.elements.$depthSelector.prop('disabled', false); - - // Records - Backend.renderWorkspaceInfos(response[0].result); - - // Stage actions - var stageActions = response[1].result.data, - i; - for (i = 0; i < stageActions.length; ++i) { - Backend.elements.$chooseStageAction.append( - $('<option />').val(stageActions[i].uid).text(stageActions[i].title) - ); - } - - // Mass actions - var massActions = response[2].result.data; - for (i = 0; i < massActions.length; ++i) { - Backend.elements.$chooseSelectionAction.append( - $('<option />').val(massActions[i].action).text(massActions[i].title) - ); - - Backend.elements.$chooseMassAction.append( - $('<option />').val(massActions[i].action).text(massActions[i].title) - ); - } - - // Languages - var languages = response[3].result.data; - for (i = 0; i < languages.length; ++i) { - var $option = $('<option />').val(languages[i].uid).text(languages[i].title).data('icon', languages[i].icon); - if (String(languages[i].uid) === String(TYPO3.settings.Workspaces.language)) { - $option.prop('selected', true); - Backend.elements.$languageSelector.prev().html(languages[i].icon); - } - Backend.elements.$languageSelector.append($option); - } - Backend.elements.$languageSelector.prop('disabled', false); - }); - }; - - /** - * Gets the workspace infos - * - * @return {Promise} - * @protected - */ - Backend.getWorkspaceInfos = function() { - Workspaces.sendRemoteRequest( - Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) - ).done(function(response) { - Backend.renderWorkspaceInfos(response[0].result); - }); - }; - - /** - * Renders fetched workspace informations - * - * @param {Object} result - */ - Backend.renderWorkspaceInfos = function(result) { - Backend.elements.$tableBody.children().remove(); - Backend.allToggled = false; - Backend.elements.$chooseStageAction.prop('disabled', true); - Backend.elements.$chooseSelectionAction.prop('disabled', true); - Backend.elements.$chooseMassAction.prop('disabled', result.data.length === 0); - - Backend.buildPagination(result.total); - - for (var i = 0; i < result.data.length; ++i) { - var item = result.data[i], - $actions = $('<div />', {class: 'btn-group'}), - $integrityIcon = ''; - $actions.append( - Backend.getAction(item.Workspaces_CollectionChildren > 0 && item.Workspaces_CollectionCurrent !== '', 'expand', 'apps-pagetree-collapse').attr('title', TYPO3.lang['tooltip.expand']).attr('data-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]').attr('data-toggle', 'collapse'), - $('<button />', {class: 'btn btn-default', 'data-action': 'changes', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.showChanges']}).append(Backend.getPreRenderedIcon('actions-document-info')), - Backend.getAction(item.allowedAction_swap && item.Workspaces_CollectionParent === '', 'swap', 'actions-version-swap-version').attr('title', TYPO3.lang['tooltip.swap']), - Backend.getAction(item.allowedAction_view, 'preview', 'actions-version-workspace-preview').attr('title', TYPO3.lang['tooltip.viewElementAction']), - $('<button />', {class: 'btn btn-default', 'data-action': 'open', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.editElementAction']}).append(Backend.getPreRenderedIcon('actions-open')), - $('<button />', {class: 'btn btn-default', 'data-action': 'version', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.openPage']}).append(Backend.getPreRenderedIcon('actions-version-page-open')), - Backend.getAction(item.allowedAction_delete, 'remove', 'actions-version-document-remove').attr('title', TYPO3.lang['tooltip.discardVersion']), - $('<label />', {class: 'btn btn-default btn-checkbox'}).append( - $('<input />', {type: 'checkbox'}), - $('<span />', {class: 't3-icon fa'}) - ) - ); - - if (item.integrity.messages !== '') { - $integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]); - $integrityIcon - .attr('data-toggle', 'tooltip') - .attr('data-placement', 'top') - .attr('data-html', true) - .attr('title', item.integrity.messages); - } - - if (Backend.latestPath !== item.path_Workspace) { - Backend.latestPath = item.path_Workspace; - Backend.elements.$tableBody.append( - $('<tr />').append( - $('<th />', {colspan: 6}).text(Backend.latestPath) - ) - ); - } - - var rowConfiguration = { - 'data-uid': item.uid, - 'data-pid': item.livepid, - 'data-t3ver_oid': item.t3ver_oid, - 'data-t3ver_wsid': item.t3ver_wsid, - 'data-table': item.table, - 'data-next-stage': item.value_nextStage, - 'data-prev-stage': item.value_prevStage, - 'data-stage': item.stage - }; - - if (item.Workspaces_CollectionParent !== '') { - rowConfiguration['data-collection'] = item.Workspaces_CollectionParent; - rowConfiguration['class'] = 'collapse'; - } - - Backend.elements.$tableBody.append( - $('<tr />', rowConfiguration).append( - $('<td />', {class: 't3js-title-workspace', style: item.Workspaces_CollectionLevel > 0 ? 'padding-left: ' + Backend.indentationPadding * item.Workspaces_CollectionLevel + 'px' : ''}).html(item.icon_Workspace + ' ' + '<a href="#" data-action="changes"><span class="item-state-' + item.state_Workspace + '">' + item.label_Workspace + '</span></a>'), - $('<td />', {class: 't3js-title-live'}).html(item.icon_Live + ' ' + item.label_Live), - $('<td />').text(item.label_Stage), - $('<td />').html($integrityIcon), - $('<td />').html(item.language.icon), - $('<td />', {class: 'text-right nowrap'}).append($actions) - ) - ); - - Tooltip.initialize('[data-toggle="tooltip"]', { - delay: { - show: 500, - hide: 100 - }, - trigger: 'hover', - container: 'body' - }); - } - }; - - /** - * Renders the pagination - * - * @param {Number} totalItems - */ - Backend.buildPagination = function(totalItems) { - if (totalItems === 0) { - Backend.elements.$pagination.contents().remove(); - return; - } - - Backend.paging.totalItems = totalItems; - Backend.paging.totalPages = Math.ceil(totalItems / Backend.settings.limit); - - if (Backend.paging.totalPages === 1) { - // early abort if only one page is available - Backend.elements.$pagination.contents().remove(); - return; - } - - var $ul = $('<ul />', {class: 'pagination pagination-block'}), - liElements = [], - $controlFirstPage = $('<li />').append( - $('<a />', {'data-action': 'previous'}).append( - $('<span />', {class: 't3-icon fa fa-arrow-left'}) - ) - ), - $controlLastPage = $('<li />').append( - $('<a />', {'data-action': 'next'}).append( - $('<span />', {class: 't3-icon fa fa-arrow-right'}) - ) - ); - - if (Backend.paging.currentPage === 1) { - $controlFirstPage.disablePagingAction(); - } - - if (Backend.paging.currentPage === Backend.paging.totalPages) { - $controlLastPage.disablePagingAction(); - } - - for (var i = 1; i <= Backend.paging.totalPages; i++) { - var $li = $('<li />', {class: Backend.paging.currentPage === i ? 'active' : ''}); - $li.append( - $('<a />', {'data-action': 'page', 'data-page': i}).append( - $('<span />').text(i) - ) - ); - liElements.push($li); - } - - $ul.append($controlFirstPage, liElements, $controlLastPage); - Backend.elements.$pagination.html($ul); - }; - - /** - * View changes of a record - * - * @param {Event} e - */ - Backend.viewChanges = function(e) { - e.preventDefault(); - - var $tr = $(e.target).closest('tr'); - - Workspaces.sendRemoteRequest( - Workspaces.generateRemotePayload('getRowDetails', { - stage: $tr.data('stage'), - t3ver_oid: $tr.data('t3ver_oid'), - table: $tr.data('table'), - uid: $tr.data('uid') - }) - ).done(function(response) { - var item = response[0].result.data[0], - $content = $('<div />'), - $tabsNav = $('<ul />', {class: 'nav nav-tabs', role: 'tablist'}), - $tabsContent = $('<div />', {class: 'tab-content'}), - modalButtons = []; - - $content.append( - $('<p />').html(TYPO3.lang['path'].replace('{0}', item.path_Live)), - $('<p />').html(TYPO3.lang['current_step'].replace('{0}', item.label_Stage).replace('{1}', item.stage_position).replace('{2}', item.stage_count)) - ); - - if (item.diff.length > 0) { - $tabsNav.append( - $('<li />', {role: 'presentation'}).append( - $('<a />', {href: '#workspace-changes', 'aria-controls': 'workspace-changes', role: 'tab', 'data-toggle': 'tab'}).text(TYPO3.lang['window.recordChanges.tabs.changeSummary']) - ) - ); - $tabsContent.append( - $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-changes'}).append( - $('<div />', {class: 'form-section'}).append( - Backend.generateDiffView(item.diff) - ) - ) - ); - } - - if (item.comments.length > 0) { - $tabsNav.append( - $('<li />', {role: 'presentation'}).append( - $('<a />', {href: '#workspace-comments', 'aria-controls': 'workspace-comments', role: 'tab', 'data-toggle': 'tab'}).html(TYPO3.lang['window.recordChanges.tabs.comments'] + ' ').append( - $('<span />', {class: 'badge'}).text(item.comments.length) - ) - ) - ); - $tabsContent.append( - $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-comments'}).append( - $('<div />', {class: 'form-section'}).append( - Backend.generateCommentView(item.comments) - ) - ) - ); - } - - if (item.history.total > 0) { - $tabsNav.append( - $('<li />', {role: 'presentation'}).append( - $('<a />', {href: '#workspace-history', 'aria-controls': 'workspace-history', role: 'tab', 'data-toggle': 'tab'}).text(TYPO3.lang['window.recordChanges.tabs.history']) - ) - ); - - $tabsContent.append( - $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-history'}).append( - $('<div />', {class: 'form-section'}).append( - Backend.generateHistoryView(item.history.data) - ) - ) - ); - } - - // Mark the first tab and pane as active - $tabsNav.find('li').first().addClass('active'); - $tabsContent.find('.tab-pane').first().addClass('active'); - - // Attach tabs - $content.append( - $('<div />').append( - $tabsNav, - $tabsContent - ) - ); - - if ($tr.data('stage') !== $tr.data('prevStage')) { - modalButtons.push({ - text: item.label_PrevStage.title, - active: true, - btnClass: 'btn-default', - name: 'prevstage', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - Backend.sendToStage($(e.target).closest('tr'), 'prev'); - } - }); - } - - modalButtons.push({ - text: item.label_NextStage.title, - active: true, - btnClass: 'btn-default', - name: 'nextstage', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - Backend.sendToStage($(e.target).closest('tr'), 'next'); - } - }); - modalButtons.push({ - text: TYPO3.lang['close'], - active: true, - btnClass: 'btn-info', - name: 'cancel', - trigger: function () { - Modal.currentModal.trigger('modal-dismiss'); - } - }); - - Modal.show( - TYPO3.lang['window.recordInformation'].replace('{0}', $.trim($tr.find('.t3js-title-live').text())), - $content, - Severity.info, - modalButtons - ); - }); - }; - - /** - * Opens a record in a preview window - * - * @param {Event} e - */ - Backend.openPreview = function(e) { - var $tr = $(e.target).closest('tr'); - - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload('viewSingleRecord', [ - $tr.data('table'), $tr.data('uid') - ]) - ).done(function(response) { - eval(response[0].result); - }); - }; - - /** - * Renders the record's history - * - * @param {Object} data - */ - Backend.generateHistoryView = function(data) { - var $history = $('<div />'); - - for (var i = 0; i < data.length; ++i) { - var $panel = $('<div />', {class: 'panel panel-default'}), - $diff; - - if (typeof data[i].differences === 'object') { - if (data[i].differences.length === 0) { - // Somehow here are no differences. What a pity, skip that record - continue; - } - $diff = $('<div />', {class: 'diff'}); - - for (var j = 0; j < data[i].differences.length; ++j) { - $diff.append( - $('<div />', {class: 'diff-item'}).append( - $('<div />', {class: 'diff-item-title'}).text(data[i].differences[j].label), - $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(data[i].differences[j].html) - ) - ); - } - - $panel.append( - $('<div />').append($diff) - ); - } else { - $panel.append( - $('<div />', {class: 'panel-body'}).text(data[i].differences) - ); - } - $panel.append( - $('<div />', {class: 'panel-footer'}).append( - $('<span />', {class: 'label label-info'}).text(data[i].datetime) - ) - ); - - $history.append( - $('<div />', {class: 'media'}).append( - $('<div />', {class: 'media-left text-center'}).text(data[i].user).prepend( - $('<div />').html(data[i].user_avatar) - ), - $('<div />', {class: 'media-body'}).append($panel) - ) - ); - } - - return $history; - }; - - /** - * Shows a confirmation modal and deletes the selected record from workspace. - * - * @param {Event} e - */ - Backend.confirmDeleteRecordFromWorkspace = function(e) { - var $tr = $(e.target).closest('tr'); - var $modal = Modal.confirm( - TYPO3.lang['window.discard.title'], - TYPO3.lang['window.discard.message'], - Severity.warning, - [ - { - text: TYPO3.lang['cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function() { - $modal.modal('hide'); - } - }, { - text: TYPO3.lang['ok'], - btnClass: 'btn-warning', - name: 'ok' - } - ] - ); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'ok') { - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload('deleteSingleRecord', [ - $tr.data('table'), - $tr.data('uid') - ]) - ]).done(function() { - $modal.modal('hide'); - Backend.getWorkspaceInfos(); - Backend.refreshPageTree(); - }); - } - }); - }; - - /** - * Runs a mass action - */ - Backend.runSelectionAction = function() { - var selectedAction = Backend.elements.$chooseSelectionAction.val(), - integrityCheckRequired = selectedAction !== 'discard'; - - if (selectedAction.length === 0) { - // Don't do anything if that value is empty - return; - } - - var affectedRecords = []; - for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) { - var affected = Backend.markedRecordsForMassAction[i].split(':'); - affectedRecords.push({ - table: affected[0], - liveId: affected[2], - versionId: affected[1] - }); - } - - if (!integrityCheckRequired) { - Wizard.setup.forceSelection = false; - Backend.renderSelectionActionWizard(selectedAction, affectedRecords); - } else { - Workspaces.checkIntegrity( - { - selection: affectedRecords, - type: 'selection' - } - ).done(function(response) { - Wizard.setup.forceSelection = false; - if (response[0].result.result === 'warning') { - Backend.addIntegrityCheckWarningToWizard(); - } - Backend.renderSelectionActionWizard(selectedAction, affectedRecords); - }); - } - }; - - /** - * Adds a slide to the wizard concerning an integrity check warning. - */ - Backend.addIntegrityCheckWarningToWizard = function() { - Wizard.addSlide( - 'integrity-warning', - 'Warning', - TYPO3.lang['integrity.hasIssuesDescription'] + '<br>' + TYPO3.lang['integrity.hasIssuesQuestion'], - Severity.warning - ); - }; - - /** - * Renders the wizard for selection actions - * - * @param {String} selectedAction - * @param {Object} affectedRecords - */ - Backend.renderSelectionActionWizard = function(selectedAction, affectedRecords) { - Wizard.addSlide( - 'mass-action-confirmation', - TYPO3.lang['window.selectionAction.title'], - $('<p />').text(TYPO3.lang['tooltip.' + selectedAction + 'Selected']), - Severity.warning - ); - Wizard.addFinalProcessingSlide(function() { - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload('executeSelectionAction', { - action: selectedAction, - selection: affectedRecords - }) - ).done(function() { - Backend.getWorkspaceInfos(); - Wizard.dismiss(); - Backend.refreshPageTree(); - }); - }).done(function() { - Wizard.show(); - - Wizard.getComponent().on('wizard-dismissed', function() { - Backend.elements.$chooseSelectionAction.val(''); - }); - }); - }; - - /** - * Runs a mass action - */ - Backend.runMassAction = function() { - var selectedAction = Backend.elements.$chooseMassAction.val(), - integrityCheckRequired = selectedAction !== 'discard'; - - if (selectedAction.length === 0) { - // Don't do anything if that value is empty - return; - } - - if (!integrityCheckRequired) { - Wizard.setup.forceSelection = false; - Backend.renderMassActionWizard(selectedAction); - } else { - Workspaces.checkIntegrity( - { - language: Backend.settings.language, - type: selectedAction - } - ).done(function(response) { - Wizard.setup.forceSelection = false; - if (response[0].result.result === 'warning') { - Backend.addIntegrityCheckWarningToWizard(); - } - Backend.renderMassActionWizard(selectedAction); - }); - } - }; - - /** - * Renders the wizard for mass actions - * - * @param {String} selectedAction - */ - Backend.renderMassActionWizard = function(selectedAction) { - var massAction, - doSwap = false; - - switch (selectedAction) { - case 'publish': - massAction = 'publishWorkspace'; - break; - case 'swap': - massAction = 'publishWorkspace'; - doSwap = true; - break; - case 'discard': - massAction = 'flushWorkspace'; - break; - } - - if (massAction === null) { - throw 'Invalid mass action ' + selectedAction + ' called.'; - } - - Wizard.setup.forceSelection = false; - Wizard.addSlide( - 'mass-action-confirmation', - TYPO3.lang['window.massAction.title'], - $('<p />').html(TYPO3.lang['tooltip.' + selectedAction + 'All'] + '<br><br>' + TYPO3.lang['tooltip.affectWholeWorkspace']), - Severity.warning - ); - Wizard.addFinalProcessingSlide(function() { - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteMassActionsPayload(massAction, { - init: true, - total: 0, - processed: 0, - language: Backend.settings.language, - swap: doSwap - }) - ).done(function(response) { - var payload = response[0].result; - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteMassActionsPayload(massAction, payload) - ).done(function() { - Backend.getWorkspaceInfos(); - Wizard.dismiss(); - }); - }); - }).done(function() { - Wizard.show(); - - Wizard.getComponent().on('wizard-dismissed', function() { - Backend.elements.$chooseMassAction.val(''); - }); - }); - }; - - /** - * Sends marked records to a stage - * - * @param {Event} e - */ - Backend.sendToSpecificStageAction = function(e) { - var affectedRecords = [], - stage = $(e.currentTarget).val(); - for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) { - var affected = Backend.markedRecordsForMassAction[i].split(':'); - affectedRecords.push({ - table: affected[0], - uid: affected[1], - t3ver_oid: affected[2] - }); - } - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload('sendToSpecificStageWindow', [ - stage, affectedRecords - ]) - ).done(function(response) { - var $modal = Workspaces.renderSendToStageWindow(response); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'ok') { - var $form = $(e.currentTarget).find('form'), - serializedForm = $form.serializeObject(); - - serializedForm.affects = { - elements: affectedRecords, - nextStage: stage - }; - - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload('sendToSpecificStageExecute', [serializedForm]), - Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) - ]).done(function(response) { - $modal.modal('hide'); - Backend.renderWorkspaceInfos(response[1].result); - Backend.refreshPageTree(); - }); - } - }).on('modal-destroyed', function() { - Backend.elements.$chooseStageAction.val(''); - }); - }); - }; - - /** - * Reloads the page tree - */ - Backend.refreshPageTree = function() { - if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { - top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - }; - - /** - * Renders the action button based on the user's permission. - * - * @returns {$} - * @private - */ - Backend.getAction = function(condition, action, iconIdentifier) { - if (condition) { - return $('<button />', {class: 'btn btn-default', 'data-action': action, 'data-toggle': 'tooltip'}).append(Backend.getPreRenderedIcon(iconIdentifier)) - } - return $('<span />', {class: 'btn btn-default disabled'}).append(Backend.getPreRenderedIcon('empty-empty')); - }; - - /** - * Fetches and renders available preview links - */ - Backend.generatePreviewLinks = function() { - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload('generateWorkspacePreviewLinksForAllLanguages', [ - Backend.settings.id - ]) - ).done(function(response) { - var result = response[0].result, - $list = $('<dl />'); - - $.each(result, function(language, url) { - $list.append( - $('<dt />').text(language), - $('<dd />').append( - $('<a />', {href: url, target: '_blank'}).text(url) - ) - ); - }); - - Modal.show( - TYPO3.lang['previewLink'], - $list, - Severity.info, - [{ - text: TYPO3.lang['ok'], - active: true, - btnClass: 'btn-info', - name: 'ok', - trigger: function() { - Modal.currentModal.trigger('modal-dismiss'); - } - }], - ['modal-inner-scroll'] - ); - }); - }; - - /** - * Gets the pre-rendered icon - * This method is intended to be dropped once we use Fluid's StandaloneView. - * - * @param {String} identifier - * @returns {$} - */ - Backend.getPreRenderedIcon = function(identifier) { - return Backend.elements.$actionIcons.find('[data-identifier="' + identifier + '"]').clone(); - }; - - /** - * Serialize a form to a JavaScript object - * - * @see http://stackoverflow.com/a/1186309/4828813 - * @return {Object} - */ - $.fn.serializeObject = function() { - var o = {}; - var a = this.serializeArray(); - $.each(a, function() { - if (typeof o[this.name] !== 'undefined') { - if (!o[this.name].push) { - o[this.name] = [o[this.name]]; - } - o[this.name].push(this.value || ''); - } else { - o[this.name] = this.value || ''; - } - }); - return o; - }; - - /** - * Changes the markup of a pagination action being disabled - */ - $.fn.disablePagingAction = function() { - $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />')); - }; - - $(Backend.initialize); + 'use strict'; + + var Backend = { + workspaceTitle: '', + identifiers: { + searchForm: '#workspace-settings-form', + searchTextField: '#workspace-settings-form input[name="search-text"]', + searchSubmitBtn: '#workspace-settings-form button[type="submit"]', + depthSelector: '#workspace-settings-form [name="depth"]', + languageSelector: '#workspace-settings-form select[name="languages"]', + actionForm: '#workspace-actions-form', + chooseStageAction: '#workspace-actions-form [name="stage-action"]', + chooseSelectionAction: '#workspace-actions-form [name="selection-action"]', + chooseMassAction: '#workspace-actions-form [name="mass-action"]', + container: '#workspace-panel', + actionIcons: '#workspace-action-icons', + toggleAll: '.t3js-toggle-all', + previewLinksButton: '.t3js-preview-link', + pagination: '#workspace-pagination' + }, + settings: { + depth: TYPO3.settings.Workspaces.depth, + dir: 'ASC', + id: TYPO3.settings.Workspaces.id, + language: TYPO3.settings.Workspaces.language, + limit: 30, + query: '', + sort: 'label_Live', + start: 0, + filterTxt: '' + }, + paging: { + currentPage: 1, + totalPages: 1, + totalItems: 0 + }, + allToggled: false, + elements: {}, // filled in Backend.getElements() + latestPath: '', + markedRecordsForMassAction: [], + indentationPadding: 26 + }; + + Backend.initialize = function() { + Backend.getElements(); + Backend.registerEvents(); + + if (TYPO3.settings.Workspaces.depth > 0) { + Backend.elements.$depthSelector.val(TYPO3.settings.Workspaces.depth); + } + + Backend.loadWorkspaceComponents(); + }; + + Backend.getElements = function() { + Backend.elements.$searchForm = $(Backend.identifiers.searchForm); + Backend.elements.$searchTextField = $(Backend.identifiers.searchTextField); + Backend.elements.$searchSubmitBtn = $(Backend.identifiers.searchSubmitBtn); + Backend.elements.$depthSelector = $(Backend.identifiers.depthSelector); + Backend.elements.$languageSelector = $(Backend.identifiers.languageSelector); + Backend.elements.$container = $(Backend.identifiers.container); + Backend.elements.$tableBody = Backend.elements.$container.find('tbody'); + Backend.elements.$actionIcons = $(Backend.identifiers.actionIcons); + Backend.elements.$toggleAll = $(Backend.identifiers.toggleAll); + Backend.elements.$chooseStageAction = $(Backend.identifiers.chooseStageAction); + Backend.elements.$chooseSelectionAction = $(Backend.identifiers.chooseSelectionAction); + Backend.elements.$chooseMassAction = $(Backend.identifiers.chooseMassAction); + Backend.elements.$previewLinksButton = $(Backend.identifiers.previewLinksButton); + Backend.elements.$pagination = $(Backend.identifiers.pagination); + }; + + Backend.registerEvents = function() { + $(document).on('click', '[data-action="swap"]', function(e) { + var $tr = $(e.target).closest('tr'); + Workspaces.checkIntegrity( + { + selection: [ + { + liveId: $tr.data('uid'), + versionId: $tr.data('t3ver_oid'), + table: $tr.data('table') + } + ], + type: 'selection' + } + ).done(function(response) { + if (response[0].result.result === 'warning') { + Backend.addIntegrityCheckWarningToWizard(); + } + + Wizard.setup.forceSelection = false; + Wizard.addSlide( + 'swap-confirm', + 'Swap', + TYPO3.lang['window.swap.message'], + Severity.info + ); + Wizard.addFinalProcessingSlide(function() { + // We passed this slide, swap the record now + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload('swapSingleRecord', [ + $tr.data('table'), + $tr.data('t3ver_oid'), + $tr.data('uid') + ]) + ).done(function() { + Wizard.dismiss(); + Backend.getWorkspaceInfos(); + Backend.refreshPageTree(); + }); + }).done(function() { + Wizard.show(); + }); + }); + }).on('click', '[data-action="prevstage"]', function(e) { + Backend.sendToStage($(e.target).closest('tr'), 'prev'); + }).on('click', '[data-action="nextstage"]', function(e) { + Backend.sendToStage($(e.target).closest('tr'), 'next'); + }).on('click', '[data-action="changes"]', Backend.viewChanges + ).on('click', '[data-action="preview"]', Backend.openPreview + ).on('click', '[data-action="open"]', function(e) { + var $tr = $(e.target).closest('tr'), + newUrl = TYPO3.settings.FormEngine.moduleUrl + '&returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + $tr.data('table') + '][' + $tr.data('uid') + ']=edit'; + + // Append workspace of record in all-workspaces view + if (TYPO3.settings.Workspaces.allView) { + newUrl += '&workspace=' + $tr.data('t3ver_wsid'); + } + window.location.href = newUrl; + }).on('click', '[data-action="version"]', function(e) { + var $tr = $(e.target).closest('tr'); + if ($tr.data('table') === 'pages') { + top.loadEditId($tr.data('t3ver_oid')); + } else { + top.loadEditId($tr.data('pid')); + } + }).on('click', '[data-action="remove"]', Backend.confirmDeleteRecordFromWorkspace + ).on('click', '[data-action="expand"]', function(e) { + var $me = $(this), + $target = Backend.elements.$tableBody.find($me.data('target')), + iconIdentifier; + + if ($target.first().attr('aria-expanded') === 'true') { + iconIdentifier = 'apps-pagetree-expand'; + } else { + iconIdentifier = 'apps-pagetree-collapse'; + } + + $me.html(Backend.getPreRenderedIcon(iconIdentifier)); + }); + + Backend.elements.$searchForm.on('submit', function(e) { + e.preventDefault(); + Backend.settings.filterTxt = Backend.elements.$searchTextField.val(); + Backend.getWorkspaceInfos(); + }); + + Backend.elements.$searchTextField.on('keyup', function() { + var $me = $(this); + + if ($me.val() !== '') { + Backend.elements.$searchSubmitBtn.removeClass('disabled'); + } else { + Backend.elements.$searchSubmitBtn.addClass('disabled'); + Backend.getWorkspaceInfos(); + } + }).clearable( + { + onClear: function() { + Backend.elements.$searchSubmitBtn.addClass('disabled'); + Backend.settings.filterTxt = ''; + Backend.getWorkspaceInfos(); + } + } + ); + + // checkboxes in the table + Backend.elements.$toggleAll.on('click', function() { + Backend.allToggled = !Backend.allToggled; + Backend.elements.$tableBody.find('input[type="checkbox"]').prop('checked', Backend.allToggled).trigger('change'); + }); + Backend.elements.$tableBody.on('change', 'tr input[type=checkbox]', Backend.handleCheckboxChange); + + // Listen for depth changes + Backend.elements.$depthSelector.on('change', function(e) { + var $me = $(this); + Backend.settings.depth = $me.val(); + + Backend.getWorkspaceInfos(); + }); + + // Generate preview links + Backend.elements.$previewLinksButton.on('click', Backend.generatePreviewLinks); + + // Listen for language changes + Backend.elements.$languageSelector.on('change', function(e) { + var $me = $(this); + Backend.settings.language = $me.val(); + + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload('saveLanguageSelection', [$me.val()]), + Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) + ]).done(function(response) { + Backend.elements.$languageSelector.prev().html($me.find(':selected').data('icon')); + Backend.renderWorkspaceInfos(response[1].result); + }); + }); + + // Listen for actions + Backend.elements.$chooseStageAction.on('change', Backend.sendToSpecificStageAction); + Backend.elements.$chooseSelectionAction.on('change', Backend.runSelectionAction); + Backend.elements.$chooseMassAction.on('change', Backend.runMassAction); + + // clicking an action in the paginator + Backend.elements.$pagination.on('click', 'a[data-action]', function(e) { + e.preventDefault(); + + var $el = $(this), + reload = false; + + switch ($el.data('action')) { + case 'previous': + if (Backend.paging.currentPage > 1) { + Backend.paging.currentPage--; + reload = true; + } + break; + case 'next': + if (Backend.paging.currentPage < Backend.paging.totalPages) { + Backend.paging.currentPage++; + reload = true; + } + break; + case 'page': + Backend.paging.currentPage = parseInt($el.data('page')); + reload = true; + break; + } + + if (reload) { + // Adjust settings + Backend.settings.start = Backend.settings.limit * (Backend.paging.currentPage - 1); + Backend.getWorkspaceInfos(); + } + }); + }; + + Backend.handleCheckboxChange = function(e) { + var $checkbox = $(this), + $tr = $checkbox.parents('tr'), + table = $tr.data('table'), + uid = $tr.data('uid'), + t3ver_oid = $tr.data('t3ver_oid'), + record = table + ':' + uid + ':' + t3ver_oid; + + if ($checkbox.prop('checked')) { + Backend.markedRecordsForMassAction.push(record); + $tr.addClass('warning'); + } else { + var index = Backend.markedRecordsForMassAction.indexOf(record); + if (index > -1) { + Backend.markedRecordsForMassAction.splice(index, 1); + } + $tr.removeClass('warning'); + } + + Backend.elements.$chooseStageAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0); + Backend.elements.$chooseSelectionAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0); + Backend.elements.$chooseMassAction.prop('disabled', Backend.markedRecordsForMassAction.length > 0); + }; + + /** + * Generates the diff view of a record + * + * @param {Object} diff + * @return {$} + */ + Backend.generateDiffView = function(diff) { + var $diff = $('<div />', {class: 'diff'}); + + for (var i = 0; i < diff.length; ++i) { + $diff.append( + $('<div />', {class: 'diff-item'}).append( + $('<div />', {class: 'diff-item-title'}).text(diff[i].label), + $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(diff[i].content) + ) + ); + } + return $diff; + }; + + /** + * Generates the comments view of a record + * + * @param {Object} comments + * @return {$} + */ + Backend.generateCommentView = function(comments) { + var $comments = $('<div />'); + + for (var i = 0; i < comments.length; ++i) { + var $panel = $('<div />', {class: 'panel panel-default'}); + + if (comments[i].user_comment.length > 0) { + $panel.append( + $('<div />', {class: 'panel-body'}).html(comments[i].user_comment) + ); + } + + $panel.append( + $('<div />', {class: 'panel-footer'}).append( + $('<span />', {class: 'label label-success'}).text(comments[i].stage_title), + $('<span />', {class: 'label label-info'}).text(comments[i].tstamp) + ) + ); + + $comments.append( + $('<div />', {class: 'media'}).append( + $('<div />', {class: 'media-left text-center'}).text(comments[i].user_username).prepend( + $('<div />').html(comments[i].user_avatar) + ), + $('<div />', {class: 'media-body'}).append($panel) + ) + ); + } + + return $comments; + }; + + /** + * Sends a record to a stage + * + * @param {Object} $row + * @param {String} direction + */ + Backend.sendToStage = function($row, direction) { + var nextStage, + stageWindowAction, + stageExecuteAction; + + if (direction === 'next') { + nextStage = $row.data('nextStage'); + stageWindowAction = 'sendToNextStageWindow'; + stageExecuteAction = 'sendToNextStageExecute'; + } else if (direction === 'prev') { + nextStage = $row.data('prevStage'); + stageWindowAction = 'sendToPrevStageWindow'; + stageExecuteAction = 'sendToPrevStageExecute'; + } else { + throw 'Invalid direction given.'; + } + + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload(stageWindowAction, [ + $row.data('uid'), $row.data('table'), $row.data('t3ver_oid') + ]) + ).done(function(response) { + var $modal = Workspaces.renderSendToStageWindow(response); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + var $form = $(e.currentTarget).find('form'), + serializedForm = $form.serializeObject(); + + serializedForm.affects = { + table: $row.data('table'), + nextStage: nextStage, + t3ver_oid: $row.data('t3ver_oid'), + uid: $row.data('uid'), + elements: [] + }; + + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload(stageExecuteAction, [serializedForm]), + Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) + ]).done(function(response) { + $modal.modal('hide'); + Backend.renderWorkspaceInfos(response[1].result); + Backend.refreshPageTree(); + }); + } + }); + }); + }; + + /** + * Loads the workspace components, like available stage actions and items of the workspace + */ + Backend.loadWorkspaceComponents = function() { + Workspaces.sendRemoteRequest([ + Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings), + Workspaces.generateRemotePayload('getStageActions', {}), + Workspaces.generateRemoteMassActionsPayload('getMassStageActions', {}), + Workspaces.generateRemotePayload('getSystemLanguages', {}) + ]).done(function(response) { + Backend.elements.$depthSelector.prop('disabled', false); + + // Records + Backend.renderWorkspaceInfos(response[0].result); + + // Stage actions + var stageActions = response[1].result.data, + i; + for (i = 0; i < stageActions.length; ++i) { + Backend.elements.$chooseStageAction.append( + $('<option />').val(stageActions[i].uid).text(stageActions[i].title) + ); + } + + // Mass actions + var massActions = response[2].result.data; + for (i = 0; i < massActions.length; ++i) { + Backend.elements.$chooseSelectionAction.append( + $('<option />').val(massActions[i].action).text(massActions[i].title) + ); + + Backend.elements.$chooseMassAction.append( + $('<option />').val(massActions[i].action).text(massActions[i].title) + ); + } + + // Languages + var languages = response[3].result.data; + for (i = 0; i < languages.length; ++i) { + var $option = $('<option />').val(languages[i].uid).text(languages[i].title).data('icon', languages[i].icon); + if (String(languages[i].uid) === String(TYPO3.settings.Workspaces.language)) { + $option.prop('selected', true); + Backend.elements.$languageSelector.prev().html(languages[i].icon); + } + Backend.elements.$languageSelector.append($option); + } + Backend.elements.$languageSelector.prop('disabled', false); + }); + }; + + /** + * Gets the workspace infos + * + * @return {Promise} + * @protected + */ + Backend.getWorkspaceInfos = function() { + Workspaces.sendRemoteRequest( + Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) + ).done(function(response) { + Backend.renderWorkspaceInfos(response[0].result); + }); + }; + + /** + * Renders fetched workspace informations + * + * @param {Object} result + */ + Backend.renderWorkspaceInfos = function(result) { + Backend.elements.$tableBody.children().remove(); + Backend.allToggled = false; + Backend.elements.$chooseStageAction.prop('disabled', true); + Backend.elements.$chooseSelectionAction.prop('disabled', true); + Backend.elements.$chooseMassAction.prop('disabled', result.data.length === 0); + + Backend.buildPagination(result.total); + + for (var i = 0; i < result.data.length; ++i) { + var item = result.data[i], + $actions = $('<div />', {class: 'btn-group'}), + $integrityIcon = ''; + $actions.append( + Backend.getAction(item.Workspaces_CollectionChildren > 0 && item.Workspaces_CollectionCurrent !== '', 'expand', 'apps-pagetree-collapse').attr('title', TYPO3.lang['tooltip.expand']).attr('data-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]').attr('data-toggle', 'collapse'), + $('<button />', { + class: 'btn btn-default', + 'data-action': 'changes', + 'data-toggle': 'tooltip', + title: TYPO3.lang['tooltip.showChanges'] + }).append(Backend.getPreRenderedIcon('actions-document-info')), + Backend.getAction(item.allowedAction_swap && item.Workspaces_CollectionParent === '', 'swap', 'actions-version-swap-version').attr('title', TYPO3.lang['tooltip.swap']), + Backend.getAction(item.allowedAction_view, 'preview', 'actions-version-workspace-preview').attr('title', TYPO3.lang['tooltip.viewElementAction']), + $('<button />', { + class: 'btn btn-default', + 'data-action': 'open', + 'data-toggle': 'tooltip', + title: TYPO3.lang['tooltip.editElementAction'] + }).append(Backend.getPreRenderedIcon('actions-open')), + $('<button />', { + class: 'btn btn-default', + 'data-action': 'version', + 'data-toggle': 'tooltip', + title: TYPO3.lang['tooltip.openPage'] + }).append(Backend.getPreRenderedIcon('actions-version-page-open')), + Backend.getAction(item.allowedAction_delete, 'remove', 'actions-version-document-remove').attr('title', TYPO3.lang['tooltip.discardVersion']), + $('<label />', {class: 'btn btn-default btn-checkbox'}).append( + $('<input />', {type: 'checkbox'}), + $('<span />', {class: 't3-icon fa'}) + ) + ); + + if (item.integrity.messages !== '') { + $integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]); + $integrityIcon + .attr('data-toggle', 'tooltip') + .attr('data-placement', 'top') + .attr('data-html', true) + .attr('title', item.integrity.messages); + } + + if (Backend.latestPath !== item.path_Workspace) { + Backend.latestPath = item.path_Workspace; + Backend.elements.$tableBody.append( + $('<tr />').append( + $('<th />', {colspan: 6}).text(Backend.latestPath) + ) + ); + } + + var rowConfiguration = { + 'data-uid': item.uid, + 'data-pid': item.livepid, + 'data-t3ver_oid': item.t3ver_oid, + 'data-t3ver_wsid': item.t3ver_wsid, + 'data-table': item.table, + 'data-next-stage': item.value_nextStage, + 'data-prev-stage': item.value_prevStage, + 'data-stage': item.stage + }; + + if (item.Workspaces_CollectionParent !== '') { + rowConfiguration['data-collection'] = item.Workspaces_CollectionParent; + rowConfiguration['class'] = 'collapse'; + } + + Backend.elements.$tableBody.append( + $('<tr />', rowConfiguration).append( + $('<td />', { + class: 't3js-title-workspace', + style: item.Workspaces_CollectionLevel > 0 ? 'padding-left: ' + Backend.indentationPadding * item.Workspaces_CollectionLevel + 'px' : '' + }).html(item.icon_Workspace + ' ' + '<a href="#" data-action="changes"><span class="item-state-' + item.state_Workspace + '">' + item.label_Workspace + '</span></a>'), + $('<td />', {class: 't3js-title-live'}).html(item.icon_Live + ' ' + item.label_Live), + $('<td />').text(item.label_Stage), + $('<td />').html($integrityIcon), + $('<td />').html(item.language.icon), + $('<td />', {class: 'text-right nowrap'}).append($actions) + ) + ); + + Tooltip.initialize('[data-toggle="tooltip"]', { + delay: { + show: 500, + hide: 100 + }, + trigger: 'hover', + container: 'body' + }); + } + }; + + /** + * Renders the pagination + * + * @param {Number} totalItems + */ + Backend.buildPagination = function(totalItems) { + if (totalItems === 0) { + Backend.elements.$pagination.contents().remove(); + return; + } + + Backend.paging.totalItems = totalItems; + Backend.paging.totalPages = Math.ceil(totalItems / Backend.settings.limit); + + if (Backend.paging.totalPages === 1) { + // early abort if only one page is available + Backend.elements.$pagination.contents().remove(); + return; + } + + var $ul = $('<ul />', {class: 'pagination pagination-block'}), + liElements = [], + $controlFirstPage = $('<li />').append( + $('<a />', {'data-action': 'previous'}).append( + $('<span />', {class: 't3-icon fa fa-arrow-left'}) + ) + ), + $controlLastPage = $('<li />').append( + $('<a />', {'data-action': 'next'}).append( + $('<span />', {class: 't3-icon fa fa-arrow-right'}) + ) + ); + + if (Backend.paging.currentPage === 1) { + $controlFirstPage.disablePagingAction(); + } + + if (Backend.paging.currentPage === Backend.paging.totalPages) { + $controlLastPage.disablePagingAction(); + } + + for (var i = 1; i <= Backend.paging.totalPages; i++) { + var $li = $('<li />', {class: Backend.paging.currentPage === i ? 'active' : ''}); + $li.append( + $('<a />', {'data-action': 'page', 'data-page': i}).append( + $('<span />').text(i) + ) + ); + liElements.push($li); + } + + $ul.append($controlFirstPage, liElements, $controlLastPage); + Backend.elements.$pagination.html($ul); + }; + + /** + * View changes of a record + * + * @param {Event} e + */ + Backend.viewChanges = function(e) { + e.preventDefault(); + + var $tr = $(e.target).closest('tr'); + + Workspaces.sendRemoteRequest( + Workspaces.generateRemotePayload('getRowDetails', { + stage: $tr.data('stage'), + t3ver_oid: $tr.data('t3ver_oid'), + table: $tr.data('table'), + uid: $tr.data('uid') + }) + ).done(function(response) { + var item = response[0].result.data[0], + $content = $('<div />'), + $tabsNav = $('<ul />', {class: 'nav nav-tabs', role: 'tablist'}), + $tabsContent = $('<div />', {class: 'tab-content'}), + modalButtons = []; + + $content.append( + $('<p />').html(TYPO3.lang['path'].replace('{0}', item.path_Live)), + $('<p />').html(TYPO3.lang['current_step'].replace('{0}', item.label_Stage).replace('{1}', item.stage_position).replace('{2}', item.stage_count)) + ); + + if (item.diff.length > 0) { + $tabsNav.append( + $('<li />', {role: 'presentation'}).append( + $('<a />', { + href: '#workspace-changes', + 'aria-controls': 'workspace-changes', + role: 'tab', + 'data-toggle': 'tab' + }).text(TYPO3.lang['window.recordChanges.tabs.changeSummary']) + ) + ); + $tabsContent.append( + $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-changes'}).append( + $('<div />', {class: 'form-section'}).append( + Backend.generateDiffView(item.diff) + ) + ) + ); + } + + if (item.comments.length > 0) { + $tabsNav.append( + $('<li />', {role: 'presentation'}).append( + $('<a />', { + href: '#workspace-comments', + 'aria-controls': 'workspace-comments', + role: 'tab', + 'data-toggle': 'tab' + }).html(TYPO3.lang['window.recordChanges.tabs.comments'] + ' ').append( + $('<span />', {class: 'badge'}).text(item.comments.length) + ) + ) + ); + $tabsContent.append( + $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-comments'}).append( + $('<div />', {class: 'form-section'}).append( + Backend.generateCommentView(item.comments) + ) + ) + ); + } + + if (item.history.total > 0) { + $tabsNav.append( + $('<li />', {role: 'presentation'}).append( + $('<a />', { + href: '#workspace-history', + 'aria-controls': 'workspace-history', + role: 'tab', + 'data-toggle': 'tab' + }).text(TYPO3.lang['window.recordChanges.tabs.history']) + ) + ); + + $tabsContent.append( + $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-history'}).append( + $('<div />', {class: 'form-section'}).append( + Backend.generateHistoryView(item.history.data) + ) + ) + ); + } + + // Mark the first tab and pane as active + $tabsNav.find('li').first().addClass('active'); + $tabsContent.find('.tab-pane').first().addClass('active'); + + // Attach tabs + $content.append( + $('<div />').append( + $tabsNav, + $tabsContent + ) + ); + + if ($tr.data('stage') !== $tr.data('prevStage')) { + modalButtons.push({ + text: item.label_PrevStage.title, + active: true, + btnClass: 'btn-default', + name: 'prevstage', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + Backend.sendToStage($(e.target).closest('tr'), 'prev'); + } + }); + } + + modalButtons.push({ + text: item.label_NextStage.title, + active: true, + btnClass: 'btn-default', + name: 'nextstage', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + Backend.sendToStage($(e.target).closest('tr'), 'next'); + } + }); + modalButtons.push({ + text: TYPO3.lang['close'], + active: true, + btnClass: 'btn-info', + name: 'cancel', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }); + + Modal.show( + TYPO3.lang['window.recordInformation'].replace('{0}', $.trim($tr.find('.t3js-title-live').text())), + $content, + Severity.info, + modalButtons + ); + }); + }; + + /** + * Opens a record in a preview window + * + * @param {Event} e + */ + Backend.openPreview = function(e) { + var $tr = $(e.target).closest('tr'); + + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload('viewSingleRecord', [ + $tr.data('table'), $tr.data('uid') + ]) + ).done(function(response) { + eval(response[0].result); + }); + }; + + /** + * Renders the record's history + * + * @param {Object} data + */ + Backend.generateHistoryView = function(data) { + var $history = $('<div />'); + + for (var i = 0; i < data.length; ++i) { + var $panel = $('<div />', {class: 'panel panel-default'}), + $diff; + + if (typeof data[i].differences === 'object') { + if (data[i].differences.length === 0) { + // Somehow here are no differences. What a pity, skip that record + continue; + } + $diff = $('<div />', {class: 'diff'}); + + for (var j = 0; j < data[i].differences.length; ++j) { + $diff.append( + $('<div />', {class: 'diff-item'}).append( + $('<div />', {class: 'diff-item-title'}).text(data[i].differences[j].label), + $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(data[i].differences[j].html) + ) + ); + } + + $panel.append( + $('<div />').append($diff) + ); + } else { + $panel.append( + $('<div />', {class: 'panel-body'}).text(data[i].differences) + ); + } + $panel.append( + $('<div />', {class: 'panel-footer'}).append( + $('<span />', {class: 'label label-info'}).text(data[i].datetime) + ) + ); + + $history.append( + $('<div />', {class: 'media'}).append( + $('<div />', {class: 'media-left text-center'}).text(data[i].user).prepend( + $('<div />').html(data[i].user_avatar) + ), + $('<div />', {class: 'media-body'}).append($panel) + ) + ); + } + + return $history; + }; + + /** + * Shows a confirmation modal and deletes the selected record from workspace. + * + * @param {Event} e + */ + Backend.confirmDeleteRecordFromWorkspace = function(e) { + var $tr = $(e.target).closest('tr'); + var $modal = Modal.confirm( + TYPO3.lang['window.discard.title'], + TYPO3.lang['window.discard.message'], + Severity.warning, + [ + { + text: TYPO3.lang['cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + $modal.modal('hide'); + } + }, { + text: TYPO3.lang['ok'], + btnClass: 'btn-warning', + name: 'ok' + } + ] + ); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload('deleteSingleRecord', [ + $tr.data('table'), + $tr.data('uid') + ]) + ]).done(function() { + $modal.modal('hide'); + Backend.getWorkspaceInfos(); + Backend.refreshPageTree(); + }); + } + }); + }; + + /** + * Runs a mass action + */ + Backend.runSelectionAction = function() { + var selectedAction = Backend.elements.$chooseSelectionAction.val(), + integrityCheckRequired = selectedAction !== 'discard'; + + if (selectedAction.length === 0) { + // Don't do anything if that value is empty + return; + } + + var affectedRecords = []; + for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) { + var affected = Backend.markedRecordsForMassAction[i].split(':'); + affectedRecords.push({ + table: affected[0], + liveId: affected[2], + versionId: affected[1] + }); + } + + if (!integrityCheckRequired) { + Wizard.setup.forceSelection = false; + Backend.renderSelectionActionWizard(selectedAction, affectedRecords); + } else { + Workspaces.checkIntegrity( + { + selection: affectedRecords, + type: 'selection' + } + ).done(function(response) { + Wizard.setup.forceSelection = false; + if (response[0].result.result === 'warning') { + Backend.addIntegrityCheckWarningToWizard(); + } + Backend.renderSelectionActionWizard(selectedAction, affectedRecords); + }); + } + }; + + /** + * Adds a slide to the wizard concerning an integrity check warning. + */ + Backend.addIntegrityCheckWarningToWizard = function() { + Wizard.addSlide( + 'integrity-warning', + 'Warning', + TYPO3.lang['integrity.hasIssuesDescription'] + '<br>' + TYPO3.lang['integrity.hasIssuesQuestion'], + Severity.warning + ); + }; + + /** + * Renders the wizard for selection actions + * + * @param {String} selectedAction + * @param {Object} affectedRecords + */ + Backend.renderSelectionActionWizard = function(selectedAction, affectedRecords) { + Wizard.addSlide( + 'mass-action-confirmation', + TYPO3.lang['window.selectionAction.title'], + $('<p />').text(TYPO3.lang['tooltip.' + selectedAction + 'Selected']), + Severity.warning + ); + Wizard.addFinalProcessingSlide(function() { + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload('executeSelectionAction', { + action: selectedAction, + selection: affectedRecords + }) + ).done(function() { + Backend.getWorkspaceInfos(); + Wizard.dismiss(); + Backend.refreshPageTree(); + }); + }).done(function() { + Wizard.show(); + + Wizard.getComponent().on('wizard-dismissed', function() { + Backend.elements.$chooseSelectionAction.val(''); + }); + }); + }; + + /** + * Runs a mass action + */ + Backend.runMassAction = function() { + var selectedAction = Backend.elements.$chooseMassAction.val(), + integrityCheckRequired = selectedAction !== 'discard'; + + if (selectedAction.length === 0) { + // Don't do anything if that value is empty + return; + } + + if (!integrityCheckRequired) { + Wizard.setup.forceSelection = false; + Backend.renderMassActionWizard(selectedAction); + } else { + Workspaces.checkIntegrity( + { + language: Backend.settings.language, + type: selectedAction + } + ).done(function(response) { + Wizard.setup.forceSelection = false; + if (response[0].result.result === 'warning') { + Backend.addIntegrityCheckWarningToWizard(); + } + Backend.renderMassActionWizard(selectedAction); + }); + } + }; + + /** + * Renders the wizard for mass actions + * + * @param {String} selectedAction + */ + Backend.renderMassActionWizard = function(selectedAction) { + var massAction, + doSwap = false; + + switch (selectedAction) { + case 'publish': + massAction = 'publishWorkspace'; + break; + case 'swap': + massAction = 'publishWorkspace'; + doSwap = true; + break; + case 'discard': + massAction = 'flushWorkspace'; + break; + } + + if (massAction === null) { + throw 'Invalid mass action ' + selectedAction + ' called.'; + } + + Wizard.setup.forceSelection = false; + Wizard.addSlide( + 'mass-action-confirmation', + TYPO3.lang['window.massAction.title'], + $('<p />').html(TYPO3.lang['tooltip.' + selectedAction + 'All'] + '<br><br>' + TYPO3.lang['tooltip.affectWholeWorkspace']), + Severity.warning + ); + Wizard.addFinalProcessingSlide(function() { + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteMassActionsPayload(massAction, { + init: true, + total: 0, + processed: 0, + language: Backend.settings.language, + swap: doSwap + }) + ).done(function(response) { + var payload = response[0].result; + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteMassActionsPayload(massAction, payload) + ).done(function() { + Backend.getWorkspaceInfos(); + Wizard.dismiss(); + }); + }); + }).done(function() { + Wizard.show(); + + Wizard.getComponent().on('wizard-dismissed', function() { + Backend.elements.$chooseMassAction.val(''); + }); + }); + }; + + /** + * Sends marked records to a stage + * + * @param {Event} e + */ + Backend.sendToSpecificStageAction = function(e) { + var affectedRecords = [], + stage = $(e.currentTarget).val(); + for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) { + var affected = Backend.markedRecordsForMassAction[i].split(':'); + affectedRecords.push({ + table: affected[0], + uid: affected[1], + t3ver_oid: affected[2] + }); + } + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload('sendToSpecificStageWindow', [ + stage, affectedRecords + ]) + ).done(function(response) { + var $modal = Workspaces.renderSendToStageWindow(response); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + var $form = $(e.currentTarget).find('form'), + serializedForm = $form.serializeObject(); + + serializedForm.affects = { + elements: affectedRecords, + nextStage: stage + }; + + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload('sendToSpecificStageExecute', [serializedForm]), + Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings) + ]).done(function(response) { + $modal.modal('hide'); + Backend.renderWorkspaceInfos(response[1].result); + Backend.refreshPageTree(); + }); + } + }).on('modal-destroyed', function() { + Backend.elements.$chooseStageAction.val(''); + }); + }); + }; + + /** + * Reloads the page tree + */ + Backend.refreshPageTree = function() { + if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) { + top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } + }; + + /** + * Renders the action button based on the user's permission. + * + * @returns {$} + * @private + */ + Backend.getAction = function(condition, action, iconIdentifier) { + if (condition) { + return $('<button />', { + class: 'btn btn-default', + 'data-action': action, + 'data-toggle': 'tooltip' + }).append(Backend.getPreRenderedIcon(iconIdentifier)) + } + return $('<span />', {class: 'btn btn-default disabled'}).append(Backend.getPreRenderedIcon('empty-empty')); + }; + + /** + * Fetches and renders available preview links + */ + Backend.generatePreviewLinks = function() { + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload('generateWorkspacePreviewLinksForAllLanguages', [ + Backend.settings.id + ]) + ).done(function(response) { + var result = response[0].result, + $list = $('<dl />'); + + $.each(result, function(language, url) { + $list.append( + $('<dt />').text(language), + $('<dd />').append( + $('<a />', {href: url, target: '_blank'}).text(url) + ) + ); + }); + + Modal.show( + TYPO3.lang['previewLink'], + $list, + Severity.info, + [{ + text: TYPO3.lang['ok'], + active: true, + btnClass: 'btn-info', + name: 'ok', + trigger: function() { + Modal.currentModal.trigger('modal-dismiss'); + } + }], + ['modal-inner-scroll'] + ); + }); + }; + + /** + * Gets the pre-rendered icon + * This method is intended to be dropped once we use Fluid's StandaloneView. + * + * @param {String} identifier + * @returns {$} + */ + Backend.getPreRenderedIcon = function(identifier) { + return Backend.elements.$actionIcons.find('[data-identifier="' + identifier + '"]').clone(); + }; + + /** + * Serialize a form to a JavaScript object + * + * @see http://stackoverflow.com/a/1186309/4828813 + * @return {Object} + */ + $.fn.serializeObject = function() { + var o = {}; + var a = this.serializeArray(); + $.each(a, function() { + if (typeof o[this.name] !== 'undefined') { + if (!o[this.name].push) { + o[this.name] = [o[this.name]]; + } + o[this.name].push(this.value || ''); + } else { + o[this.name] = this.value || ''; + } + }); + return o; + }; + + /** + * Changes the markup of a pagination action being disabled + */ + $.fn.disablePagingAction = function() { + $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />')); + }; + + $(Backend.initialize); }); diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js index 78c2188d5cce450ed53ea304f084a4659bdcbf1d..8ceaa66ed96e82cfc337f82b838b9351f129979a 100644 --- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js +++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js @@ -16,290 +16,290 @@ * RequireJS module for workspace preview */ define([ - 'jquery', - 'TYPO3/CMS/Workspaces/Workspaces', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Modal', - 'twbs/bootstrap-slider' + 'jquery', + 'TYPO3/CMS/Workspaces/Workspaces', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Modal', + 'twbs/bootstrap-slider' ], function($, Workspaces, Severity, Modal) { - 'use strict'; - - var Preview = { - identifiers: { - topbar: '#typo3-topbar', - workspacePanel: '.workspace-panel', - liveView: '#live-view', - workspaceTabs: '.t3js-workspace-tabs [data-toggle="tab"]', - workspaceActions: '.t3js-workspace-actions', - stageSlider: '#workspace-stage-slider', - workspaceView: '#workspace-view', - workspaceList: '#workspace-list', - sendToStageAction: '[data-action="send-to-stage"]', - discardAction: '[data-action="discard"]', - stageButtonsContainer: '.t3js-stage-buttons', - previewModeContainer: '.t3js-preview-mode', - activePreviewMode: '.t3js-active-preview-mode', - workspacePreview: '.t3js-workspace-preview' - }, - currentSlidePosition: 100, - elements: {} // filled in Preview.getElements() - }; - - /** - * Initializes the preview module - */ - Preview.initialize = function() { - Preview.getElements(); - Preview.resizeViews(); - - Preview.adjustPreviewModeSelectorWidth(); - Preview.elements.$stageSlider.slider(); - - Preview.registerEvents(); - }; - - /** - * Fetches and stores often required elements - */ - Preview.getElements = function() { - Preview.elements.$liveView = $(Preview.identifiers.liveView); - Preview.elements.$workspacePanel = $(Preview.identifiers.workspacePanel); - Preview.elements.$workspaceTabs = $(Preview.identifiers.workspaceTabs); - Preview.elements.$workspaceActions = $(Preview.identifiers.workspaceActions); - Preview.elements.$stageSlider = $(Preview.identifiers.stageSlider); - Preview.elements.$workspaceView = $(Preview.identifiers.workspaceView); - Preview.elements.$workspaceList = $(Preview.identifiers.workspaceList); - Preview.elements.$stageButtonsContainer = $(Preview.identifiers.stageButtonsContainer); - Preview.elements.$previewModeContainer = $(Preview.identifiers.previewModeContainer); - Preview.elements.$activePreviewMode = $(Preview.identifiers.activePreviewMode); - Preview.elements.$workspacePreview = $(Preview.identifiers.workspacePreview); - }; - - /** - * Registers the events - */ - Preview.registerEvents = function() { - $(window).on('resize', function() { - Preview.resizeViews(); - }); - $(document) - .on('click', Preview.identifiers.discardAction, Preview.renderDiscardWindow) - .on('click', Preview.identifiers.sendToStageAction, Preview.renderSendPageToStageWindow) - ; - - Preview.elements.$workspaceTabs.on('show.bs.tab', function() { - Preview.elements.$workspaceActions.toggle($(this).data('actions')); - }); - Preview.elements.$stageSlider.on('change', Preview.updateSlidePosition); - Preview.elements.$previewModeContainer.find('[data-preview-mode]').on('click', Preview.changePreviewMode); - }; - - /** - * Renders the staging buttons - * - * @param {String} buttons - */ - Preview.renderStageButtons = function(buttons) { - Preview.elements.$stageButtonsContainer.html(buttons); - }; - - /** - * Calculate the available space based on the viewport height - * - * @returns {Number} - */ - Preview.getAvailableSpace = function() { - var $viewportHeight = $(window).height(), - $topbarHeight = $(Preview.identifiers.topbar).outerHeight(); - - return $viewportHeight - $topbarHeight; - }; - - /** - * Updates the position of the comparison slider - * - * @param {Event} e - */ - Preview.updateSlidePosition = function(e) { - Preview.currentSlidePosition = e.value.newValue; - Preview.resizeViews(); - }; - - /** - * Resize the views based on the current viewport height and slider position - */ - Preview.resizeViews = function() { - var availableSpace = Preview.getAvailableSpace(), - relativeHeightOfLiveView = (Preview.currentSlidePosition - 100) * -1, - absoluteHeightOfLiveView = Math.round(Math.abs(availableSpace * relativeHeightOfLiveView / 100)), - outerHeightDifference = Preview.elements.$liveView.outerHeight() - Preview.elements.$liveView.height(); - - Preview.elements.$workspacePreview.height(availableSpace); - - if (Preview.elements.$activePreviewMode.data('activePreviewMode') === 'slider') { - Preview.elements.$liveView.height(absoluteHeightOfLiveView - outerHeightDifference); - } - Preview.elements.$workspaceList.height(availableSpace); - }; - - /** - * Renders the discard window - * - * @private - */ - Preview.renderDiscardWindow = function() { - var $modal = Modal.confirm( - TYPO3.lang['window.discardAll.title'], - TYPO3.lang['window.discardAll.message'], - Severity.warning, - [ - { - text: TYPO3.lang['cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function() { - $modal.modal('hide'); - } - }, { - text: TYPO3.lang['ok'], - btnClass: 'btn-warning', - name: 'ok' - } - ] - ); - $modal.on('button.clicked', function(e) { - if (e.target.name === 'ok') { - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload('discardStagesFromPage', [TYPO3.settings.Workspaces.id]), - Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id]) - ]).done(function(response) { - $modal.modal('hide'); - Preview.renderStageButtons(response[1].result); - // Reloading live view and and workspace list view IFRAME - Preview.elements.$workspaceView.attr('src', Preview.elements.$workspaceView.attr('src')); - Preview.elements.$workspaceList.attr('src', Preview.elements.$workspaceList.attr('src')); - }); - } - }); - }; - - /** - * Adjusts the width of the preview mode selector to avoid jumping around due to different widths of the labels - */ - Preview.adjustPreviewModeSelectorWidth = function() { - var $btnGroup = Preview.elements.$previewModeContainer.find('.btn-group'), - maximumWidth = 0; - - $btnGroup.addClass('open'); - Preview.elements.$previewModeContainer.find('li > a > span').each(function(_, el) { - var width = $(el).width(); - if (maximumWidth < width) { - maximumWidth = width; - } - }); - $btnGroup.removeClass('open'); - Preview.elements.$activePreviewMode.width(maximumWidth); - }; - - /** - * Renders the "send page to stage" window - * - * @private - */ - Preview.renderSendPageToStageWindow = function() { - var $me = $(this), - direction = $me.data('direction'), - actionName; - - if (direction === 'prev') { - actionName = 'sendPageToPreviousStage'; - } else if (direction === 'next') { - actionName = 'sendPageToNextStage'; - } else { - throw 'Invalid direction ' + direction + ' requested.'; - } - - Workspaces.sendRemoteRequest( - Workspaces.generateRemoteActionsPayload(actionName, [TYPO3.settings.Workspaces.id]) - ).done(function(response) { - var $modal = Workspaces.renderSendToStageWindow(response); - $modal.on('button.clicked', function (e) { - if (e.target.name === 'ok') { - var $form = $(e.currentTarget).find('form'), - serializedForm = $form.serializeObject(); - - serializedForm.affects = response[0].result.affects; - serializedForm.stageId = $me.data('stageId'); - - Workspaces.sendRemoteRequest([ - Workspaces.generateRemoteActionsPayload('sentCollectionToStage', [serializedForm]), - Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id]) - ]).done(function(response) { - $modal.modal('hide'); - - Preview.renderStageButtons(response[1].result); - }); - } - }); - }); - }; - - /** - * Changes the preview mode - * - * @param {Event} e - */ - Preview.changePreviewMode = function(e) { - e.preventDefault(); - - var $trigger = $(this), - currentPreviewMode = Preview.elements.$activePreviewMode.data('activePreviewMode'), - newPreviewMode = $trigger.data('previewMode'); - - Preview.elements.$activePreviewMode.text($trigger.text()).data('activePreviewMode', newPreviewMode); - Preview.elements.$workspacePreview.parent() - .removeClass('preview-mode-' + currentPreviewMode) - .addClass('preview-mode-' + newPreviewMode); - - if (newPreviewMode === 'slider') { - Preview.elements.$stageSlider.parent().toggle(true); - Preview.resizeViews(); - } else { - Preview.elements.$stageSlider.parent().toggle(false); - - if (newPreviewMode === 'vbox') { - Preview.elements.$liveView.height('100%'); - } else { - Preview.elements.$liveView.height('50%'); - } - } - - }; - - /** - * Serialize a form to a JavaScript object - * - * @see http://stackoverflow.com/a/1186309/4828813 - * @return {Object} - */ - $.fn.serializeObject = function() { - var o = {}; - var a = this.serializeArray(); - $.each(a, function() { - if (typeof o[this.name] !== 'undefined') { - if (!o[this.name].push) { - o[this.name] = [o[this.name]]; - } - o[this.name].push(this.value || ''); - } else { - o[this.name] = this.value || ''; - } - }); - return o; - }; - - $(document).ready(function() { - Preview.initialize(); - }); + 'use strict'; + + var Preview = { + identifiers: { + topbar: '#typo3-topbar', + workspacePanel: '.workspace-panel', + liveView: '#live-view', + workspaceTabs: '.t3js-workspace-tabs [data-toggle="tab"]', + workspaceActions: '.t3js-workspace-actions', + stageSlider: '#workspace-stage-slider', + workspaceView: '#workspace-view', + workspaceList: '#workspace-list', + sendToStageAction: '[data-action="send-to-stage"]', + discardAction: '[data-action="discard"]', + stageButtonsContainer: '.t3js-stage-buttons', + previewModeContainer: '.t3js-preview-mode', + activePreviewMode: '.t3js-active-preview-mode', + workspacePreview: '.t3js-workspace-preview' + }, + currentSlidePosition: 100, + elements: {} // filled in Preview.getElements() + }; + + /** + * Initializes the preview module + */ + Preview.initialize = function() { + Preview.getElements(); + Preview.resizeViews(); + + Preview.adjustPreviewModeSelectorWidth(); + Preview.elements.$stageSlider.slider(); + + Preview.registerEvents(); + }; + + /** + * Fetches and stores often required elements + */ + Preview.getElements = function() { + Preview.elements.$liveView = $(Preview.identifiers.liveView); + Preview.elements.$workspacePanel = $(Preview.identifiers.workspacePanel); + Preview.elements.$workspaceTabs = $(Preview.identifiers.workspaceTabs); + Preview.elements.$workspaceActions = $(Preview.identifiers.workspaceActions); + Preview.elements.$stageSlider = $(Preview.identifiers.stageSlider); + Preview.elements.$workspaceView = $(Preview.identifiers.workspaceView); + Preview.elements.$workspaceList = $(Preview.identifiers.workspaceList); + Preview.elements.$stageButtonsContainer = $(Preview.identifiers.stageButtonsContainer); + Preview.elements.$previewModeContainer = $(Preview.identifiers.previewModeContainer); + Preview.elements.$activePreviewMode = $(Preview.identifiers.activePreviewMode); + Preview.elements.$workspacePreview = $(Preview.identifiers.workspacePreview); + }; + + /** + * Registers the events + */ + Preview.registerEvents = function() { + $(window).on('resize', function() { + Preview.resizeViews(); + }); + $(document) + .on('click', Preview.identifiers.discardAction, Preview.renderDiscardWindow) + .on('click', Preview.identifiers.sendToStageAction, Preview.renderSendPageToStageWindow) + ; + + Preview.elements.$workspaceTabs.on('show.bs.tab', function() { + Preview.elements.$workspaceActions.toggle($(this).data('actions')); + }); + Preview.elements.$stageSlider.on('change', Preview.updateSlidePosition); + Preview.elements.$previewModeContainer.find('[data-preview-mode]').on('click', Preview.changePreviewMode); + }; + + /** + * Renders the staging buttons + * + * @param {String} buttons + */ + Preview.renderStageButtons = function(buttons) { + Preview.elements.$stageButtonsContainer.html(buttons); + }; + + /** + * Calculate the available space based on the viewport height + * + * @returns {Number} + */ + Preview.getAvailableSpace = function() { + var $viewportHeight = $(window).height(), + $topbarHeight = $(Preview.identifiers.topbar).outerHeight(); + + return $viewportHeight - $topbarHeight; + }; + + /** + * Updates the position of the comparison slider + * + * @param {Event} e + */ + Preview.updateSlidePosition = function(e) { + Preview.currentSlidePosition = e.value.newValue; + Preview.resizeViews(); + }; + + /** + * Resize the views based on the current viewport height and slider position + */ + Preview.resizeViews = function() { + var availableSpace = Preview.getAvailableSpace(), + relativeHeightOfLiveView = (Preview.currentSlidePosition - 100) * -1, + absoluteHeightOfLiveView = Math.round(Math.abs(availableSpace * relativeHeightOfLiveView / 100)), + outerHeightDifference = Preview.elements.$liveView.outerHeight() - Preview.elements.$liveView.height(); + + Preview.elements.$workspacePreview.height(availableSpace); + + if (Preview.elements.$activePreviewMode.data('activePreviewMode') === 'slider') { + Preview.elements.$liveView.height(absoluteHeightOfLiveView - outerHeightDifference); + } + Preview.elements.$workspaceList.height(availableSpace); + }; + + /** + * Renders the discard window + * + * @private + */ + Preview.renderDiscardWindow = function() { + var $modal = Modal.confirm( + TYPO3.lang['window.discardAll.title'], + TYPO3.lang['window.discardAll.message'], + Severity.warning, + [ + { + text: TYPO3.lang['cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + $modal.modal('hide'); + } + }, { + text: TYPO3.lang['ok'], + btnClass: 'btn-warning', + name: 'ok' + } + ] + ); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload('discardStagesFromPage', [TYPO3.settings.Workspaces.id]), + Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id]) + ]).done(function(response) { + $modal.modal('hide'); + Preview.renderStageButtons(response[1].result); + // Reloading live view and and workspace list view IFRAME + Preview.elements.$workspaceView.attr('src', Preview.elements.$workspaceView.attr('src')); + Preview.elements.$workspaceList.attr('src', Preview.elements.$workspaceList.attr('src')); + }); + } + }); + }; + + /** + * Adjusts the width of the preview mode selector to avoid jumping around due to different widths of the labels + */ + Preview.adjustPreviewModeSelectorWidth = function() { + var $btnGroup = Preview.elements.$previewModeContainer.find('.btn-group'), + maximumWidth = 0; + + $btnGroup.addClass('open'); + Preview.elements.$previewModeContainer.find('li > a > span').each(function(_, el) { + var width = $(el).width(); + if (maximumWidth < width) { + maximumWidth = width; + } + }); + $btnGroup.removeClass('open'); + Preview.elements.$activePreviewMode.width(maximumWidth); + }; + + /** + * Renders the "send page to stage" window + * + * @private + */ + Preview.renderSendPageToStageWindow = function() { + var $me = $(this), + direction = $me.data('direction'), + actionName; + + if (direction === 'prev') { + actionName = 'sendPageToPreviousStage'; + } else if (direction === 'next') { + actionName = 'sendPageToNextStage'; + } else { + throw 'Invalid direction ' + direction + ' requested.'; + } + + Workspaces.sendRemoteRequest( + Workspaces.generateRemoteActionsPayload(actionName, [TYPO3.settings.Workspaces.id]) + ).done(function(response) { + var $modal = Workspaces.renderSendToStageWindow(response); + $modal.on('button.clicked', function(e) { + if (e.target.name === 'ok') { + var $form = $(e.currentTarget).find('form'), + serializedForm = $form.serializeObject(); + + serializedForm.affects = response[0].result.affects; + serializedForm.stageId = $me.data('stageId'); + + Workspaces.sendRemoteRequest([ + Workspaces.generateRemoteActionsPayload('sentCollectionToStage', [serializedForm]), + Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id]) + ]).done(function(response) { + $modal.modal('hide'); + + Preview.renderStageButtons(response[1].result); + }); + } + }); + }); + }; + + /** + * Changes the preview mode + * + * @param {Event} e + */ + Preview.changePreviewMode = function(e) { + e.preventDefault(); + + var $trigger = $(this), + currentPreviewMode = Preview.elements.$activePreviewMode.data('activePreviewMode'), + newPreviewMode = $trigger.data('previewMode'); + + Preview.elements.$activePreviewMode.text($trigger.text()).data('activePreviewMode', newPreviewMode); + Preview.elements.$workspacePreview.parent() + .removeClass('preview-mode-' + currentPreviewMode) + .addClass('preview-mode-' + newPreviewMode); + + if (newPreviewMode === 'slider') { + Preview.elements.$stageSlider.parent().toggle(true); + Preview.resizeViews(); + } else { + Preview.elements.$stageSlider.parent().toggle(false); + + if (newPreviewMode === 'vbox') { + Preview.elements.$liveView.height('100%'); + } else { + Preview.elements.$liveView.height('50%'); + } + } + + }; + + /** + * Serialize a form to a JavaScript object + * + * @see http://stackoverflow.com/a/1186309/4828813 + * @return {Object} + */ + $.fn.serializeObject = function() { + var o = {}; + var a = this.serializeArray(); + $.each(a, function() { + if (typeof o[this.name] !== 'undefined') { + if (!o[this.name].push) { + o[this.name] = [o[this.name]]; + } + o[this.name].push(this.value || ''); + } else { + o[this.name] = this.value || ''; + } + }); + return o; + }; + + $(document).ready(function() { + Preview.initialize(); + }); }); diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js index c73d780a59469b67459037180a1f70faae1f2cbd..11d7380a420d71579898fa4140a0dd6ea7f2a404 100644 --- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js +++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js @@ -17,156 +17,156 @@ * and jump to the workspaces module */ define(['jquery', 'TYPO3/CMS/Backend/Viewport'], function($, Viewport) { - 'use strict'; - - /** - * - * @type {{options: {containerSelector: string, menuItemSelector: string, activeMenuItemSelector: string, toolbarItemSelector: string, workspaceBodyClass: string, workspacesTitleInToolbarClass: string, workspaceModuleLinkSelector: string}}} - * @exports TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu - */ - var WorkspacesMenu = { - options: { - containerSelector: '#typo3-cms-workspaces-backend-toolbaritems-workspaceselectortoolbaritem', - menuItemSelector: '.t3js-workspaces-switchlink', - activeMenuItemSelector: '.dropdown-menu .selected', - toolbarItemSelector: '.dropdown-toggle', - workspaceBodyClass: 'typo3-in-workspace', // attached to <body> when in a workspace - workspacesTitleInToolbarClass: 'toolbar-item-name', - workspaceModuleLinkSelector: '.t3js-workspaces-modulelink' - } - }; - - /** - * registers event listeners - */ - WorkspacesMenu.initializeEvents = function() { - - // link to the module - $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.workspaceModuleLinkSelector, function(evt) { - evt.preventDefault(); - top.goToModule($(this).data('module')); - }); - - // observe all clicks on workspace links in the menu - $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.menuItemSelector, function(evt) { - evt.preventDefault(); - WorkspacesMenu.switchWorkspace($(this).data('workspaceid')); - }); - }; - - /** - * switches the workspace via AJAX (which returns the new data, as JSON), - * then reloads the module menu, and the content frame - * - * @param {String} workspaceId - */ - WorkspacesMenu.switchWorkspace = function(workspaceId) { - $.ajax({ - url: TYPO3.settings.ajaxUrls['workspace_switch'], - type: 'post', - data: { - workspaceId: workspaceId, - pageId: fsMod.recentIds['web'] - }, - success: function(response) { - if (!response.workspaceId) { - response.workspaceId = 0; - } - - WorkspacesMenu.performWorkspaceSwitch(response.workspaceId, response.title); - - // append the returned page ID to the current module URL - if (response.pageId) { - fsMod.recentIds['web'] = response.pageId; - var url = TYPO3.Backend.ContentContainer.getUrl(); - url += (url.indexOf('?') == -1 ? '?' : '&') + '&id=' + response.pageId; - if (TYPO3.Backend.NavigationContainer.PageTree) { - TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - TYPO3.Backend.ContentContainer.setUrl(url); - - // when in web module reload, otherwise send the user to the web module - } else if (currentModuleLoaded.indexOf('web_') === 0) { - if (TYPO3.Backend.NavigationContainer.PageTree) { - TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); - } - TYPO3.ModuleMenu.App.reloadFrames(); - } else if (TYPO3.configuration.pageModule) { - TYPO3.ModuleMenu.App.showModule(TYPO3.configuration.pageModule); - } - - // reload the module menu - TYPO3.ModuleMenu.App.refreshMenu(); - } - }); - }; - - /** - * changes the data in the module menu and the updates the backend context - * - * @param {String} id the workspace ID - * @param {String} title the workspace title - */ - WorkspacesMenu.performWorkspaceSwitch = function(id, title) { - top.TYPO3.Backend.workspaceTitle = title; - top.TYPO3.configuration.inWorkspace = id !== 0; - - WorkspacesMenu.updateBackendContext(title); - - // first remove all checks, then set the check in front of the selected workspace - var stateActiveClass = 'fa fa-check'; - var stateInactiveClass = 'fa fa-empty-empty'; - - // remove "selected" class and checkmark - $(WorkspacesMenu.options.activeMenuItemSelector + ' i', WorkspacesMenu.options.containerSelector).removeClass(stateActiveClass).addClass(stateInactiveClass); - $(WorkspacesMenu.options.activeMenuItemSelector, WorkspacesMenu.options.containerSelector).removeClass('selected'); - - // add "selected" class and checkmark - var $activeElement = $(WorkspacesMenu.options.menuItemSelector + '[data-workspaceid=' + id + ']', WorkspacesMenu.options.containerSelector); - $activeElement.parent().parent().find('i').removeClass(stateInactiveClass).addClass(stateActiveClass); - $activeElement.parent().parent().addClass('selected'); - }; - - /** - * checks if the TYPO3 backend is within a backend context and adds a class - * also updates the workspaces title - * - * @param {String} title - */ - WorkspacesMenu.updateBackendContext = function(title) { - - if (TYPO3.configuration.inWorkspace) { - $('body').addClass(WorkspacesMenu.options.workspaceBodyClass); - WorkspacesMenu.updateTopBar(title || TYPO3.lang['Workspaces.workspaceTitle']); - } else { - $('body').removeClass(WorkspacesMenu.options.workspaceBodyClass); - WorkspacesMenu.updateTopBar(); - } - }; - - /** - * adds the workspace title to the toolbar next to the username - * - * @param {String} workspaceTitle - */ - WorkspacesMenu.updateTopBar = function(workspaceTitle) { - $('.' + WorkspacesMenu.options.workspacesTitleInToolbarClass, WorkspacesMenu.options.containerSelector).remove(); - - if (workspaceTitle && workspaceTitle.length) { - var title = $('<span>', { - 'class': WorkspacesMenu.options.workspacesTitleInToolbarClass - }).text(workspaceTitle); - $(WorkspacesMenu.options.toolbarItemSelector, WorkspacesMenu.options.containerSelector).append(title); - } - }; - - Viewport.Topbar.Toolbar.registerEvent(function() { - WorkspacesMenu.initializeEvents(); - WorkspacesMenu.updateBackendContext(); - }); - - // expose the module in a global object - TYPO3.WorkspacesMenu = WorkspacesMenu; - - return WorkspacesMenu; + 'use strict'; + + /** + * + * @type {{options: {containerSelector: string, menuItemSelector: string, activeMenuItemSelector: string, toolbarItemSelector: string, workspaceBodyClass: string, workspacesTitleInToolbarClass: string, workspaceModuleLinkSelector: string}}} + * @exports TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu + */ + var WorkspacesMenu = { + options: { + containerSelector: '#typo3-cms-workspaces-backend-toolbaritems-workspaceselectortoolbaritem', + menuItemSelector: '.t3js-workspaces-switchlink', + activeMenuItemSelector: '.dropdown-menu .selected', + toolbarItemSelector: '.dropdown-toggle', + workspaceBodyClass: 'typo3-in-workspace', // attached to <body> when in a workspace + workspacesTitleInToolbarClass: 'toolbar-item-name', + workspaceModuleLinkSelector: '.t3js-workspaces-modulelink' + } + }; + + /** + * registers event listeners + */ + WorkspacesMenu.initializeEvents = function() { + + // link to the module + $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.workspaceModuleLinkSelector, function(evt) { + evt.preventDefault(); + top.goToModule($(this).data('module')); + }); + + // observe all clicks on workspace links in the menu + $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.menuItemSelector, function(evt) { + evt.preventDefault(); + WorkspacesMenu.switchWorkspace($(this).data('workspaceid')); + }); + }; + + /** + * switches the workspace via AJAX (which returns the new data, as JSON), + * then reloads the module menu, and the content frame + * + * @param {String} workspaceId + */ + WorkspacesMenu.switchWorkspace = function(workspaceId) { + $.ajax({ + url: TYPO3.settings.ajaxUrls['workspace_switch'], + type: 'post', + data: { + workspaceId: workspaceId, + pageId: fsMod.recentIds['web'] + }, + success: function(response) { + if (!response.workspaceId) { + response.workspaceId = 0; + } + + WorkspacesMenu.performWorkspaceSwitch(response.workspaceId, response.title); + + // append the returned page ID to the current module URL + if (response.pageId) { + fsMod.recentIds['web'] = response.pageId; + var url = TYPO3.Backend.ContentContainer.getUrl(); + url += (url.indexOf('?') == -1 ? '?' : '&') + '&id=' + response.pageId; + if (TYPO3.Backend.NavigationContainer.PageTree) { + TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } + TYPO3.Backend.ContentContainer.setUrl(url); + + // when in web module reload, otherwise send the user to the web module + } else if (currentModuleLoaded.indexOf('web_') === 0) { + if (TYPO3.Backend.NavigationContainer.PageTree) { + TYPO3.Backend.NavigationContainer.PageTree.refreshTree(); + } + TYPO3.ModuleMenu.App.reloadFrames(); + } else if (TYPO3.configuration.pageModule) { + TYPO3.ModuleMenu.App.showModule(TYPO3.configuration.pageModule); + } + + // reload the module menu + TYPO3.ModuleMenu.App.refreshMenu(); + } + }); + }; + + /** + * changes the data in the module menu and the updates the backend context + * + * @param {String} id the workspace ID + * @param {String} title the workspace title + */ + WorkspacesMenu.performWorkspaceSwitch = function(id, title) { + top.TYPO3.Backend.workspaceTitle = title; + top.TYPO3.configuration.inWorkspace = id !== 0; + + WorkspacesMenu.updateBackendContext(title); + + // first remove all checks, then set the check in front of the selected workspace + var stateActiveClass = 'fa fa-check'; + var stateInactiveClass = 'fa fa-empty-empty'; + + // remove "selected" class and checkmark + $(WorkspacesMenu.options.activeMenuItemSelector + ' i', WorkspacesMenu.options.containerSelector).removeClass(stateActiveClass).addClass(stateInactiveClass); + $(WorkspacesMenu.options.activeMenuItemSelector, WorkspacesMenu.options.containerSelector).removeClass('selected'); + + // add "selected" class and checkmark + var $activeElement = $(WorkspacesMenu.options.menuItemSelector + '[data-workspaceid=' + id + ']', WorkspacesMenu.options.containerSelector); + $activeElement.parent().parent().find('i').removeClass(stateInactiveClass).addClass(stateActiveClass); + $activeElement.parent().parent().addClass('selected'); + }; + + /** + * checks if the TYPO3 backend is within a backend context and adds a class + * also updates the workspaces title + * + * @param {String} title + */ + WorkspacesMenu.updateBackendContext = function(title) { + + if (TYPO3.configuration.inWorkspace) { + $('body').addClass(WorkspacesMenu.options.workspaceBodyClass); + WorkspacesMenu.updateTopBar(title || TYPO3.lang['Workspaces.workspaceTitle']); + } else { + $('body').removeClass(WorkspacesMenu.options.workspaceBodyClass); + WorkspacesMenu.updateTopBar(); + } + }; + + /** + * adds the workspace title to the toolbar next to the username + * + * @param {String} workspaceTitle + */ + WorkspacesMenu.updateTopBar = function(workspaceTitle) { + $('.' + WorkspacesMenu.options.workspacesTitleInToolbarClass, WorkspacesMenu.options.containerSelector).remove(); + + if (workspaceTitle && workspaceTitle.length) { + var title = $('<span>', { + 'class': WorkspacesMenu.options.workspacesTitleInToolbarClass + }).text(workspaceTitle); + $(WorkspacesMenu.options.toolbarItemSelector, WorkspacesMenu.options.containerSelector).append(title); + } + }; + + Viewport.Topbar.Toolbar.registerEvent(function() { + WorkspacesMenu.initializeEvents(); + WorkspacesMenu.updateBackendContext(); + }); + + // expose the module in a global object + TYPO3.WorkspacesMenu = WorkspacesMenu; + + return WorkspacesMenu; }); diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js index 52f50e95e7d614acae04e8f547b46aae234bec91..adcf2d3301ac7b3c0689ae03fb18bda95e54b8ce 100644 --- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js +++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js @@ -16,201 +16,220 @@ * RequireJS module for Workspaces */ define([ - 'jquery', - 'TYPO3/CMS/Backend/Severity', - 'TYPO3/CMS/Backend/Modal' + 'jquery', + 'TYPO3/CMS/Backend/Severity', + 'TYPO3/CMS/Backend/Modal' ], function($, Severity, Modal) { - 'use strict'; - - var Workspaces = { - tid: 0 - }; - - /** - * Renders the send to stage window - * @param {Object} response - * @return {$} - */ - Workspaces.renderSendToStageWindow = function(response) { - var result = response[0].result, - $form = $('<form />'); - - if (typeof result.sendMailTo !== 'undefined' && result.sendMailTo.length > 0) { - $form.append( - $('<label />', {class: 'control-label'}).text(TYPO3.lang['window.sendToNextStageWindow.itemsWillBeSentTo']) - ); - - for (var i = 0; i < result.sendMailTo.length; ++i) { - var recipient = result.sendMailTo[i]; - - $form.append( - $('<div />', {class: 'checkbox'}).append( - $('<label />').text(recipient.label).prepend( - $('<input />', {type: 'checkbox', name: 'recipients', id: recipient.name, value: recipient.value}).prop('checked', recipient.checked).prop('disabled', recipient.disabled) - ) - ) - ); - } - } - - if (typeof result.additional !== 'undefined') { - $form.append( - $('<div />', {class: 'form-group'}).append( - $('<label />', {class: 'control-label', 'for': 'additional'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients']), - $('<textarea />', {class: 'form-control', name: 'additional', id: 'additional'}).text(result.additional.value), - $('<span />', {class: 'help-block'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients.hint']) - ) - ); - } - - $form.append( - $('<div />', {class: 'form-group'}).append( - $('<label />', {class: 'control-label', 'for': 'comments'}).text(TYPO3.lang['window.sendToNextStageWindow.comments']), - $('<textarea />', {class: 'form-control', name: 'comments', id: 'comments'}).text(result.comments.value) - ) - ); - - var $modal = Modal.show( - TYPO3.lang['actionSendToStage'], - $form, - Severity.info, - [ - { - text: TYPO3.lang['cancel'], - active: true, - btnClass: 'btn-default', - name: 'cancel', - trigger: function() { - $modal.modal('hide'); - } - }, { - text: TYPO3.lang['ok'], - btnClass: 'btn-info', - name: 'ok' - } - ] - ); - - return $modal; - }; - - /** - * Checks the integrity of a record - * - * @param {Array} payload - * @return {$} - */ - Workspaces.checkIntegrity = function(payload) { - return Workspaces.sendRemoteRequest( - Workspaces.generateRemotePayload('checkIntegrity', payload) - ); - }; - - /** - * Sends an AJAX request - * - * @param {Object} payload - * @return {$} - */ - Workspaces.sendRemoteRequest = function(payload) { - return $.ajax({ - url: TYPO3.settings.ajaxUrls['workspace_dispatch'], - method: 'POST', - contentType: 'application/json; charset=utf-8', - dataType: 'json', - data: JSON.stringify(payload) - }); - }; - - /** - * Generates the payload for a remote call - * - * @param {String} method - * @param {Object} data - * @return {{action, data, method, type}} - */ - Workspaces.generateRemotePayload = function(method, data) { - if (typeof data === 'undefined') { - data = {}; - } - return Workspaces.generateRemotePayloadBody('RemoteServer', method, data); - }; - - /** - * Generates the payload for MassActions - * - * @param {String} method - * @param {Object} data - * @return {{action, data, method, type}} - */ - Workspaces.generateRemoteMassActionsPayload = function(method, data) { - if (typeof data === 'undefined') { - data = {}; - } - return Workspaces.generateRemotePayloadBody('MassActions', method, data); - }; - - /** - * Generates the payload for Actions - * - * @param {String} method - * @param {Object} data - * @return {{action, data, method, type}} - */ - Workspaces.generateRemoteActionsPayload = function(method, data) { - if (typeof data === 'undefined') { - data = []; - } - return Workspaces.generateRemotePayloadBody('Actions', method, data); - }; - - /** - * Generates the payload body - * - * @param {String} action - * @param {String} method - * @param {Object} data - * @return {{action: String, data: Object, method: String, type: string}} - */ - Workspaces.generateRemotePayloadBody = function(action, method, data) { - if (data instanceof Array) { - data.push(TYPO3.settings.Workspaces.token); - } else { - data = [ - data, - TYPO3.settings.Workspaces.token - ]; - } - return { - action: action, - data: data, - method: method, - type: 'rpc', - tid: Workspaces.tid++ - }; - }; - - /** - * Serialize a form to a JavaScript object - * - * @see http://stackoverflow.com/a/1186309/4828813 - * @return {Object} - */ - $.fn.serializeObject = function() { - var o = {}; - var a = this.serializeArray(); - $.each(a, function() { - if (typeof o[this.name] !== 'undefined') { - if (!o[this.name].push) { - o[this.name] = [o[this.name]]; - } - o[this.name].push(this.value || ''); - } else { - o[this.name] = this.value || ''; - } - }); - return o; - }; - - return Workspaces; + 'use strict'; + + var Workspaces = { + tid: 0 + }; + + /** + * Renders the send to stage window + * @param {Object} response + * @return {$} + */ + Workspaces.renderSendToStageWindow = function(response) { + var result = response[0].result, + $form = $('<form />'); + + if (typeof result.sendMailTo !== 'undefined' && result.sendMailTo.length > 0) { + $form.append( + $('<label />', {class: 'control-label'}).text(TYPO3.lang['window.sendToNextStageWindow.itemsWillBeSentTo']) + ); + + for (var i = 0; i < result.sendMailTo.length; ++i) { + var recipient = result.sendMailTo[i]; + + $form.append( + $('<div />', {class: 'checkbox'}).append( + $('<label />').text(recipient.label).prepend( + $('<input />', { + type: 'checkbox', + name: 'recipients', + id: recipient.name, + value: recipient.value + }).prop('checked', recipient.checked).prop('disabled', recipient.disabled) + ) + ) + ); + } + } + + if (typeof result.additional !== 'undefined') { + $form.append( + $('<div />', {class: 'form-group'}).append( + $('<label />', { + class: 'control-label', + 'for': 'additional' + }).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients']), + $('<textarea />', { + class: 'form-control', + name: 'additional', + id: 'additional' + }).text(result.additional.value), + $('<span />', {class: 'help-block'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients.hint']) + ) + ); + } + + $form.append( + $('<div />', {class: 'form-group'}).append( + $('<label />', { + class: 'control-label', + 'for': 'comments' + }).text(TYPO3.lang['window.sendToNextStageWindow.comments']), + $('<textarea />', { + class: 'form-control', + name: 'comments', + id: 'comments' + }).text(result.comments.value) + ) + ); + + var $modal = Modal.show( + TYPO3.lang['actionSendToStage'], + $form, + Severity.info, + [ + { + text: TYPO3.lang['cancel'], + active: true, + btnClass: 'btn-default', + name: 'cancel', + trigger: function() { + $modal.modal('hide'); + } + }, { + text: TYPO3.lang['ok'], + btnClass: 'btn-info', + name: 'ok' + } + ] + ); + + return $modal; + }; + + /** + * Checks the integrity of a record + * + * @param {Array} payload + * @return {$} + */ + Workspaces.checkIntegrity = function(payload) { + return Workspaces.sendRemoteRequest( + Workspaces.generateRemotePayload('checkIntegrity', payload) + ); + }; + + /** + * Sends an AJAX request + * + * @param {Object} payload + * @return {$} + */ + Workspaces.sendRemoteRequest = function(payload) { + return $.ajax({ + url: TYPO3.settings.ajaxUrls['workspace_dispatch'], + method: 'POST', + contentType: 'application/json; charset=utf-8', + dataType: 'json', + data: JSON.stringify(payload) + }); + }; + + /** + * Generates the payload for a remote call + * + * @param {String} method + * @param {Object} data + * @return {{action, data, method, type}} + */ + Workspaces.generateRemotePayload = function(method, data) { + if (typeof data === 'undefined') { + data = {}; + } + return Workspaces.generateRemotePayloadBody('RemoteServer', method, data); + }; + + /** + * Generates the payload for MassActions + * + * @param {String} method + * @param {Object} data + * @return {{action, data, method, type}} + */ + Workspaces.generateRemoteMassActionsPayload = function(method, data) { + if (typeof data === 'undefined') { + data = {}; + } + return Workspaces.generateRemotePayloadBody('MassActions', method, data); + }; + + /** + * Generates the payload for Actions + * + * @param {String} method + * @param {Object} data + * @return {{action, data, method, type}} + */ + Workspaces.generateRemoteActionsPayload = function(method, data) { + if (typeof data === 'undefined') { + data = []; + } + return Workspaces.generateRemotePayloadBody('Actions', method, data); + }; + + /** + * Generates the payload body + * + * @param {String} action + * @param {String} method + * @param {Object} data + * @return {{action: String, data: Object, method: String, type: string}} + */ + Workspaces.generateRemotePayloadBody = function(action, method, data) { + if (data instanceof Array) { + data.push(TYPO3.settings.Workspaces.token); + } else { + data = [ + data, + TYPO3.settings.Workspaces.token + ]; + } + return { + action: action, + data: data, + method: method, + type: 'rpc', + tid: Workspaces.tid++ + }; + }; + + /** + * Serialize a form to a JavaScript object + * + * @see http://stackoverflow.com/a/1186309/4828813 + * @return {Object} + */ + $.fn.serializeObject = function() { + var o = {}; + var a = this.serializeArray(); + $.each(a, function() { + if (typeof o[this.name] !== 'undefined') { + if (!o[this.name].push) { + o[this.name] = [o[this.name]]; + } + o[this.name].push(this.value || ''); + } else { + o[this.name] = this.value || ''; + } + }); + return o; + }; + + return Workspaces; });