[TASK] Apply code formating for all JavaScript files 21/55521/9
authorFrank Naegler <frank.naegler@typo3.org>
Thu, 1 Feb 2018 14:38:07 +0000 (15:38 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Mon, 5 Feb 2018 12:21:56 +0000 (13:21 +0100)
This is the first step for introduce CGL for JavaScript files.
The settings of the .editorconfig file is now applied to all
JavaScript files. This will prevent merge conflicts for the
next patches.

Resolves: #83752
Releases: master, 8.7
Change-Id: Ie84691e7f7f3a3974f3c62133895a62377b22f67
Reviewed-on: https://review.typo3.org/55521
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
222 files changed:
typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js
typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js
typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js
typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js
typo3/sysext/backend/Resources/Public/JavaScript/Icons.js
typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js
typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js
typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js
typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js
typo3/sysext/backend/Resources/Public/JavaScript/Localization.js
typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js
typo3/sysext/backend/Resources/Public/JavaScript/Modal.js
typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js
typo3/sysext/backend/Resources/Public/JavaScript/Notification.js
typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js
typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js
typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js
typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js
typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js
typo3/sysext/backend/Resources/Public/JavaScript/Severity.js
typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js
typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js
typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js
typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js
typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js
typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js
typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js
typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js
typo3/sysext/backend/Resources/Public/JavaScript/backend.js
typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js
typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js
typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js
typo3/sysext/backend/Resources/Public/JavaScript/md5.js
typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js
typo3/sysext/backend/Tests/JavaScript/IconsTest.js
typo3/sysext/backend/Tests/JavaScript/PopoverTest.js
typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js
typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js
typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js
typo3/sysext/documentation/Resources/Public/JavaScript/Main.js
typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js
typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js
typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js
typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js
typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js
typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js
typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js
typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js
typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js
typo3/sysext/install/Resources/Public/JavaScript/Install.js
typo3/sysext/install/Resources/Public/JavaScript/Installer.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js
typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js
typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js
typo3/sysext/lang/Resources/Public/JavaScript/Lang.js
typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js
typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js
typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js
typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js
typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js
typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js
typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js
typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js
typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js
typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js
typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js
typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js
typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js
typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js
typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js
typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js
typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js
typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js
typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js
typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js
typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js
typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js
typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js
typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js
typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js
typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js
typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js
typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js
typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js
typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js
typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js
typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js

index 9139034..c60162c 100644 (file)
  * 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;
 });
index e1ca31e..0b4dc8b 100644 (file)
  * 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 + '&nbsp;&nbsp;<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 + '&nbsp;&nbsp;<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;
 });
index 4d45bf3..2361706 100644 (file)
  * 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;
 });
index 656fc91..f3f258b 100644 (file)
  * 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;
 });
index 0840d61..41eb529 100644 (file)
  * 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;
 });
index 267bf7d..8eb132c 100644 (file)
  *
  */
 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 + '&nbsp;</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">&nbsp;</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 + '&nbsp;</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">&nbsp;</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();
 
 });
index 3b12573..108e2f9 100644 (file)
 
 // 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;
 });
index f40db4b..4fb7f68 100644 (file)
@@ -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
index 78953f3..eb5b40a 100644 (file)
  * 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>'
+        }
       };
     };
 
index d400937..643336f 100644 (file)
  * 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) {
+   &n