[TASK] Apply code formating for all JavaScript files 22/55522/6
authorFrank Naegler <frank.naegler@typo3.org>
Thu, 1 Feb 2018 14:49:17 +0000 (15:49 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Mon, 5 Feb 2018 12:33:25 +0000 (13:33 +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/55522
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
216 files changed:
.editorconfig
typo3/sysext/about/Resources/Public/JavaScript/EqualHeight.js
typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
typo3/sysext/backend/Resources/Public/JavaScript/ColorPicker.js
typo3/sysext/backend/Resources/Public/JavaScript/ContextHelp.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/DebugConsole.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/SvgTree.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/FormEngineReview.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js
typo3/sysext/backend/Resources/Public/JavaScript/GridEditor.js
typo3/sysext/backend/Resources/Public/JavaScript/Icons.js
typo3/sysext/backend/Resources/Public/JavaScript/ImageManipulation.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/Login.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/Notification.js
typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js
typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
typo3/sysext/backend/Resources/Public/JavaScript/Popover.js
typo3/sysext/backend/Resources/Public/JavaScript/RenameFile.js
typo3/sysext/backend/Resources/Public/JavaScript/Severity.js
typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js
typo3/sysext/backend/Resources/Public/JavaScript/Storage.js
typo3/sysext/backend/Resources/Public/JavaScript/Tabs.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/UserPassLogin.js
typo3/sysext/backend/Resources/Public/JavaScript/Utility.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/extjs/components/pagetree/javascript/Ext.ux.state.TreePanel.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/actions.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/app.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/deletiondropzone.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/filteringtree.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/nodeui.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/toppanel.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/tree.js
typo3/sysext/backend/Resources/Public/JavaScript/extjs/components/pagetree/javascript/treeeditor.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/GridEditorTest.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/core/Resources/Public/JavaScript/QueryGenerator.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/frontend/Resources/Public/JavaScript/jsfunc.menu.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/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/FileEdit.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Plugins/CodeCompletion/CompletionResult.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Plugins/CodeCompletion/DescriptionPlugin.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Plugins/CodeCompletion/TsCodeCompletion.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Plugins/CodeCompletion/TsParser.js
typo3/sysext/t3editor/Resources/Public/JavaScript/Plugins/CodeCompletion/TsRef.js
typo3/sysext/t3editor/Resources/Public/JavaScript/T3editor.js
typo3/sysext/t3editor/Resources/Public/JavaScript/parse_typoscript/parsetyposcript.js
typo3/sysext/t3editor/Resources/Public/JavaScript/parse_typoscript/tokenizetyposcript.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/wizard_crpages/Resources/Public/JavaScript/WizardCreatePages.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 87da7fb..05494ee 100644 (file)
@@ -32,8 +32,8 @@ indent_size = 4
 
 # JS-Files
 [*.js]
-indent_style = tab
-indent_size = 4
+indent_style = space
+indent_size = 2
 
 # JSON-Files
 [*.json]
index 947da13..e2365c4 100644 (file)
@@ -16,8 +16,8 @@
  * matchHeight makes the height of all selected elements exactly equal.
  */
 define(['jquery', 'matchheight'], function($) {
-       'use strict';
+  'use strict';
 
-       $('.t3js-equalheight').matchHeight();
+  $('.t3js-equalheight').matchHeight();
 
 });
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 6f027e8..40f56d0 100644 (file)
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require", "exports", "jquery", "TYPO3/CMS/Core/Contrib/jquery.minicolors"], function (require, exports, $) {
-    "use strict";
+define(["require", "exports", "jquery", "TYPO3/CMS/Core/Contrib/jquery.minicolors"], function(require, exports, $) {
+  "use strict";
+  /**
+   * Module: TYPO3/CMS/Backend/ColorPicker
+   * contains all logic for the color picker used in FormEngine
+   * @exports TYPO3/CMS/Backend/ColorPicker
+   */
+  var ColorPicker = (function() {
     /**
-     * Module: TYPO3/CMS/Backend/ColorPicker
-     * contains all logic for the color picker used in FormEngine
-     * @exports TYPO3/CMS/Backend/ColorPicker
+     * The constructor, set the class properties default values
      */
-    var ColorPicker = (function () {
-        /**
-         * The constructor, set the class properties default values
-         */
-        function ColorPicker() {
-            this.selector = '.t3js-color-picker';
+    function ColorPicker() {
+      this.selector = '.t3js-color-picker';
+    }
+
+    /**
+     * Initialize the color picker for the given selector
+     */
+    ColorPicker.prototype.initialize = function() {
+      $(this.selector).minicolors({
+        format: 'hex',
+        position: 'bottom left',
+        theme: 'bootstrap'
+      });
+      $(document).on('change', '.t3js-colorpicker-value-trigger', function(event) {
+        var $element = $(event.target);
+        if ($element.val() !== '') {
+          $element.closest('.t3js-formengine-field-item')
+            .find('.t3js-color-picker')
+            .val($element.val())
+            .trigger('paste');
+          $element.val('');
         }
-        /**
-         * Initialize the color picker for the given selector
-         */
-        ColorPicker.prototype.initialize = function () {
-            $(this.selector).minicolors({
-                format: 'hex',
-                position: 'bottom left',
-                theme: 'bootstrap',
-            });
-            $(document).on('change', '.t3js-colorpicker-value-trigger', function (event) {
-                var $element = $(event.target);
-                if ($element.val() !== '') {
-                    $element.closest('.t3js-formengine-field-item')
-                        .find('.t3js-color-picker')
-                        .val($element.val())
-                        .trigger('paste');
-                    $element.val('');
-                }
-            });
-        };
-        return ColorPicker;
-    }());
-    return new ColorPicker();
+      });
+    };
+    return ColorPicker;
+  }());
+  return new ColorPicker();
 });
index ce4eaab..6c5f263 100644 (file)
  */
 define(['jquery', 'TYPO3/CMS/Backend/Popover', 'bootstrap'], function($) {
 
-       /**
-        * The main ContextHelp object
-        *
-        * @type {{ajaxUrl: *, localCache: {}, helpModuleUrl: string, trigger: string, placement: string, selector: string}}
-        * @exports TYPO3/CMS/Backend/ContextHelp
-        */
-       var ContextHelp = {
-               ajaxUrl: TYPO3.settings.ajaxUrls['context_help'],
-               localCache: {},
-               helpModuleUrl: '',
-               trigger: 'click',
-               placement: 'auto',
-               selector: '.t3-help-link'
-       };
+  /**
+   * The main ContextHelp object
+   *
+   * @type {{ajaxUrl: *, localCache: {}, helpModuleUrl: string, trigger: string, placement: string, selector: string}}
+   * @exports TYPO3/CMS/Backend/ContextHelp
+   */
+  var ContextHelp = {
+    ajaxUrl: TYPO3.settings.ajaxUrls['context_help'],
+    localCache: {},
+    helpModuleUrl: '',
+    trigger: 'click',
+    placement: 'auto',
+    selector: '.t3-help-link'
+  };
 
-       /**
-        * Initialize context help trigger
-        */
-       ContextHelp.initialize = function() {
-               var backendWindow = ContextHelp.resolveBackend();
-               ContextHelp.helpModuleUrl = null;
-               if (typeof backendWindow.TYPO3.settings.ContextHelp !== 'undefined') {
-                       ContextHelp.helpModuleUrl = backendWindow.TYPO3.settings.ContextHelp.moduleUrl;
-               }
+  /**
+   * Initialize context help trigger
+   */
+  ContextHelp.initialize = function() {
+    var backendWindow = ContextHelp.resolveBackend();
+    ContextHelp.helpModuleUrl = null;
+    if (typeof backendWindow.TYPO3.settings.ContextHelp !== 'undefined') {
+      ContextHelp.helpModuleUrl = backendWindow.TYPO3.settings.ContextHelp.moduleUrl;
+    }
 
-               if (TYPO3.ShortcutMenu === undefined && backendWindow.TYPO3.ShortcutMenu === undefined) {
-                       // @FIXME: if we are in the popup... remove the bookmark / shortcut button
-                       // @TODO: make it possible to use the bookmark button also in popup mode
-                       $('.icon-actions-system-shortcut-new').closest('.btn').hide();
-               }
-               var title = '&nbsp;';
-               if (typeof backendWindow.TYPO3.LLL !== 'undefined') {
-                       title = backendWindow.TYPO3.LLL.core.csh_tooltip_loading;
-               }
-               var $element = $(this.selector);
-               $element
-                       .attr('data-loaded', 'false')
-                       .attr('data-html', true)
-                       .attr('data-original-title', title)
-                       .attr('data-placement', this.placement)
-                       .attr('data-trigger', this.trigger);
-               TYPO3.Popover.popover($element);
+    if (TYPO3.ShortcutMenu === undefined && backendWindow.TYPO3.ShortcutMenu === undefined) {
+      // @FIXME: if we are in the popup... remove the bookmark / shortcut button
+      // @TODO: make it possible to use the bookmark button also in popup mode
+      $('.icon-actions-system-shortcut-new').closest('.btn').hide();
+    }
+    var title = '&nbsp;';
+    if (typeof backendWindow.TYPO3.LLL !== 'undefined') {
+      title = backendWindow.TYPO3.LLL.core.csh_tooltip_loading;
+    }
+    var $element = $(this.selector);
+    $element
+      .attr('data-loaded', 'false')
+      .attr('data-html', true)
+      .attr('data-original-title', title)
+      .attr('data-placement', this.placement)
+      .attr('data-trigger', this.trigger);
+    TYPO3.Popover.popover($element);
 
-               $(document).on('show.bs.popover', ContextHelp.selector, function(evt) {
-                       var $me = $(this),
-                               description = $me.data('description');
-                       if (typeof description !== 'undefined' && description !== '') {
-                               TYPO3.Popover.setOptions($me, {
-                                       title: $me.data('title'),
-                                       content: description
-                               });
-                       } else if ($me.attr('data-loaded') === 'false' && $me.data('table')) {
-                               ContextHelp.loadHelp($me);
-                       }
+    $(document).on('show.bs.popover', ContextHelp.selector, function(evt) {
+      var $me = $(this),
+        description = $me.data('description');
+      if (typeof description !== 'undefined' && description !== '') {
+        TYPO3.Popover.setOptions($me, {
+          title: $me.data('title'),
+          content: description
+        });
+      } else if ($me.attr('data-loaded') === 'false' && $me.data('table')) {
+        ContextHelp.loadHelp($me);
+      }
 
-                       // if help icon is in DocHeader, force open to bottom
-                       if ($me.closest('.t3js-module-docheader').length) {
-                               TYPO3.Popover.setOption($me, 'placement', 'bottom');
-                       }
-               });
-               $(document).on('shown.bs.popover', ContextHelp.selector, function(evt) {
-                       var $popover = $(evt.target).data('bs.popover').$tip;
-                       if (!$popover.find('.popover-title').is(':visible')) {
-                               $popover.addClass('no-title');
-                       }
-               });
-               $(document).on('click', '.tipIsLinked', function(e) {
-                       $('.popover').each(function() {
-                               var $popover = $(this);
-                               if ($popover.has(e.target).length) {
-                                       ContextHelp.showHelpPopup($popover.data('bs.popover').$element);
-                               }
-                       });
-               });
-               $(document).on('click', 'body', function (e) {
-                       $(ContextHelp.selector).each(function () {
-                               var $triggerElement = $(this);
-                               // the 'is' for buttons that trigger popups
-                               // the 'has' for icons within a button that triggers a popup
-                               if (!$triggerElement.is(e.target) && $triggerElement.has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
-                                       TYPO3.Popover.hide($triggerElement);
-                               }
-                       });
-               });
-       };
+      // if help icon is in DocHeader, force open to bottom
+      if ($me.closest('.t3js-module-docheader').length) {
+        TYPO3.Popover.setOption($me, 'placement', 'bottom');
+      }
+    });
+    $(document).on('shown.bs.popover', ContextHelp.selector, function(evt) {
+      var $popover = $(evt.target).data('bs.popover').$tip;
+      if (!$popover.find('.popover-title').is(':visible')) {
+        $popover.addClass('no-title');
+      }
+    });
+    $(document).on('click', '.tipIsLinked', function(e) {
+      $('.popover').each(function() {
+        var $popover = $(this);
+        if ($popover.has(e.target).length) {
+          ContextHelp.showHelpPopup($popover.data('bs.popover').$element);
+        }
+      });
+    });
+    $(document).on('click', 'body', function(e) {
+      $(ContextHelp.selector).each(function() {
+        var $triggerElement = $(this);
+        // the 'is' for buttons that trigger popups
+        // the 'has' for icons within a button that triggers a popup
+        if (!$triggerElement.is(e.target) && $triggerElement.has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
+          TYPO3.Popover.hide($triggerElement);
+        }
+      });
+    });
+  };
 
-       /**
-        * Open the help popup
-        *
-        * @param {Object} $trigger
-        */
-       ContextHelp.showHelpPopup = function($trigger) {
-               try {
-                       var cshWindow = window.open(
-                               ContextHelp.helpModuleUrl +
-                                       '&tx_cshmanual_help_cshmanualcshmanual[table]=' + $trigger.data('table') +
-                                       '&tx_cshmanual_help_cshmanualcshmanual[field]=' + $trigger.data('field'),
-                               'ContextHelpWindow',
-                               'height=400,width=600,status=0,menubar=0,scrollbars=1'
-                       );
-                       cshWindow.focus();
-                       TYPO3.Popover.hide($trigger);
-                       return cshWindow;
-               } catch(e) {
-                       // do nothing
-               }
-       };
+  /**
+   * Open the help popup
+   *
+   * @param {Object} $trigger
+   */
+  ContextHelp.showHelpPopup = function($trigger) {
+    try {
+      var cshWindow = window.open(
+        ContextHelp.helpModuleUrl +
+        '&tx_cshmanual_help_cshmanualcshmanual[table]=' + $trigger.data('table') +
+        '&tx_cshmanual_help_cshmanualcshmanual[field]=' + $trigger.data('field'),
+        'ContextHelpWindow',
+        'height=400,width=600,status=0,menubar=0,scrollbars=1'
+      );
+      cshWindow.focus();
+      TYPO3.Popover.hide($trigger);
+      return cshWindow;
+    } catch (e) {
+      // do nothing
+    }
+  };
 
-       /**
-        * Load help data
-        *
-        * @param {Object} $trigger
-        */
-       ContextHelp.loadHelp = function($trigger) {
-               var table = $trigger.data('table');
-               var field = $trigger.data('field');
-               // If a table is defined, use ajax call to get the tooltip's content
-               if (table) {
-                       // Load content
-                       $.getJSON(ContextHelp.ajaxUrl, {
-                               params: {
-                                       action: 'getContextHelp',
-                                       table: table,
-                                       field: field
-                               }
-                       }).done(function(data) {
-                               var title = data.title || '';
-                               var content = data.content || '<p></p>';
-                               TYPO3.Popover.setOptions($trigger, {
-                                       title: title,
-                                       content: content
-                               });
-                               $trigger
-                                       .attr('data-loaded', 'true')
-                                       .one('hidden.bs.popover', function() {
-                                               TYPO3.Popover.show($trigger);
-                                       });
-                               TYPO3.Popover.hide($trigger);
-                       });
-               }
-       };
+  /**
+   * Load help data
+   *
+   * @param {Object} $trigger
+   */
+  ContextHelp.loadHelp = function($trigger) {
+    var table = $trigger.data('table');
+    var field = $trigger.data('field');
+    // If a table is defined, use ajax call to get the tooltip's content
+    if (table) {
+      // Load content
+      $.getJSON(ContextHelp.ajaxUrl, {
+        params: {
+          action: 'getContextHelp',
+          table: table,
+          field: field
+        }
+      }).done(function(data) {
+        var title = data.title || '';
+        var content = data.content || '<p></p>';
+        TYPO3.Popover.setOptions($trigger, {
+          title: title,
+          content: content
+        });
+        $trigger
+          .attr('data-loaded', 'true')
+          .one('hidden.bs.popover', function() {
+            TYPO3.Popover.show($trigger);
+          });
+        TYPO3.Popover.hide($trigger);
+      });
+    }
+  };
 
-       /**
-        * @return {Window}
-        */
-       ContextHelp.resolveBackend = function () {
-               var windowReference;
-               if (typeof window.opener !== 'undefined' && window.opener !== null) {
-                       windowReference = window.opener.top;
-               } else {
-                       windowReference = top;
-               }
-               return windowReference;
-       };
+  /**
+   * @return {Window}
+   */
+  ContextHelp.resolveBackend = function() {
+    var windowReference;
+    if (typeof window.opener !== 'undefined' && window.opener !== null) {
+      windowReference = window.opener.top;
+    } else {
+      windowReference = top;
+    }
+    return windowReference;
+  };
 
-       ContextHelp.initialize();
-       TYPO3.ContextHelp = ContextHelp;
-       return ContextHelp;
+  ContextHelp.initialize();
+  TYPO3.ContextHelp = ContextHelp;
+  return ContextHelp;
 });
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 a10da29..2e2bcec 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();
+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) {
+    // see actions.js -> mountAsTreeRoot
+    if (table === 'pages' && typeof top.Ext.getCmp('typo3-pagetree') !== 'undefined') {
+      var app = top.Ext.getCmp('typo3-pagetree-tree').app;
+      var node = app.getTree().getRootNode().findChild('realId', uid, true);
+      if (node === null) {
+        return false;
+      }
+
+      var useNode = {
+        attributes: {
+          nodeData: {
+            id: uid
+          }
         }
-    };
-
-    ContextMenuActions.openInfoPopUp = function (table, uid) {
-        top.launchView(table, uid);
-    };
-
-    ContextMenuActions.mountAsTreeRoot = function (table, uid) {
-        // see actions.js -> mountAsTreeRoot
-        if (table === 'pages' && typeof top.Ext.getCmp('typo3-pagetree') !== 'undefined') {
-            var app = top.Ext.getCmp('typo3-pagetree-tree').app;
-            var node = app.getTree().getRootNode().findChild('realId', uid, true);
-            if (node === null) {
-                return false;
-            }
-
-            var useNode = {
-                attributes: {
-                    nodeData: {
-                        id: uid
-                    }
-                }
-            };
-            top.TYPO3.Components.PageTree.Actions.mountAsTreeRoot(useNode, node.ownerTree);
-        }
-    };
-
-    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);
+      };
+      top.TYPO3.Components.PageTree.Actions.mountAsTreeRoot(useNode, node.ownerTree);
+    }
+  };
+
+  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.disableRecord = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&prErr=1&redirect=' + ContextMenuActions.getReturnUrl()
+    ).on('load', 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&prErr=1&redirect=' + ContextMenuActions.getReturnUrl()
+    ).on('load', 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) {
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'delete') {
         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.disableRecord = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&prErr=1&redirect=' + ContextMenuActions.getReturnUrl()
-        ).on('load', function () {
+          top.TYPO3.settings.RecordCommit.moduleUrl + '&redirect=' + ContextMenuActions.getReturnUrl() + '&cmd[' + table + '][' + uid + '][delete]=1&prErr=1'
+        ).on('load', 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&prErr=1&redirect=' + ContextMenuActions.getReturnUrl()
-        ).on('load', 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'
-                }
-            ]);
-
-        $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&prErr=1'
-                ).on('load', 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.list_frame.location.reload(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.list_frame.location.reload(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.list_frame.location.reload(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&prErr=1&uPT=1'
-                + '&redirect=' + ContextMenuActions.getReturnUrl();
-
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.RecordCommit.moduleUrl + url
-            ).on('load', function () {
-                if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
-                    top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-                }
-            });
-        };
-        if (!$anchorElement.data('title')) {
-            performPaste();
-            return;
+      }
+      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.list_frame.location.reload(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.list_frame.location.reload(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.list_frame.location.reload(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&prErr=1&uPT=1'
+        + '&redirect=' + ContextMenuActions.getReturnUrl();
+
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.RecordCommit.moduleUrl + url
+      ).on('load', function() {
+        if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
+          top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
         }
-        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 8fb74df..64798bf 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', 'twbs/bootstrap-datetimepicker'], function(moment, Storage) {
-                               var userLocale = Storage.Persistent.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', 'twbs/bootstrap-datetimepicker'], function(moment, Storage) {
+        var userLocale = Storage.Persistent.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 7ef7c11..b0bf1f3 100644 (file)
  * Module: TYPO3/CMS/Backend/DebugConsole
  * The debug console shown at the bottom of the backend
  */
-define(['jquery'], function ($) {
-       'use strict';
-
-       /**
-        *
-        * @type {{$consoleDom: null, settings: {autoscroll: boolean}}}
-        * @exports TYPO3/CMS/Backend/DebugConsole
-        */
-       var DebugConsole = {
-               $consoleDom: null,
-               settings: {
-                       autoscroll: true
-               }
-       };
-
-       /**
-        * Initializes the console
-        */
-       DebugConsole.initialize = function() {
-               DebugConsole.createDOM();
-       };
-
-       /**
-        * Create the basic DOM of the Debugger Console
-        */
-       DebugConsole.createDOM = function() {
-               if (DebugConsole.$consoleDom !== null) {
-                       return DebugConsole.$consoleDom;
-               }
-
-               DebugConsole.$consoleDom =
-                       $('<div />', {id: 'typo3-debug-console'}).append(
-                               $('<div />', {class: 't3js-topbar topbar'}).append(
-                                       $('<p />', {class: 'pull-left'}).text(' TYPO3 Debug Console').prepend(
-                                               $('<span />', {class: 'fa fa-terminal topbar-icon'})
-                                       ).append(
-                                               $('<span />', {class: 'badge'})
-                                       ),
-                                       $('<div />', {class: 't3js-buttons btn-group pull-right'})
-                               ),
-                               $('<div />').append(
-                                       $('<div />', {role: 'tabpanel'}).append(
-                                               $('<ul />', {class: 'nav nav-tabs t3js-debuggroups', role: 'tablist'})
-                                       ),
-                                       $('<div />', {class: 'tab-content t3js-debugcontent'})
-                               )
-                       );
-
-               DebugConsole.addButton(
-                       $('<button />', {class: 'btn btn-default btn-sm ' + (DebugConsole.settings.autoscroll ? 'active' : ''), title: TYPO3.lang['debuggerconsole.autoscroll']}).append(
-                               $('<span />', {class: 't3-icon fa fa-magnet'})
-                       ), function() {
-                               $(this).button('toggle');
-                               DebugConsole.settings.autoscroll = !DebugConsole.settings.autoscroll;
-                       }
-               ).addButton(
-                       $('<button />', {class: 'btn btn-default btn-sm', title: TYPO3.lang['debuggerconsole.toggle.collapse']}).append(
-                               $('<span />', {class: 't3-icon fa fa-chevron-down'})
-                       ), function() {
-                               var $button = $(this),
-                                       $icon = $button.find('.t3-icon'),
-                                       $innerContainer = DebugConsole.$consoleDom.find('.t3js-topbar').next();
-                               $innerContainer.toggle();
-                               if ($innerContainer.is(':visible')) {
-                                       $button.attr('title', TYPO3.lang['debuggerconsole.toggle.collapse']);
-                                       $icon.toggleClass('fa-chevron-down', true).toggleClass('fa-chevron-up', false);
-                                       DebugConsole.resetGlobalUnreadCounter();
-                               } else {
-                                       $button.attr('title', TYPO3.lang['debuggerconsole.toggle.expand']);
-                                       $icon.toggleClass('fa-chevron-down', false).toggleClass('fa-chevron-up', true);
-                               }
-                       }
-               ).addButton(
-                       $('<button />', {class: 'btn btn-default btn-sm', title: TYPO3.lang['debuggerconsole.clear']}).append(
-                               $('<span />', {class: 't3-icon fa fa-undo'})
-                       ), function() {
-                               DebugConsole.flush();
-                       }
-               ).addButton(
-                       $('<button />', {class: 'btn btn-default btn-sm', title: TYPO3.lang['debuggerconsole.close']}).append(
-                               $('<span />', {class: 't3-icon fa fa-times'})
-                       ), function() {
-                               DebugConsole.$consoleDom.remove();
-                               DebugConsole.$consoleDom = null;
-                               DebugConsole.createDOM();
-                       }
-               );
-       };
-
-       /**
-        * Adds a button and it's callback to the console's toolbar
-        *
-        * @param {Object} $button
-        * @param {function} callback
-        * @returns {{$consoleDom: null, settings: {autoscroll: boolean}}}
-        */
-       DebugConsole.addButton = function($button, callback) {
-               $button.on('click', callback);
-               DebugConsole.$consoleDom.find('.t3js-buttons').append($button);
-
-               return DebugConsole;
-       };
-
-       /**
-        * Attach the Debugger Console to the viewport
-        */
-       DebugConsole.attachToViewport = function() {
-               var $viewport = $('.t3js-scaffold-content');
-               if ($viewport.has(DebugConsole.$consoleDom).length === 0) {
-                       $viewport.append(DebugConsole.$consoleDom);
-               }
-       };
-
-       /**
-        * Add the debug message to the console
-        *
-        * @param {String} message
-        * @param {String} header
-        * @param {String} [group=Debug]
-        */
-       DebugConsole.add = function(message, header, group) {
-               DebugConsole.attachToViewport();
-
-               var $line = $('<p />').html(message);
-               if (typeof header !== 'undefined' && header.length > 0) {
-                       $line.prepend($('<strong />').text(header));
-               }
-
-               if (typeof group === 'undefined' || group.length === 0) {
-                       group = 'Debug';
-               }
-
-               var tabIdentifier = 'debugtab-' + group.toLowerCase().replace(/\W+/g, '-'),
-                       $debugTabs = DebugConsole.$consoleDom.find('.t3js-debuggroups'),
-                       $tabContent = DebugConsole.$consoleDom.find('.t3js-debugcontent'),
-                       $tab = DebugConsole.$consoleDom.find('.t3js-debuggroups li[data-identifier=' + tabIdentifier + ']');
-
-               // check if group tab exists
-               if ($tab.length === 0) {
-                       // create new tab
-                       $tab =
-                               $('<li />', {role: 'presentation', 'data-identifier': tabIdentifier}).append(
-                                       $('<a />', {href: '#' + tabIdentifier, 'aria-controls': tabIdentifier, role: 'tab', 'data-toggle': 'tab'}).text(group + ' ').append(
-                                               $('<span />', {class: 'badge'})
-                                       )
-                               ).on('shown.bs.tab', function() {
-                                       $(this).find('.badge').text('');
-                               });
-                       $debugTabs.append($tab);
-                       $tabContent.append(
-                               $('<div />', {role: 'tabpanel', class: 'tab-pane', id: tabIdentifier}).append(
-                                       $('<div />', {class: 't3js-messages messages'})
-                               )
-                       );
-               }
-
-               DebugConsole.identifyTabLengthPresentationIcon($debugTabs);
-
-               // activate the first tab if no one is active
-               if ($debugTabs.find('.active').length === 0) {
-                       $debugTabs.find('a:first').tab('show');
-               }
-
-               DebugConsole.incrementInactiveTabCounter($tab);
-               DebugConsole.incrementUnreadMessagesIfCollapsed();
-
-               var $messageBox = $('#' + tabIdentifier + ' .t3js-messages'),
-                       isMessageBoxActive = $messageBox.parent().hasClass('active');
-
-               $messageBox.append($line);
-               if (DebugConsole.settings.autoscroll && isMessageBoxActive) {
-                       $messageBox.scrollTop($messageBox.prop('scrollHeight'));
-               }
-       };
-
-       /**
-        * Gets a proper console icon depending on the amount of tabs
-        *
-        * @param {Object} $tabs
-        */
-       DebugConsole.identifyTabLengthPresentationIcon = function($tabs) {
-               var terminalIcon1 = true,
-                       terminalIcon2 = false;
-
-               if ($tabs.children().length >= 10) {
-                       // too many tabs
-                       // much debug
-                       // so wow
-                       terminalIcon1 = false;
-                       terminalIcon2 = true;
-               }
-               DebugConsole.$consoleDom.find('.topbar-icon').toggleClass('fa-meh-o', terminalIcon2).toggleClass('fa-terminal', terminalIcon1);
-       };
-
-       /**
-        * Increment the counter of unread messages in the given tab
-        *
-        * @param {Object} $tab
-        */
-       DebugConsole.incrementInactiveTabCounter = function($tab) {
-               if (!$tab.hasClass('active')) {
-                       var $badge = $tab.find('.badge'),
-                               value = parseInt($badge.text());
-
-                       if (isNaN(value)) {
-                               value = 0;
-                       }
-                       $badge.text(++value);
-               }
-       };
-
-       /**
-        * Increment the counter of unread messages in the tabbar
-        */
-       DebugConsole.incrementUnreadMessagesIfCollapsed = function() {
-               var $topbar = DebugConsole.$consoleDom.find('.t3js-topbar'),
-                       $innerContainer = $topbar.next();
-
-               if ($innerContainer.is(':hidden')) {
-                       var $badge = $topbar.find('.badge'),
-                               value = parseInt($badge.text());
-
-                       if (isNaN(value)) {
-                               value = 0;
-                       }
-                       $badge.text(++value);
-               }
-       };
-
-       /**
-        * Reset global unread counter
-        */
-       DebugConsole.resetGlobalUnreadCounter = function() {
-               var $topbar = DebugConsole.$consoleDom.find('.t3js-topbar'),
-                       $badge = $topbar.find('.badge');
-
-               $badge.text('');
-       };
-
-       /**
-        * Reset the console to it's virginity
-        */
-       DebugConsole.flush = function() {
-               var $debugTabs = DebugConsole.$consoleDom.find('.t3js-debuggroups'),
-                       $tabContent = DebugConsole.$consoleDom.find('.t3js-debugcontent');
-
-               $debugTabs.children().remove();
-               $tabContent.children().remove();
-
-               DebugConsole.identifyTabLengthPresentationIcon($debugTabs);
-       };
-
-       /**
-        * Destroy everything of the console
-        */
-       DebugConsole.destroy = function() {
-               DebugConsole.$consoleDom.remove();
-               DebugConsole.$consoleDom = null;
-       };
-
-       $(DebugConsole.initialize);
-
-       // expose as global object
-       TYPO3.DebugConsole = DebugConsole;
-
-       return DebugConsole;
+define(['jquery'], function($) {
+  'use strict';
+
+  /**
+   *
+   * @type {{$consoleDom: null, settings: {autoscroll: boolean}}}
+   * @exports TYPO3/CMS/Backend/DebugConsole
+   */
+  var DebugConsole = {
+    $consoleDom: null,
+    settings: {
+      autoscroll: true
+    }
+  };
+
+  /**
+   * Initializes the console
+   */
+  DebugConsole.initialize = function() {
+    DebugConsole.createDOM();
+  };
+
+  /**
+   * Create the basic DOM of the Debugger Console
+   */
+  DebugConsole.createDOM = function() {
+    if (DebugConsole.$consoleDom !== null) {
+      return DebugConsole.$consoleDom;
+    }
+
+    DebugConsole.$consoleDom =
+      $('<div />', {id: 'typo3-debug-console'}).append(
+        $('<div />', {class: 't3js-topbar topbar'}).append(
+          $('<p />', {class: 'pull-left'}).text(' TYPO3 Debug Console').prepend(
+            $('<span />', {class: 'fa fa-terminal topbar-icon'})
+          ).append(
+            $('<span />', {class: 'badge'})
+          ),
+          $('<div />', {class: 't3js-buttons btn-group pull-right'})
+        ),
+        $('<div />').append(
+          $('<div />', {role: 'tabpanel'}).append(
+            $('<ul />', {class: 'nav nav-tabs t3js-debuggroups', role: 'tablist'})
+          ),
+          $('<div />', {class: 'tab-content t3js-debugcontent'})
+        )
+      );
+
+    DebugConsole.addButton(
+      $('<button />', {
+        class: 'btn btn-default btn-sm ' + (DebugConsole.settings.autoscroll ? 'active' : ''),
+        title: TYPO3.lang['debuggerconsole.autoscroll']
+      }).append(
+        $('<span />', {class: 't3-icon fa fa-magnet'})
+      ), function() {
+        $(this).button('toggle');
+        DebugConsole.settings.autoscroll = !DebugConsole.settings.autoscroll;
+      }
+    ).addButton(
+      $('<button />', {
+        class: 'btn btn-default btn-sm',
+        title: TYPO3.lang['debuggerconsole.toggle.collapse']
+      }).append(
+        $('<span />', {class: 't3-icon fa fa-chevron-down'})
+      ), function() {
+        var $button = $(this),
+          $icon = $button.find('.t3-icon'),
+          $innerContainer = DebugConsole.$consoleDom.find('.t3js-topbar').next();
+        $innerContainer.toggle();
+        if ($innerContainer.is(':visible')) {
+          $button.attr('title', TYPO3.lang['debuggerconsole.toggle.collapse']);
+          $icon.toggleClass('fa-chevron-down', true).toggleClass('fa-chevron-up', false);
+          DebugConsole.resetGlobalUnreadCounter();
+        } else {
+          $button.attr('title', TYPO3.lang['debuggerconsole.toggle.expand']);
+          $icon.toggleClass('fa-chevron-down', false).toggleClass('fa-chevron-up', true);
+        }
+      }
+    ).addButton(
+      $('<button />', {
+        class: 'btn btn-default btn-sm',
+        title: TYPO3.lang['debuggerconsole.clear']
+      }).append(
+        $('<span />', {class: 't3-icon fa fa-undo'})
+      ), function() {
+        DebugConsole.flush();
+      }
+    ).addButton(
+      $('<button />', {
+        class: 'btn btn-default btn-sm',
+        title: TYPO3.lang['debuggerconsole.close']
+      }).append(
+        $('<span />', {class: 't3-icon fa fa-times'})
+      ), function() {
+        DebugConsole.$consoleDom.remove();
+        DebugConsole.$consoleDom = null;
+        DebugConsole.createDOM();
+      }
+    );
+  };
+
+  /**
+   * Adds a button and it's callback to the console's toolbar
+   *
+   * @param {Object} $button
+   * @param {function} callback
+   * @returns {{$consoleDom: null, settings: {autoscroll: boolean}}}
+   */
+  DebugConsole.addButton = function($button, callback) {
+    $button.on('click', callback);
+    DebugConsole.$consoleDom.find('.t3js-buttons').append($button);
+
+    return DebugConsole;
+  };
+
+  /**
+   * Attach the Debugger Console to the viewport
+   */
+  DebugConsole.attachToViewport = function() {
+    var $viewport = $('.t3js-scaffold-content');
+    if ($viewport.has(DebugConsole.$consoleDom).length === 0) {
+      $viewport.append(DebugConsole.$consoleDom);
+    }
+  };
+
+  /**
+   * Add the debug message to the console
+   *
+   * @param {String} message
+   * @param {String} header
+   * @param {String} [group=Debug]
+   */
+  DebugConsole.add = function(message, header, group) {
+    DebugConsole.attachToViewport();
+
+    var $line = $('<p />').html(message);
+    if (typeof header !== 'undefined' && header.length > 0) {
+      $line.prepend($('<strong />').text(header));
+    }
+
+    if (typeof group === 'undefined' || group.length === 0) {
+      group = 'Debug';
+    }
+
+    var tabIdentifier = 'debugtab-' + group.toLowerCase().replace(/\W+/g, '-'),
+      $debugTabs = DebugConsole.$consoleDom.find('.t3js-debuggroups'),
+      $tabContent = DebugConsole.$consoleDom.find('.t3js-debugcontent'),
+      $tab = DebugConsole.$consoleDom.find('.t3js-debuggroups li[data-identifier=' + tabIdentifier + ']');
+
+    // check if group tab exists
+    if ($tab.length === 0) {
+      // create new tab
+      $tab =
+        $('<li />', {role: 'presentation', 'data-identifier': tabIdentifier}).append(
+          $('<a />', {
+            href: '#' + tabIdentifier,
+            'aria-controls': tabIdentifier,
+            role: 'tab',
+            'data-toggle': 'tab'
+          }).text(group + ' ').append(
+            $('<span />', {class: 'badge'})
+          )
+        ).on('shown.bs.tab', function() {
+          $(this).find('.badge').text('');
+        });
+      $debugTabs.append($tab);
+      $tabContent.append(
+        $('<div />', {role: 'tabpanel', class: 'tab-pane', id: tabIdentifier}).append(
+          $('<div />', {class: 't3js-messages messages'})
+        )
+      );
+    }
+
+    DebugConsole.identifyTabLengthPresentationIcon($debugTabs);
+
+    // activate the first tab if no one is active
+    if ($debugTabs.find('.active').length === 0) {
+      $debugTabs.find('a:first').tab('show');
+    }
+
+    DebugConsole.incrementInactiveTabCounter($tab);
+    DebugConsole.incrementUnreadMessagesIfCollapsed();
+
+    var $messageBox = $('#' + tabIdentifier + ' .t3js-messages'),
+      isMessageBoxActive = $messageBox.parent().hasClass('active');
+
+    $messageBox.append($line);
+    if (DebugConsole.settings.autoscroll && isMessageBoxActive) {
+      $messageBox.scrollTop($messageBox.prop('scrollHeight'));
+    }
+  };
+
+  /**
+   * Gets a proper console icon depending on the amount of tabs
+   *
+   * @param {Object} $tabs
+   */
+  DebugConsole.identifyTabLengthPresentationIcon = function($tabs) {
+    var terminalIcon1 = true,
+      terminalIcon2 = false;
+
+    if ($tabs.children().length >= 10) {
+      // too many tabs
+      // much debug
+      // so wow
+      terminalIcon1 = false;
+      terminalIcon2 = true;
+    }
+    DebugConsole.$consoleDom.find('.topbar-icon').toggleClass('fa-meh-o', terminalIcon2).toggleClass('fa-terminal', terminalIcon1);
+  };
+
+  /**
+   * Increment the counter of unread messages in the given tab
+   *
+   * @param {Object} $tab
+   */
+  DebugConsole.incrementInactiveTabCounter = function($tab) {
+    if (!$tab.hasClass('active')) {
+      var $badge = $tab.find('.badge'),
+        value = parseInt($badge.text());
+
+      if (isNaN(value)) {
+        value = 0;
+      }
+      $badge.text(++value);
+    }
+  };
+
+  /**
+   * Increment the counter of unread messages in the tabbar
+   */
+  DebugConsole.incrementUnreadMessagesIfCollapsed = function() {
+    var $topbar = DebugConsole.$consoleDom.find('.t3js-topbar'),
+      $innerContainer = $topbar.next();
+
+    if ($innerContainer.is(':hidden')) {
+      var $badge = $topbar.find('.badge'),
+        value = parseInt($badge.text());
+
+      if (isNaN(value)) {
+        value = 0;
+      }
+      $badge.text(++value);
+    }
+  };
+
+  /**
+   * Reset global unread counter
+   */
+  DebugConsole.resetGlobalUnreadCounter = function() {
+    var $topbar = DebugConsole.$consoleDom.find('.t3js-topbar'),
+      $badge = $topbar.find('.badge');
+
+    $badge.text('');
+  };
+
+  /**
+   * Reset the console to it's virginity
+   */
+  DebugConsole.flush = function() {
+    var $debugTabs = DebugConsole.$consoleDom.find('.t3js-debuggroups'),
+      $tabContent = DebugConsole.$consoleDom.find('.t3js-debugcontent');
+
+    $debugTabs.children().remove();
+    $tabContent.children().remove();
+
+    DebugConsole.identifyTabLengthPresentationIcon($debugTabs);
+  };
+
+  /**
+   * Destroy everything of the console
+   */
+  DebugConsole.destroy = function() {
+    DebugConsole.$consoleDom.remove();
+    DebugConsole.$consoleDom = null;
+  };
+
+  $(DebugConsole.initialize);
+
+  // expose as global object
+  TYPO3.DebugConsole = DebugConsole;
+
+  return DebugConsole;
 
 });
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 ebc1a33..c299013 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 = response !== false;
-                                               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('file[upload][1][target]', me.dragUploader.target);
-                       formData.append('file[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 = response !== false;
+            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('file[upload][1][target]', me.dragUploader.target);
+      formData.append('file[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 315f178..9b7707c 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'
-          ], function ($, FormEngineValidation, Modal, Severity) {
-
-       /**
-        *
-        * @type {{Validation: object, formName: *, openedPopupWindow: window, legacyFieldChangedCb: Function, browserUrl: string}}
-        * @exports TYPO3/CMS/Backend/FormEngine
-        */
-       var FormEngine = {
-               Validation: FormEngineValidation,
-               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
-        * @param {Number} width width of the window
-        * @param {Number} height height of the window
-        */
-       FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params, width, height) {
-               var url = FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params;
-               width = width ? width : TYPO3.settings.Popup.PopupWindow.width;
-               height = height ? height : TYPO3.settings.Popup.PopupWindow.height;
-               FormEngine.openedPopupWindow = window.open(url, 'Typo3WinBrowser', 'height=' + height + ',width=' + width + ',status=0,menubar=0,resizable=1,scrollbars=1');
-               FormEngine.openedPopupWindow.focus();
-       };
-
-
-       /**
-        * 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() {
-               $(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();
-               }).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);
-               });
-       };
-
-       /**
-        * 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)
-                       }
-               });
-       };
-
-       /**
-        * Show modal to confirm closing the document without saving
-        */
-       FormEngine.preventExitIfNotSaved = function() {
-               if ($('form[name="' + FormEngine.formName + '"] .has-change').length > 0) {
-                       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();
-                               } else if (e.target.name === 'yes') {
-                                       Modal.dismiss();
-                                       FormEngine.closeDocument();
-                               }
-                       });
-               } else {
-                       FormEngine.closeDocument();
-               }
-       };
-
-       /**
-        * 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'
+], function($, FormEngineValidation, Modal, Severity) {
+
+  /**
+   *
+   * @type {{Validation: object, formName: *, openedPopupWindow: window, legacyFieldChangedCb: Function, browserUrl: string}}
+   * @exports TYPO3/CMS/Backend/FormEngine
+   */
+  var FormEngine = {
+    Validation: FormEngineValidation,
+    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
+   * @param {Number} width width of the window
+   * @param {Number} height height of the window
+   */
+  FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params, width, height) {
+    var url = FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params;
+    width = width ? width : TYPO3.settings.Popup.PopupWindow.width;
+    height = height ? height : TYPO3.settings.Popup.PopupWindow.height;
+    FormEngine.openedPopupWindow = window.open(url, 'Typo3WinBrowser', 'height=' + height + ',width=' + width + ',status=0,menubar=0,resizable=1,scrollbars=1');
+    FormEngine.openedPopupWindow.focus();
+  };
+
+
+  /**
+   * 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')