From 9f73c3a68ee6c1108e46b1b4f2fc6449628065c5 Mon Sep 17 00:00:00 2001
From: Frank Naegler <frank.naegler@typo3.org>
Date: Thu, 1 Feb 2018 15:38:07 +0100
Subject: [PATCH] [TASK] Apply code formating for all JavaScript files

This is the first step for introduce CGL for JavaScript files.
The settings of the .editorconfig file is now applied to all
JavaScript files. This will prevent merge conflicts for the
next patches.

Resolves: #83752
Releases: master, 8.7
Change-Id: Ie84691e7f7f3a3974f3c62133895a62377b22f67
Reviewed-on: https://review.typo3.org/55521
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
---
 .../Public/JavaScript/AjaxDataHandler.js      |  448 +-
 .../Public/JavaScript/ContextMenu.js          |  590 +--
 .../Public/JavaScript/ContextMenuActions.js   |  440 +-
 .../Public/JavaScript/DateTimePicker.js       |  300 +-
 .../Public/JavaScript/DocumentHeader.js       |  176 +-
 .../Public/JavaScript/DragUploader.js         | 1316 +++--
 .../Resources/Public/JavaScript/FormEngine.js | 2401 ++++-----
 .../FormEngine/Element/SelectSingleElement.js |    8 +-
 .../FormEngine/Element/SelectTree.js          |   46 +-
 .../FormEngine/Element/SelectTreeElement.js   |   14 +-
 .../FormEngine/Element/TreeToolbar.js         |   56 +-
 .../Public/JavaScript/FormEngineFlexForm.js   |  520 +-
 .../FormEngineLinkBrowserAdapter.js           |  100 +-
 .../Public/JavaScript/FormEngineSuggest.js    |  214 +-
 .../Public/JavaScript/FormEngineValidation.js | 1898 ++++----
 .../Resources/Public/JavaScript/Icons.js      |  256 +-
 .../JavaScript/LayoutModule/DragDrop.js       |  460 +-
 .../Public/JavaScript/LayoutModule/Paste.js   |  206 +-
 .../Resources/Public/JavaScript/LegacyTree.js |  364 +-
 .../Resources/Public/JavaScript/LiveSearch.js |  256 +-
 .../Public/JavaScript/Localization.js         |  515 +-
 .../Public/JavaScript/LoginRefresh.js         |  945 ++--
 .../Resources/Public/JavaScript/Modal.js      |  838 ++--
 .../Resources/Public/JavaScript/ModuleMenu.js |  818 ++--
 .../Public/JavaScript/NewMultiplePages.js     |   92 +-
 .../Public/JavaScript/Notification.js         |  407 +-
 .../Public/JavaScript/OnlineMedia.js          |  212 +-
 .../Public/JavaScript/PageActions.js          |  440 +-
 .../Public/JavaScript/PageTree/PageTree.js    |   92 +-
 .../JavaScript/PageTree/PageTreeDragDrop.js   |  148 +-
 .../JavaScript/PageTree/PageTreeElement.js    |   38 +-
 .../JavaScript/PageTree/PageTreeToolbar.js    |   70 +-
 .../Resources/Public/JavaScript/Severity.js   |  132 +-
 .../Public/JavaScript/SplitButtons.js         |  168 +-
 .../Resources/Public/JavaScript/SvgTree.js    |  190 +-
 .../Public/JavaScript/ToggleSearchToolbox.js  |   42 +-
 .../Resources/Public/JavaScript/Toolbar.js    |   78 +-
 .../JavaScript/Toolbar/ClearCacheMenu.js      |  116 +-
 .../Public/JavaScript/Toolbar/ShortcutMenu.js |  400 +-
 .../Toolbar/SystemInformationMenu.js          |  250 +-
 .../Resources/Public/JavaScript/Tooltip.js    |   83 +-
 .../Public/JavaScript/ValueSlider.js          |  116 +-
 .../Resources/Public/JavaScript/Viewport.js   |  480 +-
 .../Resources/Public/JavaScript/Wizard.js     |  680 +--
 .../Public/JavaScript/Wizard/Colorpicker.js   |   98 +-
 .../Resources/Public/JavaScript/backend.js    |  124 +-
 .../Public/JavaScript/jquery.clearable.js     |  179 +-
 .../Public/JavaScript/jsfunc.evalfield.js     |  966 ++--
 .../Public/JavaScript/jsfunc.inline.js        | 2456 +++++-----
 .../Public/JavaScript/jsfunc.tbe_editor.js    |  515 +-
 .../Resources/Public/JavaScript/md5.js        |  423 +-
 .../JavaScript/FormEngineValidationTest.js    |  782 +--
 .../backend/Tests/JavaScript/IconsTest.js     |  132 +-
 .../backend/Tests/JavaScript/PopoverTest.js   |  136 +-
 .../Public/JavaScript/BackendUserListing.js   |   20 +-
 .../Public/JavaScript/ContextMenuActions.js   |   46 +-
 .../Public/JavaScript/Permissions.js          |  590 +--
 .../Resources/Public/JavaScript/Main.js       |  242 +-
 .../Resources/Public/JavaScript/Main.js       | 1416 +++---
 .../Public/JavaScript/ContextMenuActions.js   |  351 +-
 .../Resources/Public/JavaScript/FileDelete.js |   78 +-
 .../Resources/Public/JavaScript/FileList.js   |   82 +-
 .../Public/JavaScript/FileListLocalisation.js |   10 +-
 .../Resources/Public/JavaScript/FileSearch.js |   20 +-
 .../Public/JavaScript/Backend/FormEditor.js   | 2264 ++++-----
 .../JavaScript/Backend/FormEditor/Core.js     | 4330 ++++++++--------
 .../JavaScript/Backend/FormEditor/Helper.js   |  538 +-
 .../Backend/FormEditor/InspectorComponent.js  | 4336 +++++++++--------
 .../JavaScript/Backend/FormEditor/Mediator.js | 2146 ++++----
 .../Backend/FormEditor/ModalsComponent.js     | 1028 ++--
 .../Backend/FormEditor/StageComponent.js      | 2408 ++++-----
 .../Backend/FormEditor/TreeComponent.js       | 1337 ++---
 .../Backend/FormEditor/ViewModel.js           | 3494 ++++++-------
 .../Public/JavaScript/Backend/FormManager.js  |  436 +-
 .../Backend/FormManager/ViewModel.js          | 1058 ++--
 .../Vendor/jquery.mjs.nestedSortable.js       | 1784 +++----
 .../Public/JavaScript/ContextMenuActions.js   |   64 +-
 .../Public/JavaScript/ImportExport.js         |   46 +-
 .../Resources/Public/JavaScript/Install.js    |   12 +-
 .../Resources/Public/JavaScript/Installer.js  |  860 ++--
 .../Public/JavaScript/Modules/Cache.js        |   88 +-
 .../Public/JavaScript/Modules/CardLayout.js   |  300 +-
 .../Modules/ChangeInstallToolPassword.js      |  112 +-
 .../Public/JavaScript/Modules/ClearTables.js  |  222 +-
 .../JavaScript/Modules/ClearTypo3tempFiles.js |  216 +-
 .../Public/JavaScript/Modules/CoreUpdate.js   |  460 +-
 .../Public/JavaScript/Modules/CreateAdmin.js  |  120 +-
 .../JavaScript/Modules/DatabaseAnalyzer.js    |  294 +-
 .../Public/JavaScript/Modules/DumpAutoload.js |   88 +-
 .../JavaScript/Modules/EnvironmentCheck.js    |  126 +-
 .../Modules/ExtensionCompatTester.js          |  348 +-
 .../Modules/ExtensionConfiguration.js         |  408 +-
 .../JavaScript/Modules/ExtensionScanner.js    |  560 +--
 .../Public/JavaScript/Modules/FlashMessage.js |   58 +-
 .../JavaScript/Modules/FolderStructure.js     |  234 +-
 .../JavaScript/Modules/ImageProcessing.js     |  152 +-
 .../Public/JavaScript/Modules/InfoBox.js      |   58 +-
 .../JavaScript/Modules/LocalConfiguration.js  |  366 +-
 .../Public/JavaScript/Modules/MailTest.js     |  110 +-
 .../JavaScript/Modules/PasswordStrength.js    |   48 +-
 .../Public/JavaScript/Modules/Presets.js      |  212 +-
 .../Public/JavaScript/Modules/ProgressBar.js  |   56 +-
 .../JavaScript/Modules/ResetBackendUserUc.js  |   90 +-
 .../Public/JavaScript/Modules/Router.js       |  560 +--
 .../Public/JavaScript/Modules/Severity.js     |   70 +-
 .../JavaScript/Modules/SystemMaintainer.js    |  234 +-
 .../JavaScript/Modules/TcaExtTablesCheck.js   |  106 +-
 .../JavaScript/Modules/TcaMigrationsCheck.js  |  106 +-
 .../Public/JavaScript/Modules/UpgradeDocs.js  |  446 +-
 .../JavaScript/Modules/UpgradeWizards.js      |  886 ++--
 .../Public/JavaScript/RequireJSConfig.js      |   38 +-
 .../lang/Resources/Public/JavaScript/Lang.js  |   46 +-
 .../Public/JavaScript/LanguageModule.js       | 1488 +++---
 .../Resources/Public/JavaScript/Typo3Lang.js  |   86 +-
 .../Public/JavaScript/Linkvalidator.js        |   92 +-
 .../Public/JavaScript/ConfigurationView.js    |   28 +-
 .../Public/JavaScript/QueryGenerator.js       |  136 +-
 .../Public/JavaScript/Toolbar/OpendocsMenu.js |  192 +-
 .../Public/JavaScript/BrowseDatabase.js       |   44 +-
 .../Public/JavaScript/BrowseFiles.js          |  170 +-
 .../Public/JavaScript/BrowseFolders.js        |   28 +-
 .../Public/JavaScript/ElementBrowser.js       |  490 +-
 .../Public/JavaScript/FieldSelectBox.js       |   24 +-
 .../Public/JavaScript/FileLinkHandler.js      |   62 +-
 .../Public/JavaScript/LinkBrowser.js          |  226 +-
 .../Public/JavaScript/MailLinkHandler.js      |   42 +-
 .../Public/JavaScript/PageLinkHandler.js      |   88 +-
 .../Public/JavaScript/RecordLinkHandler.js    |   90 +-
 .../Resources/Public/JavaScript/Recordlist.js |  218 +-
 .../Resources/Public/JavaScript/Tooltip.js    |   22 +-
 .../Public/JavaScript/UrlLinkHandler.js       |   46 +-
 .../Resources/Public/JavaScript/Recycler.js   | 1169 ++---
 .../Public/JavaScript/RsaEncryption.js        |  356 +-
 .../Public/JavaScript/RsaEncryptionModule.js  |  268 +-
 .../Resources/Public/JavaScript/RsaLibrary.js | 1192 ++---
 .../Public/JavaScript/Plugins/autolinking.js  |  218 +-
 .../JavaScript/Plugins/quicktable/lang/af.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ar.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/bg.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/bn.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/bs.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ca.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/cs.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/cy.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/da.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/de.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/el.js  |    6 +-
 .../Plugins/quicktable/lang/en-au.js          |    6 +-
 .../Plugins/quicktable/lang/en-ca.js          |    6 +-
 .../Plugins/quicktable/lang/en-gb.js          |    6 +-
 .../JavaScript/Plugins/quicktable/lang/en.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/eo.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/es.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/et.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/eu.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/fa.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/fi.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/fo.js  |    6 +-
 .../Plugins/quicktable/lang/fr-ca.js          |    4 +-
 .../JavaScript/Plugins/quicktable/lang/fr.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/gl.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/gu.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/he.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/hi.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/hr.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/hu.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/id.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/is.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/it.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ja.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ka.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/km.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ko.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ku.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/lt.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/lv.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/mk.js  |    4 +-
 .../JavaScript/Plugins/quicktable/lang/mn.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ms.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/nb.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/nl.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/no.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/pl.js  |    6 +-
 .../Plugins/quicktable/lang/pt-br.js          |    6 +-
 .../JavaScript/Plugins/quicktable/lang/pt.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ro.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ru.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/si.js  |    4 +-
 .../JavaScript/Plugins/quicktable/lang/sk.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/sl.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/sq.js  |    4 +-
 .../Plugins/quicktable/lang/sr-latn.js        |    6 +-
 .../JavaScript/Plugins/quicktable/lang/sr.js  |    4 +-
 .../JavaScript/Plugins/quicktable/lang/sv.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/th.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/tr.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/tt.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/ug.js  |    6 +-
 .../JavaScript/Plugins/quicktable/lang/uk.js  |    4 +-
 .../JavaScript/Plugins/quicktable/lang/vi.js  |    4 +-
 .../Plugins/quicktable/lang/zh-cn.js          |    4 +-
 .../JavaScript/Plugins/quicktable/lang/zh.js  |    4 +-
 .../JavaScript/Plugins/quicktable/plugin.js   |  373 +-
 .../Public/JavaScript/Plugins/typo3link.js    |  272 +-
 .../Public/JavaScript/RteLinkBrowser.js       |  168 +-
 .../Public/JavaScript/PageBrowser.js          |   16 +-
 .../Resources/Public/JavaScript/Scheduler.js  |  347 +-
 .../Resources/Public/JavaScript/ActionTask.js |   32 +-
 .../JavaScript/Addon/Hint/CompletionResult.js |  188 +-
 .../JavaScript/Addon/Hint/TsCodeCompletion.js |  306 +-
 .../Public/JavaScript/Addon/Hint/TsParser.js  |  999 ++--
 .../Public/JavaScript/Addon/Hint/TsRef.js     |  296 +-
 .../JavaScript/Addon/Hint/TypoScriptHint.js   |  202 +-
 .../JavaScript/Mode/typoscript/typoscript.js  | 3648 +++++++-------
 .../Resources/Public/JavaScript/Taskcenter.js |  146 +-
 .../Public/JavaScript/ConstantEditor.js       |  148 +-
 .../JavaScript/TypoScriptObjectBrowser.js     |   26 +-
 .../Resources/Public/JavaScript/Main.js       |  500 +-
 .../Resources/Public/JavaScript/Backend.js    | 2379 ++++-----
 .../Resources/Public/JavaScript/Preview.js    |  570 +--
 .../JavaScript/Toolbar/WorkspacesMenu.js      |  304 +-
 .../Resources/Public/JavaScript/Workspaces.js |  411 +-
 222 files changed, 39117 insertions(+), 38811 deletions(-)

diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js b/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
index 9139034bef89..c60162cc3298 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/AjaxDataHandler.js
@@ -16,252 +16,252 @@
  * AjaxDataHandler - Javascript functions to work with AJAX and interacting with tce_db.php
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/Notification',
-		'TYPO3/CMS/Backend/Severity'
-	   ], function ($, Modal, Icons, Notification, Severity) {
-	'use strict';
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Severity'
+], function($, Modal, Icons, Notification, Severity) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{identifier: {hide: string, delete: string, icon: string}}}
-	 * @exports TYPO3/CMS/Backend/AjaxDataHandler
-	 */
-	var AjaxDataHandler = {
-		identifier: {
-			hide: '.t3js-record-hide',
-			delete: '.t3js-record-delete',
-			icon: '.t3js-icon'
-		}
-	};
+  /**
+   *
+   * @type {{identifier: {hide: string, delete: string, icon: string}}}
+   * @exports TYPO3/CMS/Backend/AjaxDataHandler
+   */
+  var AjaxDataHandler = {
+    identifier: {
+      hide: '.t3js-record-hide',
+      delete: '.t3js-record-delete',
+      icon: '.t3js-icon'
+    }
+  };
 
-	/**
-	 * generic function to call from the outside the script and validate directly showing errors
-	 *
-	 * @param {Object} parameters
-	 * @return {Promise<Object>} a jQuery deferred object (promise)
-	 */
-	AjaxDataHandler.process = function(parameters) {
-		return AjaxDataHandler._call(parameters).done(function(result) {
-			if (result.hasErrors) {
-				AjaxDataHandler.handleErrors(result);
-			}
-		});
-	};
+  /**
+   * generic function to call from the outside the script and validate directly showing errors
+   *
+   * @param {Object} parameters
+   * @return {Promise<Object>} a jQuery deferred object (promise)
+   */
+  AjaxDataHandler.process = function(parameters) {
+    return AjaxDataHandler._call(parameters).done(function(result) {
+      if (result.hasErrors) {
+        AjaxDataHandler.handleErrors(result);
+      }
+    });
+  };
 
-	/**
-	 *
-	 */
-	AjaxDataHandler.initialize = function() {
+  /**
+   *
+   */
+  AjaxDataHandler.initialize = function() {
 
-		// HIDE/UNHIDE: click events for all action icons to hide/unhide
-		$(document).on('click', AjaxDataHandler.identifier.hide, function(evt) {
-			evt.preventDefault();
-			var $anchorElement   = $(this);
-			var $iconElement     = $anchorElement.find(AjaxDataHandler.identifier.icon);
-			var $rowElement      = $anchorElement.closest('tr[data-uid]');
-			var params           = $anchorElement.data('params');
+    // HIDE/UNHIDE: click events for all action icons to hide/unhide
+    $(document).on('click', AjaxDataHandler.identifier.hide, function(evt) {
+      evt.preventDefault();
+      var $anchorElement = $(this);
+      var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
+      var $rowElement = $anchorElement.closest('tr[data-uid]');
+      var params = $anchorElement.data('params');
 
-			// add a spinner
-			AjaxDataHandler._showSpinnerIcon($iconElement);
+      // add a spinner
+      AjaxDataHandler._showSpinnerIcon($iconElement);
 
-			// make the AJAX call to toggle the visibility
-			AjaxDataHandler._call(params).done(function(result) {
-				// print messages on errors
-				if (result.hasErrors) {
-					AjaxDataHandler.handleErrors(result);
-				} else {
-					// adjust overlay icon
-					AjaxDataHandler.toggleRow($rowElement);
-				}
-			});
-		});
+      // make the AJAX call to toggle the visibility
+      AjaxDataHandler._call(params).done(function(result) {
+        // print messages on errors
+        if (result.hasErrors) {
+          AjaxDataHandler.handleErrors(result);
+        } else {
+          // adjust overlay icon
+          AjaxDataHandler.toggleRow($rowElement);
+        }
+      });
+    });
 
-		// DELETE: click events for all action icons to delete
-		$(document).on('click', AjaxDataHandler.identifier.delete, function(evt) {
-			evt.preventDefault();
-			var $anchorElement = $(this);
-			var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), Severity.warning, [
-				{
-					text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'cancel'
-				},
-				{
-					text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
-					btnClass: 'btn-warning',
-					name: 'delete'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'cancel') {
-					Modal.dismiss();
-				} else if (e.target.name === 'delete') {
-					Modal.dismiss();
-					AjaxDataHandler.deleteRecord($anchorElement);
-				}
-			});
-		});
-	};
+    // DELETE: click events for all action icons to delete
+    $(document).on('click', AjaxDataHandler.identifier.delete, function(evt) {
+      evt.preventDefault();
+      var $anchorElement = $(this);
+      var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('message'), Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
+          btnClass: 'btn-warning',
+          name: 'delete'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'cancel') {
+          Modal.dismiss();
+        } else if (e.target.name === 'delete') {
+          Modal.dismiss();
+          AjaxDataHandler.deleteRecord($anchorElement);
+        }
+      });
+    });
+  };
 
-	/**
-	 * Toggle row visibility after record has been changed
-	 *
-	 * @param {Object} $rowElement
-	 */
-	AjaxDataHandler.toggleRow = function($rowElement) {
-		var $anchorElement = $rowElement.find(AjaxDataHandler.identifier.hide);
-		var table = $anchorElement.closest('table[data-table]').data('table');
-		var params = $anchorElement.data('params');
-		var nextParams, nextState, iconName;
+  /**
+   * Toggle row visibility after record has been changed
+   *
+   * @param {Object} $rowElement
+   */
+  AjaxDataHandler.toggleRow = function($rowElement) {
+    var $anchorElement = $rowElement.find(AjaxDataHandler.identifier.hide);
+    var table = $anchorElement.closest('table[data-table]').data('table');
+    var params = $anchorElement.data('params');
+    var nextParams, nextState, iconName;
 
-		if ($anchorElement.data('state') === 'hidden') {
-			nextState = 'visible';
-			nextParams = params.replace('=0', '=1');
-			iconName = 'actions-edit-hide';
-		} else {
-			nextState = 'hidden';
-			nextParams = params.replace('=1', '=0');
-			iconName = 'actions-edit-unhide';
-		}
-		$anchorElement.data('state', nextState).data('params', nextParams);
+    if ($anchorElement.data('state') === 'hidden') {
+      nextState = 'visible';
+      nextParams = params.replace('=0', '=1');
+      iconName = 'actions-edit-hide';
+    } else {
+      nextState = 'hidden';
+      nextParams = params.replace('=1', '=0');
+      iconName = 'actions-edit-unhide';
+    }
+    $anchorElement.data('state', nextState).data('params', nextParams);
 
-		// Update tooltip title
-		$anchorElement.tooltip('hide').one('hidden.bs.tooltip', function() {
-			var nextTitle = $anchorElement.data('toggleTitle');
-			// Bootstrap Tooltip internally uses only .attr('data-original-title')
-			$anchorElement
-				.data('toggleTitle', $anchorElement.attr('data-original-title'))
-				.attr('data-original-title', nextTitle)
-				.tooltip('show');
-		});
+    // Update tooltip title
+    $anchorElement.tooltip('hide').one('hidden.bs.tooltip', function() {
+      var nextTitle = $anchorElement.data('toggleTitle');
+      // Bootstrap Tooltip internally uses only .attr('data-original-title')
+      $anchorElement
+        .data('toggleTitle', $anchorElement.attr('data-original-title'))
+        .attr('data-original-title', nextTitle)
+        .tooltip('show');
+    });
 
-		var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
-		Icons.getIcon(iconName, Icons.sizes.small).done(function(icon) {
-			$iconElement.replaceWith(icon);
-		});
+    var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
+    Icons.getIcon(iconName, Icons.sizes.small).done(function(icon) {
+      $iconElement.replaceWith(icon);
+    });
 
-		// Set overlay for the record icon
-		var $recordIcon = $rowElement.find('.col-icon ' + AjaxDataHandler.identifier.icon);
-		if (nextState === 'hidden') {
-			Icons.getIcon('miscellaneous-placeholder', Icons.sizes.small, 'overlay-hidden').done(function(icon) {
-				$recordIcon.append($(icon).find('.icon-overlay'));
-			});
-		} else {
-			$recordIcon.find('.icon-overlay').remove();
-		}
+    // Set overlay for the record icon
+    var $recordIcon = $rowElement.find('.col-icon ' + AjaxDataHandler.identifier.icon);
+    if (nextState === 'hidden') {
+      Icons.getIcon('miscellaneous-placeholder', Icons.sizes.small, 'overlay-hidden').done(function(icon) {
+        $recordIcon.append($(icon).find('.icon-overlay'));
+      });
+    } else {
+      $recordIcon.find('.icon-overlay').remove();
+    }
 
-		$rowElement.fadeTo('fast', 0.4, function() {
-			$rowElement.fadeTo('fast', 1);
-		});
-		if (table === 'pages') {
-			AjaxDataHandler.refreshPageTree();
-		}
-	};
+    $rowElement.fadeTo('fast', 0.4, function() {
+      $rowElement.fadeTo('fast', 1);
+    });
+    if (table === 'pages') {
+      AjaxDataHandler.refreshPageTree();
+    }
+  };
 
-	/**
-	 * delete record by given element (icon in table)
-	 * don't call it directly!
-	 *
-	 * @param {HTMLElement} element
-	 */
-	AjaxDataHandler.deleteRecord = function(element) {
-		var $anchorElement = $(element);
-		var params = $anchorElement.data('params');
-		var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
+  /**
+   * delete record by given element (icon in table)
+   * don't call it directly!
+   *
+   * @param {HTMLElement} element
+   */
+  AjaxDataHandler.deleteRecord = function(element) {
+    var $anchorElement = $(element);
+    var params = $anchorElement.data('params');
+    var $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
 
-		// add a spinner
-		AjaxDataHandler._showSpinnerIcon($iconElement);
+    // add a spinner
+    AjaxDataHandler._showSpinnerIcon($iconElement);
 
-		// make the AJAX call to toggle the visibility
-		AjaxDataHandler._call(params).done(function(result) {
-			// revert to the old class
-			Icons.getIcon('actions-edit-delete', Icons.sizes.small).done(function(icon) {
-				$iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
-				$iconElement.replaceWith(icon);
-			});
-			// print messages on errors
-			if (result.hasErrors) {
-				AjaxDataHandler.handleErrors(result);
-			} else {
-				var $table = $anchorElement.closest('table[data-table]');
-				var $panel = $anchorElement.closest('.panel');
-				var $panelHeading = $panel.find('.panel-heading');
-				var table = $table.data('table');
-				var $rowElements = $anchorElement.closest('tr[data-uid]');
-				var uid = $rowElements.data('uid');
-				var $translatedRowElements = $table.find('[data-l10nparent=' + uid + ']').closest('tr[data-uid]');
-				$rowElements = $rowElements.add($translatedRowElements);
+    // make the AJAX call to toggle the visibility
+    AjaxDataHandler._call(params).done(function(result) {
+      // revert to the old class
+      Icons.getIcon('actions-edit-delete', Icons.sizes.small).done(function(icon) {
+        $iconElement = $anchorElement.find(AjaxDataHandler.identifier.icon);
+        $iconElement.replaceWith(icon);
+      });
+      // print messages on errors
+      if (result.hasErrors) {
+        AjaxDataHandler.handleErrors(result);
+      } else {
+        var $table = $anchorElement.closest('table[data-table]');
+        var $panel = $anchorElement.closest('.panel');
+        var $panelHeading = $panel.find('.panel-heading');
+        var table = $table.data('table');
+        var $rowElements = $anchorElement.closest('tr[data-uid]');
+        var uid = $rowElements.data('uid');
+        var $translatedRowElements = $table.find('[data-l10nparent=' + uid + ']').closest('tr[data-uid]');
+        $rowElements = $rowElements.add($translatedRowElements);
 
-				$rowElements.fadeTo('slow', 0.4, function() {
-					$rowElements.slideUp('slow', 0, function() {
-						$rowElements.remove();
-						if ($table.find('tbody tr').length === 0) {
-							$panel.slideUp('slow');
-						}
-					});
-				});
-				if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') {
-					var count = Number($panelHeading.find('.t3js-table-total-items').html());
-					$panelHeading.find('.t3js-table-total-items').html(count-1);
-				}
+        $rowElements.fadeTo('slow', 0.4, function() {
+          $rowElements.slideUp('slow', 0, function() {
+            $rowElements.remove();
+            if ($table.find('tbody tr').length === 0) {
+              $panel.slideUp('slow');
+            }
+          });
+        });
+        if ($anchorElement.data('l10parent') === '0' || $anchorElement.data('l10parent') === '') {
+          var count = Number($panelHeading.find('.t3js-table-total-items').html());
+          $panelHeading.find('.t3js-table-total-items').html(count - 1);
+        }
 
-				if (table === 'pages') {
-					AjaxDataHandler.refreshPageTree();
-				}
-			}
-		});
-	};
+        if (table === 'pages') {
+          AjaxDataHandler.refreshPageTree();
+        }
+      }
+    });
+  };
 
-	/**
-	 * handle the errors from result object
-	 *
-	 * @param {Object} result
-	 * @private
-	 */
-	AjaxDataHandler.handleErrors = function(result) {
-		$.each(result.messages, function(position, message) {
-			Notification.error(message.title, message.message);
-		});
-	};
+  /**
+   * handle the errors from result object
+   *
+   * @param {Object} result
+   * @private
+   */
+  AjaxDataHandler.handleErrors = function(result) {
+    $.each(result.messages, function(position, message) {
+      Notification.error(message.title, message.message);
+    });
+  };
 
-	/**
-	 * refresh the page tree
-	 * @private
-	 */
-	AjaxDataHandler.refreshPageTree = function() {
-		if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
-			top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-		}
-	};
+  /**
+   * refresh the page tree
+   * @private
+   */
+  AjaxDataHandler.refreshPageTree = function() {
+    if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
+      top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+    }
+  };
 
-	/**
-	 * AJAX call to tce_db.php
-	 * returns a jQuery Promise to work with
-	 *
-	 * @param {Object} params
-	 * @returns {Object}
-	 * @private
-	 */
-	AjaxDataHandler._call = function(params) {
-		return $.getJSON(TYPO3.settings.ajaxUrls['record_process'], params);
-	};
+  /**
+   * AJAX call to tce_db.php
+   * returns a jQuery Promise to work with
+   *
+   * @param {Object} params
+   * @returns {Object}
+   * @private
+   */
+  AjaxDataHandler._call = function(params) {
+    return $.getJSON(TYPO3.settings.ajaxUrls['record_process'], params);
+  };
 
-	/**
-	 * Replace the given icon with a spinner icon
-	 *
-	 * @param {Object} $iconElement
-	 * @private
-	 */
-	AjaxDataHandler._showSpinnerIcon = function($iconElement) {
-		Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icon) {
-			$iconElement.replaceWith(icon);
-		});
-	};
+  /**
+   * Replace the given icon with a spinner icon
+   *
+   * @param {Object} $iconElement
+   * @private
+   */
+  AjaxDataHandler._showSpinnerIcon = function($iconElement) {
+    Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(icon) {
+      $iconElement.replaceWith(icon);
+    });
+  };
 
-	$(AjaxDataHandler.initialize);
+  $(AjaxDataHandler.initialize);
 
-	return AjaxDataHandler;
+  return AjaxDataHandler;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js
index e1ca31e9511e..0b4dc8bfb06f 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenu.js
@@ -16,308 +16,308 @@
  * Javascript container used to load the context menu via AJAX
  * to render the result in a layer next to the mouse cursor
  */
-define(['jquery', 'TYPO3/CMS/Backend/ContextMenuActions'], function ($, ContextMenuActions) {
-
-    /**
-     *
-     * @type {{mousePos: {X: null, Y: null}, delayContextMenuHide: boolean}}
-     * @exports TYPO3/CMS/Backend/ContextMenu
-     */
-    var ContextMenu = {
-        mousePos: {
-            X: null,
-            Y: null
-        },
-        delayContextMenuHide: false,
-        record: {
-            uid: null,
-            table: null
+define(['jquery', 'TYPO3/CMS/Backend/ContextMenuActions'], function($, ContextMenuActions) {
+
+  /**
+   *
+   * @type {{mousePos: {X: null, Y: null}, delayContextMenuHide: boolean}}
+   * @exports TYPO3/CMS/Backend/ContextMenu
+   */
+  var ContextMenu = {
+    mousePos: {
+      X: null,
+      Y: null
+    },
+    delayContextMenuHide: false,
+    record: {
+      uid: null,
+      table: null
+    }
+  };
+
+  /**
+   * Initialize events
+   */
+  ContextMenu.initializeEvents = function() {
+    $(document).on('click contextmenu', '.t3js-contextmenutrigger', function(event) {
+      // if there is an other "inline" onclick setting, context menu is not triggered
+      // usually this is the case for the foldertree
+      if ($(this).prop('onclick') && event.type === 'click') {
+        return;
+      }
+      event.preventDefault();
+      ContextMenu.show(
+        $(this).data('table'),
+        $(this).data('uid'),
+        $(this).data('context'),
+        $(this).data('iteminfo'),
+        $(this).data('parameters')
+      );
+    });
+
+    // register mouse movement inside the document
+    $(document).on('mousemove', ContextMenu.storeMousePositionEvent);
+  };
+
+  /**
+   * Main function, called from most context menu links
+   *
+   * @param {String} table Table from where info should be fetched
+   * @param {(String|Number)} uid The UID of the item
+   * @param {String} context Context of the item
+   * @param {String} enDisItems Items to disable / enable
+   * @param {String} addParams Additional params
+   * @return void
+   */
+  ContextMenu.show = function(table, uid, context, enDisItems, addParams) {
+    ContextMenu.record = null;
+    ContextMenu.record = {table: table, uid: uid};
+
+    var parameters = '';
+
+    if (typeof table !== 'undefined') {
+      parameters += 'table=' + encodeURIComponent(table);
+    }
+    if (typeof uid !== 'undefined') {
+      parameters += (parameters.length > 0 ? '&' : '') + 'uid=' + uid;
+    }
+    if (typeof context !== 'undefined') {
+      parameters += (parameters.length > 0 ? '&' : '') + 'context=' + context;
+    }
+    if (typeof enDisItems !== 'undefined') {
+      parameters += (parameters.length > 0 ? '&' : '') + 'enDisItems=' + enDisItems;
+    }
+    if (typeof addParams !== 'undefined') {
+      parameters += (parameters.length > 0 ? '&' : '') + 'addParams=' + addParams;
+    }
+    this.fetch(parameters);
+  };
+
+  /**
+   * Make the AJAX request
+   *
+   * @param {array} parameters Parameters sent to the server
+   * @return void
+   */
+  ContextMenu.fetch = function(parameters) {
+    var url = TYPO3.settings.ajaxUrls['contextmenu'];
+    if (parameters) {
+      url += ((url.indexOf('?') == -1) ? '?' : '&') + parameters;
+    }
+    $.ajax(url).done(function(response) {
+      if (typeof response !== "undefined" && Object.keys(response).length > 0) {
+        ContextMenu.populateData(response, 0);
+      }
+    });
+  };
+
+  /**
+   * fills the context menu with content and displays it correctly
+   * depending on the mouse position
+   *
+   * @param {array} items The data that will be put in the menu
+   * @param {Number} level The depth of the context menu
+   */
+  ContextMenu.populateData = function(items, level) {
+    this.initializeContextMenuContainer();
+
+    level = parseInt(level, 10) || 0;
+    var $obj = $('#contentMenu' + level);
+
+    if ($obj.length && (level === 0 || $('#contentMenu' + (level - 1)).is(':visible'))) {
+      var elements = ContextMenu.drawMenu(items, level);
+      $obj.html('<div class="list-group">' + elements + '</div>');
+
+      $('a.list-group-item', $obj).click(function(event) {
+        event.preventDefault();
+
+        if ($(this).hasClass('list-group-item-submenu')) {
+          ContextMenu.openSubmenu(level, $(this));
+          return;
         }
-    };
-
-    /**
-     * Initialize events
-     */
-    ContextMenu.initializeEvents = function () {
-        $(document).on('click contextmenu', '.t3js-contextmenutrigger', function (event) {
-            // if there is an other "inline" onclick setting, context menu is not triggered
-            // usually this is the case for the foldertree
-            if ($(this).prop('onclick') && event.type === 'click') {
-                return;
-            }
-            event.preventDefault();
-            ContextMenu.show(
-                $(this).data('table'),
-                $(this).data('uid'),
-                $(this).data('context'),
-                $(this).data('iteminfo'),
-                $(this).data('parameters')
-            );
-        });
-
-        // register mouse movement inside the document
-        $(document).on('mousemove', ContextMenu.storeMousePositionEvent);
-    };
-
-    /**
-     * Main function, called from most context menu links
-     *
-     * @param {String} table Table from where info should be fetched
-     * @param {(String|Number)} uid The UID of the item
-     * @param {String} context Context of the item
-     * @param {String} enDisItems Items to disable / enable
-     * @param {String} addParams Additional params
-     * @return void
-     */
-    ContextMenu.show = function (table, uid, context, enDisItems, addParams) {
-        ContextMenu.record = null;
-        ContextMenu.record = {table: table, uid: uid};
-
-        var parameters = '';
-
-        if (typeof table !== 'undefined') {
-            parameters += 'table=' + encodeURIComponent(table);
-        }
-        if (typeof uid !== 'undefined') {
-            parameters += (parameters.length > 0 ? '&' : '') + 'uid=' + uid;
-        }
-        if (typeof context !== 'undefined') {
-            parameters += (parameters.length > 0 ? '&' : '') + 'context=' + context;
-        }
-        if (typeof enDisItems !== 'undefined') {
-            parameters += (parameters.length > 0 ? '&' : '') + 'enDisItems=' + enDisItems;
-        }
-        if (typeof addParams !== 'undefined') {
-            parameters += (parameters.length > 0 ? '&' : '') + 'addParams=' + addParams;
-        }
-        this.fetch(parameters);
-    };
 
-    /**
-     * Make the AJAX request
-     *
-     * @param {array} parameters Parameters sent to the server
-     * @return void
-     */
-    ContextMenu.fetch = function (parameters) {
-        var url = TYPO3.settings.ajaxUrls['contextmenu'];
-        if (parameters) {
-            url += ((url.indexOf('?') == -1) ? '?' : '&') + parameters;
+        var callbackName = $(this).data('callback-action');
+        var callbackModule = $(this).data('callback-module');
+        var clickItem = $(this);
+        if (callbackModule) {
+          require([callbackModule], function(callbackModule) {
+            callbackModule[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid);
+          });
+        } else if (ContextMenuActions && ContextMenuActions[callbackName]) {
+          ContextMenuActions[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid);
+        } else {
+          console.log('action: ' + callbackName + ' not found');
         }
-        $.ajax(url).done(function (response) {
-            if (typeof response !== "undefined" && Object.keys(response).length > 0) {
-                ContextMenu.populateData(response, 0);
-            }
-        });
+        ContextMenu.hideAll();
+      });
+
+      $obj.css(ContextMenu.getPosition($obj)).show();
+    }
+  };
+
+  ContextMenu.openSubmenu = function(level, $item) {
+    var $obj = $('#contentMenu' + (level + 1)).html('');
+    $item.next().find('.list-group').clone(true).appendTo($obj);
+    $obj.css(ContextMenu.getPosition($obj)).show();
+  };
+
+  ContextMenu.getPosition = function($obj) {
+    var x = this.mousePos.X;
+    var y = this.mousePos.Y;
+    var dimsWindow = {
+      width: $(window).width() - 20, // saving margin for scrollbars
+      height: $(window).height()
     };
 
-    /**
-     * fills the context menu with content and displays it correctly
-     * depending on the mouse position
-     *
-     * @param {array} items The data that will be put in the menu
-     * @param {Number} level The depth of the context menu
-     */
-    ContextMenu.populateData = function (items, level) {
-        this.initializeContextMenuContainer();
-
-        level = parseInt(level, 10) || 0;
-        var $obj = $('#contentMenu' + level);
-
-        if ($obj.length && (level === 0 || $('#contentMenu' + (level - 1)).is(':visible'))) {
-            var elements = ContextMenu.drawMenu(items, level);
-            $obj.html('<div class="list-group">' + elements + '</div>');
-
-            $('a.list-group-item', $obj).click(function (event) {
-                event.preventDefault();
-
-                if ($(this).hasClass('list-group-item-submenu')) {
-                    ContextMenu.openSubmenu(level, $(this));
-                    return;
-                }
-
-                var callbackName = $(this).data('callback-action');
-                var callbackModule = $(this).data('callback-module');
-                var clickItem = $(this);
-                if (callbackModule) {
-                    require([callbackModule], function (callbackModule) {
-                        callbackModule[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid);
-                    });
-                } else if (ContextMenuActions && ContextMenuActions[callbackName]) {
-                    ContextMenuActions[callbackName].bind(clickItem)(ContextMenu.record.table, ContextMenu.record.uid);
-                } else {
-                    console.log('action: ' + callbackName + ' not found');
-                }
-                ContextMenu.hideAll();
-            });
-
-            $obj.css(ContextMenu.getPosition($obj)).show();
-        }
+    // dimensions for the context menu
+    var dims = {
+      width: $obj.width(),
+      height: $obj.height()
     };
 
-    ContextMenu.openSubmenu = function (level, $item) {
-        var $obj = $('#contentMenu' + (level + 1)).html('');
-        $item.next().find('.list-group').clone(true).appendTo($obj);
-        $obj.css(ContextMenu.getPosition($obj)).show();
+    var relative = {
+      X: this.mousePos.X - $(document).scrollLeft(),
+      Y: this.mousePos.Y - $(document).scrollTop()
     };
 
-    ContextMenu.getPosition = function ($obj) {
-        var x = this.mousePos.X;
-        var y = this.mousePos.Y;
-        var dimsWindow = {
-            width: $(window).width() - 20, // saving margin for scrollbars
-            height: $(window).height()
-        };
-
-        // dimensions for the context menu
-        var dims = {
-            width: $obj.width(),
-            height: $obj.height()
-        };
-
-        var relative = {
-            X: this.mousePos.X - $(document).scrollLeft(),
-            Y: this.mousePos.Y - $(document).scrollTop()
-        };
-
-        // adjusting the Y position of the layer to fit it into the window frame
-        // if there is enough space above then put it upwards,
-        // otherwise adjust it to the bottom of the window
-        if (dimsWindow.height - dims.height < relative.Y) {
-            if (relative.Y > dims.height) {
-                y -= (dims.height - 10);
-            } else {
-                y += (dimsWindow.height - dims.height - relative.Y);
-            }
-        }
-        // adjusting the X position like Y above, but align it to the left side of the viewport if it does not fit completely
-        if (dimsWindow.width - dims.width < relative.X) {
-            if (relative.X > dims.width) {
-                x -= (dims.width - 10);
-            } else if ((dimsWindow.width - dims.width - relative.X) < $(document).scrollLeft()) {
-                x = $(document).scrollLeft();
-            } else {
-                x += (dimsWindow.width - dims.width - relative.X);
-            }
-        }
-        return {left: x + 'px', top: y + 'px'};
-    };
-
-    /**
-     * fills the context menu with content and displays it correctly
-     * depending on the mouse position
-     *
-     * @param {array} items The data that will be put in the menu
-     * @param {Number} level The depth of the context menu
-     */
-    ContextMenu.drawMenu = function (items, level) {
-        var elements = '';
-        $.each(items, function (key, value) {
-            if (value.type === 'item') {
-                elements += ContextMenu.drawActionItem(value);
-            } else if (value.type === 'divider') {
-                elements += '<a class="list-group-item list-group-item-divider"></a>';
-            } else if (value.type === 'submenu' || value.childItems) {
-                elements += '<a class="list-group-item list-group-item-submenu"><span class="list-group-item-icon">' + value.icon + '</span> ' + value.label + '&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;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js
index 4d45bf34ccb3..236170632db3 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ContextMenuActions.js
@@ -15,233 +15,233 @@
  * Module: TYPO3/CMS/Backend/ContextMenuActions
  * Click menu actions for db records including tt_content and pages
  */
-define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) {
-    /**
-     *
-     * @exports TYPO3/CMS/Backend/ContextMenuActions
-     */
-    var ContextMenuActions = {};
-
-    ContextMenuActions.getReturnUrl = function () {
-       return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
-    };
-
-    ContextMenuActions.editRecord = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][' + uid + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.viewRecord = function (table, uid) {
-        var $viewUrl = $(this).data('preview-url');
-        if ($viewUrl) {
-            var previewWin = window.open($viewUrl, 'newTYPO3frontendWindow');
-            previewWin.focus();
-        }
-    };
-
-    ContextMenuActions.openInfoPopUp = function (table, uid) {
-        top.launchView(table, uid);
-    };
-
-    ContextMenuActions.mountAsTreeRoot = function (table, uid) {
-      if (table === 'pages') {
-        top.TYPO3.Backend.NavigationContainer.PageTree.setTemporaryMountPoint(uid);
-      }
-    };
-
-    ContextMenuActions.newPageWizard = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.NewRecord.moduleUrl + '&id=' + uid + '&pagesOnly=1&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.newContentWizard = function (table, uid) {
-        var $wizardUrl = $(this).data('new-wizard-url');
-        if ($wizardUrl) {
-            $wizardUrl += '&returnUrl='+ ContextMenuActions.getReturnUrl();
-            top.TYPO3.Backend.ContentContainer.setUrl($wizardUrl);
+define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) {
+  /**
+   *
+   * @exports TYPO3/CMS/Backend/ContextMenuActions
+   */
+  var ContextMenuActions = {};
+
+  ContextMenuActions.getReturnUrl = function() {
+    return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
+  };
+
+  ContextMenuActions.editRecord = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][' + uid + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.viewRecord = function(table, uid) {
+    var $viewUrl = $(this).data('preview-url');
+    if ($viewUrl) {
+      var previewWin = window.open($viewUrl, 'newTYPO3frontendWindow');
+      previewWin.focus();
+    }
+  };
+
+  ContextMenuActions.openInfoPopUp = function(table, uid) {
+    top.launchView(table, uid);
+  };
+
+  ContextMenuActions.mountAsTreeRoot = function(table, uid) {
+    if (table === 'pages') {
+      top.TYPO3.Backend.NavigationContainer.PageTree.setTemporaryMountPoint(uid);
+    }
+  };
+
+  ContextMenuActions.newPageWizard = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.NewRecord.moduleUrl + '&id=' + uid + '&pagesOnly=1&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.newContentWizard = function(table, uid) {
+    var $wizardUrl = $(this).data('new-wizard-url');
+    if ($wizardUrl) {
+      $wizardUrl += '&returnUrl=' + ContextMenuActions.getReturnUrl();
+      top.TYPO3.Backend.ContentContainer.setUrl($wizardUrl);
+    }
+  };
+
+  ContextMenuActions.newRecord = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][-' + uid + ']=new&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.openHistoryPopUp = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.RecordHistory.moduleUrl + '&element=' + table + ':' + uid + '&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.openListModule = function(table, uid) {
+    var pageId = table === 'pages' ? uid : $(this).data('page-uid');
+    top.TYPO3.ModuleMenu.App.showModule('web_list', 'id='.pageId);
+  };
+
+  ContextMenuActions.pagesSort = function(table, uid) {
+    var pagesSortUrl = $(this).data('pages-sort-url');
+    if (pagesSortUrl) {
+      top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl);
+    }
+  };
+
+  ContextMenuActions.pagesNewMultiple = function(table, uid) {
+    var pagesSortUrl = $(this).data('pages-new-multiple-url');
+    if (pagesSortUrl) {
+      top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl);
+    }
+  };
+
+  ContextMenuActions.disableRecord = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&redirect=' + ContextMenuActions.getReturnUrl()
+    ).done(function() {
+      top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+    });
+  };
+
+  ContextMenuActions.enableRecord = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=0&redirect=' + ContextMenuActions.getReturnUrl()
+    ).done(function() {
+      top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+    });
+  };
+
+  ContextMenuActions.deleteRecord = function(table, uid) {
+    var $anchorElement = $(this);
+    var $modal = Modal.confirm(
+      $anchorElement.data('title'),
+      $anchorElement.data('message'),
+      Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
+          btnClass: 'btn-warning',
+          name: 'delete'
         }
-    };
-
-    ContextMenuActions.newRecord = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FormEngine.moduleUrl + '&edit[' + table + '][-' + uid + ']=new&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
+      ]);
 
-    ContextMenuActions.openHistoryPopUp = function (table, uid) {
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'delete') {
         top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.RecordHistory.moduleUrl + '&element=' + table + ':' + uid + '&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.openListModule = function (table, uid) {
-        var pageId = table === 'pages' ? uid : $(this).data('page-uid');
-        top.TYPO3.ModuleMenu.App.showModule('web_list', 'id='.pageId);
-    };
-
-    ContextMenuActions.pagesSort = function (table, uid) {
-        var pagesSortUrl = $(this).data('pages-sort-url');
-        if (pagesSortUrl) {
-            top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl);
-        }
-    };
-
-    ContextMenuActions.pagesNewMultiple = function (table, uid) {
-        var pagesSortUrl = $(this).data('pages-new-multiple-url');
-        if (pagesSortUrl) {
-            top.TYPO3.Backend.ContentContainer.setUrl(pagesSortUrl);
-        }
-    };
-
-    ContextMenuActions.disableRecord = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=1&redirect=' + ContextMenuActions.getReturnUrl()
-        ).done(function () {
-          top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+          top.TYPO3.settings.RecordCommit.moduleUrl + '&redirect=' + ContextMenuActions.getReturnUrl() + '&cmd[' + table + '][' + uid + '][delete]=1'
+        ).done(function() {
+          if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
+            top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+          }
         });
-    };
 
-    ContextMenuActions.enableRecord = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.RecordCommit.moduleUrl + '&data[' + table + '][' + uid + '][hidden]=0&redirect=' + ContextMenuActions.getReturnUrl()
-        ).done(function () {
+      }
+      Modal.dismiss();
+    });
+  };
+
+  ContextMenuActions.copy = function(table, uid) {
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][' + table + '%7C' + uid + ']=1' + '&CB[setCopyMode]=1';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.clipboardRelease = function(table, uid) {
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][' + table + '%7C' + uid + ']=0';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.cut = function(table, uid) {
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][' + table + '%7C' + uid + ']=1' + '&CB[setCopyMode]=0';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  /**
+   * Clear cache for given page uid
+   *
+   * @param {string} table pages table
+   * @param {int} uid of the page
+   */
+  ContextMenuActions.clearCache = function(table, uid) {
+    var url = top.TYPO3.settings.WebLayout.moduleUrl;
+    url += '&id=' + uid + '&clear_cache=1';
+    $.ajax(url);
+  };
+
+  /**
+   * Paste db record after another
+   *
+   * @param {string} table any db table except sys_file
+   * @param {int} uid of the record after which record from the cliboard will be pasted
+   */
+  ContextMenuActions.pasteAfter = function(table, uid) {
+    ContextMenuActions.pasteInto.bind($(this))(table, -uid);
+  };
+
+  /**
+   * Paste page into another page
+   *
+   * @param {string} table any db table except sys_file
+   * @param {int} uid of the record after which record from the cliboard will be pasted
+   */
+  ContextMenuActions.pasteInto = function(table, uid) {
+    var $anchorElement = $(this);
+    var title = $anchorElement.data('title');
+    var performPaste = function() {
+      var url = '&CB[paste]=' + table + '%7C' + uid
+        + '&CB[pad]=normal'
+        + '&redirect=' + ContextMenuActions.getReturnUrl();
+
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.RecordCommit.moduleUrl + url
+      ).done(function() {
+        if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
           top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-        });
-    };
-
-    ContextMenuActions.deleteRecord = function (table, uid) {
-        var $anchorElement = $(this);
-        var $modal = Modal.confirm(
-            $anchorElement.data('title'),
-            $anchorElement.data('message'),
-            Severity.warning, [
-                {
-                    text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-                    active: true,
-                    btnClass: 'btn-default',
-                    name: 'cancel'
-                },
-                {
-                    text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
-                    btnClass: 'btn-warning',
-                    name: 'delete'
-                }
-            ]);
-
-        $modal.on('button.clicked', function (e) {
-            if (e.target.name === 'delete') {
-                top.TYPO3.Backend.ContentContainer.setUrl(
-                    top.TYPO3.settings.RecordCommit.moduleUrl + '&redirect=' + ContextMenuActions.getReturnUrl() + '&cmd[' + table + '][' + uid + '][delete]=1'
-                ).done(function () {
-                  if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
-                    top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-                  }
-                });
-
-            }
-            Modal.dismiss();
-        });
-    };
-
-    ContextMenuActions.copy = function (table, uid) {
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][' + table + '%7C' + uid + ']=1'+ '&CB[setCopyMode]=1';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.clipboardRelease = function (table, uid) {
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][' + table + '%7C' + uid + ']=0';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.cut = function (table, uid) {
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][' + table + '%7C' + uid + ']=1'+ '&CB[setCopyMode]=0';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    /**
-     * Clear cache for given page uid
-     *
-     * @param {string} table pages table
-     * @param {int} uid of the page
-     */
-    ContextMenuActions.clearCache = function (table, uid) {
-        var url = top.TYPO3.settings.WebLayout.moduleUrl;
-        url += '&id=' + uid + '&clear_cache=1';
-        $.ajax(url);
-    };
-
-    /**
-     * Paste db record after another
-     *
-     * @param {string} table any db table except sys_file
-     * @param {int} uid of the record after which record from the cliboard will be pasted
-     */
-    ContextMenuActions.pasteAfter = function (table, uid) {
-        ContextMenuActions.pasteInto.bind($(this))(table, -uid);
-    };
-
-    /**
-     * Paste page into another page
-     *
-     * @param {string} table any db table except sys_file
-     * @param {int} uid of the record after which record from the cliboard will be pasted
-     */
-    ContextMenuActions.pasteInto = function (table, uid) {
-        var $anchorElement = $(this);
-        var title = $anchorElement.data('title');
-        var performPaste = function () {
-            var url = '&CB[paste]=' + table + '%7C' + uid
-                + '&CB[pad]=normal'
-                + '&redirect=' + ContextMenuActions.getReturnUrl();
-
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.RecordCommit.moduleUrl + url
-            ).done(function () {
-                if (table === 'pages' && top.TYPO3.Backend.NavigationContainer.PageTree) {
-                  top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-                }
-            });
-        };
-        if (!$anchorElement.data('title')) {
-            performPaste();
-            return;
         }
-        var $modal = Modal.confirm(
-            $anchorElement.data('title'),
-            $anchorElement.data('message'),
-            Severity.warning, [
-                {
-                    text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-                    active: true,
-                    btnClass: 'btn-default',
-                    name: 'cancel'
-                },
-                {
-                    text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
-                    btnClass: 'btn-warning',
-                    name: 'ok'
-                }
-            ]);
-
-        $modal.on('button.clicked', function (e) {
-            if (e.target.name === 'ok') {
-                performPaste();
-            }
-            Modal.dismiss();
-        });
+      });
+    };
+    if (!$anchorElement.data('title')) {
+      performPaste();
+      return;
+    }
+    var $modal = Modal.confirm(
+      $anchorElement.data('title'),
+      $anchorElement.data('message'),
+      Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
+          btnClass: 'btn-warning',
+          name: 'ok'
+        }
+      ]);
 
-    };
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'ok') {
+        performPaste();
+      }
+      Modal.dismiss();
+    });
+
+  };
 
-    return ContextMenuActions;
+  return ContextMenuActions;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js
index 656fc9198115..f3f258bb8093 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/DateTimePicker.js
@@ -17,154 +17,154 @@
  * and EXT:belog and EXT:scheduler
  */
 define(['jquery'], function($) {
-	"use strict";
-
-	/**
-	 * @type {{options: {fieldSelector: string, format: *}}}
-	 * @exports TYPO3/CMS/Backend/DateTimePicker
-	 */
-	var DateTimePicker = {
-		options: {
-			fieldSelector: '.t3js-datetimepicker',
-			format: (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top).TYPO3.settings.DateTimePicker.DateFormat
-		}
-	};
-
-	/**
-	 * initialize date fields to add a datepicker to each field
-	 * note: this function can be called multiple times (e.g. after AJAX requests) because it only
-	 * applies to fields which haven't been used yet.
-	 */
-	DateTimePicker.initialize = function() {
-		// fetch the date time fields that haven't been initialized yet
-		var $dateTimeFields = $(DateTimePicker.options.fieldSelector).filter(function() {
-			return $(this).data('DateTimePicker') === undefined;
-		});
-
-		if ($dateTimeFields.length > 0) {
-			require(['moment', 'TYPO3/CMS/Backend/Storage/Persistent', 'twbs/bootstrap-datetimepicker'], function(moment, PersistentStorage) {
-				var userLocale = PersistentStorage.get('lang');
-				var setLocale = userLocale ? moment.locale(userLocale) : false;
-
-				// initialize the datepicker on each selected element
-				$dateTimeFields.each(function() {
-					DateTimePicker.initializeField(moment, $(this), setLocale);
-				});
-
-				$dateTimeFields.on('blur', function() {
-					var $element = $(this);
-					var $hiddenField = $element.parent().parent().find('input[type=hidden]');
-
-					if ($element.val() === '') {
-						$hiddenField.val('');
-					} else {
-						var type = $element.data('dateType');
-						var format = $element.data('DateTimePicker').format();
-						var date = moment.utc($element.val(), format);
-						if (date.isValid()) {
-							$hiddenField.val(DateTimePicker.formatDateForHiddenField(date, type));
-						} else {
-							$element.val(DateTimePicker.formatDateForHiddenField(moment.utc($hiddenField.val()), type));
-						}
-					}
-				});
-
-				// on datepicker change, write the selected date with the timezone offset to the hidden field
-				$dateTimeFields.on('dp.change', function(evt) {
-					var $element = $(this);
-					var $hiddenField = $element.parent().parent().find('input[type=hidden]');
-					var type = $element.data('dateType');
-					var value = '';
-
-					if ($element.val() !== '') {
-						value = DateTimePicker.formatDateForHiddenField(evt.date.utc(), type);
-					}
-					$hiddenField.val(value);
-
-					$(document).trigger('formengine.dp.change', [$(this)]);
-				});
-			});
-		}
-	};
-
-	/**
-	 * Initialize a single field
-	 *
-	 * @param {moment} moment
-	 * @param {object} $element
-	 * @param {string} locale
-	 */
-	DateTimePicker.initializeField = function(moment, $element, locale) {
-		var format = DateTimePicker.options.format;
-		var type = $element.data('dateType');
-		var options = {
-			sideBySide: true,
-			showTodayButton: true,
-			toolbarPlacement: 'bottom',
-			icons: {
-				time: 'fa fa-clock-o',
-				date: 'fa fa-calendar',
-				up: 'fa fa-chevron-up',
-				down: 'fa fa-chevron-down',
-				previous: 'fa fa-chevron-left',
-				next: 'fa fa-chevron-right',
-				today: 'fa fa-calendar-o',
-				clear: 'fa fa-trash'
-			}
-		};
-
-		// set options based on type
-		switch (type) {
-			case 'datetime':
-				options.format = format[1];
-				break;
-			case 'date':
-				options.format = format[0];
-				break;
-			case 'time':
-				options.format = 'HH:mm';
-				break;
-			case 'timesec':
-				options.format = 'HH:mm:ss';
-				break;
-			case 'year':
-				options.format = 'YYYY';
-				break;
-		}
-
-		// datepicker expects the min and max dates to be formatted with options.format but unix timestamp given
-		if ($element.data('dateMindate')) {
-			$element.data('dateMindate', moment.unix($element.data('dateMindate')).format(options.format));
-		}
-		if ($element.data('dateMaxdate')) {
-			$element.data('dateMaxdate', moment.unix($element.data('dateMaxdate')).format(options.format));
-		}
-
-		if (locale) {
-			options.locale = locale;
-		}
-
-		// initialize the date time picker on this element
-		$element.datetimepicker(options);
-	};
-
-	/**
-	 * Format a given date for the hidden FormEngine field
-	 *
-	 * Format the value for the hidden field that is passed on to the backend, i.e. most likely DataHandler.
-	 * The format for that is the timestamp for time fields, and a full-blown ISO-8601 timestamp for all date-related fields.
-	 *
-	 * @param {moment} date
-	 * @param {string} type Type of the date
-	 * @returns {string}
-	 */
-	DateTimePicker.formatDateForHiddenField = function(date, type) {
-		if (type === 'time' || type === 'timesec') {
-			date.year(1970).month(0).date(1);
-		}
-		return date.format();
-	};
-
-	$(DateTimePicker.initialize);
-	return DateTimePicker;
+  "use strict";
+
+  /**
+   * @type {{options: {fieldSelector: string, format: *}}}
+   * @exports TYPO3/CMS/Backend/DateTimePicker
+   */
+  var DateTimePicker = {
+    options: {
+      fieldSelector: '.t3js-datetimepicker',
+      format: (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top).TYPO3.settings.DateTimePicker.DateFormat
+    }
+  };
+
+  /**
+   * initialize date fields to add a datepicker to each field
+   * note: this function can be called multiple times (e.g. after AJAX requests) because it only
+   * applies to fields which haven't been used yet.
+   */
+  DateTimePicker.initialize = function() {
+    // fetch the date time fields that haven't been initialized yet
+    var $dateTimeFields = $(DateTimePicker.options.fieldSelector).filter(function() {
+      return $(this).data('DateTimePicker') === undefined;
+    });
+
+    if ($dateTimeFields.length > 0) {
+      require(['moment', 'TYPO3/CMS/Backend/Storage/Persistent', 'twbs/bootstrap-datetimepicker'], function(moment, PersistentStorage) {
+        var userLocale = PersistentStorage.get('lang');
+        var setLocale = userLocale ? moment.locale(userLocale) : false;
+
+        // initialize the datepicker on each selected element
+        $dateTimeFields.each(function() {
+          DateTimePicker.initializeField(moment, $(this), setLocale);
+        });
+
+        $dateTimeFields.on('blur', function() {
+          var $element = $(this);
+          var $hiddenField = $element.parent().parent().find('input[type=hidden]');
+
+          if ($element.val() === '') {
+            $hiddenField.val('');
+          } else {
+            var type = $element.data('dateType');
+            var format = $element.data('DateTimePicker').format();
+            var date = moment.utc($element.val(), format);
+            if (date.isValid()) {
+              $hiddenField.val(DateTimePicker.formatDateForHiddenField(date, type));
+            } else {
+              $element.val(DateTimePicker.formatDateForHiddenField(moment.utc($hiddenField.val()), type));
+            }
+          }
+        });
+
+        // on datepicker change, write the selected date with the timezone offset to the hidden field
+        $dateTimeFields.on('dp.change', function(evt) {
+          var $element = $(this);
+          var $hiddenField = $element.parent().parent().find('input[type=hidden]');
+          var type = $element.data('dateType');
+          var value = '';
+
+          if ($element.val() !== '') {
+            value = DateTimePicker.formatDateForHiddenField(evt.date.utc(), type);
+          }
+          $hiddenField.val(value);
+
+          $(document).trigger('formengine.dp.change', [$(this)]);
+        });
+      });
+    }
+  };
+
+  /**
+   * Initialize a single field
+   *
+   * @param {moment} moment
+   * @param {object} $element
+   * @param {string} locale
+   */
+  DateTimePicker.initializeField = function(moment, $element, locale) {
+    var format = DateTimePicker.options.format;
+    var type = $element.data('dateType');
+    var options = {
+      sideBySide: true,
+      showTodayButton: true,
+      toolbarPlacement: 'bottom',
+      icons: {
+        time: 'fa fa-clock-o',
+        date: 'fa fa-calendar',
+        up: 'fa fa-chevron-up',
+        down: 'fa fa-chevron-down',
+        previous: 'fa fa-chevron-left',
+        next: 'fa fa-chevron-right',
+        today: 'fa fa-calendar-o',
+        clear: 'fa fa-trash'
+      }
+    };
+
+    // set options based on type
+    switch (type) {
+      case 'datetime':
+        options.format = format[1];
+        break;
+      case 'date':
+        options.format = format[0];
+        break;
+      case 'time':
+        options.format = 'HH:mm';
+        break;
+      case 'timesec':
+        options.format = 'HH:mm:ss';
+        break;
+      case 'year':
+        options.format = 'YYYY';
+        break;
+    }
+
+    // datepicker expects the min and max dates to be formatted with options.format but unix timestamp given
+    if ($element.data('dateMindate')) {
+      $element.data('dateMindate', moment.unix($element.data('dateMindate')).format(options.format));
+    }
+    if ($element.data('dateMaxdate')) {
+      $element.data('dateMaxdate', moment.unix($element.data('dateMaxdate')).format(options.format));
+    }
+
+    if (locale) {
+      options.locale = locale;
+    }
+
+    // initialize the date time picker on this element
+    $element.datetimepicker(options);
+  };
+
+  /**
+   * Format a given date for the hidden FormEngine field
+   *
+   * Format the value for the hidden field that is passed on to the backend, i.e. most likely DataHandler.
+   * The format for that is the timestamp for time fields, and a full-blown ISO-8601 timestamp for all date-related fields.
+   *
+   * @param {moment} date
+   * @param {string} type Type of the date
+   * @returns {string}
+   */
+  DateTimePicker.formatDateForHiddenField = function(date, type) {
+    if (type === 'time' || type === 'timesec') {
+      date.year(1970).month(0).date(1);
+    }
+    return date.format();
+  };
+
+  $(DateTimePicker.initialize);
+  return DateTimePicker;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js b/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js
index 0840d61ced10..41eb52901893 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/DocumentHeader.js
@@ -16,100 +16,100 @@
  * Calculates the height of the docHeader and hides it upon scrolling
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{$documentHeader: null, $documentHeaderBars: null, $documentHeaderNavigationBar: null, $documentHeaderSearchBar: null, $moduleBody: null, direction: string, reactionRange: number, lastPosition: number, currentPosition: number, changedPosition: number, settings: {margin: number, offset: number, selectors: {moduleDocumentHeader: string, moduleDocheaderBar: string, moduleNavigationBar: string, moduleButtonBar: string, moduleSearchBar: string, moduleBody: string}}}}
-	 * @exports TYPO3/CMS/Backend/DocumentHeader
-	 */
-	var DocumentHeader = {
-		$documentHeader: null,
-		$documentHeaderBars: null,
-		$documentHeaderNavigationBar: null,
-		$documentHeaderSearchBar: null,
-		$moduleBody: null,
-		direction: 'down',
-		reactionRange: 300,
-		lastPosition: 0,
-		currentPosition: 0,
-		changedPosition: 0,
-		settings: {
-			margin: 24,
-			offset: 100,
-			selectors: {
-				moduleDocumentHeader: '.t3js-module-docheader',
-				moduleDocheaderBar: '.t3js-module-docheader-bar',
-				moduleNavigationBar: '.t3js-module-docheader-bar-navigation',
-				moduleButtonBar: '.t3js-module-docheader-bar-buttons',
-				moduleSearchBar: '.t3js-module-docheader-bar-search',
-				moduleBody: '.t3js-module-body'
+  /**
+   *
+   * @type {{$documentHeader: null, $documentHeaderBars: null, $documentHeaderNavigationBar: null, $documentHeaderSearchBar: null, $moduleBody: null, direction: string, reactionRange: number, lastPosition: number, currentPosition: number, changedPosition: number, settings: {margin: number, offset: number, selectors: {moduleDocumentHeader: string, moduleDocheaderBar: string, moduleNavigationBar: string, moduleButtonBar: string, moduleSearchBar: string, moduleBody: string}}}}
+   * @exports TYPO3/CMS/Backend/DocumentHeader
+   */
+  var DocumentHeader = {
+    $documentHeader: null,
+    $documentHeaderBars: null,
+    $documentHeaderNavigationBar: null,
+    $documentHeaderSearchBar: null,
+    $moduleBody: null,
+    direction: 'down',
+    reactionRange: 300,
+    lastPosition: 0,
+    currentPosition: 0,
+    changedPosition: 0,
+    settings: {
+      margin: 24,
+      offset: 100,
+      selectors: {
+        moduleDocumentHeader: '.t3js-module-docheader',
+        moduleDocheaderBar: '.t3js-module-docheader-bar',
+        moduleNavigationBar: '.t3js-module-docheader-bar-navigation',
+        moduleButtonBar: '.t3js-module-docheader-bar-buttons',
+        moduleSearchBar: '.t3js-module-docheader-bar-search',
+        moduleBody: '.t3js-module-body'
 
-			}
-		}
-	};
+      }
+    }
+  };
 
-	/**
-	 * Reposition
-	 */
-	DocumentHeader.reposition = function() {
-		DocumentHeader.$documentHeader.css('height', 'auto');
-		DocumentHeader.$documentHeaderBars.css('height', 'auto');
-		DocumentHeader.$moduleBody.css('padding-top', DocumentHeader.$documentHeader.outerHeight() + DocumentHeader.settings.margin);
-	};
+  /**
+   * Reposition
+   */
+  DocumentHeader.reposition = function() {
+    DocumentHeader.$documentHeader.css('height', 'auto');
+    DocumentHeader.$documentHeaderBars.css('height', 'auto');
+    DocumentHeader.$moduleBody.css('padding-top', DocumentHeader.$documentHeader.outerHeight() + DocumentHeader.settings.margin);
+  };
 
-	/**
-	 * Scroll
-	 */
-	DocumentHeader.scroll = function() {
-		DocumentHeader.currentPosition = $(window).scrollTop();
-		if (DocumentHeader.currentPosition > DocumentHeader.lastPosition) {
-			if (DocumentHeader.direction !== 'down') {
-				DocumentHeader.direction = 'down';
-				DocumentHeader.changedPosition = DocumentHeader.currentPosition;
-			}
-		} else if (DocumentHeader.currentPosition < DocumentHeader.lastPosition) {
-			if (DocumentHeader.direction !== 'up') {
-				DocumentHeader.direction = 'up';
-				DocumentHeader.changedPosition = DocumentHeader.currentPosition;
-			}
-		}
-		if (DocumentHeader.direction === 'up' && (DocumentHeader.changedPosition - DocumentHeader.reactionRange) < DocumentHeader.currentPosition) {
-			DocumentHeader.$documentHeader.css('margin-top', 0);
-		}
-		if (DocumentHeader.direction === 'down' && (DocumentHeader.changedPosition + DocumentHeader.reactionRange) < DocumentHeader.currentPosition) {
-			DocumentHeader.$documentHeader.css('margin-top', (DocumentHeader.$documentHeaderNavigationBar.outerHeight() + 4) * -1);
-		}
-		DocumentHeader.lastPosition = DocumentHeader.currentPosition;
-	};
+  /**
+   * Scroll
+   */
+  DocumentHeader.scroll = function() {
+    DocumentHeader.currentPosition = $(window).scrollTop();
+    if (DocumentHeader.currentPosition > DocumentHeader.lastPosition) {
+      if (DocumentHeader.direction !== 'down') {
+        DocumentHeader.direction = 'down';
+        DocumentHeader.changedPosition = DocumentHeader.currentPosition;
+      }
+    } else if (DocumentHeader.currentPosition < DocumentHeader.lastPosition) {
+      if (DocumentHeader.direction !== 'up') {
+        DocumentHeader.direction = 'up';
+        DocumentHeader.changedPosition = DocumentHeader.currentPosition;
+      }
+    }
+    if (DocumentHeader.direction === 'up' && (DocumentHeader.changedPosition - DocumentHeader.reactionRange) < DocumentHeader.currentPosition) {
+      DocumentHeader.$documentHeader.css('margin-top', 0);
+    }
+    if (DocumentHeader.direction === 'down' && (DocumentHeader.changedPosition + DocumentHeader.reactionRange) < DocumentHeader.currentPosition) {
+      DocumentHeader.$documentHeader.css('margin-top', (DocumentHeader.$documentHeaderNavigationBar.outerHeight() + 4) * -1);
+    }
+    DocumentHeader.lastPosition = DocumentHeader.currentPosition;
+  };
 
-	/**
-	 * Start
-	 */
-	DocumentHeader.start = function() {
-		DocumentHeader.reposition();
-		$(window).on('resize', DocumentHeader.reposition);
-		$(window).on('scroll', DocumentHeader.scroll);
-	};
+  /**
+   * Start
+   */
+  DocumentHeader.start = function() {
+    DocumentHeader.reposition();
+    $(window).on('resize', DocumentHeader.reposition);
+    $(window).on('scroll', DocumentHeader.scroll);
+  };
 
-	/**
-	 * Initialize
-	 */
-	DocumentHeader.initialize = function() {
-		DocumentHeader.$documentHeader = $(DocumentHeader.settings.selectors.moduleDocumentHeader);
-		if (DocumentHeader.$documentHeader.length > 0) {
-			DocumentHeader.$documentHeaderBars = $(DocumentHeader.settings.selectors.moduleDocheaderBar);
-			DocumentHeader.$documentHeaderNavigationBar = $(DocumentHeader.settings.selectors.moduleNavigationBar);
-			DocumentHeader.$documentHeaderSearchBar = $(DocumentHeader.settings.selectors.moduleSearchBar).remove();
-			if (DocumentHeader.$documentHeaderSearchBar.length > 0) {
-				DocumentHeader.$documentHeader.append(DocumentHeader.$documentHeaderSearchBar);
-			}
-			DocumentHeader.$moduleBody = $(DocumentHeader.settings.selectors.moduleBody);
-			DocumentHeader.start();
-		}
-	};
+  /**
+   * Initialize
+   */
+  DocumentHeader.initialize = function() {
+    DocumentHeader.$documentHeader = $(DocumentHeader.settings.selectors.moduleDocumentHeader);
+    if (DocumentHeader.$documentHeader.length > 0) {
+      DocumentHeader.$documentHeaderBars = $(DocumentHeader.settings.selectors.moduleDocheaderBar);
+      DocumentHeader.$documentHeaderNavigationBar = $(DocumentHeader.settings.selectors.moduleNavigationBar);
+      DocumentHeader.$documentHeaderSearchBar = $(DocumentHeader.settings.selectors.moduleSearchBar).remove();
+      if (DocumentHeader.$documentHeaderSearchBar.length > 0) {
+        DocumentHeader.$documentHeader.append(DocumentHeader.$documentHeaderSearchBar);
+      }
+      DocumentHeader.$moduleBody = $(DocumentHeader.settings.selectors.moduleBody);
+      DocumentHeader.start();
+    }
+  };
 
-	$(DocumentHeader.initialize);
+  $(DocumentHeader.initialize);
 
-	return DocumentHeader;
+  return DocumentHeader;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
index 267bf7d4277c..8eb132cc6b16 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
@@ -16,664 +16,662 @@
  *
  */
 define(['jquery',
-		'moment',
-		'nprogress',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Notification',
-		'TYPO3/CMS/Backend/Severity',
-		'TYPO3/CMS/Lang/Lang'
-	   ], function($, moment, NProgress, Modal, Notification, Severity) {
-
-	/**
-	 * Array of files which are asked for being overridden
-	 *
-	 * @type {array}
-	 */
-	var askForOverride = [],
-		percentagePerFile = 1;
-
-	/**
-	 * File actions
-	 */
-	var actions = {
-		OVERRIDE: 'replace',
-		RENAME: 'rename',
-		SKIP: 'cancel',
-		USE_EXISTING: 'useExisting'
-	};
-
-	/*
-	 * part 1: a generic jQuery plugin "$.dragUploader"
-	 */
-
-	// register the constructor
-	/**
-	 *
-	 * @param {HTMLElement} element
-	 * @constructor
-	 * @exports TYPO3/CMS/Backend/DragUploader
-	 */
-	var DragUploaderPlugin = function(element) {
-		var me = this;
-		me.$body = $('body');
-		me.$element = $(element);
-		me.$trigger = $(me.$element.data('dropzoneTrigger'));
-		me.$dropzone = $('<div />').addClass('dropzone').hide();
-		me.irreObjectUid = me.$element.data('fileIrreObject');
-		var dropZoneEscapedTarget = me.$element.data('dropzoneTarget');
-		if (me.irreObjectUid && me.$element.nextAll(dropZoneEscapedTarget).length !== 0) {
-			me.dropZoneInsertBefore = true;
-			me.$dropzone.insertBefore(dropZoneEscapedTarget);
-		} else {
-			me.dropZoneInsertBefore = false;
-			me.$dropzone.insertAfter(dropZoneEscapedTarget);
-		}
-		me.$dropzoneMask = $('<div />').addClass('dropzone-mask').appendTo(me.$dropzone);
-		me.$fileInput = $('<input type="file" multiple name="files[]" />').addClass('upload-file-picker').appendTo(me.$body);
-		me.$fileList = $(me.$element.data('progress-container'));
-		me.fileListColumnCount = $('thead tr:first th', me.$fileList).length;
-		me.filesExtensionsAllowed = me.$element.data('file-allowed');
-		me.fileDenyPattern = me.$element.data('file-deny-pattern') ? new RegExp(me.$element.data('file-deny-pattern'), 'i') : false;
-		me.maxFileSize = parseInt(me.$element.data('max-file-size'));
-		me.target = me.$element.data('target-folder');
-
-		me.browserCapabilities = {
-			fileReader: typeof FileReader !== 'undefined',
-			DnD: 'draggable' in document.createElement('span'),
-			FormData: !!window.FormData,
-			Progress: "upload" in new XMLHttpRequest
-		};
-
-		/**
-		 *
-		 */
-		me.showDropzone = function() {
-			me.$dropzone.show();
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 */
-		me.hideDropzone = function(event) {
-			event.stopPropagation();
-			event.preventDefault();
-			me.$dropzone.hide();
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 * @returns {Boolean}
-		 */
-		me.dragFileIntoDocument = function(event) {
-			event.stopPropagation();
-			event.preventDefault();
-			me.$body.addClass('drop-in-progress');
-			me.showDropzone();
-			return false;
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 * @returns {Boolean}
-		 */
-		me.dragAborted = function(event) {
-			event.stopPropagation();
-			event.preventDefault();
-			me.$body.removeClass('drop-in-progress');
-			return false;
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 * @returns {Boolean}
-		 */
-		me.ignoreDrop = function(event) {
-			// stops the browser from redirecting.
-			event.stopPropagation();
-			event.preventDefault();
-			me.dragAborted(event);
-			return false;
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 */
-		me.handleDrop = function(event) {
-			me.ignoreDrop(event);
-			me.processFiles(event.originalEvent.dataTransfer.files);
-			me.$dropzone.removeClass('drop-status-ok');
-		};
-
-		/**
-		 *
-		 * @param {Array} files
-		 */
-		me.processFiles = function(files) {
-			me.queueLength = files.length;
-
-			if (!me.$fileList.is(':visible')) {
-				me.$fileList.show();
-			}
-
-			NProgress.start();
-			percentagePerFile = 1 / files.length;
-
-			// Check for each file if is already exist before adding it to the queue
-			var ajaxCalls = [];
-			$.each(files, function(i, file) {
-
-				ajaxCalls[i] = $.ajax({
-					url: TYPO3.settings.ajaxUrls['file_exists'],
-					data: {
-						fileName: file.name,
-						fileTarget: me.target
-					},
-					cache: false,
-					success: function(response) {
-						var fileExists = typeof response.uid !== 'undefined';
-						if (fileExists) {
-							askForOverride.push({
-								original: response,
-								uploaded: file,
-								action: me.irreObjectUid ? actions.USE_EXISTING : actions.SKIP
-							});
-							NProgress.inc(percentagePerFile);
-						} else {
-							new FileQueueItem(me, file, 'cancel');
-						}
-					}
-				});
-			});
-
-			$.when.apply($, ajaxCalls).done(function () {
-				me.drawOverrideModal();
-				NProgress.done();
-			});
-
-			delete ajaxCalls;
-			me.$fileInput.val('');
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 */
-		me.fileInDropzone = function(event) {
-			me.$dropzone.addClass('drop-status-ok');
-		};
-
-		/**
-		 *
-		 * @param {Event} event
-		 */
-		me.fileOutOfDropzone = function(event) {
-			me.$dropzone.removeClass('drop-status-ok');
-		};
-
-		/**
-		 * bind file picker to default upload button
-		 *
-		 * @param {Object} button
-		 */
-		me.bindUploadButton = function(button) {
-			button.click(function(event) {
-				event.preventDefault();
-				me.$fileInput.click();
-				me.showDropzone();
-			});
-		};
-
-		if (me.browserCapabilities.DnD) {
-			me.$body.on('dragover', me.dragFileIntoDocument);
-			me.$body.on('dragend', me.dragAborted);
-			me.$body.on('drop', me.ignoreDrop);
-
-			me.$dropzone.on('dragenter', me.fileInDropzone);
-			me.$dropzoneMask.on('dragenter', me.fileInDropzone);
-			me.$dropzoneMask.on('dragleave', me.fileOutOfDropzone);
-			me.$dropzoneMask.on('drop', me.handleDrop);
-
-			me.$dropzone.prepend(
-				'<div class="dropzone-hint">' +
-					'<div class="dropzone-hint-media">' +
-						'<div class="dropzone-hint-icon"></div>' +
-					'</div>' +
-					'<div class="dropzone-hint-body">' +
-						'<h3 class="dropzone-hint-title">' +
-							TYPO3.lang['file_upload.dropzonehint.title'] +
-						'</h3>' +
-						'<p class="dropzone-hint-message">' +
-							TYPO3.lang['file_upload.dropzonehint.message'] +
-						'</p>' +
-					'</div>' +
-				'</div>').click(function() {
-					me.$fileInput.click()
-				});
-			$('<span />').addClass('dropzone-close').click(me.hideDropzone).appendTo(me.$dropzone);
-
-			// no filelist then create own progress table
-			if (me.$fileList.length === 0) {
-				me.$fileList = $('<table />').attr('id', 'typo3-filelist').addClass('table table-striped table-hover upload-queue').html('<tbody></tbody>').hide();
-				if (me.dropZoneInsertBefore) {
-					me.$fileList.insertAfter(me.$dropzone);
-				} else {
-					me.$fileList.insertBefore(me.$dropzone);
-				}
-				me.fileListColumnCount = 7;
-			}
-
-			me.$fileInput.on('change', function() {
-				me.processFiles(this.files);
-			});
-
-			me.bindUploadButton(me.$trigger.length ? me.$trigger : me.$element);
-		}
-
-		/**
-		 *
-		 */
-		me.decrementQueueLength = function() {
-			if (me.queueLength > 0) {
-				me.queueLength--;
-				if (me.queueLength === 0) {
-					$.ajax({
-						url: TYPO3.settings.ajaxUrls['flashmessages_render'],
-						cache: false,
-						success: function(data) {
-							$.each(data, function(index, flashMessage) {
-								Notification.showMessage(flashMessage.title, flashMessage.message, flashMessage.severity);
-							});
-						}
-					});
-				}
-			}
-		};
-
-		/**
-		 *
-		 */
-		me.drawOverrideModal = function() {
-			var amountOfItems = Object.keys(askForOverride).length;
-			if (amountOfItems === 0) {
-				return;
-			}
-			var $modalContent = $('<div/>').append(
-				$('<p/>').text(TYPO3.lang['file_upload.existingfiles.description']),
-				$('<table/>', {class: 'table table-striped'}).append(
-					$('<tr />').append(
-						$('<th/>'),
-						$('<th/>').text(TYPO3.lang['file_upload.header.originalFile']),
-						$('<th/>').text(TYPO3.lang['file_upload.header.uploadedFile']),
-						$('<th/>').text(TYPO3.lang['file_upload.header.action'])
-					)
-				)
-			);
-
-			for (var i = 0; i < amountOfItems; ++i) {
-				var $record = $('<tr />').append(
-					$('<td />').append(
-						(askForOverride[i].original.thumbUrl !== ''
-							? $('<img />', {src: askForOverride[i].original.thumbUrl, height: 40})
-							: $(askForOverride[i].original.icon)
-						)
-					),
-					$('<td />').html(
-						askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].uploaded.size)) + ')' +
-						'<br>' + moment(askForOverride[i].uploaded.lastModified, 'x').format('YYYY-MM-DD HH:mm')
-					),
-					$('<td />').html(
-						askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].original.size)) + ')' +
-						'<br>' + moment(askForOverride[i].original.mtime, 'X').format('YYYY-MM-DD HH:mm')
-					),
-					$('<td />').append(
-						$('<select />', {class: 'form-control t3js-actions', 'data-override': i}).append(
-							(me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.use_existing']) : ''),
-							$('<option />').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.skip']),
-							$('<option />').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.rename']),
-							$('<option />').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.override'])
-						)
-					)
-				);
-				$modalContent.find('table').append($record);
-			}
-
-			var $modal = Modal.confirm(TYPO3.lang['file_upload.existingfiles.title'], $modalContent, Severity.warning, [
-				{
-					text: $(this).data('button-close-text') || TYPO3.lang['file_upload.button.cancel'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'cancel'
-				},
-				{
-					text: $(this).data('button-ok-text') || TYPO3.lang['file_upload.button.continue'] || 'Continue with selected actions',
-					btnClass: 'btn-warning',
-					name: 'continue'
-				}
-			], ['modal-inner-scroll']);
-			$modal.find('.modal-dialog').addClass('modal-lg');
-
-			$modal.find('.modal-footer').prepend(
-				$('<span/>').addClass('form-inline pull-left').append(
-					$('<label/>').text(TYPO3.lang['file_upload.actions.all.label']),
-					$('<select/>', {class: 'form-control t3js-actions-all'}).append(
-						$('<option/>').val('').text(TYPO3.lang['file_upload.actions.all.empty']),
-						(me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.all.use_existing']) : ''),
-						$('<option/>').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.all.skip']),
-						$('<option/>').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.all.rename']),
-						$('<option/>').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.all.override'])
-					)
-				)
-			);
-
-			$modal.on('change', '.t3js-actions-all', function() {
-				var $me = $(this),
-					value = $me.val();
-
-				if (value !== '') {
-					// mass action was selected, apply action to every file
-					$modal.find('.t3js-actions').each(function (i, select) {
-						var $select = $(select),
-							index = parseInt($select.data('override'));
-						$select.val(value).prop('disabled', 'disabled');
-						askForOverride[index].action = $select.val();
-					});
-				} else {
-					$modal.find('.t3js-actions').removeProp('disabled');
-				}
-			}).on('change', '.t3js-actions', function() {
-				var $me = $(this),
-					index = parseInt($me.data('override'));
-				askForOverride[index].action = $me.val();
-			}).on('button.clicked', function(e) {
-				if (e.target.name === 'cancel') {
-					askForOverride = [];
-					Modal.dismiss();
-				} else if (e.target.name === 'continue') {
-					$.each(askForOverride, function(key, fileInfo) {
-						if (fileInfo.action === actions.USE_EXISTING) {
-							DragUploader.addFileToIrre(
-								me.irreObjectUid,
-								fileInfo.original
-							);
-						} else if (fileInfo.action !== actions.SKIP) {
-							new FileQueueItem(me, fileInfo.uploaded, fileInfo.action);
-						}
-					});
-					askForOverride = [];
-					Modal.dismiss();
-				}
-			}).on('hidden.bs.modal', function() {
-				askForOverride = [];
-			});
-		}
-	};
-
-	var FileQueueItem = function(dragUploader, file, override) {
-		var me = this;
-		me.dragUploader = dragUploader;
-		me.file = file;
-		me.override = override;
-
-		me.$row = $('<tr />').addClass('upload-queue-item uploading');
-		me.$iconCol = $('<td />').addClass('col-icon').appendTo(me.$row);
-		me.$fileName = $('<td />').text(file.name).appendTo(me.$row);
-		me.$progress = $('<td />').attr('colspan', me.dragUploader.fileListColumnCount-2).appendTo(me.$row);
-		me.$progressContainer = $('<div />').addClass('upload-queue-progress').appendTo(me.$progress);
-		me.$progressBar = $('<div />').addClass('upload-queue-progress-bar').appendTo(me.$progressContainer);
-		me.$progressPercentage = $('<span />').addClass('upload-queue-progress-percentage').appendTo(me.$progressContainer);
-		me.$progressMessage = $('<span />').addClass('upload-queue-progress-message').appendTo(me.$progressContainer);
-
-		me.updateMessage = function(message) {
-			me.$progressMessage.text(message);
-		};
-
-		me.removeProgress = function() {
-			if (me.$progress) {
-				me.$progress.remove();
-			}
-		};
-
-		me.uploadStart = function() {
-			me.$progressPercentage.text('(0%)');
-			me.$progressBar.width('1%');
-			me.dragUploader.$trigger.trigger('uploadStart', [me]);
-		};
-
-		me.uploadError = function(response) {
-			me.updateMessage(TYPO3.lang['file_upload.uploadFailed'].replace(/\{0\}/g, me.file.name));
-			var error = $(response.responseText);
-			if (error.is('t3err')) {
-				me.$progressPercentage.text(error.text());
-			} else {
-				me.$progressPercentage.text('(' + response.statusText + ')');
-			}
-			me.$row.addClass('error');
-			me.dragUploader.decrementQueueLength();
-			me.dragUploader.$trigger.trigger('uploadError', [me, response]);
-		};
-
-		me.updateProgress = function(event) {
-			var percentage = Math.round((event.loaded / event.total) * 100) + '%';
-			me.$progressBar.outerWidth(percentage);
-			me.$progressPercentage.text(percentage);
-			me.dragUploader.$trigger.trigger('updateProgress', [me, percentage, event]);
-		};
-
-		me.uploadSuccess = function(data) {
-			if (data.upload) {
-				me.dragUploader.decrementQueueLength();
-				me.$row.removeClass('uploading');
-				me.$fileName.text(data.upload[0].name);
-				me.$progressPercentage.text('');
-				me.$progressMessage.text('100%');
-				me.$progressBar.outerWidth('100%');
-
-				// replace file icon
-				if (data.upload[0].icon) {
-					me.$iconCol.html('<a href="#" class="t3js-contextmenutrigger" data-uid="' + data.upload[0].id + '" data-table="sys_file">' + data.upload[0].icon + '&nbsp;</span></a>');
-				}
-
-				if (me.dragUploader.irreObjectUid) {
-					DragUploader.addFileToIrre(
-						me.dragUploader.irreObjectUid,
-						data.upload[0]
-					);
-					setTimeout(function() {
-						me.$row.remove();
-						if ($('tr', me.dragUploader.$fileList).length === 0) {
-							me.dragUploader.$fileList.hide();
-							me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]);
-						}
-					}, 3000);
-				} else {
-					setTimeout(function() {
-						me.showFileInfo(data.upload[0]);
-						me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]);
-					}, 3000);
-				}
-			}
-		};
-
-		me.showFileInfo = function(fileInfo) {
-			me.removeProgress();
-			// add spacing cells when clibboard and/or extended view is enabled
-			for (i = 7; i < me.dragUploader.fileListColumnCount; i++) {
-				$('<td />').text('').appendTo(me.$row);
-			}
-			$('<td />').text(fileInfo.extension.toUpperCase()).appendTo(me.$row);
-			$('<td />').text(fileInfo.date).appendTo(me.$row);
-			$('<td />').text(DragUploader.fileSizeAsString(fileInfo.size)).appendTo(me.$row);
-			var permissions = '';
-			if (fileInfo.permissions.read) {
-				permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.read'] + '</strong>';
-			}
-			if (fileInfo.permissions.write) {
-				permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.write'] + '</strong>';
-			}
-			$('<td />').html(permissions).appendTo(me.$row);
-			$('<td />').text('-').appendTo(me.$row);
-		};
-
-		me.checkAllowedExtensions = function() {
-			if (!me.dragUploader.filesExtensionsAllowed) {
-				return true;
-			}
-			var extension = me.file.name.split('.').pop();
-			var allowed = me.dragUploader.filesExtensionsAllowed.split(',');
-			if ($.inArray(extension.toLowerCase(), allowed) !== -1) {
-				return true;
-			}
-			return false;
-		};
-
-		// position queue item in filelist
-		if ($('tbody tr.upload-queue-item', me.dragUploader.$fileList).length === 0) {
-			me.$row.prependTo($('tbody', me.dragUploader.$fileList));
-			me.$row.addClass('last');
-		} else {
-			me.$row.insertBefore($('tbody tr.upload-queue-item:first', me.dragUploader.$fileList));
-		}
-
-		// set dummy file icon
-		me.$iconCol.html('<span class="t3-icon t3-icon-mimetypes t3-icon-other-other">&nbsp;</span>')
-
-		// check file size
-		if (me.dragUploader.maxFileSize > 0 && me.file.size > me.dragUploader.maxFileSize) {
-			me.updateMessage(TYPO3.lang['file_upload.maxFileSizeExceeded']
-				.replace(/\{0\}/g, me.file.name)
-				.replace(/\{1\}/g, DragUploader.fileSizeAsString(me.dragUploader.maxFileSize)));
-			me.$row.addClass('error');
-
-			// check filename/extension against deny pattern
-		} else if (me.dragUploader.fileDenyPattern && me.file.name.match(me.dragUploader.fileDenyPattern)) {
-			me.updateMessage(TYPO3.lang['file_upload.fileNotAllowed'].replace(/\{0\}/g, me.file.name));
-			me.$row.addClass('error');
-
-		} else if (!me.checkAllowedExtensions()) {
-			me.updateMessage(TYPO3.lang['file_upload.fileExtensionExpected']
-					.replace(/\{0\}/g, me.dragUploader.filesExtensionsAllowed)
-			);
-			me.$row.addClass('error');
-		} else {
-			me.updateMessage('- ' + DragUploader.fileSizeAsString(me.file.size));
-
-			var formData = new FormData();
-			formData.append('data[upload][1][target]', me.dragUploader.target);
-			formData.append('data[upload][1][data]', '1');
-			formData.append('overwriteExistingFiles', me.override);
-			formData.append('redirect', '');
-			formData.append('upload_1', me.file);
-
-			var s = $.extend(true, {}, $.ajaxSettings, {
-				url: TYPO3.settings.ajaxUrls['file_process'],
-				contentType: false,
-				processData: false,
-				data: formData,
-				cache: false,
-				type: 'POST',
-				success: me.uploadSuccess,
-				error: me.uploadError
-			});
-
-			s.xhr = function() {
-				var xhr = $.ajaxSettings.xhr();
-				xhr.upload.addEventListener('progress', me.updateProgress);
-				return xhr;
-			};
-
-			// start upload
-			me.upload = $.ajax(s);
-		}
-	};
-
-	/**
-	 * part 2: The main module of this file
-	 * - initialize the DragUploader module and register
-	 * the jQuery plugin in the jQuery global object
-	 * when initializing the DragUploader module
-	 */
-	var DragUploader = {};
-
-	DragUploader.options = {
-	};
-
-	DragUploader.fileSizeAsString = function(size) {
-		var string = '',
-			sizeKB = size / 1024;
-
-		if (parseInt(sizeKB) > 1024) {
-			var sizeMB = sizeKB / 1024;
-			string = sizeMB.toFixed(1) + ' MB';
-		} else {
-			string = sizeKB.toFixed(1) + ' KB';
-		}
-		return string;
-	};
-
-	DragUploader.addFileToIrre = function(irre_object, file) {
-		inline.delayedImportElement(
-			irre_object,
-			'sys_file',
-			file.uid,
-			'file'
-		);
-	};
-
-	DragUploader.initialize = function() {
-		var me = this,
-			opts = me.options;
-
-		// register the jQuery plugin "DragUploaderPlugin"
-		$.fn.dragUploader = function(option) {
-			return this.each(function() {
-				var $this = $(this),
-					data = $this.data('DragUploaderPlugin');
-				if (!data) {
-					$this.data('DragUploaderPlugin', (data = new DragUploaderPlugin(this)));
-				}
-				if (typeof option === 'string') {
-					data[option]();
-				}
-			});
-		};
-
-		$(function() {
-			$('.t3js-drag-uploader').dragUploader();
-		});
-	};
-
-
-
-	/**
-	 * part 3: initialize the RequireJS module, require possible post-initialize hooks,
-	 * and return the main object
-	 */
-	var initialize = function() {
-
-		DragUploader.initialize();
-
-		// load required modules to hook in the post initialize function
-		if (
-			'undefined' !== typeof TYPO3.settings
-			&& 'undefined' !== typeof TYPO3.settings.RequireJS
-			&& 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules
-			&& 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader']
-		) {
-			$.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'], function(pos, moduleName) {
-				require([moduleName]);
-			});
-		}
-
-		// return the object in the global space
-		return DragUploader;
-	};
-
-	// call the main initialize function and execute the hooks
-	return initialize();
+  'moment',
+  'nprogress',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Lang/Lang'
+], function($, moment, NProgress, Modal, Notification, Severity) {
+
+  /**
+   * Array of files which are asked for being overridden
+   *
+   * @type {array}
+   */
+  var askForOverride = [],
+    percentagePerFile = 1;
+
+  /**
+   * File actions
+   */
+  var actions = {
+    OVERRIDE: 'replace',
+    RENAME: 'rename',
+    SKIP: 'cancel',
+    USE_EXISTING: 'useExisting'
+  };
+
+  /*
+   * part 1: a generic jQuery plugin "$.dragUploader"
+   */
+
+  // register the constructor
+  /**
+   *
+   * @param {HTMLElement} element
+   * @constructor
+   * @exports TYPO3/CMS/Backend/DragUploader
+   */
+  var DragUploaderPlugin = function(element) {
+    var me = this;
+    me.$body = $('body');
+    me.$element = $(element);
+    me.$trigger = $(me.$element.data('dropzoneTrigger'));
+    me.$dropzone = $('<div />').addClass('dropzone').hide();
+    me.irreObjectUid = me.$element.data('fileIrreObject');
+    var dropZoneEscapedTarget = me.$element.data('dropzoneTarget');
+    if (me.irreObjectUid && me.$element.nextAll(dropZoneEscapedTarget).length !== 0) {
+      me.dropZoneInsertBefore = true;
+      me.$dropzone.insertBefore(dropZoneEscapedTarget);
+    } else {
+      me.dropZoneInsertBefore = false;
+      me.$dropzone.insertAfter(dropZoneEscapedTarget);
+    }
+    me.$dropzoneMask = $('<div />').addClass('dropzone-mask').appendTo(me.$dropzone);
+    me.$fileInput = $('<input type="file" multiple name="files[]" />').addClass('upload-file-picker').appendTo(me.$body);
+    me.$fileList = $(me.$element.data('progress-container'));
+    me.fileListColumnCount = $('thead tr:first th', me.$fileList).length;
+    me.filesExtensionsAllowed = me.$element.data('file-allowed');
+    me.fileDenyPattern = me.$element.data('file-deny-pattern') ? new RegExp(me.$element.data('file-deny-pattern'), 'i') : false;
+    me.maxFileSize = parseInt(me.$element.data('max-file-size'));
+    me.target = me.$element.data('target-folder');
+
+    me.browserCapabilities = {
+      fileReader: typeof FileReader !== 'undefined',
+      DnD: 'draggable' in document.createElement('span'),
+      FormData: !!window.FormData,
+      Progress: "upload" in new XMLHttpRequest
+    };
+
+    /**
+     *
+     */
+    me.showDropzone = function() {
+      me.$dropzone.show();
+    };
+
+    /**
+     *
+     * @param {Event} event
+     */
+    me.hideDropzone = function(event) {
+      event.stopPropagation();
+      event.preventDefault();
+      me.$dropzone.hide();
+    };
+
+    /**
+     *
+     * @param {Event} event
+     * @returns {Boolean}
+     */
+    me.dragFileIntoDocument = function(event) {
+      event.stopPropagation();
+      event.preventDefault();
+      me.$body.addClass('drop-in-progress');
+      me.showDropzone();
+      return false;
+    };
+
+    /**
+     *
+     * @param {Event} event
+     * @returns {Boolean}
+     */
+    me.dragAborted = function(event) {
+      event.stopPropagation();
+      event.preventDefault();
+      me.$body.removeClass('drop-in-progress');
+      return false;
+    };
+
+    /**
+     *
+     * @param {Event} event
+     * @returns {Boolean}
+     */
+    me.ignoreDrop = function(event) {
+      // stops the browser from redirecting.
+      event.stopPropagation();
+      event.preventDefault();
+      me.dragAborted(event);
+      return false;
+    };
+
+    /**
+     *
+     * @param {Event} event
+     */
+    me.handleDrop = function(event) {
+      me.ignoreDrop(event);
+      me.processFiles(event.originalEvent.dataTransfer.files);
+      me.$dropzone.removeClass('drop-status-ok');
+    };
+
+    /**
+     *
+     * @param {Array} files
+     */
+    me.processFiles = function(files) {
+      me.queueLength = files.length;
+
+      if (!me.$fileList.is(':visible')) {
+        me.$fileList.show();
+      }
+
+      NProgress.start();
+      percentagePerFile = 1 / files.length;
+
+      // Check for each file if is already exist before adding it to the queue
+      var ajaxCalls = [];
+      $.each(files, function(i, file) {
+
+        ajaxCalls[i] = $.ajax({
+          url: TYPO3.settings.ajaxUrls['file_exists'],
+          data: {
+            fileName: file.name,
+            fileTarget: me.target
+          },
+          cache: false,
+          success: function(response) {
+            var fileExists = typeof response.uid !== 'undefined';
+            if (fileExists) {
+              askForOverride.push({
+                original: response,
+                uploaded: file,
+                action: me.irreObjectUid ? actions.USE_EXISTING : actions.SKIP
+              });
+              NProgress.inc(percentagePerFile);
+            } else {
+              new FileQueueItem(me, file, 'cancel');
+            }
+          }
+        });
+      });
+
+      $.when.apply($, ajaxCalls).done(function() {
+        me.drawOverrideModal();
+        NProgress.done();
+      });
+
+      delete ajaxCalls;
+      me.$fileInput.val('');
+    };
+
+    /**
+     *
+     * @param {Event} event
+     */
+    me.fileInDropzone = function(event) {
+      me.$dropzone.addClass('drop-status-ok');
+    };
+
+    /**
+     *
+     * @param {Event} event
+     */
+    me.fileOutOfDropzone = function(event) {
+      me.$dropzone.removeClass('drop-status-ok');
+    };
+
+    /**
+     * bind file picker to default upload button
+     *
+     * @param {Object} button
+     */
+    me.bindUploadButton = function(button) {
+      button.click(function(event) {
+        event.preventDefault();
+        me.$fileInput.click();
+        me.showDropzone();
+      });
+    };
+
+    if (me.browserCapabilities.DnD) {
+      me.$body.on('dragover', me.dragFileIntoDocument);
+      me.$body.on('dragend', me.dragAborted);
+      me.$body.on('drop', me.ignoreDrop);
+
+      me.$dropzone.on('dragenter', me.fileInDropzone);
+      me.$dropzoneMask.on('dragenter', me.fileInDropzone);
+      me.$dropzoneMask.on('dragleave', me.fileOutOfDropzone);
+      me.$dropzoneMask.on('drop', me.handleDrop);
+
+      me.$dropzone.prepend(
+        '<div class="dropzone-hint">' +
+        '<div class="dropzone-hint-media">' +
+        '<div class="dropzone-hint-icon"></div>' +
+        '</div>' +
+        '<div class="dropzone-hint-body">' +
+        '<h3 class="dropzone-hint-title">' +
+        TYPO3.lang['file_upload.dropzonehint.title'] +
+        '</h3>' +
+        '<p class="dropzone-hint-message">' +
+        TYPO3.lang['file_upload.dropzonehint.message'] +
+        '</p>' +
+        '</div>' +
+        '</div>').click(function() {
+        me.$fileInput.click()
+      });
+      $('<span />').addClass('dropzone-close').click(me.hideDropzone).appendTo(me.$dropzone);
+
+      // no filelist then create own progress table
+      if (me.$fileList.length === 0) {
+        me.$fileList = $('<table />').attr('id', 'typo3-filelist').addClass('table table-striped table-hover upload-queue').html('<tbody></tbody>').hide();
+        if (me.dropZoneInsertBefore) {
+          me.$fileList.insertAfter(me.$dropzone);
+        } else {
+          me.$fileList.insertBefore(me.$dropzone);
+        }
+        me.fileListColumnCount = 7;
+      }
+
+      me.$fileInput.on('change', function() {
+        me.processFiles(this.files);
+      });
+
+      me.bindUploadButton(me.$trigger.length ? me.$trigger : me.$element);
+    }
+
+    /**
+     *
+     */
+    me.decrementQueueLength = function() {
+      if (me.queueLength > 0) {
+        me.queueLength--;
+        if (me.queueLength === 0) {
+          $.ajax({
+            url: TYPO3.settings.ajaxUrls['flashmessages_render'],
+            cache: false,
+            success: function(data) {
+              $.each(data, function(index, flashMessage) {
+                Notification.showMessage(flashMessage.title, flashMessage.message, flashMessage.severity);
+              });
+            }
+          });
+        }
+      }
+    };
+
+    /**
+     *
+     */
+    me.drawOverrideModal = function() {
+      var amountOfItems = Object.keys(askForOverride).length;
+      if (amountOfItems === 0) {
+        return;
+      }
+      var $modalContent = $('<div/>').append(
+        $('<p/>').text(TYPO3.lang['file_upload.existingfiles.description']),
+        $('<table/>', {class: 'table table-striped'}).append(
+          $('<tr />').append(
+            $('<th/>'),
+            $('<th/>').text(TYPO3.lang['file_upload.header.originalFile']),
+            $('<th/>').text(TYPO3.lang['file_upload.header.uploadedFile']),
+            $('<th/>').text(TYPO3.lang['file_upload.header.action'])
+          )
+        )
+      );
+
+      for (var i = 0; i < amountOfItems; ++i) {
+        var $record = $('<tr />').append(
+          $('<td />').append(
+            (askForOverride[i].original.thumbUrl !== ''
+                ? $('<img />', {src: askForOverride[i].original.thumbUrl, height: 40})
+                : $(askForOverride[i].original.icon)
+            )
+          ),
+          $('<td />').html(
+            askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].uploaded.size)) + ')' +
+            '<br>' + moment(askForOverride[i].uploaded.lastModified, 'x').format('YYYY-MM-DD HH:mm')
+          ),
+          $('<td />').html(
+            askForOverride[i].uploaded.name + ' (' + (DragUploader.fileSizeAsString(askForOverride[i].original.size)) + ')' +
+            '<br>' + moment(askForOverride[i].original.mtime, 'X').format('YYYY-MM-DD HH:mm')
+          ),
+          $('<td />').append(
+            $('<select />', {class: 'form-control t3js-actions', 'data-override': i}).append(
+              (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.use_existing']) : ''),
+              $('<option />').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.skip']),
+              $('<option />').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.rename']),
+              $('<option />').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.override'])
+            )
+          )
+        );
+        $modalContent.find('table').append($record);
+      }
+
+      var $modal = Modal.confirm(TYPO3.lang['file_upload.existingfiles.title'], $modalContent, Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['file_upload.button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['file_upload.button.continue'] || 'Continue with selected actions',
+          btnClass: 'btn-warning',
+          name: 'continue'
+        }
+      ], ['modal-inner-scroll']);
+      $modal.find('.modal-dialog').addClass('modal-lg');
+
+      $modal.find('.modal-footer').prepend(
+        $('<span/>').addClass('form-inline pull-left').append(
+          $('<label/>').text(TYPO3.lang['file_upload.actions.all.label']),
+          $('<select/>', {class: 'form-control t3js-actions-all'}).append(
+            $('<option/>').val('').text(TYPO3.lang['file_upload.actions.all.empty']),
+            (me.irreObjectUid ? $('<option/>').val(actions.USE_EXISTING).text(TYPO3.lang['file_upload.actions.all.use_existing']) : ''),
+            $('<option/>').val(actions.SKIP).text(TYPO3.lang['file_upload.actions.all.skip']),
+            $('<option/>').val(actions.RENAME).text(TYPO3.lang['file_upload.actions.all.rename']),
+            $('<option/>').val(actions.OVERRIDE).text(TYPO3.lang['file_upload.actions.all.override'])
+          )
+        )
+      );
+
+      $modal.on('change', '.t3js-actions-all', function() {
+        var $me = $(this),
+          value = $me.val();
+
+        if (value !== '') {
+          // mass action was selected, apply action to every file
+          $modal.find('.t3js-actions').each(function(i, select) {
+            var $select = $(select),
+              index = parseInt($select.data('override'));
+            $select.val(value).prop('disabled', 'disabled');
+            askForOverride[index].action = $select.val();
+          });
+        } else {
+          $modal.find('.t3js-actions').removeProp('disabled');
+        }
+      }).on('change', '.t3js-actions', function() {
+        var $me = $(this),
+          index = parseInt($me.data('override'));
+        askForOverride[index].action = $me.val();
+      }).on('button.clicked', function(e) {
+        if (e.target.name === 'cancel') {
+          askForOverride = [];
+          Modal.dismiss();
+        } else if (e.target.name === 'continue') {
+          $.each(askForOverride, function(key, fileInfo) {
+            if (fileInfo.action === actions.USE_EXISTING) {
+              DragUploader.addFileToIrre(
+                me.irreObjectUid,
+                fileInfo.original
+              );
+            } else if (fileInfo.action !== actions.SKIP) {
+              new FileQueueItem(me, fileInfo.uploaded, fileInfo.action);
+            }
+          });
+          askForOverride = [];
+          Modal.dismiss();
+        }
+      }).on('hidden.bs.modal', function() {
+        askForOverride = [];
+      });
+    }
+  };
+
+  var FileQueueItem = function(dragUploader, file, override) {
+    var me = this;
+    me.dragUploader = dragUploader;
+    me.file = file;
+    me.override = override;
+
+    me.$row = $('<tr />').addClass('upload-queue-item uploading');
+    me.$iconCol = $('<td />').addClass('col-icon').appendTo(me.$row);
+    me.$fileName = $('<td />').text(file.name).appendTo(me.$row);
+    me.$progress = $('<td />').attr('colspan', me.dragUploader.fileListColumnCount - 2).appendTo(me.$row);
+    me.$progressContainer = $('<div />').addClass('upload-queue-progress').appendTo(me.$progress);
+    me.$progressBar = $('<div />').addClass('upload-queue-progress-bar').appendTo(me.$progressContainer);
+    me.$progressPercentage = $('<span />').addClass('upload-queue-progress-percentage').appendTo(me.$progressContainer);
+    me.$progressMessage = $('<span />').addClass('upload-queue-progress-message').appendTo(me.$progressContainer);
+
+    me.updateMessage = function(message) {
+      me.$progressMessage.text(message);
+    };
+
+    me.removeProgress = function() {
+      if (me.$progress) {
+        me.$progress.remove();
+      }
+    };
+
+    me.uploadStart = function() {
+      me.$progressPercentage.text('(0%)');
+      me.$progressBar.width('1%');
+      me.dragUploader.$trigger.trigger('uploadStart', [me]);
+    };
+
+    me.uploadError = function(response) {
+      me.updateMessage(TYPO3.lang['file_upload.uploadFailed'].replace(/\{0\}/g, me.file.name));
+      var error = $(response.responseText);
+      if (error.is('t3err')) {
+        me.$progressPercentage.text(error.text());
+      } else {
+        me.$progressPercentage.text('(' + response.statusText + ')');
+      }
+      me.$row.addClass('error');
+      me.dragUploader.decrementQueueLength();
+      me.dragUploader.$trigger.trigger('uploadError', [me, response]);
+    };
+
+    me.updateProgress = function(event) {
+      var percentage = Math.round((event.loaded / event.total) * 100) + '%';
+      me.$progressBar.outerWidth(percentage);
+      me.$progressPercentage.text(percentage);
+      me.dragUploader.$trigger.trigger('updateProgress', [me, percentage, event]);
+    };
+
+    me.uploadSuccess = function(data) {
+      if (data.upload) {
+        me.dragUploader.decrementQueueLength();
+        me.$row.removeClass('uploading');
+        me.$fileName.text(data.upload[0].name);
+        me.$progressPercentage.text('');
+        me.$progressMessage.text('100%');
+        me.$progressBar.outerWidth('100%');
+
+        // replace file icon
+        if (data.upload[0].icon) {
+          me.$iconCol.html('<a href="#" class="t3js-contextmenutrigger" data-uid="' + data.upload[0].id + '" data-table="sys_file">' + data.upload[0].icon + '&nbsp;</span></a>');
+        }
+
+        if (me.dragUploader.irreObjectUid) {
+          DragUploader.addFileToIrre(
+            me.dragUploader.irreObjectUid,
+            data.upload[0]
+          );
+          setTimeout(function() {
+            me.$row.remove();
+            if ($('tr', me.dragUploader.$fileList).length === 0) {
+              me.dragUploader.$fileList.hide();
+              me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]);
+            }
+          }, 3000);
+        } else {
+          setTimeout(function() {
+            me.showFileInfo(data.upload[0]);
+            me.dragUploader.$trigger.trigger('uploadSuccess', [me, data]);
+          }, 3000);
+        }
+      }
+    };
+
+    me.showFileInfo = function(fileInfo) {
+      me.removeProgress();
+      // add spacing cells when clibboard and/or extended view is enabled
+      for (i = 7; i < me.dragUploader.fileListColumnCount; i++) {
+        $('<td />').text('').appendTo(me.$row);
+      }
+      $('<td />').text(fileInfo.extension.toUpperCase()).appendTo(me.$row);
+      $('<td />').text(fileInfo.date).appendTo(me.$row);
+      $('<td />').text(DragUploader.fileSizeAsString(fileInfo.size)).appendTo(me.$row);
+      var permissions = '';
+      if (fileInfo.permissions.read) {
+        permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.read'] + '</strong>';
+      }
+      if (fileInfo.permissions.write) {
+        permissions += '<strong class="text-danger">' + TYPO3.lang['permissions.write'] + '</strong>';
+      }
+      $('<td />').html(permissions).appendTo(me.$row);
+      $('<td />').text('-').appendTo(me.$row);
+    };
+
+    me.checkAllowedExtensions = function() {
+      if (!me.dragUploader.filesExtensionsAllowed) {
+        return true;
+      }
+      var extension = me.file.name.split('.').pop();
+      var allowed = me.dragUploader.filesExtensionsAllowed.split(',');
+      if ($.inArray(extension.toLowerCase(), allowed) !== -1) {
+        return true;
+      }
+      return false;
+    };
+
+    // position queue item in filelist
+    if ($('tbody tr.upload-queue-item', me.dragUploader.$fileList).length === 0) {
+      me.$row.prependTo($('tbody', me.dragUploader.$fileList));
+      me.$row.addClass('last');
+    } else {
+      me.$row.insertBefore($('tbody tr.upload-queue-item:first', me.dragUploader.$fileList));
+    }
+
+    // set dummy file icon
+    me.$iconCol.html('<span class="t3-icon t3-icon-mimetypes t3-icon-other-other">&nbsp;</span>')
+
+    // check file size
+    if (me.dragUploader.maxFileSize > 0 && me.file.size > me.dragUploader.maxFileSize) {
+      me.updateMessage(TYPO3.lang['file_upload.maxFileSizeExceeded']
+        .replace(/\{0\}/g, me.file.name)
+        .replace(/\{1\}/g, DragUploader.fileSizeAsString(me.dragUploader.maxFileSize)));
+      me.$row.addClass('error');
+
+      // check filename/extension against deny pattern
+    } else if (me.dragUploader.fileDenyPattern && me.file.name.match(me.dragUploader.fileDenyPattern)) {
+      me.updateMessage(TYPO3.lang['file_upload.fileNotAllowed'].replace(/\{0\}/g, me.file.name));
+      me.$row.addClass('error');
+
+    } else if (!me.checkAllowedExtensions()) {
+      me.updateMessage(TYPO3.lang['file_upload.fileExtensionExpected']
+        .replace(/\{0\}/g, me.dragUploader.filesExtensionsAllowed)
+      );
+      me.$row.addClass('error');
+    } else {
+      me.updateMessage('- ' + DragUploader.fileSizeAsString(me.file.size));
+
+      var formData = new FormData();
+      formData.append('data[upload][1][target]', me.dragUploader.target);
+      formData.append('data[upload][1][data]', '1');
+      formData.append('overwriteExistingFiles', me.override);
+      formData.append('redirect', '');
+      formData.append('upload_1', me.file);
+
+      var s = $.extend(true, {}, $.ajaxSettings, {
+        url: TYPO3.settings.ajaxUrls['file_process'],
+        contentType: false,
+        processData: false,
+        data: formData,
+        cache: false,
+        type: 'POST',
+        success: me.uploadSuccess,
+        error: me.uploadError
+      });
+
+      s.xhr = function() {
+        var xhr = $.ajaxSettings.xhr();
+        xhr.upload.addEventListener('progress', me.updateProgress);
+        return xhr;
+      };
+
+      // start upload
+      me.upload = $.ajax(s);
+    }
+  };
+
+  /**
+   * part 2: The main module of this file
+   * - initialize the DragUploader module and register
+   * the jQuery plugin in the jQuery global object
+   * when initializing the DragUploader module
+   */
+  var DragUploader = {};
+
+  DragUploader.options = {};
+
+  DragUploader.fileSizeAsString = function(size) {
+    var string = '',
+      sizeKB = size / 1024;
+
+    if (parseInt(sizeKB) > 1024) {
+      var sizeMB = sizeKB / 1024;
+      string = sizeMB.toFixed(1) + ' MB';
+    } else {
+      string = sizeKB.toFixed(1) + ' KB';
+    }
+    return string;
+  };
+
+  DragUploader.addFileToIrre = function(irre_object, file) {
+    inline.delayedImportElement(
+      irre_object,
+      'sys_file',
+      file.uid,
+      'file'
+    );
+  };
+
+  DragUploader.initialize = function() {
+    var me = this,
+      opts = me.options;
+
+    // register the jQuery plugin "DragUploaderPlugin"
+    $.fn.dragUploader = function(option) {
+      return this.each(function() {
+        var $this = $(this),
+          data = $this.data('DragUploaderPlugin');
+        if (!data) {
+          $this.data('DragUploaderPlugin', (data = new DragUploaderPlugin(this)));
+        }
+        if (typeof option === 'string') {
+          data[option]();
+        }
+      });
+    };
+
+    $(function() {
+      $('.t3js-drag-uploader').dragUploader();
+    });
+  };
+
+
+  /**
+   * part 3: initialize the RequireJS module, require possible post-initialize hooks,
+   * and return the main object
+   */
+  var initialize = function() {
+
+    DragUploader.initialize();
+
+    // load required modules to hook in the post initialize function
+    if (
+      'undefined' !== typeof TYPO3.settings
+      && 'undefined' !== typeof TYPO3.settings.RequireJS
+      && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules
+      && 'undefined' !== typeof TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader']
+    ) {
+      $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/DragUploader'], function(pos, moduleName) {
+        require([moduleName]);
+      });
+    }
+
+    // return the object in the global space
+    return DragUploader;
+  };
+
+  // call the main initialize function and execute the hooks
+  return initialize();
 
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
index 3b1257388c57..108e2f9a9058 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
@@ -22,1209 +22,1210 @@
 
 // add legacy functions to be accessible in the global scope
 var setFormValueOpenBrowser,
-	setFormValueFromBrowseWin,
-	setHiddenFromList,
-	setFormValueManipulate,
-	setFormValue_getFObj;
+  setFormValueFromBrowseWin,
+  setHiddenFromList,
+  setFormValueManipulate,
+  setFormValue_getFObj;
 
 /**
  * Module: TYPO3/CMS/Backend/FormEngine
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/FormEngineValidation',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Severity',
-		'TYPO3/CMS/Backend/BackendException',
-		'TYPO3/CMS/Backend/Event/InteractionRequestMap'
-	   ], function ($, FormEngineValidation, Modal, Severity, BackendException, InteractionRequestMap) {
-
-	/**
-	 * @param {InteractionRequest} interactionRequest
-	 * @param {boolean} response
-	 */
-	function handleConsumeResponse(interactionRequest, response) {
-		if (response) {
-			FormEngine.interactionRequestMap.resolveFor(interactionRequest);
-		} else {
-			FormEngine.interactionRequestMap.rejectFor(interactionRequest);
-		}
-	}
-
-	/**
-	 * @exports TYPO3/CMS/Backend/FormEngine
-	 */
-	var FormEngine = {
-		consumeTypes: ['typo3.setUrl', 'typo3.beforeSetUrl', 'typo3.refresh'],
-		Validation: FormEngineValidation,
-		interactionRequestMap: InteractionRequestMap,
-		formName: TYPO3.settings.FormEngine.formName,
-		openedPopupWindow: null,
-		legacyFieldChangedCb: function() { !$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb) || TYPO3.settings.FormEngine.legacyFieldChangedCb(); },
-		browserUrl: ''
-	};
-
-	// functions to connect the db/file browser with this document and the formfields on it!
-
-	/**
-	 * Opens a popup window with the element browser (browser.php)
-	 *
-	 * @param {String} mode can be "db" or "file"
-	 * @param {String} params additional params for the browser window
-	 */
-	FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params) {
-		Modal.advanced({
-			type: Modal.types.iframe,
-			content: FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params,
-			size: Modal.sizes.large
-		});
-	};
-
-	/**
-	 * properly fills the select field from the popup window (element browser, link browser)
-	 * or from a multi-select (two selects side-by-side)
-	 * previously known as "setFormValueFromBrowseWin"
-	 *
-	 * @param {String} fieldName Formerly known as "fName" name of the field, like [tt_content][2387][header]
-	 * @param {(String|Number)} value The value to fill in (could be an integer)
-	 * @param {String} label The visible name in the selector
-	 * @param {String} title The title when hovering over it
-	 * @param {String} exclusiveValues If the select field has exclusive options that are not combine-able
-	 * @param {$} $optionEl The jQuery object of the selected <option> tag
-	 */
-	FormEngine.setSelectOptionFromExternalSource = setFormValueFromBrowseWin = function(fieldName, value, label, title, exclusiveValues, $optionEl) {
-		exclusiveValues = String(exclusiveValues);
-
-		var $fieldEl,
-			$originalFieldEl,
-			isMultiple = false,
-			isList = false;
-
-		$originalFieldEl = $fieldEl = FormEngine.getFieldElement(fieldName);
-
-		if ($originalFieldEl.length === 0 || value === '--div--') {
-			return;
-		}
-
-		// Check if the form object has a "_list" element
-		// The "_list" element exists for multiple selection select types
-		var $listFieldEl = FormEngine.getFieldElement(fieldName, '_list', true);
-		if ($listFieldEl.length > 0) {
-			$fieldEl = $listFieldEl;
-			isMultiple = ($fieldEl.prop('multiple') && $fieldEl.prop('size') != '1');
-			isList = true;
-		}
-
-		// clear field before adding value, if configured so (maxitems==1)
-		// @todo: clean this code
-		if (typeof TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName] !== 'undefined') {
-			var clearSettings = TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName];
-			$fieldEl.empty();
-
-			// Clear the upload field
-			// @todo: Investigate whether we either need to fix this code or we can drop it.
-			var filesContainer = document.getElementById(clearSettings.itemFormElID_file);
-			if (filesContainer) {
-				filesContainer.innerHTML = filesContainer.innerHTML;
-			}
-		}
-
-		if (isMultiple || isList) {
-			// If multiple values are not allowed, clear anything that is in the control already
-			if (!isMultiple) {
-				$fieldEl.empty();
-			}
-
-			// Clear elements if exclusive values are found
-			if (exclusiveValues) {
-				var reenableOptions = false;
-
-				var m = new RegExp('(^|,)' + value + '($|,)');
-				// the new value is exclusive => remove all existing values
-				if (exclusiveValues.match(m)) {
-					$fieldEl.empty();
-					reenableOptions = true;
-				} else if ($fieldEl.find('option').length == 1) {
-					// there is an old value and it was exclusive => it has to be removed
-					m = new RegExp("(^|,)" + $fieldEl.find('option').prop('value') + "($|,)");
-					if (exclusiveValues.match(m)) {
-						$fieldEl.empty();
-						reenableOptions = true;
-					}
-				}
-
-				if (reenableOptions && typeof $optionEl !== 'undefined') {
-					$optionEl.closest('select').find('[disabled]').removeClass('hidden').prop('disabled', false)
-				}
-			}
-
-			// Inserting the new element
-			var addNewValue = true;
-
-			// check if there is a "_mul" field (a field on the right) and if the field was already added
-			var $multipleFieldEl = FormEngine.getFieldElement(fieldName, '_mul', true);
-			if ($multipleFieldEl.length == 0 || $multipleFieldEl.val() == 0) {
-				$fieldEl.find('option').each(function(k, optionEl) {
-					if ($(optionEl).prop('value') == value) {
-						addNewValue = false;
-						return false;
-					}
-				});
-
-				if (addNewValue && typeof $optionEl !== 'undefined') {
-					$optionEl.addClass('hidden').prop('disabled', true);
-				}
-			}
-
-			// element can be added
-			if (addNewValue) {
-				// finally add the option
-				var $option = $('<option></option>');
-				$option.attr({value: value, title: title}).text(label);
-				$option.appendTo($fieldEl);
-
-				// set the hidden field
-				FormEngine.updateHiddenFieldValueFromSelect($fieldEl, $originalFieldEl);
-
-				// execute the phpcode from $FormEngine->TBE_EDITOR_fieldChanged_func
-				FormEngine.legacyFieldChangedCb();
-			}
-
-		} else {
-
-			// The incoming value consists of the table name, an underscore and the uid
-			// or just the uid
-			// For a single selection field we need only the uid, so we extract it
-			var pattern = /_(\\d+)$/
-					,result = value.toString().match(pattern);
-
-			if (result != null) {
-				value = result[1];
-			}
-
-			// Change the selected value
-			$fieldEl.val(value);
-		}
-		if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') {
-			FormEngine.Validation.validate();
-		}
-	};
-
-	/**
-	 * sets the value of the hidden field, from the select list, always executed after the select field was updated
-	 * previously known as global function setHiddenFromList()
-	 *
-	 * @param {HTMLElement} selectFieldEl the select field
-	 * @param {HTMLElement} originalFieldEl the hidden form field
-	 */
-	FormEngine.updateHiddenFieldValueFromSelect = setHiddenFromList = function(selectFieldEl, originalFieldEl) {
-		var selectedValues = [];
-		$(selectFieldEl).find('option').each(function() {
-			selectedValues.push($(this).prop('value'));
-		});
-
-		// make a comma separated list, if it is a multi-select
-		// set the values to the final hidden field
-		$(originalFieldEl).val(selectedValues.join(','));
-	};
-
-	/**
-	 * legacy function, can be removed once this function is not in use anymore
-	 *
-	 * @param {String} fName
-	 * @param {String} type
-	 * @param {Number} maxLength
-	 */
-	setFormValueManipulate = function(fName, type, maxLength) {
-		var $formEl = FormEngine.getFormElement(fName);
-		if ($formEl.length > 0) {
-			var formObj = $formEl.get(0);
-			var localArray_V = [];
-			var localArray_L = [];
-			var localArray_S = [];
-			var localArray_T = [];
-			var fObjSel = formObj[fName + '_list'];
-			var l = fObjSel.length;
-			var c = 0;
-			var a;
-
-			if (type === 'RemoveFirstIfFull') {
-				if (maxLength == 1) {
-					for (a = 1; a < l; a++) {
-						if (fObjSel.options[a].selected != 1) {
-							localArray_V[c] = fObjSel.options[a].value;
-							localArray_L[c] = fObjSel.options[a].text;
-							localArray_S[c] = 0;
-							localArray_T[c] = fObjSel.options[a].title;
-							c++;
-						}
-					}
-				} else {
-					return;
-				}
-			}
-
-			if ((type === "Remove" && fObjSel.size > 1) || type === "Top" || type === "Bottom") {
-				if (type === "Top") {
-					for (a=0;a<l;a++) {
-						if (fObjSel.options[a].selected==1) {
-							localArray_V[c]=fObjSel.options[a].value;
-							localArray_L[c]=fObjSel.options[a].text;
-							localArray_S[c]=1;
-							localArray_T[c] = fObjSel.options[a].title;
-							c++;
-						}
-					}
-				}
-				for (a=0;a<l;a++) {
-					if (fObjSel.options[a].selected!=1) {
-						localArray_V[c]=fObjSel.options[a].value;
-						localArray_L[c]=fObjSel.options[a].text;
-						localArray_S[c]=0;
-						localArray_T[c] = fObjSel.options[a].title;
-						c++;
-					}
-				}
-				if (type === "Bottom") {
-					for (a=0;a<l;a++) {
-						if (fObjSel.options[a].selected==1) {
-							localArray_V[c]=fObjSel.options[a].value;
-							localArray_L[c]=fObjSel.options[a].text;
-							localArray_S[c]=1;
-							localArray_T[c] = fObjSel.options[a].title;
-							c++;
-						}
-					}
-				}
-			}
-			if (type === "Down") {
-				var tC = 0;
-				var tA = [];
-				var aa = 0;
-
-				for (a=0;a<l;a++) {
-					if (fObjSel.options[a].selected!=1) {
-							// Add non-selected element:
-						localArray_V[c]=fObjSel.options[a].value;
-						localArray_L[c]=fObjSel.options[a].text;
-						localArray_S[c]=0;
-						localArray_T[c] = fObjSel.options[a].title;
-						c++;
-
-							// Transfer any accumulated and reset:
-						if (tA.length > 0) {
-							for (aa=0;aa<tA.length;aa++) {
-								localArray_V[c]=fObjSel.options[tA[aa]].value;
-								localArray_L[c]=fObjSel.options[tA[aa]].text;
-								localArray_S[c]=1;
-								localArray_T[c] = fObjSel.options[tA[aa]].title;
-								c++;
-							}
-
-							tC = 0;
-							tA = [];
-						}
-					} else {
-						tA[tC] = a;
-						tC++;
-					}
-				}
-					// Transfer any remaining:
-				if (tA.length > 0) {
-					for (aa=0;aa<tA.length;aa++) {
-						localArray_V[c]=fObjSel.options[tA[aa]].value;
-						localArray_L[c]=fObjSel.options[tA[aa]].text;
-						localArray_S[c]=1;
-						localArray_T[c] = fObjSel.options[tA[aa]].title;
-						c++;
-					}
-				}
-			}
-			if (type === "Up") {
-				var tC = 0;
-				var tA = [];
-				var aa = 0;
-				c = l-1;
-
-				for (a=l-1;a>=0;a--) {
-					if (fObjSel.options[a].selected!=1) {
-
-							// Add non-selected element:
-						localArray_V[c]=fObjSel.options[a].value;
-						localArray_L[c]=fObjSel.options[a].text;
-						localArray_S[c]=0;
-						localArray_T[c] = fObjSel.options[a].title;
-						c--;
-
-							// Transfer any accumulated and reset:
-						if (tA.length > 0) {
-							for (aa=0;aa<tA.length;aa++) {
-								localArray_V[c]=fObjSel.options[tA[aa]].value;
-								localArray_L[c]=fObjSel.options[tA[aa]].text;
-								localArray_S[c]=1;
-								localArray_T[c] = fObjSel.options[tA[aa]].title;
-								c--;
-							}
-
-							tC = 0;
-							tA = [];
-						}
-					} else {
-						tA[tC] = a;
-						tC++;
-					}
-				}
-					// Transfer any remaining:
-				if (tA.length > 0) {
-					for (aa=0;aa<tA.length;aa++) {
-						localArray_V[c]=fObjSel.options[tA[aa]].value;
-						localArray_L[c]=fObjSel.options[tA[aa]].text;
-						localArray_S[c]=1;
-						localArray_T[c] = fObjSel.options[tA[aa]].title;
-						c--;
-					}
-				}
-				c=l;	// Restore length value in "c"
-			}
-
-				// Transfer items in temporary storage to list object:
-			fObjSel.length = c;
-			for (a = 0; a < c; a++) {
-				fObjSel.options[a].value = localArray_V[a];
-				fObjSel.options[a].text = localArray_L[a];
-				fObjSel.options[a].selected = localArray_S[a];
-				fObjSel.options[a].title = localArray_T[a];
-			}
-			FormEngine.updateHiddenFieldValueFromSelect(fObjSel, formObj[fName]);
-
-			FormEngine.legacyFieldChangedCb();
-		}
-	};
-
-
-	/**
-	 * Legacy function
-	 * returns the DOM object for the given form name of the current form,
-	 * but only if the given field name is valid, legacy function, use "getFormElement" instead
-	 *
-	 * @param {String} fieldName the name of the field name
-	 * @returns {*|HTMLElement}
-	 */
-	setFormValue_getFObj = function(fieldName) {
-		var $formEl = FormEngine.getFormElement(fieldName);
-		if ($formEl.length > 0) {
-			// return the DOM element of the form object
-			return $formEl.get(0);
-		}
-		return null;
-	};
-
-	/**
-	 * returns a jQuery object for the given form name of the current form,
-	 * if the parameter "fieldName" is given, then the form element is only returned if the field name is available
-	 * the latter behaviour mirrors the one of the function "setFormValue_getFObj"
-	 *
-	 * @param {String} fieldName the field name to check for, optional
-	 * @returns {*|HTMLElement}
-	 */
-	FormEngine.getFormElement = function(fieldName) {
-		var $formEl = $('form[name="' + FormEngine.formName + '"]:first');
-		if (fieldName) {
-			var $fieldEl = FormEngine.getFieldElement(fieldName)
-					,$listFieldEl = FormEngine.getFieldElement(fieldName, '_list');
-
-			// Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element
-			if ($fieldEl.length > 0 &&
-				(
-					($fieldEl.prop('type') === 'select-one') ||
-					($listFieldEl.length > 0 && $listFieldEl.prop('type').match(/select-(one|multiple)/))
-				)
-			) {
-				return $formEl;
-			} else {
-				console.error('Form fields missing: form: ' + FormEngine.formName + ', field name: ' + fieldName);
-				alert('Form field is invalid');
-			}
-		} else {
-			return $formEl;
-		}
-	};
-
-
-	/**
-	 * Returns a jQuery object of the field DOM element of the current form, can also be used to
-	 * request an alternative field like "_hr", "_list" or "_mul"
-	 *
-	 * @param {String} fieldName the name of the field (<input name="fieldName">)
-	 * @param {String} appendix optional
-	 * @param {Boolean} noFallback if set, then the appendix value is returned no matter if it exists or not
-	 * @returns {*|HTMLElement}
-	 */
-	FormEngine.getFieldElement = function(fieldName, appendix, noFallback) {
-		var $formEl = FormEngine.getFormElement();
-
-		// if an appendix is set, return the field with the appendix (like _mul or _list)
-		if (appendix) {
-			var $fieldEl;
-			switch (appendix) {
-				case '_list':
-					$fieldEl = $(':input.tceforms-multiselect[data-formengine-input-name="' + fieldName + '"]', $formEl);
-					break;
-				case '_avail':
-					$fieldEl = $(':input[data-relatedfieldname="' + fieldName + '"]', $formEl);
-					break;
-				case '_mul':
-				case '_hr':
-					$fieldEl = $(':input[type=hidden][data-formengine-input-name="' + fieldName + '"]', $formEl);
-					break;
-			}
-			if (($fieldEl && $fieldEl.length > 0) || noFallback === true) {
-				return $fieldEl;
-			}
-		}
-
-		return $(':input[name="' + fieldName + '"]', $formEl);
-	};
-
-
-
-	/**************************************************
-	 * manipulate existing options in a select field
-	 **************************************************/
-
-	/**
-	 * Moves currently selected options from a select field to the very top,
-	 * can be multiple entries as well
-	 *
-	 * @param {Object} $fieldEl a jQuery object, containing the select field
-	 */
-	FormEngine.moveOptionToTop = function($fieldEl) {
-		// remove the selected options
-		var selectedOptions = $fieldEl.find(':selected').detach();
-		// and add them on first position again
-		$fieldEl.prepend(selectedOptions);
-	};
-
-
-	/**
-	 * moves currently selected options from a select field up by one position,
-	 * can be multiple entries as well
-	 *
-	 * @param {Object} $fieldEl a jQuery object, containing the select field
-	 */
-	FormEngine.moveOptionUp = function($fieldEl) {
-		// remove the selected options and add it before the previous sibling
-		$.each($fieldEl.find(':selected'), function(k, optionEl) {
-			var $optionEl = $(optionEl)
-					,$optionBefore = $optionEl.prev();
-
-			// stop if first option to move is already the first one
-			if (k == 0 && $optionBefore.length === 0) {
-				return false;
-			}
-
-			$optionBefore.before($optionEl.detach());
-		});
-	};
-
-
-	/**
-	 * moves currently selected options from a select field down one position,
-	 * can be multiple entries as well
-	 *
-	 * @param {Object} $fieldEl a jQuery object, containing the select field
-	 */
-	FormEngine.moveOptionDown = function($fieldEl) {
-		// remove the selected options and add it after the next sibling
-		// however, this time, we need to go from the last to the first
-		var selectedOptions = $fieldEl.find(':selected');
-		selectedOptions = $.makeArray(selectedOptions);
-		selectedOptions.reverse();
-		$.each(selectedOptions, function(k, optionEl) {
-			var $optionEl = $(optionEl)
-					,$optionAfter = $optionEl.next();
-
-			// stop if first option to move is already the last one
-			if (k == 0 && $optionAfter.length === 0) {
-				return false;
-			}
-
-			$optionAfter.after($optionEl.detach());
-		});
-	};
-
-
-	/**
-	 * moves currently selected options from a select field as the very last entries
-	 *
-	 * @param {Object} $fieldEl a jQuery object, containing the select field
-	 */
-	FormEngine.moveOptionToBottom = function($fieldEl) {
-		// remove the selected options
-		var selectedOptions = $fieldEl.find(':selected').detach();
-		// and add them on last position again
-		$fieldEl.append(selectedOptions);
-	};
-
-	/**
-	 * removes currently selected options from a select field
-	 *
-	 * @param {Object} $fieldEl a jQuery object, containing the select field
-	 * @param {Object} $availableFieldEl a jQuery object, containing all available value
-	 */
-	FormEngine.removeOption = function($fieldEl, $availableFieldEl) {
-		var $selected = $fieldEl.find(':selected');
-
-		$selected.each(function() {
-			$availableFieldEl
-				.find('option[value="' + $.escapeSelector($(this).attr('value')) + '"]')
-				.removeClass('hidden')
-				.prop('disabled', false);
-		});
-
-		// remove the selected options
-		$selected.remove();
-	};
-
-
-	/**
-	 * Initialize events for all form engine relevant tasks.
-	 * This function only needs to be called once on page load,
-	 * as it using deferrer methods only
-	 */
-	FormEngine.initializeEvents = function() {
-		if (top.TYPO3 && typeof top.TYPO3.Backend !== 'undefined') {
-			top.TYPO3.Backend.consumerScope.attach(FormEngine);
-			$(window).on('unload', function() {
-				top.TYPO3.Backend.consumerScope.detach(FormEngine);
-			});
-		}
-		$(document).on('click', '.t3js-btn-moveoption-top, .t3js-btn-moveoption-up, .t3js-btn-moveoption-down, .t3js-btn-moveoption-bottom, .t3js-btn-removeoption', function(evt) {
-			evt.preventDefault();
-
-			// track the arrows "Up", "Down", "Clear" etc in multi-select boxes
-			var $el = $(this)
-					,fieldName = $el.data('fieldname')
-					,$listFieldEl = FormEngine.getFieldElement(fieldName, '_list');
-
-			if ($listFieldEl.length > 0) {
-
-				if ($el.hasClass('t3js-btn-moveoption-top')) {
-					FormEngine.moveOptionToTop($listFieldEl);
-				} else if ($el.hasClass('t3js-btn-moveoption-up')) {
-					FormEngine.moveOptionUp($listFieldEl);
-				} else if ($el.hasClass('t3js-btn-moveoption-down')) {
-					FormEngine.moveOptionDown($listFieldEl);
-				} else if ($el.hasClass('t3js-btn-moveoption-bottom')) {
-					FormEngine.moveOptionToBottom($listFieldEl);
-				} else if ($el.hasClass('t3js-btn-removeoption')) {
-					var $availableFieldEl = FormEngine.getFieldElement(fieldName, '_avail');
-					FormEngine.removeOption($listFieldEl, $availableFieldEl);
-				}
-
-				// make sure to update the hidden field value when modifying the select value
-				FormEngine.updateHiddenFieldValueFromSelect($listFieldEl, FormEngine.getFieldElement(fieldName));
-				FormEngine.legacyFieldChangedCb();
-				if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') {
-					FormEngine.Validation.validate();
-				}
-			}
-		}).on('click', '.t3js-formengine-select-itemstoselect', function(evt) {
-			// in multi-select environments with two (e.g. "Access"), on click the item from the right should go to the left
-			var $el = $(this)
-				,fieldName = $el.data('relatedfieldname')
-				,exclusiveValues = $el.data('exclusivevalues');
-
-			if (fieldName) {
-				// try to add each selected field to the "left" select field
-				$el.find(':selected').each(function() {
-					var $optionEl = $(this);
-					FormEngine.setSelectOptionFromExternalSource(fieldName, $optionEl.prop('value'), $optionEl.text(), $optionEl.prop('title'), exclusiveValues, $optionEl);
-				});
-			}
-		}).on('click', '.t3js-editform-close', function(e) {
-			e.preventDefault();
-			FormEngine.preventExitIfNotSaved(
-				FormEngine.preventExitIfNotSavedCallback
-			);
-		}).on('click', '.t3js-editform-delete-record', function(e) {
-			e.preventDefault();
-			var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?';
-			var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?';
-			var $anchorElement = $(this);
-			var $modal = Modal.confirm(title, content, Severity.warning, [
-				{
-					text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'no'
-				},
-				{
-					text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record',
-					btnClass: 'btn-warning',
-					name: 'yes'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'no') {
-					Modal.dismiss();
-				} else if (e.target.name === 'yes') {
-					deleteRecord($anchorElement.data('table'), $anchorElement.data('uid'), $anchorElement.data('return-url'));
-					Modal.dismiss();
-				}
-			});
-		}).on('click', '.t3js-editform-delete-inline-record', function(e) {
-			e.preventDefault();
-			var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?';
-			var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?';
-			var $anchorElement = $(this);
-			var $modal = Modal.confirm(title, content, Severity.warning, [
-				{
-					text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'no'
-				},
-				{
-					text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record',
-					btnClass: 'btn-warning',
-					name: 'yes'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'no') {
-					Modal.dismiss();
-				} else if (e.target.name === 'yes') {
-					var objectId = $anchorElement.data('objectid');
-					inline.deleteRecord(objectId);
-					Modal.dismiss();
-				}
-			});
-		}).on('click', '.t3js-editform-submitButton', function(event) {
-			// remember the clicked submit button. we need to know that in TBE_EDITOR.submitForm();
-			var $me = $(this),
-				name = $me.data('name') || this.name,
-				$elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', '1');
-
-			$me.parents('form').append($elem);
-		}).on('change', '.t3-form-field-eval-null-checkbox input[type="checkbox"]', function(e) {
-			// Null checkboxes without placeholder click event handler
-			$(this).closest('.t3js-formengine-field-item').toggleClass('disabled');
-		}).on('change', '.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]', function(e) {
-			$(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').toggle();
-			$(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').toggle();
-		}).on('change', '.t3js-l10n-state-container input[type=radio]', function(event) {
-			// Change handler for "l10n_state" field changes
-			var $me = $(this);
-			var $input = $me.closest('.t3js-formengine-field-item').find('[data-formengine-input-name]');
-
-			if ($input.length > 0) {
-				var lastState = $input.data('last-l10n-state') || false,
-					currentState = $(this).val();
-
-				if (lastState && currentState === lastState) {
-					return;
-				}
-
-				if (currentState === 'custom') {
-					if (lastState) {
-						$(this).attr('data-original-language-value', $input.val());
-					}
-					$input.attr('disabled', false);
-				} else {
-					if (lastState === 'custom') {
-						$(this).closest('.t3js-l10n-state-container').find('.t3js-l10n-state-custom').attr('data-original-language-value', $input.val());
-					}
-					$input.attr('disabled', 'disabled');
-				}
-
-				$input.val($(this).attr('data-original-language-value')).trigger('change');
-				$input.data('last-l10n-state', $(this).val());
-			}
-		}).on('formengine.dp.change', function(event, $field) {
-			FormEngine.Validation.validate();
-			FormEngine.Validation.markFieldAsChanged($field);
-		});
-	};
-
-	/**
-	 * @param {InteractionRequest} interactionRequest
-	 * @return {jQuery.Deferred}
-	 */
-	FormEngine.consume = function(interactionRequest) {
-		if (!interactionRequest) {
-			throw new BackendException('No interaction request given', 1496589980);
-		}
-		if (interactionRequest.concernsTypes(FormEngine.consumeTypes)) {
-			var outerMostRequest = interactionRequest.outerMostRequest;
-			var deferred = $.Deferred();
-
-			FormEngine.interactionRequestMap.attachFor(
-				outerMostRequest,
-				deferred
-			);
-			// resolve or reject deferreds with previous user choice
-			if (outerMostRequest.isProcessed()) {
-				handleConsumeResponse(
-					outerMostRequest,
-					outerMostRequest.getProcessedData().response
-				);
-			// show confirmation dialog
-			} else if (FormEngine.hasChange()) {
-				FormEngine.preventExitIfNotSaved(function(response) {
-					outerMostRequest.setProcessedData(
-						{response: response}
-					);
-					handleConsumeResponse(outerMostRequest, response);
-				});
-			// resolve directly
-			} else {
-				FormEngine.interactionRequestMap.resolveFor(outerMostRequest);
-			}
-
-			return deferred;
-		}
-	};
-
-	/**
-	 * Initializes the remaining character views based on the fields' maxlength attribute
-	 */
-	FormEngine.initializeRemainingCharacterViews = function() {
-		// all fields with a "maxlength" attribute
-		var $maxlengthElements = $('[maxlength]').not('.t3js-datetimepicker').not('.t3js-charcounter-initialized');
-		$maxlengthElements.on('focus', function(e) {
-			var $field = $(this),
-				$parent = $field.parents('.t3js-formengine-field-item:first'),
-				maxlengthProperties = FormEngine.getCharacterCounterProperties($field);
-
-			// append the counter only at focus to avoid cluttering the DOM
-			$parent.append($('<div />', {'class': 't3js-charcounter'}).append(
-				$('<span />', {'class': maxlengthProperties.labelClass}).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters))
-			));
-		}).on('blur', function() {
-			var $field = $(this),
-				$parent = $field.parents('.t3js-formengine-field-item:first');
-			$parent.find('.t3js-charcounter').remove();
-		}).on('keyup', function() {
-			var $field = $(this),
-				$parent = $field.parents('.t3js-formengine-field-item:first'),
-				maxlengthProperties = FormEngine.getCharacterCounterProperties($field);
-
-			// change class and value
-			$parent.find('.t3js-charcounter span').removeClass().addClass(maxlengthProperties.labelClass).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters))
-		});
-		$maxlengthElements.addClass('t3js-charcounter-initialized');
-		$(':password').on('focus', function() {
-			$(this).attr('type', 'text').select();
-		}).on('blur', function() {
-			$(this).attr('type', 'password');
-		});
-	};
-
-	/**
-	 * Initialize select checkbox element checkboxes
-	 */
-	FormEngine.initializeSelectCheckboxes = function() {
-		$('.t3js-toggle-checkboxes').each(function() {
-			var $checkbox = $(this);
-			var $table = $checkbox.closest('table');
-			var $checkboxes = $table.find('.t3js-checkbox');
-			var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length;
-			$checkbox.prop('checked', checkIt);
-		});
-		$(document).on('change', '.t3js-toggle-checkboxes', function(e) {
-			e.preventDefault();
-			var $checkbox = $(this);
-			var $table = $checkbox.closest('table');
-			var $checkboxes = $table.find('.t3js-checkbox');
-			var checkIt = $checkboxes.length !== $table.find('.t3js-checkbox:checked').length;
-			$checkboxes.prop('checked', checkIt);
-			$checkbox.prop('checked', checkIt);
-		});
-		$(document).on('change', '.t3js-checkbox', function(e) {
-			FormEngine.updateCheckboxState(this);
-		});
-	};
-
-	/**
-	 *
-	 * @param {HTMLElement} source
-     */
-	FormEngine.updateCheckboxState = function(source) {
-		var $sourceElement = $(source);
-		var $table = $sourceElement.closest('table');
-		var $checkboxes = $table.find('.t3js-checkbox');
-		var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length;
-		$table.find('.t3js-toggle-checkboxes').prop('checked', checkIt);
-	};
-
-	/**
-	 * Get the properties required for proper rendering of the character counter
-	 *
-	 * @param {Object} $field
-	 * @returns {{remainingCharacters: number, labelClass: string}}
-	 */
-	FormEngine.getCharacterCounterProperties = function($field) {
-		var fieldText = $field.val(),
-			maxlength = $field.attr('maxlength'),
-			currentFieldLength = fieldText.length,
-			numberOfLineBreaks = (fieldText.match(/\n/g)||[]).length, // count line breaks
-			remainingCharacters = maxlength - currentFieldLength - numberOfLineBreaks,
-			threshold = 15, // hard limit of remaining characters when the label class changes
-			labelClass = '';
-
-		if (remainingCharacters < threshold) {
-			labelClass = 'label-danger';
-		} else if(remainingCharacters < threshold * 2) {
-			labelClass = 'label-warning';
-		} else {
-			labelClass = 'label-info';
-		}
-
-		return {
-			remainingCharacters: remainingCharacters,
-			labelClass: 'label ' + labelClass
-		};
-	};
-
-	/**
-	 * Select field filter functions, see TCA option "enableMultiSelectFilterTextfield"
-	 * and "multiSelectFilterItems"
-	 */
-	FormEngine.SelectBoxFilter = {
-		options: {
-			fieldContainerSelector: '.t3js-formengine-field-group',
-			filterContainerSelector: '.t3js-formengine-multiselect-filter-container',
-			filterTextFieldSelector: '.t3js-formengine-multiselect-filter-textfield',
-			filterSelectFieldSelector: '.t3js-formengine-multiselect-filter-dropdown',
-			itemsToSelectElementSelector: '.t3js-formengine-select-itemstoselect'
-		}
-	};
-
-	/**
-	 * Make sure that all selectors and input filters are recognized
-	 * note: this also works on elements that are loaded asynchronously via AJAX, no need to call this method
-	 * after an AJAX load.
-	 */
-	FormEngine.SelectBoxFilter.initializeEvents = function() {
-		$(document).on('keyup', FormEngine.SelectBoxFilter.options.filterTextFieldSelector, function() {
-			var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this));
-			FormEngine.SelectBoxFilter.filter($selectElement, $(this).val());
-		}).on('change', FormEngine.SelectBoxFilter.options.filterSelectFieldSelector, function() {
-			var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this));
-			FormEngine.SelectBoxFilter.filter($selectElement, $(this).val());
-		});
-	};
-
-	/**
-	 * Fetch the "itemstoselect" select element where a filter item is attached to
-	 *
-	 * @param {Object} $relativeElement
-	 * @returns {*}
-	 */
-	FormEngine.SelectBoxFilter.getSelectElement = function($relativeElement) {
-		var $containerElement = $relativeElement.closest(FormEngine.SelectBoxFilter.options.fieldContainerSelector);
-		return $containerElement.find(FormEngine.SelectBoxFilter.options.itemsToSelectElementSelector);
-	};
-
-	/**
-	 * Filter the actual items
-	 *
-	 * @param {Object} $selectElement
-	 * @param {String} filterText
-	 */
-	FormEngine.SelectBoxFilter.filter = function($selectElement, filterText) {
-		var $allOptionElements;
-		if (!$selectElement.data('alloptions')) {
-			$allOptionElements = $selectElement.find('option').clone();
-			$selectElement.data('alloptions', $allOptionElements);
-		} else {
-			$allOptionElements = $selectElement.data('alloptions');
-		}
-
-		if (filterText.length > 0) {
-			var matchFilter = new RegExp(filterText, 'i');
-			$selectElement.html('');
-			$allOptionElements.each(function() {
-				var $item = $(this);
-				if ($item.text().match(matchFilter)) {
-					$selectElement.append($item.clone());
-				}
-			});
-		} else {
-			$selectElement.html($allOptionElements);
-		}
-	};
-
-	/**
-	 * convert all textareas so they grow when it is typed in.
-	 */
-	FormEngine.convertTextareasResizable = function() {
-		var $elements = $('.t3js-formengine-textarea');
-		if (TYPO3.settings.Textarea && TYPO3.settings.Textarea.autosize && $elements.length) {
-			require(['autosize'], function(autosize) {
-				autosize($elements);
-			});
-		}
-	};
-
-	/**
-	 * convert all textareas to enable tab
-	 */
-	FormEngine.convertTextareasEnableTab = function() {
-		var $elements = $('.t3js-enable-tab');
-		if ($elements.length) {
-			require(['taboverride'], function(taboverride) {
-				taboverride.set($elements);
-			});
-		}
-	};
-
-	/**
-	 * Initialize input / text field "null" checkbox CSS overlay if no placeholder is set.
-	 */
-	FormEngine.initializeNullNoPlaceholderCheckboxes = function() {
-		$('.t3-form-field-eval-null-checkbox').each(function() {
-			// Add disabled class to "t3js-formengine-field-item" if the null checkbox is NOT set,
-			// This activates a CSS overlay "disabling" the input field and everything around.
-			var $checkbox = $(this).find('input[type="checkbox"]');
-			var $fieldItem = $(this).closest('.t3js-formengine-field-item');
-			if (!$checkbox.attr('checked')) {
-				$fieldItem.addClass('disabled');
-			}
-		});
-	};
-
-	/**
-	 * Initialize input / text field "null" checkbox placeholder / real field if placeholder is set.
-	 */
-	FormEngine.initializeNullWithPlaceholderCheckboxes = function() {
-		$('.t3js-form-field-eval-null-placeholder-checkbox').each(function() {
-			// Set initial state of both div's (one containing actual field, other containing placeholder field)
-			// depending on whether checkbox is checked or not
-			var $checkbox = $(this).find('input[type="checkbox"]');
-			if ($checkbox.attr('checked')) {
-				$(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').hide();
-			} else {
-				$(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').hide();
-			}
-		});
-	};
-
-	/**
-	 * This is the main function that is called on page load, but also after elements are asynchronously
-	 * called e.g. after inline elements are loaded, or a new flexform section is added.
-	 * Use this function in your extension like this "TYPO3.FormEngine.initialize()"
-	 * if you add new fields dynamically.
-	 */
-	FormEngine.reinitialize = function() {
-		// Apply "close" button to all input / datetime fields
-		if ($('.t3js-clearable').length) {
-			require(['TYPO3/CMS/Backend/jquery.clearable'], function() {
-				$('.t3js-clearable').clearable();
-			});
-		}
-		if ($('.t3-form-suggest').length) {
-			require(['TYPO3/CMS/Backend/FormEngineSuggest'], function(Suggest) {
-				Suggest($('.t3-form-suggest'));
-			});
-		}
-		// Apply DatePicker to all date time fields
-		if ($('.t3js-datetimepicker').length) {
-			require(['TYPO3/CMS/Backend/DateTimePicker'], function(DateTimePicker) {
-				DateTimePicker.initialize();
-			});
-		}
-
-		FormEngine.convertTextareasResizable();
-		FormEngine.convertTextareasEnableTab();
-		FormEngine.initializeNullNoPlaceholderCheckboxes();
-		FormEngine.initializeNullWithPlaceholderCheckboxes();
-		FormEngine.initializeInputLinkToggle();
-		FormEngine.initializeLocalizationStateSelector();
-		FormEngine.initializeRemainingCharacterViews();
-	};
-
-	/**
-	 * Disable the input field on load if localization state selector is set to "parent" or "source"
-	 */
-	FormEngine.initializeLocalizationStateSelector = function() {
-		$('.t3js-l10n-state-container').each(function() {
-			var $input = $(this).closest('.t3js-formengine-field-item').find('[data-formengine-input-name]');
-			var currentState = $(this).find('input[type="radio"]:checked').val();
-			if (currentState === 'parent' || currentState === 'source') {
-				$input.attr('disabled', 'disabled');
-			}
-		});
-	};
-
-	/**
-	 * Toggle for input link explanation
-	 */
-	FormEngine.initializeInputLinkToggle = function() {
-		var toggleClass = '.t3js-form-field-inputlink-explanation-toggle',
-			inputFieldClass = '.t3js-form-field-inputlink-input',
-			explanationClass = '.t3js-form-field-inputlink-explanation';
-
-		// if empty, show input field
-		$(explanationClass).filter(function () {
-			return !$.trim($(this).val());
-		}).each(function () {
-			var $group = $(this).closest('.t3js-form-field-inputlink'),
-				$inputField = $group.find(inputFieldClass),
-				$explanationField = $group.find(explanationClass);
-			$explanationField.toggleClass('hidden', true);
-			$inputField.toggleClass('hidden', false);
-			$group.find('.form-control-clearable button.close').toggleClass('hidden', false)
-		});
-
-		$(document).on('click', toggleClass, function (e) {
-			e.preventDefault();
-
-			var $group = $(this).closest('.t3js-form-field-inputlink'),
-				$inputField = $group.find(inputFieldClass),
-				$explanationField = $group.find(explanationClass),
-				explanationShown;
-
-			explanationShown = !$explanationField.hasClass('hidden');
-			$explanationField.toggleClass('hidden', explanationShown);
-			$inputField.toggleClass('hidden', !explanationShown);
-			$group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown)
-		});
-
-		$(inputFieldClass).on('change', function () {
-			var $group = $(this).closest('.t3js-form-field-inputlink'),
-				$inputField = $group.find(inputFieldClass),
-				$explanationField = $group.find(explanationClass),
-				explanationShown;
-
-			if (!$explanationField.hasClass('hidden')) {
-
-				explanationShown = !$explanationField.hasClass('hidden');
-				$explanationField.toggleClass('hidden', explanationShown);
-				$inputField.toggleClass('hidden', !explanationShown);
-				$group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown)
-			}
-		});
-	};
-
-	/**
-	 * @return {boolean}
-	 */
-	FormEngine.hasChange = function() {
-		return $('form[name="' + FormEngine.formName + '"] .has-change').length > 0;
-	};
-
-	/**
-	 * @param {boolean} response
-	 */
-	FormEngine.preventExitIfNotSavedCallback = function(response) {
-		if (response) {
-			FormEngine.closeDocument();
-		}
-	};
-
-	/**
-	 * Show modal to confirm closing the document without saving.
-	 *
-	 * @param {Function} callback
-	 */
-	FormEngine.preventExitIfNotSaved = function(callback) {
-		callback = callback || FormEngine.preventExitIfNotSavedCallback;
-
-		if (FormEngine.hasChange()) {
-			var title = TYPO3.lang['label.confirm.close_without_save.title'] || 'Do you want to quit without saving?';
-			var content = TYPO3.lang['label.confirm.close_without_save.content'] || 'You have currently unsaved changes. Are you sure that you want to discard all changes?';
-			var $modal = Modal.confirm(title, content, Severity.warning, [
-				{
-					text: TYPO3.lang['buttons.confirm.close_without_save.no'] || 'No, I will continue editing',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'no'
-				},
-				{
-					text: TYPO3.lang['buttons.confirm.close_without_save.yes'] || 'Yes, discard my changes',
-					btnClass: 'btn-warning',
-					name: 'yes'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'no') {
-					Modal.dismiss();
-					callback.call(null, false);
-				} else if (e.target.name === 'yes') {
-					Modal.dismiss();
-					callback.call(null, true);
-				}
-			});
-		} else {
-			callback.call(null, true);
-		}
-	};
-
-	/**
-	 * Show modal to confirm closing the document without saving
-	 */
-	FormEngine.preventSaveIfHasErrors = function() {
-		if ($('.has-error').length > 0) {
-			var title = TYPO3.lang['label.alert.save_with_error.title'] || 'You have errors in your form!';
-			var content = TYPO3.lang['label.alert.save_with_error.content'] || 'Please check the form, there is at least one error in your form.';
-			var $modal = Modal.confirm(title, content, Severity.error, [
-				{
-					text: TYPO3.lang['buttons.alert.save_with_error.ok'] || 'OK',
-					btnClass: 'btn-danger',
-					name: 'ok'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'ok') {
-					Modal.dismiss();
-				}
-			});
-			return false;
-		}
-		return true;
-	};
-
-	/**
-	 * Close current open document
-	 */
-	FormEngine.closeDocument = function() {
-		document.editform.closeDoc.value=1;
-		document.editform.submit();
-	};
-
-	/**
-	 * Main init function called from outside
-	 *
-	 * Sets some options and registers the DOMready handler to initialize further things
-	 *
-	 * @param {String} browserUrl
-	 * @param {Number} mode
-	 */
-	FormEngine.initialize = function(browserUrl, mode) {
-		FormEngine.browserUrl = browserUrl;
-		FormEngine.Validation.setUsMode(mode);
-
-		$(function() {
-			FormEngine.initializeEvents();
-			FormEngine.SelectBoxFilter.initializeEvents();
-			FormEngine.initializeSelectCheckboxes();
-			FormEngine.Validation.initialize();
-			FormEngine.reinitialize();
-			$('#t3js-ui-block').remove();
-		});
-	};
-
-	// load required modules to hook in the post initialize function
-	if (undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine']) {
-		$.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine'], function(pos, moduleName) {
-			require([moduleName]);
-		});
-	}
-
-	// make the form engine object publicly visible for other objects in the TYPO3 namespace
-	TYPO3.FormEngine = FormEngine;
-
-	// return the object in the global space
-	return FormEngine;
+  'TYPO3/CMS/Backend/FormEngineValidation',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/BackendException',
+  'TYPO3/CMS/Backend/Event/InteractionRequestMap'
+], function($, FormEngineValidation, Modal, Severity, BackendException, InteractionRequestMap) {
+
+  /**
+   * @param {InteractionRequest} interactionRequest
+   * @param {boolean} response
+   */
+  function handleConsumeResponse(interactionRequest, response) {
+    if (response) {
+      FormEngine.interactionRequestMap.resolveFor(interactionRequest);
+    } else {
+      FormEngine.interactionRequestMap.rejectFor(interactionRequest);
+    }
+  }
+
+  /**
+   * @exports TYPO3/CMS/Backend/FormEngine
+   */
+  var FormEngine = {
+    consumeTypes: ['typo3.setUrl', 'typo3.beforeSetUrl', 'typo3.refresh'],
+    Validation: FormEngineValidation,
+    interactionRequestMap: InteractionRequestMap,
+    formName: TYPO3.settings.FormEngine.formName,
+    openedPopupWindow: null,
+    legacyFieldChangedCb: function() {
+      !$.isFunction(TYPO3.settings.FormEngine.legacyFieldChangedCb) || TYPO3.settings.FormEngine.legacyFieldChangedCb();
+    },
+    browserUrl: ''
+  };
+
+  // functions to connect the db/file browser with this document and the formfields on it!
+
+  /**
+   * Opens a popup window with the element browser (browser.php)
+   *
+   * @param {String} mode can be "db" or "file"
+   * @param {String} params additional params for the browser window
+   */
+  FormEngine.openPopupWindow = setFormValueOpenBrowser = function(mode, params) {
+    Modal.advanced({
+      type: Modal.types.iframe,
+      content: FormEngine.browserUrl + '&mode=' + mode + '&bparams=' + params,
+      size: Modal.sizes.large
+    });
+  };
+
+  /**
+   * properly fills the select field from the popup window (element browser, link browser)
+   * or from a multi-select (two selects side-by-side)
+   * previously known as "setFormValueFromBrowseWin"
+   *
+   * @param {String} fieldName Formerly known as "fName" name of the field, like [tt_content][2387][header]
+   * @param {(String|Number)} value The value to fill in (could be an integer)
+   * @param {String} label The visible name in the selector
+   * @param {String} title The title when hovering over it
+   * @param {String} exclusiveValues If the select field has exclusive options that are not combine-able
+   * @param {$} $optionEl The jQuery object of the selected <option> tag
+   */
+  FormEngine.setSelectOptionFromExternalSource = setFormValueFromBrowseWin = function(fieldName, value, label, title, exclusiveValues, $optionEl) {
+    exclusiveValues = String(exclusiveValues);
+
+    var $fieldEl,
+      $originalFieldEl,
+      isMultiple = false,
+      isList = false;
+
+    $originalFieldEl = $fieldEl = FormEngine.getFieldElement(fieldName);
+
+    if ($originalFieldEl.length === 0 || value === '--div--') {
+      return;
+    }
+
+    // Check if the form object has a "_list" element
+    // The "_list" element exists for multiple selection select types
+    var $listFieldEl = FormEngine.getFieldElement(fieldName, '_list', true);
+    if ($listFieldEl.length > 0) {
+      $fieldEl = $listFieldEl;
+      isMultiple = ($fieldEl.prop('multiple') && $fieldEl.prop('size') != '1');
+      isList = true;
+    }
+
+    // clear field before adding value, if configured so (maxitems==1)
+    // @todo: clean this code
+    if (typeof TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName] !== 'undefined') {
+      var clearSettings = TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[fieldName];
+      $fieldEl.empty();
+
+      // Clear the upload field
+      // @todo: Investigate whether we either need to fix this code or we can drop it.
+      var filesContainer = document.getElementById(clearSettings.itemFormElID_file);
+      if (filesContainer) {
+        filesContainer.innerHTML = filesContainer.innerHTML;
+      }
+    }
+
+    if (isMultiple || isList) {
+      // If multiple values are not allowed, clear anything that is in the control already
+      if (!isMultiple) {
+        $fieldEl.empty();
+      }
+
+      // Clear elements if exclusive values are found
+      if (exclusiveValues) {
+        var reenableOptions = false;
+
+        var m = new RegExp('(^|,)' + value + '($|,)');
+        // the new value is exclusive => remove all existing values
+        if (exclusiveValues.match(m)) {
+          $fieldEl.empty();
+          reenableOptions = true;
+        } else if ($fieldEl.find('option').length == 1) {
+          // there is an old value and it was exclusive => it has to be removed
+          m = new RegExp("(^|,)" + $fieldEl.find('option').prop('value') + "($|,)");
+          if (exclusiveValues.match(m)) {
+            $fieldEl.empty();
+            reenableOptions = true;
+          }
+        }
+
+        if (reenableOptions && typeof $optionEl !== 'undefined') {
+          $optionEl.closest('select').find('[disabled]').removeClass('hidden').prop('disabled', false)
+        }
+      }
+
+      // Inserting the new element
+      var addNewValue = true;
+
+      // check if there is a "_mul" field (a field on the right) and if the field was already added
+      var $multipleFieldEl = FormEngine.getFieldElement(fieldName, '_mul', true);
+      if ($multipleFieldEl.length == 0 || $multipleFieldEl.val() == 0) {
+        $fieldEl.find('option').each(function(k, optionEl) {
+          if ($(optionEl).prop('value') == value) {
+            addNewValue = false;
+            return false;
+          }
+        });
+
+        if (addNewValue && typeof $optionEl !== 'undefined') {
+          $optionEl.addClass('hidden').prop('disabled', true);
+        }
+      }
+
+      // element can be added
+      if (addNewValue) {
+        // finally add the option
+        var $option = $('<option></option>');
+        $option.attr({value: value, title: title}).text(label);
+        $option.appendTo($fieldEl);
+
+        // set the hidden field
+        FormEngine.updateHiddenFieldValueFromSelect($fieldEl, $originalFieldEl);
+
+        // execute the phpcode from $FormEngine->TBE_EDITOR_fieldChanged_func
+        FormEngine.legacyFieldChangedCb();
+      }
+
+    } else {
+
+      // The incoming value consists of the table name, an underscore and the uid
+      // or just the uid
+      // For a single selection field we need only the uid, so we extract it
+      var pattern = /_(\\d+)$/
+        , result = value.toString().match(pattern);
+
+      if (result != null) {
+        value = result[1];
+      }
+
+      // Change the selected value
+      $fieldEl.val(value);
+    }
+    if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') {
+      FormEngine.Validation.validate();
+    }
+  };
+
+  /**
+   * sets the value of the hidden field, from the select list, always executed after the select field was updated
+   * previously known as global function setHiddenFromList()
+   *
+   * @param {HTMLElement} selectFieldEl the select field
+   * @param {HTMLElement} originalFieldEl the hidden form field
+   */
+  FormEngine.updateHiddenFieldValueFromSelect = setHiddenFromList = function(selectFieldEl, originalFieldEl) {
+    var selectedValues = [];
+    $(selectFieldEl).find('option').each(function() {
+      selectedValues.push($(this).prop('value'));
+    });
+
+    // make a comma separated list, if it is a multi-select
+    // set the values to the final hidden field
+    $(originalFieldEl).val(selectedValues.join(','));
+  };
+
+  /**
+   * legacy function, can be removed once this function is not in use anymore
+   *
+   * @param {String} fName
+   * @param {String} type
+   * @param {Number} maxLength
+   */
+  setFormValueManipulate = function(fName, type, maxLength) {
+    var $formEl = FormEngine.getFormElement(fName);
+    if ($formEl.length > 0) {
+      var formObj = $formEl.get(0);
+      var localArray_V = [];
+      var localArray_L = [];
+      var localArray_S = [];
+      var localArray_T = [];
+      var fObjSel = formObj[fName + '_list'];
+      var l = fObjSel.length;
+      var c = 0;
+      var a;
+
+      if (type === 'RemoveFirstIfFull') {
+        if (maxLength == 1) {
+          for (a = 1; a < l; a++) {
+            if (fObjSel.options[a].selected != 1) {
+              localArray_V[c] = fObjSel.options[a].value;
+              localArray_L[c] = fObjSel.options[a].text;
+              localArray_S[c] = 0;
+              localArray_T[c] = fObjSel.options[a].title;
+              c++;
+            }
+          }
+        } else {
+          return;
+        }
+      }
+
+      if ((type === "Remove" && fObjSel.size > 1) || type === "Top" || type === "Bottom") {
+        if (type === "Top") {
+          for (a = 0; a < l; a++) {
+            if (fObjSel.options[a].selected == 1) {
+              localArray_V[c] = fObjSel.options[a].value;
+              localArray_L[c] = fObjSel.options[a].text;
+              localArray_S[c] = 1;
+              localArray_T[c] = fObjSel.options[a].title;
+              c++;
+            }
+          }
+        }
+        for (a = 0; a < l; a++) {
+          if (fObjSel.options[a].selected != 1) {
+            localArray_V[c] = fObjSel.options[a].value;
+            localArray_L[c] = fObjSel.options[a].text;
+            localArray_S[c] = 0;
+            localArray_T[c] = fObjSel.options[a].title;
+            c++;
+          }
+        }
+        if (type === "Bottom") {
+          for (a = 0; a < l; a++) {
+            if (fObjSel.options[a].selected == 1) {
+              localArray_V[c] = fObjSel.options[a].value;
+              localArray_L[c] = fObjSel.options[a].text;
+              localArray_S[c] = 1;
+              localArray_T[c] = fObjSel.options[a].title;
+              c++;
+            }
+          }
+        }
+      }
+      if (type === "Down") {
+        var tC = 0;
+        var tA = [];
+        var aa = 0;
+
+        for (a = 0; a < l; a++) {
+          if (fObjSel.options[a].selected != 1) {
+            // Add non-selected element:
+            localArray_V[c] = fObjSel.options[a].value;
+            localArray_L[c] = fObjSel.options[a].text;
+            localArray_S[c] = 0;
+            localArray_T[c] = fObjSel.options[a].title;
+            c++;
+
+            // Transfer any accumulated and reset:
+            if (tA.length > 0) {
+              for (aa = 0; aa < tA.length; aa++) {
+                localArray_V[c] = fObjSel.options[tA[aa]].value;
+                localArray_L[c] = fObjSel.options[tA[aa]].text;
+                localArray_S[c] = 1;
+                localArray_T[c] = fObjSel.options[tA[aa]].title;
+                c++;
+              }
+
+              tC = 0;
+              tA = [];
+            }
+          } else {
+            tA[tC] = a;
+            tC++;
+          }
+        }
+        // Transfer any remaining:
+        if (tA.length > 0) {
+          for (aa = 0; aa < tA.length; aa++) {
+            localArray_V[c] = fObjSel.options[tA[aa]].value;
+            localArray_L[c] = fObjSel.options[tA[aa]].text;
+            localArray_S[c] = 1;
+            localArray_T[c] = fObjSel.options[tA[aa]].title;
+            c++;
+          }
+        }
+      }
+      if (type === "Up") {
+        var tC = 0;
+        var tA = [];
+        var aa = 0;
+        c = l - 1;
+
+        for (a = l - 1; a >= 0; a--) {
+          if (fObjSel.options[a].selected != 1) {
+
+            // Add non-selected element:
+            localArray_V[c] = fObjSel.options[a].value;
+            localArray_L[c] = fObjSel.options[a].text;
+            localArray_S[c] = 0;
+            localArray_T[c] = fObjSel.options[a].title;
+            c--;
+
+            // Transfer any accumulated and reset:
+            if (tA.length > 0) {
+              for (aa = 0; aa < tA.length; aa++) {
+                localArray_V[c] = fObjSel.options[tA[aa]].value;
+                localArray_L[c] = fObjSel.options[tA[aa]].text;
+                localArray_S[c] = 1;
+                localArray_T[c] = fObjSel.options[tA[aa]].title;
+                c--;
+              }
+
+              tC = 0;
+              tA = [];
+            }
+          } else {
+            tA[tC] = a;
+            tC++;
+          }
+        }
+        // Transfer any remaining:
+        if (tA.length > 0) {
+          for (aa = 0; aa < tA.length; aa++) {
+            localArray_V[c] = fObjSel.options[tA[aa]].value;
+            localArray_L[c] = fObjSel.options[tA[aa]].text;
+            localArray_S[c] = 1;
+            localArray_T[c] = fObjSel.options[tA[aa]].title;
+            c--;
+          }
+        }
+        c = l;	// Restore length value in "c"
+      }
+
+      // Transfer items in temporary storage to list object:
+      fObjSel.length = c;
+      for (a = 0; a < c; a++) {
+        fObjSel.options[a].value = localArray_V[a];
+        fObjSel.options[a].text = localArray_L[a];
+        fObjSel.options[a].selected = localArray_S[a];
+        fObjSel.options[a].title = localArray_T[a];
+      }
+      FormEngine.updateHiddenFieldValueFromSelect(fObjSel, formObj[fName]);
+
+      FormEngine.legacyFieldChangedCb();
+    }
+  };
+
+
+  /**
+   * Legacy function
+   * returns the DOM object for the given form name of the current form,
+   * but only if the given field name is valid, legacy function, use "getFormElement" instead
+   *
+   * @param {String} fieldName the name of the field name
+   * @returns {*|HTMLElement}
+   */
+  setFormValue_getFObj = function(fieldName) {
+    var $formEl = FormEngine.getFormElement(fieldName);
+    if ($formEl.length > 0) {
+      // return the DOM element of the form object
+      return $formEl.get(0);
+    }
+    return null;
+  };
+
+  /**
+   * returns a jQuery object for the given form name of the current form,
+   * if the parameter "fieldName" is given, then the form element is only returned if the field name is available
+   * the latter behaviour mirrors the one of the function "setFormValue_getFObj"
+   *
+   * @param {String} fieldName the field name to check for, optional
+   * @returns {*|HTMLElement}
+   */
+  FormEngine.getFormElement = function(fieldName) {
+    var $formEl = $('form[name="' + FormEngine.formName + '"]:first');
+    if (fieldName) {
+      var $fieldEl = FormEngine.getFieldElement(fieldName)
+        , $listFieldEl = FormEngine.getFieldElement(fieldName, '_list');
+
+      // Take the form object if it is either of type select-one or of type-multiple and it has a "_list" element
+      if ($fieldEl.length > 0 &&
+        (
+          ($fieldEl.prop('type') === 'select-one') ||
+          ($listFieldEl.length > 0 && $listFieldEl.prop('type').match(/select-(one|multiple)/))
+        )
+      ) {
+        return $formEl;
+      } else {
+        console.error('Form fields missing: form: ' + FormEngine.formName + ', field name: ' + fieldName);
+        alert('Form field is invalid');
+      }
+    } else {
+      return $formEl;
+    }
+  };
+
+
+  /**
+   * Returns a jQuery object of the field DOM element of the current form, can also be used to
+   * request an alternative field like "_hr", "_list" or "_mul"
+   *
+   * @param {String} fieldName the name of the field (<input name="fieldName">)
+   * @param {String} appendix optional
+   * @param {Boolean} noFallback if set, then the appendix value is returned no matter if it exists or not
+   * @returns {*|HTMLElement}
+   */
+  FormEngine.getFieldElement = function(fieldName, appendix, noFallback) {
+    var $formEl = FormEngine.getFormElement();
+
+    // if an appendix is set, return the field with the appendix (like _mul or _list)
+    if (appendix) {
+      var $fieldEl;
+      switch (appendix) {
+        case '_list':
+          $fieldEl = $(':input.tceforms-multiselect[data-formengine-input-name="' + fieldName + '"]', $formEl);
+          break;
+        case '_avail':
+          $fieldEl = $(':input[data-relatedfieldname="' + fieldName + '"]', $formEl);
+          break;
+        case '_mul':
+        case '_hr':
+          $fieldEl = $(':input[type=hidden][data-formengine-input-name="' + fieldName + '"]', $formEl);
+          break;
+      }
+      if (($fieldEl && $fieldEl.length > 0) || noFallback === true) {
+        return $fieldEl;
+      }
+    }
+
+    return $(':input[name="' + fieldName + '"]', $formEl);
+  };
+
+
+  /**************************************************
+   * manipulate existing options in a select field
+   **************************************************/
+
+  /**
+   * Moves currently selected options from a select field to the very top,
+   * can be multiple entries as well
+   *
+   * @param {Object} $fieldEl a jQuery object, containing the select field
+   */
+  FormEngine.moveOptionToTop = function($fieldEl) {
+    // remove the selected options
+    var selectedOptions = $fieldEl.find(':selected').detach();
+    // and add them on first position again
+    $fieldEl.prepend(selectedOptions);
+  };
+
+
+  /**
+   * moves currently selected options from a select field up by one position,
+   * can be multiple entries as well
+   *
+   * @param {Object} $fieldEl a jQuery object, containing the select field
+   */
+  FormEngine.moveOptionUp = function($fieldEl) {
+    // remove the selected options and add it before the previous sibling
+    $.each($fieldEl.find(':selected'), function(k, optionEl) {
+      var $optionEl = $(optionEl)
+        , $optionBefore = $optionEl.prev();
+
+      // stop if first option to move is already the first one
+      if (k == 0 && $optionBefore.length === 0) {
+        return false;
+      }
+
+      $optionBefore.before($optionEl.detach());
+    });
+  };
+
+
+  /**
+   * moves currently selected options from a select field down one position,
+   * can be multiple entries as well
+   *
+   * @param {Object} $fieldEl a jQuery object, containing the select field
+   */
+  FormEngine.moveOptionDown = function($fieldEl) {
+    // remove the selected options and add it after the next sibling
+    // however, this time, we need to go from the last to the first
+    var selectedOptions = $fieldEl.find(':selected');
+    selectedOptions = $.makeArray(selectedOptions);
+    selectedOptions.reverse();
+    $.each(selectedOptions, function(k, optionEl) {
+      var $optionEl = $(optionEl)
+        , $optionAfter = $optionEl.next();
+
+      // stop if first option to move is already the last one
+      if (k == 0 && $optionAfter.length === 0) {
+        return false;
+      }
+
+      $optionAfter.after($optionEl.detach());
+    });
+  };
+
+
+  /**
+   * moves currently selected options from a select field as the very last entries
+   *
+   * @param {Object} $fieldEl a jQuery object, containing the select field
+   */
+  FormEngine.moveOptionToBottom = function($fieldEl) {
+    // remove the selected options
+    var selectedOptions = $fieldEl.find(':selected').detach();
+    // and add them on last position again
+    $fieldEl.append(selectedOptions);
+  };
+
+  /**
+   * removes currently selected options from a select field
+   *
+   * @param {Object} $fieldEl a jQuery object, containing the select field
+   * @param {Object} $availableFieldEl a jQuery object, containing all available value
+   */
+  FormEngine.removeOption = function($fieldEl, $availableFieldEl) {
+    var $selected = $fieldEl.find(':selected');
+
+    $selected.each(function() {
+      $availableFieldEl
+        .find('option[value="' + $.escapeSelector($(this).attr('value')) + '"]')
+        .removeClass('hidden')
+        .prop('disabled', false);
+    });
+
+    // remove the selected options
+    $selected.remove();
+  };
+
+
+  /**
+   * Initialize events for all form engine relevant tasks.
+   * This function only needs to be called once on page load,
+   * as it using deferrer methods only
+   */
+  FormEngine.initializeEvents = function() {
+    if (top.TYPO3 && typeof top.TYPO3.Backend !== 'undefined') {
+      top.TYPO3.Backend.consumerScope.attach(FormEngine);
+      $(window).on('unload', function() {
+        top.TYPO3.Backend.consumerScope.detach(FormEngine);
+      });
+    }
+    $(document).on('click', '.t3js-btn-moveoption-top, .t3js-btn-moveoption-up, .t3js-btn-moveoption-down, .t3js-btn-moveoption-bottom, .t3js-btn-removeoption', function(evt) {
+      evt.preventDefault();
+
+      // track the arrows "Up", "Down", "Clear" etc in multi-select boxes
+      var $el = $(this)
+        , fieldName = $el.data('fieldname')
+        , $listFieldEl = FormEngine.getFieldElement(fieldName, '_list');
+
+      if ($listFieldEl.length > 0) {
+
+        if ($el.hasClass('t3js-btn-moveoption-top')) {
+          FormEngine.moveOptionToTop($listFieldEl);
+        } else if ($el.hasClass('t3js-btn-moveoption-up')) {
+          FormEngine.moveOptionUp($listFieldEl);
+        } else if ($el.hasClass('t3js-btn-moveoption-down')) {
+          FormEngine.moveOptionDown($listFieldEl);
+        } else if ($el.hasClass('t3js-btn-moveoption-bottom')) {
+          FormEngine.moveOptionToBottom($listFieldEl);
+        } else if ($el.hasClass('t3js-btn-removeoption')) {
+          var $availableFieldEl = FormEngine.getFieldElement(fieldName, '_avail');
+          FormEngine.removeOption($listFieldEl, $availableFieldEl);
+        }
+
+        // make sure to update the hidden field value when modifying the select value
+        FormEngine.updateHiddenFieldValueFromSelect($listFieldEl, FormEngine.getFieldElement(fieldName));
+        FormEngine.legacyFieldChangedCb();
+        if (typeof FormEngine.Validation !== 'undefined' && typeof FormEngine.Validation.validate === 'function') {
+          FormEngine.Validation.validate();
+        }
+      }
+    }).on('click', '.t3js-formengine-select-itemstoselect', function(evt) {
+      // in multi-select environments with two (e.g. "Access"), on click the item from the right should go to the left
+      var $el = $(this)
+        , fieldName = $el.data('relatedfieldname')
+        , exclusiveValues = $el.data('exclusivevalues');
+
+      if (fieldName) {
+        // try to add each selected field to the "left" select field
+        $el.find(':selected').each(function() {
+          var $optionEl = $(this);
+          FormEngine.setSelectOptionFromExternalSource(fieldName, $optionEl.prop('value'), $optionEl.text(), $optionEl.prop('title'), exclusiveValues, $optionEl);
+        });
+      }
+    }).on('click', '.t3js-editform-close', function(e) {
+      e.preventDefault();
+      FormEngine.preventExitIfNotSaved(
+        FormEngine.preventExitIfNotSavedCallback
+      );
+    }).on('click', '.t3js-editform-delete-record', function(e) {
+      e.preventDefault();
+      var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?';
+      var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?';
+      var $anchorElement = $(this);
+      var $modal = Modal.confirm(title, content, Severity.warning, [
+        {
+          text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'no'
+        },
+        {
+          text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record',
+          btnClass: 'btn-warning',
+          name: 'yes'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'no') {
+          Modal.dismiss();
+        } else if (e.target.name === 'yes') {
+          deleteRecord($anchorElement.data('table'), $anchorElement.data('uid'), $anchorElement.data('return-url'));
+          Modal.dismiss();
+        }
+      });
+    }).on('click', '.t3js-editform-delete-inline-record', function(e) {
+      e.preventDefault();
+      var title = TYPO3.lang['label.confirm.delete_record.title'] || 'Delete this record?';
+      var content = TYPO3.lang['label.confirm.delete_record.content'] || 'Are you sure you want to delete this record?';
+      var $anchorElement = $(this);
+      var $modal = Modal.confirm(title, content, Severity.warning, [
+        {
+          text: TYPO3.lang['buttons.confirm.delete_record.no'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'no'
+        },
+        {
+          text: TYPO3.lang['buttons.confirm.delete_record.yes'] || 'Yes, delete this record',
+          btnClass: 'btn-warning',
+          name: 'yes'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'no') {
+          Modal.dismiss();
+        } else if (e.target.name === 'yes') {
+          var objectId = $anchorElement.data('objectid');
+          inline.deleteRecord(objectId);
+          Modal.dismiss();
+        }
+      });
+    }).on('click', '.t3js-editform-submitButton', function(event) {
+      // remember the clicked submit button. we need to know that in TBE_EDITOR.submitForm();
+      var $me = $(this),
+        name = $me.data('name') || this.name,
+        $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', '1');
+
+      $me.parents('form').append($elem);
+    }).on('change', '.t3-form-field-eval-null-checkbox input[type="checkbox"]', function(e) {
+      // Null checkboxes without placeholder click event handler
+      $(this).closest('.t3js-formengine-field-item').toggleClass('disabled');
+    }).on('change', '.t3js-form-field-eval-null-placeholder-checkbox input[type="checkbox"]', function(e) {
+      $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').toggle();
+      $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').toggle();
+    }).on('change', '.t3js-l10n-state-container input[type=radio]', function(event) {
+      // Change handler for "l10n_state" field changes
+      var $me = $(this);
+      var $input = $me.closest('.t3js-formengine-field-item').find('[data-formengine-input-name]');
+
+      if ($input.length > 0) {
+        var lastState = $input.data('last-l10n-state') || false,
+          currentState = $(this).val();
+
+        if (lastState && currentState === lastState) {
+          return;
+        }
+
+        if (currentState === 'custom') {
+          if (lastState) {
+            $(this).attr('data-original-language-value', $input.val());
+          }
+          $input.attr('disabled', false);
+        } else {
+          if (lastState === 'custom') {
+            $(this).closest('.t3js-l10n-state-container').find('.t3js-l10n-state-custom').attr('data-original-language-value', $input.val());
+          }
+          $input.attr('disabled', 'disabled');
+        }
+
+        $input.val($(this).attr('data-original-language-value')).trigger('change');
+        $input.data('last-l10n-state', $(this).val());
+      }
+    }).on('formengine.dp.change', function(event, $field) {
+      FormEngine.Validation.validate();
+      FormEngine.Validation.markFieldAsChanged($field);
+    });
+  };
+
+  /**
+   * @param {InteractionRequest} interactionRequest
+   * @return {jQuery.Deferred}
+   */
+  FormEngine.consume = function(interactionRequest) {
+    if (!interactionRequest) {
+      throw new BackendException('No interaction request given', 1496589980);
+    }
+    if (interactionRequest.concernsTypes(FormEngine.consumeTypes)) {
+      var outerMostRequest = interactionRequest.outerMostRequest;
+      var deferred = $.Deferred();
+
+      FormEngine.interactionRequestMap.attachFor(
+        outerMostRequest,
+        deferred
+      );
+      // resolve or reject deferreds with previous user choice
+      if (outerMostRequest.isProcessed()) {
+        handleConsumeResponse(
+          outerMostRequest,
+          outerMostRequest.getProcessedData().response
+        );
+        // show confirmation dialog
+      } else if (FormEngine.hasChange()) {
+        FormEngine.preventExitIfNotSaved(function(response) {
+          outerMostRequest.setProcessedData(
+            {response: response}
+          );
+          handleConsumeResponse(outerMostRequest, response);
+        });
+        // resolve directly
+      } else {
+        FormEngine.interactionRequestMap.resolveFor(outerMostRequest);
+      }
+
+      return deferred;
+    }
+  };
+
+  /**
+   * Initializes the remaining character views based on the fields' maxlength attribute
+   */
+  FormEngine.initializeRemainingCharacterViews = function() {
+    // all fields with a "maxlength" attribute
+    var $maxlengthElements = $('[maxlength]').not('.t3js-datetimepicker').not('.t3js-charcounter-initialized');
+    $maxlengthElements.on('focus', function(e) {
+      var $field = $(this),
+        $parent = $field.parents('.t3js-formengine-field-item:first'),
+        maxlengthProperties = FormEngine.getCharacterCounterProperties($field);
+
+      // append the counter only at focus to avoid cluttering the DOM
+      $parent.append($('<div />', {'class': 't3js-charcounter'}).append(
+        $('<span />', {'class': maxlengthProperties.labelClass}).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters))
+      ));
+    }).on('blur', function() {
+      var $field = $(this),
+        $parent = $field.parents('.t3js-formengine-field-item:first');
+      $parent.find('.t3js-charcounter').remove();
+    }).on('keyup', function() {
+      var $field = $(this),
+        $parent = $field.parents('.t3js-formengine-field-item:first'),
+        maxlengthProperties = FormEngine.getCharacterCounterProperties($field);
+
+      // change class and value
+      $parent.find('.t3js-charcounter span').removeClass().addClass(maxlengthProperties.labelClass).text(TYPO3.lang['FormEngine.remainingCharacters'].replace('{0}', maxlengthProperties.remainingCharacters))
+    });
+    $maxlengthElements.addClass('t3js-charcounter-initialized');
+    $(':password').on('focus', function() {
+      $(this).attr('type', 'text').select();
+    }).on('blur', function() {
+      $(this).attr('type', 'password');
+    });
+  };
+
+  /**
+   * Initialize select checkbox element checkboxes
+   */
+  FormEngine.initializeSelectCheckboxes = function() {
+    $('.t3js-toggle-checkboxes').each(function() {
+      var $checkbox = $(this);
+      var $table = $checkbox.closest('table');
+      var $checkboxes = $table.find('.t3js-checkbox');
+      var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length;
+      $checkbox.prop('checked', checkIt);
+    });
+    $(document).on('change', '.t3js-toggle-checkboxes', function(e) {
+      e.preventDefault();
+      var $checkbox = $(this);
+      var $table = $checkbox.closest('table');
+      var $checkboxes = $table.find('.t3js-checkbox');
+      var checkIt = $checkboxes.length !== $table.find('.t3js-checkbox:checked').length;
+      $checkboxes.prop('checked', checkIt);
+      $checkbox.prop('checked', checkIt);
+    });
+    $(document).on('change', '.t3js-checkbox', function(e) {
+      FormEngine.updateCheckboxState(this);
+    });
+  };
+
+  /**
+   *
+   * @param {HTMLElement} source
+   */
+  FormEngine.updateCheckboxState = function(source) {
+    var $sourceElement = $(source);
+    var $table = $sourceElement.closest('table');
+    var $checkboxes = $table.find('.t3js-checkbox');
+    var checkIt = $checkboxes.length === $table.find('.t3js-checkbox:checked').length;
+    $table.find('.t3js-toggle-checkboxes').prop('checked', checkIt);
+  };
+
+  /**
+   * Get the properties required for proper rendering of the character counter
+   *
+   * @param {Object} $field
+   * @returns {{remainingCharacters: number, labelClass: string}}
+   */
+  FormEngine.getCharacterCounterProperties = function($field) {
+    var fieldText = $field.val(),
+      maxlength = $field.attr('maxlength'),
+      currentFieldLength = fieldText.length,
+      numberOfLineBreaks = (fieldText.match(/\n/g) || []).length, // count line breaks
+      remainingCharacters = maxlength - currentFieldLength - numberOfLineBreaks,
+      threshold = 15, // hard limit of remaining characters when the label class changes
+      labelClass = '';
+
+    if (remainingCharacters < threshold) {
+      labelClass = 'label-danger';
+    } else if (remainingCharacters < threshold * 2) {
+      labelClass = 'label-warning';
+    } else {
+      labelClass = 'label-info';
+    }
+
+    return {
+      remainingCharacters: remainingCharacters,
+      labelClass: 'label ' + labelClass
+    };
+  };
+
+  /**
+   * Select field filter functions, see TCA option "enableMultiSelectFilterTextfield"
+   * and "multiSelectFilterItems"
+   */
+  FormEngine.SelectBoxFilter = {
+    options: {
+      fieldContainerSelector: '.t3js-formengine-field-group',
+      filterContainerSelector: '.t3js-formengine-multiselect-filter-container',
+      filterTextFieldSelector: '.t3js-formengine-multiselect-filter-textfield',
+      filterSelectFieldSelector: '.t3js-formengine-multiselect-filter-dropdown',
+      itemsToSelectElementSelector: '.t3js-formengine-select-itemstoselect'
+    }
+  };
+
+  /**
+   * Make sure that all selectors and input filters are recognized
+   * note: this also works on elements that are loaded asynchronously via AJAX, no need to call this method
+   * after an AJAX load.
+   */
+  FormEngine.SelectBoxFilter.initializeEvents = function() {
+    $(document).on('keyup', FormEngine.SelectBoxFilter.options.filterTextFieldSelector, function() {
+      var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this));
+      FormEngine.SelectBoxFilter.filter($selectElement, $(this).val());
+    }).on('change', FormEngine.SelectBoxFilter.options.filterSelectFieldSelector, function() {
+      var $selectElement = FormEngine.SelectBoxFilter.getSelectElement($(this));
+      FormEngine.SelectBoxFilter.filter($selectElement, $(this).val());
+    });
+  };
+
+  /**
+   * Fetch the "itemstoselect" select element where a filter item is attached to
+   *
+   * @param {Object} $relativeElement
+   * @returns {*}
+   */
+  FormEngine.SelectBoxFilter.getSelectElement = function($relativeElement) {
+    var $containerElement = $relativeElement.closest(FormEngine.SelectBoxFilter.options.fieldContainerSelector);
+    return $containerElement.find(FormEngine.SelectBoxFilter.options.itemsToSelectElementSelector);
+  };
+
+  /**
+   * Filter the actual items
+   *
+   * @param {Object} $selectElement
+   * @param {String} filterText
+   */
+  FormEngine.SelectBoxFilter.filter = function($selectElement, filterText) {
+    var $allOptionElements;
+    if (!$selectElement.data('alloptions')) {
+      $allOptionElements = $selectElement.find('option').clone();
+      $selectElement.data('alloptions', $allOptionElements);
+    } else {
+      $allOptionElements = $selectElement.data('alloptions');
+    }
+
+    if (filterText.length > 0) {
+      var matchFilter = new RegExp(filterText, 'i');
+      $selectElement.html('');
+      $allOptionElements.each(function() {
+        var $item = $(this);
+        if ($item.text().match(matchFilter)) {
+          $selectElement.append($item.clone());
+        }
+      });
+    } else {
+      $selectElement.html($allOptionElements);
+    }
+  };
+
+  /**
+   * convert all textareas so they grow when it is typed in.
+   */
+  FormEngine.convertTextareasResizable = function() {
+    var $elements = $('.t3js-formengine-textarea');
+    if (TYPO3.settings.Textarea && TYPO3.settings.Textarea.autosize && $elements.length) {
+      require(['autosize'], function(autosize) {
+        autosize($elements);
+      });
+    }
+  };
+
+  /**
+   * convert all textareas to enable tab
+   */
+  FormEngine.convertTextareasEnableTab = function() {
+    var $elements = $('.t3js-enable-tab');
+    if ($elements.length) {
+      require(['taboverride'], function(taboverride) {
+        taboverride.set($elements);
+      });
+    }
+  };
+
+  /**
+   * Initialize input / text field "null" checkbox CSS overlay if no placeholder is set.
+   */
+  FormEngine.initializeNullNoPlaceholderCheckboxes = function() {
+    $('.t3-form-field-eval-null-checkbox').each(function() {
+      // Add disabled class to "t3js-formengine-field-item" if the null checkbox is NOT set,
+      // This activates a CSS overlay "disabling" the input field and everything around.
+      var $checkbox = $(this).find('input[type="checkbox"]');
+      var $fieldItem = $(this).closest('.t3js-formengine-field-item');
+      if (!$checkbox.attr('checked')) {
+        $fieldItem.addClass('disabled');
+      }
+    });
+  };
+
+  /**
+   * Initialize input / text field "null" checkbox placeholder / real field if placeholder is set.
+   */
+  FormEngine.initializeNullWithPlaceholderCheckboxes = function() {
+    $('.t3js-form-field-eval-null-placeholder-checkbox').each(function() {
+      // Set initial state of both div's (one containing actual field, other containing placeholder field)
+      // depending on whether checkbox is checked or not
+      var $checkbox = $(this).find('input[type="checkbox"]');
+      if ($checkbox.attr('checked')) {
+        $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-placeholder').hide();
+      } else {
+        $(this).closest('.t3js-formengine-field-item').find('.t3js-formengine-placeholder-formfield').hide();
+      }
+    });
+  };
+
+  /**
+   * This is the main function that is called on page load, but also after elements are asynchronously
+   * called e.g. after inline elements are loaded, or a new flexform section is added.
+   * Use this function in your extension like this "TYPO3.FormEngine.initialize()"
+   * if you add new fields dynamically.
+   */
+  FormEngine.reinitialize = function() {
+    // Apply "close" button to all input / datetime fields
+    if ($('.t3js-clearable').length) {
+      require(['TYPO3/CMS/Backend/jquery.clearable'], function() {
+        $('.t3js-clearable').clearable();
+      });
+    }
+    if ($('.t3-form-suggest').length) {
+      require(['TYPO3/CMS/Backend/FormEngineSuggest'], function(Suggest) {
+        Suggest($('.t3-form-suggest'));
+      });
+    }
+    // Apply DatePicker to all date time fields
+    if ($('.t3js-datetimepicker').length) {
+      require(['TYPO3/CMS/Backend/DateTimePicker'], function(DateTimePicker) {
+        DateTimePicker.initialize();
+      });
+    }
+
+    FormEngine.convertTextareasResizable();
+    FormEngine.convertTextareasEnableTab();
+    FormEngine.initializeNullNoPlaceholderCheckboxes();
+    FormEngine.initializeNullWithPlaceholderCheckboxes();
+    FormEngine.initializeInputLinkToggle();
+    FormEngine.initializeLocalizationStateSelector();
+    FormEngine.initializeRemainingCharacterViews();
+  };
+
+  /**
+   * Disable the input field on load if localization state selector is set to "parent" or "source"
+   */
+  FormEngine.initializeLocalizationStateSelector = function() {
+    $('.t3js-l10n-state-container').each(function() {
+      var $input = $(this).closest('.t3js-formengine-field-item').find('[data-formengine-input-name]');
+      var currentState = $(this).find('input[type="radio"]:checked').val();
+      if (currentState === 'parent' || currentState === 'source') {
+        $input.attr('disabled', 'disabled');
+      }
+    });
+  };
+
+  /**
+   * Toggle for input link explanation
+   */
+  FormEngine.initializeInputLinkToggle = function() {
+    var toggleClass = '.t3js-form-field-inputlink-explanation-toggle',
+      inputFieldClass = '.t3js-form-field-inputlink-input',
+      explanationClass = '.t3js-form-field-inputlink-explanation';
+
+    // if empty, show input field
+    $(explanationClass).filter(function() {
+      return !$.trim($(this).val());
+    }).each(function() {
+      var $group = $(this).closest('.t3js-form-field-inputlink'),
+        $inputField = $group.find(inputFieldClass),
+        $explanationField = $group.find(explanationClass);
+      $explanationField.toggleClass('hidden', true);
+      $inputField.toggleClass('hidden', false);
+      $group.find('.form-control-clearable button.close').toggleClass('hidden', false)
+    });
+
+    $(document).on('click', toggleClass, function(e) {
+      e.preventDefault();
+
+      var $group = $(this).closest('.t3js-form-field-inputlink'),
+        $inputField = $group.find(inputFieldClass),
+        $explanationField = $group.find(explanationClass),
+        explanationShown;
+
+      explanationShown = !$explanationField.hasClass('hidden');
+      $explanationField.toggleClass('hidden', explanationShown);
+      $inputField.toggleClass('hidden', !explanationShown);
+      $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown)
+    });
+
+    $(inputFieldClass).on('change', function() {
+      var $group = $(this).closest('.t3js-form-field-inputlink'),
+        $inputField = $group.find(inputFieldClass),
+        $explanationField = $group.find(explanationClass),
+        explanationShown;
+
+      if (!$explanationField.hasClass('hidden')) {
+
+        explanationShown = !$explanationField.hasClass('hidden');
+        $explanationField.toggleClass('hidden', explanationShown);
+        $inputField.toggleClass('hidden', !explanationShown);
+        $group.find('.form-control-clearable button.close').toggleClass('hidden', !explanationShown)
+      }
+    });
+  };
+
+  /**
+   * @return {boolean}
+   */
+  FormEngine.hasChange = function() {
+    return $('form[name="' + FormEngine.formName + '"] .has-change').length > 0;
+  };
+
+  /**
+   * @param {boolean} response
+   */
+  FormEngine.preventExitIfNotSavedCallback = function(response) {
+    if (response) {
+      FormEngine.closeDocument();
+    }
+  };
+
+  /**
+   * Show modal to confirm closing the document without saving.
+   *
+   * @param {Function} callback
+   */
+  FormEngine.preventExitIfNotSaved = function(callback) {
+    callback = callback || FormEngine.preventExitIfNotSavedCallback;
+
+    if (FormEngine.hasChange()) {
+      var title = TYPO3.lang['label.confirm.close_without_save.title'] || 'Do you want to quit without saving?';
+      var content = TYPO3.lang['label.confirm.close_without_save.content'] || 'You have currently unsaved changes. Are you sure that you want to discard all changes?';
+      var $modal = Modal.confirm(title, content, Severity.warning, [
+        {
+          text: TYPO3.lang['buttons.confirm.close_without_save.no'] || 'No, I will continue editing',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'no'
+        },
+        {
+          text: TYPO3.lang['buttons.confirm.close_without_save.yes'] || 'Yes, discard my changes',
+          btnClass: 'btn-warning',
+          name: 'yes'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'no') {
+          Modal.dismiss();
+          callback.call(null, false);
+        } else if (e.target.name === 'yes') {
+          Modal.dismiss();
+          callback.call(null, true);
+        }
+      });
+    } else {
+      callback.call(null, true);
+    }
+  };
+
+  /**
+   * Show modal to confirm closing the document without saving
+   */
+  FormEngine.preventSaveIfHasErrors = function() {
+    if ($('.has-error').length > 0) {
+      var title = TYPO3.lang['label.alert.save_with_error.title'] || 'You have errors in your form!';
+      var content = TYPO3.lang['label.alert.save_with_error.content'] || 'Please check the form, there is at least one error in your form.';
+      var $modal = Modal.confirm(title, content, Severity.error, [
+        {
+          text: TYPO3.lang['buttons.alert.save_with_error.ok'] || 'OK',
+          btnClass: 'btn-danger',
+          name: 'ok'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'ok') {
+          Modal.dismiss();
+        }
+      });
+      return false;
+    }
+    return true;
+  };
+
+  /**
+   * Close current open document
+   */
+  FormEngine.closeDocument = function() {
+    document.editform.closeDoc.value = 1;
+    document.editform.submit();
+  };
+
+  /**
+   * Main init function called from outside
+   *
+   * Sets some options and registers the DOMready handler to initialize further things
+   *
+   * @param {String} browserUrl
+   * @param {Number} mode
+   */
+  FormEngine.initialize = function(browserUrl, mode) {
+    FormEngine.browserUrl = browserUrl;
+    FormEngine.Validation.setUsMode(mode);
+
+    $(function() {
+      FormEngine.initializeEvents();
+      FormEngine.SelectBoxFilter.initializeEvents();
+      FormEngine.initializeSelectCheckboxes();
+      FormEngine.Validation.initialize();
+      FormEngine.reinitialize();
+      $('#t3js-ui-block').remove();
+    });
+  };
+
+  // load required modules to hook in the post initialize function
+  if (undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine']) {
+    $.each(TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine'], function(pos, moduleName) {
+      require([moduleName]);
+    });
+  }
+
+  // make the form engine object publicly visible for other objects in the TYPO3 namespace
+  TYPO3.FormEngine = FormEngine;
+
+  // return the object in the global space
+  return FormEngine;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js
index f40db4b0b260..4fb7f682956b 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectSingleElement.js
@@ -15,7 +15,7 @@
  * Module: TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement
  * Logic for SelectSingleElement
  */
-define(['jquery'], function ($) {
+define(['jquery'], function($) {
 
   /**
    *
@@ -30,13 +30,13 @@ define(['jquery'], function ($) {
    * @param {String} selector
    * @param {Object} options
    */
-  SelectSingleElement.initialize = function (selector, options) {
+  SelectSingleElement.initialize = function(selector, options) {
 
     var $selectElement = $(selector);
     var $groupIconContainer = $selectElement.prev('.input-group-icon');
     var options = options || {};
 
-    $selectElement.on('change', function () {
+    $selectElement.on('change', function() {
       // Update prepended select icon
       $groupIconContainer.html($selectElement.find(':selected').data('icon'));
     });
@@ -51,7 +51,7 @@ define(['jquery'], function ($) {
       $selectElement.on('focus', options.onFocus);
     }
 
-    $selectElement.closest('.form-control-wrap').find('.t3js-forms-select-single-icons').on('click', function (e) {
+    $selectElement.closest('.form-control-wrap').find('.t3js-forms-select-single-icons').on('click', function(e) {
       var $selectIcon = $(e.target).closest('[data-select-index]');
 
       $selectElement
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
index 78953f3b1367..eb5b40a8be8a 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTree.js
@@ -19,14 +19,14 @@
  * Extends TYPO3/CMS/Backend/SvgTree component.
  */
 define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
-  function (d3, SvgTree) {
+  function(d3, SvgTree) {
     'use strict';
 
     /**
      * @constructor
      * @exports TYPO3/CMS/Backend/FormEngine/Element/SelectTree
      */
-    var SelectTree = function () {
+    var SelectTree = function() {
       SvgTree.call(this);
       this.settings.showCheckboxes = true;
     };
@@ -40,7 +40,7 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      * @param {String} selector
      * @param {Object} settings
      */
-    SelectTree.prototype.initialize = function (selector, settings) {
+    SelectTree.prototype.initialize = function(selector, settings) {
       if (!_super_.initialize.call(this, selector, settings)) {
         return false;
       }
@@ -58,11 +58,11 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      *
      * @param {Selection} nodeSelection
      */
-    SelectTree.prototype.updateNodes = function (nodeSelection) {
+    SelectTree.prototype.updateNodes = function(nodeSelection) {
       if (this.settings.showCheckboxes) {
         nodeSelection
           .selectAll('.tree-check use')
-          .attr('visibility', function (node) {
+          .attr('visibility', function(node) {
             var checked = Boolean(node.checked);
             if (d3.select(this).classed('icon-checked') && checked) {
               return 'visible';
@@ -82,20 +82,20 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      *
      * @param {Selection} nodeSelection ENTER selection (only new DOM objects)
      */
-    SelectTree.prototype.renderCheckbox = function (nodeSelection) {
+    SelectTree.prototype.renderCheckbox = function(nodeSelection) {
       var _this = this;
       if (this.settings.showCheckboxes) {
         this.textPosition = 50;
 
         // this can be simplified to single "use" element with changing href on click
         // when we drop IE11 on WIN7 support
-        var g = nodeSelection.filter(function (node) {
+        var g = nodeSelection.filter(function(node) {
           // do not render checkbox if node is not selectable
           return _this.isNodeSelectable(node) || Boolean(node.checked);
         })
           .append('g')
           .attr('class', 'tree-check')
-          .on('click', function (d) {
+          .on('click', function(d) {
             _this.selectNode(d);
           });
 
@@ -125,12 +125,12 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      *
      * @param {Node} node
      */
-    SelectTree.prototype.updateAncestorsIndeterminateState = function (node) {
+    SelectTree.prototype.updateAncestorsIndeterminateState = function(node) {
       var _this = this;
 
       //foreach ancestor except node itself
       var indeterminate = false;
-      node.parents.forEach(function (index) {
+      node.parents.forEach(function(index) {
         var n = _this.nodes[index];
         n.indeterminate = (node.checked || node.indeterminate || indeterminate);
 
@@ -144,8 +144,8 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      * It's done once after loading data.
      * Later indeterminate state is updated just for the subset of nodes
      */
-    SelectTree.prototype.loadDataAfter = function () {
-      this.nodes.forEach(function (node) {
+    SelectTree.prototype.loadDataAfter = function() {
+      this.nodes.forEach(function(node) {
         node.indeterminate = false;
       });
 
@@ -164,10 +164,10 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      *
      * @param {Array} nodes
      */
-    SelectTree.prototype.calculateIndeterminate = function (nodes) {
-      nodes.forEach(function (node) {
+    SelectTree.prototype.calculateIndeterminate = function(nodes) {
+      nodes.forEach(function(node) {
         if ((node.checked || node.indeterminate) && node.parents && node.parents.length > 0) {
-          node.parents.forEach(function (parentNodeIndex) {
+          node.parents.forEach(function(parentNodeIndex) {
             nodes[parentNodeIndex].indeterminate = true;
           });
         }
@@ -179,7 +179,7 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
      *
      * @param {Node} node
      */
-    SelectTree.prototype.nodeSelectedAfter = function (node) {
+    SelectTree.prototype.nodeSelectedAfter = function(node) {
       this.updateAncestorsIndeterminateState(node);
 
       // check all nodes again, to ensure correct display of indeterminate state
@@ -190,10 +190,10 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
     /**
      * Sets a comma-separated list of selected nodes identifiers to configured input
      */
-    SelectTree.prototype.saveCheckboxes = function () {
+    SelectTree.prototype.saveCheckboxes = function() {
       if (typeof this.settings.input !== 'undefined') {
         var selectedNodes = this.getSelectedNodes();
-        this.settings.input.val(selectedNodes.map(function (d) {
+        this.settings.input.val(selectedNodes.map(function(d) {
           return d.identifier;
         }));
       }
@@ -202,22 +202,22 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
     /**
      * Add icons imitating checkboxes
      */
-    SelectTree.prototype.addIcons = function () {
+    SelectTree.prototype.addIcons = function() {
 
       this.data.icons = {
         check: {
           identifier: 'check',
           icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">' +
-          '<rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>',
+          '<rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1312 256h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-832q0-66-47-113t-113-47zm288 160v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'
         },
         checked: {
           identifier: 'checked',
-          icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>',
+          icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M813 1299l614-614q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-467 467-211-211q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l358 358q19 19 45 19t45-19zm851-883v960q0 119-84.5 203.5t-203.5 84.5h-960q-119 0-203.5-84.5t-84.5-203.5v-960q0-119 84.5-203.5t203.5-84.5h960q119 0 203.5 84.5t84.5 203.5z"></path></g>'
         },
         indeterminate: {
           identifier: 'indeterminate',
-          icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>',
-        },
+          icon: '<g width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><rect height="16" width="16" fill="transparent"></rect><path transform="scale(0.01)" d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"></path></g>'
+        }
       };
     };
 
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js
index d4009378a8e2..643336ffc167 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/SelectTreeElement.js
@@ -15,14 +15,14 @@
  * Initialization of the selectTree js component used e.g. for category tree rendering
  */
 define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
-  function ($, SelectTree) {
+  function($, SelectTree) {
     'use strict';
 
     var SelectTreeElement = {};
 
-    SelectTreeElement.initialize = function () {
-      $(document).ready(function () {
-        $('.typo3-tceforms-tree .treeRecord').each(function (i, element) {
+    SelectTreeElement.initialize = function() {
+      $(document).ready(function() {
+        $('.typo3-tceforms-tree .treeRecord').each(function(i, element) {
 
           /**
            * Hidden input field storing selected elements.
@@ -43,7 +43,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
             flexFormContainerIdentifier: $treeInput.data('flexformcontaineridentifier'),
             flexFormContainerFieldName: $treeInput.data('flexformcontainerfieldname'),
             flexFormSectionContainerIsNew: $treeInput.data('flexformsectioncontainerisnew'),
-            command: $treeInput.data('command'),
+            command: $treeInput.data('command')
           };
           var $wrapper = $treeInput.parent().siblings('.svg-tree-wrapper');
           var dataUrl = TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(dataParams);
@@ -56,7 +56,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
             input: $treeInput,
             exclusiveNodesIdentifiers: $treeInput.data('tree-exclusive-keys'),
             validation: $treeInput.data('formengine-validation-rules')[0],
-            expandUpToLevel: $treeInput.data('tree-expand-up-to-level'),
+            expandUpToLevel: $treeInput.data('tree-expand-up-to-level')
           });
           if (!initialized) {
             return;
@@ -65,7 +65,7 @@ define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
           tree.dispatch.on('nodeSelectedAfter.requestUpdate', window[$wrapper.attr('id')]);
 
           if ($treeInput.data('tree-show-toolbar')) {
-            require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function (TreeToolbar) {
+            require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function(TreeToolbar) {
               var selectTreeToolbar = new TreeToolbar();
               selectTreeToolbar.initialize($wrapper);
             });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js
index b67145cf95ca..abb34c49f562 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngine/Element/TreeToolbar.js
@@ -17,9 +17,9 @@
 define(['jquery',
     'TYPO3/CMS/Backend/Icons',
     'TYPO3/CMS/Backend/Tooltip',
-    'TYPO3/CMS/Backend/SvgTree',
+    'TYPO3/CMS/Backend/SvgTree'
   ],
-  function ($, Icons) {
+  function($, Icons) {
     'use strict';
 
     /**
@@ -28,13 +28,13 @@ define(['jquery',
      * @constructor
      * @exports TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar
      */
-    var TreeToolbar = function () {
+    var TreeToolbar = function() {
       this.settings = {
         toolbarSelector: '.tree-toolbar',
         collapseAllBtn: '.collapse-all-btn',
         expandAllBtn: '.expand-all-btn',
         searchInput: '.search-input',
-        toggleHideUnchecked: '.hide-unchecked-btn',
+        toggleHideUnchecked: '.hide-unchecked-btn'
       };
 
       /**
@@ -66,15 +66,15 @@ define(['jquery',
        */
       this.$template = $(
         '<div class="tree-toolbar btn-toolbar">' +
-          '<div class="input-group">' +
-            '<span class="input-group-addon input-group-icon filter"></span>' +
-            '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tcatree.findItem'] + '">' +
-          '</div>' +
-          '<div class="btn-group">' +
-            '<button type="button" data-toggle="tooltip" class="btn btn-default expand-all-btn" title="' + TYPO3.lang['tcatree.expandAll'] + '"></button>' +
-            '<button type="button" data-toggle="tooltip" class="btn btn-default collapse-all-btn" title="' + TYPO3.lang['tcatree.collapseAll'] + '"></button>' +
-            '<button type="button" data-toggle="tooltip" class="btn btn-default hide-unchecked-btn" title="' + TYPO3.lang['tcatree.toggleHideUnchecked'] + '"></button>' +
-          '</div>' +
+        '<div class="input-group">' +
+        '<span class="input-group-addon input-group-icon filter"></span>' +
+        '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tcatree.findItem'] + '">' +
+        '</div>' +
+        '<div class="btn-group">' +
+        '<button type="button" data-toggle="tooltip" class="btn btn-default expand-all-btn" title="' + TYPO3.lang['tcatree.expandAll'] + '"></button>' +
+        '<button type="button" data-toggle="tooltip" class="btn btn-default collapse-all-btn" title="' + TYPO3.lang['tcatree.collapseAll'] + '"></button>' +
+        '<button type="button" data-toggle="tooltip" class="btn btn-default hide-unchecked-btn" title="' + TYPO3.lang['tcatree.toggleHideUnchecked'] + '"></button>' +
+        '</div>' +
         '</div>'
       );
     };
@@ -85,7 +85,7 @@ define(['jquery',
      * @param {String} treeSelector
      * @param {Object} settings
      */
-    TreeToolbar.prototype.initialize = function (treeSelector, settings) {
+    TreeToolbar.prototype.initialize = function(treeSelector, settings) {
       this.$treeWrapper = $(treeSelector);
       if (!this.$treeWrapper.data('svgtree-initialized') || typeof this.$treeWrapper.data('svgtree') !== 'object') {
 
@@ -103,30 +103,30 @@ define(['jquery',
     /**
      * Renders toolbar
      */
-    TreeToolbar.prototype.render = function () {
+    TreeToolbar.prototype.render = function() {
       var _this = this;
       this.tree = this.$treeWrapper.data('svgtree');
       var $toolbar = this.$template.clone().insertBefore(this.$treeWrapper);
 
-      Icons.getIcon('actions-filter', Icons.sizes.small).done(function (icon) {
+      Icons.getIcon('actions-filter', Icons.sizes.small).done(function(icon) {
         $toolbar.find('.filter').append(icon);
       });
 
-      Icons.getIcon('apps-pagetree-category-expand-all', Icons.sizes.small).done(function (icon) {
+      Icons.getIcon('apps-pagetree-category-expand-all', Icons.sizes.small).done(function(icon) {
         $toolbar.find('.expand-all-btn').append(icon);
       });
 
-      Icons.getIcon('apps-pagetree-category-collapse-all', Icons.sizes.small).done(function (icon) {
+      Icons.getIcon('apps-pagetree-category-collapse-all', Icons.sizes.small).done(function(icon) {
         $toolbar.find('.collapse-all-btn').append(icon);
       });
 
-      Icons.getIcon('apps-pagetree-category-toggle-hide-checked', Icons.sizes.small).done(function (icon) {
+      Icons.getIcon('apps-pagetree-category-toggle-hide-checked', Icons.sizes.small).done(function(icon) {
         $toolbar.find('.hide-unchecked-btn').append(icon);
       });
 
       $toolbar.find(this.settings.collapseAllBtn).on('click', this.collapseAll.bind(this));
       $toolbar.find(this.settings.expandAllBtn).on('click', this.expandAll.bind(this));
-      $toolbar.find(this.settings.searchInput).on('input', function () {
+      $toolbar.find(this.settings.searchInput).on('input', function() {
         _this.search.call(_this, this);
       });
 
@@ -137,14 +137,14 @@ define(['jquery',
     /**
      * Collapse children of root node
      */
-    TreeToolbar.prototype.collapseAll = function () {
+    TreeToolbar.prototype.collapseAll = function() {
       this.tree.collapseAll();
     };
 
     /**
      * Expand all nodes
      */
-    TreeToolbar.prototype.expandAll = function () {
+    TreeToolbar.prototype.expandAll = function() {
       this.tree.expandAll();
     };
 
@@ -153,12 +153,12 @@ define(['jquery',
      *
      * @param {HTMLElement} input
      */
-    TreeToolbar.prototype.search = function (input) {
+    TreeToolbar.prototype.search = function(input) {
       var _this = this;
       var name = $(input).val();
 
       this.tree.nodes[0].open = false;
-      this.tree.nodes.forEach(function (node) {
+      this.tree.nodes.forEach(function(node) {
         var regex = new RegExp(name, 'i');
         if (regex.test(node.name)) {
           _this.showParents(node);
@@ -177,13 +177,13 @@ define(['jquery',
     /**
      * Show only checked items
      */
-    TreeToolbar.prototype.toggleHideUnchecked = function () {
+    TreeToolbar.prototype.toggleHideUnchecked = function() {
       var _this = this;
 
       this._hideUncheckedState = !this._hideUncheckedState;
 
       if (this._hideUncheckedState) {
-        this.tree.nodes.forEach(function (node) {
+        this.tree.nodes.forEach(function(node) {
           if (node.checked) {
             _this.showParents(node);
             node.open = true;
@@ -194,7 +194,7 @@ define(['jquery',
           }
         });
       } else {
-        this.tree.nodes.forEach(function (node) {
+        this.tree.nodes.forEach(function(node) {
           node.hidden = false;
         });
       }
@@ -209,7 +209,7 @@ define(['jquery',
      * @param {Node} node
      * @returns {Boolean}
      */
-    TreeToolbar.prototype.showParents = function (node) {
+    TreeToolbar.prototype.showParents = function(node) {
       if (node.parents.length === 0) {
         return true;
       }
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js
index 458b3d1e5166..30fceb691763 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineFlexForm.js
@@ -21,264 +21,264 @@
  * which can contain one ore more sections
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/FormEngine'
-	   ], function ($, Modal) {
-
-	/**
-	 *
-	 * @param {HTMLElement} el
-	 * @param {Object} options
-	 * @constructor
-	 * @exports TYPO3/CMS/Backend/FormEngineFlexForm
-	 */
-	TYPO3.FormEngine.FlexFormElement = function(el, options) {
-		var me = this;	// avoid scope issues
-		var opts;	// shorthand options notation
-
-		// initialization function; private
-		me.initialize = function() {
-			// store DOM element and jQuery object for later use
-			me.el = el;
-			me.$el = $(el);
-
-			// remove any existing backups
-			var old_me = me.$el.data('TYPO3.FormEngine.FlexFormElement');
-			if (typeof old_me !== 'undefined') {
-				me.$el.removeData('TYPO3.FormEngine.FlexFormElement');
-			}
-
-			// add a reverse reference to the DOM element
-			me.$el.data('TYPO3.FormEngine.FlexFormElement', me);
-
-			if (!options) {
-				options = {};
-			}
-
-			// set some values from existing properties
-			options.allowRestructure = me.$el.data('t3-flex-allow-restructure');
-			options.flexformId = me.$el.attr('id');
-
-			// store options and merge with default options
-			opts = me.options = $.extend({}, TYPO3.FormEngine.FlexFormElement.defaults, options);
-
-			// initialize events
-			me.initializeEvents();
-
-			// generate the preview text if a section is hidden on load
-			me.$el.find(opts.sectionSelector).each(function() {
-				me.generateSectionPreview($(this));
-			});
-
-			return me;
-		};
-
-		/**
-		 * init all events related to the flexform. As this method is called multiple times,
-		 * some handlers need to be off'ed first to prevent event stacking.
-		 */
-		me.initializeEvents = function() {
-			// Toggling all sections on/off by clicking all toggle buttons of each section
-			me.$el.prev(opts.flexFormToggleAllSectionsSelector).off('click').on('click', function() {
-				me.$el.find(opts.sectionToggleButtonSelector).trigger('click');
-			});
-
-			if (opts.allowRestructure) {
-				// create a sortable when dragging on the header of a section
-				me.createSortable();
-
-				// allow delete of a single section
-				me.$el.off('click').on('click', opts.deleteIconSelector, function(evt) {
-					evt.preventDefault();
-
-					var confirmTitle = TYPO3.lang['flexform.section.delete.title'] || 'Are you sure?';
-					var confirmMessage = TYPO3.lang['flexform.section.delete.message'] || 'Are you sure you want to delete this section?';
-					var $confirm = Modal.confirm(confirmTitle, confirmMessage);
-					$confirm.on('confirm.button.cancel', function() {
-						Modal.currentModal.trigger('modal-dismiss');
-					});
-					$confirm.on('confirm.button.ok', function(event) {
-						$(evt.target).closest(opts.sectionSelector).hide().addClass(opts.sectionDeletedClass);
-						me.setActionStatus();
-						TYPO3.FormEngine.Validation.validate();
-						Modal.currentModal.trigger('modal-dismiss');
-					});
-				});
-
-				// allow the toggle open/close of the main selection
-				me.$el.on('click', opts.sectionToggleButtonSelector, function(evt) {
-					evt.preventDefault();
-					var $sectionEl = $(this).closest(opts.sectionSelector);
-					me.toggleSection($sectionEl);
-				}).on('click', opts.sectionToggleButtonSelector + ' .form-irre-header-control', function(evt) {
-					evt.stopPropagation();
-				});
-			}
-
-			return me;
-		};
-
-		// initialize ourself
-		me.initialize();
-	};
-
-	// setting some default values
-	TYPO3.FormEngine.FlexFormElement.defaults = {
-		'deleteIconSelector': '.t3js-delete',
-		'sectionSelector': '.t3js-flex-section',
-		'sectionContentSelector': '.t3js-flex-section-content',
-		'sectionHeaderSelector': '.t3js-flex-section-header',
-		'sectionHeaderPreviewSelector': '.t3js-flex-section-header-preview',
-		'sectionActionInputFieldSelector': '.t3js-flex-control-action',
-		'sectionToggleInputFieldSelector': '.t3js-flex-control-toggle',
-		'sectionToggleIconOpenSelector': '.t3js-flex-control-toggle-icon-open',
-		'sectionToggleIconCloseSelector': '.t3js-flex-control-toggle-icon-close',
-		'sectionToggleButtonSelector': '[data-toggle="formengine-flex"]',
-		'flexFormToggleAllSectionsSelector': '.t3js-form-field-toggle-flexsection',
-		'sectionDeletedClass': 't3js-flex-section-deleted',
-		'allowRestructure': 0,	// whether the form can be modified
-		'flexformId': false
-	};
-
-
-	/**
-	 * Allow flexform sections to be sorted
-	 */
-	TYPO3.FormEngine.FlexFormElement.prototype.createSortable = function() {
-		var me = this;
-
-		require(['jquery-ui/sortable'], function () {
-			me.$el.sortable({
-				containment: 'parent',
-				handle: '.t3js-sortable-handle',
-				axis: 'y',
-				tolerance: 'pointer',
-				stop: function () {
-					me.setActionStatus();
-				}
-			});
-		});
-	};
-
-	// Updates the "action"-status for a section. This is used to move and delete elements.
-	TYPO3.FormEngine.FlexFormElement.prototype.setActionStatus = function() {
-		var me = this;
-
-		// Traverse and find how many sections are open or closed, and save the value accordingly
-		me.$el.find(me.options.sectionActionInputFieldSelector).each(function(index) {
-			var actionValue = ($(this).parents(me.options.sectionSelector).hasClass(me.options.sectionDeletedClass) ? 'DELETE' : index);
-			$(this).val(actionValue);
-		});
-	};
-
-	// Toggling flexform elements on/off
-	// hides the flexform section and shows a preview text
-	// or shows the form parts
-	TYPO3.FormEngine.FlexFormElement.prototype.toggleSection = function($sectionEl) {
-
-		var $contentEl = $sectionEl.find(this.options.sectionContentSelector);
-
-		// display/hide the content of this flexform section
-		$contentEl.toggle();
-
-		if ($contentEl.is(':visible')) {
-			// show the open icon, and set the hidden field for toggling to "hidden"
-			$sectionEl.find(this.options.sectionToggleIconOpenSelector).show();
-			$sectionEl.find(this.options.sectionToggleIconCloseSelector).hide();
-			$sectionEl.find(this.options.sectionToggleInputFieldSelector).val(0);
-		} else {
-			// show the close icon, and set the hidden field for toggling to "1"
-			$sectionEl.find(this.options.sectionToggleIconOpenSelector).hide();
-			$sectionEl.find(this.options.sectionToggleIconCloseSelector).show();
-			$sectionEl.find(this.options.sectionToggleInputFieldSelector).val(1);
-		}
-
-		// see if the preview content needs to be generated
-		this.generateSectionPreview($sectionEl);
-	};
-
-	// function to generate the section preview in the header
-	// if the section content is hidden
-	// called on load and when toggling an icon
-	TYPO3.FormEngine.FlexFormElement.prototype.generateSectionPreview = function($sectionEl) {
-		var $contentEl = $sectionEl.find(this.options.sectionContentSelector);
-		var previewContent = '';
-
-		if (!$contentEl.is(':visible')) {
-			$contentEl.find('input[type=text], textarea').each(function() {
-				var content = $($.parseHTML($(this).val())).text();
-				if (content.length > 50) {
-					content = content.substring(0, 50) + '...';
-				}
-				previewContent += (previewContent ? ' / ' : '') + content;
-			});
-		}
-
-		// create a preview container span element
-		if ($sectionEl.find(this.options.sectionHeaderPreviewSelector).length === 0) {
-			$sectionEl.find(this.options.sectionHeaderSelector).find('.t3js-record-title').parent()
-				.append('<span class="' + this.options.sectionHeaderPreviewSelector.replace(/\./, '') + '"></span>');
-		}
-
-		$sectionEl.find(this.options.sectionHeaderPreviewSelector).text(previewContent);
-	};
-
-	// register the flex functions as jQuery Plugin
-	$.fn.t3FormEngineFlexFormElement = function(options) {
-		// apply all util functions to ourself (for use in templates, etc.)
-		return this.each(function() {
-			(new TYPO3.FormEngine.FlexFormElement(this, options));
-		});
-	};
-
-	// Initialization Code
-	$(function() {
-		// run the flexform functions on all containers (which contains one or more sections)
-		$('.t3-flex-container').t3FormEngineFlexFormElement();
-
-		// Add handler to fetch container data on click on "add container" buttons
-		$('.t3js-flex-container-add').on('click', function(e) {
-			var me = $(this);
-			e.preventDefault();
-			$.ajax({
-				url: TYPO3.settings.ajaxUrls['record_flex_container_add'],
-				type: 'POST',
-				cache: false,
-				data: {
-					vanillaUid: me.data('vanillauid'),
-					databaseRowUid: me.data('databaserowuid'),
-					command: me.data('command'),
-					tableName: me.data('tablename'),
-					fieldName: me.data('fieldname'),
-					recordTypeValue: me.data('recordtypevalue'),
-					dataStructureIdentifier: me.data('datastructureidentifier'),
-					flexFormSheetName: me.data('flexformsheetname'),
-					flexFormFieldName: me.data('flexformfieldname'),
-					flexFormContainerName: me.data('flexformcontainername')
-				},
-				success: function(response) {
-					me.closest('.t3-form-field-container').find('.t3-flex-container').append(response.html);
-					$('.t3-flex-container').t3FormEngineFlexFormElement();
-					if (response.scriptCall && response.scriptCall.length > 0) {
-						$.each(response.scriptCall, function (index, value) {
-							eval(value);
-						});
-					}
-					if (response.stylesheetFiles && response.stylesheetFiles.length > 0) {
-						$.each(response.stylesheetFiles, function (index, stylesheetFile) {
-							var element = document.createElement('link');
-							element['rel'] = 'stylesheet';
-							element['type'] = 'text/css';
-							element['href'] = stylesheetFile;
-							document.head.appendChild(element);
-						});
-					}
-					TYPO3.FormEngine.reinitialize();
-					TYPO3.FormEngine.Validation.initializeInputFields();
-					TYPO3.FormEngine.Validation.validate();
-				}
-			});
-		});
-
-	});
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/FormEngine'
+], function($, Modal) {
+
+  /**
+   *
+   * @param {HTMLElement} el
+   * @param {Object} options
+   * @constructor
+   * @exports TYPO3/CMS/Backend/FormEngineFlexForm
+   */
+  TYPO3.FormEngine.FlexFormElement = function(el, options) {
+    var me = this;	// avoid scope issues
+    var opts;	// shorthand options notation
+
+    // initialization function; private
+    me.initialize = function() {
+      // store DOM element and jQuery object for later use
+      me.el = el;
+      me.$el = $(el);
+
+      // remove any existing backups
+      var old_me = me.$el.data('TYPO3.FormEngine.FlexFormElement');
+      if (typeof old_me !== 'undefined') {
+        me.$el.removeData('TYPO3.FormEngine.FlexFormElement');
+      }
+
+      // add a reverse reference to the DOM element
+      me.$el.data('TYPO3.FormEngine.FlexFormElement', me);
+
+      if (!options) {
+        options = {};
+      }
+
+      // set some values from existing properties
+      options.allowRestructure = me.$el.data('t3-flex-allow-restructure');
+      options.flexformId = me.$el.attr('id');
+
+      // store options and merge with default options
+      opts = me.options = $.extend({}, TYPO3.FormEngine.FlexFormElement.defaults, options);
+
+      // initialize events
+      me.initializeEvents();
+
+      // generate the preview text if a section is hidden on load
+      me.$el.find(opts.sectionSelector).each(function() {
+        me.generateSectionPreview($(this));
+      });
+
+      return me;
+    };
+
+    /**
+     * init all events related to the flexform. As this method is called multiple times,
+     * some handlers need to be off'ed first to prevent event stacking.
+     */
+    me.initializeEvents = function() {
+      // Toggling all sections on/off by clicking all toggle buttons of each section
+      me.$el.prev(opts.flexFormToggleAllSectionsSelector).off('click').on('click', function() {
+        me.$el.find(opts.sectionToggleButtonSelector).trigger('click');
+      });
+
+      if (opts.allowRestructure) {
+        // create a sortable when dragging on the header of a section
+        me.createSortable();
+
+        // allow delete of a single section
+        me.$el.off('click').on('click', opts.deleteIconSelector, function(evt) {
+          evt.preventDefault();
+
+          var confirmTitle = TYPO3.lang['flexform.section.delete.title'] || 'Are you sure?';
+          var confirmMessage = TYPO3.lang['flexform.section.delete.message'] || 'Are you sure you want to delete this section?';
+          var $confirm = Modal.confirm(confirmTitle, confirmMessage);
+          $confirm.on('confirm.button.cancel', function() {
+            Modal.currentModal.trigger('modal-dismiss');
+          });
+          $confirm.on('confirm.button.ok', function(event) {
+            $(evt.target).closest(opts.sectionSelector).hide().addClass(opts.sectionDeletedClass);
+            me.setActionStatus();
+            TYPO3.FormEngine.Validation.validate();
+            Modal.currentModal.trigger('modal-dismiss');
+          });
+        });
+
+        // allow the toggle open/close of the main selection
+        me.$el.on('click', opts.sectionToggleButtonSelector, function(evt) {
+          evt.preventDefault();
+          var $sectionEl = $(this).closest(opts.sectionSelector);
+          me.toggleSection($sectionEl);
+        }).on('click', opts.sectionToggleButtonSelector + ' .form-irre-header-control', function(evt) {
+          evt.stopPropagation();
+        });
+      }
+
+      return me;
+    };
+
+    // initialize ourself
+    me.initialize();
+  };
+
+  // setting some default values
+  TYPO3.FormEngine.FlexFormElement.defaults = {
+    'deleteIconSelector': '.t3js-delete',
+    'sectionSelector': '.t3js-flex-section',
+    'sectionContentSelector': '.t3js-flex-section-content',
+    'sectionHeaderSelector': '.t3js-flex-section-header',
+    'sectionHeaderPreviewSelector': '.t3js-flex-section-header-preview',
+    'sectionActionInputFieldSelector': '.t3js-flex-control-action',
+    'sectionToggleInputFieldSelector': '.t3js-flex-control-toggle',
+    'sectionToggleIconOpenSelector': '.t3js-flex-control-toggle-icon-open',
+    'sectionToggleIconCloseSelector': '.t3js-flex-control-toggle-icon-close',
+    'sectionToggleButtonSelector': '[data-toggle="formengine-flex"]',
+    'flexFormToggleAllSectionsSelector': '.t3js-form-field-toggle-flexsection',
+    'sectionDeletedClass': 't3js-flex-section-deleted',
+    'allowRestructure': 0,	// whether the form can be modified
+    'flexformId': false
+  };
+
+
+  /**
+   * Allow flexform sections to be sorted
+   */
+  TYPO3.FormEngine.FlexFormElement.prototype.createSortable = function() {
+    var me = this;
+
+    require(['jquery-ui/sortable'], function() {
+      me.$el.sortable({
+        containment: 'parent',
+        handle: '.t3js-sortable-handle',
+        axis: 'y',
+        tolerance: 'pointer',
+        stop: function() {
+          me.setActionStatus();
+        }
+      });
+    });
+  };
+
+  // Updates the "action"-status for a section. This is used to move and delete elements.
+  TYPO3.FormEngine.FlexFormElement.prototype.setActionStatus = function() {
+    var me = this;
+
+    // Traverse and find how many sections are open or closed, and save the value accordingly
+    me.$el.find(me.options.sectionActionInputFieldSelector).each(function(index) {
+      var actionValue = ($(this).parents(me.options.sectionSelector).hasClass(me.options.sectionDeletedClass) ? 'DELETE' : index);
+      $(this).val(actionValue);
+    });
+  };
+
+  // Toggling flexform elements on/off
+  // hides the flexform section and shows a preview text
+  // or shows the form parts
+  TYPO3.FormEngine.FlexFormElement.prototype.toggleSection = function($sectionEl) {
+
+    var $contentEl = $sectionEl.find(this.options.sectionContentSelector);
+
+    // display/hide the content of this flexform section
+    $contentEl.toggle();
+
+    if ($contentEl.is(':visible')) {
+      // show the open icon, and set the hidden field for toggling to "hidden"
+      $sectionEl.find(this.options.sectionToggleIconOpenSelector).show();
+      $sectionEl.find(this.options.sectionToggleIconCloseSelector).hide();
+      $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(0);
+    } else {
+      // show the close icon, and set the hidden field for toggling to "1"
+      $sectionEl.find(this.options.sectionToggleIconOpenSelector).hide();
+      $sectionEl.find(this.options.sectionToggleIconCloseSelector).show();
+      $sectionEl.find(this.options.sectionToggleInputFieldSelector).val(1);
+    }
+
+    // see if the preview content needs to be generated
+    this.generateSectionPreview($sectionEl);
+  };
+
+  // function to generate the section preview in the header
+  // if the section content is hidden
+  // called on load and when toggling an icon
+  TYPO3.FormEngine.FlexFormElement.prototype.generateSectionPreview = function($sectionEl) {
+    var $contentEl = $sectionEl.find(this.options.sectionContentSelector);
+    var previewContent = '';
+
+    if (!$contentEl.is(':visible')) {
+      $contentEl.find('input[type=text], textarea').each(function() {
+        var content = $($.parseHTML($(this).val())).text();
+        if (content.length > 50) {
+          content = content.substring(0, 50) + '...';
+        }
+        previewContent += (previewContent ? ' / ' : '') + content;
+      });
+    }
+
+    // create a preview container span element
+    if ($sectionEl.find(this.options.sectionHeaderPreviewSelector).length === 0) {
+      $sectionEl.find(this.options.sectionHeaderSelector).find('.t3js-record-title').parent()
+        .append('<span class="' + this.options.sectionHeaderPreviewSelector.replace(/\./, '') + '"></span>');
+    }
+
+    $sectionEl.find(this.options.sectionHeaderPreviewSelector).text(previewContent);
+  };
+
+  // register the flex functions as jQuery Plugin
+  $.fn.t3FormEngineFlexFormElement = function(options) {
+    // apply all util functions to ourself (for use in templates, etc.)
+    return this.each(function() {
+      (new TYPO3.FormEngine.FlexFormElement(this, options));
+    });
+  };
+
+  // Initialization Code
+  $(function() {
+    // run the flexform functions on all containers (which contains one or more sections)
+    $('.t3-flex-container').t3FormEngineFlexFormElement();
+
+    // Add handler to fetch container data on click on "add container" buttons
+    $('.t3js-flex-container-add').on('click', function(e) {
+      var me = $(this);
+      e.preventDefault();
+      $.ajax({
+        url: TYPO3.settings.ajaxUrls['record_flex_container_add'],
+        type: 'POST',
+        cache: false,
+        data: {
+          vanillaUid: me.data('vanillauid'),
+          databaseRowUid: me.data('databaserowuid'),
+          command: me.data('command'),
+          tableName: me.data('tablename'),
+          fieldName: me.data('fieldname'),
+          recordTypeValue: me.data('recordtypevalue'),
+          dataStructureIdentifier: me.data('datastructureidentifier'),
+          flexFormSheetName: me.data('flexformsheetname'),
+          flexFormFieldName: me.data('flexformfieldname'),
+          flexFormContainerName: me.data('flexformcontainername')
+        },
+        success: function(response) {
+          me.closest('.t3-form-field-container').find('.t3-flex-container').append(response.html);
+          $('.t3-flex-container').t3FormEngineFlexFormElement();
+          if (response.scriptCall && response.scriptCall.length > 0) {
+            $.each(response.scriptCall, function(index, value) {
+              eval(value);
+            });
+          }
+          if (response.stylesheetFiles && response.stylesheetFiles.length > 0) {
+            $.each(response.stylesheetFiles, function(index, stylesheetFile) {
+              var element = document.createElement('link');
+              element['rel'] = 'stylesheet';
+              element['type'] = 'text/css';
+              element['href'] = stylesheetFile;
+              document.head.appendChild(element);
+            });
+          }
+          TYPO3.FormEngine.reinitialize();
+          TYPO3.FormEngine.Validation.initializeInputFields();
+          TYPO3.FormEngine.Validation.validate();
+        }
+      });
+    });
+
+  });
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js
index f350f1306d65..166de25f894a 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineLinkBrowserAdapter.js
@@ -16,61 +16,61 @@
  * LinkBrowser communication with parent window
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{updateFunctions: null}}
-	 * @exports TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter
-	 */
-	var FormEngineLinkBrowserAdapter = {
-		updateFunctions: null // those are set in the module initializer function in PHP
-	};
+  /**
+   *
+   * @type {{updateFunctions: null}}
+   * @exports TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter
+   */
+  var FormEngineLinkBrowserAdapter = {
+    updateFunctions: null // those are set in the module initializer function in PHP
+  };
 
-	/**
-	 * Return reference to parent's form element
-	 *
-	 * @returns {Element}
-	 */
-	FormEngineLinkBrowserAdapter.checkReference = function () {
-		var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]';
-		if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) {
-			return window.opener.document.querySelector(selector);
-		} else {
-			close();
-		}
-	};
+  /**
+   * Return reference to parent's form element
+   *
+   * @returns {Element}
+   */
+  FormEngineLinkBrowserAdapter.checkReference = function() {
+    var selector = 'form[name="' + LinkBrowser.parameters.formName + '"] [data-formengine-input-name="' + LinkBrowser.parameters.itemName + '"]';
+    if (window.opener && window.opener.document && window.opener.document.querySelector(selector)) {
+      return window.opener.document.querySelector(selector);
+    } else {
+      close();
+    }
+  };
 
-	/**
-	 * Save the current link back to the opener
-	 *
-	 * @param {String} input
-	 */
-	LinkBrowser.finalizeFunction = function(input) {
-		var field = FormEngineLinkBrowserAdapter.checkReference();
-		if (field) {
-			var attributeValues = LinkBrowser.getLinkAttributeValues();
-			// encode link on server
-			attributeValues.url = input;
+  /**
+   * Save the current link back to the opener
+   *
+   * @param {String} input
+   */
+  LinkBrowser.finalizeFunction = function(input) {
+    var field = FormEngineLinkBrowserAdapter.checkReference();
+    if (field) {
+      var attributeValues = LinkBrowser.getLinkAttributeValues();
+      // encode link on server
+      attributeValues.url = input;
 
-			$.ajax({
-				url: TYPO3.settings.ajaxUrls['link_browser_encodetypolink'],
-				data: attributeValues,
-				method: 'GET'
-			}).done(function(data) {
-				if (data.typoLink) {
-					$('#' + field.id, parent.opener.document).val(data.typoLink);
-					if (typeof field.onchange === 'function') {
-						field.onchange();
-					}
+      $.ajax({
+        url: TYPO3.settings.ajaxUrls['link_browser_encodetypolink'],
+        data: attributeValues,
+        method: 'GET'
+      }).done(function(data) {
+        if (data.typoLink) {
+          $('#' + field.id, parent.opener.document).val(data.typoLink);
+          if (typeof field.onchange === 'function') {
+            field.onchange();
+          }
 
-					FormEngineLinkBrowserAdapter.updateFunctions();
+          FormEngineLinkBrowserAdapter.updateFunctions();
 
-					close();
-				}
-			});
-		}
-	};
+          close();
+        }
+      });
+    }
+  };
 
-	return FormEngineLinkBrowserAdapter;
+  return FormEngineLinkBrowserAdapter;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js
index f43a8d9b80f5..e54c8fcd786c 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineSuggest.js
@@ -15,114 +15,114 @@
  * Module: TYPO3/CMS/Backend/FormEngineSuggest
  * Functionality to load suggest functionality
  */
-define(['jquery', 'jquery/autocomplete'], function ($) {
-	var initialize = function($searchField) {
-		var $containerElement = $searchField.closest('.t3-form-suggest-container');
-		var tableName = $searchField.data('tablename'),
-			fieldName = $searchField.data('fieldname'),
-			formEl = $searchField.data('field'),
-			uid = $searchField.data('uid'),
-			pid = $searchField.data('pid'),
-			dataStructureIdentifier = $searchField.data('datastructureidentifier'),
-			flexFormSheetName = $searchField.data('flexformsheetname'),
-			flexFormFieldName = $searchField.data('flexformfieldname'),
-			flexFormContainerName = $searchField.data('flexformcontainername'),
-			flexFormContainerFieldName = $searchField.data('flexformcontainerfieldname'),
-			minimumCharacters = $searchField.data('minchars'),
-			url = TYPO3.settings.ajaxUrls['record_suggest'],
-			params = {
-				'tableName': tableName,
-				'fieldName': fieldName,
-				'uid': uid,
-				'pid': pid,
-				'dataStructureIdentifier': dataStructureIdentifier,
-				'flexFormSheetName': flexFormSheetName,
-				'flexFormFieldName': flexFormFieldName,
-				'flexFormContainerName': flexFormContainerName,
-				'flexFormContainerFieldName': flexFormContainerFieldName
-			},
-			insertValue = function(element) {
-				var insertData = '';
-				if ($searchField.data('fieldtype') === 'select') {
-					insertData = $(element).data('uid');
-				} else {
-					insertData = $(element).data('table') + '_' + $(element).data('uid');
-				}
-				var labelEl = $('<div>').html($(element).data('label'));
-				var label = labelEl.text();
-				var title = labelEl.find('span').attr('title') || label;
-				setFormValueFromBrowseWin(formEl, insertData, label, title);
-				TBE_EDITOR.fieldChanged(tableName, uid, fieldName, formEl);
-			};
+define(['jquery', 'jquery/autocomplete'], function($) {
+  var initialize = function($searchField) {
+    var $containerElement = $searchField.closest('.t3-form-suggest-container');
+    var tableName = $searchField.data('tablename'),
+      fieldName = $searchField.data('fieldname'),
+      formEl = $searchField.data('field'),
+      uid = $searchField.data('uid'),
+      pid = $searchField.data('pid'),
+      dataStructureIdentifier = $searchField.data('datastructureidentifier'),
+      flexFormSheetName = $searchField.data('flexformsheetname'),
+      flexFormFieldName = $searchField.data('flexformfieldname'),
+      flexFormContainerName = $searchField.data('flexformcontainername'),
+      flexFormContainerFieldName = $searchField.data('flexformcontainerfieldname'),
+      minimumCharacters = $searchField.data('minchars'),
+      url = TYPO3.settings.ajaxUrls['record_suggest'],
+      params = {
+        'tableName': tableName,
+        'fieldName': fieldName,
+        'uid': uid,
+        'pid': pid,
+        'dataStructureIdentifier': dataStructureIdentifier,
+        'flexFormSheetName': flexFormSheetName,
+        'flexFormFieldName': flexFormFieldName,
+        'flexFormContainerName': flexFormContainerName,
+        'flexFormContainerFieldName': flexFormContainerFieldName
+      },
+      insertValue = function(element) {
+        var insertData = '';
+        if ($searchField.data('fieldtype') === 'select') {
+          insertData = $(element).data('uid');
+        } else {
+          insertData = $(element).data('table') + '_' + $(element).data('uid');
+        }
+        var labelEl = $('<div>').html($(element).data('label'));
+        var label = labelEl.text();
+        var title = labelEl.find('span').attr('title') || label;
+        setFormValueFromBrowseWin(formEl, insertData, label, title);
+        TBE_EDITOR.fieldChanged(tableName, uid, fieldName, formEl);
+      };
 
-		$searchField.autocomplete({
-			// ajax options
-			serviceUrl: url,
-			params: params,
-			type: 'POST',
-			paramName: 'value',
-			dataType: 'json',
-			minChars: minimumCharacters,
-			groupBy: 'typeLabel',
-			containerClass: 'autocomplete-results',
-			appendTo: $containerElement,
-			forceFixPosition: false,
-			preserveInput: true,
-			showNoSuggestionNotice: true,
-			noSuggestionNotice: '<div class="autocomplete-info">No results</div>',
-			minLength: minimumCharacters,
-			preventBadQueries: false,
-			// put the AJAX results in the right format
-			transformResult: function(response) {
-				return {
-					suggestions: $.map(response, function(dataItem) {
-						return { value: dataItem.text, data: dataItem };
-					})
-				};
-			},
-			// Rendering of each item
-			formatResult: function(suggestion, value) {
-				return $('<div>').append(
-							$('<a class="autocomplete-suggestion-link" href="#">' +
-								suggestion.data.sprite + suggestion.data.text +
-							'</a></div>').attr({
-								'data-label': suggestion.data.label,
-								'data-table': suggestion.data.table,
-								'data-uid': suggestion.data.uid
-							})).html();
-			},
-			onSearchComplete: function() {
-				$containerElement.addClass('open');
-			},
-			beforeRender: function(container) {
-				// Unset height, width and z-index again, should be fixed by the plugin at a later point
-				container.attr('style', '');
-				$containerElement.addClass('open');
-			},
-			onHide: function() {
-				$containerElement.removeClass('open');
-			},
-			onSelect: function() {
-				insertValue($containerElement.find('.autocomplete-selected a')[0]);
-			}
-		});
+    $searchField.autocomplete({
+      // ajax options
+      serviceUrl: url,
+      params: params,
+      type: 'POST',
+      paramName: 'value',
+      dataType: 'json',
+      minChars: minimumCharacters,
+      groupBy: 'typeLabel',
+      containerClass: 'autocomplete-results',
+      appendTo: $containerElement,
+      forceFixPosition: false,
+      preserveInput: true,
+      showNoSuggestionNotice: true,
+      noSuggestionNotice: '<div class="autocomplete-info">No results</div>',
+      minLength: minimumCharacters,
+      preventBadQueries: false,
+      // put the AJAX results in the right format
+      transformResult: function(response) {
+        return {
+          suggestions: $.map(response, function(dataItem) {
+            return {value: dataItem.text, data: dataItem};
+          })
+        };
+      },
+      // Rendering of each item
+      formatResult: function(suggestion, value) {
+        return $('<div>').append(
+          $('<a class="autocomplete-suggestion-link" href="#">' +
+            suggestion.data.sprite + suggestion.data.text +
+            '</a></div>').attr({
+            'data-label': suggestion.data.label,
+            'data-table': suggestion.data.table,
+            'data-uid': suggestion.data.uid
+          })).html();
+      },
+      onSearchComplete: function() {
+        $containerElement.addClass('open');
+      },
+      beforeRender: function(container) {
+        // Unset height, width and z-index again, should be fixed by the plugin at a later point
+        container.attr('style', '');
+        $containerElement.addClass('open');
+      },
+      onHide: function() {
+        $containerElement.removeClass('open');
+      },
+      onSelect: function() {
+        insertValue($containerElement.find('.autocomplete-selected a')[0]);
+      }
+    });
 
-		// set up the events
-		$containerElement.on('click', '.autocomplete-suggestion-link', function(evt) {
-			evt.preventDefault();
-		});
-	};
+    // set up the events
+    $containerElement.on('click', '.autocomplete-suggestion-link', function(evt) {
+      evt.preventDefault();
+    });
+  };
 
-	/**
-	 * Return a function that gets DOM elements that are checked if suggest is already initialized
-	 * @exports TYPO3/CMS/Backend/FormEngineSuggest
-	 */
-	return function(selectorElements) {
-		$(selectorElements).each(function(key, el) {
-			if (!$(el).data('t3-suggest-initialized')) {
-				initialize($(el));
-				$(el).data('t3-suggest-initialized', true);
-			}
-		});
-	};
+  /**
+   * Return a function that gets DOM elements that are checked if suggest is already initialized
+   * @exports TYPO3/CMS/Backend/FormEngineSuggest
+   */
+  return function(selectorElements) {
+    $(selectorElements).each(function(key, el) {
+      if (!$(el).data('t3-suggest-initialized')) {
+        initialize($(el));
+        $(el).data('t3-suggest-initialized', true);
+      }
+    });
+  };
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js
index d6523808697d..7c74acb9be0f 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/FormEngineValidation.js
@@ -16,1009 +16,1009 @@
  * Contains all JS functions related to TYPO3 TCEforms/FormEngineValidation
  * @internal
  */
-define(['jquery', 'moment'], function ($, moment) {
+define(['jquery', 'moment'], function($, moment) {
 
-	/**
-	 * The main FormEngineValidation object
-	 *
-	 * @type {{rulesSelector: string, inputSelector: string, markerSelector: string, groupFieldHiddenElement: string, relatedFieldSelector: string, errorClass: string, lastYear: number, lastDate: number, lastTime: number, USmode: number, passwordDummy: string}}
-	 * @exports TYPO3/CMS/Backend/FormEngineValidation
-	 */
-	var FormEngineValidation = {
-		rulesSelector: '[data-formengine-validation-rules]',
-		inputSelector: '[data-formengine-input-params]',
-		markerSelector: '.t3js-formengine-validation-marker',
-		groupFieldHiddenElement: '.t3js-formengine-field-group input[type=hidden]',
-		relatedFieldSelector: '[data-relatedfieldname]',
-		errorClass: 'has-error',
-		lastYear: 0,
-		lastDate: 0,
-		lastTime: 0,
-		USmode: 0,
-		passwordDummy: '********'
-	};
+  /**
+   * The main FormEngineValidation object
+   *
+   * @type {{rulesSelector: string, inputSelector: string, markerSelector: string, groupFieldHiddenElement: string, relatedFieldSelector: string, errorClass: string, lastYear: number, lastDate: number, lastTime: number, USmode: number, passwordDummy: string}}
+   * @exports TYPO3/CMS/Backend/FormEngineValidation
+   */
+  var FormEngineValidation = {
+    rulesSelector: '[data-formengine-validation-rules]',
+    inputSelector: '[data-formengine-input-params]',
+    markerSelector: '.t3js-formengine-validation-marker',
+    groupFieldHiddenElement: '.t3js-formengine-field-group input[type=hidden]',
+    relatedFieldSelector: '[data-relatedfieldname]',
+    errorClass: 'has-error',
+    lastYear: 0,
+    lastDate: 0,
+    lastTime: 0,
+    USmode: 0,
+    passwordDummy: '********'
+  };
 
-	/**
-	 * Initialize validation for the first time
-	 */
-	FormEngineValidation.initialize = function() {
-		$(document).find('.' + FormEngineValidation.errorClass).removeClass(FormEngineValidation.errorClass);
+  /**
+   * Initialize validation for the first time
+   */
+  FormEngineValidation.initialize = function() {
+    $(document).find('.' + FormEngineValidation.errorClass).removeClass(FormEngineValidation.errorClass);
 
-		// Initialize input fields
-		FormEngineValidation.initializeInputFields().promise().done(function () {
-			// Bind to field changes
-			$(document).on('change', FormEngineValidation.rulesSelector, function() {
-				FormEngineValidation.validate();
-				FormEngineValidation.markFieldAsChanged($(this));
-			});
-		});
+    // Initialize input fields
+    FormEngineValidation.initializeInputFields().promise().done(function() {
+      // Bind to field changes
+      $(document).on('change', FormEngineValidation.rulesSelector, function() {
+        FormEngineValidation.validate();
+        FormEngineValidation.markFieldAsChanged($(this));
+      });
+    });
 
-		var today = new Date();
-		FormEngineValidation.lastYear = FormEngineValidation.getYear(today);
-		FormEngineValidation.lastDate = FormEngineValidation.getDate(today);
-		FormEngineValidation.lastTime = 0;
-		FormEngineValidation.USmode = 0;
-		FormEngineValidation.validate();
-	};
+    var today = new Date();
+    FormEngineValidation.lastYear = FormEngineValidation.getYear(today);
+    FormEngineValidation.lastDate = FormEngineValidation.getDate(today);
+    FormEngineValidation.lastTime = 0;
+    FormEngineValidation.USmode = 0;
+    FormEngineValidation.validate();
+  };
 
-	/**
-	 * Initialize all input fields
-	 *
-	 * @returns {Object}
-	 */
-	FormEngineValidation.initializeInputFields = function() {
-		return $(document).find(FormEngineValidation.inputSelector).each(function() {
-			var config = $(this).data('formengine-input-params');
-			var fieldName = config.field;
-			var $field = $('[name="' + fieldName + '"]');
+  /**
+   * Initialize all input fields
+   *
+   * @returns {Object}
+   */
+  FormEngineValidation.initializeInputFields = function() {
+    return $(document).find(FormEngineValidation.inputSelector).each(function() {
+      var config = $(this).data('formengine-input-params');
+      var fieldName = config.field;
+      var $field = $('[name="' + fieldName + '"]');
 
-			// ignore fields which already have been initialized
-			if ($field.data('main-field') === undefined) {
-				$field.data('main-field', fieldName);
-				$field.data('config', config);
-				FormEngineValidation.initializeInputField(fieldName);
-			}
-		});
-	};
+      // ignore fields which already have been initialized
+      if ($field.data('main-field') === undefined) {
+        $field.data('main-field', fieldName);
+        $field.data('config', config);
+        FormEngineValidation.initializeInputField(fieldName);
+      }
+    });
+  };
 
-	/**
-	 *
-	 * @param {Number} mode
-	 */
-	FormEngineValidation.setUsMode = function(mode) {
-		FormEngineValidation.USmode = mode;
-	};
+  /**
+   *
+   * @param {Number} mode
+   */
+  FormEngineValidation.setUsMode = function(mode) {
+    FormEngineValidation.USmode = mode;
+  };
 
-	/**
-	 * Initialize field by name
-	 *
-	 * @param {String} fieldName
-	 */
-	FormEngineValidation.initializeInputField = function(fieldName) {
-		var $field = $('[name="' + fieldName + '"]');
-		var $humanReadableField = $('[data-formengine-input-name="' + fieldName + '"]');
-		var $mainField = $('[name="' + $field.data('main-field') + '"]');
-		if ($mainField.length === 0) {
-			$mainField = $field;
-		}
+  /**
+   * Initialize field by name
+   *
+   * @param {String} fieldName
+   */
+  FormEngineValidation.initializeInputField = function(fieldName) {
+    var $field = $('[name="' + fieldName + '"]');
+    var $humanReadableField = $('[data-formengine-input-name="' + fieldName + '"]');
+    var $mainField = $('[name="' + $field.data('main-field') + '"]');
+    if ($mainField.length === 0) {
+      $mainField = $field;
+    }
 
-		var config = $mainField.data('config');
-		if (typeof config !== 'undefined') {
-			var evalList = FormEngineValidation.trimExplode(',', config.evalList);
-			var value = $field.val();
+    var config = $mainField.data('config');
+    if (typeof config !== 'undefined') {
+      var evalList = FormEngineValidation.trimExplode(',', config.evalList);
+      var value = $field.val();
 
-			for (var i = 0; i < evalList.length; i++) {
-				value = FormEngineValidation.formatValue(evalList[i], value, config);
-			}
-			// Prevent password fields to be overwritten with original value
-			if (value.length && $humanReadableField.attr('type') !== 'password') {
-				$humanReadableField.val(value);
-			}
-		}
-		$humanReadableField.data('main-field', fieldName);
-		$humanReadableField.data('config', config);
-		$humanReadableField.on('change', function() {
-			FormEngineValidation.updateInputField($(this).attr('data-formengine-input-name'));
-		});
-		$humanReadableField.on('keyup', FormEngineValidation.validate);
+      for (var i = 0; i < evalList.length; i++) {
+        value = FormEngineValidation.formatValue(evalList[i], value, config);
+      }
+      // Prevent password fields to be overwritten with original value
+      if (value.length && $humanReadableField.attr('type') !== 'password') {
+        $humanReadableField.val(value);
+      }
+    }
+    $humanReadableField.data('main-field', fieldName);
+    $humanReadableField.data('config', config);
+    $humanReadableField.on('change', function() {
+      FormEngineValidation.updateInputField($(this).attr('data-formengine-input-name'));
+    });
+    $humanReadableField.on('keyup', FormEngineValidation.validate);
 
-		// add the attribute so that acceptance tests can know when the field initialization has completed
-		$humanReadableField.attr('data-formengine-input-initialized', 'true');
-	};
+    // add the attribute so that acceptance tests can know when the field initialization has completed
+    $humanReadableField.attr('data-formengine-input-initialized', 'true');
+  };
 
-	/**
-	 * Format field value
-	 *
-	 * @param {String} type
-	 * @param {String} value
-	 * @param {Object} config
-	 * @returns {String}
-	 */
-	FormEngineValidation.formatValue = function(type, value, config) {
-		var theString = '';
-		var parsedInt, theTime;
-		switch (type) {
-			case 'date':
-				// poor man’s ISO-8601 detection: if we have a "-" in it, it apparently is not an integer.
-				if (value.toString().indexOf('-') > 0) {
-					var date = moment.utc(value);
-					if (FormEngineValidation.USmode) {
-						theString = date.format('MM-DD-YYYY');
-					} else {
-						theString = date.format('DD-MM-YYYY');
-					}
-				} else {
-					parsedInt = value * 1;
-					if (!parsedInt) {
-						return '';
-					}
-					theTime = new Date(parsedInt * 1000);
-					if (FormEngineValidation.USmode) {
-						theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime);
-					} else {
-						theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime);
-					}
-				}
-				break;
-			case 'datetime':
-				if (value.toString().indexOf('-') <= 0 && !parseInt(value)) {
-					return '';
-				}
-				theString = FormEngineValidation.formatValue('time', value, config) + ' ' + FormEngineValidation.formatValue('date', value, config);
-				break;
-			case 'time':
-			case 'timesec':
-				var dateValue;
-				if (value.toString().indexOf('-') > 0) {
-					dateValue = moment.utc(value);
-				} else {
-					parsedInt = parseInt(value);
-					if (!parsedInt && value.toString() !== '0') {
-						return '';
-					}
-					dateValue = moment.unix(parsedInt).utc();
-				}
-				if (type === 'timesec') {
-					theString = dateValue.format('HH:mm:ss');
-				} else {
-					theString = dateValue.format('HH:mm');
-				}
-				break;
-			case 'password':
-				theString = (value) ? FormEngineValidation.passwordDummy : '';
-				break;
-			default:
-				theString = value;
-		}
-		return theString;
-	};
+  /**
+   * Format field value
+   *
+   * @param {String} type
+   * @param {String} value
+   * @param {Object} config
+   * @returns {String}
+   */
+  FormEngineValidation.formatValue = function(type, value, config) {
+    var theString = '';
+    var parsedInt, theTime;
+    switch (type) {
+      case 'date':
+        // poor man’s ISO-8601 detection: if we have a "-" in it, it apparently is not an integer.
+        if (value.toString().indexOf('-') > 0) {
+          var date = moment.utc(value);
+          if (FormEngineValidation.USmode) {
+            theString = date.format('MM-DD-YYYY');
+          } else {
+            theString = date.format('DD-MM-YYYY');
+          }
+        } else {
+          parsedInt = value * 1;
+          if (!parsedInt) {
+            return '';
+          }
+          theTime = new Date(parsedInt * 1000);
+          if (FormEngineValidation.USmode) {
+            theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime);
+          } else {
+            theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime);
+          }
+        }
+        break;
+      case 'datetime':
+        if (value.toString().indexOf('-') <= 0 && !parseInt(value)) {
+          return '';
+        }
+        theString = FormEngineValidation.formatValue('time', value, config) + ' ' + FormEngineValidation.formatValue('date', value, config);
+        break;
+      case 'time':
+      case 'timesec':
+        var dateValue;
+        if (value.toString().indexOf('-') > 0) {
+          dateValue = moment.utc(value);
+        } else {
+          parsedInt = parseInt(value);
+          if (!parsedInt && value.toString() !== '0') {
+            return '';
+          }
+          dateValue = moment.unix(parsedInt).utc();
+        }
+        if (type === 'timesec') {
+          theString = dateValue.format('HH:mm:ss');
+        } else {
+          theString = dateValue.format('HH:mm');
+        }
+        break;
+      case 'password':
+        theString = (value) ? FormEngineValidation.passwordDummy : '';
+        break;
+      default:
+        theString = value;
+    }
+    return theString;
+  };
 
-	/**
-	 * Update input field after change
-	 *
-	 * @param {String} fieldName
-	 */
-	FormEngineValidation.updateInputField = function(fieldName) {
-		var $field = $('[name="' + fieldName + '"]');
-		var $mainField = $('[name="' + $field.data('main-field') + '"]');
-		if ($mainField.length === 0) {
-			$mainField = $field;
-		}
-		var $humanReadableField = $('[data-formengine-input-name="' + $mainField.attr('name') + '"]');
+  /**
+   * Update input field after change
+   *
+   * @param {String} fieldName
+   */
+  FormEngineValidation.updateInputField = function(fieldName) {
+    var $field = $('[name="' + fieldName + '"]');
+    var $mainField = $('[name="' + $field.data('main-field') + '"]');
+    if ($mainField.length === 0) {
+      $mainField = $field;
+    }
+    var $humanReadableField = $('[data-formengine-input-name="' + $mainField.attr('name') + '"]');
 
-		var config = $mainField.data('config');
-		if (typeof config !== 'undefined') {
-			var evalList = FormEngineValidation.trimExplode(',', config.evalList);
-			var newValue = $humanReadableField.val();
-			var i;
+    var config = $mainField.data('config');
+    if (typeof config !== 'undefined') {
+      var evalList = FormEngineValidation.trimExplode(',', config.evalList);
+      var newValue = $humanReadableField.val();
+      var i;
 
-			for (i = 0; i < evalList.length; i++) {
-				newValue = FormEngineValidation.processValue(evalList[i], newValue, config);
-			}
+      for (i = 0; i < evalList.length; i++) {
+        newValue = FormEngineValidation.processValue(evalList[i], newValue, config);
+      }
 
-			var formattedValue = newValue;
-			for (i = 0; i < evalList.length; i++) {
-				formattedValue = FormEngineValidation.formatValue(evalList[i], formattedValue, config);
-			}
+      var formattedValue = newValue;
+      for (i = 0; i < evalList.length; i++) {
+        formattedValue = FormEngineValidation.formatValue(evalList[i], formattedValue, config);
+      }
 
-			$mainField.val(newValue);
-			$humanReadableField.val(formattedValue);
-		}
-	};
+      $mainField.val(newValue);
+      $humanReadableField.val(formattedValue);
+    }
+  };
 
-	/**
-	 * Run validation for field
-	 *
-	 * @param {Object} $field
-	 * @param {String} [value=$field.val()]
-	 * @returns {String}
-	 */
-	FormEngineValidation.validateField = function($field, value) {
-		value = value || $field.val() || '';
+  /**
+   * Run validation for field
+   *
+   * @param {Object} $field
+   * @param {String} [value=$field.val()]
+   * @returns {String}
+   */
+  FormEngineValidation.validateField = function($field, value) {
+    value = value || $field.val() || '';
 
-		var rules = $field.data('formengine-validation-rules');
-		var markParent = false;
-		var selected = 0;
-		// keep the original value, validateField should not alter it
-		var returnValue = value;
-		var $relatedField;
-		var minItems;
-		var maxItems;
+    var rules = $field.data('formengine-validation-rules');
+    var markParent = false;
+    var selected = 0;
+    // keep the original value, validateField should not alter it
+    var returnValue = value;
+    var $relatedField;
+    var minItems;
+    var maxItems;
 
-		if (!$.isArray(value)) {
-			value = FormEngineValidation.ltrim(value);
-		}
+    if (!$.isArray(value)) {
+      value = FormEngineValidation.ltrim(value);
+    }
 
-		$.each(rules, function(k, rule) {
-			if (markParent) {
-				// abort any further validation as validating the field already failed
-				return false;
-			}
-			switch (rule.type) {
-				case 'required':
-					if (value === '') {
-						markParent = true;
-						$field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass);
-					}
-					break;
-				case 'range':
-					if (value !== '') {
-						if (rule.minItems || rule.maxItems) {
-							$relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]');
-							if ($relatedField.length) {
-								selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length;
-							} else {
-								selected = $field.val();
-							}
-							if (typeof rule.minItems !== 'undefined') {
-								minItems = rule.minItems * 1;
-								if (!isNaN(minItems) && selected < minItems) {
-									markParent = true;
-								}
-							}
-							if (typeof rule.maxItems !== 'undefined') {
-								maxItems = rule.maxItems * 1;
-								if (!isNaN(maxItems) && selected > maxItems) {
-									markParent = true;
-								}
-							}
-						}
-						if (typeof rule.lower !== 'undefined') {
-							var minValue = rule.lower * 1;
-							if (!isNaN(minValue) && value < minValue) {
-								markParent = true;
-							}
-						}
-						if (typeof rule.upper !== 'undefined') {
-							var maxValue = rule.upper * 1;
-							if (!isNaN(maxValue) && value > maxValue) {
-								markParent = true;
-							}
-						}
-					}
-					break;
-				case 'select':
-					if (rule.minItems || rule.maxItems) {
-						$relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]');
-						if ($relatedField.length) {
-							selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length;
-						} else {
-							selected = $field.find('option:selected').length;
-						}
-						if (typeof rule.minItems !== 'undefined') {
-							minItems = rule.minItems * 1;
-							if (!isNaN(minItems) && selected < minItems) {
-								markParent = true;
-							}
-						}
-						if (typeof rule.maxItems !== 'undefined') {
-							maxItems = rule.maxItems * 1;
-							if (!isNaN(maxItems) && selected > maxItems) {
-								markParent = true;
-							}
-						}
-					}
-					break;
-				case 'group':
-					if (rule.minItems || rule.maxItems) {
-						selected = $field.find('option').length;
-						if (typeof rule.minItems !== 'undefined') {
-							minItems = rule.minItems * 1;
-							if (!isNaN(minItems) && selected < minItems) {
-								markParent = true;
-							}
-						}
-						if (typeof rule.maxItems !== 'undefined') {
-							maxItems = rule.maxItems * 1;
-							if (!isNaN(maxItems) && selected > maxItems) {
-								markParent = true;
-							}
-						}
-					}
-					break;
-				case 'inline':
-					if (rule.minItems || rule.maxItems) {
-						selected = FormEngineValidation.trimExplode(',', $field.val()).length;
-						if (typeof rule.minItems !== 'undefined') {
-							minItems = rule.minItems * 1;
-							if (!isNaN(minItems) && selected < minItems) {
-								markParent = true;
-							}
-						}
-						if (typeof rule.maxItems !== 'undefined') {
-							maxItems = rule.maxItems * 1;
-							if (!isNaN(maxItems) && selected > maxItems) {
-								markParent = true;
-							}
-						}
-					}
-					break;
-				case 'null':
-					// unknown type null, we ignore it
-					break;
-			}
-		});
-		if (markParent) {
-			// mark field
-			$field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass);
+    $.each(rules, function(k, rule) {
+      if (markParent) {
+        // abort any further validation as validating the field already failed
+        return false;
+      }
+      switch (rule.type) {
+        case 'required':
+          if (value === '') {
+            markParent = true;
+            $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass);
+          }
+          break;
+        case 'range':
+          if (value !== '') {
+            if (rule.minItems || rule.maxItems) {
+              $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]');
+              if ($relatedField.length) {
+                selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length;
+              } else {
+                selected = $field.val();
+              }
+              if (typeof rule.minItems !== 'undefined') {
+                minItems = rule.minItems * 1;
+                if (!isNaN(minItems) && selected < minItems) {
+                  markParent = true;
+                }
+              }
+              if (typeof rule.maxItems !== 'undefined') {
+                maxItems = rule.maxItems * 1;
+                if (!isNaN(maxItems) && selected > maxItems) {
+                  markParent = true;
+                }
+              }
+            }
+            if (typeof rule.lower !== 'undefined') {
+              var minValue = rule.lower * 1;
+              if (!isNaN(minValue) && value < minValue) {
+                markParent = true;
+              }
+            }
+            if (typeof rule.upper !== 'undefined') {
+              var maxValue = rule.upper * 1;
+              if (!isNaN(maxValue) && value > maxValue) {
+                markParent = true;
+              }
+            }
+          }
+          break;
+        case 'select':
+          if (rule.minItems || rule.maxItems) {
+            $relatedField = $(document).find('[name="' + $field.data('relatedfieldname') + '"]');
+            if ($relatedField.length) {
+              selected = FormEngineValidation.trimExplode(',', $relatedField.val()).length;
+            } else {
+              selected = $field.find('option:selected').length;
+            }
+            if (typeof rule.minItems !== 'undefined') {
+              minItems = rule.minItems * 1;
+              if (!isNaN(minItems) && selected < minItems) {
+                markParent = true;
+              }
+            }
+            if (typeof rule.maxItems !== 'undefined') {
+              maxItems = rule.maxItems * 1;
+              if (!isNaN(maxItems) && selected > maxItems) {
+                markParent = true;
+              }
+            }
+          }
+          break;
+        case 'group':
+          if (rule.minItems || rule.maxItems) {
+            selected = $field.find('option').length;
+            if (typeof rule.minItems !== 'undefined') {
+              minItems = rule.minItems * 1;
+              if (!isNaN(minItems) && selected < minItems) {
+                markParent = true;
+              }
+            }
+            if (typeof rule.maxItems !== 'undefined') {
+              maxItems = rule.maxItems * 1;
+              if (!isNaN(maxItems) && selected > maxItems) {
+                markParent = true;
+              }
+            }
+          }
+          break;
+        case 'inline':
+          if (rule.minItems || rule.maxItems) {
+            selected = FormEngineValidation.trimExplode(',', $field.val()).length;
+            if (typeof rule.minItems !== 'undefined') {
+              minItems = rule.minItems * 1;
+              if (!isNaN(minItems) && selected < minItems) {
+                markParent = true;
+              }
+            }
+            if (typeof rule.maxItems !== 'undefined') {
+              maxItems = rule.maxItems * 1;
+              if (!isNaN(maxItems) && selected > maxItems) {
+                markParent = true;
+              }
+            }
+          }
+          break;
+        case 'null':
+          // unknown type null, we ignore it
+          break;
+      }
+    });
+    if (markParent) {
+      // mark field
+      $field.closest(FormEngineValidation.markerSelector).addClass(FormEngineValidation.errorClass);
 
-			// check tabs
-			FormEngineValidation.markParentTab($field);
-		}
-		return returnValue;
-	};
+      // check tabs
+      FormEngineValidation.markParentTab($field);
+    }
+    return returnValue;
+  };
 
-	/**
-	 * Process a value by given command and config
-	 *
-	 * @param {String} command
-	 * @param {String} value
-	 * @param {Array} config
-	 * @returns {String}
-	 */
-	FormEngineValidation.processValue = function(command, value, config) {
-		var newString = '';
-		var theValue = '';
-		var theCmd = '';
-		var a = 0;
-		var returnValue = value;
-		switch (command) {
-			case 'alpha':
-			case 'num':
-			case 'alphanum':
-			case 'alphanum_x':
-				newString = '';
-				for (a = 0; a < value.length; a++) {
-					theChar = value.substr(a, 1);
-					var special = (theChar === '_' || theChar === '-');
-					var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
-					var num = (theChar >= '0' && theChar <= '9');
-					switch (command) {
-						case 'alphanum':
-							special = 0;
-							break;
-						case 'alpha':
-							num = 0;
-							special = 0;
-							break;
-						case 'num':
-							alpha = 0;
-							special = 0;
-							break;
-					}
-					if (alpha || num || special) {
-						newString += theChar;
-					}
-				}
-				if (newString !== value) {
-					returnValue = newString;
-				}
-				break;
-			case 'is_in':
-				if (config.is_in) {
-					theValue = '' + value;
-					// Escape special characters, see https://stackoverflow.com/a/6969486/4828813
-					config.is_in = config.is_in.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
-					var re = new RegExp('[^' + config.is_in + ']+', 'g');
-					newString = theValue.replace(re, '');
-				} else {
-					newString = theValue;
-				}
-				returnValue = newString;
-				break;
-			case 'nospace':
-				returnValue = ('' + value).replace(/ /g, '');
-				break;
-			case 'md5':
-				if (value !== '') {
-					returnValue = MD5(value);
-				}
-				break;
-			case 'upper':
-				returnValue = value.toUpperCase();
-				break;
-			case 'lower':
-				returnValue = value.toLowerCase();
-				break;
-			case 'int':
-				if (value !== '') {
-					returnValue = FormEngineValidation.parseInt(value);
-				}
-				break;
-			case 'double2':
-				if (value !== '') {
-					returnValue = FormEngineValidation.parseDouble(value);
-				}
-				break;
-			case 'trim':
-				returnValue = String(value).trim();
-				break;
-			case 'datetime':
-				if (value !== '') {
-					theCmd = value.substr(0, 1);
-					returnValue = FormEngineValidation.parseDateTime(value, theCmd);
-				}
-				break;
-			case 'date':
-				if (value !== '') {
-					theCmd = value.substr(0, 1);
-					returnValue = FormEngineValidation.parseDate(value, theCmd);
-				}
-				break;
-			case 'time':
-			case 'timesec':
-				if (value !== '') {
-					theCmd = value.substr(0, 1);
-					returnValue = FormEngineValidation.parseTime(value, theCmd, command);
-				}
-				break;
-			case 'year':
-				if (value !== '') {
-					theCmd = value.substr(0, 1);
-					returnValue = FormEngineValidation.parseYear(value, theCmd);
-				}
-				break;
-			case 'null':
-				// unknown type null, we ignore it
-				break;
-			case 'password':
-				// password is only a display evaluation, we ignore it
-				break;
-			default:
-				if (typeof TBE_EDITOR.customEvalFunctions !== 'undefined' && typeof TBE_EDITOR.customEvalFunctions[command] === 'function') {
-					returnValue = TBE_EDITOR.customEvalFunctions[command](value);
-				}
-		}
-		return returnValue;
-	};
+  /**
+   * Process a value by given command and config
+   *
+   * @param {String} command
+   * @param {String} value
+   * @param {Array} config
+   * @returns {String}
+   */
+  FormEngineValidation.processValue = function(command, value, config) {
+    var newString = '';
+    var theValue = '';
+    var theCmd = '';
+    var a = 0;
+    var returnValue = value;
+    switch (command) {
+      case 'alpha':
+      case 'num':
+      case 'alphanum':
+      case 'alphanum_x':
+        newString = '';
+        for (a = 0; a < value.length; a++) {
+          theChar = value.substr(a, 1);
+          var special = (theChar === '_' || theChar === '-');
+          var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
+          var num = (theChar >= '0' && theChar <= '9');
+          switch (command) {
+            case 'alphanum':
+              special = 0;
+              break;
+            case 'alpha':
+              num = 0;
+              special = 0;
+              break;
+            case 'num':
+              alpha = 0;
+              special = 0;
+              break;
+          }
+          if (alpha || num || special) {
+            newString += theChar;
+          }
+        }
+        if (newString !== value) {
+          returnValue = newString;
+        }
+        break;
+      case 'is_in':
+        if (config.is_in) {
+          theValue = '' + value;
+          // Escape special characters, see https://stackoverflow.com/a/6969486/4828813
+          config.is_in = config.is_in.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+          var re = new RegExp('[^' + config.is_in + ']+', 'g');
+          newString = theValue.replace(re, '');
+        } else {
+          newString = theValue;
+        }
+        returnValue = newString;
+        break;
+      case 'nospace':
+        returnValue = ('' + value).replace(/ /g, '');
+        break;
+      case 'md5':
+        if (value !== '') {
+          returnValue = MD5(value);
+        }
+        break;
+      case 'upper':
+        returnValue = value.toUpperCase();
+        break;
+      case 'lower':
+        returnValue = value.toLowerCase();
+        break;
+      case 'int':
+        if (value !== '') {
+          returnValue = FormEngineValidation.parseInt(value);
+        }
+        break;
+      case 'double2':
+        if (value !== '') {
+          returnValue = FormEngineValidation.parseDouble(value);
+        }
+        break;
+      case 'trim':
+        returnValue = String(value).trim();
+        break;
+      case 'datetime':
+        if (value !== '') {
+          theCmd = value.substr(0, 1);
+          returnValue = FormEngineValidation.parseDateTime(value, theCmd);
+        }
+        break;
+      case 'date':
+        if (value !== '') {
+          theCmd = value.substr(0, 1);
+          returnValue = FormEngineValidation.parseDate(value, theCmd);
+        }
+        break;
+      case 'time':
+      case 'timesec':
+        if (value !== '') {
+          theCmd = value.substr(0, 1);
+          returnValue = FormEngineValidation.parseTime(value, theCmd, command);
+        }
+        break;
+      case 'year':
+        if (value !== '') {
+          theCmd = value.substr(0, 1);
+          returnValue = FormEngineValidation.parseYear(value, theCmd);
+        }
+        break;
+      case 'null':
+        // unknown type null, we ignore it
+        break;
+      case 'password':
+        // password is only a display evaluation, we ignore it
+        break;
+      default:
+        if (typeof TBE_EDITOR.customEvalFunctions !== 'undefined' && typeof TBE_EDITOR.customEvalFunctions[command] === 'function') {
+          returnValue = TBE_EDITOR.customEvalFunctions[command](value);
+        }
+    }
+    return returnValue;
+  };
 
-	/**
-	 * Validate the complete form
-	 */
-	FormEngineValidation.validate = function() {
-		$(document).find(FormEngineValidation.markerSelector + ', .t3js-tabmenu-item')
-			.removeClass(FormEngineValidation.errorClass)
-			.removeClass('has-validation-error');
+  /**
+   * Validate the complete form
+   */
+  FormEngineValidation.validate = function() {
+    $(document).find(FormEngineValidation.markerSelector + ', .t3js-tabmenu-item')
+      .removeClass(FormEngineValidation.errorClass)
+      .removeClass('has-validation-error');
 
-		$(FormEngineValidation.rulesSelector).each(function() {
-			var $field = $(this);
-			if (!$field.closest('.t3js-flex-section-deleted, .t3js-inline-record-deleted').length) {
-				var modified = false;
-				var currentValue = $field.val();
-				var newValue = FormEngineValidation.validateField($field, currentValue);
-				if ($.isArray(newValue) && $.isArray(currentValue)) {
-					// handling for multi-selects
-					if (newValue.length !== currentValue.length) {
-						modified = true;
-					} else {
-						for (var i = 0; i < newValue.length; i++) {
-							if (newValue[i] !== currentValue[i]) {
-								modified = true;
-								break;
-							}
-						}
-					}
-				} else if (newValue.length && currentValue !== newValue) {
-					modified = true;
-				}
-				if (modified) {
-					$field.val(newValue);
-				}
-			}
-		});
-		$(document).trigger('t3-formengine-postfieldvalidation');
-	};
+    $(FormEngineValidation.rulesSelector).each(function() {
+      var $field = $(this);
+      if (!$field.closest('.t3js-flex-section-deleted, .t3js-inline-record-deleted').length) {
+        var modified = false;
+        var currentValue = $field.val();
+        var newValue = FormEngineValidation.validateField($field, currentValue);
+        if ($.isArray(newValue) && $.isArray(currentValue)) {
+          // handling for multi-selects
+          if (newValue.length !== currentValue.length) {
+            modified = true;
+          } else {
+            for (var i = 0; i < newValue.length; i++) {
+              if (newValue[i] !== currentValue[i]) {
+                modified = true;
+                break;
+              }
+            }
+          }
+        } else if (newValue.length && currentValue !== newValue) {
+          modified = true;
+        }
+        if (modified) {
+          $field.val(newValue);
+        }
+      }
+    });
+    $(document).trigger('t3-formengine-postfieldvalidation');
+  };
 
-	/**
-	 * Helper function to mark a field as changed.
-	 *
-	 * @param {Object} $field
-	 */
-	FormEngineValidation.markFieldAsChanged = function($field) {
-		var $paletteField = $field.closest('.t3js-formengine-palette-field');
-		$paletteField.addClass('has-change');
-	};
+  /**
+   * Helper function to mark a field as changed.
+   *
+   * @param {Object} $field
+   */
+  FormEngineValidation.markFieldAsChanged = function($field) {
+    var $paletteField = $field.closest('.t3js-formengine-palette-field');
+    $paletteField.addClass('has-change');
+  };
 
-	/**
-	 * Helper function to get clean trimmed array from comma list
-	 *
-	 * @param {String} delimiter
-	 * @param {String} string
-	 * @returns {Array}
-	 */
-	FormEngineValidation.trimExplode = function(delimiter, string) {
-		var result = [];
-		var items = string.split(delimiter);
-		for (var i=0; i<items.length; i++) {
-			var item = items[i].trim();
-			if (item.length > 0) {
-				result.push(item);
-			}
-		}
-		return result;
-	};
+  /**
+   * Helper function to get clean trimmed array from comma list
+   *
+   * @param {String} delimiter
+   * @param {String} string
+   * @returns {Array}
+   */
+  FormEngineValidation.trimExplode = function(delimiter, string) {
+    var result = [];
+    var items = string.split(delimiter);
+    for (var i = 0; i < items.length; i++) {
+      var item = items[i].trim();
+      if (item.length > 0) {
+        result.push(item);
+      }
+    }
+    return result;
+  };
 
-	/**
-	 * Parse value to integer
-	 *
-	 * @param {(Number|String)} value
-	 * @returns {Number}
-	 */
-	FormEngineValidation.parseInt = function(value) {
-		var theVal = '' + value,
-			returnValue;
+  /**
+   * Parse value to integer
+   *
+   * @param {(Number|String)} value
+   * @returns {Number}
+   */
+  FormEngineValidation.parseInt = function(value) {
+    var theVal = '' + value,
+      returnValue;
 
-		if (!value) {
-			return 0;
-		}
+    if (!value) {
+      return 0;
+    }
 
-		returnValue = parseInt(theVal, 10);
-		if (isNaN(returnValue)) {
-			return 0;
-		}
-		return returnValue;
-	};
+    returnValue = parseInt(theVal, 10);
+    if (isNaN(returnValue)) {
+      return 0;
+    }
+    return returnValue;
+  };
 
-	/**
-	 * Parse value to double
-	 *
-	 * @param {String} value
-	 * @returns {String}
-	 */
-	FormEngineValidation.parseDouble = function(value) {
-		var theVal = '' + value;
-		theVal = theVal.replace(/[^0-9,\.-]/g, '');
-		var negative = theVal.substring(0, 1) === '-';
-		theVal = theVal.replace(/-/g, '');
-		theVal = theVal.replace(/,/g, '.');
-		if (theVal.indexOf('.') === -1) {
-			theVal += '.0';
-		}
-		var parts = theVal.split('.');
-		var dec = parts.pop();
-		theVal = Number(parts.join('') + '.' + dec);
-		if (negative) {
-			theVal *= -1;
-		}
-		theVal = theVal.toFixed(2);
+  /**
+   * Parse value to double
+   *
+   * @param {String} value
+   * @returns {String}
+   */
+  FormEngineValidation.parseDouble = function(value) {
+    var theVal = '' + value;
+    theVal = theVal.replace(/[^0-9,\.-]/g, '');
+    var negative = theVal.substring(0, 1) === '-';
+    theVal = theVal.replace(/-/g, '');
+    theVal = theVal.replace(/,/g, '.');
+    if (theVal.indexOf('.') === -1) {
+      theVal += '.0';
+    }
+    var parts = theVal.split('.');
+    var dec = parts.pop();
+    theVal = Number(parts.join('') + '.' + dec);
+    if (negative) {
+      theVal *= -1;
+    }
+    theVal = theVal.toFixed(2);
 
-		return theVal;
-	};
+    return theVal;
+  };
 
-	/**
-	 * Trims leading whitespace characters
-	 *
-	 * @param {String} value
-	 * @returns {String}
-	 */
-	FormEngineValidation.ltrim = function(value) {
-		var theVal = '' + value;
-		if (!value) {
-			return '';
-		}
-		return theVal.replace(/^\s+/, '');
-	};
+  /**
+   * Trims leading whitespace characters
+   *
+   * @param {String} value
+   * @returns {String}
+   */
+  FormEngineValidation.ltrim = function(value) {
+    var theVal = '' + value;
+    if (!value) {
+      return '';
+    }
+    return theVal.replace(/^\s+/, '');
+  };
 
-	/**
-	 * Trims trailing whitespace characters
-	 *
-	 * @param {String} value
-	 * @returns {String}
-	 */
-	FormEngineValidation.btrim = function(value) {
-		var theVal = '' + value;
-		if (!value) {
-			return '';
-		}
-		return theVal.replace(/\s+$/, '');
-	};
+  /**
+   * Trims trailing whitespace characters
+   *
+   * @param {String} value
+   * @returns {String}
+   */
+  FormEngineValidation.btrim = function(value) {
+    var theVal = '' + value;
+    if (!value) {
+      return '';
+    }
+    return theVal.replace(/\s+$/, '');
+  };
 
-	/**
-	 * Parse datetime value
-	 *
-	 * @param {String} value
-	 * @param {String} command
-	 * @returns {*}
-	 */
-	FormEngineValidation.parseDateTime = function(value, command) {
-		var today = new Date();
-		var values = FormEngineValidation.split(value);
-		var add = 0;
-		switch (command) {
-			case 'd':
-			case 't':
-			case 'n':
-				FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0);
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			case '+':
-			case '-':
-				if (FormEngineValidation.lastTime === 0) {
-					FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0);
-				}
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			default:
-				var index = value.indexOf(' ');
-				if (index !== -1) {
-					var dateVal = FormEngineValidation.parseDate(value.substr(index, value.length), value.substr(0, 1));
-					FormEngineValidation.lastTime = dateVal + FormEngineValidation.parseTime(value.substr(0, index), value.substr(0, 1), 'time');
-				} else {
-					// only date, no time
-					FormEngineValidation.lastTime = FormEngineValidation.parseDate(value, value.substr(0, 1));
-				}
-		}
-		FormEngineValidation.lastTime += add * 24 * 60 * 60;
-		return FormEngineValidation.lastTime;
-	};
+  /**
+   * Parse datetime value
+   *
+   * @param {String} value
+   * @param {String} command
+   * @returns {*}
+   */
+  FormEngineValidation.parseDateTime = function(value, command) {
+    var today = new Date();
+    var values = FormEngineValidation.split(value);
+    var add = 0;
+    switch (command) {
+      case 'd':
+      case 't':
+      case 'n':
+        FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0);
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      case '+':
+      case '-':
+        if (FormEngineValidation.lastTime === 0) {
+          FormEngineValidation.lastTime = FormEngineValidation.convertClientTimestampToUTC(FormEngineValidation.getTimestamp(today), 0);
+        }
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      default:
+        var index = value.indexOf(' ');
+        if (index !== -1) {
+          var dateVal = FormEngineValidation.parseDate(value.substr(index, value.length), value.substr(0, 1));
+          FormEngineValidation.lastTime = dateVal + FormEngineValidation.parseTime(value.substr(0, index), value.substr(0, 1), 'time');
+        } else {
+          // only date, no time
+          FormEngineValidation.lastTime = FormEngineValidation.parseDate(value, value.substr(0, 1));
+        }
+    }
+    FormEngineValidation.lastTime += add * 24 * 60 * 60;
+    return FormEngineValidation.lastTime;
+  };
 
-	/**
-	 * Parse date value
-	 *
-	 * @param {String} value
-	 * @param {String} command
-	 * @returns {*}
-	 */
-	FormEngineValidation.parseDate = function(value, command) {
-		var today = new Date();
-		var values = FormEngineValidation.split(value);
-		var add = 0;
-		switch (command) {
-			case 'd':
-			case 't':
-			case 'n':
-				FormEngineValidation.lastDate = FormEngineValidation.getTimestamp(today);
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			case '+':
-			case '-':
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			default:
-				var index = 4;
-				if (values.valPol[index]) {
-					add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index]));
-				}
-				if (values.values[1] && values.values[1].length > 2) {
-					if (values.valPol[2]) {
-						add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
-					}
-					var temp = values.values[1];
-					values = FormEngineValidation.splitSingle(temp);
-				}
+  /**
+   * Parse date value
+   *
+   * @param {String} value
+   * @param {String} command
+   * @returns {*}
+   */
+  FormEngineValidation.parseDate = function(value, command) {
+    var today = new Date();
+    var values = FormEngineValidation.split(value);
+    var add = 0;
+    switch (command) {
+      case 'd':
+      case 't':
+      case 'n':
+        FormEngineValidation.lastDate = FormEngineValidation.getTimestamp(today);
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      case '+':
+      case '-':
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      default:
+        var index = 4;
+        if (values.valPol[index]) {
+          add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index]));
+        }
+        if (values.values[1] && values.values[1].length > 2) {
+          if (values.valPol[2]) {
+            add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
+          }
+          var temp = values.values[1];
+          values = FormEngineValidation.splitSingle(temp);
+        }
 
-				var year = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : FormEngineValidation.getYear(today);
-				var usMode = FormEngineValidation.USmode ? 1 : 2;
-				var month = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCMonth() + 1;
-				usMode = FormEngineValidation.USmode ? 2 : 1;
-				var day = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCDate();
+        var year = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : FormEngineValidation.getYear(today);
+        var usMode = FormEngineValidation.USmode ? 1 : 2;
+        var month = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCMonth() + 1;
+        usMode = FormEngineValidation.USmode ? 2 : 1;
+        var day = (values.values[usMode]) ? FormEngineValidation.parseInt(values.values[usMode]) : today.getUTCDate();
 
 
-				var theTime = moment.utc();
-				theTime.year(parseInt(year)).month(parseInt(month)-1).date(parseInt(day)).hour(0).minute(0).second(0);
-				FormEngineValidation.lastDate = theTime.unix();
-		}
-		FormEngineValidation.lastDate += add * 24 * 60 * 60;
-		return FormEngineValidation.lastDate;
-	};
+        var theTime = moment.utc();
+        theTime.year(parseInt(year)).month(parseInt(month) - 1).date(parseInt(day)).hour(0).minute(0).second(0);
+        FormEngineValidation.lastDate = theTime.unix();
+    }
+    FormEngineValidation.lastDate += add * 24 * 60 * 60;
+    return FormEngineValidation.lastDate;
+  };
 
-	/**
-	 * Parse time value
-	 *
-	 * @param {String} value
-	 * @param {String} command
-	 * @param {String} type
-	 * @returns {*}
-	 */
-	FormEngineValidation.parseTime = function(value, command, type) {
-		var today = new Date();
-		var values = FormEngineValidation.split(value);
-		var add = 0;
-		switch (command) {
-			case 'd':
-			case 't':
-			case 'n':
-				FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today);
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			case '+':
-			case '-':
-				if (FormEngineValidation.lastTime == 0) {
-					FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today);
-				}
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			default:
-				var index = (type === 'timesec') ? 4 : 3;
-				if (values.valPol[index]) {
-					add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index]));
-				}
-				if (values.values[1] && values.values[1].length > 2) {
-					if (values.valPol[2]) {
-						add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
-					}
-					var temp = values.values[1];
-					values = FormEngineValidation.splitSingle(temp);
-				}
-				var sec = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : today.getUTCSeconds();
-				if (sec > 59) {
-					sec = 59;
-				}
-				var min = (values.values[2]) ? FormEngineValidation.parseInt(values.values[2]) : today.getUTCMinutes();
-				if (min > 59) {
-					min = 59;
-				}
-				var hour = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : today.getUTCHours();
-				if (hour >= 24) {
-					hour = 0;
-				}
+  /**
+   * Parse time value
+   *
+   * @param {String} value
+   * @param {String} command
+   * @param {String} type
+   * @returns {*}
+   */
+  FormEngineValidation.parseTime = function(value, command, type) {
+    var today = new Date();
+    var values = FormEngineValidation.split(value);
+    var add = 0;
+    switch (command) {
+      case 'd':
+      case 't':
+      case 'n':
+        FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today);
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      case '+':
+      case '-':
+        if (FormEngineValidation.lastTime == 0) {
+          FormEngineValidation.lastTime = FormEngineValidation.getTimeSecs(today);
+        }
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      default:
+        var index = (type === 'timesec') ? 4 : 3;
+        if (values.valPol[index]) {
+          add = FormEngineValidation.pol(values.valPol[index], FormEngineValidation.parseInt(values.values[index]));
+        }
+        if (values.values[1] && values.values[1].length > 2) {
+          if (values.valPol[2]) {
+            add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
+          }
+          var temp = values.values[1];
+          values = FormEngineValidation.splitSingle(temp);
+        }
+        var sec = (values.values[3]) ? FormEngineValidation.parseInt(values.values[3]) : today.getUTCSeconds();
+        if (sec > 59) {
+          sec = 59;
+        }
+        var min = (values.values[2]) ? FormEngineValidation.parseInt(values.values[2]) : today.getUTCMinutes();
+        if (min > 59) {
+          min = 59;
+        }
+        var hour = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : today.getUTCHours();
+        if (hour >= 24) {
+          hour = 0;
+        }
 
-				var theTime = moment.utc();
-				theTime.year(1970).month(0).date(1).hour(hour).minute(min).second(type === 'timesec' ? sec : 0);
+        var theTime = moment.utc();
+        theTime.year(1970).month(0).date(1).hour(hour).minute(min).second(type === 'timesec' ? sec : 0);
 
-				FormEngineValidation.lastTime = theTime.unix();
-		}
-		FormEngineValidation.lastTime += add * 60;
-		if (FormEngineValidation.lastTime < 0) {
-			FormEngineValidation.lastTime += 24 * 60 * 60;
-		}
-		return FormEngineValidation.lastTime;
-	};
+        FormEngineValidation.lastTime = theTime.unix();
+    }
+    FormEngineValidation.lastTime += add * 60;
+    if (FormEngineValidation.lastTime < 0) {
+      FormEngineValidation.lastTime += 24 * 60 * 60;
+    }
+    return FormEngineValidation.lastTime;
+  };
 
-	/**
-	 * Parse year value
-	 *
-	 * @param {String} value
-	 * @param {String} command
-	 * @returns {*}
-	 */
-	FormEngineValidation.parseYear = function(value, command) {
-		var today = new Date();
-		var values = FormEngineValidation.split(value);
-		var add = 0;
-		switch (command) {
-			case 'd':
-			case 't':
-			case 'n':
-				FormEngineValidation.lastYear = FormEngineValidation.getYear(today);
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			case '+':
-			case '-':
-				if (values.valPol[1]) {
-					add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
-				}
-				break;
-			default:
-				if (values.valPol[2]) {
-					add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
-				}
-				var year = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : FormEngineValidation.getYear(today);
-				FormEngineValidation.lastYear = year;
-		}
-		FormEngineValidation.lastYear += add;
-		return FormEngineValidation.lastYear;
-	};
+  /**
+   * Parse year value
+   *
+   * @param {String} value
+   * @param {String} command
+   * @returns {*}
+   */
+  FormEngineValidation.parseYear = function(value, command) {
+    var today = new Date();
+    var values = FormEngineValidation.split(value);
+    var add = 0;
+    switch (command) {
+      case 'd':
+      case 't':
+      case 'n':
+        FormEngineValidation.lastYear = FormEngineValidation.getYear(today);
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      case '+':
+      case '-':
+        if (values.valPol[1]) {
+          add = FormEngineValidation.pol(values.valPol[1], FormEngineValidation.parseInt(values.values[1]));
+        }
+        break;
+      default:
+        if (values.valPol[2]) {
+          add = FormEngineValidation.pol(values.valPol[2], FormEngineValidation.parseInt(values.values[2]));
+        }
+        var year = (values.values[1]) ? FormEngineValidation.parseInt(values.values[1]) : FormEngineValidation.getYear(today);
+        FormEngineValidation.lastYear = year;
+    }
+    FormEngineValidation.lastYear += add;
+    return FormEngineValidation.lastYear;
+  };
 
-	/**
-	 * Get year from date object
-	 *
-	 * @param {Date} timeObj
-	 * @returns {?number}
-	 */
-	FormEngineValidation.getYear = function(timeObj) {
-		if (timeObj === null) {
-			return null;
-		}
-		return timeObj.getUTCFullYear();
-	};
+  /**
+   * Get year from date object
+   *
+   * @param {Date} timeObj
+   * @returns {?number}
+   */
+  FormEngineValidation.getYear = function(timeObj) {
+    if (timeObj === null) {
+      return null;
+    }
+    return timeObj.getUTCFullYear();
+  };
 
-	/**
-	 * Get date as timestamp from Date object
-	 *
-	 * @param {Date} timeObj
-	 * @returns {Number}
-	 */
-	FormEngineValidation.getDate = function(timeObj) {
-		var theTime = new Date(FormEngineValidation.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
-		return FormEngineValidation.getTimestamp(theTime);
-	};
+  /**
+   * Get date as timestamp from Date object
+   *
+   * @param {Date} timeObj
+   * @returns {Number}
+   */
+  FormEngineValidation.getDate = function(timeObj) {
+    var theTime = new Date(FormEngineValidation.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
+    return FormEngineValidation.getTimestamp(theTime);
+  };
 
-	/**
-	 *
-	 * @param {String} foreign
-	 * @param {String} value
-	 * @returns {Object}
-	 */
-	FormEngineValidation.pol = function(foreign, value) {
-		return eval(((foreign == '-') ? '-' : '') + value);
-	};
+  /**
+   *
+   * @param {String} foreign
+   * @param {String} value
+   * @returns {Object}
+   */
+  FormEngineValidation.pol = function(foreign, value) {
+    return eval(((foreign == '-') ? '-' : '') + value);
+  };
 
-	/**
-	 * Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server
-	 *
-	 * @param {Number} timestamp
-	 * @param {Number} timeonly
-	 * @returns {*}
-	 */
-	FormEngineValidation.convertClientTimestampToUTC = function(timestamp, timeonly) {
-		var timeObj = new Date(timestamp*1000);
-		timeObj.setTime((timestamp - timeObj.getTimezoneOffset()*60)*1000);
-		if (timeonly) {
-			// only seconds since midnight
-			return FormEngineValidation.getTime(timeObj);
-		} else {
-			// seconds since the "unix-epoch"
-			return FormEngineValidation.getTimestamp(timeObj);
-		}
-	};
+  /**
+   * Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server
+   *
+   * @param {Number} timestamp
+   * @param {Number} timeonly
+   * @returns {*}
+   */
+  FormEngineValidation.convertClientTimestampToUTC = function(timestamp, timeonly) {
+    var timeObj = new Date(timestamp * 1000);
+    timeObj.setTime((timestamp - timeObj.getTimezoneOffset() * 60) * 1000);
+    if (timeonly) {
+      // only seconds since midnight
+      return FormEngineValidation.getTime(timeObj);
+    } else {
+      // seconds since the "unix-epoch"
+      return FormEngineValidation.getTimestamp(timeObj);
+    }
+  };
 
-	/**
-	 * Parse date string or object and return unix timestamp
-	 *
-	 * @param {(String|Date)} timeObj
-	 * @returns {Number}
-	 */
-	FormEngineValidation.getTimestamp = function(timeObj) {
-		return Date.parse(timeObj)/1000;
-	};
+  /**
+   * Parse date string or object and return unix timestamp
+   *
+   * @param {(String|Date)} timeObj
+   * @returns {Number}
+   */
+  FormEngineValidation.getTimestamp = function(timeObj) {
+    return Date.parse(timeObj) / 1000;
+  };
 
-	/**
-	 * Seconds since midnight
-	 *
-	 * @param timeObj
-	 * @returns {*}
-	 */
-	FormEngineValidation.getTime = function(timeObj) {
-		return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + FormEngineValidation.getSecs(timeObj);
-	};
+  /**
+   * Seconds since midnight
+   *
+   * @param timeObj
+   * @returns {*}
+   */
+  FormEngineValidation.getTime = function(timeObj) {
+    return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + FormEngineValidation.getSecs(timeObj);
+  };
 
-	/**
-	 *
-	 * @param timeObj
-	 * @returns {Number}
-	 */
-	FormEngineValidation.getSecs = function(timeObj) {
-		return timeObj.getUTCSeconds();
-	};
+  /**
+   *
+   * @param timeObj
+   * @returns {Number}
+   */
+  FormEngineValidation.getSecs = function(timeObj) {
+    return timeObj.getUTCSeconds();
+  };
 
-	/**
-	 *
-	 * @param timeObj
-	 * @returns {Number}
-	 */
-	FormEngineValidation.getTimeSecs = function(timeObj) {
-		return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds();
-	};
+  /**
+   *
+   * @param timeObj
+   * @returns {Number}
+   */
+  FormEngineValidation.getTimeSecs = function(timeObj) {
+    return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds();
+  };
 
-	/**
-	 * Find tab by field and mark it as has-validation-error
-	 *
-	 * @param {Object} $element
-	 */
-	FormEngineValidation.markParentTab = function($element) {
-		var $panes = $element.parents('.tab-pane');
-		$panes.each(function() {
-			var $pane = $(this);
-			var id = $pane.attr('id');
-			$(document)
-				.find('a[href="#' + id + '"]')
-				.closest('.t3js-tabmenu-item')
-				.addClass('has-validation-error');
-		});
-	};
+  /**
+   * Find tab by field and mark it as has-validation-error
+   *
+   * @param {Object} $element
+   */
+  FormEngineValidation.markParentTab = function($element) {
+    var $panes = $element.parents('.tab-pane');
+    $panes.each(function() {
+      var $pane = $(this);
+      var id = $pane.attr('id');
+      $(document)
+        .find('a[href="#' + id + '"]')
+        .closest('.t3js-tabmenu-item')
+        .addClass('has-validation-error');
+    });
+  };
 
-	/**
-	 *
-	 * @param value
-	 * @returns {{values: Array, pointer: number}}
-	 */
-	FormEngineValidation.splitSingle = function(value) {
-		var theVal = '' + value;
-		var result = {
-			values: [],
-			pointer: 3
-		};
-		result.values[1] = theVal.substr(0,2);
-		result.values[2] = theVal.substr(2,2);
-		result.values[3] = theVal.substr(4,10);
-		return result;
-	};
+  /**
+   *
+   * @param value
+   * @returns {{values: Array, pointer: number}}
+   */
+  FormEngineValidation.splitSingle = function(value) {
+    var theVal = '' + value;
+    var result = {
+      values: [],
+      pointer: 3
+    };
+    result.values[1] = theVal.substr(0, 2);
+    result.values[2] = theVal.substr(2, 2);
+    result.values[3] = theVal.substr(4, 10);
+    return result;
+  };
 
-	/**
-	 *
-	 * @param theStr1
-	 * @param delim
-	 * @param index
-	 * @returns {*}
-	 */
-	FormEngineValidation.splitStr = function(theStr1, delim, index) {
-		var theStr = '' + theStr1;
-		var lengthOfDelim = delim.length;
-		var sPos = -lengthOfDelim;
-		if (index < 1) {
-			index = 1;
-		}
-		for (var a = 1; a < index; a++) {
-			sPos = theStr.indexOf(delim, sPos + lengthOfDelim);
-			if (sPos == -1) {
-				return null;
-			}
-		}
-		var ePos = theStr.indexOf(delim, sPos + lengthOfDelim);
-		if (ePos == -1) {
-			ePos = theStr.length;
-		}
-		return (theStr.substring(sPos + lengthOfDelim, ePos));
-	};
+  /**
+   *
+   * @param theStr1
+   * @param delim
+   * @param index
+   * @returns {*}
+   */
+  FormEngineValidation.splitStr = function(theStr1, delim, index) {
+    var theStr = '' + theStr1;
+    var lengthOfDelim = delim.length;
+    var sPos = -lengthOfDelim;
+    if (index < 1) {
+      index = 1;
+    }
+    for (var a = 1; a < index; a++) {
+      sPos = theStr.indexOf(delim, sPos + lengthOfDelim);
+      if (sPos == -1) {
+        return null;
+      }
+    }
+    var ePos = theStr.indexOf(delim, sPos + lengthOfDelim);
+    if (ePos == -1) {
+      ePos = theStr.length;
+    }
+    return (theStr.substring(sPos + lengthOfDelim, ePos));
+  };
 
-	/**
-	 *
-	 * @param value
-	 * @returns {{values: Array, valPol: Array, pointer: number, numberMode: number, theVal: string}}
-	 */
-	FormEngineValidation.split = function(value) {
-		var result = {
-			values: [],
-			valPol: [],
-			pointer: 0,
-			numberMode: 0,
-			theVal: ''
-		};
-		value += ' ';
-		for (var a=0; a < value.length; a++) {
-			var theChar = value.substr(a, 1);
-			if (theChar < '0' || theChar > '9') {
-				if (result.numberMode) {
-					result.pointer++;
-					result.values[result.pointer] = result.theVal;
-					result.theVal = '';
-					result.numberMode = 0;
-				}
-				if (theChar == '+' || theChar == '-') {
-					result.valPol[result.pointer + 1] = theChar;
-				}
-			} else {
-				result.theVal += theChar;
-				result.numberMode = 1;
-			}
-		}
-		return result;
-	};
+  /**
+   *
+   * @param value
+   * @returns {{values: Array, valPol: Array, pointer: number, numberMode: number, theVal: string}}
+   */
+  FormEngineValidation.split = function(value) {
+    var result = {
+      values: [],
+      valPol: [],
+      pointer: 0,
+      numberMode: 0,
+      theVal: ''
+    };
+    value += ' ';
+    for (var a = 0; a < value.length; a++) {
+      var theChar = value.substr(a, 1);
+      if (theChar < '0' || theChar > '9') {
+        if (result.numberMode) {
+          result.pointer++;
+          result.values[result.pointer] = result.theVal;
+          result.theVal = '';
+          result.numberMode = 0;
+        }
+        if (theChar == '+' || theChar == '-') {
+          result.valPol[result.pointer + 1] = theChar;
+        }
+      } else {
+        result.theVal += theChar;
+        result.numberMode = 1;
+      }
+    }
+    return result;
+  };
 
-	return FormEngineValidation;
+  return FormEngineValidation;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js b/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js
index 0ba0541471e1..5df4ef5b271c 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Icons.js
@@ -16,145 +16,145 @@
  * Uses the icon API of the core to fetch icons via AJAX.
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	try {
-		// fetch from opening window
-		if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Icons) {
-			return window.opener.TYPO3.Icons;
-		}
+  try {
+    // fetch from opening window
+    if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Icons) {
+      return window.opener.TYPO3.Icons;
+    }
 
-		// fetch from parent
-		if (parent && parent.window.TYPO3 && parent.window.TYPO3.Icons) {
-			return parent.window.TYPO3.Icons;
-		}
+    // fetch from parent
+    if (parent && parent.window.TYPO3 && parent.window.TYPO3.Icons) {
+      return parent.window.TYPO3.Icons;
+    }
 
-		// fetch object from outer frame
-		if (top && top.TYPO3.Icons) {
-			return top.TYPO3.Icons;
-		}
-	} catch (e) {
-		// This only happens if the opener, parent or top is some other url (eg a local file)
-		// which loaded the current window. Then the browser's cross domain policy jumps in
-		// and raises an exception.
-		// For this case we are safe and we can create our global object below.
-	}
+    // fetch object from outer frame
+    if (top && top.TYPO3.Icons) {
+      return top.TYPO3.Icons;
+    }
+  } catch (e) {
+    // This only happens if the opener, parent or top is some other url (eg a local file)
+    // which loaded the current window. Then the browser's cross domain policy jumps in
+    // and raises an exception.
+    // For this case we are safe and we can create our global object below.
+  }
 
-	/**
-	 *
-	 * @type {{cache: {}, sizes: {small: string, default: string, large: string, overlay: string}, states: {default: string, disabled: string}}}
-	 * @exports TYPO3/CMS/Backend/Icons
-	 */
-	var Icons = {
-		cache: {},
-		sizes: {
-			small: 'small',
-			default: 'default',
-			large: 'large',
-			overlay: 'overlay'
-		},
-		states: {
-			default: 'default',
-			disabled: 'disabled'
-		},
-		markupIdentifiers: {
-			default: 'default',
-			inline: 'inline'
-		}
-	};
+  /**
+   *
+   * @type {{cache: {}, sizes: {small: string, default: string, large: string, overlay: string}, states: {default: string, disabled: string}}}
+   * @exports TYPO3/CMS/Backend/Icons
+   */
+  var Icons = {
+    cache: {},
+    sizes: {
+      small: 'small',
+      default: 'default',
+      large: 'large',
+      overlay: 'overlay'
+    },
+    states: {
+      default: 'default',
+      disabled: 'disabled'
+    },
+    markupIdentifiers: {
+      default: 'default',
+      inline: 'inline'
+    }
+  };
 
-	/**
-	 * Get the icon by its identifier.
-	 *
-	 * @param {String} identifier
-	 * @param {String} size
-	 * @param {String} overlayIdentifier
-	 * @param {String} state
-	 * @param {String} markupIdentifier
-	 * @return {Promise<Array>}
-	 */
-	Icons.getIcon = function(identifier, size, overlayIdentifier, state, markupIdentifier) {
-		return $.when(Icons.fetch(identifier, size, overlayIdentifier, state, markupIdentifier));
-	};
+  /**
+   * Get the icon by its identifier.
+   *
+   * @param {String} identifier
+   * @param {String} size
+   * @param {String} overlayIdentifier
+   * @param {String} state
+   * @param {String} markupIdentifier
+   * @return {Promise<Array>}
+   */
+  Icons.getIcon = function(identifier, size, overlayIdentifier, state, markupIdentifier) {
+    return $.when(Icons.fetch(identifier, size, overlayIdentifier, state, markupIdentifier));
+  };
 
-	/**
-	 * Performs the AJAX request to fetch the icon.
-	 *
-	 * @param {string} identifier
-	 * @param {string} size
-	 * @param {string} overlayIdentifier
-	 * @param {string} state
-	 * @param {string} markupIdentifier
-	 * @return {String|Promise}
-	 * @private
-	 */
-	Icons.fetch = function(identifier, size, overlayIdentifier, state, markupIdentifier) {
-		/**
-		 * Icon keys:
-		 *
-		 * 0: identifier
-		 * 1: size
-		 * 2: overlayIdentifier
-		 * 3: state
-		 * 4: markupIdentifier
-		 */
-		size = size || Icons.sizes.default;
-		state = state || Icons.states.default;
-		markupIdentifier = markupIdentifier || Icons.markupIdentifiers.default;
+  /**
+   * Performs the AJAX request to fetch the icon.
+   *
+   * @param {string} identifier
+   * @param {string} size
+   * @param {string} overlayIdentifier
+   * @param {string} state
+   * @param {string} markupIdentifier
+   * @return {String|Promise}
+   * @private
+   */
+  Icons.fetch = function(identifier, size, overlayIdentifier, state, markupIdentifier) {
+    /**
+     * Icon keys:
+     *
+     * 0: identifier
+     * 1: size
+     * 2: overlayIdentifier
+     * 3: state
+     * 4: markupIdentifier
+     */
+    size = size || Icons.sizes.default;
+    state = state || Icons.states.default;
+    markupIdentifier = markupIdentifier || Icons.markupIdentifiers.default;
 
-		var icon = [identifier, size, overlayIdentifier, state, markupIdentifier],
-			cacheIdentifier = icon.join('_');
+    var icon = [identifier, size, overlayIdentifier, state, markupIdentifier],
+      cacheIdentifier = icon.join('_');
 
-		if (!Icons.isCached(cacheIdentifier)) {
-			Icons.putInCache(cacheIdentifier, $.ajax({
-				url: TYPO3.settings.ajaxUrls['icons'],
-				dataType: 'html',
-				data: {
-					icon: JSON.stringify(icon)
-				},
-				success: function(markup) {
-					return markup;
-				}
-			}).promise());
-		}
-		return Icons.getFromCache(cacheIdentifier).done();
-	};
+    if (!Icons.isCached(cacheIdentifier)) {
+      Icons.putInCache(cacheIdentifier, $.ajax({
+        url: TYPO3.settings.ajaxUrls['icons'],
+        dataType: 'html',
+        data: {
+          icon: JSON.stringify(icon)
+        },
+        success: function(markup) {
+          return markup;
+        }
+      }).promise());
+    }
+    return Icons.getFromCache(cacheIdentifier).done();
+  };
 
-	/**
-	 * Check whether icon was fetched already
-	 *
-	 * @param {String} cacheIdentifier
-	 * @returns {Boolean}
-	 * @private
-	 */
-	Icons.isCached = function(cacheIdentifier) {
-		return typeof Icons.cache[cacheIdentifier] !== 'undefined';
-	};
+  /**
+   * Check whether icon was fetched already
+   *
+   * @param {String} cacheIdentifier
+   * @returns {Boolean}
+   * @private
+   */
+  Icons.isCached = function(cacheIdentifier) {
+    return typeof Icons.cache[cacheIdentifier] !== 'undefined';
+  };
 
-	/**
-	 * Get icon from cache
-	 *
-	 * @param {String} cacheIdentifier
-	 * @returns {String}
-	 * @private
-	 */
-	Icons.getFromCache = function(cacheIdentifier) {
-		return Icons.cache[cacheIdentifier];
-	};
+  /**
+   * Get icon from cache
+   *
+   * @param {String} cacheIdentifier
+   * @returns {String}
+   * @private
+   */
+  Icons.getFromCache = function(cacheIdentifier) {
+    return Icons.cache[cacheIdentifier];
+  };
 
-	/**
-	 * Put icon into cache
-	 *
-	 * @param {String} cacheIdentifier
-	 * @param {Object} markup
-	 * @private
-	 */
-	Icons.putInCache = function(cacheIdentifier, markup) {
-		Icons.cache[cacheIdentifier] = markup;
-	};
+  /**
+   * Put icon into cache
+   *
+   * @param {String} cacheIdentifier
+   * @param {Object} markup
+   * @private
+   */
+  Icons.putInCache = function(cacheIdentifier, markup) {
+    Icons.cache[cacheIdentifier] = markup;
+  };
 
-	// attach to global frame
-	TYPO3.Icons = Icons;
+  // attach to global frame
+  TYPO3.Icons = Icons;
 
-	return Icons;
+  return Icons;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js
index 90036f2bb9ed..2094cb36f994 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/DragDrop.js
@@ -16,251 +16,251 @@
  * this JS code does the drag+drop logic for the Layout module (Web => Page)
  * based on jQuery UI
  */
-define(['jquery', 'jquery-ui/droppable'], function ($) {
-	'use strict';
+define(['jquery', 'jquery-ui/droppable'], function($) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{contentIdentifier: string, dragIdentifier: string, dragHeaderIdentifier: string, dropZoneIdentifier: string, columnIdentifier: string, validDropZoneClass: string, dropPossibleHoverClass: string, addContentIdentifier: string, originalStyles: string}}
-	 * @exports TYPO3/CMS/Backend/LayoutModule/DragDrop
-	 */
-	var DragDrop = {
-		contentIdentifier: '.t3js-page-ce',
-		dragIdentifier: '.t3-page-ce-dragitem',
-		dragHeaderIdentifier: '.t3js-page-ce-draghandle',
-		dropZoneIdentifier: '.t3js-page-ce-dropzone-available',
-		columnIdentifier: '.t3js-page-column',
-		validDropZoneClass: 'active',
-		dropPossibleHoverClass: 't3-page-ce-dropzone-possible',
-		addContentIdentifier: '.t3js-page-new-ce',
-		clone: true,
-		originalStyles: ''
-	};
+  /**
+   *
+   * @type {{contentIdentifier: string, dragIdentifier: string, dragHeaderIdentifier: string, dropZoneIdentifier: string, columnIdentifier: string, validDropZoneClass: string, dropPossibleHoverClass: string, addContentIdentifier: string, originalStyles: string}}
+   * @exports TYPO3/CMS/Backend/LayoutModule/DragDrop
+   */
+  var DragDrop = {
+    contentIdentifier: '.t3js-page-ce',
+    dragIdentifier: '.t3-page-ce-dragitem',
+    dragHeaderIdentifier: '.t3js-page-ce-draghandle',
+    dropZoneIdentifier: '.t3js-page-ce-dropzone-available',
+    columnIdentifier: '.t3js-page-column',
+    validDropZoneClass: 'active',
+    dropPossibleHoverClass: 't3-page-ce-dropzone-possible',
+    addContentIdentifier: '.t3js-page-new-ce',
+    clone: true,
+    originalStyles: ''
+  };
 
-	/**
-	 * initializes Drag+Drop for all content elements on the page
-	 */
-	DragDrop.initialize = function () {
-		$(DragDrop.contentIdentifier).draggable({
-			handle: DragDrop.dragHeaderIdentifier,
-			scope: 'tt_content',
-			cursor: 'move',
-			distance: 20,
-			addClasses: 'active-drag',
-			revert: 'invalid',
-			zIndex: 100,
-			start: function (evt, ui) {
-				DragDrop.onDragStart($(this));
-			},
-			stop: function (evt, ui) {
-				DragDrop.onDragStop($(this));
-			}
-		});
+  /**
+   * initializes Drag+Drop for all content elements on the page
+   */
+  DragDrop.initialize = function() {
+    $(DragDrop.contentIdentifier).draggable({
+      handle: DragDrop.dragHeaderIdentifier,
+      scope: 'tt_content',
+      cursor: 'move',
+      distance: 20,
+      addClasses: 'active-drag',
+      revert: 'invalid',
+      zIndex: 100,
+      start: function(evt, ui) {
+        DragDrop.onDragStart($(this));
+      },
+      stop: function(evt, ui) {
+        DragDrop.onDragStop($(this));
+      }
+    });
 
-		$(DragDrop.dropZoneIdentifier).droppable({
-			accept: this.contentIdentifier,
-			scope: 'tt_content',
-			tolerance: 'pointer',
-			over: function (evt, ui) {
-				DragDrop.onDropHoverOver($(ui.draggable), $(this));
-			},
-			out: function (evt, ui) {
-				DragDrop.onDropHoverOut($(ui.draggable), $(this));
-			},
-			drop: function (evt, ui) {
-				DragDrop.onDrop($(ui.draggable), $(this), evt);
-			}
-		});
-	};
+    $(DragDrop.dropZoneIdentifier).droppable({
+      accept: this.contentIdentifier,
+      scope: 'tt_content',
+      tolerance: 'pointer',
+      over: function(evt, ui) {
+        DragDrop.onDropHoverOver($(ui.draggable), $(this));
+      },
+      out: function(evt, ui) {
+        DragDrop.onDropHoverOut($(ui.draggable), $(this));
+      },
+      drop: function(evt, ui) {
+        DragDrop.onDrop($(ui.draggable), $(this), evt);
+      }
+    });
+  };
 
-	/**
-	 * called when a draggable is selected to be moved
-	 * @param $element a jQuery object for the draggable
-	 * @private
-	 */
-	DragDrop.onDragStart = function ($element) {
-		// Add css class for the drag shadow
-		DragDrop.originalStyles = $element.get(0).style.cssText;
-		$element.children(DragDrop.dragIdentifier).addClass('dragitem-shadow');
-		$element.append('<div class="ui-draggable-copy-message">' + TYPO3.lang['dragdrop.copy.message'] + '</div>');
-		// Hide create new element button
-		$element.children(DragDrop.dropZoneIdentifier).addClass('drag-start');
-		$element.closest(DragDrop.columnIdentifier).removeClass('active');
+  /**
+   * called when a draggable is selected to be moved
+   * @param $element a jQuery object for the draggable
+   * @private
+   */
+  DragDrop.onDragStart = function($element) {
+    // Add css class for the drag shadow
+    DragDrop.originalStyles = $element.get(0).style.cssText;
+    $element.children(DragDrop.dragIdentifier).addClass('dragitem-shadow');
+    $element.append('<div class="ui-draggable-copy-message">' + TYPO3.lang['dragdrop.copy.message'] + '</div>');
+    // Hide create new element button
+    $element.children(DragDrop.dropZoneIdentifier).addClass('drag-start');
+    $element.closest(DragDrop.columnIdentifier).removeClass('active');
 
-		$element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).hide();
-		$element.find(DragDrop.dropZoneIdentifier).hide();
+    $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).hide();
+    $element.find(DragDrop.dropZoneIdentifier).hide();
 
-		$(DragDrop.dropZoneIdentifier).each(function () {
-			var $me = $(this);
-			if ($me.parent().find('.icon-actions-add').length) {
-				$me.addClass(DragDrop.validDropZoneClass);
-			} else {
-				$me.closest(DragDrop.contentIdentifier).find('> ' + DragDrop.addContentIdentifier + ', > > ' + DragDrop.addContentIdentifier).show();
-			}
-		});
-	};
+    $(DragDrop.dropZoneIdentifier).each(function() {
+      var $me = $(this);
+      if ($me.parent().find('.icon-actions-add').length) {
+        $me.addClass(DragDrop.validDropZoneClass);
+      } else {
+        $me.closest(DragDrop.contentIdentifier).find('> ' + DragDrop.addContentIdentifier + ', > > ' + DragDrop.addContentIdentifier).show();
+      }
+    });
+  };
 
-	/**
-	 * called when a draggable is released
-	 * @param $element a jQuery object for the draggable
-	 * @private
-	 */
-	DragDrop.onDragStop = function ($element) {
-		// Remove css class for the drag shadow
-		$element.children(DragDrop.dragIdentifier).removeClass('dragitem-shadow');
-		// Show create new element button
-		$element.children(DragDrop.dropZoneIdentifier).removeClass('drag-start');
-		$element.closest(DragDrop.columnIdentifier).addClass('active');
-		$element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).show();
-		$element.find(DragDrop.dropZoneIdentifier).show();
-		$element.find('.ui-draggable-copy-message').remove();
+  /**
+   * called when a draggable is released
+   * @param $element a jQuery object for the draggable
+   * @private
+   */
+  DragDrop.onDragStop = function($element) {
+    // Remove css class for the drag shadow
+    $element.children(DragDrop.dragIdentifier).removeClass('dragitem-shadow');
+    // Show create new element button
+    $element.children(DragDrop.dropZoneIdentifier).removeClass('drag-start');
+    $element.closest(DragDrop.columnIdentifier).addClass('active');
+    $element.parents(DragDrop.columnHolderIdentifier).find(DragDrop.addContentIdentifier).show();
+    $element.find(DragDrop.dropZoneIdentifier).show();
+    $element.find('.ui-draggable-copy-message').remove();
 
-		// Reset inline style
-		$element.get(0).style.cssText = DragDrop.originalStyles;
+    // Reset inline style
+    $element.get(0).style.cssText = DragDrop.originalStyles;
 
-		$(DragDrop.dropZoneIdentifier + '.' + DragDrop.validDropZoneClass).removeClass(DragDrop.validDropZoneClass);
-	};
+    $(DragDrop.dropZoneIdentifier + '.' + DragDrop.validDropZoneClass).removeClass(DragDrop.validDropZoneClass);
+  };
 
-	/**
-	 * adds CSS classes when hovering over a dropzone
-	 * @param $draggableElement
-	 * @param $droppableElement
-	 * @private
-	 */
-	DragDrop.onDropHoverOver = function ($draggableElement, $droppableElement) {
-		if ($droppableElement.hasClass(DragDrop.validDropZoneClass)) {
-			$droppableElement.addClass(DragDrop.dropPossibleHoverClass);
-		}
-	};
+  /**
+   * adds CSS classes when hovering over a dropzone
+   * @param $draggableElement
+   * @param $droppableElement
+   * @private
+   */
+  DragDrop.onDropHoverOver = function($draggableElement, $droppableElement) {
+    if ($droppableElement.hasClass(DragDrop.validDropZoneClass)) {
+      $droppableElement.addClass(DragDrop.dropPossibleHoverClass);
+    }
+  };
 
-	/**
-	 * removes the CSS classes after hovering out of a dropzone again
-	 * @param $draggableElement
-	 * @param $droppableElement
-	 * @private
-	 */
-	DragDrop.onDropHoverOut = function ($draggableElement, $droppableElement) {
-		$droppableElement.removeClass(DragDrop.dropPossibleHoverClass);
-	};
+  /**
+   * removes the CSS classes after hovering out of a dropzone again
+   * @param $draggableElement
+   * @param $droppableElement
+   * @private
+   */
+  DragDrop.onDropHoverOut = function($draggableElement, $droppableElement) {
+    $droppableElement.removeClass(DragDrop.dropPossibleHoverClass);
+  };
 
-	/**
-	 * this method does the whole logic when a draggable is dropped on to a dropzone
-	 * sending out the request and afterwards move the HTML element in the right place.
-	 *
-	 * @param $draggableElement
-	 * @param $droppableElement
-	 * @param {Event} evt the event
-	 * @private
-	 */
-	DragDrop.onDrop = function ($draggableElement, $droppableElement, evt) {
-		var newColumn = DragDrop.getColumnPositionForElement($droppableElement);
+  /**
+   * this method does the whole logic when a draggable is dropped on to a dropzone
+   * sending out the request and afterwards move the HTML element in the right place.
+   *
+   * @param $draggableElement
+   * @param $droppableElement
+   * @param {Event} evt the event
+   * @private
+   */
+  DragDrop.onDrop = function($draggableElement, $droppableElement, evt) {
+    var newColumn = DragDrop.getColumnPositionForElement($droppableElement);
 
-		$droppableElement.removeClass(DragDrop.dropPossibleHoverClass);
-		var $pasteAction = typeof $draggableElement === 'number';
+    $droppableElement.removeClass(DragDrop.dropPossibleHoverClass);
+    var $pasteAction = typeof $draggableElement === 'number';
 
-		// send an AJAX requst via the AjaxDataHandler
-		var contentElementUid = $pasteAction ? $draggableElement : parseInt($draggableElement.data('uid'));
-		if (contentElementUid > 0) {
-			var parameters = {};
-			// add the information about a possible column position change
-			var targetFound = $droppableElement.closest(DragDrop.contentIdentifier).data('uid');
-			// the item was moved to the top of the colPos, so the page ID is used here
-			var targetPid = 0;
-			if (typeof targetFound === 'undefined') {
-				// the actual page is needed
-				targetPid = $('[data-page]').first().data('page');
-			} else {
-				// the negative value of the content element after where it should be moved
-				targetPid = 0 - parseInt(targetFound);
-			}
-			var language = parseInt($droppableElement.closest('[data-language-uid]').data('language-uid'));
-			var colPos = 0;
-			if (targetPid !== 0) {
-				colPos = newColumn;
-			}
-			parameters['cmd'] = {tt_content: {}};
-			parameters['data'] = {tt_content: {}};
-			var copyAction = (evt && evt.originalEvent.ctrlKey || $droppableElement.hasClass('t3js-paste-copy'));
-			if (copyAction) {
-				parameters['cmd']['tt_content'][contentElementUid] = {
-					copy: {
-						action: 'paste',
-						target: targetPid,
-						update: {
-							colPos: colPos,
-							sys_language_uid: language
-						}
-					}
-				};
-				DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction);
-			} else {
-				parameters['data']['tt_content'][contentElementUid] = {
-					colPos: colPos,
-					sys_language_uid: language
-				};
-				if ($pasteAction) {
-					parameters = {
-						CB: {
-							paste: 'tt_content|' + targetPid,
-							update: {
-								colPos: colPos,
-								sys_language_uid: language
-							}
-						}
-					};
-				} else {
-					parameters['cmd']['tt_content'][contentElementUid] = {move: targetPid};
-				}
-				// fire the request, and show a message if it has failed
-				DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction);
-			}
-		}
-	};
+    // send an AJAX requst via the AjaxDataHandler
+    var contentElementUid = $pasteAction ? $draggableElement : parseInt($draggableElement.data('uid'));
+    if (contentElementUid > 0) {
+      var parameters = {};
+      // add the information about a possible column position change
+      var targetFound = $droppableElement.closest(DragDrop.contentIdentifier).data('uid');
+      // the item was moved to the top of the colPos, so the page ID is used here
+      var targetPid = 0;
+      if (typeof targetFound === 'undefined') {
+        // the actual page is needed
+        targetPid = $('[data-page]').first().data('page');
+      } else {
+        // the negative value of the content element after where it should be moved
+        targetPid = 0 - parseInt(targetFound);
+      }
+      var language = parseInt($droppableElement.closest('[data-language-uid]').data('language-uid'));
+      var colPos = 0;
+      if (targetPid !== 0) {
+        colPos = newColumn;
+      }
+      parameters['cmd'] = {tt_content: {}};
+      parameters['data'] = {tt_content: {}};
+      var copyAction = (evt && evt.originalEvent.ctrlKey || $droppableElement.hasClass('t3js-paste-copy'));
+      if (copyAction) {
+        parameters['cmd']['tt_content'][contentElementUid] = {
+          copy: {
+            action: 'paste',
+            target: targetPid,
+            update: {
+              colPos: colPos,
+              sys_language_uid: language
+            }
+          }
+        };
+        DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction);
+      } else {
+        parameters['data']['tt_content'][contentElementUid] = {
+          colPos: colPos,
+          sys_language_uid: language
+        };
+        if ($pasteAction) {
+          parameters = {
+            CB: {
+              paste: 'tt_content|' + targetPid,
+              update: {
+                colPos: colPos,
+                sys_language_uid: language
+              }
+            }
+          };
+        } else {
+          parameters['cmd']['tt_content'][contentElementUid] = {move: targetPid};
+        }
+        // fire the request, and show a message if it has failed
+        DragDrop.ajaxAction($droppableElement, $draggableElement, parameters, copyAction, $pasteAction);
+      }
+    }
+  };
 
-	/**
-	 * this method does the actual AJAX request for both, the move and the copy action.
-	 *
-	 * @param $droppableElement
-	 * @param $draggableElement
-	 * @param parameters
-	 * @param $copyAction
-	 * @param $pasteAction
-	 * @private
-	 */
-	DragDrop.ajaxAction = function ($droppableElement, $draggableElement, parameters, $copyAction, $pasteAction) {
-		require(['TYPO3/CMS/Backend/AjaxDataHandler'], function (DataHandler) {
-			DataHandler.process(parameters).done(function (result) {
-				if (!result.hasErrors) {
-					// insert draggable on the new position
-					if (!$pasteAction) {
-						if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) {
-							$draggableElement.detach().css({top: 0, left: 0})
-									.insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier));
-						} else {
-							$draggableElement.detach().css({top: 0, left: 0})
-									.insertAfter($droppableElement.closest(DragDrop.contentIdentifier));
-						}
-					}
-					self.location.reload(true);
-				}
-			});
-		});
-	};
+  /**
+   * this method does the actual AJAX request for both, the move and the copy action.
+   *
+   * @param $droppableElement
+   * @param $draggableElement
+   * @param parameters
+   * @param $copyAction
+   * @param $pasteAction
+   * @private
+   */
+  DragDrop.ajaxAction = function($droppableElement, $draggableElement, parameters, $copyAction, $pasteAction) {
+    require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) {
+      DataHandler.process(parameters).done(function(result) {
+        if (!result.hasErrors) {
+          // insert draggable on the new position
+          if (!$pasteAction) {
+            if (!$droppableElement.parent().hasClass(DragDrop.contentIdentifier.substring(1))) {
+              $draggableElement.detach().css({top: 0, left: 0})
+                .insertAfter($droppableElement.closest(DragDrop.dropZoneIdentifier));
+            } else {
+              $draggableElement.detach().css({top: 0, left: 0})
+                .insertAfter($droppableElement.closest(DragDrop.contentIdentifier));
+            }
+          }
+          self.location.reload(true);
+        }
+      });
+    });
+  };
 
-	/**
-	 * returns the next "upper" container colPos parameter inside the code
-	 * @param $element
-	 * @return int|null the colPos
-	 */
-	DragDrop.getColumnPositionForElement = function ($element) {
-		var $columnContainer = $element.closest('[data-colpos]');
-		if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') {
-			return $columnContainer.data('colpos');
-		} else {
-			return false;
-		}
-	};
+  /**
+   * returns the next "upper" container colPos parameter inside the code
+   * @param $element
+   * @return int|null the colPos
+   */
+  DragDrop.getColumnPositionForElement = function($element) {
+    var $columnContainer = $element.closest('[data-colpos]');
+    if ($columnContainer.length && $columnContainer.data('colpos') !== 'undefined') {
+      return $columnContainer.data('colpos');
+    } else {
+      return false;
+    }
+  };
 
-	$(DragDrop.initialize);
-	return DragDrop;
+  $(DragDrop.initialize);
+  return DragDrop;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js
index d433572939ff..7cbccd3eff05 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/LayoutModule/Paste.js
@@ -17,112 +17,112 @@
  * based on jQuery UI
  */
 define(['jquery',
-        'TYPO3/CMS/Backend/LayoutModule/DragDrop',
-        'TYPO3/CMS/Backend/Modal',
-        'TYPO3/CMS/Backend/Severity'
-       ], function ($, DragDrop, Modal, Severity) {
-	'use strict';
+  'TYPO3/CMS/Backend/LayoutModule/DragDrop',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity'
+], function($, DragDrop, Modal, Severity) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Backend/LayoutModule/Paste
-	 */
-	var Paste = {
-		openedPopupWindow: []
-	};
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Backend/LayoutModule/Paste
+   */
+  var Paste = {
+    openedPopupWindow: []
+  };
 
-	/**
-	 * initializes paste icons for all content elements on the page
-	 */
-	Paste.initialize = function () {
-		if ($('.t3js-page-columns').length) {
-			Paste.activatePasteIcons();
-		}
-	};
+  /**
+   * initializes paste icons for all content elements on the page
+   */
+  Paste.initialize = function() {
+    if ($('.t3js-page-columns').length) {
+      Paste.activatePasteIcons();
+    }
+  };
 
-	/**
-	 * activates the paste into / paste after icons outside of the context menus
-	 */
-	Paste.activatePasteIcons = function () {
-		$('.t3-page-ce-wrapper-new-ce').each(function () {
-			if (!$(this).find('.icon-actions-add').length) {
-				return true;
-			}
-			$('.t3js-page-lang-column .t3-page-ce > .t3-page-ce').removeClass('t3js-page-ce');
-			if (top.pasteAfterLinkTemplate && top.pasteIntoLinkTemplate) {
-				var parent = $(this).parent();
-				if (parent.data('page')) {
-					$(this).append(top.pasteIntoLinkTemplate);
-				} else {
-					$(this).append(top.pasteAfterLinkTemplate);
-				}
-				$(this).find('.t3js-paste').on('click', function (evt) {
-					evt.preventDefault();
-					Paste.activatePasteModal($(this));
-				});
-			}
-		});
-	}
+  /**
+   * activates the paste into / paste after icons outside of the context menus
+   */
+  Paste.activatePasteIcons = function() {
+    $('.t3-page-ce-wrapper-new-ce').each(function() {
+      if (!$(this).find('.icon-actions-add').length) {
+        return true;
+      }
+      $('.t3js-page-lang-column .t3-page-ce > .t3-page-ce').removeClass('t3js-page-ce');
+      if (top.pasteAfterLinkTemplate && top.pasteIntoLinkTemplate) {
+        var parent = $(this).parent();
+        if (parent.data('page')) {
+          $(this).append(top.pasteIntoLinkTemplate);
+        } else {
+          $(this).append(top.pasteAfterLinkTemplate);
+        }
+        $(this).find('.t3js-paste').on('click', function(evt) {
+          evt.preventDefault();
+          Paste.activatePasteModal($(this));
+        });
+      }
+    });
+  }
 
-	/**
-	 * generates the paste into / paste after modal
-	 */
-	Paste.activatePasteModal = function (element) {
-		var $element = $(element);
-		var url = $element.data('url') || null;
-		var title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + $element.data('title') + '"';
-		var severity = (typeof top.TYPO3.Severity[$element.data('severity')] !== 'undefined') ? top.TYPO3.Severity[$element.data('severity')] : top.TYPO3.Severity.info;
-		if ($element.hasClass('t3js-paste-copy')) {
-			var content = TYPO3.lang['paste.modal.pastecopy'] || 'Do you want to copy the record to this position?';
-			var buttons = [
-				{
-					text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					trigger: function () {
-						Modal.currentModal.trigger('modal-dismiss');
-					}
-				},
-				{
-					text: TYPO3.lang['paste.modal.button.pastecopy'] || 'Copy',
-					btnClass: 'btn-' + Severity.getCssClass(severity),
-					trigger: function () {
-						Modal.currentModal.trigger('modal-dismiss');
-						DragDrop.onDrop($element.data('content'), $element, null);
-					}
-				}
-			];
-		} else {
-			var content = TYPO3.lang['paste.modal.paste'] || 'Do you want to move the record to this position?';
-			var buttons = [
-				{
-					text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					trigger: function () {
-						Modal.currentModal.trigger('modal-dismiss');
-					}
-				},
-				{
-					text: TYPO3.lang['paste.modal.button.paste'] || 'Move',
-					btnClass: 'btn-' + Severity.getCssClass(severity),
-					trigger: function () {
-						Modal.currentModal.trigger('modal-dismiss');
-						DragDrop.onDrop($element.data('content'), $element, null);
-					}
-				}
-			];
-		}
-		if (url !== null) {
-			var separator = (url.indexOf('?') > -1) ? '&' : '?';
-			var params = $.param({data: $element.data()});
-			Modal.loadUrl(title, severity, buttons, url + separator + params);
-		} else {
-			Modal.show(title, content, severity, buttons);
-		}
-	}
+  /**
+   * generates the paste into / paste after modal
+   */
+  Paste.activatePasteModal = function(element) {
+    var $element = $(element);
+    var url = $element.data('url') || null;
+    var title = (TYPO3.lang['paste.modal.title.paste'] || 'Paste record') + ': "' + $element.data('title') + '"';
+    var severity = (typeof top.TYPO3.Severity[$element.data('severity')] !== 'undefined') ? top.TYPO3.Severity[$element.data('severity')] : top.TYPO3.Severity.info;
+    if ($element.hasClass('t3js-paste-copy')) {
+      var content = TYPO3.lang['paste.modal.pastecopy'] || 'Do you want to copy the record to this position?';
+      var buttons = [
+        {
+          text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+          }
+        },
+        {
+          text: TYPO3.lang['paste.modal.button.pastecopy'] || 'Copy',
+          btnClass: 'btn-' + Severity.getCssClass(severity),
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+            DragDrop.onDrop($element.data('content'), $element, null);
+          }
+        }
+      ];
+    } else {
+      var content = TYPO3.lang['paste.modal.paste'] || 'Do you want to move the record to this position?';
+      var buttons = [
+        {
+          text: TYPO3.lang['paste.modal.button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+          }
+        },
+        {
+          text: TYPO3.lang['paste.modal.button.paste'] || 'Move',
+          btnClass: 'btn-' + Severity.getCssClass(severity),
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+            DragDrop.onDrop($element.data('content'), $element, null);
+          }
+        }
+      ];
+    }
+    if (url !== null) {
+      var separator = (url.indexOf('?') > -1) ? '&' : '?';
+      var params = $.param({data: $element.data()});
+      Modal.loadUrl(title, severity, buttons, url + separator + params);
+    } else {
+      Modal.show(title, content, severity, buttons);
+    }
+  }
 
-	$(Paste.initialize);
-	return Paste;
+  $(Paste.initialize);
+  return Paste;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js
index 2f1db7452ba5..693ef5cbc4fe 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/LegacyTree.js
@@ -24,186 +24,186 @@ var Tree, DragDrop;
  */
 define(['jquery'], function($) {
 
-	DragDrop = {
-		dragID: null,
-		table: null	// can be "pages" or "folders", needed for doing the changes when dropping
-	};
-
-	DragDrop.dragElement = function(event, $element) {
-		event.preventDefault();
-		var $container = $element.parent().parent();
-		var elementID = $container.prop('id');
-		elementID = elementID.substring(elementID.indexOf('_') + 1);
-		DragDrop.dragID = DragDrop.getIdFromEvent(event);
-
-		if (!DragDrop.dragID) {
-			return false;
-		}
-
-		if (!elementID) {
-			elementID = DragDrop.dragID;
-		}
-
-		if ($('#dragIcon').length === 0) {
-			$('body').append('<div id="dragIcon" style="display: none;">&nbsp;</div>');
-		}
-
-		$('#dragIcon').html($container.find('.dragIcon').html() + $container.find('.dragTitle').children(':first').text());
-
-		document.onmouseup = function(event) {
-			DragDrop.cancelDragEvent(event);
-		};
-
-		document.onmousemove = function(event) {
-			DragDrop.mouseMoveEvent(event);
-		};
-	};
-
-	DragDrop.dropElement = function(event) {
-		var dropID = DragDrop.getIdFromEvent(event);
-		if ((DragDrop.dragID) && (DragDrop.dragID !== dropID)) {
-			var dragID = DragDrop.dragID;
-			var table = DragDrop.table;
-			var parameters = 'table=' + table + '-drag' +
-				'&uid=' + dragID +
-				'&dragDrop=' + table +
-				'&srcId=' + dragID +
-				'&dstId=' + dropID;
-			require(['TYPO3/CMS/Backend/ContextMenu'], function (ContextMenu) {
-				ContextMenu.record = {table: decodeURIComponent(table), uid: decodeURIComponent(dragID)};
-				ContextMenu.fetch(parameters);
-			});
-		}
-		DragDrop.cancelDragEvent();
-		return false;
-	};
-
-	DragDrop.cancelDragEvent = function(event) {
-		DragDrop.dragID = null;
-		if ($('#dragIcon').length && $('#dragIcon').is(':visible')) {
-			$('#dragIcon').hide();
-		}
-
-		document.onmouseup = null;
-		document.onmousemove = null;
-	};
-
-	DragDrop.mouseMoveEvent = function(event) {
-		if (!event) {
-			event = window.event;
-		}
-		$('#dragIcon').css({
-			left: (event.x + 5) + 'px',
-			top: (event.y - 5) + 'px'
-		}).show();
-	};
-
-	DragDrop.getIdFromEvent = function(event) {
-		var obj = event.currentTarget;
-		while (obj.id == false && obj.parentNode) {
-			obj = obj.parentNode;
-		}
-		return obj.id.substring(obj.id.indexOf('_') + 1);
-	};
-
-	Tree = {
-		ajaxRoute: 'sc_alt_file_navframe_expandtoggle',
-		frameSetModule: null,
-		activateDragDrop: true,
-		highlightClass: 'active',
-		pageID: 0,
-
-		// reloads a part of the page tree (useful when "expand" / "collapse")
-		load: function(params, isExpand, obj, scopeData, scopeHash) {
-			var $obj = $(obj);
-			var $parentNode = $(obj).parent().parent();
-
-			// immediately collapse the subtree and change the plus to a minus when collapsing
-			// without waiting for the response
-			if (!isExpand) {
-				$parentNode.find('ul:first').remove();
-				var $pm = $obj.parent().find('.pm:first');
-				if ($pm.length) {
-					$pm.get().onclick = null;
-					var src = $pm.children(':first').prop('src');
-					src = src.replace(/minus/, 'plus');
-					$pm.children('first').prop('src', src);
-				}
-			} else {
-				$obj.css({cursor: 'wait'});
-			}
-			$.ajax({
-				url: TYPO3.settings.ajaxUrls[this.ajaxRoute],
-				data: {
-					PM: params,
-					scopeData: scopeData,
-					scopeHash: scopeHash
-				}
-			}).done(function(data) {
-				// the parent node needs to be overwritten, not the object
-				$parentNode.replaceWith(data);
-				Tree.reSelectActiveItem();
-			});
-		},
-
-		// does the complete page refresh (previously known as "_refresh_nav()")
-		refresh: function() {
-			var r = new Date();
-			// randNum is useful so pagetree does not get cached in browser cache when refreshing
-			var loc = window.location.href.replace(/&randNum=\d+|#.*/g, '');
-			var addSign = loc.indexOf('?') > 0 ? '&' : '?';
-			window.location = loc + addSign + 'randNum=' + r.getTime();
-		},
-
-		// attaches the events to the elements needed for the drag and drop (for the titles and the icons)
-		registerDragDropHandlers: function() {
-			if (!Tree.activateDragDrop) {
-				return;
-			}
-
-			$('.list-tree-root').on('mousedown', '.dragTitle, .dragIcon', function(evt) {
-				DragDrop.dragElement(evt, $(this));
-			}).on('mouseup', '.dragTitle, .dragIcon', function(evt) {
-				DragDrop.dropElement(evt, $(this));
-			});
-		},
-
-		// selects the activated item again, in case it collapsed and got expanded again
-		reSelectActiveItem: function() {
-			if (!top.fsMod) {
-				return;
-			}
-			var $activeItem = $('#' + top.fsMod.navFrameHighlightedID[this.frameSetModule]);
-			if ($activeItem.length) {
-				$activeItem.addClass(Tree.highlightClass);
-				Tree.extractPageIdFromTreeItem($activeItem.prop('id'));
-			}
-		},
-
-		// highlights an active list item in the page tree and registers it to the top-frame
-		// used when loading the page for the first time
-		highlightActiveItem: function(frameSetModule, highlightID) {
-			Tree.frameSetModule = frameSetModule;
-			Tree.extractPageIdFromTreeItem(highlightID);
-
-			// Remove all items that are already highlighted
-			var $obj = $('#' + top.fsMod.navFrameHighlightedID[frameSetModule]);
-			if ($obj.length) {
-				$obj.removeClass(Tree.highlightClass);
-			}
-
-			// Set the new item
-			top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
-			$('#' + highlightID).addClass(Tree.highlightClass);
-		},
-
-		//extract pageID from the given id (pagesxxx_y_z where xxx is the ID)
-		extractPageIdFromTreeItem: function(highlightID) {
-			if (highlightID) {
-				Tree.pageID = highlightID.split('_')[0].substring(5);
-			}
-		}
-	};
-
-	return Tree;
+  DragDrop = {
+    dragID: null,
+    table: null	// can be "pages" or "folders", needed for doing the changes when dropping
+  };
+
+  DragDrop.dragElement = function(event, $element) {
+    event.preventDefault();
+    var $container = $element.parent().parent();
+    var elementID = $container.prop('id');
+    elementID = elementID.substring(elementID.indexOf('_') + 1);
+    DragDrop.dragID = DragDrop.getIdFromEvent(event);
+
+    if (!DragDrop.dragID) {
+      return false;
+    }
+
+    if (!elementID) {
+      elementID = DragDrop.dragID;
+    }
+
+    if ($('#dragIcon').length === 0) {
+      $('body').append('<div id="dragIcon" style="display: none;">&nbsp;</div>');
+    }
+
+    $('#dragIcon').html($container.find('.dragIcon').html() + $container.find('.dragTitle').children(':first').text());
+
+    document.onmouseup = function(event) {
+      DragDrop.cancelDragEvent(event);
+    };
+
+    document.onmousemove = function(event) {
+      DragDrop.mouseMoveEvent(event);
+    };
+  };
+
+  DragDrop.dropElement = function(event) {
+    var dropID = DragDrop.getIdFromEvent(event);
+    if ((DragDrop.dragID) && (DragDrop.dragID !== dropID)) {
+      var dragID = DragDrop.dragID;
+      var table = DragDrop.table;
+      var parameters = 'table=' + table + '-drag' +
+        '&uid=' + dragID +
+        '&dragDrop=' + table +
+        '&srcId=' + dragID +
+        '&dstId=' + dropID;
+      require(['TYPO3/CMS/Backend/ContextMenu'], function(ContextMenu) {
+        ContextMenu.record = {table: decodeURIComponent(table), uid: decodeURIComponent(dragID)};
+        ContextMenu.fetch(parameters);
+      });
+    }
+    DragDrop.cancelDragEvent();
+    return false;
+  };
+
+  DragDrop.cancelDragEvent = function(event) {
+    DragDrop.dragID = null;
+    if ($('#dragIcon').length && $('#dragIcon').is(':visible')) {
+      $('#dragIcon').hide();
+    }
+
+    document.onmouseup = null;
+    document.onmousemove = null;
+  };
+
+  DragDrop.mouseMoveEvent = function(event) {
+    if (!event) {
+      event = window.event;
+    }
+    $('#dragIcon').css({
+      left: (event.x + 5) + 'px',
+      top: (event.y - 5) + 'px'
+    }).show();
+  };
+
+  DragDrop.getIdFromEvent = function(event) {
+    var obj = event.currentTarget;
+    while (obj.id == false && obj.parentNode) {
+      obj = obj.parentNode;
+    }
+    return obj.id.substring(obj.id.indexOf('_') + 1);
+  };
+
+  Tree = {
+    ajaxRoute: 'sc_alt_file_navframe_expandtoggle',
+    frameSetModule: null,
+    activateDragDrop: true,
+    highlightClass: 'active',
+    pageID: 0,
+
+    // reloads a part of the page tree (useful when "expand" / "collapse")
+    load: function(params, isExpand, obj, scopeData, scopeHash) {
+      var $obj = $(obj);
+      var $parentNode = $(obj).parent().parent();
+
+      // immediately collapse the subtree and change the plus to a minus when collapsing
+      // without waiting for the response
+      if (!isExpand) {
+        $parentNode.find('ul:first').remove();
+        var $pm = $obj.parent().find('.pm:first');
+        if ($pm.length) {
+          $pm.get().onclick = null;
+          var src = $pm.children(':first').prop('src');
+          src = src.replace(/minus/, 'plus');
+          $pm.children('first').prop('src', src);
+        }
+      } else {
+        $obj.css({cursor: 'wait'});
+      }
+      $.ajax({
+        url: TYPO3.settings.ajaxUrls[this.ajaxRoute],
+        data: {
+          PM: params,
+          scopeData: scopeData,
+          scopeHash: scopeHash
+        }
+      }).done(function(data) {
+        // the parent node needs to be overwritten, not the object
+        $parentNode.replaceWith(data);
+        Tree.reSelectActiveItem();
+      });
+    },
+
+    // does the complete page refresh (previously known as "_refresh_nav()")
+    refresh: function() {
+      var r = new Date();
+      // randNum is useful so pagetree does not get cached in browser cache when refreshing
+      var loc = window.location.href.replace(/&randNum=\d+|#.*/g, '');
+      var addSign = loc.indexOf('?') > 0 ? '&' : '?';
+      window.location = loc + addSign + 'randNum=' + r.getTime();
+    },
+
+    // attaches the events to the elements needed for the drag and drop (for the titles and the icons)
+    registerDragDropHandlers: function() {
+      if (!Tree.activateDragDrop) {
+        return;
+      }
+
+      $('.list-tree-root').on('mousedown', '.dragTitle, .dragIcon', function(evt) {
+        DragDrop.dragElement(evt, $(this));
+      }).on('mouseup', '.dragTitle, .dragIcon', function(evt) {
+        DragDrop.dropElement(evt, $(this));
+      });
+    },
+
+    // selects the activated item again, in case it collapsed and got expanded again
+    reSelectActiveItem: function() {
+      if (!top.fsMod) {
+        return;
+      }
+      var $activeItem = $('#' + top.fsMod.navFrameHighlightedID[this.frameSetModule]);
+      if ($activeItem.length) {
+        $activeItem.addClass(Tree.highlightClass);
+        Tree.extractPageIdFromTreeItem($activeItem.prop('id'));
+      }
+    },
+
+    // highlights an active list item in the page tree and registers it to the top-frame
+    // used when loading the page for the first time
+    highlightActiveItem: function(frameSetModule, highlightID) {
+      Tree.frameSetModule = frameSetModule;
+      Tree.extractPageIdFromTreeItem(highlightID);
+
+      // Remove all items that are already highlighted
+      var $obj = $('#' + top.fsMod.navFrameHighlightedID[frameSetModule]);
+      if ($obj.length) {
+        $obj.removeClass(Tree.highlightClass);
+      }
+
+      // Set the new item
+      top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
+      $('#' + highlightID).addClass(Tree.highlightClass);
+    },
+
+    //extract pageID from the given id (pagesxxx_y_z where xxx is the ID)
+    extractPageIdFromTreeItem: function(highlightID) {
+      if (highlightID) {
+        Tree.pageID = highlightID.split('_')[0].substring(5);
+      }
+    }
+  };
+
+  return Tree;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js b/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js
index 43ae4bae382f..343cc2200cc9 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/LiveSearch.js
@@ -17,139 +17,139 @@
  * @exports TYPO3/CMS/Backend/LiveSearch
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Viewport',
-	'TYPO3/CMS/Backend/Icons',
-	'jquery/autocomplete',
-	'TYPO3/CMS/Backend/jquery.clearable'
-], function ($, Viewport, Icons) {
-	'use strict';
+  'jquery',
+  'TYPO3/CMS/Backend/Viewport',
+  'TYPO3/CMS/Backend/Icons',
+  'jquery/autocomplete',
+  'TYPO3/CMS/Backend/jquery.clearable'
+], function($, Viewport, Icons) {
+  'use strict';
 
-	var containerSelector = '#typo3-cms-backend-backend-toolbaritems-livesearchtoolbaritem';
-	var toolbarItem = '.t3js-toolbar-item-search';
-	var dropdownToggle = '.t3js-toolbar-search-dropdowntoggle';
-	var searchFieldSelector = '.t3js-topbar-navigation-search-field';
-	var formSelector = '.t3js-topbar-navigation-search';
-	var url = TYPO3.settings.ajaxUrls['livesearch'];
+  var containerSelector = '#typo3-cms-backend-backend-toolbaritems-livesearchtoolbaritem';
+  var toolbarItem = '.t3js-toolbar-item-search';
+  var dropdownToggle = '.t3js-toolbar-search-dropdowntoggle';
+  var searchFieldSelector = '.t3js-topbar-navigation-search-field';
+  var formSelector = '.t3js-topbar-navigation-search';
+  var url = TYPO3.settings.ajaxUrls['livesearch'];
 
-	Viewport.Topbar.Toolbar.registerEvent(function() {
-		$(searchFieldSelector).autocomplete({
-			// ajax options
-			serviceUrl: url,
-			paramName: 'q',
-			dataType: 'json',
-			minChars: 2,
-			width: '100%',
-			groupBy: 'typeLabel',
-			containerClass: toolbarItem.substr(1, toolbarItem.length),
-			appendTo: containerSelector + ' .dropdown-menu',
-			forceFixPosition: false,
-			preserveInput: true,
-			showNoSuggestionNotice: true,
-			triggerSelectOnValidInput: false,
-			preventBadQueries: false,
-			noSuggestionNotice: '<h3 class="dropdown-headline">' + TYPO3.lang['liveSearch_listEmptyText'] + '</h3>'
-					+ '<p>' + TYPO3.lang['liveSearch_helpTitle'] + '</p>'
-					+ '<hr>'
-					+ '<p>' + TYPO3.lang['liveSearch_helpDescription'] + '<br>' + TYPO3.lang['liveSearch_helpDescriptionPages'] + '</p>',
-			// put the AJAX results in the right format
-			transformResult: function(response) {
-				return {
-					suggestions: $.map(response, function(dataItem) {
-						return { value: dataItem.title, data: dataItem };
-					})
-				};
-			},
-			formatGroup: function(suggestion, category, i) {
-				var html = '';
-				// add a divider if it's not the first group
-				if (i > 0) {
-					html = '<hr>';
-				}
-				return html + '<h3 class="dropdown-headline">' + category + '</h3>';
-			},
-			// Rendering of each item
-			formatResult: function(suggestion, value, i) {
-				return ''
-					+ '<div class="dropdown-table">'
-					+ '<div class="dropdown-table-row">'
-					+ '<div class="dropdown-table-column dropdown-table-icon">' + suggestion.data.iconHTML + '</div>'
-					+ '<div class="dropdown-table-column dropdown-table-title">'
-					+ '<a class="dropdown-table-title-ellipsis dropdown-list-link" href="#" data-pageid="' + suggestion.data.pageId + '" data-target="' + suggestion.data.editLink + '">'
-					+ suggestion.data.title
-					+ '</a>'
-					+ '</div>'
-					+ '</div>'
-					+ '</div>'
-					+ '';
-			},
-			onSearchStart: function () {
-				if(!$(toolbarItem).hasClass('loading')) {
-					$(toolbarItem).addClass('loading');
-					Icons.getIcon('spinner-circle-light', Icons.sizes.small, '', 'default', 'inline').done(function (markup) {
-						$(toolbarItem).find('.icon-apps-toolbar-menu-search').replaceWith(markup)
-					});
-				}
-			},
-			onSearchComplete: function(query, suggestions) {
-				if (!$(toolbarItem).hasClass('open') && $(searchFieldSelector).val().length > 1) {
-					$(dropdownToggle).dropdown('toggle');
-					$(searchFieldSelector).focus();
-				}
-				if ($(toolbarItem).hasClass('loading')) {
-					$(toolbarItem).removeClass('loading');
-					Icons.getIcon('apps-toolbar-menu-search', Icons.sizes.small, '', 'default', 'inline').done(function (markup) {
-						$(toolbarItem).find('.icon-spinner-circle-light').replaceWith(markup)
-					});
-				}
-			},
-			beforeRender: function(container) {
-				container.append('<hr><div>' +
-					'<a href="#" class="btn btn-primary pull-right t3js-live-search-show-all">' +
-						TYPO3.lang['liveSearch_showAllResults'] +
-					'</a>' +
-				'</div>');
-				if (!$(toolbarItem).hasClass('open')) {
-					$(dropdownToggle).dropdown('toggle');
-					$(searchFieldSelector).focus();
-				}
-			},
-			onHide: function() {
-				if ($(toolbarItem).hasClass('open')) {
-					$(dropdownToggle).dropdown('toggle');
-				}
-			}
-		});
+  Viewport.Topbar.Toolbar.registerEvent(function() {
+    $(searchFieldSelector).autocomplete({
+      // ajax options
+      serviceUrl: url,
+      paramName: 'q',
+      dataType: 'json',
+      minChars: 2,
+      width: '100%',
+      groupBy: 'typeLabel',
+      containerClass: toolbarItem.substr(1, toolbarItem.length),
+      appendTo: containerSelector + ' .dropdown-menu',
+      forceFixPosition: false,
+      preserveInput: true,
+      showNoSuggestionNotice: true,
+      triggerSelectOnValidInput: false,
+      preventBadQueries: false,
+      noSuggestionNotice: '<h3 class="dropdown-headline">' + TYPO3.lang['liveSearch_listEmptyText'] + '</h3>'
+      + '<p>' + TYPO3.lang['liveSearch_helpTitle'] + '</p>'
+      + '<hr>'
+      + '<p>' + TYPO3.lang['liveSearch_helpDescription'] + '<br>' + TYPO3.lang['liveSearch_helpDescriptionPages'] + '</p>',
+      // put the AJAX results in the right format
+      transformResult: function(response) {
+        return {
+          suggestions: $.map(response, function(dataItem) {
+            return {value: dataItem.title, data: dataItem};
+          })
+        };
+      },
+      formatGroup: function(suggestion, category, i) {
+        var html = '';
+        // add a divider if it's not the first group
+        if (i > 0) {
+          html = '<hr>';
+        }
+        return html + '<h3 class="dropdown-headline">' + category + '</h3>';
+      },
+      // Rendering of each item
+      formatResult: function(suggestion, value, i) {
+        return ''
+          + '<div class="dropdown-table">'
+          + '<div class="dropdown-table-row">'
+          + '<div class="dropdown-table-column dropdown-table-icon">' + suggestion.data.iconHTML + '</div>'
+          + '<div class="dropdown-table-column dropdown-table-title">'
+          + '<a class="dropdown-table-title-ellipsis dropdown-list-link" href="#" data-pageid="' + suggestion.data.pageId + '" data-target="' + suggestion.data.editLink + '">'
+          + suggestion.data.title
+          + '</a>'
+          + '</div>'
+          + '</div>'
+          + '</div>'
+          + '';
+      },
+      onSearchStart: function() {
+        if (!$(toolbarItem).hasClass('loading')) {
+          $(toolbarItem).addClass('loading');
+          Icons.getIcon('spinner-circle-light', Icons.sizes.small, '', 'default', 'inline').done(function(markup) {
+            $(toolbarItem).find('.icon-apps-toolbar-menu-search').replaceWith(markup)
+          });
+        }
+      },
+      onSearchComplete: function(query, suggestions) {
+        if (!$(toolbarItem).hasClass('open') && $(searchFieldSelector).val().length > 1) {
+          $(dropdownToggle).dropdown('toggle');
+          $(searchFieldSelector).focus();
+        }
+        if ($(toolbarItem).hasClass('loading')) {
+          $(toolbarItem).removeClass('loading');
+          Icons.getIcon('apps-toolbar-menu-search', Icons.sizes.small, '', 'default', 'inline').done(function(markup) {
+            $(toolbarItem).find('.icon-spinner-circle-light').replaceWith(markup)
+          });
+        }
+      },
+      beforeRender: function(container) {
+        container.append('<hr><div>' +
+          '<a href="#" class="btn btn-primary pull-right t3js-live-search-show-all">' +
+          TYPO3.lang['liveSearch_showAllResults'] +
+          '</a>' +
+          '</div>');
+        if (!$(toolbarItem).hasClass('open')) {
+          $(dropdownToggle).dropdown('toggle');
+          $(searchFieldSelector).focus();
+        }
+      },
+      onHide: function() {
+        if ($(toolbarItem).hasClass('open')) {
+          $(dropdownToggle).dropdown('toggle');
+        }
+      }
+    });
 
-		// set up the events
-		$(containerSelector).on('click', '.t3js-live-search-show-all', function(evt) {
-			evt.preventDefault();
-			TYPO3.ModuleMenu.App.showModule('web_list', 'id=0&search_levels=-1&search_field=' + encodeURIComponent($(searchFieldSelector).val()));
-			$(searchFieldSelector).val('').trigger('change');
-		});
-		if ($(searchFieldSelector).length) {
-			$('.' + $(searchFieldSelector).autocomplete().options.containerClass).on('click.autocomplete', '.dropdown-list-link', function (evt) {
-				evt.preventDefault();
-				jump($(this).data('target'), 'web_list', 'web', $(this).data('pageid'));
-				$(searchFieldSelector).val('').trigger('change');
-			});
-		}
+    // set up the events
+    $(containerSelector).on('click', '.t3js-live-search-show-all', function(evt) {
+      evt.preventDefault();
+      TYPO3.ModuleMenu.App.showModule('web_list', 'id=0&search_levels=-1&search_field=' + encodeURIComponent($(searchFieldSelector).val()));
+      $(searchFieldSelector).val('').trigger('change');
+    });
+    if ($(searchFieldSelector).length) {
+      $('.' + $(searchFieldSelector).autocomplete().options.containerClass).on('click.autocomplete', '.dropdown-list-link', function(evt) {
+        evt.preventDefault();
+        jump($(this).data('target'), 'web_list', 'web', $(this).data('pageid'));
+        $(searchFieldSelector).val('').trigger('change');
+      });
+    }
 
-		// Unset height, width and z-index
-		$(toolbarItem).removeAttr('style');
+    // Unset height, width and z-index
+    $(toolbarItem).removeAttr('style');
 
-		$(searchFieldSelector).clearable({
-			onClear: function() {
-				if ($(toolbarItem).hasClass('open')) {
-					$(dropdownToggle).dropdown('toggle');
-				}
-			}
-		});
+    $(searchFieldSelector).clearable({
+      onClear: function() {
+        if ($(toolbarItem).hasClass('open')) {
+          $(dropdownToggle).dropdown('toggle');
+        }
+      }
+    });
 
-		// Prevent submitting the search form
-		$(formSelector).submit(function(evt) {
-			evt.preventDefault();
-		});
-	});
+    // Prevent submitting the search form
+    $(formSelector).submit(function(evt) {
+      evt.preventDefault();
+    });
+  });
 
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js b/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js
index e561b0ed372d..7314d770bd17 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Localization.js
@@ -16,280 +16,289 @@
  * UI for localization workflow.
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/AjaxDataHandler',
-	'TYPO3/CMS/Backend/Wizard',
-	'TYPO3/CMS/Backend/Icons',
-	'TYPO3/CMS/Backend/Severity',
-	'bootstrap'
+  'jquery',
+  'TYPO3/CMS/Backend/AjaxDataHandler',
+  'TYPO3/CMS/Backend/Wizard',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Severity',
+  'bootstrap'
 ], function($, DataHandler, Wizard, Icons, Severity) {
-	'use strict';
+  'use strict';
 
-	/**
-	 * @type {{identifier: {triggerButton: string}, actions: {translate: $, copy: $}, settings: {}, records: []}}
-	 * @exports TYPO3/CMS/Backend/Localization
-	 */
-	var Localization = {
-		identifier: {
-			triggerButton: '.t3js-localize'
-		},
-		actions: {
-			translate: $('<label />', {
-				class: 'btn btn-block btn-default t3js-option',
-				'data-helptext': '.t3js-helptext-translate'
-			}).html('<br>Translate').prepend(
-				$('<input />', {
-					type: 'radio',
-					name: 'mode',
-					id: 'mode_translate',
-					value: 'localize',
-					style: 'display: none'
-				})
-			),
-			copy: $('<label />', {
-				class: 'btn btn-block btn-default t3js-option',
-				'data-helptext': '.t3js-helptext-copy'
-			}).html('<br>Copy').prepend(
-				$('<input />', {
-					type: 'radio',
-					name: 'mode',
-					id: 'mode_copy',
-					value: 'copyFromLanguage',
-					style: 'display: none'
-				})
-			)
-		},
-		settings: {},
-		records: []
-	};
+  /**
+   * @type {{identifier: {triggerButton: string}, actions: {translate: $, copy: $}, settings: {}, records: []}}
+   * @exports TYPO3/CMS/Backend/Localization
+   */
+  var Localization = {
+    identifier: {
+      triggerButton: '.t3js-localize'
+    },
+    actions: {
+      translate: $('<label />', {
+        class: 'btn btn-block btn-default t3js-option',
+        'data-helptext': '.t3js-helptext-translate'
+      }).html('<br>Translate').prepend(
+        $('<input />', {
+          type: 'radio',
+          name: 'mode',
+          id: 'mode_translate',
+          value: 'localize',
+          style: 'display: none'
+        })
+      ),
+      copy: $('<label />', {
+        class: 'btn btn-block btn-default t3js-option',
+        'data-helptext': '.t3js-helptext-copy'
+      }).html('<br>Copy').prepend(
+        $('<input />', {
+          type: 'radio',
+          name: 'mode',
+          id: 'mode_copy',
+          value: 'copyFromLanguage',
+          style: 'display: none'
+        })
+      )
+    },
+    settings: {},
+    records: []
+  };
 
-	Localization.initialize = function() {
-		Icons.getIcon('actions-localize', Icons.sizes.large).done(function(localizeIconMarkup) {
-			Icons.getIcon('actions-edit-copy', Icons.sizes.large).done(function(copyIconMarkup) {
-				Localization.actions.translate.prepend(localizeIconMarkup);
-				Localization.actions.copy.prepend(copyIconMarkup);
-				$(Localization.identifier.triggerButton).prop('disabled', false);
-			});
-		});
+  Localization.initialize = function() {
+    Icons.getIcon('actions-localize', Icons.sizes.large).done(function(localizeIconMarkup) {
+      Icons.getIcon('actions-edit-copy', Icons.sizes.large).done(function(copyIconMarkup) {
+        Localization.actions.translate.prepend(localizeIconMarkup);
+        Localization.actions.copy.prepend(copyIconMarkup);
+        $(Localization.identifier.triggerButton).prop('disabled', false);
+      });
+    });
 
-		$(document).on('click', Localization.identifier.triggerButton, function() {
-			var $triggerButton = $(this),
-				actions = [],
-				slideStep1 = '';
+    $(document).on('click', Localization.identifier.triggerButton, function() {
+      var $triggerButton = $(this),
+        actions = [],
+        slideStep1 = '';
 
-			if ($triggerButton.data('allowTranslate')) {
-				actions.push(
-					'<div class="row">'
-						+ '<div class="btn-group col-sm-3">' + Localization.actions.translate[0].outerHTML + '</div>'
-						+ '<div class="col-sm-9">'
-							+ '<p class="t3js-helptext t3js-helptext-translate text-muted">' + TYPO3.lang['localize.educate.translate'] + '</p>'
-						+ '</div>'
-					+ '</div>'
-				);
-			}
+      if ($triggerButton.data('allowTranslate')) {
+        actions.push(
+          '<div class="row">'
+          + '<div class="btn-group col-sm-3">' + Localization.actions.translate[0].outerHTML + '</div>'
+          + '<div class="col-sm-9">'
+          + '<p class="t3js-helptext t3js-helptext-translate text-muted">' + TYPO3.lang['localize.educate.translate'] + '</p>'
+          + '</div>'
+          + '</div>'
+        );
+      }
 
-			if ($triggerButton.data('allowCopy')) {
-				actions.push(
-					'<div class="row">'
-						+ '<div class="col-sm-3 btn-group">' + Localization.actions.copy[0].outerHTML + '</div>'
-						+ '<div class="col-sm-9">'
-							+ '<p class="t3js-helptext t3js-helptext-copy text-muted">' + TYPO3.lang['localize.educate.copy'] + '</p>'
-						+ '</div>'
-					+ '</div>'
-				);
-			}
+      if ($triggerButton.data('allowCopy')) {
+        actions.push(
+          '<div class="row">'
+          + '<div class="col-sm-3 btn-group">' + Localization.actions.copy[0].outerHTML + '</div>'
+          + '<div class="col-sm-9">'
+          + '<p class="t3js-helptext t3js-helptext-copy text-muted">' + TYPO3.lang['localize.educate.copy'] + '</p>'
+          + '</div>'
+          + '</div>'
+        );
+      }
 
-			slideStep1 += '<div data-toggle="buttons">' + actions.join('<hr>') + '</div>';
+      slideStep1 += '<div data-toggle="buttons">' + actions.join('<hr>') + '</div>';
 
-			Wizard.addSlide('localize-choose-action', TYPO3.lang['localize.wizard.header'].replace('{0}', $triggerButton.data('colposName')).replace('{1}', $triggerButton.data('languageName')), slideStep1, Severity.info);
-			Wizard.addSlide('localize-choose-language', TYPO3.lang['localize.view.chooseLanguage'], '', Severity.info, function($slide) {
-				Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) {
-					$slide.html(
-						$('<div />', {class: 'text-center'}).append(markup)
-					);
-					Localization.loadAvailableLanguages(
-						$triggerButton.data('pageId'),
-						$triggerButton.data('colposId'),
-						$triggerButton.data('languageId')
-					).done(function(result) {
-						if (result.length === 1) {
-							// We only have one result, auto select the record and continue
-							Localization.settings.language = result[0].uid + ''; // we need a string
-							Wizard.unlockNextStep().trigger('click');
-							return;
-						}
+      Wizard.addSlide('localize-choose-action', TYPO3.lang['localize.wizard.header'].replace('{0}', $triggerButton.data('colposName')).replace('{1}', $triggerButton.data('languageName')), slideStep1, Severity.info);
+      Wizard.addSlide('localize-choose-language', TYPO3.lang['localize.view.chooseLanguage'], '', Severity.info, function($slide) {
+        Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) {
+          $slide.html(
+            $('<div />', {class: 'text-center'}).append(markup)
+          );
+          Localization.loadAvailableLanguages(
+            $triggerButton.data('pageId'),
+            $triggerButton.data('colposId'),
+            $triggerButton.data('languageId')
+          ).done(function(result) {
+            if (result.length === 1) {
+              // We only have one result, auto select the record and continue
+              Localization.settings.language = result[0].uid + ''; // we need a string
+              Wizard.unlockNextStep().trigger('click');
+              return;
+            }
 
-						var $languageButtons = $('<div />', {class: 'row', 'data-toggle': 'buttons'});
+            var $languageButtons = $('<div />', {class: 'row', 'data-toggle': 'buttons'});
 
-						$.each(result, function(_, languageObject) {
-							$languageButtons.append(
-								$('<div />', {class: 'col-sm-4'}).append(
-									$('<label />', {class: 'btn btn-default btn-block t3js-option option'}).text(' ' + languageObject.title).prepend(
-										languageObject.flagIcon
-									).prepend(
-										$('<input />', {
-											type: 'radio',
-											name: 'language',
-											id: 'language' + languageObject.uid,
-											value: languageObject.uid,
-											style: 'display: none;'
-										})
-									)
-								)
-							);
-						});
-						$slide.html($languageButtons);
-					});
-				});
-			});
-			Wizard.addSlide('localize-summary', TYPO3.lang['localize.view.summary'], '', Severity.info, function($slide) {
-				Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) {
-					$slide.html(
-						$('<div />', {class: 'text-center'}).append(markup)
-					);
+            $.each(result, function(_, languageObject) {
+              $languageButtons.append(
+                $('<div />', {class: 'col-sm-4'}).append(
+                  $('<label />', {class: 'btn btn-default btn-block t3js-option option'}).text(' ' + languageObject.title).prepend(
+                    languageObject.flagIcon
+                  ).prepend(
+                    $('<input />', {
+                      type: 'radio',
+                      name: 'language',
+                      id: 'language' + languageObject.uid,
+                      value: languageObject.uid,
+                      style: 'display: none;'
+                    })
+                  )
+                )
+              );
+            });
+            $slide.html($languageButtons);
+          });
+        });
+      });
+      Wizard.addSlide('localize-summary', TYPO3.lang['localize.view.summary'], '', Severity.info, function($slide) {
+        Icons.getIcon('spinner-circle-dark', Icons.sizes.large).done(function(markup) {
+          $slide.html(
+            $('<div />', {class: 'text-center'}).append(markup)
+          );
 
-					Localization.getSummary(
-						$triggerButton.data('pageId'),
-						$triggerButton.data('colposId'),
-						$triggerButton.data('languageId')
-					).done(function(result) {
-						var $summary = $('<div />', {class: 'row'});
-						Localization.records = [];
+          Localization.getSummary(
+            $triggerButton.data('pageId'),
+            $triggerButton.data('colposId'),
+            $triggerButton.data('languageId')
+          ).done(function(result) {
+            var $summary = $('<div />', {class: 'row'});
+            Localization.records = [];
 
-						$.each(result, function(_, record) {
-							var label = ' (' + record.uid + ') ' + record.title;
-							Localization.records.push(record.uid);
+            $.each(result, function(_, record) {
+              var label = ' (' + record.uid + ') ' + record.title;
+              Localization.records.push(record.uid);
 
-							$summary.append(
-								$('<div />', {'class': 'col-sm-6'}).append(
-									$('<div />', {'class': 'input-group'}).append(
-										$('<span />', {'class': 'input-group-addon'}).append(
-											$('<input />', {type: 'checkbox', id: 'record-uid-' + record.uid, checked: 'checked', 'data-uid': record.uid, 'aria-label': label})
-										),
-										$('<label />', {'class': 'form-control', for: 'record-uid-' + record.uid}).text(label).prepend(record.icon)
-									)
-								)
-							);
-						});
-						$slide.html($summary);
-						Wizard.unlockNextStep();
+              $summary.append(
+                $('<div />', {'class': 'col-sm-6'}).append(
+                  $('<div />', {'class': 'input-group'}).append(
+                    $('<span />', {'class': 'input-group-addon'}).append(
+                      $('<input />', {
+                        type: 'checkbox',
+                        id: 'record-uid-' + record.uid,
+                        checked: 'checked',
+                        'data-uid': record.uid,
+                        'aria-label': label
+                      })
+                    ),
+                    $('<label />', {
+                      'class': 'form-control',
+                      for: 'record-uid-' + record.uid
+                    }).text(label).prepend(record.icon)
+                  )
+                )
+              );
+            });
+            $slide.html($summary);
+            Wizard.unlockNextStep();
 
-						Wizard.getComponent().on('change', 'input[type="checkbox"]', function() {
-							var $me = $(this),
-								uid = $me.data('uid');
+            Wizard.getComponent().on('change', 'input[type="checkbox"]', function() {
+              var $me = $(this),
+                uid = $me.data('uid');
 
-							if ($me.is(':checked')) {
-								Localization.records.push(uid);
-							} else {
-								var index = Localization.records.indexOf(uid);
-								if (index > -1) {
-									Localization.records.splice(index, 1);
-								}
-							}
+              if ($me.is(':checked')) {
+                Localization.records.push(uid);
+              } else {
+                var index = Localization.records.indexOf(uid);
+                if (index > -1) {
+                  Localization.records.splice(index, 1);
+                }
+              }
 
-							if (Localization.records.length > 0) {
-								Wizard.unlockNextStep();
-							} else {
-								Wizard.lockNextStep();
-							}
-						});
-					});
-				});
-			});
-			Wizard.addFinalProcessingSlide(function() {
-				Localization.localizeRecords(
-					$triggerButton.data('pageId'),
-					$triggerButton.data('colposId'),
-					$triggerButton.data('languageId'),
-					Localization.records
-				).done(function() {
-					Wizard.dismiss();
-					document.location.reload();
-				});
-			}).done(function() {
-				Wizard.show();
+              if (Localization.records.length > 0) {
+                Wizard.unlockNextStep();
+              } else {
+                Wizard.lockNextStep();
+              }
+            });
+          });
+        });
+      });
+      Wizard.addFinalProcessingSlide(function() {
+        Localization.localizeRecords(
+          $triggerButton.data('pageId'),
+          $triggerButton.data('colposId'),
+          $triggerButton.data('languageId'),
+          Localization.records
+        ).done(function() {
+          Wizard.dismiss();
+          document.location.reload();
+        });
+      }).done(function() {
+        Wizard.show();
 
-				Wizard.getComponent().on('click', '.t3js-option', function(e) {
-					var $me = $(this),
-						$radio = $me.find('input[type="radio"]');
+        Wizard.getComponent().on('click', '.t3js-option', function(e) {
+          var $me = $(this),
+            $radio = $me.find('input[type="radio"]');
 
-					if ($me.data('helptext')) {
-						var $container = $(e.delegateTarget);
-						$container.find('.t3js-helptext').addClass('text-muted');
-						$container.find($me.data('helptext')).removeClass('text-muted');
-					}
-					if ($radio.length > 0) {
-						Localization.settings[$radio.attr('name')] = $radio.val();
-					}
-					Wizard.unlockNextStep();
-				});
-			});
-		});
+          if ($me.data('helptext')) {
+            var $container = $(e.delegateTarget);
+            $container.find('.t3js-helptext').addClass('text-muted');
+            $container.find($me.data('helptext')).removeClass('text-muted');
+          }
+          if ($radio.length > 0) {
+            Localization.settings[$radio.attr('name')] = $radio.val();
+          }
+          Wizard.unlockNextStep();
+        });
+      });
+    });
 
-		/**
-		 * Load available languages from page and colPos
-		 *
-		 * @param {Integer} pageId
-		 * @param {Integer} colPos
-		 * @param {Integer} languageId
-		 * @return {Promise}
-		 */
-		Localization.loadAvailableLanguages = function(pageId, colPos, languageId) {
-			return $.ajax({
-				url: TYPO3.settings.ajaxUrls['languages_page_colpos'],
-				data: {
-					pageId: pageId,
-					colPos: colPos,
-					languageId: languageId
-				}
-			});
-		};
+    /**
+     * Load available languages from page and colPos
+     *
+     * @param {Integer} pageId
+     * @param {Integer} colPos
+     * @param {Integer} languageId
+     * @return {Promise}
+     */
+    Localization.loadAvailableLanguages = function(pageId, colPos, languageId) {
+      return $.ajax({
+        url: TYPO3.settings.ajaxUrls['languages_page_colpos'],
+        data: {
+          pageId: pageId,
+          colPos: colPos,
+          languageId: languageId
+        }
+      });
+    };
 
-		/**
-		 * Get summary for record processing
-		 *
-		 * @param {Integer} pageId
-		 * @param {Integer} colPos
-		 * @param {Integer} languageId
-		 * @return {Promise}
-		 */
-		Localization.getSummary = function(pageId, colPos, languageId) {
-			return $.ajax({
-				url: TYPO3.settings.ajaxUrls['records_localize_summary'],
-				data: {
-					pageId: pageId,
-					colPos: colPos,
-					destLanguageId: languageId,
-					languageId: Localization.settings.language
-				}
-			});
-		};
+    /**
+     * Get summary for record processing
+     *
+     * @param {Integer} pageId
+     * @param {Integer} colPos
+     * @param {Integer} languageId
+     * @return {Promise}
+     */
+    Localization.getSummary = function(pageId, colPos, languageId) {
+      return $.ajax({
+        url: TYPO3.settings.ajaxUrls['records_localize_summary'],
+        data: {
+          pageId: pageId,
+          colPos: colPos,
+          destLanguageId: languageId,
+          languageId: Localization.settings.language
+        }
+      });
+    };
 
-		/**
-		 * Localize records
-		 *
-		 * @param {Integer} pageId
-		 * @param {Integer} colPos
-		 * @param {Integer} languageId
-		 * @param {Array} uidList
-		 * @return {Promise}
-		 */
-		Localization.localizeRecords = function(pageId, colPos, languageId, uidList) {
-			return $.ajax({
-				url: TYPO3.settings.ajaxUrls['records_localize'],
-				data: {
-					pageId: pageId,
-					colPos: colPos,
-					srcLanguageId: Localization.settings.language,
-					destLanguageId: languageId,
-					action: Localization.settings.mode,
-					uidList: uidList
-				}
-			});
-		};
-	};
+    /**
+     * Localize records
+     *
+     * @param {Integer} pageId
+     * @param {Integer} colPos
+     * @param {Integer} languageId
+     * @param {Array} uidList
+     * @return {Promise}
+     */
+    Localization.localizeRecords = function(pageId, colPos, languageId, uidList) {
+      return $.ajax({
+        url: TYPO3.settings.ajaxUrls['records_localize'],
+        data: {
+          pageId: pageId,
+          colPos: colPos,
+          srcLanguageId: Localization.settings.language,
+          destLanguageId: languageId,
+          action: Localization.settings.mode,
+          uidList: uidList
+        }
+      });
+    };
+  };
 
-	$(Localization.initialize);
+  $(Localization.initialize);
 
-	return Localization;
+  return Localization;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js
index da64e7f6b7cf..4f0817b7b1f0 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/LoginRefresh.js
@@ -17,465 +17,488 @@
  * displays a proper dialog to the user.
  */
 define(['jquery', 'TYPO3/CMS/Backend/Notification', 'bootstrap'], function($, Typo3Notification) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{identifier: {loginrefresh: string, lockedModal: string, loginFormModal: string}, options: {modalConfig: {backdrop: string}}, webNotification: null, intervalTime: integer, intervalId: null, backendIsLocked: boolean, isTimingOut: boolean, $timeoutModal: string, $backendLockedModal: string, $loginForm: string, loginFramesetUrl: string, logoutUrl: string}}
-	 * @exports TYPO3/CMS/Backend/LoginRefresh
-	 */
-	var LoginRefresh = {
-		identifier: {
-			loginrefresh: 't3js-modal-loginrefresh',
-			lockedModal: 't3js-modal-backendlocked',
-			loginFormModal: 't3js-modal-backendloginform'
-		},
-		options: {
-			modalConfig: {
-				backdrop: 'static'
-			}
-		},
-		webNotification: null,
-		intervalTime: 60,
-		intervalId: null,
-		backendIsLocked: false,
-		isTimingOut: false,
-		$timeoutModal: '',
-		$backendLockedModal: '',
-		$loginForm: '',
-		loginFramesetUrl: '',
-		logoutUrl: ''
-	};
-
-	/**
-	 * Starts the session check task (if not running already)
-	 */
-	LoginRefresh.startTask = function() {
-		if (LoginRefresh.intervalId !== null) {
-			return;
-		}
-
-		// set interval to 60 seconds
-		var interval = 1000 * LoginRefresh.intervalTime;
-		LoginRefresh.intervalId = setInterval(LoginRefresh.checkActiveSession, interval);
-	};
-
-	/**
-	 * Stops the session check task
-	 */
-	LoginRefresh.stopTask = function() {
-		clearInterval(LoginRefresh.intervalId);
-		LoginRefresh.intervalId = null;
-	};
-
-	/**
-	 * Generates a modal dialog as template.
-	 *
-	 * @param {String} identifier
-	 * @returns {Object}
-	 */
-	LoginRefresh.generateModal = function(identifier) {
-		return $('<div />', {id: identifier, class: 't3js-modal ' + identifier + ' modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade'}).append(
-			$('<div />', {class: 'modal-dialog'}).append(
-				$('<div />', {class: 'modal-content'}).append(
-					$('<div />', {class: 'modal-header'}).append(
-						$('<h4 />', {class: 'modal-title'})
-					),
-					$('<div />', {class: 'modal-body'}),
-					$('<div />', {class: 'modal-footer'})
-				)
-			)
-		);
-	};
-
-	/**
-	 * Set interval time
-	 *
-	 * @param {integer} intervalTime
-	 */
-	LoginRefresh.setIntervalTime = function(intervalTime) {
-		// To avoid the integer overflow in setInterval, we limit the interval time to be one request per day
-		LoginRefresh.intervalTime = Math.min(intervalTime, 86400);
-	};
-
-	/**
-	 * Set logout url
-	 *
-	 * @param {String} logoutUrl
-	 */
-	LoginRefresh.setLogoutUrl = function(logoutUrl) {
-		LoginRefresh.logoutUrl = logoutUrl;
-	};
-
-	/**
-	 * Generates the modal displayed on near session time outs
-	 */
-	LoginRefresh.initializeTimeoutModal = function() {
-		LoginRefresh.$timeoutModal = LoginRefresh.generateModal(LoginRefresh.identifier.loginrefresh);
-		LoginRefresh.$timeoutModal.addClass('modal-severity-notice');
-		LoginRefresh.$timeoutModal.find('.modal-header h4').text(TYPO3.lang['mess.login_about_to_expire_title']);
-		LoginRefresh.$timeoutModal.find('.modal-body').append(
-			$('<p />').text(TYPO3.lang['mess.login_about_to_expire']),
-			$('<div />', {class: 'progress'}).append(
-				$('<div />', {
-					class: 'progress-bar progress-bar-warning progress-bar-striped active',
-					role: 'progressbar',
-					'aria-valuemin': '0',
-					'aria-valuemax': '100'
-				}).append(
-					$('<span />', {class: 'sr-only'})
-				)
-			)
-		);
-		LoginRefresh.$timeoutModal.find('.modal-footer').append(
-			$('<button />', {class: 'btn btn-default', 'data-action': 'logout'}).text(TYPO3.lang['mess.refresh_login_logout_button']).on('click', function() {
-				top.location.href = LoginRefresh.logoutUrl;
-			}),
-			$('<button />', {class: 'btn btn-primary t3js-active', 'data-action': 'refreshSession'}).text(TYPO3.lang['mess.refresh_login_refresh_button']).on('click', function() {
-				$.ajax({
-					url: TYPO3.settings.ajaxUrls['login_timedout'],
-					method: 'GET',
-					success: function() {
-						LoginRefresh.hideTimeoutModal();
-					}
-				});
-			})
-		);
-		LoginRefresh.registerDefaultModalEvents(LoginRefresh.$timeoutModal);
-
-		$('body').append(LoginRefresh.$timeoutModal);
-	};
-
-	/**
-	 * Shows the timeout dialog. If the backend is not focused, a Web Notification
-	 * is displayed, too.
-	 */
-	LoginRefresh.showTimeoutModal = function() {
-		LoginRefresh.isTimingOut = true;
-		LoginRefresh.$timeoutModal.modal(LoginRefresh.options.modalConfig);
-		LoginRefresh.fillProgressbar(LoginRefresh.$timeoutModal);
-
-		if (typeof Notification !== 'undefined' && Notification.permission === 'granted' && !LoginRefresh.isPageActive()) {
-			LoginRefresh.webNotification = new Notification(TYPO3.lang['mess.login_about_to_expire_title'], {
-				body: TYPO3.lang['mess.login_about_to_expire'],
-				icon: '/typo3/sysext/backend/Resources/Public/Images/Logo.png'
-			});
-			LoginRefresh.webNotification.onclick = function() {
-				window.focus();
-			};
-		}
-	};
-
-	/**
-	 * Hides the timeout dialog. If a Web Notification is displayed, close it too.
-	 */
-	LoginRefresh.hideTimeoutModal = function() {
-		LoginRefresh.isTimingOut = false;
-		LoginRefresh.$timeoutModal.modal('hide');
-
-		if (typeof Notification !== 'undefined' && LoginRefresh.webNotification !== null) {
-			LoginRefresh.webNotification.close();
-		}
-	};
-
-	/**
-	 * Generates the modal displayed if the backend is locked.
-	 */
-	LoginRefresh.initializeBackendLockedModal = function() {
-		LoginRefresh.$backendLockedModal = LoginRefresh.generateModal(LoginRefresh.identifier.lockedModal);
-		LoginRefresh.$backendLockedModal.find('.modal-header h4').text(TYPO3.lang['mess.please_wait']);
-		LoginRefresh.$backendLockedModal.find('.modal-body').append(
-			$('<p />').text(TYPO3.lang['mess.be_locked'])
-		);
-		LoginRefresh.$backendLockedModal.find('.modal-footer').remove();
-
-		$('body').append(LoginRefresh.$backendLockedModal);
-	};
-
-	/**
-	 * Shows the "backend locked" dialog.
-	 */
-	LoginRefresh.showBackendLockedModal = function() {
-		LoginRefresh.$backendLockedModal.modal(LoginRefresh.options.modalConfig);
-	};
-
-	/**
-	 * Hides the "backend locked" dialog.
-	 */
-	LoginRefresh.hideBackendLockedModal = function() {
-		LoginRefresh.$backendLockedModal.modal('hide');
-	};
-
-	/**
-	 * Generates the login form displayed if the session has timed out.
-	 */
-	LoginRefresh.initializeLoginForm = function() {
-		if (TYPO3.configuration.showRefreshLoginPopup) {
-			// dialog is not required if "showRefreshLoginPopup" is enabled
-			return;
-		}
-
-		LoginRefresh.$loginForm = LoginRefresh.generateModal(LoginRefresh.identifier.loginFormModal);
-		LoginRefresh.$loginForm.addClass('modal-notice');
-		var refresh_login_title = String(TYPO3.lang['mess.refresh_login_title']).replace('%s', TYPO3.configuration.username);
-		LoginRefresh.$loginForm.find('.modal-header h4').text(refresh_login_title);
-		LoginRefresh.$loginForm.find('.modal-body').append(
-			$('<p />').text(TYPO3.lang['mess.login_expired']),
-			$('<form />', {id: 'beLoginRefresh', method: 'POST', action: TYPO3.settings.ajaxUrls['login']}).append(
-				$('<div />', {class: 'form-group'}).append(
-					$('<input />', {type: 'password', name: 'p_field', autofocus: 'autofocus', class: 'form-control', placeholder: TYPO3.lang['mess.refresh_login_password'], 'data-rsa-encryption': 't3-loginrefres-userident'})
-				),
-				$('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}),
-				$('<input />', {type: 'hidden', name: 'userident', id: 't3-loginrefres-userident'})
-			)
-		);
-		LoginRefresh.$loginForm.find('.modal-footer').append(
-			$('<a />', {href: LoginRefresh.logoutUrl, class: 'btn btn-default'}).text(TYPO3.lang['mess.refresh_exit_button']),
-			$('<button />', {type: 'button', class: 'btn btn-primary', 'data-action': 'refreshSession'})
-				.text(TYPO3.lang['mess.refresh_login_button'])
-				.on('click', function(e) {
-					LoginRefresh.$loginForm.find('form').submit();
-				})
-		);
-		LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.submitForm);
-		$('body').append(LoginRefresh.$loginForm);
-		if (require.specified('TYPO3/CMS/Rsaauth/RsaEncryptionModule')) {
-			require(['TYPO3/CMS/Rsaauth/RsaEncryptionModule'], function(RsaEncryption) {
-				RsaEncryption.registerForm($('#beLoginRefresh').get(0));
-			});
-		}
-	};
-
-	/**
-	 * Shows the login form.
-	 */
-	LoginRefresh.showLoginForm = function() {
-		// log off for sure
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['logout'],
-			method: 'GET',
-			success: function() {
-				if (TYPO3.configuration.showRefreshLoginPopup) {
-					LoginRefresh.showLoginPopup();
-				} else {
-					LoginRefresh.$loginForm.modal(LoginRefresh.options.modalConfig);
-				}
-			},
-			failure: function() {
-				alert('something went wrong');
-			}
-		});
-	};
-
-	/**
-	 * Set login frameset url
-	 */
-	LoginRefresh.setLoginFramesetUrl = function(loginFramesetUrl) {
-		LoginRefresh.loginFramesetUrl = loginFramesetUrl;
-	};
-
-	/**
-	 * Opens the login form in a new window.
-	 */
-	LoginRefresh.showLoginPopup = function() {
-		var vHWin = window.open(LoginRefresh.loginFramesetUrl, 'relogin_' + Math.random().toString(16).slice(2), 'height=450,width=700,status=0,menubar=0,location=1');
-		if (vHWin) {
-			vHWin.focus();
-		}
-	};
-
-	/**
-	 * Hides the login form.
-	 */
-	LoginRefresh.hideLoginForm = function() {
-		LoginRefresh.$loginForm.modal('hide');
-	};
-
-	/**
-	 * Fills the progressbar attached to the given modal.
-	 */
-	LoginRefresh.fillProgressbar = function($activeModal) {
-		if (!LoginRefresh.isTimingOut) {
-			return;
-		}
-
-		var max = 100,
-			current = 0,
-			$progressBar = $activeModal.find('.progress-bar'),
-			$srText = $progressBar.children('.sr-only');
-
-		var progress = setInterval(function() {
-			var isOverdue = (current >= max);
-
-			if (!LoginRefresh.isTimingOut || isOverdue) {
-				clearInterval(progress);
-
-				if (isOverdue) {
-					// show login form
-					LoginRefresh.hideTimeoutModal();
-					LoginRefresh.showLoginForm();
-				}
-
-				// reset current
-				current = 0;
-			} else {
-				current += 1;
-			}
-
-			var percentText = (current) + '%';
-			$progressBar.css('width', percentText);
-			$srText.text(percentText);
-		}, 300);
-	};
-
-	/**
-	 * Creates additional data based on the security level and "submits" the form
-	 * via an AJAX request.
-	 *
-	 * @param {Event} event
-	 */
-	LoginRefresh.submitForm = function(event) {
-		event.preventDefault();
-
-		var $form = LoginRefresh.$loginForm.find('form'),
-			$passwordField = $form.find('input[name=p_field]'),
-			$useridentField = $form.find('input[name=userident]'),
-			passwordFieldValue = $passwordField.val();
-
-		if (passwordFieldValue === '' && $useridentField.val() === '') {
-			Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']);
-			$passwordField.focus();
-			return;
-		}
-
-		if (passwordFieldValue) {
-			$useridentField.val(passwordFieldValue);
-			$passwordField.val('');
-		}
-
-		var postData = {
-			login_status: 'login'
-		};
-		$.each($form.serializeArray(), function(i, field) {
-			postData[field.name] = field.value;
-		});
-		$.ajax({
-			url: $form.attr('action'),
-			method: 'POST',
-			data: postData,
-			success: function(response) {
-				var result = response.login;
-				if (result.success) {
-					// User is logged in
-					LoginRefresh.hideLoginForm();
-				} else {
-					Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']);
-					$passwordField.focus();
-				}
-			}
-		});
-	};
-
-	/**
-	 * Registers the (shown|hidden).bs.modal events.
-	 * If a modal is shown, the interval check is stopped. If the modal hides,
-	 * the interval check starts again.
-	 * This method is not invoked for the backend locked modal, because we still
-	 * need to check if the backend gets unlocked again.
-	 *
-	 * @param {Object} $modal
-	 * @returns {Object}
-	 */
-	LoginRefresh.registerDefaultModalEvents = function($modal) {
-		$modal.on('hidden.bs.modal', function() {
-			LoginRefresh.startTask();
-		}).on('shown.bs.modal', function() {
-			LoginRefresh.stopTask();
-			// focus the button which was configured as active button
-			LoginRefresh.$timeoutModal.find('.modal-footer .t3js-active').first().focus();
-		});
-
-		return $modal;
-	};
-
-	/**
-	 * Checks if the user is in focus of the backend.
-	 * Thanks to http://stackoverflow.com/a/19519701
-	 */
-	LoginRefresh.isPageActive = function() {
-		var stateKey, eventKey, keys = {
-			hidden: 'visibilitychange',
-			webkitHidden: 'webkitvisibilitychange',
-			mozHidden: 'mozvisibilitychange',
-			msHidden: 'msvisibilitychange'
-		};
-
-		for (stateKey in keys) {
-			if (stateKey in document) {
-				eventKey = keys[stateKey];
-				break;
-			}
-		}
-		return function(c) {
-			if (c) {
-				document.addEventListener(eventKey, c);
-			}
-			return !document[stateKey];
-		}();
-	};
-
-	/**
-	 * Periodically called task that checks if
-	 *
-	 * - the user's backend session is about to expire
-	 * - the user's backend session has expired
-	 * - the backend got locked
-	 *
-	 * and opens a dialog.
-	 */
-	LoginRefresh.checkActiveSession = function() {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['login_timedout'],
-			success: function(response) {
-				if (response.login.locked) {
-					if (!LoginRefresh.backendIsLocked) {
-						LoginRefresh.backendIsLocked = true;
-						LoginRefresh.showBackendLockedModal();
-					}
-				} else {
-					if (LoginRefresh.backendIsLocked) {
-						LoginRefresh.backendIsLocked = false;
-						LoginRefresh.hideBackendLockedModal();
-					}
-				}
-
-				if (!LoginRefresh.backendIsLocked) {
-					if (response.login.timed_out || response.login.will_time_out) {
-						if (response.login.timed_out) {
-							LoginRefresh.showLoginForm();
-						} else {
-							LoginRefresh.showTimeoutModal();
-						}
-					}
-				}
-			}
-		});
-	};
-
-	LoginRefresh.initialize = function() {
-		LoginRefresh.initializeTimeoutModal();
-		LoginRefresh.initializeBackendLockedModal();
-		LoginRefresh.initializeLoginForm();
-
-		LoginRefresh.startTask();
-
-		if (typeof Notification !== 'undefined' && Notification.permission !== 'granted') {
-			Notification.requestPermission();
-		}
-	};
-
-	// expose to global
-	TYPO3.LoginRefresh = LoginRefresh;
-
-	return LoginRefresh;
+  'use strict';
+
+  /**
+   *
+   * @type {{identifier: {loginrefresh: string, lockedModal: string, loginFormModal: string}, options: {modalConfig: {backdrop: string}}, webNotification: null, intervalTime: integer, intervalId: null, backendIsLocked: boolean, isTimingOut: boolean, $timeoutModal: string, $backendLockedModal: string, $loginForm: string, loginFramesetUrl: string, logoutUrl: string}}
+   * @exports TYPO3/CMS/Backend/LoginRefresh
+   */
+  var LoginRefresh = {
+    identifier: {
+      loginrefresh: 't3js-modal-loginrefresh',
+      lockedModal: 't3js-modal-backendlocked',
+      loginFormModal: 't3js-modal-backendloginform'
+    },
+    options: {
+      modalConfig: {
+        backdrop: 'static'
+      }
+    },
+    webNotification: null,
+    intervalTime: 60,
+    intervalId: null,
+    backendIsLocked: false,
+    isTimingOut: false,
+    $timeoutModal: '',
+    $backendLockedModal: '',
+    $loginForm: '',
+    loginFramesetUrl: '',
+    logoutUrl: ''
+  };
+
+  /**
+   * Starts the session check task (if not running already)
+   */
+  LoginRefresh.startTask = function() {
+    if (LoginRefresh.intervalId !== null) {
+      return;
+    }
+
+    // set interval to 60 seconds
+    var interval = 1000 * LoginRefresh.intervalTime;
+    LoginRefresh.intervalId = setInterval(LoginRefresh.checkActiveSession, interval);
+  };
+
+  /**
+   * Stops the session check task
+   */
+  LoginRefresh.stopTask = function() {
+    clearInterval(LoginRefresh.intervalId);
+    LoginRefresh.intervalId = null;
+  };
+
+  /**
+   * Generates a modal dialog as template.
+   *
+   * @param {String} identifier
+   * @returns {Object}
+   */
+  LoginRefresh.generateModal = function(identifier) {
+    return $('<div />', {
+      id: identifier,
+      class: 't3js-modal ' + identifier + ' modal modal-type-default modal-severity-notice modal-style-light modal-size-small fade'
+    }).append(
+      $('<div />', {class: 'modal-dialog'}).append(
+        $('<div />', {class: 'modal-content'}).append(
+          $('<div />', {class: 'modal-header'}).append(
+            $('<h4 />', {class: 'modal-title'})
+          ),
+          $('<div />', {class: 'modal-body'}),
+          $('<div />', {class: 'modal-footer'})
+        )
+      )
+    );
+  };
+
+  /**
+   * Set interval time
+   *
+   * @param {integer} intervalTime
+   */
+  LoginRefresh.setIntervalTime = function(intervalTime) {
+    // To avoid the integer overflow in setInterval, we limit the interval time to be one request per day
+    LoginRefresh.intervalTime = Math.min(intervalTime, 86400);
+  };
+
+  /**
+   * Set logout url
+   *
+   * @param {String} logoutUrl
+   */
+  LoginRefresh.setLogoutUrl = function(logoutUrl) {
+    LoginRefresh.logoutUrl = logoutUrl;
+  };
+
+  /**
+   * Generates the modal displayed on near session time outs
+   */
+  LoginRefresh.initializeTimeoutModal = function() {
+    LoginRefresh.$timeoutModal = LoginRefresh.generateModal(LoginRefresh.identifier.loginrefresh);
+    LoginRefresh.$timeoutModal.addClass('modal-severity-notice');
+    LoginRefresh.$timeoutModal.find('.modal-header h4').text(TYPO3.lang['mess.login_about_to_expire_title']);
+    LoginRefresh.$timeoutModal.find('.modal-body').append(
+      $('<p />').text(TYPO3.lang['mess.login_about_to_expire']),
+      $('<div />', {class: 'progress'}).append(
+        $('<div />', {
+          class: 'progress-bar progress-bar-warning progress-bar-striped active',
+          role: 'progressbar',
+          'aria-valuemin': '0',
+          'aria-valuemax': '100'
+        }).append(
+          $('<span />', {class: 'sr-only'})
+        )
+      )
+    );
+    LoginRefresh.$timeoutModal.find('.modal-footer').append(
+      $('<button />', {
+        class: 'btn btn-default',
+        'data-action': 'logout'
+      }).text(TYPO3.lang['mess.refresh_login_logout_button']).on('click', function() {
+        top.location.href = LoginRefresh.logoutUrl;
+      }),
+      $('<button />', {
+        class: 'btn btn-primary t3js-active',
+        'data-action': 'refreshSession'
+      }).text(TYPO3.lang['mess.refresh_login_refresh_button']).on('click', function() {
+        $.ajax({
+          url: TYPO3.settings.ajaxUrls['login_timedout'],
+          method: 'GET',
+          success: function() {
+            LoginRefresh.hideTimeoutModal();
+          }
+        });
+      })
+    );
+    LoginRefresh.registerDefaultModalEvents(LoginRefresh.$timeoutModal);
+
+    $('body').append(LoginRefresh.$timeoutModal);
+  };
+
+  /**
+   * Shows the timeout dialog. If the backend is not focused, a Web Notification
+   * is displayed, too.
+   */
+  LoginRefresh.showTimeoutModal = function() {
+    LoginRefresh.isTimingOut = true;
+    LoginRefresh.$timeoutModal.modal(LoginRefresh.options.modalConfig);
+    LoginRefresh.fillProgressbar(LoginRefresh.$timeoutModal);
+
+    if (typeof Notification !== 'undefined' && Notification.permission === 'granted' && !LoginRefresh.isPageActive()) {
+      LoginRefresh.webNotification = new Notification(TYPO3.lang['mess.login_about_to_expire_title'], {
+        body: TYPO3.lang['mess.login_about_to_expire'],
+        icon: '/typo3/sysext/backend/Resources/Public/Images/Logo.png'
+      });
+      LoginRefresh.webNotification.onclick = function() {
+        window.focus();
+      };
+    }
+  };
+
+  /**
+   * Hides the timeout dialog. If a Web Notification is displayed, close it too.
+   */
+  LoginRefresh.hideTimeoutModal = function() {
+    LoginRefresh.isTimingOut = false;
+    LoginRefresh.$timeoutModal.modal('hide');
+
+    if (typeof Notification !== 'undefined' && LoginRefresh.webNotification !== null) {
+      LoginRefresh.webNotification.close();
+    }
+  };
+
+  /**
+   * Generates the modal displayed if the backend is locked.
+   */
+  LoginRefresh.initializeBackendLockedModal = function() {
+    LoginRefresh.$backendLockedModal = LoginRefresh.generateModal(LoginRefresh.identifier.lockedModal);
+    LoginRefresh.$backendLockedModal.find('.modal-header h4').text(TYPO3.lang['mess.please_wait']);
+    LoginRefresh.$backendLockedModal.find('.modal-body').append(
+      $('<p />').text(TYPO3.lang['mess.be_locked'])
+    );
+    LoginRefresh.$backendLockedModal.find('.modal-footer').remove();
+
+    $('body').append(LoginRefresh.$backendLockedModal);
+  };
+
+  /**
+   * Shows the "backend locked" dialog.
+   */
+  LoginRefresh.showBackendLockedModal = function() {
+    LoginRefresh.$backendLockedModal.modal(LoginRefresh.options.modalConfig);
+  };
+
+  /**
+   * Hides the "backend locked" dialog.
+   */
+  LoginRefresh.hideBackendLockedModal = function() {
+    LoginRefresh.$backendLockedModal.modal('hide');
+  };
+
+  /**
+   * Generates the login form displayed if the session has timed out.
+   */
+  LoginRefresh.initializeLoginForm = function() {
+    if (TYPO3.configuration.showRefreshLoginPopup) {
+      // dialog is not required if "showRefreshLoginPopup" is enabled
+      return;
+    }
+
+    LoginRefresh.$loginForm = LoginRefresh.generateModal(LoginRefresh.identifier.loginFormModal);
+    LoginRefresh.$loginForm.addClass('modal-notice');
+    var refresh_login_title = String(TYPO3.lang['mess.refresh_login_title']).replace('%s', TYPO3.configuration.username);
+    LoginRefresh.$loginForm.find('.modal-header h4').text(refresh_login_title);
+    LoginRefresh.$loginForm.find('.modal-body').append(
+      $('<p />').text(TYPO3.lang['mess.login_expired']),
+      $('<form />', {
+        id: 'beLoginRefresh',
+        method: 'POST',
+        action: TYPO3.settings.ajaxUrls['login']
+      }).append(
+        $('<div />', {class: 'form-group'}).append(
+          $('<input />', {
+            type: 'password',
+            name: 'p_field',
+            autofocus: 'autofocus',
+            class: 'form-control',
+            placeholder: TYPO3.lang['mess.refresh_login_password'],
+            'data-rsa-encryption': 't3-loginrefres-userident'
+          })
+        ),
+        $('<input />', {type: 'hidden', name: 'username', value: TYPO3.configuration.username}),
+        $('<input />', {type: 'hidden', name: 'userident', id: 't3-loginrefres-userident'})
+      )
+    );
+    LoginRefresh.$loginForm.find('.modal-footer').append(
+      $('<a />', {
+        href: LoginRefresh.logoutUrl,
+        class: 'btn btn-default'
+      }).text(TYPO3.lang['mess.refresh_exit_button']),
+      $('<button />', {type: 'button', class: 'btn btn-primary', 'data-action': 'refreshSession'})
+        .text(TYPO3.lang['mess.refresh_login_button'])
+        .on('click', function(e) {
+          LoginRefresh.$loginForm.find('form').submit();
+        })
+    );
+    LoginRefresh.registerDefaultModalEvents(LoginRefresh.$loginForm).on('submit', LoginRefresh.submitForm);
+    $('body').append(LoginRefresh.$loginForm);
+    if (require.specified('TYPO3/CMS/Rsaauth/RsaEncryptionModule')) {
+      require(['TYPO3/CMS/Rsaauth/RsaEncryptionModule'], function(RsaEncryption) {
+        RsaEncryption.registerForm($('#beLoginRefresh').get(0));
+      });
+    }
+  };
+
+  /**
+   * Shows the login form.
+   */
+  LoginRefresh.showLoginForm = function() {
+    // log off for sure
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['logout'],
+      method: 'GET',
+      success: function() {
+        if (TYPO3.configuration.showRefreshLoginPopup) {
+          LoginRefresh.showLoginPopup();
+        } else {
+          LoginRefresh.$loginForm.modal(LoginRefresh.options.modalConfig);
+        }
+      },
+      failure: function() {
+        alert('something went wrong');
+      }
+    });
+  };
+
+  /**
+   * Set login frameset url
+   */
+  LoginRefresh.setLoginFramesetUrl = function(loginFramesetUrl) {
+    LoginRefresh.loginFramesetUrl = loginFramesetUrl;
+  };
+
+  /**
+   * Opens the login form in a new window.
+   */
+  LoginRefresh.showLoginPopup = function() {
+    var vHWin = window.open(LoginRefresh.loginFramesetUrl, 'relogin_' + Math.random().toString(16).slice(2), 'height=450,width=700,status=0,menubar=0,location=1');
+    if (vHWin) {
+      vHWin.focus();
+    }
+  };
+
+  /**
+   * Hides the login form.
+   */
+  LoginRefresh.hideLoginForm = function() {
+    LoginRefresh.$loginForm.modal('hide');
+  };
+
+  /**
+   * Fills the progressbar attached to the given modal.
+   */
+  LoginRefresh.fillProgressbar = function($activeModal) {
+    if (!LoginRefresh.isTimingOut) {
+      return;
+    }
+
+    var max = 100,
+      current = 0,
+      $progressBar = $activeModal.find('.progress-bar'),
+      $srText = $progressBar.children('.sr-only');
+
+    var progress = setInterval(function() {
+      var isOverdue = (current >= max);
+
+      if (!LoginRefresh.isTimingOut || isOverdue) {
+        clearInterval(progress);
+
+        if (isOverdue) {
+          // show login form
+          LoginRefresh.hideTimeoutModal();
+          LoginRefresh.showLoginForm();
+        }
+
+        // reset current
+        current = 0;
+      } else {
+        current += 1;
+      }
+
+      var percentText = (current) + '%';
+      $progressBar.css('width', percentText);
+      $srText.text(percentText);
+    }, 300);
+  };
+
+  /**
+   * Creates additional data based on the security level and "submits" the form
+   * via an AJAX request.
+   *
+   * @param {Event} event
+   */
+  LoginRefresh.submitForm = function(event) {
+    event.preventDefault();
+
+    var $form = LoginRefresh.$loginForm.find('form'),
+      $passwordField = $form.find('input[name=p_field]'),
+      $useridentField = $form.find('input[name=userident]'),
+      passwordFieldValue = $passwordField.val();
+
+    if (passwordFieldValue === '' && $useridentField.val() === '') {
+      Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_emptyPassword']);
+      $passwordField.focus();
+      return;
+    }
+
+    if (passwordFieldValue) {
+      $useridentField.val(passwordFieldValue);
+      $passwordField.val('');
+    }
+
+    var postData = {
+      login_status: 'login'
+    };
+    $.each($form.serializeArray(), function(i, field) {
+      postData[field.name] = field.value;
+    });
+    $.ajax({
+      url: $form.attr('action'),
+      method: 'POST',
+      data: postData,
+      success: function(response) {
+        var result = response.login;
+        if (result.success) {
+          // User is logged in
+          LoginRefresh.hideLoginForm();
+        } else {
+          Typo3Notification.error(TYPO3.lang['mess.refresh_login_failed'], TYPO3.lang['mess.refresh_login_failed_message']);
+          $passwordField.focus();
+        }
+      }
+    });
+  };
+
+  /**
+   * Registers the (shown|hidden).bs.modal events.
+   * If a modal is shown, the interval check is stopped. If the modal hides,
+   * the interval check starts again.
+   * This method is not invoked for the backend locked modal, because we still
+   * need to check if the backend gets unlocked again.
+   *
+   * @param {Object} $modal
+   * @returns {Object}
+   */
+  LoginRefresh.registerDefaultModalEvents = function($modal) {
+    $modal.on('hidden.bs.modal', function() {
+      LoginRefresh.startTask();
+    }).on('shown.bs.modal', function() {
+      LoginRefresh.stopTask();
+      // focus the button which was configured as active button
+      LoginRefresh.$timeoutModal.find('.modal-footer .t3js-active').first().focus();
+    });
+
+    return $modal;
+  };
+
+  /**
+   * Checks if the user is in focus of the backend.
+   * Thanks to http://stackoverflow.com/a/19519701
+   */
+  LoginRefresh.isPageActive = function() {
+    var stateKey, eventKey, keys = {
+      hidden: 'visibilitychange',
+      webkitHidden: 'webkitvisibilitychange',
+      mozHidden: 'mozvisibilitychange',
+      msHidden: 'msvisibilitychange'
+    };
+
+    for (stateKey in keys) {
+      if (stateKey in document) {
+        eventKey = keys[stateKey];
+        break;
+      }
+    }
+    return function(c) {
+      if (c) {
+        document.addEventListener(eventKey, c);
+      }
+      return !document[stateKey];
+    }();
+  };
+
+  /**
+   * Periodically called task that checks if
+   *
+   * - the user's backend session is about to expire
+   * - the user's backend session has expired
+   * - the backend got locked
+   *
+   * and opens a dialog.
+   */
+  LoginRefresh.checkActiveSession = function() {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['login_timedout'],
+      success: function(response) {
+        if (response.login.locked) {
+          if (!LoginRefresh.backendIsLocked) {
+            LoginRefresh.backendIsLocked = true;
+            LoginRefresh.showBackendLockedModal();
+          }
+        } else {
+          if (LoginRefresh.backendIsLocked) {
+            LoginRefresh.backendIsLocked = false;
+            LoginRefresh.hideBackendLockedModal();
+          }
+        }
+
+        if (!LoginRefresh.backendIsLocked) {
+          if (response.login.timed_out || response.login.will_time_out) {
+            if (response.login.timed_out) {
+              LoginRefresh.showLoginForm();
+            } else {
+              LoginRefresh.showTimeoutModal();
+            }
+          }
+        }
+      }
+    });
+  };
+
+  LoginRefresh.initialize = function() {
+    LoginRefresh.initializeTimeoutModal();
+    LoginRefresh.initializeBackendLockedModal();
+    LoginRefresh.initializeLoginForm();
+
+    LoginRefresh.startTask();
+
+    if (typeof Notification !== 'undefined' && Notification.permission !== 'granted') {
+      Notification.requestPermission();
+    }
+  };
+
+  // expose to global
+  TYPO3.LoginRefresh = LoginRefresh;
+
+  return LoginRefresh;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js
index 03648fbc1d2c..ba37686c98f0 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js
@@ -16,445 +16,451 @@
  * API for modal windows powered by Twitter Bootstrap.
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/Severity',
-		'TYPO3/CMS/Backend/Icons',
-		'bootstrap'
-	   ], function($, Severity, Icons) {
-	'use strict';
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Icons',
+  'bootstrap'
+], function($, Severity, Icons) {
+  'use strict';
 
-	try {
-		// fetch from parent
-		if (parent && parent.window.TYPO3 && parent.window.TYPO3.Modal) {
-			// we need to trigger the event capturing again, in order to make sure this works inside iframes
-			parent.window.TYPO3.Modal.initializeMarkupTrigger(document);
-			return parent.window.TYPO3.Modal;
-		}
+  try {
+    // fetch from parent
+    if (parent && parent.window.TYPO3 && parent.window.TYPO3.Modal) {
+      // we need to trigger the event capturing again, in order to make sure this works inside iframes
+      parent.window.TYPO3.Modal.initializeMarkupTrigger(document);
+      return parent.window.TYPO3.Modal;
+    }
 
-		// fetch object from outer frame
-		if (top && top.TYPO3.Modal) {
-			// we need to trigger the event capturing again, in order to make sure this works inside iframes
-			top.TYPO3.Modal.initializeMarkupTrigger(document);
-			return top.TYPO3.Modal;
-		}
-	} catch (e) {
-		// This only happens if the opener, parent or top is some other url (eg a local file)
-		// which loaded the current window. Then the browser's cross domain policy jumps in
-		// and raises an exception.
-		// For this case we are safe and we can create our global object below.
-	}
+    // fetch object from outer frame
+    if (top && top.TYPO3.Modal) {
+      // we need to trigger the event capturing again, in order to make sure this works inside iframes
+      top.TYPO3.Modal.initializeMarkupTrigger(document);
+      return top.TYPO3.Modal;
+    }
+  } catch (e) {
+    // This only happens if the opener, parent or top is some other url (eg a local file)
+    // which loaded the current window. Then the browser's cross domain policy jumps in
+    // and raises an exception.
+    // For this case we are safe and we can create our global object below.
+  }
 
-	/**
-	 * The main object of the modal API
-	 *
-	 * @type {{instances: Array, currentModal: null, template: (*), identifiers: {modal: string, content: string, title: string, close: string, body: string, footer: string, iframe: string, iconPlaceholder: string}, sizes: {small: string, default: string, large: string, full: string}, styles: {default: string, light: string, dark: string}, types: {default: string, ajax: string, iframe: string}, defaultConfiguration: {type: string, title: string, content: string, severity: number, buttons: Array, style: string, size: string, additionalCssClasses: Array, callback: Modal.defaultConfiguration.callback, ajaxCallback: Modal.defaultConfiguration.ajaxCallback, ajaxTarget: null}}}
-	 * @exports TYPO3/CMS/Backend/Modal
-	 */
-	var Modal = {
-		instances: [],
-		currentModal: null,
-		template: $(
-			'<div class="t3js-modal modal fade">' +
-				'<div class="modal-dialog">' +
-					'<div class="t3js-modal-content modal-content">' +
-						'<div class="modal-header">' +
-							'<button class="t3js-modal-close close">' +
-								'<span aria-hidden="true">' +
-									'<span class="t3js-modal-icon-placeholder" data-icon="actions-close"></span>' +
-								'</span>' +
-								'<span class="sr-only"></span>' +
-							'</button>' +
-							'<h4 class="t3js-modal-title modal-title"></h4>' +
-						'</div>' +
-						'<div class="t3js-modal-body modal-body"></div>' +
-						'<div class="t3js-modal-footer modal-footer"></div>' +
-					'</div>' +
-				'</div>' +
-			'</div>'
-		),
-		identifiers: {
-			modal: '.t3js-modal',
-			content: '.t3js-modal-content',
-			title: '.t3js-modal-title',
-			close: '.t3js-modal-close',
-			body: '.t3js-modal-body',
-			footer: '.t3js-modal-footer',
-			iframe: '.t3js-modal-iframe',
-			iconPlaceholder: '.t3js-modal-icon-placeholder'
-		},
-		sizes: {
-			small: 'small',
-			default: 'default',
-			medium: 'medium',
-			large: 'large',
-			full: 'full'
-		},
-		styles: {
-			default: 'light',
-			light: 'light',
-			dark: 'dark'
-		},
-		types: {
-			default: 'default',
-			ajax: 'ajax',
-			iframe: 'iframe'
-		},
-		defaultConfiguration: {
-			type: 'default',
-			title: 'Information',
-			content: 'No content provided, please check your <code>Modal</code> configuration.',
-			severity: Severity.notice,
-			buttons: [],
-			style: 'default',
-			size: 'default',
-			additionalCssClasses: [],
-			callback: function(){ },
-			ajaxCallback: function(){ },
-			ajaxTarget: null
-		}
-	};
+  /**
+   * The main object of the modal API
+   *
+   * @type {{instances: Array, currentModal: null, template: (*), identifiers: {modal: string, content: string, title: string, close: string, body: string, footer: string, iframe: string, iconPlaceholder: string}, sizes: {small: string, default: string, large: string, full: string}, styles: {default: string, light: string, dark: string}, types: {default: string, ajax: string, iframe: string}, defaultConfiguration: {type: string, title: string, content: string, severity: number, buttons: Array, style: string, size: string, additionalCssClasses: Array, callback: Modal.defaultConfiguration.callback, ajaxCallback: Modal.defaultConfiguration.ajaxCallback, ajaxTarget: null}}}
+   * @exports TYPO3/CMS/Backend/Modal
+   */
+  var Modal = {
+    instances: [],
+    currentModal: null,
+    template: $(
+      '<div class="t3js-modal modal fade">' +
+      '<div class="modal-dialog">' +
+      '<div class="t3js-modal-content modal-content">' +
+      '<div class="modal-header">' +
+      '<button class="t3js-modal-close close">' +
+      '<span aria-hidden="true">' +
+      '<span class="t3js-modal-icon-placeholder" data-icon="actions-close"></span>' +
+      '</span>' +
+      '<span class="sr-only"></span>' +
+      '</button>' +
+      '<h4 class="t3js-modal-title modal-title"></h4>' +
+      '</div>' +
+      '<div class="t3js-modal-body modal-body"></div>' +
+      '<div class="t3js-modal-footer modal-footer"></div>' +
+      '</div>' +
+      '</div>' +
+      '</div>'
+    ),
+    identifiers: {
+      modal: '.t3js-modal',
+      content: '.t3js-modal-content',
+      title: '.t3js-modal-title',
+      close: '.t3js-modal-close',
+      body: '.t3js-modal-body',
+      footer: '.t3js-modal-footer',
+      iframe: '.t3js-modal-iframe',
+      iconPlaceholder: '.t3js-modal-icon-placeholder'
+    },
+    sizes: {
+      small: 'small',
+      default: 'default',
+      medium: 'medium',
+      large: 'large',
+      full: 'full'
+    },
+    styles: {
+      default: 'light',
+      light: 'light',
+      dark: 'dark'
+    },
+    types: {
+      default: 'default',
+      ajax: 'ajax',
+      iframe: 'iframe'
+    },
+    defaultConfiguration: {
+      type: 'default',
+      title: 'Information',
+      content: 'No content provided, please check your <code>Modal</code> configuration.',
+      severity: Severity.notice,
+      buttons: [],
+      style: 'default',
+      size: 'default',
+      additionalCssClasses: [],
+      callback: function() {
+      },
+      ajaxCallback: function() {
+      },
+      ajaxTarget: null
+    }
+  };
 
-	/**
-	 * Shows a confirmation dialog
-	 * Events:
-	 * - button.clicked
-	 * - confirm.button.cancel
-	 * - confirm.button.ok
-	 *
-	 * @param {String} title the title for the confirm modal
-	 * @param {*} content the content for the conform modal, e.g. the main question
-	 * @param {int} [severity=Severity.warning] severity default Severity.warning
-	 * @param {array} [buttons] an array with buttons, default no buttons
-	 * @param {array} [additionalCssClasses=''] additional css classes to add to the modal
-	 */
-	Modal.confirm = function(title, content, severity, buttons, additionalCssClasses) {
-		severity = typeof severity !== 'undefined' ? severity : Severity.warning;
+  /**
+   * Shows a confirmation dialog
+   * Events:
+   * - button.clicked
+   * - confirm.button.cancel
+   * - confirm.button.ok
+   *
+   * @param {String} title the title for the confirm modal
+   * @param {*} content the content for the conform modal, e.g. the main question
+   * @param {int} [severity=Severity.warning] severity default Severity.warning
+   * @param {array} [buttons] an array with buttons, default no buttons
+   * @param {array} [additionalCssClasses=''] additional css classes to add to the modal
+   */
+  Modal.confirm = function(title, content, severity, buttons, additionalCssClasses) {
+    severity = typeof severity !== 'undefined' ? severity : Severity.warning;
 
-		return Modal.advanced(
-			{
-				title: title,
-				content: content,
-				severity: severity,
-				buttons: buttons || [
-					{
-						text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-						active: true,
-						btnClass: 'btn-default',
-						name: 'cancel'
-					},
-					{
-						text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
-						btnClass: 'btn-' + Severity.getCssClass(severity),
-						name: 'ok'
-					}
-				],
-				additionalCssClasses: additionalCssClasses || [],
-				callback: function(currentModal) {
-					currentModal.on('button.clicked', function(e) {
-						if (e.target.name === 'cancel') {
-							$(this).trigger('confirm.button.cancel');
-						} else if (e.target.name === 'ok') {
-							$(this).trigger('confirm.button.ok');
-						}
-					});
-				}
-			}
-		);
-	};
+    return Modal.advanced(
+      {
+        title: title,
+        content: content,
+        severity: severity,
+        buttons: buttons || [
+          {
+            text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+            active: true,
+            btnClass: 'btn-default',
+            name: 'cancel'
+          },
+          {
+            text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
+            btnClass: 'btn-' + Severity.getCssClass(severity),
+            name: 'ok'
+          }
+        ],
+        additionalCssClasses: additionalCssClasses || [],
+        callback: function(currentModal) {
+          currentModal.on('button.clicked', function(e) {
+            if (e.target.name === 'cancel') {
+              $(this).trigger('confirm.button.cancel');
+            } else if (e.target.name === 'ok') {
+              $(this).trigger('confirm.button.ok');
+            }
+          });
+        }
+      }
+    );
+  };
 
-	/**
-	 * load URL with AJAX, append the content to the modal-body
-	 * and trigger the callback
-	 *
-	 * @param {String} title
-	 * @param {int} severity
-	 * @param {array} buttons
-	 * @param {String} url
-	 * @param {function} callback
-	 * @param {String} target
-	 */
-	Modal.loadUrl = function(title, severity, buttons, url, callback, target) {
-		return Modal.advanced({
-			type: Modal.types.ajax,
-			title: title,
-			content: url,
-			severity: typeof severity !== 'undefined' ? severity : Severity.info,
-			buttons: buttons,
-			ajaxCallback: callback,
-			ajaxTarget: target
-		});
-	};
+  /**
+   * load URL with AJAX, append the content to the modal-body
+   * and trigger the callback
+   *
+   * @param {String} title
+   * @param {int} severity
+   * @param {array} buttons
+   * @param {String} url
+   * @param {function} callback
+   * @param {String} target
+   */
+  Modal.loadUrl = function(title, severity, buttons, url, callback, target) {
+    return Modal.advanced({
+      type: Modal.types.ajax,
+      title: title,
+      content: url,
+      severity: typeof severity !== 'undefined' ? severity : Severity.info,
+      buttons: buttons,
+      ajaxCallback: callback,
+      ajaxTarget: target
+    });
+  };
 
-	/**
-	 * Shows a dialog
-	 *
-	 * @param {String} title the title for the modal
-	 * @param {*} content the content for the modal, e.g. the main question
-	 * @param {int} severity default Severity.info
-	 * @param {array} buttons an array with buttons, default no buttons
-	 * @param {array} additionalCssClasses additional css classes to add to the modal
-	 */
-	Modal.show = function(title, content, severity, buttons, additionalCssClasses) {
-		return Modal.advanced({
-			type: Modal.types.default,
-			title: title,
-			content: content,
-			severity: typeof severity !== 'undefined' ? severity : Severity.info,
-			buttons: buttons,
-			additionalCssClasses: additionalCssClasses
-		});
-	};
+  /**
+   * Shows a dialog
+   *
+   * @param {String} title the title for the modal
+   * @param {*} content the content for the modal, e.g. the main question
+   * @param {int} severity default Severity.info
+   * @param {array} buttons an array with buttons, default no buttons
+   * @param {array} additionalCssClasses additional css classes to add to the modal
+   */
+  Modal.show = function(title, content, severity, buttons, additionalCssClasses) {
+    return Modal.advanced({
+      type: Modal.types.default,
+      title: title,
+      content: content,
+      severity: typeof severity !== 'undefined' ? severity : Severity.info,
+      buttons: buttons,
+      additionalCssClasses: additionalCssClasses
+    });
+  };
 
-	/**
-	 * Loads modal by configuration
-	 *
-	 * @param {object} configuration configuration for the modal
-	 */
-	Modal.advanced = function(configuration) {
-		if (typeof configuration !== 'object') {
-			configuration = {};
-		}
+  /**
+   * Loads modal by configuration
+   *
+   * @param {object} configuration configuration for the modal
+   */
+  Modal.advanced = function(configuration) {
+    if (typeof configuration !== 'object') {
+      configuration = {};
+    }
 
-		// Validation of configuration
-		configuration.type = typeof configuration.type === 'string' && configuration.type in Modal.types ? configuration.type : Modal.defaultConfiguration.type;
-		configuration.title = typeof configuration.title === 'string' ? configuration.title : Modal.defaultConfiguration.title;
-		configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object' ? configuration.content : Modal.defaultConfiguration.content;
-		configuration.severity = typeof configuration.severity !== 'undefined' ? configuration.severity : Modal.defaultConfiguration.severity;
-		configuration.buttons = configuration.buttons || Modal.defaultConfiguration.buttons;
-		configuration.size = typeof configuration.size === 'string' && configuration.size in Modal.sizes ? configuration.size : Modal.defaultConfiguration.size;
-		configuration.style = typeof configuration.style === 'string' && configuration.style in Modal.styles ? configuration.style : Modal.defaultConfiguration.style;
-		configuration.additionalCssClasses = configuration.additionalCssClasses || Modal.defaultConfiguration.additionalCssClasses;
-		configuration.callback = typeof configuration.callback === 'function' ? configuration.callback : Modal.defaultConfiguration.callback;
-		configuration.ajaxCallback = typeof configuration.ajaxCallback === 'function' ? configuration.ajaxCallback :  Modal.defaultConfiguration.ajaxCallback;
-		configuration.ajaxTarget = typeof configuration.ajaxTarget === 'string' ? configuration.ajaxTarget : Modal.defaultConfiguration.ajaxTarget;
+    // Validation of configuration
+    configuration.type = typeof configuration.type === 'string' && configuration.type in Modal.types ? configuration.type : Modal.defaultConfiguration.type;
+    configuration.title = typeof configuration.title === 'string' ? configuration.title : Modal.defaultConfiguration.title;
+    configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object' ? configuration.content : Modal.defaultConfiguration.content;
+    configuration.severity = typeof configuration.severity !== 'undefined' ? configuration.severity : Modal.defaultConfiguration.severity;
+    configuration.buttons = configuration.buttons || Modal.defaultConfiguration.buttons;
+    configuration.size = typeof configuration.size === 'string' && configuration.size in Modal.sizes ? configuration.size : Modal.defaultConfiguration.size;
+    configuration.style = typeof configuration.style === 'string' && configuration.style in Modal.styles ? configuration.style : Modal.defaultConfiguration.style;
+    configuration.additionalCssClasses = configuration.additionalCssClasses || Modal.defaultConfiguration.additionalCssClasses;
+    configuration.callback = typeof configuration.callback === 'function' ? configuration.callback : Modal.defaultConfiguration.callback;
+    configuration.ajaxCallback = typeof configuration.ajaxCallback === 'function' ? configuration.ajaxCallback : Modal.defaultConfiguration.ajaxCallback;
+    configuration.ajaxTarget = typeof configuration.ajaxTarget === 'string' ? configuration.ajaxTarget : Modal.defaultConfiguration.ajaxTarget;
 
-		return Modal._generate(
-			configuration.type,
-			configuration.title,
-			configuration.content,
-			configuration.severity,
-			configuration.buttons,
-			configuration.style,
-			configuration.size,
-			configuration.additionalCssClasses,
-			configuration.callback,
-			configuration.ajaxCallback,
-			configuration.ajaxTarget
-		);
-	};
+    return Modal._generate(
+      configuration.type,
+      configuration.title,
+      configuration.content,
+      configuration.severity,
+      configuration.buttons,
+      configuration.style,
+      configuration.size,
+      configuration.additionalCssClasses,
+      configuration.callback,
+      configuration.ajaxCallback,
+      configuration.ajaxTarget
+    );
+  };
 
-	/**
-	 * Generate the modal window
-	 * Events:
-	 * - button.clicked
-	 *
-	 * @param {String} type the type of the modal
-	 * @param {String} title the title for the modal
-	 * @param {*} content the content for the modal, e.g. the main question
-	 * @param {int} severity default Severity.info
-	 * @param {array} buttons an array with buttons, default no buttons
-	 * @param {String} style the style of the modal window
-	 * @param {String} size the size of the modal window
-	 * @param {array} additionalCssClasses additional css classes to add to the modal
-	 * @param {function} callback
-	 * @param {function} ajaxCallback
-	 * @param {String} ajaxTarget
-	 * @private
-	 */
-	Modal._generate = function(type, title, content, severity, buttons, style, size, additionalCssClasses, callback, ajaxCallback, ajaxTarget) {
-		var currentModal = Modal.template.clone();
-		if (additionalCssClasses.length) {
-			for (var i = 0; i < additionalCssClasses.length; i++) {
-				currentModal.addClass(additionalCssClasses[i]);
-			}
-		}
-		currentModal.addClass('modal-type-' + Modal.types[type]);
-		currentModal.addClass('modal-severity-' + Severity.getCssClass(severity));
-		currentModal.addClass('modal-style-' + Modal.styles[style]);
-		currentModal.addClass('modal-size-' + Modal.sizes[size]);
-		currentModal.attr('tabindex', '-1');
-		currentModal.find(Modal.identifiers.title).text(title);
-		currentModal.find(Modal.identifiers.close).on('click', function() {
-			currentModal.modal('hide');
-		});
+  /**
+   * Generate the modal window
+   * Events:
+   * - button.clicked
+   *
+   * @param {String} type the type of the modal
+   * @param {String} title the title for the modal
+   * @param {*} content the content for the modal, e.g. the main question
+   * @param {int} severity default Severity.info
+   * @param {array} buttons an array with buttons, default no buttons
+   * @param {String} style the style of the modal window
+   * @param {String} size the size of the modal window
+   * @param {array} additionalCssClasses additional css classes to add to the modal
+   * @param {function} callback
+   * @param {function} ajaxCallback
+   * @param {String} ajaxTarget
+   * @private
+   */
+  Modal._generate = function(type, title, content, severity, buttons, style, size, additionalCssClasses, callback, ajaxCallback, ajaxTarget) {
+    var currentModal = Modal.template.clone();
+    if (additionalCssClasses.length) {
+      for (var i = 0; i < additionalCssClasses.length; i++) {
+        currentModal.addClass(additionalCssClasses[i]);
+      }
+    }
+    currentModal.addClass('modal-type-' + Modal.types[type]);
+    currentModal.addClass('modal-severity-' + Severity.getCssClass(severity));
+    currentModal.addClass('modal-style-' + Modal.styles[style]);
+    currentModal.addClass('modal-size-' + Modal.sizes[size]);
+    currentModal.attr('tabindex', '-1');
+    currentModal.find(Modal.identifiers.title).text(title);
+    currentModal.find(Modal.identifiers.close).on('click', function() {
+      currentModal.modal('hide');
+    });
 
-		// Add content
-		if (type === 'ajax') {
-			$.get(content, function(response) {
-				Modal.currentModal.find(ajaxTarget ? ajaxTarget : Modal.identifiers.body).empty().append(response);
-				if (ajaxCallback) {
-					ajaxCallback();
-				}
-				Modal.currentModal.trigger('modal-loaded');
-			}, 'html');
-			Icons.getIcon('spinner-circle', Icons.sizes.default, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
-				currentModal.find(Modal.identifiers.body).html('<div class="modal-loading">' + icon + '</div>');
-			});
-		} else if (type === 'iframe') {
-			currentModal.find(Modal.identifiers.body).append(
-				$('<iframe />', { src: content, 'name': 'modal_frame', 'class': 'modal-iframe t3js-modal-iframe' })
-			);
-			currentModal.find(Modal.identifiers.iframe).on('load',function() {
-				currentModal.find(Modal.identifiers.title).text(
-					currentModal.find(Modal.identifiers.iframe).get(0).contentDocument.title
-				);
-  			});
-		} else {
-			if (typeof content === 'object') {
-				currentModal.find(Modal.identifiers.body).append(content);
-			} else {
-				// we need html, check if we have to wrap content in <p>
-				if (!/^<[a-z][\s\S]*>/i.test(content)) {
-					content = $('<p />').html(content);
-				}
-				currentModal.find(Modal.identifiers.body).html(content);
-			}
-		}
+    // Add content
+    if (type === 'ajax') {
+      $.get(content, function(response) {
+        Modal.currentModal.find(ajaxTarget ? ajaxTarget : Modal.identifiers.body).empty().append(response);
+        if (ajaxCallback) {
+          ajaxCallback();
+        }
+        Modal.currentModal.trigger('modal-loaded');
+      }, 'html');
+      Icons.getIcon('spinner-circle', Icons.sizes.default, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
+        currentModal.find(Modal.identifiers.body).html('<div class="modal-loading">' + icon + '</div>');
+      });
+    } else if (type === 'iframe') {
+      currentModal.find(Modal.identifiers.body).append(
+        $('<iframe />', {
+          src: content,
+          'name': 'modal_frame',
+          'class': 'modal-iframe t3js-modal-iframe'
+        })
+      );
+      currentModal.find(Modal.identifiers.iframe).on('load', function() {
+        currentModal.find(Modal.identifiers.title).text(
+          currentModal.find(Modal.identifiers.iframe).get(0).contentDocument.title
+        );
+      });
+    } else {
+      if (typeof content === 'object') {
+        currentModal.find(Modal.identifiers.body).append(content);
+      } else {
+        // we need html, check if we have to wrap content in <p>
+        if (!/^<[a-z][\s\S]*>/i.test(content)) {
+          content = $('<p />').html(content);
+        }
+        currentModal.find(Modal.identifiers.body).html(content);
+      }
+    }
 
-		// Add buttons
-		if (buttons.length > 0) {
-			for (i = 0; i<buttons.length; i++) {
-				var button = buttons[i];
-				var $button = $('<button />', {class: 'btn'});
-				$button.html('<span>' + button.text + '</span>');
-				if (button.active) {
-					$button.addClass('t3js-active');
-				}
-				if (button.btnClass) {
-					$button.addClass(button.btnClass);
-				}
-				if (button.name) {
-					$button.attr('name', button.name);
-				}
-				if (button.trigger) {
-					$button.on('click', button.trigger);
-				}
-				if (button.dataAttributes) {
-					if (Object.keys(button.dataAttributes).length > 0) {
-						Object.keys(button.dataAttributes).map(function(key, index) {
-							$button.attr('data-' + key, button.dataAttributes[key]);
-						});
-					}
-				}
-				if (button.icon) {
-					$button.prepend('<span class="t3js-modal-icon-placeholder" data-icon="' + button.icon + '"></span>');
-				}
-				currentModal.find(Modal.identifiers.footer).append($button);
-			}
-			currentModal
-				.find(Modal.identifiers.footer).find('button')
-				.on('click', function() {
-					$(this).trigger('button.clicked');
-				});
+    // Add buttons
+    if (buttons.length > 0) {
+      for (i = 0; i < buttons.length; i++) {
+        var button = buttons[i];
+        var $button = $('<button />', {class: 'btn'});
+        $button.html('<span>' + button.text + '</span>');
+        if (button.active) {
+          $button.addClass('t3js-active');
+        }
+        if (button.btnClass) {
+          $button.addClass(button.btnClass);
+        }
+        if (button.name) {
+          $button.attr('name', button.name);
+        }
+        if (button.trigger) {
+          $button.on('click', button.trigger);
+        }
+        if (button.dataAttributes) {
+          if (Object.keys(button.dataAttributes).length > 0) {
+            Object.keys(button.dataAttributes).map(function(key, index) {
+              $button.attr('data-' + key, button.dataAttributes[key]);
+            });
+          }
+        }
+        if (button.icon) {
+          $button.prepend('<span class="t3js-modal-icon-placeholder" data-icon="' + button.icon + '"></span>');
+        }
+        currentModal.find(Modal.identifiers.footer).append($button);
+      }
+      currentModal
+        .find(Modal.identifiers.footer).find('button')
+        .on('click', function() {
+          $(this).trigger('button.clicked');
+        });
 
-		} else {
-			currentModal.find(Modal.identifiers.footer).remove();
-		}
+    } else {
+      currentModal.find(Modal.identifiers.footer).remove();
+    }
 
-		currentModal.on('shown.bs.modal', function() {
-			// focus the button which was configured as active button
-			$(this).find(Modal.identifiers.footer).find('.t3js-active').first().focus();
-			// Get Icons
-			$(this).find(Modal.identifiers.iconPlaceholder).each(function() {
-				Icons.getIcon($(this).data('icon'), Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
-					Modal.currentModal.find(Modal.identifiers.iconPlaceholder + '[data-icon=' + $(icon).data('identifier') + ']').replaceWith(icon);
-				});
-			});
-		});
+    currentModal.on('shown.bs.modal', function() {
+      // focus the button which was configured as active button
+      $(this).find(Modal.identifiers.footer).find('.t3js-active').first().focus();
+      // Get Icons
+      $(this).find(Modal.identifiers.iconPlaceholder).each(function() {
+        Icons.getIcon($(this).data('icon'), Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
+          Modal.currentModal.find(Modal.identifiers.iconPlaceholder + '[data-icon=' + $(icon).data('identifier') + ']').replaceWith(icon);
+        });
+      });
+    });
 
-		// Remove modal from Modal.instances when hidden
-		currentModal.on('hidden.bs.modal', function() {
-			if (Modal.instances.length > 0) {
-				var lastIndex = Modal.instances.length-1;
-				Modal.instances.splice(lastIndex, 1);
-				Modal.currentModal = Modal.instances[lastIndex-1];
-			}
-			currentModal.trigger('modal-destroyed');
-			$(this).remove();
-			// Keep class modal-open on body tag as long as open modals exist
-			if (Modal.instances.length > 0) {
-				$('body').addClass('modal-open');
-			}
-		});
+    // Remove modal from Modal.instances when hidden
+    currentModal.on('hidden.bs.modal', function() {
+      if (Modal.instances.length > 0) {
+        var lastIndex = Modal.instances.length - 1;
+        Modal.instances.splice(lastIndex, 1);
+        Modal.currentModal = Modal.instances[lastIndex - 1];
+      }
+      currentModal.trigger('modal-destroyed');
+      $(this).remove();
+      // Keep class modal-open on body tag as long as open modals exist
+      if (Modal.instances.length > 0) {
+        $('body').addClass('modal-open');
+      }
+    });
 
-		// When modal is opened/shown add it to Modal.instances and make it Modal.currentModal
-		currentModal.on('show.bs.modal', function() {
-			Modal.currentModal = $(this);
-			Modal.instances.push(Modal.currentModal);
-		});
-		currentModal.on('modal-dismiss', function() {
-			// Hide modal, the bs.modal events will clean up Modal.instances
-			$(this).modal('hide');
-		});
+    // When modal is opened/shown add it to Modal.instances and make it Modal.currentModal
+    currentModal.on('show.bs.modal', function() {
+      Modal.currentModal = $(this);
+      Modal.instances.push(Modal.currentModal);
+    });
+    currentModal.on('modal-dismiss', function() {
+      // Hide modal, the bs.modal events will clean up Modal.instances
+      $(this).modal('hide');
+    });
 
-		if (callback) {
-			callback(currentModal);
-		}
+    if (callback) {
+      callback(currentModal);
+    }
 
-		return currentModal.modal();
-	};
+    return currentModal.modal();
+  };
 
-	/**
-	 * Close the current open modal
-	 */
-	Modal.dismiss = function() {
-		if (Modal.currentModal) {
-			Modal.currentModal.modal('hide');
-		}
-	};
+  /**
+   * Close the current open modal
+   */
+  Modal.dismiss = function() {
+    if (Modal.currentModal) {
+      Modal.currentModal.modal('hide');
+    }
+  };
 
-	/**
-	 * Initialize markup with data attributes
-	 *
-	 * @param {object} theDocument
-	 */
-	Modal.initializeMarkupTrigger = function(theDocument) {
-		$(theDocument).on('click', '.t3js-modal-trigger', function(evt) {
-			evt.preventDefault();
-			var $element = $(this);
-			var url = $element.data('url') || null;
-			var content = $element.data('content') || 'Are you sure?';
-			var severity = typeof Severity[$element.data('severity')] !== 'undefined' ? Severity[$element.data('severity')] : Severity.info;
-			if (url !== null) {
-				var separator = (url.indexOf('?') > -1) ? '&' : '?';
-				var params = $.param({data: $element.data()});
-				url = url + separator + params;
-			}
-			Modal.advanced({
-				type: url !== null ? Modal.types.ajax : Modal.types.default,
-				title: $element.data('title') || 'Alert',
-				content: url !== null ? url : content,
-				severity: severity,
-				buttons: [
-					{
-						text: $element.data('button-close-text') || 'Close',
-						active: true,
-						btnClass: 'btn-default',
-						trigger: function() {
-							Modal.currentModal.trigger('modal-dismiss');
-						}
-					},
-					{
-						text: $element.data('button-ok-text') || 'OK',
-						btnClass: 'btn-' + Severity.getCssClass(severity),
-						trigger: function() {
-							Modal.currentModal.trigger('modal-dismiss');
-							evt.target.ownerDocument.location.href = $element.data('href') || $element.attr('href');
-						}
-					}
-				]
-			});
-		});
-	};
+  /**
+   * Initialize markup with data attributes
+   *
+   * @param {object} theDocument
+   */
+  Modal.initializeMarkupTrigger = function(theDocument) {
+    $(theDocument).on('click', '.t3js-modal-trigger', function(evt) {
+      evt.preventDefault();
+      var $element = $(this);
+      var url = $element.data('url') || null;
+      var content = $element.data('content') || 'Are you sure?';
+      var severity = typeof Severity[$element.data('severity')] !== 'undefined' ? Severity[$element.data('severity')] : Severity.info;
+      if (url !== null) {
+        var separator = (url.indexOf('?') > -1) ? '&' : '?';
+        var params = $.param({data: $element.data()});
+        url = url + separator + params;
+      }
+      Modal.advanced({
+        type: url !== null ? Modal.types.ajax : Modal.types.default,
+        title: $element.data('title') || 'Alert',
+        content: url !== null ? url : content,
+        severity: severity,
+        buttons: [
+          {
+            text: $element.data('button-close-text') || 'Close',
+            active: true,
+            btnClass: 'btn-default',
+            trigger: function() {
+              Modal.currentModal.trigger('modal-dismiss');
+            }
+          },
+          {
+            text: $element.data('button-ok-text') || 'OK',
+            btnClass: 'btn-' + Severity.getCssClass(severity),
+            trigger: function() {
+              Modal.currentModal.trigger('modal-dismiss');
+              evt.target.ownerDocument.location.href = $element.data('href') || $element.attr('href');
+            }
+          }
+        ]
+      });
+    });
+  };
 
-	/**
-	 * Custom event, fired if modal gets closed
-	 */
-	$(document).on('modal-dismiss', Modal.dismiss);
+  /**
+   * Custom event, fired if modal gets closed
+   */
+  $(document).on('modal-dismiss', Modal.dismiss);
 
-	Modal.initializeMarkupTrigger(document);
+  Modal.initializeMarkupTrigger(document);
 
-	// expose as global object
-	TYPO3.Modal = Modal;
+  // expose as global object
+  TYPO3.Modal = Modal;
 
-	return Modal;
+  return Modal;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js
index 90e2371d250a..94e94a2f369c 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ModuleMenu.js
@@ -16,413 +16,413 @@
  * Class to render the module menu and handle the BE navigation
  */
 require(
-	[
-		'jquery',
-		'TYPO3/CMS/Backend/Storage/Persistent',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/Viewport',
-		'TYPO3/CMS/Backend/Event/ClientRequest',
-		'TYPO3/CMS/Backend/Event/TriggerRequest'
-	],
-	function ($, PersistentStorage, Icons, Viewport, ClientRequest, TriggerRequest) {
-		if (typeof TYPO3.ModuleMenu !== 'undefined') {
-			return TYPO3.ModuleMenu.App;
-		}
-
-		TYPO3.ModuleMenu = {};
-		TYPO3.ModuleMenu.App = {
-			loadedModule: null,
-			loadedNavigationComponentId: '',
-
-			initialize: function () {
-				var me = this;
-
-				var deferred = $.Deferred();
-				deferred.resolve();
-
-				// load the start module
-				if (top.startInModule && top.startInModule[0] && $('#' + top.startInModule[0]).length > 0) {
-					deferred = me.showModule(
-						top.startInModule[0],
-						top.startInModule[1]
-					);
-				} else {
-					// fetch first module
-					if ($('.t3js-mainmodule:first').attr('id')) {
-						deferred = me.showModule(
-							$('.t3js-mainmodule:first').attr('id')
-						);
-					}
-					// else case: the main module has no entries, this is probably a backend
-					// user with very little access rights, maybe only the logout button and
-					// a user settings module in topbar.
-				}
-
-				deferred.then(function() {
-					// check if module menu should be collapsed or not
-					var state = PersistentStorage.get('BackendComponents.States.typo3-module-menu');
-					if (state && state.collapsed) {
-						TYPO3.ModuleMenu.App.toggleMenu(state.collapsed === 'true');
-					}
-
-					// check if there are collapsed items in the users' configuration
-					var collapsedMainMenuItems = me.getCollapsedMainMenuItems();
-					$.each(collapsedMainMenuItems, function (key, itm) {
-						if (itm !== true) {
-							return;
-						}
-						var $group = $('#' + key);
-						if ($group.length > 0) {
-							var $groupContainer = $group.find('.modulemenu-group-container');
-							$group.addClass('collapsed').removeClass('expanded');
-							TYPO3.Backend.NavigationContainer.cleanup();
-							$groupContainer.hide().promise().done(function () {
-								TYPO3.Backend.doLayout();
-							});
-						}
-					});
-					me.initializeEvents();
-				});
-			},
-
-			initializeEvents: function () {
-				var me = this;
-				$(document).on('click', '.modulemenu-group .modulemenu-group-header', function () {
-					var $group = $(this).parent('.modulemenu-group');
-					var $groupContainer = $group.find('.modulemenu-group-container');
-
-					TYPO3.Backend.NavigationContainer.cleanup();
-					if ($group.hasClass('expanded')) {
-						me.addCollapsedMainMenuItem($group.attr('id'));
-						$group.addClass('collapsed').removeClass('expanded');
-						$groupContainer.stop().slideUp().promise().done(function () {
-							TYPO3.Backend.doLayout();
-						});
-					} else {
-						me.removeCollapseMainMenuItem($group.attr('id'));
-						$group.addClass('expanded').removeClass('collapsed');
-						$groupContainer.stop().slideDown().promise().done(function () {
-							TYPO3.Backend.doLayout();
-						});
-					}
-
-				});
-				// register clicking on sub modules
-				$(document).on('click', '.modulemenu-item,.t3-menuitem-submodule', function (evt) {
-					evt.preventDefault();
-					me.showModule(
-						$(this).attr('id'),
-						'',
-						evt
-					);
-				});
-				$(document).on('click', '.t3js-topbar-button-modulemenu',
-					function (evt) {
-						evt.preventDefault();
-						TYPO3.ModuleMenu.App.toggleMenu();
-					}
-				);
-				$(document).on('click', '.t3js-scaffold-content-overlay',
-					function (evt) {
-						evt.preventDefault();
-						TYPO3.ModuleMenu.App.toggleMenu(true);
-					}
-				);
-				$(document).on('click', '.t3js-topbar-button-navigationcomponent',
-					function (evt) {
-						evt.preventDefault();
-						TYPO3.Backend.NavigationContainer.toggle();
-					}
-				);
-			},
-
-			/**
-			 * @param {Boolean} collapse
-			 */
-			toggleMenu: function (collapse) {
-				TYPO3.Backend.NavigationContainer.cleanup();
-
-				var $mainContainer = $('.t3js-scaffold');
-				var expandedClass = 'scaffold-modulemenu-expanded';
-
-				if (typeof collapse === 'undefined') {
-					collapse = $mainContainer.hasClass(expandedClass);
-				}
-				$mainContainer.toggleClass(expandedClass, !collapse);
-				if (!collapse) {
-					$('.scaffold')
-						.removeClass('scaffold-search-expanded')
-						.removeClass('scaffold-toolbar-expanded');
-				}
-
-				// Persist collapsed state in the UC of the current user
-				PersistentStorage.set(
-					'BackendComponents.States.typo3-module-menu',
-					{
-						collapsed: collapse
-					}
-				);
-
-				TYPO3.Backend.doLayout();
-			},
-
-			/**
-			 * Gets the module properties from module menu markup (data attributes)
-			 *
-			 * @param {string} name module name e.g. web_list
-			 * @return {Object}
-			 */
-			getRecordFromName: function (name) {
-				var $subModuleElement = $('#' + name);
-				return {
-					name: name,
-					navigationComponentId: $subModuleElement.data('navigationcomponentid'),
-					navigationFrameScript: $subModuleElement.data('navigationframescript'),
-					navigationFrameScriptParam: $subModuleElement.data('navigationframescriptparameters'),
-					link: $subModuleElement.find('a').data('link')
-				};
-			},
-
-			/**
-			 * Event handler called after clicking on the module menu item
-			 *
-			 * @param {string} name module name e.g. web_layout
-			 * @param {string} params
-			 * @param {Event} [event]
-			 * @return {jQuery.Deferred}
-			 */
-			showModule: function (name, params, event) {
-				params = params || '';
-				var moduleData = this.getRecordFromName(name);
-				return this.loadModuleComponents(
-					moduleData,
-					params,
-					new ClientRequest('typo3.showModule', event)
-				);
-			},
-
-			ensurePageInTreeSelected: function () {
-				if (this.loadedNavigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement'
-					&& this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].isInitialized()
-				) {
-					this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].selectRequestedPageId();
-				}
-			},
-
-			/**
-			 * Shows requested module (e.g. list/page)
-			 *
-			 * @param {Object} moduleData
-			 * @param {string} params
-			 * @param {InteractionRequest} [interactionRequest]
-			 * @return {jQuery.Deferred}
-			 */
-			loadModuleComponents: function (moduleData, params, interactionRequest) {
-				var moduleName = moduleData.name;
-
-				// Allow other components e.g. Formengine to cancel switching between modules
-				// (e.g. you have unsaved changes in the form)
-				var deferred = TYPO3.Backend.ContentContainer.beforeSetUrl(interactionRequest);
-				deferred.then(
-					$.proxy(function() {
-						if (moduleData.navigationComponentId) {
-							this.loadNavigationComponent(moduleData.navigationComponentId);
-						} else if (moduleData.navigationFrameScript) {
-							TYPO3.Backend.NavigationContainer.show('typo3-navigationIframe');
-							this.openInNavFrame(
-								moduleData.navigationFrameScript,
-								moduleData.navigationFrameScriptParam,
-								new TriggerRequest(
-									'typo3.loadModuleComponents',
-									interactionRequest
-								)
-							);
-						} else {
-							TYPO3.Backend.NavigationContainer.hide();
-						}
-
-						this.highlightModuleMenuItem(moduleName);
-						this.loadedModule = moduleName;
-						params = this.includeId(moduleData, params);
-						this.openInContentFrame(
-							moduleData.link,
-							params,
-							new TriggerRequest(
-								'typo3.loadModuleComponents',
-								interactionRequest
-							)
-						);
-
-						// compatibility
-						top.currentSubScript = moduleData.link;
-						top.currentModuleLoaded = moduleName;
-
-						TYPO3.Backend.doLayout();
-						this.ensurePageInTreeSelected();
-					}, this
-				));
-
-				return deferred;
-			},
-
-			/**
-			 * Prepends previously saved record id to the url params
-			 *
-			 * @param {Object} moduleData
-			 * @param {string} params query string parameters for module url
-			 * @return {string}
-			 */
-			includeId: function (moduleData, params) {
-				if (!moduleData.navigationComponentId && !moduleData.navigationFrameScript) {
-					return params;
-				}
-				//get id
-				var section = '';
-				if (moduleData.navigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement') {
-					section = 'web';
-				} else {
-					section = moduleData.name.split('_')[0];
-				}
-				if (top.fsMod.recentIds[section]) {
-					params = 'id=' + top.fsMod.recentIds[section] + '&' + params;
-				}
-
-				return params;
-			},
-
-			/**
-			 * Renders registered (non-iframe) navigation component e.g. a page tree
-			 *
-			 * @param {string} navigationComponentId
-			 */
-			loadNavigationComponent: function (navigationComponentId) {
-				TYPO3.Backend.NavigationContainer.show(navigationComponentId);
-				if (navigationComponentId === this.loadedNavigationComponentId) {
-					return;
-				}
-				var componentCssName = navigationComponentId.replace(/[/]/g, '_');
-				if (this.loadedNavigationComponentId !== '') {
-					$('#navigationComponent-' + this.loadedNavigationComponentId.replace(/[/]/g, '_')).hide();
-				}
-				if ($('.t3js-scaffold-content-navigation [data-component="' + navigationComponentId + '"]').length < 1) {
-					$('.t3js-scaffold-content-navigation')
-						.append('<div class="scaffold-content-navigation-component" data-component="' + navigationComponentId + '" id="navigationComponent-' + componentCssName + '"></div>');
-				}
-
-				require([navigationComponentId], function (NavigationComponent) {
-					NavigationComponent.initialize('#navigationComponent-' + componentCssName);
-					TYPO3.Backend.NavigationContainer.show(navigationComponentId);
-					self.loadedNavigationComponentId = navigationComponentId;
-				});
-			},
-
-			/**
-			 * @param {string} url
-			 * @param {string} params
-			 * @param {InteractionRequest} [interactionRequest]
-			 * @return {jQuery.Deferred}
-			 */
-			openInNavFrame: function (url, params, interactionRequest) {
-				var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
-				var currentUrl = TYPO3.Backend.NavigationContainer.getUrl();
-				var deferred = TYPO3.Backend.NavigationContainer.setUrl(
-					url,
-					new TriggerRequest('typo3.openInNavFrame', interactionRequest)
-				);
-				if (currentUrl !== navUrl) {
-					// if deferred is already resolved, execute directly
-					if (deferred.state() === 'resolved') {
-						TYPO3.Backend.NavigationContainer.refresh();
-					// otherwise hand in future callback
-					} else {
-						deferred.then(TYPO3.Backend.NavigationContainer.refresh);
-					}
-				}
-				return deferred;
-			},
-
-			/**
-			 * @param {string} url
-			 * @param {string} params
-			 * @param {InteractionRequest} [interactionRequest]
-			 * @return {jQuery.Deferred}
-			 */
-			openInContentFrame: function (url, params, interactionRequest) {
-				var deferred;
-
-				if (top.nextLoadModuleUrl) {
-					deferred = TYPO3.Backend.ContentContainer.setUrl(
-						top.nextLoadModuleUrl,
-						new TriggerRequest('typo3.openInContentFrame', interactionRequest)
-					);
-					top.nextLoadModuleUrl = '';
-				} else {
-					var urlToLoad = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
-					deferred = TYPO3.Backend.ContentContainer.setUrl(
-						urlToLoad,
-						new TriggerRequest('typo3.openInContentFrame', interactionRequest)
-					);
-				}
-
-				return deferred;
-			},
-
-			highlightModuleMenuItem: function (module, mainModule) {
-				$('.modulemenu-item.active').removeClass('active');
-				$('#' + module).addClass('active');
-			},
-
-			// refresh the HTML by fetching the menu again
-			refreshMenu: function () {
-				$.ajax(TYPO3.settings.ajaxUrls['modulemenu']).done(function (result) {
-					$('#menu').replaceWith(result.menu);
-					if (top.currentModuleLoaded) {
-						TYPO3.ModuleMenu.App.highlightModuleMenuItem(top.currentModuleLoaded);
-					}
-					TYPO3.Backend.doLayout();
-				});
-			},
-
-			reloadFrames: function () {
-				TYPO3.Backend.NavigationContainer.refresh();
-				TYPO3.Backend.ContentContainer.refresh();
-			},
-
-			/**
-			 * fetches all module menu elements in the local storage that should be collapsed
-			 * @returns {*}
-			 */
-			getCollapsedMainMenuItems: function () {
-				if (PersistentStorage.isset('modulemenu')) {
-					return JSON.parse(PersistentStorage.get('modulemenu'));
-				} else {
-					return {};
-				}
-			},
-
-			/**
-			 * adds a module menu item to the local storage
-			 * @param item
-			 */
-			addCollapsedMainMenuItem: function (item) {
-				var existingItems = this.getCollapsedMainMenuItems();
-				existingItems[item] = true;
-				PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
-			},
-
-			/**
-			 * removes a module menu item from the local storage
-			 * @param item
-			 */
-			removeCollapseMainMenuItem: function (item) {
-				var existingItems = this.getCollapsedMainMenuItems();
-				delete existingItems[item];
-				PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
-			}
-
-		};
-		// start the module menu app
-		TYPO3.ModuleMenu.App.initialize();
-		return TYPO3.ModuleMenu;
-	}
+  [
+    'jquery',
+    'TYPO3/CMS/Backend/Storage/Persistent',
+    'TYPO3/CMS/Backend/Icons',
+    'TYPO3/CMS/Backend/Viewport',
+    'TYPO3/CMS/Backend/Event/ClientRequest',
+    'TYPO3/CMS/Backend/Event/TriggerRequest'
+  ],
+  function($, PersistentStorage, Icons, Viewport, ClientRequest, TriggerRequest) {
+    if (typeof TYPO3.ModuleMenu !== 'undefined') {
+      return TYPO3.ModuleMenu.App;
+    }
+
+    TYPO3.ModuleMenu = {};
+    TYPO3.ModuleMenu.App = {
+      loadedModule: null,
+      loadedNavigationComponentId: '',
+
+      initialize: function() {
+        var me = this;
+
+        var deferred = $.Deferred();
+        deferred.resolve();
+
+        // load the start module
+        if (top.startInModule && top.startInModule[0] && $('#' + top.startInModule[0]).length > 0) {
+          deferred = me.showModule(
+            top.startInModule[0],
+            top.startInModule[1]
+          );
+        } else {
+          // fetch first module
+          if ($('.t3js-mainmodule:first').attr('id')) {
+            deferred = me.showModule(
+              $('.t3js-mainmodule:first').attr('id')
+            );
+          }
+          // else case: the main module has no entries, this is probably a backend
+          // user with very little access rights, maybe only the logout button and
+          // a user settings module in topbar.
+        }
+
+        deferred.then(function() {
+          // check if module menu should be collapsed or not
+          var state = PersistentStorage.get('BackendComponents.States.typo3-module-menu');
+          if (state && state.collapsed) {
+            TYPO3.ModuleMenu.App.toggleMenu(state.collapsed === 'true');
+          }
+
+          // check if there are collapsed items in the users' configuration
+          var collapsedMainMenuItems = me.getCollapsedMainMenuItems();
+          $.each(collapsedMainMenuItems, function(key, itm) {
+            if (itm !== true) {
+              return;
+            }
+            var $group = $('#' + key);
+            if ($group.length > 0) {
+              var $groupContainer = $group.find('.modulemenu-group-container');
+              $group.addClass('collapsed').removeClass('expanded');
+              TYPO3.Backend.NavigationContainer.cleanup();
+              $groupContainer.hide().promise().done(function() {
+                TYPO3.Backend.doLayout();
+              });
+            }
+          });
+          me.initializeEvents();
+        });
+      },
+
+      initializeEvents: function() {
+        var me = this;
+        $(document).on('click', '.modulemenu-group .modulemenu-group-header', function() {
+          var $group = $(this).parent('.modulemenu-group');
+          var $groupContainer = $group.find('.modulemenu-group-container');
+
+          TYPO3.Backend.NavigationContainer.cleanup();
+          if ($group.hasClass('expanded')) {
+            me.addCollapsedMainMenuItem($group.attr('id'));
+            $group.addClass('collapsed').removeClass('expanded');
+            $groupContainer.stop().slideUp().promise().done(function() {
+              TYPO3.Backend.doLayout();
+            });
+          } else {
+            me.removeCollapseMainMenuItem($group.attr('id'));
+            $group.addClass('expanded').removeClass('collapsed');
+            $groupContainer.stop().slideDown().promise().done(function() {
+              TYPO3.Backend.doLayout();
+            });
+          }
+
+        });
+        // register clicking on sub modules
+        $(document).on('click', '.modulemenu-item,.t3-menuitem-submodule', function(evt) {
+          evt.preventDefault();
+          me.showModule(
+            $(this).attr('id'),
+            '',
+            evt
+          );
+        });
+        $(document).on('click', '.t3js-topbar-button-modulemenu',
+          function(evt) {
+            evt.preventDefault();
+            TYPO3.ModuleMenu.App.toggleMenu();
+          }
+        );
+        $(document).on('click', '.t3js-scaffold-content-overlay',
+          function(evt) {
+            evt.preventDefault();
+            TYPO3.ModuleMenu.App.toggleMenu(true);
+          }
+        );
+        $(document).on('click', '.t3js-topbar-button-navigationcomponent',
+          function(evt) {
+            evt.preventDefault();
+            TYPO3.Backend.NavigationContainer.toggle();
+          }
+        );
+      },
+
+      /**
+       * @param {Boolean} collapse
+       */
+      toggleMenu: function(collapse) {
+        TYPO3.Backend.NavigationContainer.cleanup();
+
+        var $mainContainer = $('.t3js-scaffold');
+        var expandedClass = 'scaffold-modulemenu-expanded';
+
+        if (typeof collapse === 'undefined') {
+          collapse = $mainContainer.hasClass(expandedClass);
+        }
+        $mainContainer.toggleClass(expandedClass, !collapse);
+        if (!collapse) {
+          $('.scaffold')
+            .removeClass('scaffold-search-expanded')
+            .removeClass('scaffold-toolbar-expanded');
+        }
+
+        // Persist collapsed state in the UC of the current user
+        PersistentStorage.set(
+          'BackendComponents.States.typo3-module-menu',
+          {
+            collapsed: collapse
+          }
+        );
+
+        TYPO3.Backend.doLayout();
+      },
+
+      /**
+       * Gets the module properties from module menu markup (data attributes)
+       *
+       * @param {string} name module name e.g. web_list
+       * @return {Object}
+       */
+      getRecordFromName: function(name) {
+        var $subModuleElement = $('#' + name);
+        return {
+          name: name,
+          navigationComponentId: $subModuleElement.data('navigationcomponentid'),
+          navigationFrameScript: $subModuleElement.data('navigationframescript'),
+          navigationFrameScriptParam: $subModuleElement.data('navigationframescriptparameters'),
+          link: $subModuleElement.find('a').data('link')
+        };
+      },
+
+      /**
+       * Event handler called after clicking on the module menu item
+       *
+       * @param {string} name module name e.g. web_layout
+       * @param {string} params
+       * @param {Event} [event]
+       * @return {jQuery.Deferred}
+       */
+      showModule: function(name, params, event) {
+        params = params || '';
+        var moduleData = this.getRecordFromName(name);
+        return this.loadModuleComponents(
+          moduleData,
+          params,
+          new ClientRequest('typo3.showModule', event)
+        );
+      },
+
+      ensurePageInTreeSelected: function() {
+        if (this.loadedNavigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement'
+          && this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].isInitialized()
+        ) {
+          this.availableNavigationComponents['TYPO3/CMS/Backend/PageTree/PageTreeElement'].selectRequestedPageId();
+        }
+      },
+
+      /**
+       * Shows requested module (e.g. list/page)
+       *
+       * @param {Object} moduleData
+       * @param {string} params
+       * @param {InteractionRequest} [interactionRequest]
+       * @return {jQuery.Deferred}
+       */
+      loadModuleComponents: function(moduleData, params, interactionRequest) {
+        var moduleName = moduleData.name;
+
+        // Allow other components e.g. Formengine to cancel switching between modules
+        // (e.g. you have unsaved changes in the form)
+        var deferred = TYPO3.Backend.ContentContainer.beforeSetUrl(interactionRequest);
+        deferred.then(
+          $.proxy(function() {
+              if (moduleData.navigationComponentId) {
+                this.loadNavigationComponent(moduleData.navigationComponentId);
+              } else if (moduleData.navigationFrameScript) {
+                TYPO3.Backend.NavigationContainer.show('typo3-navigationIframe');
+                this.openInNavFrame(
+                  moduleData.navigationFrameScript,
+                  moduleData.navigationFrameScriptParam,
+                  new TriggerRequest(
+                    'typo3.loadModuleComponents',
+                    interactionRequest
+                  )
+                );
+              } else {
+                TYPO3.Backend.NavigationContainer.hide();
+              }
+
+              this.highlightModuleMenuItem(moduleName);
+              this.loadedModule = moduleName;
+              params = this.includeId(moduleData, params);
+              this.openInContentFrame(
+                moduleData.link,
+                params,
+                new TriggerRequest(
+                  'typo3.loadModuleComponents',
+                  interactionRequest
+                )
+              );
+
+              // compatibility
+              top.currentSubScript = moduleData.link;
+              top.currentModuleLoaded = moduleName;
+
+              TYPO3.Backend.doLayout();
+              this.ensurePageInTreeSelected();
+            }, this
+          ));
+
+        return deferred;
+      },
+
+      /**
+       * Prepends previously saved record id to the url params
+       *
+       * @param {Object} moduleData
+       * @param {string} params query string parameters for module url
+       * @return {string}
+       */
+      includeId: function(moduleData, params) {
+        if (!moduleData.navigationComponentId && !moduleData.navigationFrameScript) {
+          return params;
+        }
+        //get id
+        var section = '';
+        if (moduleData.navigationComponentId === 'TYPO3/CMS/Backend/PageTree/PageTreeElement') {
+          section = 'web';
+        } else {
+          section = moduleData.name.split('_')[0];
+        }
+        if (top.fsMod.recentIds[section]) {
+          params = 'id=' + top.fsMod.recentIds[section] + '&' + params;
+        }
+
+        return params;
+      },
+
+      /**
+       * Renders registered (non-iframe) navigation component e.g. a page tree
+       *
+       * @param {string} navigationComponentId
+       */
+      loadNavigationComponent: function(navigationComponentId) {
+        TYPO3.Backend.NavigationContainer.show(navigationComponentId);
+        if (navigationComponentId === this.loadedNavigationComponentId) {
+          return;
+        }
+        var componentCssName = navigationComponentId.replace(/[/]/g, '_');
+        if (this.loadedNavigationComponentId !== '') {
+          $('#navigationComponent-' + this.loadedNavigationComponentId.replace(/[/]/g, '_')).hide();
+        }
+        if ($('.t3js-scaffold-content-navigation [data-component="' + navigationComponentId + '"]').length < 1) {
+          $('.t3js-scaffold-content-navigation')
+            .append('<div class="scaffold-content-navigation-component" data-component="' + navigationComponentId + '" id="navigationComponent-' + componentCssName + '"></div>');
+        }
+
+        require([navigationComponentId], function(NavigationComponent) {
+          NavigationComponent.initialize('#navigationComponent-' + componentCssName);
+          TYPO3.Backend.NavigationContainer.show(navigationComponentId);
+          self.loadedNavigationComponentId = navigationComponentId;
+        });
+      },
+
+      /**
+       * @param {string} url
+       * @param {string} params
+       * @param {InteractionRequest} [interactionRequest]
+       * @return {jQuery.Deferred}
+       */
+      openInNavFrame: function(url, params, interactionRequest) {
+        var navUrl = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
+        var currentUrl = TYPO3.Backend.NavigationContainer.getUrl();
+        var deferred = TYPO3.Backend.NavigationContainer.setUrl(
+          url,
+          new TriggerRequest('typo3.openInNavFrame', interactionRequest)
+        );
+        if (currentUrl !== navUrl) {
+          // if deferred is already resolved, execute directly
+          if (deferred.state() === 'resolved') {
+            TYPO3.Backend.NavigationContainer.refresh();
+            // otherwise hand in future callback
+          } else {
+            deferred.then(TYPO3.Backend.NavigationContainer.refresh);
+          }
+        }
+        return deferred;
+      },
+
+      /**
+       * @param {string} url
+       * @param {string} params
+       * @param {InteractionRequest} [interactionRequest]
+       * @return {jQuery.Deferred}
+       */
+      openInContentFrame: function(url, params, interactionRequest) {
+        var deferred;
+
+        if (top.nextLoadModuleUrl) {
+          deferred = TYPO3.Backend.ContentContainer.setUrl(
+            top.nextLoadModuleUrl,
+            new TriggerRequest('typo3.openInContentFrame', interactionRequest)
+          );
+          top.nextLoadModuleUrl = '';
+        } else {
+          var urlToLoad = url + (params ? (url.indexOf('?') !== -1 ? '&' : '?') + params : '');
+          deferred = TYPO3.Backend.ContentContainer.setUrl(
+            urlToLoad,
+            new TriggerRequest('typo3.openInContentFrame', interactionRequest)
+          );
+        }
+
+        return deferred;
+      },
+
+      highlightModuleMenuItem: function(module, mainModule) {
+        $('.modulemenu-item.active').removeClass('active');
+        $('#' + module).addClass('active');
+      },
+
+      // refresh the HTML by fetching the menu again
+      refreshMenu: function() {
+        $.ajax(TYPO3.settings.ajaxUrls['modulemenu']).done(function(result) {
+          $('#menu').replaceWith(result.menu);
+          if (top.currentModuleLoaded) {
+            TYPO3.ModuleMenu.App.highlightModuleMenuItem(top.currentModuleLoaded);
+          }
+          TYPO3.Backend.doLayout();
+        });
+      },
+
+      reloadFrames: function() {
+        TYPO3.Backend.NavigationContainer.refresh();
+        TYPO3.Backend.ContentContainer.refresh();
+      },
+
+      /**
+       * fetches all module menu elements in the local storage that should be collapsed
+       * @returns {*}
+       */
+      getCollapsedMainMenuItems: function() {
+        if (PersistentStorage.isset('modulemenu')) {
+          return JSON.parse(PersistentStorage.get('modulemenu'));
+        } else {
+          return {};
+        }
+      },
+
+      /**
+       * adds a module menu item to the local storage
+       * @param item
+       */
+      addCollapsedMainMenuItem: function(item) {
+        var existingItems = this.getCollapsedMainMenuItems();
+        existingItems[item] = true;
+        PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
+      },
+
+      /**
+       * removes a module menu item from the local storage
+       * @param item
+       */
+      removeCollapseMainMenuItem: function(item) {
+        var existingItems = this.getCollapsedMainMenuItems();
+        delete existingItems[item];
+        PersistentStorage.set('modulemenu', JSON.stringify(existingItems));
+      }
+
+    };
+    // start the module menu app
+    TYPO3.ModuleMenu.App.initialize();
+    return TYPO3.ModuleMenu;
+  }
 );
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js b/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js
index 7de0e7deaebd..5af8fb1859bd 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/NewMultiplePages.js
@@ -16,57 +16,57 @@
  * JavaScript functions for creating multiple pages
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 * @type {{lineCounter: number, containerSelector: string, addMoreFieldsButtonSelector: string, doktypeSelector: string}}
-	 * @exports TYPO3/CMS/Backend/NewMultiplePages
-	 */
-	var NewMultiplePages = {
-		lineCounter: 5,
-		containerSelector: '.t3js-newmultiplepages-container',
-		addMoreFieldsButtonSelector: '.t3js-newmultiplepages-createnewfields',
-		doktypeSelector: '.t3js-newmultiplepages-select-doktype',
-		templateRow: '.t3js-newmultiplepages-newlinetemplate'
-	};
+  /**
+   * @type {{lineCounter: number, containerSelector: string, addMoreFieldsButtonSelector: string, doktypeSelector: string}}
+   * @exports TYPO3/CMS/Backend/NewMultiplePages
+   */
+  var NewMultiplePages = {
+    lineCounter: 5,
+    containerSelector: '.t3js-newmultiplepages-container',
+    addMoreFieldsButtonSelector: '.t3js-newmultiplepages-createnewfields',
+    doktypeSelector: '.t3js-newmultiplepages-select-doktype',
+    templateRow: '.t3js-newmultiplepages-newlinetemplate'
+  };
 
-	/**
-	 * Add further input rows
-	 */
-	NewMultiplePages.createNewFormFields = function() {
-		for (var i = 0; i < 5; i++) {
-			var label = NewMultiplePages.lineCounter + i + 1;
-			var line = $(NewMultiplePages.templateRow).html()
-				.replace(/\[0\]/g, (NewMultiplePages.lineCounter + i))
-				.replace(/\[1\]/g, label);
-			$(line).appendTo(NewMultiplePages.containerSelector);
-		}
-		NewMultiplePages.lineCounter += 5;
-	};
+  /**
+   * Add further input rows
+   */
+  NewMultiplePages.createNewFormFields = function() {
+    for (var i = 0; i < 5; i++) {
+      var label = NewMultiplePages.lineCounter + i + 1;
+      var line = $(NewMultiplePages.templateRow).html()
+        .replace(/\[0\]/g, (NewMultiplePages.lineCounter + i))
+        .replace(/\[1\]/g, label);
+      $(line).appendTo(NewMultiplePages.containerSelector);
+    }
+    NewMultiplePages.lineCounter += 5;
+  };
 
-	/**
-	 * @param {Object} $selectElement
-	 */
-	NewMultiplePages.actOnTypeSelectChange = function($selectElement) {
-		var $optionElement = $selectElement.find(':selected');
-		var $target = $($selectElement.data('target'));
-		$target.html($optionElement.data('icon'));
-	};
+  /**
+   * @param {Object} $selectElement
+   */
+  NewMultiplePages.actOnTypeSelectChange = function($selectElement) {
+    var $optionElement = $selectElement.find(':selected');
+    var $target = $($selectElement.data('target'));
+    $target.html($optionElement.data('icon'));
+  };
 
-	/**
-	 * Register listeners
-	 */
-	NewMultiplePages.initializeEvents = function() {
-		$(NewMultiplePages.addMoreFieldsButtonSelector).on('click', function() {
-			NewMultiplePages.createNewFormFields();
-		});
+  /**
+   * Register listeners
+   */
+  NewMultiplePages.initializeEvents = function() {
+    $(NewMultiplePages.addMoreFieldsButtonSelector).on('click', function() {
+      NewMultiplePages.createNewFormFields();
+    });
 
-		$(document).on('change', NewMultiplePages.doktypeSelector, function() {
-			NewMultiplePages.actOnTypeSelectChange($(this));
-		});
-	};
+    $(document).on('change', NewMultiplePages.doktypeSelector, function() {
+      NewMultiplePages.actOnTypeSelectChange($(this));
+    });
+  };
 
-	$(NewMultiplePages.initializeEvents);
+  $(NewMultiplePages.initializeEvents);
 
-	return NewMultiplePages;
+  return NewMultiplePages;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js b/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js
index 22b39834ddd2..845cd07dbae3 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Notification.js
@@ -18,208 +18,207 @@
  * @deprecation: Severity got its own AMD module, it is required here only for
  * backwards compatibility reasons
  */
-define(['jquery', 'TYPO3/CMS/Backend/Severity'], function ($) {
-	'use strict';
-
-	try {
-		// fetch from parent
-		if (parent && parent.window.TYPO3 && parent.window.TYPO3.Notification) {
-			return parent.window.TYPO3.Notification;
-		}
-
-		// fetch object from outer frame
-		if (top && top.TYPO3.Notification) {
-			return top.TYPO3.Notification;
-		}
-	} catch (e) {
-		// This only happens if the opener, parent or top is some other url (eg a local file)
-		// which loaded the current window. Then the browser's cross domain policy jumps in
-		// and raises an exception.
-		// For this case we are safe and we can create our global object below.
-	}
-
-	/**
-	 * The main Notification object
-	 *
-	 * @type {{NOTICE: number, INFO: number, OK: number, WARNING: number, ERROR: number, messageContainer: null, duration: number}}
-	 * @exports TYPO3/CMS/Backend/Notification
-	 */
-	var Notification = {
-		NOTICE: -2,
-		INFO: -1,
-		OK: 0,
-		WARNING: 1,
-		ERROR: 2,
-		messageContainer: null,
-		duration: 5
-	};
-
-	/**
-	 * Show a notice notification
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
-	 *
-	 * @public
-	 */
-	Notification.notice = function(title, message, duration) {
-		Notification.showMessage(title, message, Notification.NOTICE, duration);
-	};
-
-	/**
-	 * Show an info notification
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
-	 *
-	 * @public
-	 */
-	Notification.info = function(title, message, duration) {
-		Notification.showMessage(title, message, Notification.INFO, duration);
-	};
-
-	/**
-	 * Show an ok notification
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
-	 *
-	 * @public
-	 */
-	Notification.success = function(title, message, duration) {
-		Notification.showMessage(title, message, Notification.OK, duration);
-	};
-
-	/**
-	 * Show a warning notification
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
-	 *
-	 * @public
-	 */
-	Notification.warning = function(title, message, duration) {
-		Notification.showMessage(title, message, Notification.WARNING, duration);
-	};
-
-	/**
-	 * Show an error notification
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 0, 0 = sticky
-	 *
-	 * @public
-	 */
-	Notification.error = function(title, message, duration) {
-		duration = duration || 0;
-		Notification.showMessage(title, message, Notification.ERROR, duration);
-	};
-
-	/**
-	 * Show message
-	 *
-	 * @param {String} title The title for the notification
-	 * @param {String} message The message for the notification
-	 * @param {int} severity See constants in this object
-	 * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
-	 *
-	 * @private
-	 */
-	Notification.showMessage = function(title, message, severity, duration) {
-		var className = '';
-		var icon = '';
-		switch (severity) {
-			case Notification.NOTICE:
-				className = 'notice';
-				icon = 'lightbulb-o';
-				break;
-			case Notification.INFO:
-				className = 'info';
-				icon = 'info';
-				break;
-			case Notification.OK:
-				className = 'success';
-				icon = 'check';
-				break;
-			case Notification.WARNING:
-				className = 'warning';
-				icon = 'exclamation';
-				break;
-			case Notification.ERROR:
-				className = 'danger';
-				icon = 'times';
-				break;
-			default:
-				className = 'info';
-				icon = 'info';
-		}
-
-		duration = (typeof duration === 'undefined') ? Notification.duration : parseFloat(duration);
-
-		if (Notification.messageContainer === null) {
-			Notification.messageContainer = $('<div id="alert-container"></div>').appendTo('body');
-		}
-		var $box = $(
-			'<div class="alert alert-' + className + ' alert-dismissible fade" role="alert">' +
-				'<button type="button" class="close" data-dismiss="alert">' +
-					'<span aria-hidden="true"><i class="fa fa-times-circle"></i></span>' +
-					'<span class="sr-only">Close</span>' +
-				'</button>' +
-				'<div class="media">' +
-					'<div class="media-left">' +
-						'<span class="fa-stack fa-lg">' +
-							'<i class="fa fa-circle fa-stack-2x"></i>' +
-							'<i class="fa fa-' + icon + ' fa-stack-1x"></i>' +
-						'</span>' +
-					'</div>' +
-					'<div class="media-body">' +
-						'<h4 class="alert-title"></h4>' +
-						'<p class="alert-message text-pre-wrap"></p>' +
-					'</div>' +
-				'</div>' +
-			'</div>'
-		);
-		$box.find('.alert-title').text(title);
-		$box.find('.alert-message').text(message);
-		$box.on('close.bs.alert', function(e) {
-			e.preventDefault();
-			$(this)
-				.clearQueue()
-				.queue(function(next) {
-					$(this).removeClass('in');
-					next();
-				})
-				.slideUp(function () {
-					$(this).remove();
-				});
-		});
-		$box.appendTo(Notification.messageContainer);
-		$box.delay('fast')
-			.queue(function(next) {
-				$(this).addClass('in');
-				next();
-			});
-		// if duration > 0 dismiss alert
-		if (duration > 0) {
-			$box.delay(duration * 1000)
-				.queue(function(next) {
-					$(this).alert('close');
-					next();
-				});
-		}
-	};
-
-
-
-	// attach to global frame
-	if (typeof TYPO3 !== 'undefined') {
-		TYPO3.Notification = Notification;
-	}
-
-	return Notification;
+define(['jquery', 'TYPO3/CMS/Backend/Severity'], function($) {
+  'use strict';
+
+  try {
+    // fetch from parent
+    if (parent && parent.window.TYPO3 && parent.window.TYPO3.Notification) {
+      return parent.window.TYPO3.Notification;
+    }
+
+    // fetch object from outer frame
+    if (top && top.TYPO3.Notification) {
+      return top.TYPO3.Notification;
+    }
+  } catch (e) {
+    // This only happens if the opener, parent or top is some other url (eg a local file)
+    // which loaded the current window. Then the browser's cross domain policy jumps in
+    // and raises an exception.
+    // For this case we are safe and we can create our global object below.
+  }
+
+  /**
+   * The main Notification object
+   *
+   * @type {{NOTICE: number, INFO: number, OK: number, WARNING: number, ERROR: number, messageContainer: null, duration: number}}
+   * @exports TYPO3/CMS/Backend/Notification
+   */
+  var Notification = {
+    NOTICE: -2,
+    INFO: -1,
+    OK: 0,
+    WARNING: 1,
+    ERROR: 2,
+    messageContainer: null,
+    duration: 5
+  };
+
+  /**
+   * Show a notice notification
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
+   *
+   * @public
+   */
+  Notification.notice = function(title, message, duration) {
+    Notification.showMessage(title, message, Notification.NOTICE, duration);
+  };
+
+  /**
+   * Show an info notification
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
+   *
+   * @public
+   */
+  Notification.info = function(title, message, duration) {
+    Notification.showMessage(title, message, Notification.INFO, duration);
+  };
+
+  /**
+   * Show an ok notification
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
+   *
+   * @public
+   */
+  Notification.success = function(title, message, duration) {
+    Notification.showMessage(title, message, Notification.OK, duration);
+  };
+
+  /**
+   * Show a warning notification
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
+   *
+   * @public
+   */
+  Notification.warning = function(title, message, duration) {
+    Notification.showMessage(title, message, Notification.WARNING, duration);
+  };
+
+  /**
+   * Show an error notification
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {float} duration Time in seconds to show notification before it disappears, default 0, 0 = sticky
+   *
+   * @public
+   */
+  Notification.error = function(title, message, duration) {
+    duration = duration || 0;
+    Notification.showMessage(title, message, Notification.ERROR, duration);
+  };
+
+  /**
+   * Show message
+   *
+   * @param {String} title The title for the notification
+   * @param {String} message The message for the notification
+   * @param {int} severity See constants in this object
+   * @param {float} duration Time in seconds to show notification before it disappears, default 5, 0 = sticky
+   *
+   * @private
+   */
+  Notification.showMessage = function(title, message, severity, duration) {
+    var className = '';
+    var icon = '';
+    switch (severity) {
+      case Notification.NOTICE:
+        className = 'notice';
+        icon = 'lightbulb-o';
+        break;
+      case Notification.INFO:
+        className = 'info';
+        icon = 'info';
+        break;
+      case Notification.OK:
+        className = 'success';
+        icon = 'check';
+        break;
+      case Notification.WARNING:
+        className = 'warning';
+        icon = 'exclamation';
+        break;
+      case Notification.ERROR:
+        className = 'danger';
+        icon = 'times';
+        break;
+      default:
+        className = 'info';
+        icon = 'info';
+    }
+
+    duration = (typeof duration === 'undefined') ? Notification.duration : parseFloat(duration);
+
+    if (Notification.messageContainer === null) {
+      Notification.messageContainer = $('<div id="alert-container"></div>').appendTo('body');
+    }
+    var $box = $(
+      '<div class="alert alert-' + className + ' alert-dismissible fade" role="alert">' +
+      '<button type="button" class="close" data-dismiss="alert">' +
+      '<span aria-hidden="true"><i class="fa fa-times-circle"></i></span>' +
+      '<span class="sr-only">Close</span>' +
+      '</button>' +
+      '<div class="media">' +
+      '<div class="media-left">' +
+      '<span class="fa-stack fa-lg">' +
+      '<i class="fa fa-circle fa-stack-2x"></i>' +
+      '<i class="fa fa-' + icon + ' fa-stack-1x"></i>' +
+      '</span>' +
+      '</div>' +
+      '<div class="media-body">' +
+      '<h4 class="alert-title"></h4>' +
+      '<p class="alert-message text-pre-wrap"></p>' +
+      '</div>' +
+      '</div>' +
+      '</div>'
+    );
+    $box.find('.alert-title').text(title);
+    $box.find('.alert-message').text(message);
+    $box.on('close.bs.alert', function(e) {
+      e.preventDefault();
+      $(this)
+        .clearQueue()
+        .queue(function(next) {
+          $(this).removeClass('in');
+          next();
+        })
+        .slideUp(function() {
+          $(this).remove();
+        });
+    });
+    $box.appendTo(Notification.messageContainer);
+    $box.delay('fast')
+      .queue(function(next) {
+        $(this).addClass('in');
+        next();
+      });
+    // if duration > 0 dismiss alert
+    if (duration > 0) {
+      $box.delay(duration * 1000)
+        .queue(function(next) {
+          $(this).alert('close');
+          next();
+        });
+    }
+  };
+
+
+  // attach to global frame
+  if (typeof TYPO3 !== 'undefined') {
+    TYPO3.Notification = Notification;
+  }
+
+  return Notification;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js b/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js
index 314726ff407a..c9d305139116 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/OnlineMedia.js
@@ -16,117 +16,117 @@
  * Javascript for show the online media dialog
  */
 define(['jquery',
-		'nprogress',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Severity',
-		'TYPO3/CMS/Lang/Lang'
-	   ], function($, NProgress, Modal, Severity) {
-	'use strict';
+  'nprogress',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Lang/Lang'
+], function($, NProgress, Modal, Severity) {
+  'use strict';
 
-	/**
-	 *
-	 * @param element
-	 * @constructor
-	 * @exports TYPO3/CMS/Backend/OnlineMedia
-	 */
-	var OnlineMediaPlugin = function(element) {
-		var me = this;
-		me.$btn = $(element);
-		me.target = me.$btn.data('target-folder');
-		me.irreObjectUid = me.$btn.data('file-irre-object');
-		me.allowed = me.$btn.data('online-media-allowed');
-		me.allowedHelpText = me.$btn.data('online-media-allowed-help-text') || 'Allow to embed from sources:';
-		me.btnSubmit = me.$btn.data('data-btn-submit') || 'Add';
-		me.placeholder = me.$btn.data('placeholder') || 'Paste media url here...';
+  /**
+   *
+   * @param element
+   * @constructor
+   * @exports TYPO3/CMS/Backend/OnlineMedia
+   */
+  var OnlineMediaPlugin = function(element) {
+    var me = this;
+    me.$btn = $(element);
+    me.target = me.$btn.data('target-folder');
+    me.irreObjectUid = me.$btn.data('file-irre-object');
+    me.allowed = me.$btn.data('online-media-allowed');
+    me.allowedHelpText = me.$btn.data('online-media-allowed-help-text') || 'Allow to embed from sources:';
+    me.btnSubmit = me.$btn.data('data-btn-submit') || 'Add';
+    me.placeholder = me.$btn.data('placeholder') || 'Paste media url here...';
 
-		/**
-		 *
-		 * @param {String} url
-		 */
-		me.addOnlineMedia = function(url) {
-			NProgress.start();
-			$.post(TYPO3.settings.ajaxUrls['online_media_create'],
-				{
-					url: url,
-					targetFolder: me.target,
-					allowed: me.allowed
-				},
-				function(data) {
-					if (data.file) {
-						inline.delayedImportElement(
-							me.irreObjectUid,
-							'sys_file',
-							data.file,
-							'file'
-						);
-					} else {
-						var $confirm = Modal.confirm(
-							'ERROR',
-							data.error,
-							Severity.error,
-							[{
-								text: TYPO3.lang['button.ok'] || 'OK',
-								btnClass: 'btn-' + Severity.getCssClass(Severity.error),
-								name: 'ok',
-								active: true
-							}]
-						).on('confirm.button.ok', function() {
-							$confirm.modal('hide');
-						});
-					}
-					NProgress.done();
-				}
-			);
-		};
+    /**
+     *
+     * @param {String} url
+     */
+    me.addOnlineMedia = function(url) {
+      NProgress.start();
+      $.post(TYPO3.settings.ajaxUrls['online_media_create'],
+        {
+          url: url,
+          targetFolder: me.target,
+          allowed: me.allowed
+        },
+        function(data) {
+          if (data.file) {
+            inline.delayedImportElement(
+              me.irreObjectUid,
+              'sys_file',
+              data.file,
+              'file'
+            );
+          } else {
+            var $confirm = Modal.confirm(
+              'ERROR',
+              data.error,
+              Severity.error,
+              [{
+                text: TYPO3.lang['button.ok'] || 'OK',
+                btnClass: 'btn-' + Severity.getCssClass(Severity.error),
+                name: 'ok',
+                active: true
+              }]
+            ).on('confirm.button.ok', function() {
+              $confirm.modal('hide');
+            });
+          }
+          NProgress.done();
+        }
+      );
+    };
 
-		/**
-		 * Trigger the modal
-		 */
-		me.triggerModal = function() {
-			var allowedExtMarkup = $.map(me.allowed.split(','), function(ext) {
-				return '<span class="label label-success">' + ext.toUpperCase() + '</span>';
-			});
-			var $modal = Modal.show(
-				me.$btn.attr('title'),
-				'<div class="form-control-wrap">' +
-					'<input type="text" class="form-control online-media-url" placeholder="' + me.placeholder + '" />' +
-				'</div><div class="help-block">' + me.allowedHelpText + '<br>' + allowedExtMarkup.join(' ') + '</div>',
-				Severity.notice,
-				[{
-					text: me.btnSubmit,
-					btnClass: 'btn',
-					name: 'ok',
-					trigger: function() {
-						var url = $modal.find('input.online-media-url').val();
-						if (url) {
-							$modal.modal('hide');
-							me.addOnlineMedia(url);
-						}
-					}
-				}]
-			);
+    /**
+     * Trigger the modal
+     */
+    me.triggerModal = function() {
+      var allowedExtMarkup = $.map(me.allowed.split(','), function(ext) {
+        return '<span class="label label-success">' + ext.toUpperCase() + '</span>';
+      });
+      var $modal = Modal.show(
+        me.$btn.attr('title'),
+        '<div class="form-control-wrap">' +
+        '<input type="text" class="form-control online-media-url" placeholder="' + me.placeholder + '" />' +
+        '</div><div class="help-block">' + me.allowedHelpText + '<br>' + allowedExtMarkup.join(' ') + '</div>',
+        Severity.notice,
+        [{
+          text: me.btnSubmit,
+          btnClass: 'btn',
+          name: 'ok',
+          trigger: function() {
+            var url = $modal.find('input.online-media-url').val();
+            if (url) {
+              $modal.modal('hide');
+              me.addOnlineMedia(url);
+            }
+          }
+        }]
+      );
 
-			$modal.on('shown.bs.modal', function() {
-				// focus the input field
-				$(this).find('input.online-media-url').first().focus().on('keydown', function(e) {
-					if (e.keyCode === 13) {
-						$modal.find('button[name="ok"]').trigger('click');
-					}
-				});
-			});
-		};
+      $modal.on('shown.bs.modal', function() {
+        // focus the input field
+        $(this).find('input.online-media-url').first().focus().on('keydown', function(e) {
+          if (e.keyCode === 13) {
+            $modal.find('button[name="ok"]').trigger('click');
+          }
+        });
+      });
+    };
 
-		return {triggerModal: me.triggerModal};
-	};
+    return {triggerModal: me.triggerModal};
+  };
 
-	$(document).on('click', '.t3js-online-media-add-btn', function(evt) {
-		evt.preventDefault();
-		var $this = $(this),
-			onlineMediaPlugin = $this.data('OnlineMediaPlugin');
-		if (!onlineMediaPlugin) {
-			$this.data('OnlineMediaPlugin', (onlineMediaPlugin = new OnlineMediaPlugin(this)));
-		}
-		onlineMediaPlugin.triggerModal();
-	});
+  $(document).on('click', '.t3js-online-media-add-btn', function(evt) {
+    evt.preventDefault();
+    var $this = $(this),
+      onlineMediaPlugin = $this.data('OnlineMediaPlugin');
+    if (!onlineMediaPlugin) {
+      $this.data('OnlineMediaPlugin', (onlineMediaPlugin = new OnlineMediaPlugin(this)));
+    }
+    onlineMediaPlugin.triggerModal();
+  });
 
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
index 2fa442d9dc97..d89a014c954d 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageActions.js
@@ -16,222 +16,226 @@
  * JavaScript implementations for page actions
  */
 define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent', 'TYPO3/CMS/Backend/Wizard/NewContentElement'], function($, PersistentStorage, NewContentElement) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{settings: {pageId: number, language: {pageOverlayId: number}}, identifier: {pageTitle: string, hiddenElements: string}, elements: {$pageTitle: null, $showHiddenElementsCheckbox: null}, documentIsReady: boolean}}
-	 * @exports TYPO3/CMS/Backend/PageActions
-	 */
-	var PageActions = {
-		settings: {
-			pageId: 0,
-			language: {
-				pageOverlayId: 0
-			}
-		},
-		identifier: {
-			pageTitle: '.t3js-title-inlineedit',
-			hiddenElements: '.t3js-hidden-record',
-			newButton: '.t3js-toggle-new-content-element-wizard'
-		},
-		elements: {
-			$pageTitle: null,
-			$showHiddenElementsCheckbox: null
-		},
-		documentIsReady: false
-	};
-
-	/**
-	 * Initialize page title renaming
-	 */
-	PageActions.initializePageTitleRenaming = function() {
-		if (!PageActions.documentIsReady) {
-			$(function() {
-				PageActions.initializePageTitleRenaming();
-			});
-			return;
-		}
-		if (PageActions.settings.pageId <= 0) {
-			return;
-		}
-
-		var $editActionLink = $('<a class="hidden" href="#" data-action="edit"><span class="t3-icon fa fa-pencil"></span></a>');
-		$editActionLink.on('click', function(e) {
-			e.preventDefault();
-			PageActions.editPageTitle();
-		});
-		PageActions.elements.$pageTitle
-			.on('dblclick', PageActions.editPageTitle)
-			.on('mouseover', function() { $editActionLink.removeClass('hidden'); })
-			.on('mouseout', function() { $editActionLink.addClass('hidden'); })
-			.append($editActionLink);
-	};
-
-	/**
-	 * Initialize elements
-	 */
-	PageActions.initializeElements = function() {
-		PageActions.elements.$pageTitle = $(PageActions.identifier.pageTitle + ':first');
-		PageActions.elements.$showHiddenElementsCheckbox = $('#checkTt_content_showHidden');
-	};
-
-	/**
-	 * Initialize events
-	 */
-	PageActions.initializeEvents = function() {
-		PageActions.elements.$showHiddenElementsCheckbox.on('change', PageActions.toggleContentElementVisibility);
-	};
-
-	/**
-	 * Toggles the "Show hidden content elements" checkbox
-	 */
-	PageActions.toggleContentElementVisibility = function() {
-		var $me = $(this),
-			$hiddenElements = $(PageActions.identifier.hiddenElements);
-
-		// show a spinner to show activity
-		var $spinner = $('<span />', {class: 'checkbox-spinner fa fa-circle-o-notch fa-spin'});
-		$me.hide().after($spinner);
-
-		if ($me.prop('checked')) {
-			$hiddenElements.slideDown();
-		} else {
-			$hiddenElements.slideUp();
-		}
-
-		PersistentStorage.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() {
-			$spinner.remove();
-			$me.show();
-		});
-	};
-
-	/**
-	 * Changes the h1 to an edit form
-	 */
-	PageActions.editPageTitle = function() {
-		var $inputFieldWrap = $(
-				'<form>' +
-					'<div class="form-group">' +
-						'<div class="input-group input-group-lg">' +
-							'<input class="form-control">' +
-							'<span class="input-group-btn">' +
-								'<button class="btn btn-default" type="button" data-action="submit"><span class="t3-icon fa fa-floppy-o"></span></button> ' +
-							'</span>' +
-							'<span class="input-group-btn">' +
-								'<button class="btn btn-default" type="button" data-action="cancel"><span class="t3-icon fa fa-times"></span></button> ' +
-							'</span>' +
-						'</div>' +
-					'</div>' +
-				'</form>'
-			),
-			$inputField = $inputFieldWrap.find('input');
-
-		$inputFieldWrap.find('[data-action=cancel]').on('click', function() {
-			$inputFieldWrap.replaceWith(PageActions.elements.$pageTitle);
-			PageActions.initializePageTitleRenaming();
-		});
-
-		$inputFieldWrap.find('[data-action=submit]').on('click', function() {
-			var newPageTitle = $.trim($inputField.val());
-			if (newPageTitle !== '' && PageActions.elements.$pageTitle.text() !== newPageTitle) {
-				PageActions.saveChanges($inputField);
-			} else {
-				$inputFieldWrap.find('[data-action=cancel]').trigger('click');
-			}
-		});
-
-		// the form stuff is a wacky workaround to prevent the submission of the docheader form
-		$inputField.parents('form').on('submit', function(e) {
-			e.preventDefault();
-			return false;
-		});
-
-		var $h1 = PageActions.elements.$pageTitle;
-		$h1.children().last().remove();
-		$h1.replaceWith($inputFieldWrap);
-		$inputField.val($h1.text()).focus();
-
-		$inputField.on('keyup', function(e) {
-			switch (e.which) {
-				case 13: // enter
-					$inputFieldWrap.find('[data-action=submit]').trigger('click');
-					break;
-				case 27: // escape
-					$inputFieldWrap.find('[data-action=cancel]').trigger('click');
-					break;
-			}
-		});
-	};
-
-	/**
-	 * Set the page id (used in the RequireJS callback)
-	 *
-	 * @param {Number} pageId
-	 */
-	PageActions.setPageId = function(pageId) {
-		PageActions.settings.pageId = pageId;
-	};
-
-	/**
-	 * Set the overlay id
-	 *
-	 * @param {Number} overlayId
-	 */
-	PageActions.setLanguageOverlayId = function(overlayId) {
-		PageActions.settings.language.pageOverlayId = overlayId;
-	};
-
-	/**
-	 * Activate New Content Element Wizard
-	 */
-	PageActions.initializeNewContentElementWizard = function() {
-		$(PageActions.identifier.newButton).click(function() {
-			NewContentElement.wizard($(this).data('url'), $(this).data('title'));
-		});
-	};
-
-	/**
-	 * Save the changes and reload the page tree
-	 *
-	 * @param {Object} $field
-	 */
-	PageActions.saveChanges = function($field) {
-		var $inputFieldWrap = $field.parents('form');
-		$inputFieldWrap.find('button').addClass('disabled');
-		$field.attr('disabled', 'disabled');
-
-		var parameters = {},
-			recordUid;
-
-		if (PageActions.settings.language.pageOverlayId === 0) {
-			recordUid = PageActions.settings.pageId;
-		} else {
-			recordUid = PageActions.settings.language.pageOverlayId;
-		}
-
-		parameters.data = {};
-		parameters.data['pages'] = {};
-		parameters.data['pages'][recordUid] = {title: $field.val()};
-
-		require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) {
-			DataHandler.process(parameters).done(function() {
-				$inputFieldWrap.find('[data-action=cancel]').trigger('click');
-				PageActions.elements.$pageTitle.text($field.val());
-				PageActions.initializePageTitleRenaming();
-				top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-			}).fail(function() {
-				$inputFieldWrap.find('[data-action=cancel]').trigger('click');
-			});
-		});
-	};
-
-	$(function() {
-		PageActions.initializeElements();
-		PageActions.initializeEvents();
-		PageActions.initializeNewContentElementWizard();
-		PageActions.documentIsReady = true;
-	});
-
-	return PageActions;
+  'use strict';
+
+  /**
+   *
+   * @type {{settings: {pageId: number, language: {pageOverlayId: number}}, identifier: {pageTitle: string, hiddenElements: string}, elements: {$pageTitle: null, $showHiddenElementsCheckbox: null}, documentIsReady: boolean}}
+   * @exports TYPO3/CMS/Backend/PageActions
+   */
+  var PageActions = {
+    settings: {
+      pageId: 0,
+      language: {
+        pageOverlayId: 0
+      }
+    },
+    identifier: {
+      pageTitle: '.t3js-title-inlineedit',
+      hiddenElements: '.t3js-hidden-record',
+      newButton: '.t3js-toggle-new-content-element-wizard'
+    },
+    elements: {
+      $pageTitle: null,
+      $showHiddenElementsCheckbox: null
+    },
+    documentIsReady: false
+  };
+
+  /**
+   * Initialize page title renaming
+   */
+  PageActions.initializePageTitleRenaming = function() {
+    if (!PageActions.documentIsReady) {
+      $(function() {
+        PageActions.initializePageTitleRenaming();
+      });
+      return;
+    }
+    if (PageActions.settings.pageId <= 0) {
+      return;
+    }
+
+    var $editActionLink = $('<a class="hidden" href="#" data-action="edit"><span class="t3-icon fa fa-pencil"></span></a>');
+    $editActionLink.on('click', function(e) {
+      e.preventDefault();
+      PageActions.editPageTitle();
+    });
+    PageActions.elements.$pageTitle
+      .on('dblclick', PageActions.editPageTitle)
+      .on('mouseover', function() {
+        $editActionLink.removeClass('hidden');
+      })
+      .on('mouseout', function() {
+        $editActionLink.addClass('hidden');
+      })
+      .append($editActionLink);
+  };
+
+  /**
+   * Initialize elements
+   */
+  PageActions.initializeElements = function() {
+    PageActions.elements.$pageTitle = $(PageActions.identifier.pageTitle + ':first');
+    PageActions.elements.$showHiddenElementsCheckbox = $('#checkTt_content_showHidden');
+  };
+
+  /**
+   * Initialize events
+   */
+  PageActions.initializeEvents = function() {
+    PageActions.elements.$showHiddenElementsCheckbox.on('change', PageActions.toggleContentElementVisibility);
+  };
+
+  /**
+   * Toggles the "Show hidden content elements" checkbox
+   */
+  PageActions.toggleContentElementVisibility = function() {
+    var $me = $(this),
+      $hiddenElements = $(PageActions.identifier.hiddenElements);
+
+    // show a spinner to show activity
+    var $spinner = $('<span />', {class: 'checkbox-spinner fa fa-circle-o-notch fa-spin'});
+    $me.hide().after($spinner);
+
+    if ($me.prop('checked')) {
+      $hiddenElements.slideDown();
+    } else {
+      $hiddenElements.slideUp();
+    }
+
+    PersistentStorage.set('moduleData.web_layout.tt_content_showHidden', $me.prop('checked') ? 1 : 0).done(function() {
+      $spinner.remove();
+      $me.show();
+    });
+  };
+
+  /**
+   * Changes the h1 to an edit form
+   */
+  PageActions.editPageTitle = function() {
+    var $inputFieldWrap = $(
+      '<form>' +
+      '<div class="form-group">' +
+      '<div class="input-group input-group-lg">' +
+      '<input class="form-control">' +
+      '<span class="input-group-btn">' +
+      '<button class="btn btn-default" type="button" data-action="submit"><span class="t3-icon fa fa-floppy-o"></span></button> ' +
+      '</span>' +
+      '<span class="input-group-btn">' +
+      '<button class="btn btn-default" type="button" data-action="cancel"><span class="t3-icon fa fa-times"></span></button> ' +
+      '</span>' +
+      '</div>' +
+      '</div>' +
+      '</form>'
+      ),
+      $inputField = $inputFieldWrap.find('input');
+
+    $inputFieldWrap.find('[data-action=cancel]').on('click', function() {
+      $inputFieldWrap.replaceWith(PageActions.elements.$pageTitle);
+      PageActions.initializePageTitleRenaming();
+    });
+
+    $inputFieldWrap.find('[data-action=submit]').on('click', function() {
+      var newPageTitle = $.trim($inputField.val());
+      if (newPageTitle !== '' && PageActions.elements.$pageTitle.text() !== newPageTitle) {
+        PageActions.saveChanges($inputField);
+      } else {
+        $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+      }
+    });
+
+    // the form stuff is a wacky workaround to prevent the submission of the docheader form
+    $inputField.parents('form').on('submit', function(e) {
+      e.preventDefault();
+      return false;
+    });
+
+    var $h1 = PageActions.elements.$pageTitle;
+    $h1.children().last().remove();
+    $h1.replaceWith($inputFieldWrap);
+    $inputField.val($h1.text()).focus();
+
+    $inputField.on('keyup', function(e) {
+      switch (e.which) {
+        case 13: // enter
+          $inputFieldWrap.find('[data-action=submit]').trigger('click');
+          break;
+        case 27: // escape
+          $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+          break;
+      }
+    });
+  };
+
+  /**
+   * Set the page id (used in the RequireJS callback)
+   *
+   * @param {Number} pageId
+   */
+  PageActions.setPageId = function(pageId) {
+    PageActions.settings.pageId = pageId;
+  };
+
+  /**
+   * Set the overlay id
+   *
+   * @param {Number} overlayId
+   */
+  PageActions.setLanguageOverlayId = function(overlayId) {
+    PageActions.settings.language.pageOverlayId = overlayId;
+  };
+
+  /**
+   * Activate New Content Element Wizard
+   */
+  PageActions.initializeNewContentElementWizard = function() {
+    $(PageActions.identifier.newButton).click(function() {
+      NewContentElement.wizard($(this).data('url'), $(this).data('title'));
+    });
+  };
+
+  /**
+   * Save the changes and reload the page tree
+   *
+   * @param {Object} $field
+   */
+  PageActions.saveChanges = function($field) {
+    var $inputFieldWrap = $field.parents('form');
+    $inputFieldWrap.find('button').addClass('disabled');
+    $field.attr('disabled', 'disabled');
+
+    var parameters = {},
+      recordUid;
+
+    if (PageActions.settings.language.pageOverlayId === 0) {
+      recordUid = PageActions.settings.pageId;
+    } else {
+      recordUid = PageActions.settings.language.pageOverlayId;
+    }
+
+    parameters.data = {};
+    parameters.data['pages'] = {};
+    parameters.data['pages'][recordUid] = {title: $field.val()};
+
+    require(['TYPO3/CMS/Backend/AjaxDataHandler'], function(DataHandler) {
+      DataHandler.process(parameters).done(function() {
+        $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+        PageActions.elements.$pageTitle.text($field.val());
+        PageActions.initializePageTitleRenaming();
+        top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+      }).fail(function() {
+        $inputFieldWrap.find('[data-action=cancel]').trigger('click');
+      });
+    });
+  };
+
+  $(function() {
+    PageActions.initializeElements();
+    PageActions.initializeEvents();
+    PageActions.initializeNewContentElementWizard();
+    PageActions.documentIsReady = true;
+  });
+
+  return PageActions;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js
index 23259dc54a34..403c08429af4 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTree.js
@@ -21,16 +21,16 @@ define(['jquery',
     'TYPO3/CMS/Backend/SvgTree',
     'TYPO3/CMS/Backend/ContextMenu',
     'TYPO3/CMS/Backend/Storage/Persistent',
-    'TYPO3/CMS/Backend/Notification',
+    'TYPO3/CMS/Backend/Notification'
   ],
-  function ($, d3, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) {
+  function($, d3, Icons, PageTreeDragDrop, SvgTree, ContextMenu, Persistent, Notification) {
     'use strict';
 
     /**
      * @constructor
      * @exports TYPO3/CMS/Backend/PageTree/PageTree
      */
-    var PageTree = function () {
+    var PageTree = function() {
       SvgTree.call(this);
     };
 
@@ -43,7 +43,7 @@ define(['jquery',
      * @param {String} selector
      * @param {Object} settings
      */
-    PageTree.prototype.initialize = function (selector, settings) {
+    PageTree.prototype.initialize = function(selector, settings) {
       var _this = this;
 
       if (!_super_.initialize.call(_this, selector, settings)) {
@@ -68,7 +68,7 @@ define(['jquery',
     /**
      * Add mount point
      */
-    PageTree.prototype.addMountPoint = function (breadcrumb) {
+    PageTree.prototype.addMountPoint = function(breadcrumb) {
       var _this = this;
 
       if (_this.wrapper.parent().find('.node-mount-point').length) {
@@ -77,24 +77,24 @@ define(['jquery',
 
       _this.mountPoint = _this.wrapper.before(
         '<div class="node-mount-point">' +
-          '<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' +
-          '<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' +
-          '<div class="node-mount-point__icon" data-tree-icon="actions-close" title="' + TYPO3.lang['labels.temporaryDBmount'] + '"></div>' +
+        '<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' +
+        '<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' +
+        '<div class="node-mount-point__icon" data-tree-icon="actions-close" title="' + TYPO3.lang['labels.temporaryDBmount'] + '"></div>' +
         '</div>'
       );
 
       _this.wrapper.parent()
         .find('[data-tree-icon=actions-close]')
-        .on('click', function () {
+        .on('click', function() {
           top.TYPO3.Backend.NavigationContainer.PageTree.unsetTemporaryMountPoint();
           _this.wrapper.parent().find('.node-mount-point').remove();
         });
 
       //get icons
-      _this.wrapper.parent().find('.node-mount-point [data-tree-icon]').each(function () {
+      _this.wrapper.parent().find('.node-mount-point [data-tree-icon]').each(function() {
         var $this = $(this);
 
-        Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small, null, null, 'inline').done(function (icon) {
+        Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small, null, null, 'inline').done(function(icon) {
           $this.append(icon);
         });
       });
@@ -105,19 +105,19 @@ define(['jquery',
      *
      * @param error
      */
-    PageTree.prototype.errorNotification = function (error) {
+    PageTree.prototype.errorNotification = function(error) {
       var title = TYPO3.lang.pagetree_networkErrorTitle;
       var desc = TYPO3.lang.pagetree_networkErrorDesc;
 
       if (error && error.target && (error.target.status || error.target.statusText)) {
-        title += ' - ' + (error.target.status || '')  + ' ' + (error.target.statusText || '');
+        title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || '');
       }
 
       Notification.error(title, desc);
       this.loadData();
     };
 
-    PageTree.prototype.sendChangeCommand = function (data) {
+    PageTree.prototype.sendChangeCommand = function(data) {
       var _this = this;
       var params = '';
 
@@ -148,17 +148,17 @@ define(['jquery',
       d3.request(top.TYPO3.settings.ajaxUrls.record_process)
         .header('X-Requested-With', 'XMLHttpRequest')
         .header('Content-Type', 'application/x-www-form-urlencoded')
-        .on('error', function (error) {
+        .on('error', function(error) {
           _this.errorNotification(error);
           throw error;
         })
-        .post(params, function (data) {
+        .post(params, function(data) {
           if (data) {
             var response = JSON.parse(data.response);
 
             if (response && response.hasErrors) {
               if (response.messages) {
-                $.each(response.messages, function (id, message) {
+                $.each(response.messages, function(id, message) {
                   Notification.error(
                     message.title,
                     message.message
@@ -185,7 +185,7 @@ define(['jquery',
      *
      * @param {Node} node
      */
-    PageTree.prototype.nodeSelectedAfter = function (node) {
+    PageTree.prototype.nodeSelectedAfter = function(node) {
       var separator = '?';
       if (currentSubScript.indexOf('?') !== -1) {
         separator = '&';
@@ -197,7 +197,7 @@ define(['jquery',
       );
     };
 
-    PageTree.prototype.nodeRightClick = function (node) {
+    PageTree.prototype.nodeRightClick = function(node) {
       d3.event.preventDefault();
       var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']');
 
@@ -212,7 +212,7 @@ define(['jquery',
       }
     };
 
-    PageTree.prototype.contextmenu = function (node) {
+    PageTree.prototype.contextmenu = function(node) {
       var $node = $(node).closest('svg').find('.nodes .node[data-state-id=' + this.stateIdentifier + ']');
 
       if ($node.length) {
@@ -226,27 +226,27 @@ define(['jquery',
       }
     };
 
-    PageTree.prototype.updateSvg = function (nodeEnter) {
+    PageTree.prototype.updateSvg = function(nodeEnter) {
       nodeEnter
         .select('use')
         .attr('data-table', 'pages');
     };
 
-    PageTree.prototype.hideChildren = function (node) {
+    PageTree.prototype.hideChildren = function(node) {
       _super_.hideChildren(node);
       Persistent.set('BackendComponents.States.Pagetree.stateHash.' + node.stateIdentifier, 0);
     };
 
-    PageTree.prototype.showChildren = function (node) {
+    PageTree.prototype.showChildren = function(node) {
       _super_.showChildren(node);
       Persistent.set('BackendComponents.States.Pagetree.stateHash.' + node.stateIdentifier, 1);
     };
 
-    PageTree.prototype.updateNodeBgClass = function (nodeBg) {
+    PageTree.prototype.updateNodeBgClass = function(nodeBg) {
       return _super_.updateNodeBgClass.call(this, nodeBg).call(this.dragDrop.drag());
     };
 
-    PageTree.prototype.nodesUpdate = function (nodes) {
+    PageTree.prototype.nodesUpdate = function(nodes) {
       var _this = this;
 
       nodes = _super_.nodesUpdate.call(this, nodes)
@@ -258,10 +258,10 @@ define(['jquery',
         .attr('class', 'node-stop')
         .attr('dx', 30)
         .attr('dy', 5)
-        .attr('visibility', function (node) {
+        .attr('visibility', function(node) {
           return (node.stopPageTree && (node.depth !== 0)) ? 'visible' : 'hidden';
         })
-        .on('click', function (node) {
+        .on('click', function(node) {
           _this.setTemporaryMountPoint(node.identifier);
         });
 
@@ -274,24 +274,24 @@ define(['jquery',
      *
      * @param {Node} node
      */
-    PageTree.prototype.appendTextElement = function (node) {
+    PageTree.prototype.appendTextElement = function(node) {
       var _this = this;
       var clicks = 0;
 
       _super_.appendTextElement.call(this, node)
-        .attr('dx', function (node) {
+        .attr('dx', function(node) {
           if (node.stopPageTree && node.depth !== 0) {
             return _this.textPosition + 15;
           }
 
           return _this.textPosition;
         })
-        .on('click', function (node) {
+        .on('click', function(node) {
           if (node.identifier !== 0) {
             clicks++;
 
             if (clicks === 1) {
-              setTimeout(function () {
+              setTimeout(function() {
                 if (clicks === 1) {
                   _this.clickOnLabel(node, this);
                   _this.nodeBgEvents().click(node, this);
@@ -311,24 +311,24 @@ define(['jquery',
         });
     };
 
-    PageTree.prototype.setTemporaryMountPoint = function (pid) {
+    PageTree.prototype.setTemporaryMountPoint = function(pid) {
       var params = 'pid=' + pid;
       var _this = this;
 
       d3.request(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point)
         .header('X-Requested-With', 'XMLHttpRequest')
         .header('Content-Type', 'application/x-www-form-urlencoded')
-        .on('error', function (error) {
+        .on('error', function(error) {
           _this.errorNotification(error);
           throw error;
         })
-        .post(params, function (data) {
+        .post(params, function(data) {
           if (data) {
             var response = JSON.parse(data.response);
 
             if (response && response.hasErrors) {
               if (response.messages) {
-                $.each(response.messages, function (id, message) {
+                $.each(response.messages, function(id, message) {
                   Notification.error(
                     message.title,
                     message.message
@@ -349,14 +349,14 @@ define(['jquery',
         });
     };
 
-    PageTree.prototype.unsetTemporaryMountPoint = function () {
+    PageTree.prototype.unsetTemporaryMountPoint = function() {
       var _this = this;
-      Persistent.unset('pageTree_temporaryMountPoint').then(function () {
+      Persistent.unset('pageTree_temporaryMountPoint').then(function() {
         _this.refreshTree();
       });
     };
 
-    PageTree.prototype.sendEditNodeLabelCommand = function (node) {
+    PageTree.prototype.sendEditNodeLabelCommand = function(node) {
       var _this = this;
 
       var params = '&data[pages][' + node.identifier + '][' + node.nameSourceField + ']=' + node.newName;
@@ -367,17 +367,17 @@ define(['jquery',
       d3.request(top.TYPO3.settings.ajaxUrls.record_process)
         .header('X-Requested-With', 'XMLHttpRequest')
         .header('Content-Type', 'application/x-www-form-urlencoded')
-        .on('error', function (error) {
+        .on('error', function(error) {
           _this.errorNotification(error);
           throw error;
         })
-        .post(params, function (data) {
+        .post(params, function(data) {
           if (data) {
             var response = JSON.parse(data.response);
 
             if (response && response.hasErrors) {
               if (response.messages) {
-                $.each(response.messages, function (id, message) {
+                $.each(response.messages, function(id, message) {
                   Notification.error(
                     message.title,
                     message.message
@@ -402,7 +402,7 @@ define(['jquery',
         });
     };
 
-    PageTree.prototype.editNodeLabel = function (node) {
+    PageTree.prototype.editNodeLabel = function(node) {
       var _this = this;
 
       _this.removeEditedText();
@@ -411,7 +411,7 @@ define(['jquery',
       d3.select(_this.svg.node().parentNode)
         .append('input')
         .attr('class', 'node-edit')
-        .style('top', function () {
+        .style('top', function() {
           var top = node.y + _this.settings.marginTop;
           return top + 'px';
         })
@@ -420,7 +420,7 @@ define(['jquery',
         .style('height', _this.settings.nodeHeight + 'px')
         .attr('type', 'text')
         .attr('value', node.name)
-        .on('keydown', function () {
+        .on('keydown', function() {
           var code = d3.event.keyCode;
 
           if (code === 13 || code === 9) { //enter || tab
@@ -441,7 +441,7 @@ define(['jquery',
             _this.removeEditedText();
           }
         })
-        .on('blur', function () {
+        .on('blur', function() {
           if (_this.nodeIsEdit) {
             var newName = this.value.trim();
 
@@ -459,7 +459,7 @@ define(['jquery',
         .select();
     };
 
-    PageTree.prototype.removeEditedText = function () {
+    PageTree.prototype.removeEditedText = function() {
       var _this = this;
       var inputWrapper = d3.selectAll('.node-edit');
 
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js
index 31e4a10f4c10..25d69c9b3ef9 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeDragDrop.js
@@ -17,11 +17,11 @@
  * Provides drag&drop related functionality for the SVG page tree
  */
 define([
-    'jquery',
-    'd3',
-    'TYPO3/CMS/Backend/Modal',
-    'TYPO3/CMS/Backend/Severity',
-  ], function ($, d3, Modal, Severity) {
+  'jquery',
+  'd3',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity'
+], function($, d3, Modal, Severity) {
   'use strict';
 
   /**
@@ -40,7 +40,7 @@ define([
      */
     dropZoneDelete: null,
 
-    init: function (svgTree) {
+    init: function(svgTree) {
       this.tree = svgTree;
     },
 
@@ -49,7 +49,7 @@ define([
      *
      * Returns initialized d3.drag() function
      */
-    drag: function () {
+    drag: function() {
       var self = {};
       var _this = this;
       var tree = _this.tree;
@@ -60,7 +60,7 @@ define([
        * @param node
        * @returns {string}
        */
-      self.getDropZoneOpenTransform = function (node) {
+      self.getDropZoneOpenTransform = function(node) {
         var svgWidth = parseFloat(tree.svg.style('width')) || 300;
 
         return 'translate(' + (svgWidth - 58 - node.x) + ', -10)';
@@ -72,13 +72,13 @@ define([
        * @param node
        * @returns {string}
        */
-      self.getDropZoneCloseTransform = function (node) {
+      self.getDropZoneCloseTransform = function(node) {
         var svgWidth = parseFloat(tree.svg.style('width')) || 300;
 
         return 'translate(' + (svgWidth - node.x) + ', -10)';
       };
 
-      self.dragStart = function (node) {
+      self.dragStart = function(node) {
         if (tree.settings.isDragAnDrop !== true || node.depth === 0) {
           return false;
         }
@@ -103,10 +103,10 @@ define([
             .attr('width', '50px')
             .attr('x', 0)
             .attr('y', 0)
-            .on('mouseover', function () {
+            .on('mouseover', function() {
               tree.nodeIsOverDelete = true;
             })
-            .on('mouseout', function () {
+            .on('mouseout', function() {
               tree.nodeIsOverDelete = false;
             });
 
@@ -122,7 +122,7 @@ define([
         $.extend(self, _this.setDragStart());
       };
 
-      self.dragDragged = function (node) {
+      self.dragDragged = function(node) {
         if (_this.isDragNodeDistanceMore(self, 10)) {
           self.startDrag = true;
         } else {
@@ -168,7 +168,7 @@ define([
         $(document).find('.node-dd').css({
           left: left,
           top: top,
-          display: 'block',
+          display: 'block'
         });
 
         tree.settings.nodeDragPosition = false;
@@ -179,7 +179,7 @@ define([
           || (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsStateIdentifier.indexOf(node.stateIdentifier) !== -1)
           || !tree.isOverSvg) {
 
-          _this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop' });
+          _this.addNodeDdClass({$nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop'});
 
           if (!tree.isOverSvg) {
             _this.tree.nodesBgContainer
@@ -194,7 +194,7 @@ define([
               .attr('data-open', 'true');
           }
         } else if (!tree.settings.nodeOver.node) {
-          _this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop' });
+          _this.addNodeDdClass({$nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop'});
           _this.tree.nodesBgContainer
             .selectAll('.node-bg__border')
             .style('display', 'none');
@@ -210,7 +210,7 @@ define([
         }
       };
 
-      self.dragEnd = function (node) {
+      self.dragEnd = function(node) {
         _this.setDragEnd();
 
         if (!self.startDrag || tree.settings.isDragAnDrop !== true || node.depth === 0) {
@@ -234,7 +234,7 @@ define([
           $nodesWrap: $svg.find('.nodes-wrapper'),
           className: '',
           rmClass: 'dragging',
-          setCanNodeDrag: false,
+          setCanNodeDrag: false
         });
 
         $nodesBg
@@ -257,7 +257,7 @@ define([
             || !tree.isOverSvg
           )
         ) {
-          var options = _this.changeNodePosition({ droppedNode: droppedNode });
+          var options = _this.changeNodePosition({droppedNode: droppedNode});
 
           var modalText = options.position === 'in' ? TYPO3.lang['mess.move_into'] : TYPO3.lang['mess.move_after'];
           modalText = modalText.replace('%s', options.node.name).replace('%s', options.target.name);
@@ -270,20 +270,20 @@ define([
                 text: $(this).data('button-close-text') || TYPO3.lang['labels.cancel'] || 'Cancel',
                 active: true,
                 btnClass: 'btn-default',
-                name: 'cancel',
+                name: 'cancel'
               },
               {
                 text: $(this).data('button-ok-text') || TYPO3.lang['cm.copy'] || 'Copy',
                 btnClass: 'btn-warning',
-                name: 'copy',
+                name: 'copy'
               },
               {
                 text: $(this).data('button-ok-text') || TYPO3.lang['button.move'] || 'Move',
                 btnClass: 'btn-warning',
-                name: 'move',
-              },
+                name: 'move'
+              }
             ])
-            .on('button.clicked', function (e) {
+            .on('button.clicked', function(e) {
               if (e.target.name === 'move') {
                 options.command = 'move';
                 tree.sendChangeCommand(options);
@@ -295,7 +295,7 @@ define([
               Modal.dismiss();
             });
         } else if (tree.nodeIsOverDelete) {
-          var options = _this.changeNodePosition({ droppedNode: droppedNode, command: 'delete' });
+          var options = _this.changeNodePosition({droppedNode: droppedNode, command: 'delete'});
           if (tree.settings.displayDeleteConfirmation) {
             var $modal = Modal.confirm(
               TYPO3.lang.deleteItem,
@@ -305,16 +305,16 @@ define([
                   text: $(this).data('button-close-text') || TYPO3.lang['labels.cancel'] || 'Cancel',
                   active: true,
                   btnClass: 'btn-default',
-                  name: 'cancel',
+                  name: 'cancel'
                 },
                 {
                   text: $(this).data('button-ok-text') || TYPO3.lang['cm.delete'] || 'Delete',
                   btnClass: 'btn-warning',
-                  name: 'delete',
-                },
+                  name: 'delete'
+                }
               ]);
 
-            $modal.on('button.clicked', function (e) {
+            $modal.on('button.clicked', function(e) {
               if (e.target.name === 'delete') {
 
                 tree.sendChangeCommand(options);
@@ -337,7 +337,7 @@ define([
     /**
      * Open node with children while holding the node/element over this node for one second
      */
-    openNodeTimeout: function () {
+    openNodeTimeout: function() {
       var _this = this;
 
       if (!_this.timeout) {
@@ -348,7 +348,7 @@ define([
         if (_this.timeout.node != _this.tree.settings.nodeOver.node) {
           _this.timeout.node = _this.tree.settings.nodeOver;
           clearTimeout(_this.timeout.time);
-          _this.timeout.time = setTimeout(function () {
+          _this.timeout.time = setTimeout(function() {
             if (_this.tree.settings.nodeOver.node) {
               _this.tree.showChildren(_this.tree.settings.nodeOver.node);
               _this.tree.prepareDataForVisibleNodes();
@@ -361,7 +361,7 @@ define([
       }
     },
 
-    changeNodeClasses: function () {
+    changeNodeClasses: function() {
       var elementNodeBg = this.tree.svg.select('.node-over');
       var $svg = $(this.tree.svg.node());
       var $nodesWrap = $svg.find('.nodes-wrapper');
@@ -390,19 +390,19 @@ define([
             this.addNodeDdClass({
               $nodeDd: $nodeDd,
               $nodesWrap: $nodesWrap,
-              className: 'nodrop',
+              className: 'nodrop'
             });
           } else if (this.tree.settings.nodeOver.node.firstChild) {
             this.addNodeDdClass({
               $nodeDd: $nodeDd,
               $nodesWrap: $nodesWrap,
-              className: 'ok-above',
+              className: 'ok-above'
             });
           } else {
             this.addNodeDdClass({
               $nodeDd: $nodeDd,
               $nodesWrap: $nodesWrap,
-              className: 'ok-between',
+              className: 'ok-between'
             });
           }
 
@@ -415,7 +415,7 @@ define([
             this.addNodeDdClass({
               $nodeDd: $nodeDd,
               $nodesWrap: $nodesWrap,
-              className: 'ok-append',
+              className: 'ok-append'
             });
             this.tree.settings.nodeDragPosition = 'in';
           } else {
@@ -427,14 +427,14 @@ define([
               this.addNodeDdClass({
                 $nodeDd: $nodeDd,
                 $nodesWrap: $nodesWrap,
-                className: 'ok-below',
+                className: 'ok-below'
               });
 
             } else {
               this.addNodeDdClass({
                 $nodeDd: $nodeDd,
                 $nodesWrap: $nodesWrap,
-                className: 'ok-between',
+                className: 'ok-between'
               });
             }
 
@@ -447,7 +447,7 @@ define([
           this.addNodeDdClass({
             $nodeDd: $nodeDd,
             $nodesWrap: $nodesWrap,
-            className: 'ok-append',
+            className: 'ok-append'
           });
           this.tree.settings.nodeDragPosition = 'in';
         }
@@ -459,12 +459,12 @@ define([
         this.addNodeDdClass({
           $nodeDd: $nodeDd,
           $nodesWrap: $nodesWrap,
-          className: 'nodrop',
+          className: 'nodrop'
         });
       }
     },
 
-    addNodeDdClass: function (options) {
+    addNodeDdClass: function(options) {
       var clearClass = ' #prefix#--nodrop #prefix#--ok-append #prefix#--ok-below #prefix#--ok-between #prefix#--ok-above';
       var rmClass = '';
       var addClass = '';
@@ -499,9 +499,9 @@ define([
      * @param {Integer} distance
      * @returns {boolean}
      */
-    isDragNodeDistanceMore: function (data, distance) {
+    isDragNodeDistanceMore: function(data, distance) {
       return (data.startDrag ||
-         (((data.startPageX - distance) > d3.event.sourceEvent.pageX) ||
+        (((data.startPageX - distance) > d3.event.sourceEvent.pageX) ||
           ((data.startPageX + distance) < d3.event.sourceEvent.pageX) ||
           ((data.startPageY - distance) > d3.event.sourceEvent.pageY) ||
           ((data.startPageY + distance) < d3.event.sourceEvent.pageY)));
@@ -512,21 +512,21 @@ define([
      *
      * @returns {{startPageX, startPageY, startDrag: boolean}}
      */
-    setDragStart: function () {
-      $('body iframe').css({ 'pointer-events': 'none' });
+    setDragStart: function() {
+      $('body iframe').css({'pointer-events': 'none'});
 
       return {
         startPageX: d3.event.sourceEvent.pageX,
         startPageY: d3.event.sourceEvent.pageY,
-        startDrag: false,
+        startDrag: false
       };
     },
 
     /**
      * Sets the same parameters on end for method drag() and dragToolbar()
      */
-    setDragEnd: function () {
-      $('body iframe').css({ 'pointer-events': '' });
+    setDragEnd: function() {
+      $('body iframe').css({'pointer-events': ''});
     },
 
     /**
@@ -534,12 +534,12 @@ define([
      *
      * Returns method from d3js
      */
-    dragToolbar: function () {
+    dragToolbar: function() {
       var self = {};
       var _this = this;
       var tree = _this.tree;
 
-      self.dragStart = function () {
+      self.dragStart = function() {
         self.id = $(this).data('node-type');
         self.name = $(this).attr('title');
         self.tooltip = $(this).attr('tooltip');
@@ -548,7 +548,7 @@ define([
         $.extend(self, _this.setDragStart());
       };
 
-      self.dragDragged = function () {
+      self.dragDragged = function() {
         if (_this.isDragNodeDistanceMore(self, 10)) {
           self.startDrag = true;
         } else {
@@ -584,13 +584,13 @@ define([
         $(document).find('.node-dd').css({
           left: left,
           top: top,
-          display: 'block',
+          display: 'block'
         });
 
         _this.changeNodeClasses();
       };
 
-      self.dragEnd = function () {
+      self.dragEnd = function() {
         _this.setDragEnd();
 
         if (!self.startDrag) {
@@ -614,7 +614,7 @@ define([
           $nodesWrap: $svg.find('.nodes-wrapper'),
           className: '',
           rmClass: 'dragging',
-          setCanNodeDrag: false,
+          setCanNodeDrag: false
         });
 
         $nodesBg
@@ -643,7 +643,7 @@ define([
             icon: self.icon,
             position: _this.tree.settings.nodeDragPosition,
             command: 'new',
-            target: _this.tree.settings.nodeOver.node,
+            target: _this.tree.settings.nodeOver.node
           };
 
           _this.addNewNode(data);
@@ -656,7 +656,7 @@ define([
         .on('end', self.dragEnd);
     },
 
-    changeNodePosition: function (options) {
+    changeNodePosition: function(options) {
       var _this = this;
       var tree = _this.tree;
       var nodes = tree.nodes;
@@ -686,7 +686,7 @@ define([
         uid: uid, // dragged node id
         target: target, // hovered node
         position: position, // before, in, after
-        command: options.command, // element is copied or moved
+        command: options.command // element is copied or moved
       };
 
       $.extend(data, options);
@@ -701,7 +701,7 @@ define([
      * @param {Integer} index
      * @returns {Array} [position, target]
      */
-    setNodePositionAndTarget: function (nodeDepth, index) {
+    setNodePositionAndTarget: function(nodeDepth, index) {
       if (index > 0) {
         index--;
       }
@@ -728,12 +728,12 @@ define([
      *
      * @type {Object} options
      */
-    addNewNode: function (options) {
+    addNewNode: function(options) {
       var _this = this;
       var target = options.target;
       var index = _this.tree.nodes.indexOf(target);
       var newNode = {};
-      var removeNode = function (newNode) {
+      var removeNode = function(newNode) {
         var index = _this.tree.nodes.indexOf(newNode);
 
         // if newNode is only one child
@@ -755,8 +755,8 @@ define([
       newNode.target = target;
       newNode.parents = target.parents;
       newNode.parentsStateIdentifier = target.parentsStateIdentifier;
-      newNode.depth =  target.depth;
-      newNode.position =  options.position;
+      newNode.depth = target.depth;
+      newNode.position = options.position;
       newNode.name = (typeof options.title !== 'undefined') ? options.title : TYPO3.lang['tree.defaultPageTitle'];
       newNode.y = newNode.y || newNode.target.y;
       newNode.x = newNode.x || newNode.target.x;
@@ -799,7 +799,7 @@ define([
         .style('height', _this.tree.settings.nodeHeight + 'px')
         .attr('text', 'text')
         .attr('value', newNode.name)
-        .on('keydown', function () {
+        .on('keydown', function() {
           var code = d3.event.keyCode;
 
           if (code === 13 || code === 9) { // enter || tab
@@ -818,7 +818,7 @@ define([
             removeNode(newNode);
           }
         })
-        .on('blur', function () {
+        .on('blur', function() {
           if (_this.tree.nodeIsEdit && (_this.tree.nodes.indexOf(newNode) > -1)) {
             var newName = this.value.trim();
 
@@ -840,18 +840,18 @@ define([
      *
      * @returns {String}
      */
-    template: function (icon, name) {
+    template: function(icon, name) {
       return '<div class="node-dd node-dd--nodrop">' +
-          '<div class="node-dd__ctrl-icon">' +
-          '</div>' +
-            '<div class="node-dd__text">' +
-              '<span class="node-dd__icon">' +
-                '<svg aria-hidden="true" width="16px" height="16px"><use xlink:href="' + icon + '"/></svg>' +
-              '</span>' +
-              '<span class="node-dd__name">' + name + '</span>' +
-          '</div>' +
+        '<div class="node-dd__ctrl-icon">' +
+        '</div>' +
+        '<div class="node-dd__text">' +
+        '<span class="node-dd__icon">' +
+        '<svg aria-hidden="true" width="16px" height="16px"><use xlink:href="' + icon + '"/></svg>' +
+        '</span>' +
+        '<span class="node-dd__name">' + name + '</span>' +
+        '</div>' +
         '</div>';
-    },
+    }
   };
 
   return PageTreeDragDrop;
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js
index a39725abb4b1..400106a0e14a 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeElement.js
@@ -20,24 +20,24 @@ define(['jquery',
     'TYPO3/CMS/Backend/PageTree/PageTree',
     'TYPO3/CMS/Backend/PageTree/PageTreeToolbar',
     'TYPO3/CMS/Backend/Viewport',
-    'TYPO3/CMS/Backend/Icons',
+    'TYPO3/CMS/Backend/Icons'
   ],
-  function ($, PageTree, PageTreeToolbar, Viewport, Icons) {
+  function($, PageTree, PageTreeToolbar, Viewport, Icons) {
     'use strict';
 
     var PageTreeElement = {
       template:
-        '<div id="typo3-pagetree" class="svg-tree">' +
-          '<div>' +
-            '<div id="svg-toolbar" class="svg-toolbar"></div>' +
-              '<div id="typo3-pagetree-treeContainer">' +
-                '<div id="typo3-pagetree-tree" class="svg-tree-wrapper" style="height:1000px;">' +
-                  '<div class="node-loader"></div>' +
-                '</div>' +
-              '</div>' +
-            '</div>' +
-          '<div class="svg-tree-loader"></div>' +
-        '</div>',
+      '<div id="typo3-pagetree" class="svg-tree">' +
+      '<div>' +
+      '<div id="svg-toolbar" class="svg-toolbar"></div>' +
+      '<div id="typo3-pagetree-treeContainer">' +
+      '<div id="typo3-pagetree-tree" class="svg-tree-wrapper" style="height:1000px;">' +
+      '<div class="node-loader"></div>' +
+      '</div>' +
+      '</div>' +
+      '</div>' +
+      '<div class="svg-tree-loader"></div>' +
+      '</div>'
     };
 
     /**
@@ -45,8 +45,8 @@ define(['jquery',
      *
      * @param {String} selector
      */
-    PageTreeElement.initialize = function (selector) {
-      $(function () {
+    PageTreeElement.initialize = function(selector) {
+      $(function() {
         var $element = $(selector);
 
         if ($element.html().trim().length !== 0) {
@@ -56,21 +56,21 @@ define(['jquery',
         var tree = new PageTree();
         $element.append(PageTreeElement.template);
 
-        Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function (spinner) {
+        Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
           $('.node-loader').append(spinner);
         });
 
-        Icons.getIcon('spinner-circle-light', Icons.sizes.large).done(function (spinner) {
+        Icons.getIcon('spinner-circle-light', Icons.sizes.large).done(function(spinner) {
           $('.svg-tree-loader').append(spinner);
         });
 
         var dataUrl = top.TYPO3.settings.ajaxUrls.page_tree_data;
         var configurationUrl = top.TYPO3.settings.ajaxUrls.page_tree_configuration;
 
-        $.ajax({ url: configurationUrl }).done(function (configuration) {
+        $.ajax({url: configurationUrl}).done(function(configuration) {
           tree.initialize($element.find('#typo3-pagetree-tree'), $.extend(configuration, {
             dataUrl: dataUrl,
-            showIcons: true,
+            showIcons: true
           }));
 
           Viewport.NavigationContainer.setComponentInstance(tree);
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js
index 7769ee0c6a3c..6bde7aa1503a 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/PageTree/PageTreeToolbar.js
@@ -20,9 +20,9 @@ define(['jquery',
     'TYPO3/CMS/Backend/PageTree/PageTreeDragDrop',
     'TYPO3/CMS/Backend/Tooltip',
     'TYPO3/CMS/Backend/SvgTree',
-    'TYPO3/CMS/Lang/Lang',
+    'TYPO3/CMS/Lang/Lang'
   ],
-  function ($, Icons, d3, PageTreeDragDrop) {
+  function($, Icons, d3, PageTreeDragDrop) {
     'use strict';
 
     /**
@@ -31,11 +31,11 @@ define(['jquery',
      * @constructor
      * @exports TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar
      */
-    var TreeToolbar = function () {
+    var TreeToolbar = function() {
       this.settings = {
         toolbarSelector: 'tree-toolbar',
         searchInput: '.search-input',
-        target: '.svg-toolbar',
+        target: '.svg-toolbar'
       };
 
       /**
@@ -74,7 +74,7 @@ define(['jquery',
      * @param {String} treeSelector
      * @param {Object} settings
      */
-    TreeToolbar.prototype.initialize = function (treeSelector, settings) {
+    TreeToolbar.prototype.initialize = function(treeSelector, settings) {
       var _this = this;
       _this.$treeWrapper = $(treeSelector);
 
@@ -95,37 +95,37 @@ define(['jquery',
     /**
      * Create toolbar template
      */
-    TreeToolbar.prototype.createTemplate = function () {
+    TreeToolbar.prototype.createTemplate = function() {
       var _this = this;
 
       var $template = $(
         '<div class="' + _this.settings.toolbarSelector + '">' +
-          '<div class="svg-toolbar__menu">' +
-            '<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter">' +
-              '<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="' + TYPO3.lang['tree.buttonFilter'] + '"></button>' +
-            '</div>' +
-            '<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh">' +
-              '<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="' + TYPO3.lang['labels.refresh'] + '"></button>' +
-            '</div>' +
+        '<div class="svg-toolbar__menu">' +
+        '<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="filter">' +
+        '<button class="svg-toolbar__btn" data-tree-icon="actions-filter" title="' + TYPO3.lang['tree.buttonFilter'] + '"></button>' +
+        '</div>' +
+        '<div class="x-btn btn btn-default btn-sm x-btn-noicon js-svg-refresh">' +
+        '<button class="svg-toolbar__btn" data-tree-icon="actions-refresh" title="' + TYPO3.lang['labels.refresh'] + '"></button>' +
+        '</div>' +
         '</div>' +
         '<div class="svg-toolbar__submenu">' +
-          '<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">' +
-            '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tree.searchTermInfo'] + '">' +
-          '</div>' +
-          '<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">' +
-          '</div>' +
-          '</div>' +
+        '<div class="svg-toolbar__submenu-item" data-tree-submenu="filter">' +
+        '<input type="text" class="form-control search-input" placeholder="' + TYPO3.lang['tree.searchTermInfo'] + '">' +
+        '</div>' +
+        '<div class="svg-toolbar__submenu-item" data-tree-submenu="page-new">' +
+        '</div>' +
+        '</div>' +
         '</div>'
       );
 
       if (this.tree.settings.doktypes && this.tree.settings.doktypes.length) {
         var $buttons = $template.find('[data-tree-submenu=page-new]');
         $template.find('.svg-toolbar__menu').prepend('<div class="x-btn btn btn-default btn-sm x-btn-noicon" data-tree-show-submenu="page-new">' +
-          '<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="' + TYPO3.lang['tree.buttonNewNode'] +'"></button>' +
+          '<button class="svg-toolbar__btn" data-tree-icon="actions-page-new" title="' + TYPO3.lang['tree.buttonNewNode'] + '"></button>' +
           '</div>'
         );
 
-        $.each(this.tree.settings.doktypes, function (id, e) {
+        $.each(this.tree.settings.doktypes, function(id, e) {
           _this.tree.fetchIcon(e.icon, false);
           $buttons.append('<div class="svg-toolbar__drag-node" data-tree-icon="' + e.icon + '" data-node-type="' + e.nodeType + '" title="' + e.title + '" tooltip="' + e.tooltip + '"></div>');
         });
@@ -137,7 +137,7 @@ define(['jquery',
     /**
      * Renders toolbar
      */
-    TreeToolbar.prototype.render = function () {
+    TreeToolbar.prototype.render = function() {
       var _this = this;
       this.tree = this.$treeWrapper.data('svgtree');
 
@@ -147,18 +147,18 @@ define(['jquery',
       var $toolbar = $(this.settings.target).append(this.template);
 
       //get icons
-      $toolbar.find('[data-tree-icon]').each(function () {
+      $toolbar.find('[data-tree-icon]').each(function() {
         var $this = $(this);
 
-        Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small).done(function (icon) {
+        Icons.getIcon($this.attr('data-tree-icon'), Icons.sizes.small).done(function(icon) {
           $this.append(icon);
         });
       });
 
       //toggle toolbar submenu
-      $toolbar.find('[data-tree-show-submenu]').each(function () {
+      $toolbar.find('[data-tree-show-submenu]').each(function() {
         var _this = this;
-        $(this).click(function () {
+        $(this).click(function() {
           var $this = $(this);
           var name = $this.attr('data-tree-show-submenu');
           var $submenu = $toolbar.find('[data-tree-submenu=' + name + ']');
@@ -176,13 +176,13 @@ define(['jquery',
 
       var d3Toolbar = d3.select('.svg-toolbar');
 
-      $.each(this.tree.settings.doktypes, function (id, e) {
+      $.each(this.tree.settings.doktypes, function(id, e) {
         d3Toolbar
           .selectAll('[data-tree-icon=' + e.icon + ']')
           .call(_this.dragDrop.dragToolbar());
       });
 
-      $toolbar.find(this.settings.searchInput).on('input', function () {
+      $toolbar.find(this.settings.searchInput).on('input', function() {
         _this.search.call(_this, this);
       });
 
@@ -192,7 +192,7 @@ define(['jquery',
     /**
      * Refresh tree
      */
-    TreeToolbar.prototype.refreshTree = function () {
+    TreeToolbar.prototype.refreshTree = function() {
       this.tree.refreshTree();
     };
 
@@ -201,12 +201,12 @@ define(['jquery',
      *
      * @param {HTMLElement} input
      */
-    TreeToolbar.prototype.search = function (input) {
+    TreeToolbar.prototype.search = function(input) {
       var _this = this;
       var name = $(input).val().trim();
 
       this.tree.nodes[0].expanded = false;
-      this.tree.nodes.forEach(function (node) {
+      this.tree.nodes.forEach(function(node) {
         var regex = new RegExp(name, 'i');
         if (node.identifier.toString() === name || regex.test(node.name) || regex.test(node.alias)) {
           _this.showParents(node);
@@ -227,13 +227,13 @@ define(['jquery',
      *
      * @param {HTMLElement} input
      */
-    TreeToolbar.prototype.toggleHideUnchecked = function (input) {
+    TreeToolbar.prototype.toggleHideUnchecked = function(input) {
       var _this = this;
 
       this._hideUncheckedState = !this._hideUncheckedState;
 
       if (this._hideUncheckedState) {
-        this.tree.nodes.forEach(function (node) {
+        this.tree.nodes.forEach(function(node) {
           if (node.checked) {
             _this.showParents(node);
             node.expanded = true;
@@ -244,7 +244,7 @@ define(['jquery',
           }
         });
       } else {
-        this.tree.nodes.forEach(function (node) {
+        this.tree.nodes.forEach(function(node) {
           node.hidden = false;
         });
       }
@@ -259,7 +259,7 @@ define(['jquery',
      * @param {Node} node
      * @returns {Boolean}
      */
-    TreeToolbar.prototype.showParents = function (node) {
+    TreeToolbar.prototype.showParents = function(node) {
       if (node.parents.length === 0) {
         return true;
       }
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js b/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js
index fc7f4615b693..cf5288ce51eb 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Severity.js
@@ -15,77 +15,77 @@
  * Module: TYPO3/CMS/Backend/Severity
  * Severity for the TYPO3 backend
  */
-define(function () {
-	'use strict';
+define(function() {
+  'use strict';
 
-	try {
-		// fetch from opening window
-		if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Severity) {
-			return window.opener.TYPO3.Severity;
-		}
+  try {
+    // fetch from opening window
+    if (window.opener && window.opener.TYPO3 && window.opener.TYPO3.Severity) {
+      return window.opener.TYPO3.Severity;
+    }
 
-		// fetch from parent
-		if (parent && parent.window.TYPO3 && parent.window.TYPO3.Severity) {
-			return parent.window.TYPO3.Severity;
-		}
+    // fetch from parent
+    if (parent && parent.window.TYPO3 && parent.window.TYPO3.Severity) {
+      return parent.window.TYPO3.Severity;
+    }
 
-		// fetch object from outer frame
-		if (top && top.TYPO3 && top.TYPO3.Severity) {
-			return top.TYPO3.Severity;
-		}
-	} catch (e) {
-		// This only happens if the opener, parent or top is some other url (eg a local file)
-		// which loaded the current window. Then the browser's cross domain policy jumps in
-		// and raises an exception.
-		// For this case we are safe and we can create our global object below.
-	}
+    // fetch object from outer frame
+    if (top && top.TYPO3 && top.TYPO3.Severity) {
+      return top.TYPO3.Severity;
+    }
+  } catch (e) {
+    // This only happens if the opener, parent or top is some other url (eg a local file)
+    // which loaded the current window. Then the browser's cross domain policy jumps in
+    // and raises an exception.
+    // For this case we are safe and we can create our global object below.
+  }
 
-	/**
-	 * Severity object
-	 *
-	 * @type {{notice: number, information: number, info: number, ok: number, warning: number, error: number}}
-	 * @exports TYPO3/CMS/Backend/Severity
-	 */
-	var Severity = {
-		notice: -2,
-		info: -1,
-		ok: 0,
-		warning: 1,
-		error: 2
-	};
+  /**
+   * Severity object
+   *
+   * @type {{notice: number, information: number, info: number, ok: number, warning: number, error: number}}
+   * @exports TYPO3/CMS/Backend/Severity
+   */
+  var Severity = {
+    notice: -2,
+    info: -1,
+    ok: 0,
+    warning: 1,
+    error: 2
+  };
 
-	/**
-	 * Gets the CSS class for the severity
-	 *
-	 * @param {Number} severity
-	 * @returns {String}
-	 */
-	Severity.getCssClass = function(severity) {
-		var severityClass;
-		switch (severity) {
-			case Severity.notice:
-				severityClass = 'notice';
-				break;
-			case Severity.ok:
-				severityClass = 'success';
-				break;
-			case Severity.warning:
-				severityClass = 'warning';
-				break;
-			case Severity.error:
-				severityClass = 'danger';
-				break;
-			case Severity.info:
-			default:
-				severityClass = 'info';
-		}
-		return severityClass;
-	};
+  /**
+   * Gets the CSS class for the severity
+   *
+   * @param {Number} severity
+   * @returns {String}
+   */
+  Severity.getCssClass = function(severity) {
+    var severityClass;
+    switch (severity) {
+      case Severity.notice:
+        severityClass = 'notice';
+        break;
+      case Severity.ok:
+        severityClass = 'success';
+        break;
+      case Severity.warning:
+        severityClass = 'warning';
+        break;
+      case Severity.error:
+        severityClass = 'danger';
+        break;
+      case Severity.info:
+      default:
+        severityClass = 'info';
+    }
+    return severityClass;
+  };
 
-	// attach to global frame
-	if (typeof TYPO3 !== 'undefined') {
-		TYPO3.Severity = Severity;
-	}
+  // attach to global frame
+  if (typeof TYPO3 !== 'undefined') {
+    TYPO3.Severity = Severity;
+  }
 
-	return Severity;
+  return Severity;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js b/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js
index 57cc99fc611b..702be26a9e0b 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/SplitButtons.js
@@ -16,100 +16,100 @@
  * Initializes global handling of split buttons.
  */
 define(['jquery', 'TYPO3/CMS/Backend/Icons'], function($, Icons) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{preSubmitCallbacks: Array}}
-	 * @exports TYPO3/CMS/Backend/SplitButtons
-	 */
-	var SplitButtons = {
-		preSubmitCallbacks: []
-	};
+  /**
+   *
+   * @type {{preSubmitCallbacks: Array}}
+   * @exports TYPO3/CMS/Backend/SplitButtons
+   */
+  var SplitButtons = {
+    preSubmitCallbacks: []
+  };
 
-	/**
-	 * Initializes the save handling
-	 */
-	SplitButtons.initializeSaveHandling = function() {
-		var preventExec = false;
-		var elements = [
-			'button[form]',
-			'button[name^="_save"]',
-			'a[data-name^="_save"]',
-			'button[name="CMD"][value^="save"]',
-			'a[data-name="CMD"][data-value^="save"]',
-			'button[name^="_translation_save"]',
-			'a[data-name^="_translation_save"]',
-			'button[name="CMD"][value^="_translation_save"]',
-			'a[data-name="CMD"][data-value^="_translation_save"]'
-		].join(',');
-		$('.t3js-module-docheader').on('click', elements, function(e) {
-			// prevent doubleclick double submission bug in chrome,
-			// see https://forge.typo3.org/issues/77942
-			if (!preventExec) {
-				preventExec = true;
-				var $me = $(this),
-					linkedForm = $me.attr('form') || $me.attr('data-form') || null,
-					$form = linkedForm ? $('#' + linkedForm) : $me.closest('form'),
-					name = $me.data('name') || this.name,
-					value = $me.data('value') || this.value,
-					$elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', value);
+  /**
+   * Initializes the save handling
+   */
+  SplitButtons.initializeSaveHandling = function() {
+    var preventExec = false;
+    var elements = [
+      'button[form]',
+      'button[name^="_save"]',
+      'a[data-name^="_save"]',
+      'button[name="CMD"][value^="save"]',
+      'a[data-name="CMD"][data-value^="save"]',
+      'button[name^="_translation_save"]',
+      'a[data-name^="_translation_save"]',
+      'button[name="CMD"][value^="_translation_save"]',
+      'a[data-name="CMD"][data-value^="_translation_save"]'
+    ].join(',');
+    $('.t3js-module-docheader').on('click', elements, function(e) {
+      // prevent doubleclick double submission bug in chrome,
+      // see https://forge.typo3.org/issues/77942
+      if (!preventExec) {
+        preventExec = true;
+        var $me = $(this),
+          linkedForm = $me.attr('form') || $me.attr('data-form') || null,
+          $form = linkedForm ? $('#' + linkedForm) : $me.closest('form'),
+          name = $me.data('name') || this.name,
+          value = $me.data('value') || this.value,
+          $elem = $('<input />').attr('type', 'hidden').attr('name', name).attr('value', value);
 
-				// Run any preSubmit callbacks
-				for (var i = 0; i < SplitButtons.preSubmitCallbacks.length; ++i) {
-					SplitButtons.preSubmitCallbacks[i](e);
+        // Run any preSubmit callbacks
+        for (var i = 0; i < SplitButtons.preSubmitCallbacks.length; ++i) {
+          SplitButtons.preSubmitCallbacks[i](e);
 
-					if (e.isPropagationStopped()) {
-						preventExec = false;
-						return false;
-					}
-				}
-				$form.append($elem);
-				// Disable submit buttons
-				$form.on('submit', function() {
-					if ($form.find('.has-error').length > 0) {
-						preventExec = false;
-						return false;
-					}
+          if (e.isPropagationStopped()) {
+            preventExec = false;
+            return false;
+          }
+        }
+        $form.append($elem);
+        // Disable submit buttons
+        $form.on('submit', function() {
+          if ($form.find('.has-error').length > 0) {
+            preventExec = false;
+            return false;
+          }
 
-					var $affectedButton,
-						$splitButton = $me.closest('.t3js-splitbutton');
+          var $affectedButton,
+            $splitButton = $me.closest('.t3js-splitbutton');
 
-					if ($splitButton.length > 0) {
-						$splitButton.find('button').prop('disabled', true);
-						$affectedButton = $splitButton.children().first();
-					} else {
-						$me.prop('disabled', true);
-						$affectedButton = $me;
-					}
+          if ($splitButton.length > 0) {
+            $splitButton.find('button').prop('disabled', true);
+            $affectedButton = $splitButton.children().first();
+          } else {
+            $me.prop('disabled', true);
+            $affectedButton = $me;
+          }
 
-					Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(markup) {
-						$affectedButton.find('.t3js-icon').replaceWith(markup);
-					});
-				});
+          Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(markup) {
+            $affectedButton.find('.t3js-icon').replaceWith(markup);
+          });
+        });
 
-				if ((e.currentTarget.tagName === 'A' || $me.attr('form')) && !e.isDefaultPrevented()) {
-					$form.submit();
-					e.preventDefault();
-				}
-			}
-		});
-	};
+        if ((e.currentTarget.tagName === 'A' || $me.attr('form')) && !e.isDefaultPrevented()) {
+          $form.submit();
+          e.preventDefault();
+        }
+      }
+    });
+  };
 
-	/**
-	 * Adds a callback being executed before submit
-	 *
-	 * @param {function} callback
-	 */
-	SplitButtons.addPreSubmitCallback = function(callback) {
-		if (typeof callback !== 'function') {
-			throw 'callback must be a function.';
-		}
+  /**
+   * Adds a callback being executed before submit
+   *
+   * @param {function} callback
+   */
+  SplitButtons.addPreSubmitCallback = function(callback) {
+    if (typeof callback !== 'function') {
+      throw 'callback must be a function.';
+    }
 
-		SplitButtons.preSubmitCallbacks.push(callback);
-	};
+    SplitButtons.preSubmitCallbacks.push(callback);
+  };
 
-	$(SplitButtons.initializeSaveHandling);
+  $(SplitButtons.initializeSaveHandling);
 
-	return SplitButtons;
+  return SplitButtons;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js
index e6f6fb24098c..eb8b99e69f67 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/SvgTree.js
@@ -23,16 +23,16 @@ define(
     'TYPO3/CMS/Backend/Severity',
     'TYPO3/CMS/Backend/Notification',
     'TYPO3/CMS/Backend/Icons',
-    'TYPO3/CMS/Lang/Lang',
+    'TYPO3/CMS/Lang/Lang'
   ],
-  function ($, d3, ContextMenu, Modal, Severity, Notification, Icons) {
+  function($, d3, ContextMenu, Modal, Severity, Notification, Icons) {
     'use strict';
 
     /**
      * @constructor
      * @exports SvgTree
      */
-    var SvgTree = function () {
+    var SvgTree = function() {
       this.settings = {
         showCheckboxes: false,
         showIcons: false,
@@ -45,7 +45,7 @@ define(
         dataUrl: '',
         nodeOver: {},
         validation: {
-          maxItems: Number.MAX_VALUE,
+          maxItems: Number.MAX_VALUE
         },
         unselectableElements: [],
         expandUpToLevel: null,
@@ -53,7 +53,7 @@ define(
         /**
          * List node identifiers which can not be selected together with any other node
          */
-        exclusiveNodesIdentifiers: '',
+        exclusiveNodesIdentifiers: ''
       };
 
       /**
@@ -154,7 +154,7 @@ define(
        * @param {String} selector
        * @param {Object} settings
        */
-      initialize: function (selector, settings) {
+      initialize: function(selector, settings) {
         var $wrapper = $(selector);
 
         // Do nothing if already initialized
@@ -191,10 +191,10 @@ define(
         this.svg = this.d3wrapper.append('svg')
           .attr('version', '1.1')
           .attr('width', '100%')
-          .on('mouseover', function () {
+          .on('mouseover', function() {
             _this.isOverSvg = true;
           })
-          .on('mouseout', function () {
+          .on('mouseout', function() {
             _this.isOverSvg = false;
           });
 
@@ -216,7 +216,7 @@ define(
         this.updateScrollPosition();
         this.loadData();
 
-        this.wrapper.on('resize scroll', function () {
+        this.wrapper.on('resize scroll', function() {
           _this.updateScrollPosition();
           _this.update();
         });
@@ -232,10 +232,10 @@ define(
       /**
        * Update svg tree after changed window height
        */
-      resize: function () {
+      resize: function() {
         var _this = this;
 
-        $(window).resize(function () {
+        $(window).resize(function() {
           _this.setWrapperHeight();
           _this.updateScrollPosition();
           _this.update();
@@ -245,7 +245,7 @@ define(
       /**
        * Set svg wrapper height
        */
-      setWrapperHeight: function () {
+      setWrapperHeight: function() {
         var treeWrapperHeight = ($('#typo3-pagetree').height() - $('#svg-toolbar').height());
         $('#typo3-pagetree-tree').height(treeWrapperHeight);
       },
@@ -253,7 +253,7 @@ define(
       /**
        * Updates variables used for visible nodes calculation
        */
-      updateScrollPosition: function () {
+      updateScrollPosition: function() {
         this.viewportHeight = this.wrapper.height();
         this.scrollTop = this.wrapper.scrollTop();
         this.scrollBottom = this.scrollTop + this.viewportHeight + (this.viewportHeight / 2);
@@ -262,17 +262,17 @@ define(
       /**
        * Loads tree data (json) from configured url
        */
-      loadData: function () {
+      loadData: function() {
         var _this = this;
         _this.nodesAddPlaceholder();
 
-        d3.json(this.settings.dataUrl, function (error, json) {
+        d3.json(this.settings.dataUrl, function(error, json) {
           if (error) {
             var title = TYPO3.lang.pagetree_networkErrorTitle;
             var desc = TYPO3.lang.pagetree_networkErrorDesc;
 
             if (error && error.target && (error.target.status || error.target.statusText)) {
-              title += ' - ' + (error.target.status || '')  + ' ' + (error.target.statusText || '');
+              title += ' - ' + (error.target.status || '') + ' ' + (error.target.statusText || '');
             }
 
             Notification.error(
@@ -294,7 +294,7 @@ define(
        *
        * @param {Node[]} nodes
        */
-      replaceData: function (nodes) {
+      replaceData: function(nodes) {
         var _this = this;
 
         _this.setParametersNode(nodes);
@@ -311,11 +311,11 @@ define(
        *
        * @param {Node[]} nodes
        */
-      setParametersNode: function (nodes) {
+      setParametersNode: function(nodes) {
         var _this = this;
 
         nodes = nodes || this.nodes;
-        nodes = nodes.map(function (node, index) {
+        nodes = nodes.map(function(node, index) {
           node.expanded = (_this.settings.expandUpToLevel !== null) ? node.depth < _this.settings.expandUpToLevel : Boolean(node.expanded);
           node.parents = [];
           node.parentsStateIdentifier = [];
@@ -353,14 +353,14 @@ define(
         _this.nodes = nodes;
       },
 
-      nodesRemovePlaceholder: function () {
+      nodesRemovePlaceholder: function() {
         $('.svg-tree').find('.node-loader').hide();
         $('.svg-tree').find('.svg-tree-loader').hide();
       },
 
-      nodesAddPlaceholder: function (node) {
+      nodesAddPlaceholder: function(node) {
         if (node) {
-          $('.svg-tree').find('.node-loader').css({ top: node.y + this.settings.marginTop }).show();
+          $('.svg-tree').find('.node-loader').css({top: node.y + this.settings.marginTop}).show();
         } else {
           $('.svg-tree').find('.svg-tree-loader').show();
         }
@@ -371,18 +371,18 @@ define(
        * and enriches dataset with additional properties
        * Visible dataset is stored in this.data
        */
-      prepareDataForVisibleNodes: function () {
+      prepareDataForVisibleNodes: function() {
         var _this = this;
 
         var blacklist = {};
-        this.nodes.map(function (node, index) {
+        this.nodes.map(function(node, index) {
           if (!node.expanded) {
             blacklist[index] = true;
           }
         });
 
-        this.data.nodes = this.nodes.filter(function (node) {
-          return node.hidden !== true && !node.parents.some(function (index) {
+        this.data.nodes = this.nodes.filter(function(node) {
+          return node.hidden !== true && !node.parents.some(function(index) {
             return Boolean(blacklist[index]);
           });
         });
@@ -390,7 +390,7 @@ define(
         this.data.links = [];
         var pathAboveMounts = 0;
 
-        this.data.nodes.forEach(function (n, i) {
+        this.data.nodes.forEach(function(n, i) {
           // delete n.children;
           n.x = n.depth * _this.settings.indentWidth;
 
@@ -402,7 +402,7 @@ define(
           if (n.parents[0] !== undefined) {
             _this.data.links.push({
               source: _this.nodes[n.parents[0]],
-              target: n,
+              target: n
             });
           }
 
@@ -421,7 +421,7 @@ define(
        * @param {String} iconName
        * @param {Boolean} update
        */
-      fetchIcon: function (iconName, update) {
+      fetchIcon: function(iconName, update) {
         if (!iconName) {
           return;
         }
@@ -434,9 +434,9 @@ define(
         if (!(iconName in this.data.icons)) {
           this.data.icons[iconName] = {
             identifier: iconName,
-            icon: '',
+            icon: ''
           };
-          Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function (icon) {
+          Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) {
             var result = icon.match(/<svg[\s\S]*<\/svg>/i);
 
             // Check if the icon is from the Bitmap Icon Provider (see PHP class for the inline rendering)
@@ -458,17 +458,17 @@ define(
       /**
        * Renders the subset of the tree nodes fitting the viewport (adding, modifying and removing SVG nodes)
        */
-      update: function () {
+      update: function() {
         var _this = this;
         var visibleRows = Math.ceil(_this.viewportHeight / _this.settings.nodeHeight + 1);
         var position = Math.floor(Math.max(_this.scrollTop, 0) / _this.settings.nodeHeight);
 
         var visibleNodes = this.data.nodes.slice(position, position + visibleRows);
-        var nodes = this.nodesContainer.selectAll('.node').data(visibleNodes, function (d) {
+        var nodes = this.nodesContainer.selectAll('.node').data(visibleNodes, function(d) {
           return d.stateIdentifier;
         });
 
-        var nodesBg = this.nodesBgContainer.selectAll('.node-bg').data(visibleNodes, function (d) {
+        var nodesBg = this.nodesBgContainer.selectAll('.node-bg').data(visibleNodes, function(d) {
           return d.stateIdentifier;
         });
 
@@ -486,10 +486,10 @@ define(
         var nodeBgClass = this.updateNodeBgClass(nodesBg);
 
         nodeBgClass
-          .attr('class', function (node, i) {
+          .attr('class', function(node, i) {
             return _this.getNodeBgClass(node, i, nodeBgClass);
           })
-          .attr('style', function (node) {
+          .attr('style', function(node) {
             return node.backgroundColor ? 'fill: ' + node.backgroundColor + ';' : '';
           });
 
@@ -529,7 +529,7 @@ define(
        * @param {Node} nodesBg
        * @returns {Node} nodesBg
        */
-      updateNodeBgClass: function (nodesBg) {
+      updateNodeBgClass: function(nodesBg) {
         var _this = this;
 
         return nodesBg.enter()
@@ -539,17 +539,17 @@ define(
           .attr('height', this.settings.nodeHeight)
           .attr('data-state-id', this.getNodeStateIdentifier)
           .attr('transform', this.getNodeBgTransform)
-          .on('mouseover', function (node) {
+          .on('mouseover', function(node) {
             _this.nodeBgEvents().mouseOver(node, this);
           })
-          .on('mouseout', function (node) {
+          .on('mouseout', function(node) {
             _this.nodeBgEvents().mouseOut(node, this);
           })
-          .on('click', function (node) {
+          .on('click', function(node) {
             _this.nodeBgEvents().click(node, this);
             _this.selectNode(node);
           })
-          .on('contextmenu', function (node) {
+          .on('contextmenu', function(node) {
             _this.dispatch.call('nodeRightClick', node, this);
           });
       },
@@ -558,11 +558,11 @@ define(
        * node background events
        *
        */
-      nodeBgEvents: function () {
+      nodeBgEvents: function() {
         var _this = this;
         var self = {};
 
-        self.mouseOver = function (node, element) {
+        self.mouseOver = function(node, element) {
           var elementNodeBg = _this.svg.select('.nodes-bg .node-bg[data-state-id="' + node.stateIdentifier + '"]');
 
           node.isOver = true;
@@ -576,7 +576,7 @@ define(
           }
         };
 
-        self.mouseOut = function (node, element) {
+        self.mouseOut = function(node, element) {
           var elementNodeBg = _this.svg.select('.nodes-bg .node-bg[data-state-id="' + node.stateIdentifier + '"]');
 
           node.isOver = false;
@@ -590,10 +590,10 @@ define(
           }
         };
 
-        self.click = function (node, element) {
+        self.click = function(node, element) {
           var $nodeBg = $(element).closest('svg').find('.nodes-bg .node-bg[data-state-id=' + node.stateIdentifier + ']');
 
-          _this.nodes.forEach(function (node) {
+          _this.nodes.forEach(function(node) {
             if (node.selected === true) {
               node.selected = false;
             }
@@ -615,9 +615,9 @@ define(
       /**
        * Renders links(lines) between parent and child nodes
        */
-      updateLinks: function () {
+      updateLinks: function() {
         var _this = this;
-        var visibleLinks = this.data.links.filter(function (linkData) {
+        var visibleLinks = this.data.links.filter(function(linkData) {
           return linkData.source.y <= _this.scrollBottom && linkData.target.y >= _this.scrollTop;
         });
 
@@ -646,18 +646,18 @@ define(
        * @param {Selection} nodes
        * @returns {Selection}
        */
-      enterSvgElements: function (nodes) {
+      enterSvgElements: function(nodes) {
         var _this = this;
         this.textPosition = 10;
 
         if (this.settings.showIcons) {
-          var iconsArray = $.map(this.data.icons, function (value) {
+          var iconsArray = $.map(this.data.icons, function(value) {
             if (value.icon !== '') return value;
           });
 
           var icons = this.iconsContainer
             .selectAll('.icon-def')
-            .data(iconsArray, function (i) {
+            .data(iconsArray, function(i) {
               return i.stateIdentifier;
             });
 
@@ -665,10 +665,10 @@ define(
             .enter()
             .append('g')
             .attr('class', 'icon-def')
-            .attr('id', function (i) {
+            .attr('id', function(i) {
               return 'icon-' + i.identifier;
             })
-            .append(function (i) {
+            .append(function(i) {
               // workaround for IE11 where you can't simply call .html(content) on svg
               var parser = new DOMParser();
               var markupText = i.icon.replace('<svg', '<g').replace('/svg>', '/g>');
@@ -687,7 +687,7 @@ define(
           .attr('class', 'toggle')
           .attr('visibility', this.getToggleVisibility)
           .attr('transform', 'translate(-8, -8)')
-          .on('click', function (node) {
+          .on('click', function(node) {
             _this.chevronClick(node);
           });
 
@@ -710,7 +710,7 @@ define(
             .attr('y', -8)
             .attr('class', 'node-icon')
             .attr('data-uid', this.getNodeIdentifier)
-            .on('click', function (node) {
+            .on('click', function(node) {
               _this.clickOnIcon(node, this);
             });
 
@@ -719,7 +719,7 @@ define(
             .attr('x', 8)
             .attr('y', -3)
             .attr('class', 'node-icon-overlay')
-            .on('click', function (node) {
+            .on('click', function(node) {
               _this.clickOnIcon(node, this);
             });
         }
@@ -741,7 +741,7 @@ define(
        * @param {Node} node
        * @returns {Node} node
        */
-      appendTextElement: function (node) {
+      appendTextElement: function(node) {
         var _this = this;
 
         return node
@@ -749,7 +749,7 @@ define(
           .attr('dx', this.textPosition)
           .attr('dy', 5)
           .attr('class', 'node-name')
-          .on('click', function (node) {
+          .on('click', function(node) {
             _this.clickOnLabel(node, this);
             _this.nodeBgEvents().click(node, this);
             _this.selectNode(node);
@@ -760,7 +760,7 @@ define(
        * @param {Node} nodes
        * @returns {Node} nodes
        */
-      nodesUpdate: function (nodes) {
+      nodesUpdate: function(nodes) {
         var _this = this;
 
         nodes = nodes
@@ -771,25 +771,25 @@ define(
           .attr('data-table', 'pages')
           .attr('data-state-id', this.getNodeStateIdentifier)
           .attr('title', this.getNodeTitle)
-          .on('mouseover', function (node) {
+          .on('mouseover', function(node) {
             _this.nodeBgEvents().mouseOver(node, this);
           })
-          .on('mouseout', function (node) {
+          .on('mouseout', function(node) {
             _this.nodeBgEvents().mouseOut(node, this);
           })
-          .on('contextmenu', function (node) {
+          .on('contextmenu', function(node) {
             _this.dispatch.call('nodeRightClick', node, this);
           });
 
         var nodeStop = nodes
           .append('text')
-          .text(function (node) {
+          .text(function(node) {
             return node.readableRootline;
           })
           .attr('class', 'node-rootline')
           .attr('dx', 0)
           .attr('dy', -15)
-          .attr('visibility', function (node) {
+          .attr('visibility', function(node) {
             return node.readableRootline ? 'visible' : 'hidden';
           });
 
@@ -802,7 +802,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getNodeIdentifier: function (node) {
+      getNodeIdentifier: function(node) {
         return node.identifier;
       },
 
@@ -812,7 +812,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getNodeStateIdentifier: function (node) {
+      getNodeStateIdentifier: function(node) {
         return node.stateIdentifier;
       },
 
@@ -822,7 +822,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getNodeLabel: function (node) {
+      getNodeLabel: function(node) {
         return (node.prefix || '') + node.name + (node.suffix || '');
       },
 
@@ -832,7 +832,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getNodeClass: function (node) {
+      getNodeClass: function(node) {
         return 'node identifier-' + node.stateIdentifier;
       },
 
@@ -844,7 +844,7 @@ define(
        * @param {Object} nodeBgClass
        * @returns {String}
        */
-      getNodeBgClass: function (node, i, nodeBgClass) {
+      getNodeBgClass: function(node, i, nodeBgClass) {
         var bgClass = 'node-bg';
         var prevNode = false;
         var nextNode = false;
@@ -881,7 +881,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getNodeTitle: function (node) {
+      getNodeTitle: function(node) {
         return node.tip ? node.tip : 'uid=' + node.identifier;
       },
 
@@ -891,7 +891,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getChevronTransform: function (node) {
+      getChevronTransform: function(node) {
         return node.expanded ? 'translate(16,0) rotate(90)' : ' rotate(0)';
       },
 
@@ -901,7 +901,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getChevronColor: function (node) {
+      getChevronColor: function(node) {
         return node.expanded ? '#000' : '#8e8e8e';
       },
 
@@ -911,7 +911,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getToggleVisibility: function (node) {
+      getToggleVisibility: function(node) {
         return node.hasChildren ? 'visible' : 'hidden';
       },
 
@@ -921,7 +921,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getChevronClass: function (node) {
+      getChevronClass: function(node) {
         return 'chevron ' + (node.expanded ? 'expanded' : 'collapsed');
       },
 
@@ -931,7 +931,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getIconId: function (node) {
+      getIconId: function(node) {
         return '#icon-' + node.icon;
       },
 
@@ -941,7 +941,7 @@ define(
        * @param {Node} node
        * @returns {String}
        */
-      getIconOverlayId: function (node) {
+      getIconOverlayId: function(node) {
         return '#icon-' + node.overlayIcon;
       },
 
@@ -951,10 +951,10 @@ define(
        * @param {Object} link
        * @returns {String}
        */
-      getLinkPath: function (link) {
+      getLinkPath: function(link) {
         var target = {
           x: link.target._isDragged ? link.target._x : link.target.x,
-          y: link.target._isDragged ? link.target._y : link.target.y,
+          y: link.target._isDragged ? link.target._y : link.target.y
         };
         var path = [];
         path.push('M' + link.source.x + ' ' + link.source.y);
@@ -973,7 +973,7 @@ define(
        *
        * @param {Node} node
        */
-      getNodeTransform: function (node) {
+      getNodeTransform: function(node) {
         return 'translate(' + (node.x || 0) + ',' + (node.y || 0) + ')';
       },
 
@@ -982,7 +982,7 @@ define(
        *
        * @param {Node} node
        */
-      getNodeBgTransform: function (node) {
+      getNodeBgTransform: function(node) {
         return 'translate(-8, ' + ((node.y || 0) - 10) + ')';
       },
 
@@ -991,7 +991,7 @@ define(
        *
        * @param {Node} node
        */
-      selectNode: function (node) {
+      selectNode: function(node) {
         if (!this.isNodeSelectable(node)) {
           return;
         }
@@ -1019,14 +1019,14 @@ define(
        *
        * @param {Node} node
        */
-      handleExclusiveNodeSelection: function (node) {
+      handleExclusiveNodeSelection: function(node) {
         var exclusiveKeys = this.settings.exclusiveNodesIdentifiers.split(',');
         var _this = this;
         if (this.settings.exclusiveNodesIdentifiers.length && node.checked === false) {
           if (exclusiveKeys.indexOf('' + node.identifier) > -1) {
 
             // this key is exclusive, so uncheck all others
-            this.nodes.forEach(function (node) {
+            this.nodes.forEach(function(node) {
               if (node.checked === true) {
                 node.checked = false;
                 _this.dispatch.call('nodeSelectedAfter', _this, node);
@@ -1052,7 +1052,7 @@ define(
        * @param {Node} node
        * @returns {Boolean}
        */
-      isNodeSelectable: function (node) {
+      isNodeSelectable: function(node) {
         return !this.settings.readOnlyMode && this.settings.unselectableElements.indexOf(node.identifier) === -1;
       },
 
@@ -1061,8 +1061,8 @@ define(
        *
        * @returns {Node[]}
        */
-      getSelectedNodes: function () {
-        return this.nodes.filter(function (node) {
+      getSelectedNodes: function() {
+        return this.nodes.filter(function(node) {
           return node.checked;
         });
       },
@@ -1073,7 +1073,7 @@ define(
        * @param {Node} node
        * @param {HTMLElement} element
        */
-      clickOnIcon: function (node, element) {
+      clickOnIcon: function(node, element) {
         this.dispatch.call('contextmenu', node, element);
       },
 
@@ -1083,7 +1083,7 @@ define(
        * @param {Node} node
        * @param {HTMLElement} element
        */
-      clickOnLabel: function (node, element) {
+      clickOnLabel: function(node, element) {
         this.selectNode(node);
         this.nodeBgEvents().click(node, element);
       },
@@ -1093,7 +1093,7 @@ define(
        *
        * @param {Node} node
        */
-      chevronClick: function (node) {
+      chevronClick: function(node) {
         if (node.expanded) {
           this.hideChildren(node);
         } else {
@@ -1109,7 +1109,7 @@ define(
        *
        * @param {Node} node
        */
-      hideChildren: function (node) {
+      hideChildren: function(node) {
         node.expanded = false;
       },
 
@@ -1118,21 +1118,21 @@ define(
        *
        * @param {Node} node
        */
-      showChildren: function (node) {
+      showChildren: function(node) {
         node.expanded = true;
       },
 
       /**
        * Refresh view with new data
        */
-      refreshTree: function () {
+      refreshTree: function() {
         this.loadData();
       },
 
       /**
        * Expand all nodes and refresh view
        */
-      expandAll: function () {
+      expandAll: function() {
         this.nodes.forEach(this.showChildren.bind(this));
         this.prepareDataForVisibleNodes();
         this.update();
@@ -1141,11 +1141,11 @@ define(
       /**
        * Collapse all nodes recursively and refresh view
        */
-      collapseAll: function () {
+      collapseAll: function() {
         this.nodes.forEach(this.hideChildren.bind(this));
         this.prepareDataForVisibleNodes();
         this.update();
-      },
+      }
     };
 
     return SvgTree;
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js b/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js
index f5ce43154e05..79cb7dba09d3 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ToggleSearchToolbox.js
@@ -17,28 +17,28 @@
  * @exports TYPO3/CMS/Backend/ToggleSearchToolbox
  */
 define(['jquery', 'TYPO3/CMS/Backend/DocumentHeader', 'TYPO3/CMS/Backend/jquery.clearable'], function($, DocumentHeader) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		var $toolbar = $('#db_list-searchbox-toolbar');
-		$('.t3js-toggle-search-toolbox').on('click', function() {
-			$toolbar.toggle();
-			DocumentHeader.reposition();
-			if ($toolbar.is(':visible')) {
-				$('#search_field').focus();
-			}
-		});
+  $(function() {
+    var $toolbar = $('#db_list-searchbox-toolbar');
+    $('.t3js-toggle-search-toolbox').on('click', function() {
+      $toolbar.toggle();
+      DocumentHeader.reposition();
+      if ($toolbar.is(':visible')) {
+        $('#search_field').focus();
+      }
+    });
 
-		var $searchFields = $('#search_field');
-		var searchResultShown = ('' !== $searchFields.val());
+    var $searchFields = $('#search_field');
+    var searchResultShown = ('' !== $searchFields.val());
 
-		// make search field clearable
-		$searchFields.clearable({
-			onClear: function() {
-				if (searchResultShown) {
-					$(this).closest('form').submit();
-				}
-			}
-		});
-	});
+    // make search field clearable
+    $searchFields.clearable({
+      onClear: function() {
+        if (searchResultShown) {
+          $(this).closest('form').submit();
+        }
+      }
+    });
+  });
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js
index 723dc9152335..886731b62394 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar.js
@@ -17,44 +17,44 @@
  * @exports TYPO3/CMS/Backend/Toolbar
  */
 require(
-	[
-		'jquery',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/ModuleMenu'
-	],
-	function ($) {
+  [
+    'jquery',
+    'TYPO3/CMS/Backend/Icons',
+    'TYPO3/CMS/Backend/ModuleMenu'
+  ],
+  function($) {
 
-		TYPO3.Toolbar = {};
-		TYPO3.Toolbar.App = {
-			initialize: function () {
-				this.initializeEvents();
-			},
-			initializeEvents: function () {
-				$('.t3js-toolbar-item').parent().on('hidden.bs.dropdown', function () {
-					$('.scaffold')
-						.removeClass('scaffold-toolbar-expanded')
-						.removeClass('scaffold-search-expanded');
-				});
-				$(document).on('click', '.toolbar-item [data-modulename]', function (evt) {
-					var moduleName = $(this).data('modulename');
-					TYPO3.ModuleMenu.App.showModule(moduleName);
-					evt.preventDefault();
-				});
-				$(document).on('click', '.t3js-topbar-button-toolbar', function () {
-					$('.scaffold')
-						.removeClass('scaffold-modulemenu-expanded')
-						.removeClass('scaffold-search-expanded')
-						.toggleClass('scaffold-toolbar-expanded');
-				});
-				$(document).on('click', '.t3js-topbar-button-search', function () {
-					$('.scaffold')
-						.removeClass('scaffold-modulemenu-expanded')
-						.removeClass('scaffold-toolbar-expanded')
-						.toggleClass('scaffold-search-expanded');
-				});
-			}
-		};
-		// start the module menu app
-		TYPO3.Toolbar.App.initialize();
-	}
+    TYPO3.Toolbar = {};
+    TYPO3.Toolbar.App = {
+      initialize: function() {
+        this.initializeEvents();
+      },
+      initializeEvents: function() {
+        $('.t3js-toolbar-item').parent().on('hidden.bs.dropdown', function() {
+          $('.scaffold')
+            .removeClass('scaffold-toolbar-expanded')
+            .removeClass('scaffold-search-expanded');
+        });
+        $(document).on('click', '.toolbar-item [data-modulename]', function(evt) {
+          var moduleName = $(this).data('modulename');
+          TYPO3.ModuleMenu.App.showModule(moduleName);
+          evt.preventDefault();
+        });
+        $(document).on('click', '.t3js-topbar-button-toolbar', function() {
+          $('.scaffold')
+            .removeClass('scaffold-modulemenu-expanded')
+            .removeClass('scaffold-search-expanded')
+            .toggleClass('scaffold-toolbar-expanded');
+        });
+        $(document).on('click', '.t3js-topbar-button-search', function() {
+          $('.scaffold')
+            .removeClass('scaffold-modulemenu-expanded')
+            .removeClass('scaffold-toolbar-expanded')
+            .toggleClass('scaffold-search-expanded');
+        });
+      }
+    };
+    // start the module menu app
+    TYPO3.Toolbar.App.initialize();
+  }
 );
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js
index 66041556d73f..88a00a236dc8 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ClearCacheMenu.js
@@ -17,71 +17,71 @@
  * reloading the clear cache icon
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Icons',
-	'TYPO3/CMS/Backend/Notification',
-	'TYPO3/CMS/Backend/Viewport'
+  'jquery',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Viewport'
 ], function($, Icons, Notification, Viewport) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{options: {containerSelector: string, menuItemSelector: string, toolbarIconSelector: string}}}
-	 * @exports TYPO3/CMS/Backend/Toolbar/ClearCacheMenu
-	 */
-	var ClearCacheMenu = {
-		options: {
-			containerSelector: '#typo3-cms-backend-backend-toolbaritems-clearcachetoolbaritem',
-			menuItemSelector: 'a.toolbar-cache-flush-action',
-			toolbarIconSelector: '.toolbar-item-icon .t3js-icon',
-		}
-	};
+  /**
+   *
+   * @type {{options: {containerSelector: string, menuItemSelector: string, toolbarIconSelector: string}}}
+   * @exports TYPO3/CMS/Backend/Toolbar/ClearCacheMenu
+   */
+  var ClearCacheMenu = {
+    options: {
+      containerSelector: '#typo3-cms-backend-backend-toolbaritems-clearcachetoolbaritem',
+      menuItemSelector: 'a.toolbar-cache-flush-action',
+      toolbarIconSelector: '.toolbar-item-icon .t3js-icon'
+    }
+  };
 
-	/**
-	 * Registers listeners for the icons inside the dropdown to trigger
-	 * the clear cache call
-	 */
-	ClearCacheMenu.initializeEvents = function() {
-		$(ClearCacheMenu.options.containerSelector).on('click', ClearCacheMenu.options.menuItemSelector, function(evt) {
-			evt.preventDefault();
-			var ajaxUrl = $(this).attr('href');
-			if (ajaxUrl) {
-				ClearCacheMenu.clearCache(ajaxUrl);
-			}
-		});
-	};
+  /**
+   * Registers listeners for the icons inside the dropdown to trigger
+   * the clear cache call
+   */
+  ClearCacheMenu.initializeEvents = function() {
+    $(ClearCacheMenu.options.containerSelector).on('click', ClearCacheMenu.options.menuItemSelector, function(evt) {
+      evt.preventDefault();
+      var ajaxUrl = $(this).attr('href');
+      if (ajaxUrl) {
+        ClearCacheMenu.clearCache(ajaxUrl);
+      }
+    });
+  };
 
-	/**
-	 * calls TYPO3 to clear a cache, then changes the topbar icon
-	 * to a spinner. Restores the original topbar icon when the request completed.
-	 *
-	 * @param {String} ajaxUrl the URL to load
-	 */
-	ClearCacheMenu.clearCache = function(ajaxUrl) {
-		// Close clear cache menu
-		$(ClearCacheMenu.options.containerSelector).removeClass('open');
+  /**
+   * calls TYPO3 to clear a cache, then changes the topbar icon
+   * to a spinner. Restores the original topbar icon when the request completed.
+   *
+   * @param {String} ajaxUrl the URL to load
+   */
+  ClearCacheMenu.clearCache = function(ajaxUrl) {
+    // Close clear cache menu
+    $(ClearCacheMenu.options.containerSelector).removeClass('open');
 
-		var $toolbarItemIcon = $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector),
-			$existingIcon = $toolbarItemIcon.clone();
+    var $toolbarItemIcon = $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector),
+      $existingIcon = $toolbarItemIcon.clone();
 
-		Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
-			$toolbarItemIcon.replaceWith(spinner);
-		});
+    Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
+      $toolbarItemIcon.replaceWith(spinner);
+    });
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			cache: false,
-			complete: function(jqXHRObject, status) {
-				$(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector).replaceWith($existingIcon);
-				if (status !== 'success' || jqXHRObject.responseText !== '') {
-					Notification.error('An error occurs', 'An error occurred while clearing the cache. It is likely not all caches were cleared as expected.', 0);
-				}
-			}
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      cache: false,
+      complete: function(jqXHRObject, status) {
+        $(ClearCacheMenu.options.toolbarIconSelector, ClearCacheMenu.options.containerSelector).replaceWith($existingIcon);
+        if (status !== 'success' || jqXHRObject.responseText !== '') {
+          Notification.error('An error occurs', 'An error occurred while clearing the cache. It is likely not all caches were cleared as expected.', 0);
+        }
+      }
+    });
+  };
 
-	Viewport.Topbar.Toolbar.registerEvent(ClearCacheMenu.initializeEvents);
+  Viewport.Topbar.Toolbar.registerEvent(ClearCacheMenu.initializeEvents);
 
-	return ClearCacheMenu;
+  return ClearCacheMenu;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js
index a9da605d7ec4..3eca32db27c9 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/ShortcutMenu.js
@@ -17,204 +17,204 @@
  * and edit a shortcut
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/Notification',
-		'TYPO3/CMS/Backend/Viewport'
-	], function($, Modal, Icons, Notification, Viewport) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{options: {containerSelector: string, toolbarIconSelector: string, toolbarMenuSelector: string, shortcutItemSelector: string, shortcutDeleteSelector: string, shortcutEditSelector: string, shortcutFormTitleSelector: string, shortcutFormGroupSelector: string, shortcutFormSaveSelector: string, shortcutFormCancelSelector: string}}}
-	 * @exports TYPO3/CMS/Backend/Toolbar/ShortcutMenu
-	 */
-	var ShortcutMenu = {
-		options: {
-			containerSelector: '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem',
-			toolbarIconSelector: '.dropdown-toggle span.icon',
-			toolbarMenuSelector: '.dropdown-menu',
-
-			shortcutItemSelector: '.t3js-topbar-shortcut',
-			shortcutDeleteSelector: '.t3js-shortcut-delete',
-			shortcutEditSelector: '.t3js-shortcut-edit',
-
-			shortcutFormTitleSelector: 'input[name="shortcut-title"]',
-			shortcutFormGroupSelector: 'select[name="shortcut-group"]',
-			shortcutFormSaveSelector: '.shortcut-form-save',
-			shortcutFormCancelSelector: '.shortcut-form-cancel',
-			shortcutFormSelector: '.shortcut-form'
-		}
-	};
-
-	/**
-	 * build the in-place-editor for a shortcut
-	 *
-	 * @param {Object} $shortcutRecord
-	 */
-	ShortcutMenu.editShortcut = function($shortcutRecord) {
-		// load the form
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['shortcut_editform'],
-			data: {
-				shortcutId: $shortcutRecord.data('shortcutid'),
-				shortcutGroup: $shortcutRecord.data('shortcutgroup')
-			},
-			cache: false
-		}).done(function(data) {
-			$(ShortcutMenu.options.containerSelector).find(ShortcutMenu.options.toolbarMenuSelector).html(data);
-		});
-	};
-
-	/**
-	 * Save the data from the in-place-editor for a shortcut
-	 *
-	 * @param {Object} $shortcutForm
-	 */
-	ShortcutMenu.saveShortcutForm = function($shortcutForm) {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['shortcut_saveform'],
-			data: {
-				shortcutId: $shortcutForm.data('shortcutid'),
-				shortcutTitle: $shortcutForm.find(ShortcutMenu.options.shortcutFormTitleSelector).val(),
-				shortcutGroup: $shortcutForm.find(ShortcutMenu.options.shortcutFormGroupSelector).val()
-			},
-			type: 'post',
-			cache: false
-		}).done(function(data) {
-			Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']);
-			ShortcutMenu.refreshMenu();
-		});
-	};
-
-	/**
-	 * removes an existing short by sending an AJAX call
-	 *
-	 * @param {Object} $shortcutRecord
-	 */
-	ShortcutMenu.deleteShortcut = function($shortcutRecord) {
-		Modal.confirm(TYPO3.lang['bookmark.delete'], TYPO3.lang['bookmark.confirmDelete'])
-			.on('confirm.button.ok', function() {
-				$.ajax({
-					url: TYPO3.settings.ajaxUrls['shortcut_remove'],
-					data: {
-						shortcutId: $shortcutRecord.data('shortcutid')
-					},
-					type: 'post',
-					cache: false
-				}).done(function() {
-					// a reload is used in order to restore the original behaviour
-					// e.g. remove groups that are now empty because the last one in the group
-					// was removed
-					ShortcutMenu.refreshMenu();
-				});
-				$(this).trigger('modal-dismiss');
-			})
-			.on('confirm.button.cancel', function() {
-				$(this).trigger('modal-dismiss');
-			});
-	};
-
-	/**
-	 * makes a call to the backend class to create a new shortcut,
-	 * when finished it reloads the menu
-	 *
-	 * @param {String} moduleName
-	 * @param {String} url
-	 * @param {String} confirmationText
-	 * @param {String} motherModule
-	 * @param {Object} shortcutButton
-	 * @param {String} displayName
-	 */
-	ShortcutMenu.createShortcut = function(moduleName, url, confirmationText, motherModule, shortcutButton, displayName) {
-		if (typeof confirmationText !== 'undefined') {
-			Modal.confirm(TYPO3.lang['bookmark.create'], confirmationText)
-				.on('confirm.button.ok', function() {
- 					var $toolbarItemIcon = $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector),
-						$existingIcon = $toolbarItemIcon.clone();
-
-					Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
-						$toolbarItemIcon.replaceWith(spinner);
-					});
-
-					$.ajax({
-						url: TYPO3.settings.ajaxUrls['shortcut_create'],
-						type: 'post',
-						data: {
-							module: moduleName,
-							url: url,
-							motherModName: motherModule,
-							displayName: displayName
-						},
-						cache: false
-					}).done(function() {
-						ShortcutMenu.refreshMenu();
-						$(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector).replaceWith($existingIcon);
-						if (typeof shortcutButton === 'object') {
-							Icons.getIcon('actions-system-shortcut-active', Icons.sizes.small).done(function(icons) {
-								$(shortcutButton).html(icons['actions-system-shortcut-active']);
-							});
-							$(shortcutButton).addClass('active');
-							$(shortcutButton).attr('title', null);
-							$(shortcutButton).attr('onclick', null);
-						}
-					});
-					$(this).trigger('modal-dismiss');
-				})
-				.on('confirm.button.cancel', function() {
-					$(this).trigger('modal-dismiss');
-				});
-		}
-
-	};
-
-	/**
-	 * reloads the menu after an update
-	 */
-	ShortcutMenu.refreshMenu = function() {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['shortcut_list'],
-			type: 'get',
-			cache: false
-		}).done(function(data) {
-			$(ShortcutMenu.options.toolbarMenuSelector, ShortcutMenu.options.containerSelector).html(data);
-		});
-	};
-
-	/**
-	 * Registers listeners
-	 */
-	ShortcutMenu.initializeEvents = function() {
-		$(ShortcutMenu.options.containerSelector).on('click', ShortcutMenu.options.shortcutDeleteSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-			ShortcutMenu.deleteShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector));
-		}).on('click', ShortcutMenu.options.shortcutFormGroupSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-		}).on('click', ShortcutMenu.options.shortcutEditSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-			ShortcutMenu.editShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector));
-		}).on('click', ShortcutMenu.options.shortcutFormSaveSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-			ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector));
-		}).on('submit', ShortcutMenu.options.shortcutFormSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-			ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector));
-		}).on('click', ShortcutMenu.options.shortcutFormCancelSelector, function(evt) {
-			evt.preventDefault();
-			evt.stopImmediatePropagation();
-			ShortcutMenu.refreshMenu();
-		});
-	};
-
-	Viewport.Topbar.Toolbar.registerEvent(ShortcutMenu.initializeEvents);
-
-	// expose as global object
-	TYPO3.ShortcutMenu = ShortcutMenu;
-
-	return ShortcutMenu;
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Viewport'
+], function($, Modal, Icons, Notification, Viewport) {
+  'use strict';
+
+  /**
+   *
+   * @type {{options: {containerSelector: string, toolbarIconSelector: string, toolbarMenuSelector: string, shortcutItemSelector: string, shortcutDeleteSelector: string, shortcutEditSelector: string, shortcutFormTitleSelector: string, shortcutFormGroupSelector: string, shortcutFormSaveSelector: string, shortcutFormCancelSelector: string}}}
+   * @exports TYPO3/CMS/Backend/Toolbar/ShortcutMenu
+   */
+  var ShortcutMenu = {
+    options: {
+      containerSelector: '#typo3-cms-backend-backend-toolbaritems-shortcuttoolbaritem',
+      toolbarIconSelector: '.dropdown-toggle span.icon',
+      toolbarMenuSelector: '.dropdown-menu',
+
+      shortcutItemSelector: '.t3js-topbar-shortcut',
+      shortcutDeleteSelector: '.t3js-shortcut-delete',
+      shortcutEditSelector: '.t3js-shortcut-edit',
+
+      shortcutFormTitleSelector: 'input[name="shortcut-title"]',
+      shortcutFormGroupSelector: 'select[name="shortcut-group"]',
+      shortcutFormSaveSelector: '.shortcut-form-save',
+      shortcutFormCancelSelector: '.shortcut-form-cancel',
+      shortcutFormSelector: '.shortcut-form'
+    }
+  };
+
+  /**
+   * build the in-place-editor for a shortcut
+   *
+   * @param {Object} $shortcutRecord
+   */
+  ShortcutMenu.editShortcut = function($shortcutRecord) {
+    // load the form
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['shortcut_editform'],
+      data: {
+        shortcutId: $shortcutRecord.data('shortcutid'),
+        shortcutGroup: $shortcutRecord.data('shortcutgroup')
+      },
+      cache: false
+    }).done(function(data) {
+      $(ShortcutMenu.options.containerSelector).find(ShortcutMenu.options.toolbarMenuSelector).html(data);
+    });
+  };
+
+  /**
+   * Save the data from the in-place-editor for a shortcut
+   *
+   * @param {Object} $shortcutForm
+   */
+  ShortcutMenu.saveShortcutForm = function($shortcutForm) {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['shortcut_saveform'],
+      data: {
+        shortcutId: $shortcutForm.data('shortcutid'),
+        shortcutTitle: $shortcutForm.find(ShortcutMenu.options.shortcutFormTitleSelector).val(),
+        shortcutGroup: $shortcutForm.find(ShortcutMenu.options.shortcutFormGroupSelector).val()
+      },
+      type: 'post',
+      cache: false
+    }).done(function(data) {
+      Notification.success(TYPO3.lang['bookmark.savedTitle'], TYPO3.lang['bookmark.savedMessage']);
+      ShortcutMenu.refreshMenu();
+    });
+  };
+
+  /**
+   * removes an existing short by sending an AJAX call
+   *
+   * @param {Object} $shortcutRecord
+   */
+  ShortcutMenu.deleteShortcut = function($shortcutRecord) {
+    Modal.confirm(TYPO3.lang['bookmark.delete'], TYPO3.lang['bookmark.confirmDelete'])
+      .on('confirm.button.ok', function() {
+        $.ajax({
+          url: TYPO3.settings.ajaxUrls['shortcut_remove'],
+          data: {
+            shortcutId: $shortcutRecord.data('shortcutid')
+          },
+          type: 'post',
+          cache: false
+        }).done(function() {
+          // a reload is used in order to restore the original behaviour
+          // e.g. remove groups that are now empty because the last one in the group
+          // was removed
+          ShortcutMenu.refreshMenu();
+        });
+        $(this).trigger('modal-dismiss');
+      })
+      .on('confirm.button.cancel', function() {
+        $(this).trigger('modal-dismiss');
+      });
+  };
+
+  /**
+   * makes a call to the backend class to create a new shortcut,
+   * when finished it reloads the menu
+   *
+   * @param {String} moduleName
+   * @param {String} url
+   * @param {String} confirmationText
+   * @param {String} motherModule
+   * @param {Object} shortcutButton
+   * @param {String} displayName
+   */
+  ShortcutMenu.createShortcut = function(moduleName, url, confirmationText, motherModule, shortcutButton, displayName) {
+    if (typeof confirmationText !== 'undefined') {
+      Modal.confirm(TYPO3.lang['bookmark.create'], confirmationText)
+        .on('confirm.button.ok', function() {
+          var $toolbarItemIcon = $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector),
+            $existingIcon = $toolbarItemIcon.clone();
+
+          Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
+            $toolbarItemIcon.replaceWith(spinner);
+          });
+
+          $.ajax({
+            url: TYPO3.settings.ajaxUrls['shortcut_create'],
+            type: 'post',
+            data: {
+              module: moduleName,
+              url: url,
+              motherModName: motherModule,
+              displayName: displayName
+            },
+            cache: false
+          }).done(function() {
+            ShortcutMenu.refreshMenu();
+            $(ShortcutMenu.options.toolbarIconSelector, ShortcutMenu.options.containerSelector).replaceWith($existingIcon);
+            if (typeof shortcutButton === 'object') {
+              Icons.getIcon('actions-system-shortcut-active', Icons.sizes.small).done(function(icons) {
+                $(shortcutButton).html(icons['actions-system-shortcut-active']);
+              });
+              $(shortcutButton).addClass('active');
+              $(shortcutButton).attr('title', null);
+              $(shortcutButton).attr('onclick', null);
+            }
+          });
+          $(this).trigger('modal-dismiss');
+        })
+        .on('confirm.button.cancel', function() {
+          $(this).trigger('modal-dismiss');
+        });
+    }
+
+  };
+
+  /**
+   * reloads the menu after an update
+   */
+  ShortcutMenu.refreshMenu = function() {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['shortcut_list'],
+      type: 'get',
+      cache: false
+    }).done(function(data) {
+      $(ShortcutMenu.options.toolbarMenuSelector, ShortcutMenu.options.containerSelector).html(data);
+    });
+  };
+
+  /**
+   * Registers listeners
+   */
+  ShortcutMenu.initializeEvents = function() {
+    $(ShortcutMenu.options.containerSelector).on('click', ShortcutMenu.options.shortcutDeleteSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+      ShortcutMenu.deleteShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector));
+    }).on('click', ShortcutMenu.options.shortcutFormGroupSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+    }).on('click', ShortcutMenu.options.shortcutEditSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+      ShortcutMenu.editShortcut($(this).closest(ShortcutMenu.options.shortcutItemSelector));
+    }).on('click', ShortcutMenu.options.shortcutFormSaveSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+      ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector));
+    }).on('submit', ShortcutMenu.options.shortcutFormSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+      ShortcutMenu.saveShortcutForm($(this).closest(ShortcutMenu.options.shortcutFormSelector));
+    }).on('click', ShortcutMenu.options.shortcutFormCancelSelector, function(evt) {
+      evt.preventDefault();
+      evt.stopImmediatePropagation();
+      ShortcutMenu.refreshMenu();
+    });
+  };
+
+  Viewport.Topbar.Toolbar.registerEvent(ShortcutMenu.initializeEvents);
+
+  // expose as global object
+  TYPO3.ShortcutMenu = ShortcutMenu;
+
+  return ShortcutMenu;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js
index 47ca331caf5e..4349d0c5ee18 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Toolbar/SystemInformationMenu.js
@@ -16,130 +16,130 @@
  * System information menu handler
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Icons',
-	'TYPO3/CMS/Backend/Storage/Persistent',
-	'TYPO3/CMS/Backend/Viewport'
+  'jquery',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Storage/Persistent',
+  'TYPO3/CMS/Backend/Viewport'
 ], function($, Icons, PersistentStorage, Viewport) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{identifier: {containerSelector: string, toolbarIconSelector: string, menuContainerSelector: string, moduleLinks: string}, elements: {$counter: (*|jQuery|HTMLElement)}}}
-	 * @exports TYPO3/CMS/Backend/Toolbar/SystemInformationMenu
-	 */
-	var SystemInformationMenu = {
-		identifier: {
-			containerSelector: '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem',
-			toolbarIconSelector: '.toolbar-item-icon .t3js-icon',
-			menuContainerSelector: '.dropdown-menu',
-			moduleLinks: '.t3js-systeminformation-module',
-			counter: '.t3js-systeminformation-counter'
-		}
-	};
-
-	/**
-	 * Initialize the events
-	 */
-	SystemInformationMenu.initialize = function() {
-		$(SystemInformationMenu.identifier.moduleLinks).on('click', SystemInformationMenu.openModule);
-	};
-
-	/**
-	 * Timer for auto reloading the SystemInformation
-	 */
-	SystemInformationMenu.timer = null;
-
-	/**
-	 * Updates the menu
-	 */
-	SystemInformationMenu.updateMenu = function() {
-		var $toolbarItemIcon = $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector),
-			$existingIcon = $toolbarItemIcon.clone(),
-			$menuContainer = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector);
-
-		if (SystemInformationMenu.timer !== null) {
-			clearTimeout(SystemInformationMenu.timer);
-			SystemInformationMenu.timer = null;
-		}
-
-		Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
-			$toolbarItemIcon.replaceWith(spinner);
-		});
-
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['systeminformation_render'],
-			type: 'post',
-			cache: false,
-			success: function(data) {
-				$menuContainer.html(data);
-				SystemInformationMenu.updateCounter();
-
-				SystemInformationMenu.initialize();
-			},
-			complete: function() {
-				$(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector).replaceWith($existingIcon);
-			}
-		}).done(function(){
-			// reload error data every five minutes
-			SystemInformationMenu.timer = setTimeout(
-				SystemInformationMenu.updateMenu,
-				1000 * 300
-			);
-		});
-	};
-
-	/**
-	 * Updates the counter
-	 */
-	SystemInformationMenu.updateCounter = function() {
-		var $container = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector).find('.t3js-systeminformation-container'),
-			$counter = $(SystemInformationMenu.identifier.counter),
-			count = $container.data('count'),
-			badgeClass = $container.data('severityclass');
-
-		$counter.text(count).toggle(parseInt(count) > 0);
-
-		// ensure all default classes are available and previous
-		// (at this time in processing unknown) class is removed
-		$counter.removeClass();
-		$counter.addClass('t3js-systeminformation-counter toolbar-item-badge badge');
-		// badgeClass e.g. could be 'badge-info', 'badge-danger', ...
-		if (badgeClass !== '') {
-			$counter.addClass(badgeClass);
-		}
-	};
-
-	/**
-	 * Updates the UC and opens the linked module
-	 *
-	 * @param {Event} e
-	 */
-	SystemInformationMenu.openModule = function(e) {
-		e.preventDefault();
-		e.stopPropagation();
-
-		var storedSystemInformationSettings = {},
-			moduleStorageObject = {},
-			requestedModule = $(e.currentTarget).data('modulename'),
-			moduleParams = $(e.currentTarget).data('moduleparams'),
-			timestamp = Math.floor((new Date()).getTime() / 1000);
-
-		if (PersistentStorage.isset('systeminformation')) {
-			storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation'));
-		}
-
-		moduleStorageObject[requestedModule] = {lastAccess: timestamp};
-		$.extend(true, storedSystemInformationSettings, moduleStorageObject);
-		var $ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings));
-		$ajax.done(function() {
-			// finally, open the module now
-			TYPO3.ModuleMenu.App.showModule(requestedModule, moduleParams);
-			Viewport.Topbar.refresh();
-		});
-	};
-
-	Viewport.Topbar.Toolbar.registerEvent(SystemInformationMenu.updateMenu);
-
-	return SystemInformationMenu;
+  'use strict';
+
+  /**
+   *
+   * @type {{identifier: {containerSelector: string, toolbarIconSelector: string, menuContainerSelector: string, moduleLinks: string}, elements: {$counter: (*|jQuery|HTMLElement)}}}
+   * @exports TYPO3/CMS/Backend/Toolbar/SystemInformationMenu
+   */
+  var SystemInformationMenu = {
+    identifier: {
+      containerSelector: '#typo3-cms-backend-backend-toolbaritems-systeminformationtoolbaritem',
+      toolbarIconSelector: '.toolbar-item-icon .t3js-icon',
+      menuContainerSelector: '.dropdown-menu',
+      moduleLinks: '.t3js-systeminformation-module',
+      counter: '.t3js-systeminformation-counter'
+    }
+  };
+
+  /**
+   * Initialize the events
+   */
+  SystemInformationMenu.initialize = function() {
+    $(SystemInformationMenu.identifier.moduleLinks).on('click', SystemInformationMenu.openModule);
+  };
+
+  /**
+   * Timer for auto reloading the SystemInformation
+   */
+  SystemInformationMenu.timer = null;
+
+  /**
+   * Updates the menu
+   */
+  SystemInformationMenu.updateMenu = function() {
+    var $toolbarItemIcon = $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector),
+      $existingIcon = $toolbarItemIcon.clone(),
+      $menuContainer = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector);
+
+    if (SystemInformationMenu.timer !== null) {
+      clearTimeout(SystemInformationMenu.timer);
+      SystemInformationMenu.timer = null;
+    }
+
+    Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
+      $toolbarItemIcon.replaceWith(spinner);
+    });
+
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['systeminformation_render'],
+      type: 'post',
+      cache: false,
+      success: function(data) {
+        $menuContainer.html(data);
+        SystemInformationMenu.updateCounter();
+
+        SystemInformationMenu.initialize();
+      },
+      complete: function() {
+        $(SystemInformationMenu.identifier.toolbarIconSelector, SystemInformationMenu.identifier.containerSelector).replaceWith($existingIcon);
+      }
+    }).done(function() {
+      // reload error data every five minutes
+      SystemInformationMenu.timer = setTimeout(
+        SystemInformationMenu.updateMenu,
+        1000 * 300
+      );
+    });
+  };
+
+  /**
+   * Updates the counter
+   */
+  SystemInformationMenu.updateCounter = function() {
+    var $container = $(SystemInformationMenu.identifier.containerSelector).find(SystemInformationMenu.identifier.menuContainerSelector).find('.t3js-systeminformation-container'),
+      $counter = $(SystemInformationMenu.identifier.counter),
+      count = $container.data('count'),
+      badgeClass = $container.data('severityclass');
+
+    $counter.text(count).toggle(parseInt(count) > 0);
+
+    // ensure all default classes are available and previous
+    // (at this time in processing unknown) class is removed
+    $counter.removeClass();
+    $counter.addClass('t3js-systeminformation-counter toolbar-item-badge badge');
+    // badgeClass e.g. could be 'badge-info', 'badge-danger', ...
+    if (badgeClass !== '') {
+      $counter.addClass(badgeClass);
+    }
+  };
+
+  /**
+   * Updates the UC and opens the linked module
+   *
+   * @param {Event} e
+   */
+  SystemInformationMenu.openModule = function(e) {
+    e.preventDefault();
+    e.stopPropagation();
+
+    var storedSystemInformationSettings = {},
+      moduleStorageObject = {},
+      requestedModule = $(e.currentTarget).data('modulename'),
+      moduleParams = $(e.currentTarget).data('moduleparams'),
+      timestamp = Math.floor((new Date()).getTime() / 1000);
+
+    if (PersistentStorage.isset('systeminformation')) {
+      storedSystemInformationSettings = JSON.parse(PersistentStorage.get('systeminformation'));
+    }
+
+    moduleStorageObject[requestedModule] = {lastAccess: timestamp};
+    $.extend(true, storedSystemInformationSettings, moduleStorageObject);
+    var $ajax = PersistentStorage.set('systeminformation', JSON.stringify(storedSystemInformationSettings));
+    $ajax.done(function() {
+      // finally, open the module now
+      TYPO3.ModuleMenu.App.showModule(requestedModule, moduleParams);
+      Viewport.Topbar.refresh();
+    });
+  };
+
+  Viewport.Topbar.Toolbar.registerEvent(SystemInformationMenu.updateMenu);
+
+  return SystemInformationMenu;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js b/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js
index 2b2fb55993ad..23c82e4e660e 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Tooltip.js
@@ -16,53 +16,52 @@
  * API for tooltip windows powered by Twitter Bootstrap.
  */
 define(['jquery', 'bootstrap'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 * The main tooltip object
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Backend/Tooltip
-	 */
-	var Tooltip = {
-	};
+  /**
+   * The main tooltip object
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Backend/Tooltip
+   */
+  var Tooltip = {};
 
-	/**
-	 * Initialize
-	 */
-	Tooltip.initialize = function(selector, options) {
-		options = options || {};
-		$(selector).tooltip(options);
-	};
+  /**
+   * Initialize
+   */
+  Tooltip.initialize = function(selector, options) {
+    options = options || {};
+    $(selector).tooltip(options);
+  };
 
-	/**
-	 * Show tooltip on $element
-	 *
-	 * @param {Object} $element
-	 * @param {String} title
-	 */
-	Tooltip.show = function($element, title) {
-		$element
-			.attr('data-placement', 'auto')
-			.attr('data-title', title)
-			.tooltip('show');
-	};
+  /**
+   * Show tooltip on $element
+   *
+   * @param {Object} $element
+   * @param {String} title
+   */
+  Tooltip.show = function($element, title) {
+    $element
+      .attr('data-placement', 'auto')
+      .attr('data-title', title)
+      .tooltip('show');
+  };
 
-	/**
-	 * Hide tooltip on $element
-	 *
-	 * @param {Object} $element
-	 */
-	Tooltip.hide = function($element) {
-		$element.tooltip('hide');
-	};
+  /**
+   * Hide tooltip on $element
+   *
+   * @param {Object} $element
+   */
+  Tooltip.hide = function($element) {
+    $element.tooltip('hide');
+  };
 
-	$(function () {
-		Tooltip.initialize('[data-toggle="tooltip"]');
-	});
+  $(function() {
+    Tooltip.initialize('[data-toggle="tooltip"]');
+  });
 
-	// expose as global object
-	TYPO3.Tooltip = Tooltip;
+  // expose as global object
+  TYPO3.Tooltip = Tooltip;
 
-	return Tooltip;
+  return Tooltip;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js b/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js
index 7a4d93f0da73..992382392c31 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/ValueSlider.js
@@ -17,69 +17,69 @@
  * Module: TYPO3/CMS/Backend/ValueSlider
  */
 define(['jquery', 'twbs/bootstrap-slider'], function($) {
-	/**
-	 * ValueSlider object
-	 *
-	 * @type {{selector: string}}
-	 * @exports TYPO3/CMS/Backend/ValueSlider
-	 */
-	var ValueSlider = {
-		selector: '[data-slider-id]'
-	};
+  /**
+   * ValueSlider object
+   *
+   * @type {{selector: string}}
+   * @exports TYPO3/CMS/Backend/ValueSlider
+   */
+  var ValueSlider = {
+    selector: '[data-slider-id]'
+  };
 
-	/**
-	 * Initialize all slider elements
-	 */
-	ValueSlider.initializeSlider = function() {
-		var $sliders = $(ValueSlider.selector);
-		if ($sliders.length > 0) {
-			$sliders.slider({
-				formatter: ValueSlider.renderTooltipValue
-			});
-			$sliders.on('change', ValueSlider.updateValue);
-		}
-	};
+  /**
+   * Initialize all slider elements
+   */
+  ValueSlider.initializeSlider = function() {
+    var $sliders = $(ValueSlider.selector);
+    if ($sliders.length > 0) {
+      $sliders.slider({
+        formatter: ValueSlider.renderTooltipValue
+      });
+      $sliders.on('change', ValueSlider.updateValue);
+    }
+  };
 
-	/**
-	 * Update value of slider element
-	 *
-	 * @param {Event} e
-	 */
-	ValueSlider.updateValue = function(e) {
-		var $slider = $(e.currentTarget),
-			$foreignField = $('[data-formengine-input-name="' + $slider.data('sliderItemName') + '"]'),
-			sliderField = $slider.data('sliderField'),
-			sliderCallbackParams = $slider.data('sliderCallbackParams');
+  /**
+   * Update value of slider element
+   *
+   * @param {Event} e
+   */
+  ValueSlider.updateValue = function(e) {
+    var $slider = $(e.currentTarget),
+      $foreignField = $('[data-formengine-input-name="' + $slider.data('sliderItemName') + '"]'),
+      sliderField = $slider.data('sliderField'),
+      sliderCallbackParams = $slider.data('sliderCallbackParams');
 
-		$foreignField.val(e.value.newValue);
-		TBE_EDITOR.fieldChanged.apply(TBE_EDITOR, sliderCallbackParams);
-	};
+    $foreignField.val(e.value.newValue);
+    TBE_EDITOR.fieldChanged.apply(TBE_EDITOR, sliderCallbackParams);
+  };
 
-	/**
-	 *
-	 * @param {Number} value
-	 * @returns {*}
-	 */
-	ValueSlider.renderTooltipValue = function(value) {
-		var renderedValue,
-			$slider = $('[data-slider-id="' + this.id + '"]'),
-			data = $slider.data();
-		switch (data.sliderValueType) {
-			case 'double':
-				renderedValue = parseFloat(value).toFixed(2);
-				break;
-			case 'int':
-			default:
-				renderedValue = parseInt(value);
-		}
+  /**
+   *
+   * @param {Number} value
+   * @returns {*}
+   */
+  ValueSlider.renderTooltipValue = function(value) {
+    var renderedValue,
+      $slider = $('[data-slider-id="' + this.id + '"]'),
+      data = $slider.data();
+    switch (data.sliderValueType) {
+      case 'double':
+        renderedValue = parseFloat(value).toFixed(2);
+        break;
+      case 'int':
+      default:
+        renderedValue = parseInt(value);
+    }
 
-		return renderedValue;
-	};
+    return renderedValue;
+  };
 
-	// init if document is ready
-	$(document).ready(function() {
-		ValueSlider.initializeSlider();
-	});
+  // init if document is ready
+  $(document).ready(function() {
+    ValueSlider.initializeSlider();
+  });
 
-	return ValueSlider;
+  return ValueSlider;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js b/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js
index 0498a4c3bf7f..d1338fb4a44d 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Viewport.js
@@ -17,251 +17,251 @@
  * @exports TYPO3/CMS/Backend/Viewport
  */
 define(
-	'TYPO3/CMS/Backend/Viewport',
-	[
-		'jquery',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/Utility',
-		'TYPO3/CMS/Backend/Event/ConsumerScope',
-		'TYPO3/CMS/Backend/Event/TriggerRequest'
-	],
-	function ($, Icons, Utility, ConsumerScope, TriggerRequest) {
-		'use strict';
+  'TYPO3/CMS/Backend/Viewport',
+  [
+    'jquery',
+    'TYPO3/CMS/Backend/Icons',
+    'TYPO3/CMS/Backend/Utility',
+    'TYPO3/CMS/Backend/Event/ConsumerScope',
+    'TYPO3/CMS/Backend/Event/TriggerRequest'
+  ],
+  function($, Icons, Utility, ConsumerScope, TriggerRequest) {
+    'use strict';
 
-		function resolveIFrameElement() {
-			var $iFrame = $('.t3js-scaffold-content-module-iframe:first');
-			if ($iFrame.length === 0) {
-				return null;
-			}
-			return $iFrame.get(0);
-		}
+    function resolveIFrameElement() {
+      var $iFrame = $('.t3js-scaffold-content-module-iframe:first');
+      if ($iFrame.length === 0) {
+        return null;
+      }
+      return $iFrame.get(0);
+    }
 
-		TYPO3.Backend = {
-			/**
-			 * @type {ConsumerScope}
-			 */
-			consumerScope: ConsumerScope,
+    TYPO3.Backend = {
+      /**
+       * @type {ConsumerScope}
+       */
+      consumerScope: ConsumerScope,
 
-			initialize: function() {
-				TYPO3.Backend.doLayout();
-				$(window).on('resize', TYPO3.Backend.doLayout);
-			},
-			/**
-			 * This function is triggered whenever a re-layouting of component is needed
-			 */
-			doLayout: function () {
-				TYPO3.Backend.NavigationContainer.cleanup();
-				TYPO3.Backend.NavigationContainer.calculateScrollbar();
-				$('.t3js-topbar-header').css('padding-right', $('.t3js-scaffold-toolbar').outerWidth());
-			},
-			Loader: {
-				start: function() {
-					require(['nprogress'], function(NProgress) {
-						NProgress.configure({parent: '.t3js-scaffold-content-module', showSpinner: false});
-						NProgress.start();
-					});
-				},
-				finish: function() {
-					require(['nprogress'], function(NProgress) {
-						NProgress.done();
-					});
-				}
-			},
-			NavigationContainer: {
-				instance: null,
+      initialize: function() {
+        TYPO3.Backend.doLayout();
+        $(window).on('resize', TYPO3.Backend.doLayout);
+      },
+      /**
+       * This function is triggered whenever a re-layouting of component is needed
+       */
+      doLayout: function() {
+        TYPO3.Backend.NavigationContainer.cleanup();
+        TYPO3.Backend.NavigationContainer.calculateScrollbar();
+        $('.t3js-topbar-header').css('padding-right', $('.t3js-scaffold-toolbar').outerWidth());
+      },
+      Loader: {
+        start: function() {
+          require(['nprogress'], function(NProgress) {
+            NProgress.configure({parent: '.t3js-scaffold-content-module', showSpinner: false});
+            NProgress.start();
+          });
+        },
+        finish: function() {
+          require(['nprogress'], function(NProgress) {
+            NProgress.done();
+          });
+        }
+      },
+      NavigationContainer: {
+        instance: null,
 
-				PageTree: {
-					refreshTree: function() {
-						if (TYPO3.Backend.NavigationContainer.instance !== null) {
-							TYPO3.Backend.NavigationContainer.instance.refreshTree();
-						}
-					},
-					setTemporaryMountPoint: function (pid) {
-						if (TYPO3.Backend.NavigationContainer.instance !== null) {
-							TYPO3.Backend.NavigationContainer.instance.setTemporaryMountPoint(pid);
-						}
-					},
-					unsetTemporaryMountPoint: function () {
-						if (TYPO3.Backend.NavigationContainer.instance !== null) {
-							TYPO3.Backend.NavigationContainer.instance.unsetTemporaryMountPoint();
-						}
-					}
-				},
-				toggle: function () {
-					$('.t3js-scaffold').toggleClass('scaffold-content-navigation-expanded')
-				},
-				cleanup: function() {
-					$('.t3js-scaffold-modulemenu').removeAttr('style');
-					$('t3js-scaffold-content').removeAttr('style');
-				},
-				hide: function () {
-					$('.t3js-topbar-button-navigationcomponent').attr('disabled', true);
-					Icons.getIcon('actions-pagetree', Icons.sizes.small, 'overlay-readonly', null, Icons.markupIdentifiers.inline).done(function(icon) {
-						$('.t3js-topbar-button-navigationcomponent').html(icon);
-					});
-					$('.t3js-scaffold').removeClass('scaffold-content-navigation-expanded');
-					$('.t3js-scaffold-content-module').removeAttr('style');
-				},
-				show: function (component) {
-					$('.t3js-topbar-button-navigationcomponent').attr('disabled', false);
-					Icons.getIcon('actions-pagetree', Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
-						$('.t3js-topbar-button-navigationcomponent').html(icon);
-					});
-					if(component !== undefined) {
-						$('.t3js-scaffold').addClass('scaffold-content-navigation-expanded');
-					}
-					$('.t3js-scaffold-content-navigation [data-component]').hide();
-					$('.t3js-scaffold-content-navigation [data-component="' + component + '"]').show();
-				},
-				/**
-				 * @param {string} urlToLoad
-				 * @param {InteractionRequest} [interactionRequest]
-				 * @return {jQuery.Deferred}
-				 */
-				setUrl: function(urlToLoad, interactionRequest) {
-					var deferred = TYPO3.Backend.consumerScope.invoke(
-						new TriggerRequest('typo3.setUrl', interactionRequest)
-					);
-					deferred.then(function() {
-						$('.t3js-scaffold').addClass('scaffold-content-navigation-expanded');
-						$('.t3js-scaffold-content-navigation-iframe').attr('src', urlToLoad);
-					});
-					return deferred;
-				},
-				getUrl: function() {
-					return $('.t3js-scaffold-content-navigation-iframe').attr('src');
-				},
-				/**
-				 * @param {boolean} forceGet
-				 */
-				refresh: function(forceGet) {
-					$('.t3js-scaffold-content-navigation-iframe')[0].contentWindow.location.reload(forceGet);
-				},
-				calculateScrollbar: function (){
-					TYPO3.Backend.NavigationContainer.cleanup();
-					var $scaffold = $('.t3js-scaffold');
-					var $moduleMenuContainer = $('.t3js-scaffold-modulemenu');
-					var $contentContainer = $('.t3js-scaffold-content');
-					var $moduleMenu = $('.t3js-modulemenu');
-					$moduleMenuContainer.css('overflow', 'auto');
-					var moduleMenuContainerWidth = $moduleMenuContainer.outerWidth();
-					var moduleMenuWidth = $moduleMenu.outerWidth();
-					$moduleMenuContainer.removeAttr('style').css('overflow', 'hidden');
-					if ($scaffold.hasClass('scaffold-modulemenu-expanded') === false) {
-						$moduleMenuContainer.width(moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth));
-						$contentContainer.css('left', moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth))
-					} else {
-						$moduleMenuContainer.removeAttr('style');
-						$contentContainer.removeAttr('style');
-					}
-					$moduleMenuContainer.css('overflow', 'auto');
-				},
+        PageTree: {
+          refreshTree: function() {
+            if (TYPO3.Backend.NavigationContainer.instance !== null) {
+              TYPO3.Backend.NavigationContainer.instance.refreshTree();
+            }
+          },
+          setTemporaryMountPoint: function(pid) {
+            if (TYPO3.Backend.NavigationContainer.instance !== null) {
+              TYPO3.Backend.NavigationContainer.instance.setTemporaryMountPoint(pid);
+            }
+          },
+          unsetTemporaryMountPoint: function() {
+            if (TYPO3.Backend.NavigationContainer.instance !== null) {
+              TYPO3.Backend.NavigationContainer.instance.unsetTemporaryMountPoint();
+            }
+          }
+        },
+        toggle: function() {
+          $('.t3js-scaffold').toggleClass('scaffold-content-navigation-expanded')
+        },
+        cleanup: function() {
+          $('.t3js-scaffold-modulemenu').removeAttr('style');
+          $('t3js-scaffold-content').removeAttr('style');
+        },
+        hide: function() {
+          $('.t3js-topbar-button-navigationcomponent').attr('disabled', true);
+          Icons.getIcon('actions-pagetree', Icons.sizes.small, 'overlay-readonly', null, Icons.markupIdentifiers.inline).done(function(icon) {
+            $('.t3js-topbar-button-navigationcomponent').html(icon);
+          });
+          $('.t3js-scaffold').removeClass('scaffold-content-navigation-expanded');
+          $('.t3js-scaffold-content-module').removeAttr('style');
+        },
+        show: function(component) {
+          $('.t3js-topbar-button-navigationcomponent').attr('disabled', false);
+          Icons.getIcon('actions-pagetree', Icons.sizes.small, null, null, Icons.markupIdentifiers.inline).done(function(icon) {
+            $('.t3js-topbar-button-navigationcomponent').html(icon);
+          });
+          if (component !== undefined) {
+            $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded');
+          }
+          $('.t3js-scaffold-content-navigation [data-component]').hide();
+          $('.t3js-scaffold-content-navigation [data-component="' + component + '"]').show();
+        },
+        /**
+         * @param {string} urlToLoad
+         * @param {InteractionRequest} [interactionRequest]
+         * @return {jQuery.Deferred}
+         */
+        setUrl: function(urlToLoad, interactionRequest) {
+          var deferred = TYPO3.Backend.consumerScope.invoke(
+            new TriggerRequest('typo3.setUrl', interactionRequest)
+          );
+          deferred.then(function() {
+            $('.t3js-scaffold').addClass('scaffold-content-navigation-expanded');
+            $('.t3js-scaffold-content-navigation-iframe').attr('src', urlToLoad);
+          });
+          return deferred;
+        },
+        getUrl: function() {
+          return $('.t3js-scaffold-content-navigation-iframe').attr('src');
+        },
+        /**
+         * @param {boolean} forceGet
+         */
+        refresh: function(forceGet) {
+          $('.t3js-scaffold-content-navigation-iframe')[0].contentWindow.location.reload(forceGet);
+        },
+        calculateScrollbar: function() {
+          TYPO3.Backend.NavigationContainer.cleanup();
+          var $scaffold = $('.t3js-scaffold');
+          var $moduleMenuContainer = $('.t3js-scaffold-modulemenu');
+          var $contentContainer = $('.t3js-scaffold-content');
+          var $moduleMenu = $('.t3js-modulemenu');
+          $moduleMenuContainer.css('overflow', 'auto');
+          var moduleMenuContainerWidth = $moduleMenuContainer.outerWidth();
+          var moduleMenuWidth = $moduleMenu.outerWidth();
+          $moduleMenuContainer.removeAttr('style').css('overflow', 'hidden');
+          if ($scaffold.hasClass('scaffold-modulemenu-expanded') === false) {
+            $moduleMenuContainer.width(moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth));
+            $contentContainer.css('left', moduleMenuContainerWidth + (moduleMenuContainerWidth - moduleMenuWidth))
+          } else {
+            $moduleMenuContainer.removeAttr('style');
+            $contentContainer.removeAttr('style');
+          }
+          $moduleMenuContainer.css('overflow', 'auto');
+        },
 
-				/**
-				 * Public method used by Naviagtion components to register themselves.
-				 * See TYPO3/CMS/Backend/PageTree/PageTreeElement->initialize
-				 *
-				 * @param {Object} component
-				 */
-				setComponentInstance: function (component) {
-					TYPO3.Backend.NavigationContainer.instance = component;
+        /**
+         * Public method used by Naviagtion components to register themselves.
+         * See TYPO3/CMS/Backend/PageTree/PageTreeElement->initialize
+         *
+         * @param {Object} component
+         */
+        setComponentInstance: function(component) {
+          TYPO3.Backend.NavigationContainer.instance = component;
+        }
+      },
+      /**
+       * Content container manages the right site of the viewport (showing module specific content)
+       */
+      ContentContainer: {
+        get: function() {
+          return $('.t3js-scaffold-content-module-iframe')[0].contentWindow;
+        },
+        /**
+         * @param {InteractionRequest} [interactionRequest]
+         * @return {jQuery.Deferred}
+         */
+        beforeSetUrl: function(interactionRequest) {
+          return TYPO3.Backend.consumerScope.invoke(
+            new TriggerRequest('typo3.beforeSetUrl', interactionRequest)
+          );
+        },
+        /**
+         * @param {String} urlToLoad
+         * @param {InteractionRequest} [interactionRequest]
+         * @return {jQuery.Deferred}
+         */
+        setUrl: function(urlToLoad, interactionRequest) {
+          var deferred;
+          var iFrame = resolveIFrameElement();
+          // abort, if no IFRAME can be found
+          if (iFrame === null) {
+            deferred = $.Deferred();
+            deferred.reject();
+            return deferred;
+          }
+          deferred = TYPO3.Backend.consumerScope.invoke(
+            new TriggerRequest('typo3.setUrl', interactionRequest)
+          );
+          deferred.then(function() {
+            TYPO3.Backend.Loader.start();
+            $('.t3js-scaffold-content-module-iframe')
+              .attr('src', urlToLoad)
+              .one('load', function() {
+                TYPO3.Backend.Loader.finish();
+              });
+          });
+          return deferred;
+        },
+        getUrl: function() {
+          return $('.t3js-scaffold-content-module-iframe').attr('src');
+        },
+        /**
+         * @param {boolean} forceGet
+         * @param {InteractionRequest} interactionRequest
+         * @return {jQuery.Deferred}
+         */
+        refresh: function(forceGet, interactionRequest) {
+          var deferred;
+          var iFrame = resolveIFrameElement();
+          // abort, if no IFRAME can be found
+          if (iFrame === null) {
+            deferred = $.Deferred();
+            deferred.reject();
+            return deferred;
+          }
+          deferred = TYPO3.Backend.consumerScope.invoke(
+            new TriggerRequest('typo3.refresh', interactionRequest)
+          );
+          deferred.then(function() {
+            iFrame.contentWindow.location.reload(forceGet);
+          });
+          return deferred;
+        },
+        getIdFromUrl: function() {
+          if (this.getUrl) {
+            return Utility.getParameterFromUrl(this.getUrl, 'id');
+          } else {
+            return 0;
+          }
+        }
+      },
+      Topbar: {
+        topbarSelector: '.t3js-scaffold-header',
+        refresh: function() {
+          $.ajax(TYPO3.settings.ajaxUrls['topbar']).done(function(data) {
+            $(TYPO3.Backend.Topbar.topbarSelector).html(data.topbar);
+            $(TYPO3.Backend.Topbar.topbarSelector).trigger('t3-topbar-update');
+          });
+        },
+        Toolbar: {
+          registerEvent: function(callback) {
+            $(callback);
+            $(TYPO3.Backend.Topbar.topbarSelector).on('t3-topbar-update', callback);
+          }
         }
-			},
-			/**
-			 * Content container manages the right site of the viewport (showing module specific content)
-			 */
-			ContentContainer: {
-				get: function() {
-					return $('.t3js-scaffold-content-module-iframe')[0].contentWindow;
-				},
-				/**
-				 * @param {InteractionRequest} [interactionRequest]
-				 * @return {jQuery.Deferred}
-				 */
-				beforeSetUrl: function(interactionRequest) {
-					return TYPO3.Backend.consumerScope.invoke(
-						new TriggerRequest('typo3.beforeSetUrl', interactionRequest)
-					);
-				},
-				/**
-				 * @param {String} urlToLoad
-				 * @param {InteractionRequest} [interactionRequest]
-				 * @return {jQuery.Deferred}
-				 */
-				setUrl: function (urlToLoad, interactionRequest) {
-					var deferred;
-					var iFrame = resolveIFrameElement();
-					// abort, if no IFRAME can be found
-					if (iFrame === null) {
-						deferred = $.Deferred();
-						deferred.reject();
-						return deferred;
-					}
-					deferred = TYPO3.Backend.consumerScope.invoke(
-						new TriggerRequest('typo3.setUrl', interactionRequest)
-					);
-					deferred.then(function() {
-						TYPO3.Backend.Loader.start();
-						$('.t3js-scaffold-content-module-iframe')
-							.attr('src', urlToLoad)
-							.one('load', function() {
-								TYPO3.Backend.Loader.finish();
-							});
-					});
-					return deferred;
-				},
-				getUrl: function() {
-					return $('.t3js-scaffold-content-module-iframe').attr('src');
-				},
-				/**
-				 * @param {boolean} forceGet
-				 * @param {InteractionRequest} interactionRequest
-				 * @return {jQuery.Deferred}
-				 */
-				refresh: function(forceGet, interactionRequest) {
-					var deferred;
-					var iFrame = resolveIFrameElement();
-					// abort, if no IFRAME can be found
-					if (iFrame === null) {
-						deferred = $.Deferred();
-						deferred.reject();
-						return deferred;
-					}
-					deferred = TYPO3.Backend.consumerScope.invoke(
-						new TriggerRequest('typo3.refresh', interactionRequest)
-					);
-					deferred.then(function() {
-						iFrame.contentWindow.location.reload(forceGet);
-					});
-					return deferred;
-				},
-				getIdFromUrl: function() {
-					if(this.getUrl) {
-						return Utility.getParameterFromUrl(this.getUrl, 'id');
-					} else {
-						return 0;
-					}
-				}
-			},
-			Topbar: {
-				topbarSelector: '.t3js-scaffold-header',
-				refresh: function() {
-					$.ajax(TYPO3.settings.ajaxUrls['topbar']).done(function(data) {
-						$(TYPO3.Backend.Topbar.topbarSelector).html(data.topbar);
-						$(TYPO3.Backend.Topbar.topbarSelector).trigger('t3-topbar-update');
-					});
-				},
-				Toolbar: {
-					registerEvent: function (callback) {
-						$(callback);
-						$(TYPO3.Backend.Topbar.topbarSelector).on('t3-topbar-update', callback);
-					}
-				}
-			}
-		};
+      }
+    };
 
-		// start the module menu app
-		TYPO3.Backend.initialize();
-		return TYPO3.Backend;
-	}
+    // start the module menu app
+    TYPO3.Backend.initialize();
+    return TYPO3.Backend;
+  }
 );
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js
index 79d12b29d599..bbb7fc5eeca1 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard.js
@@ -16,345 +16,345 @@
  * API for wizard windows.
  */
 define(['jquery',
-	'TYPO3/CMS/Backend/Modal',
-	'TYPO3/CMS/Backend/Severity',
-	'TYPO3/CMS/Backend/Icons',
-	'bootstrap'
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Icons',
+  'bootstrap'
 ], function($, Modal, Severity, Icons) {
-	'use strict';
-
-	try {
-		// fetch from parent
-		if (parent && parent.window.TYPO3 && parent.window.TYPO3.Wizard) {
-			return parent.window.TYPO3.Wizard;
-		}
-
-		// fetch object from outer frame
-		if (top && top.TYPO3 && top.TYPO3.Wizard) {
-			return top.TYPO3.Wizard;
-		}
-	} catch (e) {
-		// This only happens if the opener, parent or top is some other url (eg a local file)
-		// which loaded the current window. Then the browser's cross domain policy jumps in
-		// and raises an exception.
-		// For this case we are safe and we can create our global object below.
-	}
-
-	/**
-	 * @type {{setup: {slides: Array, settings: {}, forceSelection: boolean, $carousel: null}, originalSetup: {}}}
-	 * @exports TYPO3/CMS/Backend/Wizard
-	 */
-	var Wizard = {
-		setup: {
-			slides: [],
-			settings: {},
-			forceSelection: true,
-			$carousel: null
-		},
-		originalSetup: {}
-	};
-
-	/**
-	 * Initializes the events after building the wizards
-	 *
-	 * @private
-	 */
-	Wizard.initializeEvents = function() {
-		var $modal = Wizard.setup.$carousel.closest('.modal'),
-			$modalTitle = $modal.find('.modal-title'),
-			$modalFooter = $modal.find('.modal-footer'),
-			$nextButton = $modalFooter.find('button[name="next"]');
-
-		$nextButton.on('click', function() {
-			Wizard.setup.$carousel.carousel('next');
-		});
-
-		Wizard.setup.$carousel.on('slide.bs.carousel', function() {
-			var nextSlideNumber = Wizard.setup.$carousel.data('currentSlide') + 1,
-				currentIndex = Wizard.setup.$carousel.data('currentIndex') + 1;
-
-			$modalTitle.text(Wizard.setup.slides[currentIndex].title);
-
-			Wizard.setup.$carousel.data('currentSlide', nextSlideNumber);
-			Wizard.setup.$carousel.data('currentIndex', currentIndex);
-
-			if (nextSlideNumber >= Wizard.setup.$carousel.data('realSlideCount')) {
-				// Point of no return - hide modal footer disable any closing ability
-				$modal.find('.modal-header .close').remove();
-				$modalFooter.slideUp();
-			} else {
-				$modalFooter.find('.progress-bar')
-					.width(Wizard.setup.$carousel.data('initialStep') * nextSlideNumber + '%')
-					.text(top.TYPO3.lang['wizard.progress']
-						.replace('{0}', nextSlideNumber)
-						.replace('{1}', Wizard.setup.$carousel.data('slideCount')));
-			}
-
-			$nextButton
-				.removeClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex -1].severity))
-				.addClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity));
-
-			$modal
-				.removeClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex -1].severity))
-				.addClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity));
-		}).on('slid.bs.carousel', function(e) {
-			var currentIndex = Wizard.setup.$carousel.data('currentIndex'),
-				slide = Wizard.setup.slides[currentIndex];
-
-			Wizard.runSlideCallback(slide, $(e.relatedTarget));
-
-			if (Wizard.setup.forceSelection) {
-				Wizard.lockNextStep();
-			}
-		});
-
-		/**
-		 * Custom event, closes the wizard
-		 */
-		var cmp = Wizard.getComponent();
-		cmp.on('wizard-dismiss', Wizard.dismiss);
-
-		Modal.currentModal.on('hidden.bs.modal', function() {
-			cmp.trigger('wizard-dismissed');
-		}).on('shown.bs.modal', function() {
-			cmp.trigger('wizard-visible');
-		});
-	};
-
-	/**
-	 * @param {String} key
-	 * @param {*} value
-	 * @returns {Object}
-	 */
-	Wizard.set = function(key, value) {
-		Wizard.setup.settings[key] = value;
-		return Wizard;
-	};
-
-	/**
-	 * Adds a new slide to the wizard
-	 *
-	 * @param {String} identifier
-	 * @param {String} title
-	 * @param {String} content
-	 * @param {String} severity
-	 * @param {Function} callback
-	 * @returns {Object}
-	 */
-	Wizard.addSlide = function(identifier, title, content, severity, callback) {
-		Wizard.setup.slides.push({
-			identifier: identifier,
-			title: title,
-			content: content || '',
-			severity: (typeof severity !== 'undefined' ? severity : Severity.info),
-			callback: callback
-		});
-
-		return Wizard;
-	};
-
-	/**
-	 * Adds a final processing slide
-	 *
-	 * @param {Function} callback
-	 * @returns {Object}
-	 */
-	Wizard.addFinalProcessingSlide = function(callback) {
-		if (typeof callback !== 'function') {
-			callback = function() {
-				Wizard.dismiss();
-			}
-		}
-
-		return Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
-			var $processingSlide = $('<div />', {class: 'text-center'}).append(markup);
-			Wizard.addSlide(
-				'final-processing-slide', top.TYPO3.lang['wizard.processing.title'],
-				$processingSlide[0].outerHTML,
-				Severity.info,
-				callback
-			);
-		});
-	};
-
-	/**
-	 * Processes the footer of the modal
-	 *
-	 * @private
-	 */
-	Wizard.addProgressBar = function() {
-		var realSlideCount = Wizard.setup.$carousel.find('.item').length,
-			slideCount = Math.max(1, realSlideCount),
-			initialStep,
-			$modal = Wizard.setup.$carousel.closest('.modal'),
-			$modalFooter = $modal.find('.modal-footer');
-
-		initialStep = Math.round(100 / slideCount);
-
-		Wizard.setup.$carousel
-			.data('initialStep', initialStep)
-			.data('slideCount', slideCount)
-			.data('realSlideCount', realSlideCount)
-			.data('currentIndex', 0)
-			.data('currentSlide', 1);
-
-		// Append progress bar to modal footer
-		if (slideCount > 1) {
-			$modalFooter.prepend(
-				$('<div />', {class: 'progress'}).append(
-					$('<div />', {
-						role: 'progressbar',
-						class: 'progress-bar',
-						'aria-valuemin': 0,
-						'aria-valuenow': initialStep,
-						'aria-valuemax': 100
-					}).width(initialStep + '%').text(
-						top.TYPO3.lang['wizard.progress']
-							.replace('{0}', '1')
-							.replace('{1}', slideCount)
-					)
-				)
-			);
-		}
-	};
-
-	/**
-	 * Generates the markup of slides added by addSlide()
-	 *
-	 * @returns {$}
-	 * @private
-	 */
-	Wizard.generateSlides = function() {
-		// Check whether the slides were already generated
-		if (Wizard.setup.$carousel !== null) {
-			return Wizard.setup.$carousel;
-		}
-
-		var slides =
-			'<div class="carousel slide" data-ride="carousel" data-interval="false">'
-			+ '<div class="carousel-inner" role="listbox">';
-
-		for (var i = 0; i < Wizard.setup.slides.length; ++i) {
-			var currentSlide = Wizard.setup.slides[i],
-				slideContent = currentSlide.content;
-
-			if (typeof slideContent === 'object') {
-				slideContent = slideContent.html();
-			}
-			slides += '<div class="item" data-slide="' + currentSlide.identifier + '">' + slideContent + '</div>';
-		}
-
-		slides += '</div></div>';
-
-		Wizard.setup.$carousel = $(slides);
-		Wizard.setup.$carousel.find('.item').first().addClass('active');
-
-		return Wizard.setup.$carousel;
-	};
-
-	/**
-	 * Renders the wizard
-	 *
-	 * @returns {$}
-	 */
-	Wizard.show = function() {
-		var $slides = Wizard.generateSlides(),
-			firstSlide = Wizard.setup.slides[0];
-
-		var $modal = Modal.confirm(
-			firstSlide.title,
-			$slides,
-			firstSlide.severity,
-			[{
-				text: top.TYPO3.lang['wizard.button.cancel'],
-				active: true,
-				btnClass: 'btn-default',
-				name: 'cancel',
-				trigger: function() {
-					Wizard.getComponent().trigger('wizard-dismiss');
-				}
-			}, {
-				text: top.TYPO3.lang['wizard.button.next'],
-				btnClass: 'btn-' + Severity.getCssClass(firstSlide.severity),
-				name: 'next'
-			}]
-		);
-
-		if (Wizard.setup.forceSelection) {
-			Wizard.lockNextStep();
-		}
-
-		Wizard.addProgressBar($modal);
-		Wizard.initializeEvents();
-
-		Wizard.getComponent().on('wizard-visible', function() {
-			Wizard.runSlideCallback(firstSlide, Wizard.setup.$carousel.find('.item').first());
-		}).on('wizard-dismissed', function() {
-			Wizard.setup = $.extend(true, {}, Wizard.originalSetup);
-		});
-	};
-
-	/**
-	 * Runs the callback for the given slide
-	 *
-	 * @param {Object} slide
-	 * @param {$} $slide
-	 * @private
-	 */
-	Wizard.runSlideCallback = function(slide, $slide) {
-		if (typeof slide.callback === 'function') {
-			slide.callback($slide, Wizard.setup.settings, slide.identifier);
-		}
-	};
-
-	/**
-	 * Get the wizard component
-	 *
-	 * @returns {$}
-	 */
-	Wizard.getComponent = function() {
-		if (Wizard.setup.$carousel === null) {
-			Wizard.generateSlides();
-		}
-		return Wizard.setup.$carousel;
-	};
-
-	/**
-	 * Closes the wizard window
-	 */
-	Wizard.dismiss = function() {
-		Modal.dismiss();
-	};
-
-	/**
-	 * Locks the button for continuing to the next step
-	 *
-	 * @returns {$}
-	 */
-	Wizard.lockNextStep = function() {
-		var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]');
-		$button.prop('disabled', true);
-
-		return $button;
-	};
-
-	/**
-	 * Unlocks the button for continuing to the next step
-	 *
-	 * @returns {$}
-	 */
-	Wizard.unlockNextStep = function() {
-		var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]');
-		$button.prop('disabled', false);
-
-		return $button;
-	};
-
-	// Store the initial setup
-	Wizard.originalSetup = $.extend(true, {}, Wizard.setup);
-
-	// expose as global object
-	TYPO3.Wizard = Wizard;
-
-	return Wizard;
+  'use strict';
+
+  try {
+    // fetch from parent
+    if (parent && parent.window.TYPO3 && parent.window.TYPO3.Wizard) {
+      return parent.window.TYPO3.Wizard;
+    }
+
+    // fetch object from outer frame
+    if (top && top.TYPO3 && top.TYPO3.Wizard) {
+      return top.TYPO3.Wizard;
+    }
+  } catch (e) {
+    // This only happens if the opener, parent or top is some other url (eg a local file)
+    // which loaded the current window. Then the browser's cross domain policy jumps in
+    // and raises an exception.
+    // For this case we are safe and we can create our global object below.
+  }
+
+  /**
+   * @type {{setup: {slides: Array, settings: {}, forceSelection: boolean, $carousel: null}, originalSetup: {}}}
+   * @exports TYPO3/CMS/Backend/Wizard
+   */
+  var Wizard = {
+    setup: {
+      slides: [],
+      settings: {},
+      forceSelection: true,
+      $carousel: null
+    },
+    originalSetup: {}
+  };
+
+  /**
+   * Initializes the events after building the wizards
+   *
+   * @private
+   */
+  Wizard.initializeEvents = function() {
+    var $modal = Wizard.setup.$carousel.closest('.modal'),
+      $modalTitle = $modal.find('.modal-title'),
+      $modalFooter = $modal.find('.modal-footer'),
+      $nextButton = $modalFooter.find('button[name="next"]');
+
+    $nextButton.on('click', function() {
+      Wizard.setup.$carousel.carousel('next');
+    });
+
+    Wizard.setup.$carousel.on('slide.bs.carousel', function() {
+      var nextSlideNumber = Wizard.setup.$carousel.data('currentSlide') + 1,
+        currentIndex = Wizard.setup.$carousel.data('currentIndex') + 1;
+
+      $modalTitle.text(Wizard.setup.slides[currentIndex].title);
+
+      Wizard.setup.$carousel.data('currentSlide', nextSlideNumber);
+      Wizard.setup.$carousel.data('currentIndex', currentIndex);
+
+      if (nextSlideNumber >= Wizard.setup.$carousel.data('realSlideCount')) {
+        // Point of no return - hide modal footer disable any closing ability
+        $modal.find('.modal-header .close').remove();
+        $modalFooter.slideUp();
+      } else {
+        $modalFooter.find('.progress-bar')
+          .width(Wizard.setup.$carousel.data('initialStep') * nextSlideNumber + '%')
+          .text(top.TYPO3.lang['wizard.progress']
+            .replace('{0}', nextSlideNumber)
+            .replace('{1}', Wizard.setup.$carousel.data('slideCount')));
+      }
+
+      $nextButton
+        .removeClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex - 1].severity))
+        .addClass('btn-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity));
+
+      $modal
+        .removeClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex - 1].severity))
+        .addClass('modal-severity-' + Severity.getCssClass(Wizard.setup.slides[currentIndex].severity));
+    }).on('slid.bs.carousel', function(e) {
+      var currentIndex = Wizard.setup.$carousel.data('currentIndex'),
+        slide = Wizard.setup.slides[currentIndex];
+
+      Wizard.runSlideCallback(slide, $(e.relatedTarget));
+
+      if (Wizard.setup.forceSelection) {
+        Wizard.lockNextStep();
+      }
+    });
+
+    /**
+     * Custom event, closes the wizard
+     */
+    var cmp = Wizard.getComponent();
+    cmp.on('wizard-dismiss', Wizard.dismiss);
+
+    Modal.currentModal.on('hidden.bs.modal', function() {
+      cmp.trigger('wizard-dismissed');
+    }).on('shown.bs.modal', function() {
+      cmp.trigger('wizard-visible');
+    });
+  };
+
+  /**
+   * @param {String} key
+   * @param {*} value
+   * @returns {Object}
+   */
+  Wizard.set = function(key, value) {
+    Wizard.setup.settings[key] = value;
+    return Wizard;
+  };
+
+  /**
+   * Adds a new slide to the wizard
+   *
+   * @param {String} identifier
+   * @param {String} title
+   * @param {String} content
+   * @param {String} severity
+   * @param {Function} callback
+   * @returns {Object}
+   */
+  Wizard.addSlide = function(identifier, title, content, severity, callback) {
+    Wizard.setup.slides.push({
+      identifier: identifier,
+      title: title,
+      content: content || '',
+      severity: (typeof severity !== 'undefined' ? severity : Severity.info),
+      callback: callback
+    });
+
+    return Wizard;
+  };
+
+  /**
+   * Adds a final processing slide
+   *
+   * @param {Function} callback
+   * @returns {Object}
+   */
+  Wizard.addFinalProcessingSlide = function(callback) {
+    if (typeof callback !== 'function') {
+      callback = function() {
+        Wizard.dismiss();
+      }
+    }
+
+    return Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
+      var $processingSlide = $('<div />', {class: 'text-center'}).append(markup);
+      Wizard.addSlide(
+        'final-processing-slide', top.TYPO3.lang['wizard.processing.title'],
+        $processingSlide[0].outerHTML,
+        Severity.info,
+        callback
+      );
+    });
+  };
+
+  /**
+   * Processes the footer of the modal
+   *
+   * @private
+   */
+  Wizard.addProgressBar = function() {
+    var realSlideCount = Wizard.setup.$carousel.find('.item').length,
+      slideCount = Math.max(1, realSlideCount),
+      initialStep,
+      $modal = Wizard.setup.$carousel.closest('.modal'),
+      $modalFooter = $modal.find('.modal-footer');
+
+    initialStep = Math.round(100 / slideCount);
+
+    Wizard.setup.$carousel
+      .data('initialStep', initialStep)
+      .data('slideCount', slideCount)
+      .data('realSlideCount', realSlideCount)
+      .data('currentIndex', 0)
+      .data('currentSlide', 1);
+
+    // Append progress bar to modal footer
+    if (slideCount > 1) {
+      $modalFooter.prepend(
+        $('<div />', {class: 'progress'}).append(
+          $('<div />', {
+            role: 'progressbar',
+            class: 'progress-bar',
+            'aria-valuemin': 0,
+            'aria-valuenow': initialStep,
+            'aria-valuemax': 100
+          }).width(initialStep + '%').text(
+            top.TYPO3.lang['wizard.progress']
+              .replace('{0}', '1')
+              .replace('{1}', slideCount)
+          )
+        )
+      );
+    }
+  };
+
+  /**
+   * Generates the markup of slides added by addSlide()
+   *
+   * @returns {$}
+   * @private
+   */
+  Wizard.generateSlides = function() {
+    // Check whether the slides were already generated
+    if (Wizard.setup.$carousel !== null) {
+      return Wizard.setup.$carousel;
+    }
+
+    var slides =
+      '<div class="carousel slide" data-ride="carousel" data-interval="false">'
+      + '<div class="carousel-inner" role="listbox">';
+
+    for (var i = 0; i < Wizard.setup.slides.length; ++i) {
+      var currentSlide = Wizard.setup.slides[i],
+        slideContent = currentSlide.content;
+
+      if (typeof slideContent === 'object') {
+        slideContent = slideContent.html();
+      }
+      slides += '<div class="item" data-slide="' + currentSlide.identifier + '">' + slideContent + '</div>';
+    }
+
+    slides += '</div></div>';
+
+    Wizard.setup.$carousel = $(slides);
+    Wizard.setup.$carousel.find('.item').first().addClass('active');
+
+    return Wizard.setup.$carousel;
+  };
+
+  /**
+   * Renders the wizard
+   *
+   * @returns {$}
+   */
+  Wizard.show = function() {
+    var $slides = Wizard.generateSlides(),
+      firstSlide = Wizard.setup.slides[0];
+
+    var $modal = Modal.confirm(
+      firstSlide.title,
+      $slides,
+      firstSlide.severity,
+      [{
+        text: top.TYPO3.lang['wizard.button.cancel'],
+        active: true,
+        btnClass: 'btn-default',
+        name: 'cancel',
+        trigger: function() {
+          Wizard.getComponent().trigger('wizard-dismiss');
+        }
+      }, {
+        text: top.TYPO3.lang['wizard.button.next'],
+        btnClass: 'btn-' + Severity.getCssClass(firstSlide.severity),
+        name: 'next'
+      }]
+    );
+
+    if (Wizard.setup.forceSelection) {
+      Wizard.lockNextStep();
+    }
+
+    Wizard.addProgressBar($modal);
+    Wizard.initializeEvents();
+
+    Wizard.getComponent().on('wizard-visible', function() {
+      Wizard.runSlideCallback(firstSlide, Wizard.setup.$carousel.find('.item').first());
+    }).on('wizard-dismissed', function() {
+      Wizard.setup = $.extend(true, {}, Wizard.originalSetup);
+    });
+  };
+
+  /**
+   * Runs the callback for the given slide
+   *
+   * @param {Object} slide
+   * @param {$} $slide
+   * @private
+   */
+  Wizard.runSlideCallback = function(slide, $slide) {
+    if (typeof slide.callback === 'function') {
+      slide.callback($slide, Wizard.setup.settings, slide.identifier);
+    }
+  };
+
+  /**
+   * Get the wizard component
+   *
+   * @returns {$}
+   */
+  Wizard.getComponent = function() {
+    if (Wizard.setup.$carousel === null) {
+      Wizard.generateSlides();
+    }
+    return Wizard.setup.$carousel;
+  };
+
+  /**
+   * Closes the wizard window
+   */
+  Wizard.dismiss = function() {
+    Modal.dismiss();
+  };
+
+  /**
+   * Locks the button for continuing to the next step
+   *
+   * @returns {$}
+   */
+  Wizard.lockNextStep = function() {
+    var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]');
+    $button.prop('disabled', true);
+
+    return $button;
+  };
+
+  /**
+   * Unlocks the button for continuing to the next step
+   *
+   * @returns {$}
+   */
+  Wizard.unlockNextStep = function() {
+    var $button = Wizard.setup.$carousel.closest('.modal').find('button[name="next"]');
+    $button.prop('disabled', false);
+
+    return $button;
+  };
+
+  // Store the initial setup
+  Wizard.originalSetup = $.extend(true, {}, Wizard.setup);
+
+  // expose as global object
+  TYPO3.Wizard = Wizard;
+
+  return Wizard;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js
index f8e8171948c9..8cc79e735da0 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/Wizard/Colorpicker.js
@@ -15,61 +15,61 @@
  * Module: TYPO3/CMS/Backend/Wizard/Colorpicker
  * Colorpicker JavaScript
  */
-define(['jquery'], function ($) {
-	'use strict';
+define(['jquery'], function($) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{options: {}}}
-	 * @exports TYPO3/CMS/Backend/Wizard/Colorpicker
-	 */
-	var Colorpicker = {
-		options: {}
-	};
+  /**
+   *
+   * @type {{options: {}}}
+   * @exports TYPO3/CMS/Backend/Wizard/Colorpicker
+   */
+  var Colorpicker = {
+    options: {}
+  };
 
-	/**
-	 *
-	 * @param {Object} options
-	 */
-	Colorpicker.setFieldChangeFunctions = function(options) {
-		Colorpicker.options = options;
-	};
+  /**
+   *
+   * @param {Object} options
+   */
+  Colorpicker.setFieldChangeFunctions = function(options) {
+    Colorpicker.options = options;
+  };
 
-	/**
-	 *
-	 */
-	Colorpicker.initializeEvents = function() {
-		// Set color value
-		$('.t3js-colorpicker-value').on('click', function(e) {
-			e.preventDefault();
-			$('#colorValue').val($(this).data('color-value'));
-			$(this).closest('form').submit();
-		});
+  /**
+   *
+   */
+  Colorpicker.initializeEvents = function() {
+    // Set color value
+    $('.t3js-colorpicker-value').on('click', function(e) {
+      e.preventDefault();
+      $('#colorValue').val($(this).data('color-value'));
+      $(this).closest('form').submit();
+    });
 
-		// Handle the change of the color selector
-		$('.t3js-colorpicker-selector').on('change', function(e) {
-			e.preventDefault();
-			$('#colorValue').val($(this).val());
-			$(this).closest('form').submit();
-		});
+    // Handle the change of the color selector
+    $('.t3js-colorpicker-selector').on('change', function(e) {
+      e.preventDefault();
+      $('#colorValue').val($(this).val());
+      $(this).closest('form').submit();
+    });
 
-		// Handle the transfer of the color value and closing of popup
-		$('#colorpicker-saveclose').on('click', function(e) {
-			e.preventDefault();
-			var theField = $('[data-formengine-input-name="' + $('[name="fieldName"]').val() + '"]').get(0);
-			if (theField) {
-				theField.value = $('#colorValue').val();
+    // Handle the transfer of the color value and closing of popup
+    $('#colorpicker-saveclose').on('click', function(e) {
+      e.preventDefault();
+      var theField = $('[data-formengine-input-name="' + $('[name="fieldName"]').val() + '"]').get(0);
+      if (theField) {
+        theField.value = $('#colorValue').val();
 
-				if (typeof Colorpicker.options.fieldChangeFunctions === 'function') {
-					Colorpicker.options.fieldChangeFunctions();
-				}
-			}
-			parent.close();
-			return false;
-		});
-	};
+        if (typeof Colorpicker.options.fieldChangeFunctions === 'function') {
+          Colorpicker.options.fieldChangeFunctions();
+        }
+      }
+      parent.close();
+      return false;
+    });
+  };
 
-	$(Colorpicker.initializeEvents);
+  $(Colorpicker.initializeEvents);
 
-	return Colorpicker;
+  return Colorpicker;
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/backend.js b/typo3/sysext/backend/Resources/Public/JavaScript/backend.js
index 42e9417e25c1..f991de31c81c 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/backend.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/backend.js
@@ -21,104 +21,106 @@ var TYPO3 = TYPO3 || {};
  * jump the backend to a module
  */
 function jump(url, modName, mainModName, pageId) {
-	if (isNaN(pageId)) {
-		pageId = -2;
-	}
-	// clear information about which entry in nav. tree that might have been highlighted.
-	top.fsMod.navFrameHighlightedID = [];
-	top.fsMod.recentIds['web'] = pageId;
+  if (isNaN(pageId)) {
+    pageId = -2;
+  }
+  // clear information about which entry in nav. tree that might have been highlighted.
+  top.fsMod.navFrameHighlightedID = [];
+  top.fsMod.recentIds['web'] = pageId;
 
-	top.nextLoadModuleUrl = url;
-	top.TYPO3.ModuleMenu.App.showModule(modName);
+  top.nextLoadModuleUrl = url;
+  top.TYPO3.ModuleMenu.App.showModule(modName);
 }
 
 /**
  * Function similar to PHPs  rawurlencode();
  */
 function rawurlencode(str) {
-	var output = encodeURIComponent(str);
-	output = str_replace("*","%2A", output);
-	output = str_replace("+","%2B", output);
-	output = str_replace("/","%2F", output);
-	output = str_replace("@","%40", output);
-	return output;
+  var output = encodeURIComponent(str);
+  output = str_replace("*", "%2A", output);
+  output = str_replace("+", "%2B", output);
+  output = str_replace("/", "%2F", output);
+  output = str_replace("@", "%40", output);
+  return output;
 }
 
 
 /**
  * String-replace function
  */
-function str_replace(match,replace,string)	{	//
-	var input = ""+string;
-	var matchStr = ""+match;
-	if (!matchStr)	{return string;}
-	var output = "";
-	var pointer=0;
-	var pos = input.indexOf(matchStr);
-	while (pos !== -1) {
-		output+=""+input.substr(pointer, pos-pointer)+replace;
-		pointer=pos+matchStr.length;
-		pos = input.indexOf(match,pos+1);
-	}
-	output+=""+input.substr(pointer);
-	return output;
+function str_replace(match, replace, string) {	//
+  var input = "" + string;
+  var matchStr = "" + match;
+  if (!matchStr) {
+    return string;
+  }
+  var output = "";
+  var pointer = 0;
+  var pos = input.indexOf(matchStr);
+  while (pos !== -1) {
+    output += "" + input.substr(pointer, pos - pointer) + replace;
+    pointer = pos + matchStr.length;
+    pos = input.indexOf(match, pos + 1);
+  }
+  output += "" + input.substr(pointer);
+  return output;
 }
 
 
-
 /**
  * Launcing information window for records/files (fileref as "table" argument)
  */
 function launchView(table, uid) {
-	var thePreviewWindow = window.open(TYPO3.settings.ShowItem.moduleUrl + '&table=' + encodeURIComponent(table) + "&uid=" + encodeURIComponent(uid),
-			"ShowItem" + Math.random().toString(16).slice(2),
-			"width=650,height=600,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
-	if (thePreviewWindow && thePreviewWindow.focus) {
-		thePreviewWindow.focus();
-	}
+  var thePreviewWindow = window.open(TYPO3.settings.ShowItem.moduleUrl + '&table=' + encodeURIComponent(table) + "&uid=" + encodeURIComponent(uid),
+    "ShowItem" + Math.random().toString(16).slice(2),
+    "width=650,height=600,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
+  if (thePreviewWindow && thePreviewWindow.focus) {
+    thePreviewWindow.focus();
+  }
 }
 
 /**
  * Opens plain window with url
  */
-function openUrlInWindow(url,windowName)	{	//
-	regularWindow = window.open(
-		url,
-		windowName,
-		"status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
-	regularWindow.focus();
-	return false;
+function openUrlInWindow(url, windowName) {	//
+  regularWindow = window.open(
+    url,
+    windowName,
+    "status=1,menubar=1,resizable=1,location=1,directories=0,scrollbars=1,toolbar=1");
+  regularWindow.focus();
+  return false;
 }
 
 /**
  * Loads a page id for editing in the page edit module:
  */
-function loadEditId(id,addGetVars)	{	//
-	top.fsMod.recentIds.web = id;
-	top.fsMod.navFrameHighlightedID.web = "pages" + id + "_0";		// For highlighting
+function loadEditId(id, addGetVars) {	//
+  top.fsMod.recentIds.web = id;
+  top.fsMod.navFrameHighlightedID.web = "pages" + id + "_0";		// For highlighting
 
-	if (top.nav_frame && top.nav_frame.refresh_nav) {
-		top.nav_frame.refresh_nav();
-	}
-	if (TYPO3.configuration.pageModule) {
-		top.goToModule(TYPO3.configuration.pageModule, 0, addGetVars?addGetVars:"");
-	}
+  if (top.nav_frame && top.nav_frame.refresh_nav) {
+    top.nav_frame.refresh_nav();
+  }
+  if (TYPO3.configuration.pageModule) {
+    top.goToModule(TYPO3.configuration.pageModule, 0, addGetVars ? addGetVars : "");
+  }
 }
 
 /**
  * Returns incoming URL (to a module) unless nextLoadModuleUrl is set. If that is the case nextLoadModuleUrl is returned (and cleared)
  * Used by the shortcut frame to set a "intermediate URL"
  */
-var nextLoadModuleUrl="";
-function getModuleUrl(inUrl)	{	//
-	var nMU;
-	if (top.nextLoadModuleUrl) {
-		nMU=top.nextLoadModuleUrl;
-		top.nextLoadModuleUrl="";
-		return nMU;
-	} else {
-		return inUrl;
-	}
+var nextLoadModuleUrl = "";
+
+function getModuleUrl(inUrl) {	//
+  var nMU;
+  if (top.nextLoadModuleUrl) {
+    nMU = top.nextLoadModuleUrl;
+    top.nextLoadModuleUrl = "";
+    return nMU;
+  } else {
+    return inUrl;
+  }
 }
 
 // Used by Frameset Modules
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js
index 7faccd830d0c..691dffbaa144 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jquery.clearable.js
@@ -16,109 +16,110 @@
  * These fields show a "clear"-button when someone hovers over them and
  * they are not empty.
  * Options:
- *   * 'onClear':	Function that is called after clearing. Takes no arguments,
- *					'this' is set to the clearable input element. Defaults to an
- *					empty function.
+ *   * 'onClear':  Function that is called after clearing. Takes no arguments,
+ *          'this' is set to the clearable input element. Defaults to an
+ *          empty function.
  */
 (function(factory) {
-	if (typeof define === "function" && define.amd) {
-		// AMD. Register as an anonymous module.
-		define([ "jquery" ], factory);
-	} else {
-		// Browser globals
-		factory(jQuery);
-	}
+  if (typeof define === "function" && define.amd) {
+    // AMD. Register as an anonymous module.
+    define(["jquery"], factory);
+  } else {
+    // Browser globals
+    factory(jQuery);
+  }
 }(function($) {
-	$.fn.clearable = function(options) {
+  $.fn.clearable = function(options) {
 
-		var defaults = {
-			'onClear': function() {}
-		};
+    var defaults = {
+      'onClear': function() {
+      }
+    };
 
-		// The inlined markup represent the current generated markup from the
-		// icon api for the icon actions-close that can be found in the official
-		// icon repository and is registered in the backend icon api.
-		//
-		// It´s not possible to use/open the backend icon api without opening
-		// new possible vectors for attackers to sniff system informations.
-		//
-		// When the icon definition of actions-close changes also the inlined
-		// icon should be updated.
-		//
-		// https://github.com/typo3/typo3.icons
-		var closeIcon = '<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">' +
-			'<span class="icon-markup">' +
-			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0 .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7 0l.7.7c.2.2.2.5 0 .7z" class="icon-color"/></svg>' +
-			'</span>' +
-			'</span>';
+    // The inlined markup represent the current generated markup from the
+    // icon api for the icon actions-close that can be found in the official
+    // icon repository and is registered in the backend icon api.
+    //
+    // It´s not possible to use/open the backend icon api without opening
+    // new possible vectors for attackers to sniff system informations.
+    //
+    // When the icon definition of actions-close changes also the inlined
+    // icon should be updated.
+    //
+    // https://github.com/typo3/typo3.icons
+    var closeIcon = '<span class="t3js-icon icon icon-size-small icon-state-default icon-actions-close" data-identifier="actions-close">' +
+      '<span class="icon-markup">' +
+      '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M11.9 5.5L9.4 8l2.5 2.5c.2.2.2.5 0 .7l-.7.7c-.2.2-.5.2-.7 0L8 9.4l-2.5 2.5c-.2.2-.5.2-.7 0l-.7-.7c-.2-.2-.2-.5 0-.7L6.6 8 4.1 5.5c-.2-.2-.2-.5 0-.7l.7-.7c.2-.2.5-.2.7 0L8 6.6l2.5-2.5c.2-.2.5-.2.7 0l.7.7c.2.2.2.5 0 .7z" class="icon-color"/></svg>' +
+      '</span>' +
+      '</span>';
 
-		// Merge defaults and given options. Given options have higher priority
-		// because they are the last argument.
-		var settings = $.extend({}, defaults, options);
+    // Merge defaults and given options. Given options have higher priority
+    // because they are the last argument.
+    var settings = $.extend({}, defaults, options);
 
-		// Iterate over the list of inputs and make each clearable. Return
-		// the list to allow chaining.
-		return this.each(function() {
+    // Iterate over the list of inputs and make each clearable. Return
+    // the list to allow chaining.
+    return this.each(function() {
 
-			// The input element to make clearable.
-			var $input = $(this);
+      // The input element to make clearable.
+      var $input = $(this);
 
-			// make sure the input field is not used twice for a clearable
-			// or the input field is a colorpicker, because it breaks the colorpicker.
-			if (!$input.data('clearable') && !$input.hasClass('t3js-color-picker')) {
-				$input.data('clearable', 'loaded');
-				var hiddenClass = $input.hasClass('hidden') ? ' hidden' : '';
+      // make sure the input field is not used twice for a clearable
+      // or the input field is a colorpicker, because it breaks the colorpicker.
+      if (!$input.data('clearable') && !$input.hasClass('t3js-color-picker')) {
+        $input.data('clearable', 'loaded');
+        var hiddenClass = $input.hasClass('hidden') ? ' hidden' : '';
 
-				// Wrap it with a div and add a span that is the trigger for
-				// clearing.
-				$input.wrap('<div class="form-control-clearable" />');
-				$input.after('<button type="button" class="close' + hiddenClass + '" tabindex="-1" aria-hidden="true">' + closeIcon + '</button>');
-				$input.addClass('t3js-clearable');
+        // Wrap it with a div and add a span that is the trigger for
+        // clearing.
+        $input.wrap('<div class="form-control-clearable" />');
+        $input.after('<button type="button" class="close' + hiddenClass + '" tabindex="-1" aria-hidden="true">' + closeIcon + '</button>');
+        $input.addClass('t3js-clearable');
 
-				var $clearer = $input.next();
+        var $clearer = $input.next();
 
-				// Register a listener the various events triggering the clearer to
-				// be shown or hidden.
-				var handler = function() {
-					var $element = $(this);
-					if ($element.next('input[type=hidden]').length) {
-						$element = $element.next('input[type=hidden]');
-					}
-					var value = $element.val();
-					var hasEmptyValue = (value.length === 0);
-					if (value === "0" && $element.closest('.t3js-datetimepicker').length) {
-						hasEmptyValue = true;
-					}
+        // Register a listener the various events triggering the clearer to
+        // be shown or hidden.
+        var handler = function() {
+          var $element = $(this);
+          if ($element.next('input[type=hidden]').length) {
+            $element = $element.next('input[type=hidden]');
+          }
+          var value = $element.val();
+          var hasEmptyValue = (value.length === 0);
+          if (value === "0" && $element.closest('.t3js-datetimepicker').length) {
+            hasEmptyValue = true;
+          }
 
-					// only show the clearing button if the value is set, or if the value is not "0" on a datetime field
-					if (!hasEmptyValue) {
-						$clearer.show();
-					} else {
-						$clearer.hide();
-					}
-				};
-				$input.on('keyup', handler);
-				$input.on('mouseenter', handler);
-				$input.on('change', handler);
-				$input.on('initialize', handler);
+          // only show the clearing button if the value is set, or if the value is not "0" on a datetime field
+          if (!hasEmptyValue) {
+            $clearer.show();
+          } else {
+            $clearer.hide();
+          }
+        };
+        $input.on('keyup', handler);
+        $input.on('mouseenter', handler);
+        $input.on('change', handler);
+        $input.on('initialize', handler);
 
-				// The actual clearing action. Focus the input element afterwards,
-				// the user probably wants to type into it after clearing.
-				$clearer.click(function(e) {
-					e.preventDefault();
-					$input.val('').change();
-					if (!$input.hasClass("t3js-datetimepicker")) {
-						$input.focus();
-					}
-					$input.trigger('keyup');
+        // The actual clearing action. Focus the input element afterwards,
+        // the user probably wants to type into it after clearing.
+        $clearer.click(function(e) {
+          e.preventDefault();
+          $input.val('').change();
+          if (!$input.hasClass("t3js-datetimepicker")) {
+            $input.focus();
+          }
+          $input.trigger('keyup');
 
-					if ('function' === typeof(settings.onClear)) {
-						settings.onClear.call($input.get());
-					}
-				});
+          if ('function' === typeof(settings.onClear)) {
+            settings.onClear.call($input.get());
+          }
+        });
 
-				$input.trigger('initialize');
-			}
-		});
-	};
+        $input.trigger('initialize');
+      }
+    });
+  };
 }));
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js
index d34384ebddaf..313b34634a21 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.evalfield.js
@@ -16,505 +16,557 @@
  */
 
 function evalFunc() {
-	this.input = evalFunc_input;
-	this.output = evalFunc_output;
-	this.parseInt = evalFunc_parseInt;
-	this.getNumChars = evalFunc_getNumChars;
-	this.parseDouble = evalFunc_parseDouble;
-	this.noSpace = evalFunc_noSpace;
-	this.getSecs = evalFunc_getSecs;
-	this.getYear = evalFunc_getYear;
-	this.getTimeSecs = evalFunc_getTimeSecs;
-	this.getTime = evalFunc_getTime;
-	this.getDate = evalFunc_getDate;
-	this.getTimestamp = evalFunc_getTimestamp;
-	this.caseSwitch = evalFunc_caseSwitch;
-	this.evalObjValue = evalFunc_evalObjValue;
-	this.outputObjValue = evalFunc_outputObjValue;
-	this.split = evalFunc_splitStr;
-	this.pol = evalFunc_pol;
-	this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC;
-
-	this.ltrim = evalFunc_ltrim;
-	this.btrim = evalFunc_btrim;
-	var today = new Date();
-	this.lastYear = this.getYear(today);
-	this.lastDate = this.getDate(today);
-	this.lastTime = 0;
-	this.refDate = today;
-	this.isInString = '';
-	this.USmode = 0;
+  this.input = evalFunc_input;
+  this.output = evalFunc_output;
+  this.parseInt = evalFunc_parseInt;
+  this.getNumChars = evalFunc_getNumChars;
+  this.parseDouble = evalFunc_parseDouble;
+  this.noSpace = evalFunc_noSpace;
+  this.getSecs = evalFunc_getSecs;
+  this.getYear = evalFunc_getYear;
+  this.getTimeSecs = evalFunc_getTimeSecs;
+  this.getTime = evalFunc_getTime;
+  this.getDate = evalFunc_getDate;
+  this.getTimestamp = evalFunc_getTimestamp;
+  this.caseSwitch = evalFunc_caseSwitch;
+  this.evalObjValue = evalFunc_evalObjValue;
+  this.outputObjValue = evalFunc_outputObjValue;
+  this.split = evalFunc_splitStr;
+  this.pol = evalFunc_pol;
+  this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC;
+
+  this.ltrim = evalFunc_ltrim;
+  this.btrim = evalFunc_btrim;
+  var today = new Date();
+  this.lastYear = this.getYear(today);
+  this.lastDate = this.getDate(today);
+  this.lastTime = 0;
+  this.refDate = today;
+  this.isInString = '';
+  this.USmode = 0;
 }
+
 function evalFunc_pol(foreign, value) {
-	return eval (((foreign=="-")?'-':'')+value);
+  return eval(((foreign == "-") ? '-' : '') + value);
 }
-function evalFunc_evalObjValue(FObj,value) {
-	var evallist = FObj.evallist;
-	this.isInString = (FObj.is_in) ? ''+FObj.is_in : '';
-	var index=1;
-	var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false;
-	var newValue=value;
-	while (theEvalType) {
-		if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') {
-			newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue);
-		} else {
-			newValue = evalFunc.input(theEvalType, newValue);
-		}
-		index++;
-		theEvalType = this.split(evallist, ",", index);
-	}
-	return newValue;
+
+function evalFunc_evalObjValue(FObj, value) {
+  var evallist = FObj.evallist;
+  this.isInString = (FObj.is_in) ? '' + FObj.is_in : '';
+  var index = 1;
+  var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false;
+  var newValue = value;
+  while (theEvalType) {
+    if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') {
+      newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue);
+    } else {
+      newValue = evalFunc.input(theEvalType, newValue);
+    }
+    index++;
+    theEvalType = this.split(evallist, ",", index);
+  }
+  return newValue;
 }
-function evalFunc_outputObjValue(FObj,value) {
-	var evallist = FObj.evallist;
-	var index=1;
-	var theEvalType = this.split(evallist, ",", index);
-	var newValue=value;
-	while (theEvalType) {
-		if (theEvalType != 'required') {
-			newValue = evalFunc.output(theEvalType, value, FObj);
-		}
-		index++;
-		theEvalType = this.split(evallist, ",", index);
-	}
-	return newValue;
+
+function evalFunc_outputObjValue(FObj, value) {
+  var evallist = FObj.evallist;
+  var index = 1;
+  var theEvalType = this.split(evallist, ",", index);
+  var newValue = value;
+  while (theEvalType) {
+    if (theEvalType != 'required') {
+      newValue = evalFunc.output(theEvalType, value, FObj);
+    }
+    index++;
+    theEvalType = this.split(evallist, ",", index);
+  }
+  return newValue;
 }
-function evalFunc_caseSwitch(type,inVal) {
-	var theVal = ''+inVal;
-	var newString = '';
-	switch (type) {
-		case "alpha":
-		case "num":
-		case "alphanum":
-		case "alphanum_x":
-			for (var a=0;a<theVal.length;a++) {
-				var theChar = theVal.substr(a,1);
-				var special = (theChar == '_' || theChar == '-');
-				var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
-				var num = (theChar>='0' && theChar<='9');
-				switch(type) {
-					case "alphanum":	special=0;		break;
-					case "alpha":	num=0; special=0;		break;
-					case "num":	alpha=0; special=0;		break;
-				}
-				if (alpha || num || special) {
-					newString+=theChar;
-				}
-			}
-			break;
-		case "is_in":
-			if (this.isInString) {
-				for (var a=0;a<theVal.length;a++) {
-					var theChar = theVal.substr(a,1);
-					if (this.isInString.indexOf(theChar)!=-1) {
-						newString+=theChar;
-					}
-				}
-			} else {newString = theVal;}
-			break;
-		case "nospace":
-			newString = this.noSpace(theVal);
-			break;
-		case "upper":
-			newString = theVal.toUpperCase();
-			break;
-		case "lower":
-			newString = theVal.toLowerCase();
-			break;
-		default:
-			return inVal;
-	}
-	return newString;
+
+function evalFunc_caseSwitch(type, inVal) {
+  var theVal = '' + inVal;
+  var newString = '';
+  switch (type) {
+    case "alpha":
+    case "num":
+    case "alphanum":
+    case "alphanum_x":
+      for (var a = 0; a < theVal.length; a++) {
+        var theChar = theVal.substr(a, 1);
+        var special = (theChar == '_' || theChar == '-');
+        var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
+        var num = (theChar >= '0' && theChar <= '9');
+        switch (type) {
+          case "alphanum":
+            special = 0;
+            break;
+          case "alpha":
+            num = 0;
+            special = 0;
+            break;
+          case "num":
+            alpha = 0;
+            special = 0;
+            break;
+        }
+        if (alpha || num || special) {
+          newString += theChar;
+        }
+      }
+      break;
+    case "is_in":
+      if (this.isInString) {
+        for (var a = 0; a < theVal.length; a++) {
+          var theChar = theVal.substr(a, 1);
+          if (this.isInString.indexOf(theChar) != -1) {
+            newString += theChar;
+          }
+        }
+      } else {
+        newString = theVal;
+      }
+      break;
+    case "nospace":
+      newString = this.noSpace(theVal);
+      break;
+    case "upper":
+      newString = theVal.toUpperCase();
+      break;
+    case "lower":
+      newString = theVal.toLowerCase();
+      break;
+    default:
+      return inVal;
+  }
+  return newString;
 }
+
 function evalFunc_parseInt(value) {
-	var theVal = ''+value;
-	if (!value) {
-		return 0;
-	}
-	for (var a = 0; a < theVal.length; a++) {
-		if (theVal.substr(a,1)!='0') {
-			return parseInt(theVal.substr(a,theVal.length)) || 0;
-		}
-	}
-	return 0;
+  var theVal = '' + value;
+  if (!value) {
+    return 0;
+  }
+  for (var a = 0; a < theVal.length; a++) {
+    if (theVal.substr(a, 1) != '0') {
+      return parseInt(theVal.substr(a, theVal.length)) || 0;
+    }
+  }
+  return 0;
 }
+
 function evalFunc_getNumChars(value) {
-	var theVal = ''+value;
-	if (!value) {
-		return 0;
-	}
-	var outVal="";
-	for (var a = 0; a < theVal.length; a++) {
-		if (theVal.substr(a,1)==parseInt(theVal.substr(a,1))) {
-			outVal+=theVal.substr(a,1);
-		}
-	}
-	return outVal;
+  var theVal = '' + value;
+  if (!value) {
+    return 0;
+  }
+  var outVal = "";
+  for (var a = 0; a < theVal.length; a++) {
+    if (theVal.substr(a, 1) == parseInt(theVal.substr(a, 1))) {
+      outVal += theVal.substr(a, 1);
+    }
+  }
+  return outVal;
 }
+
 function evalFunc_parseDouble(value) {
-	var theVal = "" + value;
-	theVal = theVal.replace(/[^0-9,\.-]/g, "");
-	var negative = theVal.substring(0, 1) === '-';
-	theVal = theVal.replace(/-/g, "");
-	theVal = theVal.replace(/,/g, ".");
-	if (theVal.indexOf(".") == -1) {
-		theVal += ".0";
-	}
-	var parts = theVal.split(".");
-	var dec = parts.pop();
-	theVal = Number(parts.join("") + "." + dec);
-	if (negative) {
-		theVal *= -1;
-	}
-	theVal = theVal.toFixed(2);
-
-	return theVal;
+  var theVal = "" + value;
+  theVal = theVal.replace(/[^0-9,\.-]/g, "");
+  var negative = theVal.substring(0, 1) === '-';
+  theVal = theVal.replace(/-/g, "");
+  theVal = theVal.replace(/,/g, ".");
+  if (theVal.indexOf(".") == -1) {
+    theVal += ".0";
+  }
+  var parts = theVal.split(".");
+  var dec = parts.pop();
+  theVal = Number(parts.join("") + "." + dec);
+  if (negative) {
+    theVal *= -1;
+  }
+  theVal = theVal.toFixed(2);
+
+  return theVal;
 }
+
 function evalFunc_noSpace(value) {
-	var theVal = ''+value;
-	var newString="";
-	for (var a=0;a<theVal.length;a++) {
-		var theChar = theVal.substr(a,1);
-		if (theChar!=' ') {
-			newString+=theChar;
-		}
-	}
-	return newString;
+  var theVal = '' + value;
+  var newString = "";
+  for (var a = 0; a < theVal.length; a++) {
+    var theChar = theVal.substr(a, 1);
+    if (theChar != ' ') {
+      newString += theChar;
+    }
+  }
+  return newString;
 }
+
 function evalFunc_ltrim(value) {
-	var theVal = ''+value;
-	if (!value) {
-		return '';
-	}
-	for (var a = 0; a < theVal.length; a++) {
-		if (theVal.substr(a,1)!=' ') {
-			return theVal.substr(a,theVal.length);
-		}
-	}
-	return '';
+  var theVal = '' + value;
+  if (!value) {
+    return '';
+  }
+  for (var a = 0; a < theVal.length; a++) {
+    if (theVal.substr(a, 1) != ' ') {
+      return theVal.substr(a, theVal.length);
+    }
+  }
+  return '';
 }
+
 function evalFunc_btrim(value) {
-	var theVal = ''+value;
-	if (!value) {
-		return '';
-	}
-	for (var a = theVal.length; a > 0; a--) {
-		if (theVal.substr(a-1,1)!=' ') {
-			return theVal.substr(0,a);
-		}
-	}
-	return '';
+  var theVal = '' + value;
+  if (!value) {
+    return '';
+  }
+  for (var a = theVal.length; a > 0; a--) {
+    if (theVal.substr(a - 1, 1) != ' ') {
+      return theVal.substr(0, a);
+    }
+  }
+  return '';
 }
+
 function evalFunc_splitSingle(value) {
-	var theVal = ''+value;
-	this.values = new Array();
-	this.pointer = 3;
-	this.values[1]=theVal.substr(0,2);
-	this.values[2]=theVal.substr(2,2);
-	this.values[3]=theVal.substr(4,10);
+  var theVal = '' + value;
+  this.values = new Array();
+  this.pointer = 3;
+  this.values[1] = theVal.substr(0, 2);
+  this.values[2] = theVal.substr(2, 2);
+  this.values[3] = theVal.substr(4, 10);
 }
+
 function evalFunc_split(value) {
-	this.values = new Array();
-	this.valPol = new Array();
-	this.pointer = 0;
-	var numberMode = 0;
-	var theVal = "";
-	value+=" ";
-	for (var a=0;a<value.length;a++) {
-		var theChar = value.substr(a,1);
-		if (theChar<"0" || theChar>"9") {
-			if (numberMode) {
-				this.pointer++;
-				this.values[this.pointer]=theVal;
-				theVal = "";
-				numberMode=0;
-			}
-			if (theChar=="+" || theChar=="-") {
-				this.valPol[this.pointer+1] = theChar;
-			}
-		} else {
-			theVal+=theChar;
-			numberMode=1;
-		}
-	}
+  this.values = new Array();
+  this.valPol = new Array();
+  this.pointer = 0;
+  var numberMode = 0;
+  var theVal = "";
+  value += " ";
+  for (var a = 0; a < value.length; a++) {
+    var theChar = value.substr(a, 1);
+    if (theChar < "0" || theChar > "9") {
+      if (numberMode) {
+        this.pointer++;
+        this.values[this.pointer] = theVal;
+        theVal = "";
+        numberMode = 0;
+      }
+      if (theChar == "+" || theChar == "-") {
+        this.valPol[this.pointer + 1] = theChar;
+      }
+    } else {
+      theVal += theChar;
+      numberMode = 1;
+    }
+  }
 }
-function evalFunc_input(type,inVal) {
-	if (type=="md5") {
-		return MD5(inVal);
-	}
-	if (type=="trim") {
-		return this.ltrim(this.btrim(inVal));
-	}
-	if (type=="int") {
-		return this.parseInt(inVal);
-	}
-	if (type=="double2") {
-		return this.parseDouble(inVal);
-	}
-
-	var today = new Date();
-	var add=0;
-	var value = this.ltrim(inVal);
-	var values = new evalFunc_split(value);
-	var theCmd = value.substr(0,1);
-	value = this.caseSwitch(type,value);
-	if (value=="") {
-		return "";
-	}
-	switch (type) {
-		case "datetime":
-			switch (theCmd) {
-				case "d":
-				case "t":
-				case "n":
-					this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				case "+":
-				case "-":
-					if (this.lastTime == 0) {
-						this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
-					}
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
-					}
-					break;
-				default:
-					var index = value.indexOf(' ');
-					if (index!=-1) {
-						var dateVal = this.input("date", value.substr(index,value.length));
-						// set refDate so that evalFunc_input on time will work with correct DST information
-						this.refDate = new Date(dateVal*1000);
-						this.lastTime = dateVal + this.input("time", value.substr(0,index));
-					} else	{
-						// only date, no time
-						this.lastTime = this.input("date", value);
-					}
-			}
-			this.lastTime+=add*24*60*60;
-			return this.lastTime;
-			break;
-		case "year":
-			switch (theCmd) {
-				case "d":
-				case "t":
-				case "n":
-					this.lastYear = this.getYear(today);
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				case "+":
-				case "-":
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				default:
-					if (values.valPol[2]) {
-						add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-					}
-					var year = (values.values[1])?this.parseInt(values.values[1]):this.getYear(today);
-					if ((year >= 0 && year < 38) || (year >= 70 && year<100) || (year >= 1902 && year < 2038)) {
-						if (year<100) {
-							year = (year<38) ? year+=2000 : year+=1900;
-						}
-					} else {
-						year = this.getYear(today);
-					}
-					this.lastYear = year;
-			}
-			this.lastYear+=add;
-			return this.lastYear;
-			break;
-		case "date":
-			switch (theCmd) {
-				case "d":
-				case "t":
-				case "n":
-					this.lastDate = this.getTimestamp(today);
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				case "+":
-				case "-":
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				default:
-					var index = 4;
-					if (values.valPol[index]) {
-						add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
-					}
-					if (values.values[1] && values.values[1].length>2) {
-						if (values.valPol[2]) {
-							add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-						}
-						var temp = values.values[1];
-						values = new evalFunc_splitSingle(temp);
-					}
-
-					var year = (values.values[3])?this.parseInt(values.values[3]):this.getYear(today);
-					if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year<2038)) {
-						if (year<100) {
-							year = (year<38) ? year+=2000 : year+=1900;
-						}
-					} else {
-						year = this.getYear(today);
-					}
-					var month = (values.values[this.USmode?1:2])?this.parseInt(values.values[this.USmode?1:2]):today.getUTCMonth()+1;
-					var day = (values.values[this.USmode?2:1])?this.parseInt(values.values[this.USmode?2:1]):today.getUTCDate();
-
-					var theTime = new Date(parseInt(year), parseInt(month)-1, parseInt(day));
-
-					// Substract timezone offset from client
-					this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0);
-			}
-			this.lastDate+=add*24*60*60;
-			return this.lastDate;
-			break;
-		case "time":
-		case "timesec":
-			switch (theCmd) {
-				case "d":
-				case "t":
-				case "n":
-					this.lastTime = this.getTimeSecs(today);
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				case "+":
-				case "-":
-					if (this.lastTime == 0) {
-						this.lastTime = this.getTimeSecs(today);
-					}
-					if (values.valPol[1]) {
-						add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-					}
-					break;
-				default:
-					var index = (type=="timesec")?4:3;
-					if (values.valPol[index]) {
-						add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
-					}
-					if (values.values[1] && values.values[1].length>2) {
-						if (values.valPol[2]) {
-							add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-						}
-						var temp = values.values[1];
-						values = new evalFunc_splitSingle(temp);
-					}
-					var sec = (values.values[3])?this.parseInt(values.values[3]):today.getUTCSeconds();
-					if (sec > 59)	{sec=59;}
-					var min = (values.values[2])?this.parseInt(values.values[2]):today.getUTCMinutes();
-					if (min > 59)	{min=59;}
-					var hour = (values.values[1])?this.parseInt(values.values[1]):today.getUTCHours();
-					if (hour >= 24)	{hour=0;}
-
-					var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type=="timesec")?sec:0));
-
-					// Substract timezone offset from client
-					this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1);
-			}
-			this.lastTime+=add*60;
-			if (this.lastTime<0) {this.lastTime+=24*60*60;}
-			return this.lastTime;
-			break;
-		default:
-			return value;
-	}
+
+function evalFunc_input(type, inVal) {
+  if (type == "md5") {
+    return MD5(inVal);
+  }
+  if (type == "trim") {
+    return this.ltrim(this.btrim(inVal));
+  }
+  if (type == "int") {
+    return this.parseInt(inVal);
+  }
+  if (type == "double2") {
+    return this.parseDouble(inVal);
+  }
+
+  var today = new Date();
+  var add = 0;
+  var value = this.ltrim(inVal);
+  var values = new evalFunc_split(value);
+  var theCmd = value.substr(0, 1);
+  value = this.caseSwitch(type, value);
+  if (value == "") {
+    return "";
+  }
+  switch (type) {
+    case "datetime":
+      switch (theCmd) {
+        case "d":
+        case "t":
+        case "n":
+          this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        case "+":
+        case "-":
+          if (this.lastTime == 0) {
+            this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
+          }
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        default:
+          var index = value.indexOf(' ');
+          if (index != -1) {
+            var dateVal = this.input("date", value.substr(index, value.length));
+            // set refDate so that evalFunc_input on time will work with correct DST information
+            this.refDate = new Date(dateVal * 1000);
+            this.lastTime = dateVal + this.input("time", value.substr(0, index));
+          } else {
+            // only date, no time
+            this.lastTime = this.input("date", value);
+          }
+      }
+      this.lastTime += add * 24 * 60 * 60;
+      return this.lastTime;
+      break;
+    case "year":
+      switch (theCmd) {
+        case "d":
+        case "t":
+        case "n":
+          this.lastYear = this.getYear(today);
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        case "+":
+        case "-":
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        default:
+          if (values.valPol[2]) {
+            add = this.pol(values.valPol[2], this.parseInt(values.values[2]));
+          }
+          var year = (values.values[1]) ? this.parseInt(values.values[1]) : this.getYear(today);
+          if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year < 2038)) {
+            if (year < 100) {
+              year = (year < 38) ? year += 2000 : year += 1900;
+            }
+          } else {
+            year = this.getYear(today);
+          }
+          this.lastYear = year;
+      }
+      this.lastYear += add;
+      return this.lastYear;
+      break;
+    case "date":
+      switch (theCmd) {
+        case "d":
+        case "t":
+        case "n":
+          this.lastDate = this.getTimestamp(today);
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        case "+":
+        case "-":
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        default:
+          var index = 4;
+          if (values.valPol[index]) {
+            add = this.pol(values.valPol[index], this.parseInt(values.values[index]));
+          }
+          if (values.values[1] && values.values[1].length > 2) {
+            if (values.valPol[2]) {
+              add = this.pol(values.valPol[2], this.parseInt(values.values[2]));
+            }
+            var temp = values.values[1];
+            values = new evalFunc_splitSingle(temp);
+          }
+
+          var year = (values.values[3]) ? this.parseInt(values.values[3]) : this.getYear(today);
+          if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year < 2038)) {
+            if (year < 100) {
+              year = (year < 38) ? year += 2000 : year += 1900;
+            }
+          } else {
+            year = this.getYear(today);
+          }
+          var month = (values.values[this.USmode ? 1 : 2]) ? this.parseInt(values.values[this.USmode ? 1 : 2]) : today.getUTCMonth() + 1;
+          var day = (values.values[this.USmode ? 2 : 1]) ? this.parseInt(values.values[this.USmode ? 2 : 1]) : today.getUTCDate();
+
+          var theTime = new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
+
+          // Substract timezone offset from client
+          this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0);
+      }
+      this.lastDate += add * 24 * 60 * 60;
+      return this.lastDate;
+      break;
+    case "time":
+    case "timesec":
+      switch (theCmd) {
+        case "d":
+        case "t":
+        case "n":
+          this.lastTime = this.getTimeSecs(today);
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        case "+":
+        case "-":
+          if (this.lastTime == 0) {
+            this.lastTime = this.getTimeSecs(today);
+          }
+          if (values.valPol[1]) {
+            add = this.pol(values.valPol[1], this.parseInt(values.values[1]));
+          }
+          break;
+        default:
+          var index = (type == "timesec") ? 4 : 3;
+          if (values.valPol[index]) {
+            add = this.pol(values.valPol[index], this.parseInt(values.values[index]));
+          }
+          if (values.values[1] && values.values[1].length > 2) {
+            if (values.valPol[2]) {
+              add = this.pol(values.valPol[2], this.parseInt(values.values[2]));
+            }
+            var temp = values.values[1];
+            values = new evalFunc_splitSingle(temp);
+          }
+          var sec = (values.values[3]) ? this.parseInt(values.values[3]) : today.getUTCSeconds();
+          if (sec > 59) {
+            sec = 59;
+          }
+          var min = (values.values[2]) ? this.parseInt(values.values[2]) : today.getUTCMinutes();
+          if (min > 59) {
+            min = 59;
+          }
+          var hour = (values.values[1]) ? this.parseInt(values.values[1]) : today.getUTCHours();
+          if (hour >= 24) {
+            hour = 0;
+          }
+
+          var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type == "timesec") ? sec : 0));
+
+          // Substract timezone offset from client
+          this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1);
+      }
+      this.lastTime += add * 60;
+      if (this.lastTime < 0) {
+        this.lastTime += 24 * 60 * 60;
+      }
+      return this.lastTime;
+      break;
+    default:
+      return value;
+  }
 }
-function evalFunc_output(type,value,FObj) {
-	var theString = "";
-	switch (type) {
-		case "date":
-			if (!parseInt(value))	{return '';}
-			var theTime = new Date(parseInt(value) * 1000);
-			if (this.USmode) {
-				theString = (theTime.getUTCMonth()+1)+'-'+theTime.getUTCDate()+'-'+this.getYear(theTime);
-			} else {
-				theString = theTime.getUTCDate()+'-'+(theTime.getUTCMonth()+1)+'-'+this.getYear(theTime);
-			}
-			break;
-		case "datetime":
-			if (!parseInt(value))	{return '';}
-			theString = this.output("time",value)+' '+this.output("date",value);
-			break;
-		case "time":
-		case "timesec":
-			if (!parseInt(value))	{return '';}
-			var theTime = new Date(parseInt(value) * 1000);
-			var h = theTime.getUTCHours();
-			var m = theTime.getUTCMinutes();
-			var s = theTime.getUTCSeconds();
-			theString = h+':'+((m<10)?'0':'')+m + ((type=="timesec")?':'+((s<10)?'0':'')+s:'');
-			break;
-		case "password":
-			theString = (value)	? "********" : "";
-			break;
-		case "int":
-			theString = (FObj.checkbox && value==FObj.checkboxValue)?'':value;
-			break;
-		default:
-			theString = value;
-	}
-	return theString;
+
+function evalFunc_output(type, value, FObj) {
+  var theString = "";
+  switch (type) {
+    case "date":
+      if (!parseInt(value)) {
+        return '';
+      }
+      var theTime = new Date(parseInt(value) * 1000);
+      if (this.USmode) {
+        theString = (theTime.getUTCMonth() + 1) + '-' + theTime.getUTCDate() + '-' + this.getYear(theTime);
+      } else {
+        theString = theTime.getUTCDate() + '-' + (theTime.getUTCMonth() + 1) + '-' + this.getYear(theTime);
+      }
+      break;
+    case "datetime":
+      if (!parseInt(value)) {
+        return '';
+      }
+      theString = this.output("time", value) + ' ' + this.output("date", value);
+      break;
+    case "time":
+    case "timesec":
+      if (!parseInt(value)) {
+        return '';
+      }
+      var theTime = new Date(parseInt(value) * 1000);
+      var h = theTime.getUTCHours();
+      var m = theTime.getUTCMinutes();
+      var s = theTime.getUTCSeconds();
+      theString = h + ':' + ((m < 10) ? '0' : '') + m + ((type == "timesec") ? ':' + ((s < 10) ? '0' : '') + s : '');
+      break;
+    case "password":
+      theString = (value) ? "********" : "";
+      break;
+    case "int":
+      theString = (FObj.checkbox && value == FObj.checkboxValue) ? '' : value;
+      break;
+    default:
+      theString = value;
+  }
+  return theString;
 }
+
 function evalFunc_getSecs(timeObj) {
-	return timeObj.getUTCSeconds();
+  return timeObj.getUTCSeconds();
 }
+
 // Seconds since midnight:
 function evalFunc_getTime(timeObj) {
-	return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj);
+  return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj);
 }
+
 function evalFunc_getYear(timeObj) {
-	return timeObj.getUTCFullYear();
+  return timeObj.getUTCFullYear();
 }
+
 // Seconds since midnight with client timezone offset:
 function evalFunc_getTimeSecs(timeObj) {
-	return timeObj.getHours()*60*60+timeObj.getMinutes()*60+timeObj.getSeconds();
+  return timeObj.getHours() * 60 * 60 + timeObj.getMinutes() * 60 + timeObj.getSeconds();
 }
+
 function evalFunc_getDate(timeObj) {
-	var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
-	return this.getTimestamp(theTime);
+  var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
+  return this.getTimestamp(theTime);
 }
-function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) {
-	this.evallist = evallist;
-	this.is_in = is_in;
-	this.checkboxValue = checkboxValue;
-	this.checkbox = checkbox;
+
+function evalFunc_dummy(evallist, is_in, checkbox, checkboxValue) {
+  this.evallist = evallist;
+  this.is_in = is_in;
+  this.checkboxValue = checkboxValue;
+  this.checkbox = checkbox;
 }
+
 function evalFunc_splitStr(theStr1, delim, index) {
-	var theStr = ''+theStr1;
-	var lengthOfDelim = delim.length;
-	sPos = -lengthOfDelim;
-	if (index<1) {index=1;}
-	for (a=1; a<index; a++) {
-		sPos = theStr.indexOf(delim, sPos+lengthOfDelim);
-		if (sPos==-1)	{return null;}
-	}
-	ePos = theStr.indexOf(delim, sPos+lengthOfDelim);
-	if(ePos == -1)	{ePos = theStr.length;}
-	return (theStr.substring(sPos+lengthOfDelim,ePos));
+  var theStr = '' + theStr1;
+  var lengthOfDelim = delim.length;
+  sPos = -lengthOfDelim;
+  if (index < 1) {
+    index = 1;
+  }
+  for (a = 1; a < index; a++) {
+    sPos = theStr.indexOf(delim, sPos + lengthOfDelim);
+    if (sPos == -1) {
+      return null;
+    }
+  }
+  ePos = theStr.indexOf(delim, sPos + lengthOfDelim);
+  if (ePos == -1) {
+    ePos = theStr.length;
+  }
+  return (theStr.substring(sPos + lengthOfDelim, ePos));
 }
+
 function evalFunc_getTimestamp(timeObj) {
-	return Date.parse(timeObj)/1000;
+  return Date.parse(timeObj) / 1000;
 }
 
 // Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server
 function evalFunc_convertClientTimestampToUTC(timestamp, timeonly) {
-	var timeObj = new Date(timestamp*1000);
-	timeObj.setTime((timestamp - timeObj.getTimezoneOffset()*60)*1000);
-	if (timeonly) {
-		// only seconds since midnight
-		return this.getTime(timeObj);
-	} else	{
-		// seconds since the "unix-epoch"
-		return this.getTimestamp(timeObj);
-	}
+  var timeObj = new Date(timestamp * 1000);
+  timeObj.setTime((timestamp - timeObj.getTimezoneOffset() * 60) * 1000);
+  if (timeonly) {
+    // only seconds since midnight
+    return this.getTime(timeObj);
+  } else {
+    // seconds since the "unix-epoch"
+    return this.getTimestamp(timeObj);
+  }
 }
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
index cbf9c07eb443..72ec8b48f4ba 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
@@ -18,1235 +18,1235 @@
  */
 
 var inline = {
-	classVisible: 'panel-visible',
-	classCollapsed: 'panel-collapsed',
-	structureSeparator: '-',
-	flexFormSeparator: '---',
-	flexFormSubstitute: ':',
-	noTitleString: (TYPO3.lang ? TYPO3.lang['FormEngine.noRecordTitle'] : '[No title]'),
-	lockedAjaxMethod: {},
-	sourcesLoaded: {},
-	data: {},
-	isLoading: false,
-
-	addToDataArray: function (object) {
-		$.each(object, function (key, value) {
-			if (!inline.data[key]) {
-				inline.data[key] = {};
-			}
-			$.extend(inline.data[key], value);
-		});
-	},
-	toggleEvent: function (event) {
-		var $triggerElement = $(event.target);
-		if ($triggerElement.parents('.t3js-formengine-irre-control').length == 1) {
-			return;
-		}
-
-		var $recordHeader = $triggerElement.closest('.panel-heading');
-		inline.expandCollapseRecord(
-			$recordHeader.attr('id').replace(/_header$/, ''),
-			$recordHeader.attr('data-expandSingle')
-		);
-	},
-	expandCollapseRecord: function (objectId, expandSingle) {
-		var currentUid = this.parseObjectId('none', objectId, 1);
-		var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
-		var escapedObjectId = this.escapeObjectId(objectId);
-
-		var $currentObject = $('#' + escapedObjectId + '_div');
-		// if content is not loaded yet, get it now from server
-		if (inline.isLoading) {
-			return false;
-		} else if ($('#' + escapedObjectId + '_fields').length > 0 && $('#' + escapedObjectId + '_fields').html().substr(0, 16) === '<!--notloaded-->') {
-			inline.isLoading = true;
-			var headerIdentifier = '#' + escapedObjectId + '_header';
-			// add loading-indicator
-			require(['nprogress'], function (NProgress) {
-				inline.progress = NProgress;
-				inline.progress.configure({parent: headerIdentifier, showSpinner: false});
-				inline.progress.start();
-			});
-			return this.getRecordDetails(objectId);
-		}
-
-		var isCollapsed = $currentObject.hasClass(this.classCollapsed);
-		var collapse = [];
-		var expand = [];
-
-		// if only a single record should be visibly for that set of records
-		// and the record clicked itself is no visible, collapse all others
-		if (expandSingle && $currentObject.hasClass(this.classCollapsed)) {
-			collapse = this.collapseAllRecords(objectId, objectPrefix, currentUid);
-		}
-
-		inline.toggleElement(objectId);
-
-		if (this.isNewRecord(objectId)) {
-			this.updateExpandedCollapsedStateLocally(objectId, isCollapsed);
-		} else if (isCollapsed) {
-			expand.push(currentUid);
-		} else if (!isCollapsed) {
-			collapse.push(currentUid);
-		}
-
-		this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(','));
-
-		return false;
-	},
-
-	toggleElement: function (objectId) {
-		var escapedObjectId = this.escapeObjectId(objectId);
-		var $jQueryObject = $('#' + escapedObjectId + '_div');
-
-		if ($jQueryObject.hasClass(this.classCollapsed)) {
-			$jQueryObject.removeClass(this.classCollapsed).addClass(this.classVisible);
-			$jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-collapsed').removeClass('t3-icon-irre-collapsed').addClass('t3-icon-irre-expanded');
-		} else {
-			$jQueryObject.removeClass(this.classVisible).addClass(this.classCollapsed);
-			$jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-expanded').addClass('t3-icon-irre-collapsed').removeClass('t3-icon-irre-expanded');
-		}
-	},
-	collapseAllRecords: function (objectId, objectPrefix, callingUid) {
-		// get the form field, where all records are stored
-		var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true);
-		var formObj = document.getElementsByName(objectName);
-		var collapse = [];
-
-		if (formObj.length) {
-			// the uid of the calling object (last part in objectId)
-			var recObjectId = '', escapedRecordObjectId;
-
-			var records = this.trimExplode(',', formObj[0].value);
-			for (var i = 0; i < records.length; i++) {
-				recObjectId = objectPrefix + this.structureSeparator + records[i];
-				escapedRecordObjectId = this.escapeObjectId(recObjectId);
-
-				var $recordEntry = $('#' + escapedRecordObjectId + '_div');
-				if (records[i] != callingUid && $recordEntry.hasClass(this.classVisible)) {
-					$recordEntry.removeClass(this.classVisible).addClass(this.classCollapsed);
-					if (this.isNewRecord(recObjectId)) {
-						this.updateExpandedCollapsedStateLocally(recObjectId, 0);
-					} else {
-						collapse.push(records[i]);
-					}
-				}
-			}
-		}
-
-		return collapse;
-	},
-
-	updateExpandedCollapsedStateLocally: function (objectId, value) {
-		var ucName = 'uc[inlineView]' + this.parseObjectId('parts', objectId, 3, 2, true);
-		var ucFormObj = document.getElementsByName(ucName);
-		if (ucFormObj.length) {
-			ucFormObj[0].value = value;
-		}
-	},
-
-	getRecordDetails: function (objectId) {
-		var context = this.getContext(this.parseObjectId('full', objectId, 0, 1));
-		inline.makeAjaxCall('details', [objectId], true, context);
-		return false;
-	},
-
-	createNewRecord: function (objectId, recordUid) {
-		if (this.isBelowMax(objectId)) {
-			var context = this.getContext(objectId);
-			if (recordUid) {
-				objectId += this.structureSeparator + recordUid;
-			}
-			this.makeAjaxCall('create', [objectId], true, context);
-		} else {
-			var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectId].max);
-			var matches = objectId.match(/^(data-\d+-.*?-\d+-.*?)-(.*?)$/);
-			var title = '';
-			if (matches) {
-				title = $('#' + matches[1] + '_records').data('title');
-			}
-			top.TYPO3.Notification.error(title, message, 5);
-		}
-		return false;
-	},
-
-	synchronizeLocalizeRecords: function (objectId, type) {
-		var context = this.getContext(objectId);
-		this.makeAjaxCall('synchronizelocalize', [objectId, type], true, context);
-		return false;
-	},
-
-	setExpandedCollapsedState: function (objectId, expand, collapse) {
-		var context = this.getContext(objectId);
-		this.makeAjaxCall('expandcollapse', [objectId, expand, collapse], false, context);
-	},
-
-	makeAjaxCall: function (method, params, lock, context) {
-		var url = '', urlParams = '', options = {};
-		if (method && params && params.length && this.lockAjaxMethod(method, lock)) {
-			url = TYPO3.settings.ajaxUrls['record_inline_' + method];
-			urlParams = '';
-			for (var i = 0; i < params.length; i++) {
-				urlParams += '&ajax[' + i + ']=' + encodeURIComponent(params[i]);
-			}
-			if (context) {
-				urlParams += '&ajax[context]=' + encodeURIComponent(JSON.stringify(context));
-			}
-			options = {
-				type: 'POST',
-				data: urlParams,
-				success: function (data, message, jqXHR) {
-					inline.isLoading = false;
-					inline.processAjaxResponse(method, jqXHR);
-					if (inline.progress) {
-						inline.progress.done();
-					}
-				},
-				error: function (jqXHR) {
-					inline.isLoading = false;
-					inline.showAjaxFailure(method, jqXHR);
-					if (inline.progress) {
-						inline.progress.done();
-					}
-				}
-			};
-
-			$.ajax(url, options);
-		}
-	},
-
-	lockAjaxMethod: function (method, lock) {
-		if (!lock || !inline.lockedAjaxMethod[method]) {
-			inline.lockedAjaxMethod[method] = true;
-			return true;
-		} else {
-			return false;
-		}
-	},
-
-	unlockAjaxMethod: function (method) {
-		inline.lockedAjaxMethod[method] = false;
-	},
-
-	processAjaxResponse: function (method, xhr, json) {
-		var processedCount = 0, sourcesWaiting = [];
-		if (!json && xhr) {
-			json = xhr.responseJSON;
-		}
-		if (json.hasErrors) {
-			$.each(json.messages, function(position, message) {
-				top.TYPO3.Notification.error(message.title, message.message);
-			});
-		}
-		// If there are elements the should be added to the <HEAD> tag (e.g. for RTEhtmlarea):
-		if (json.stylesheetFiles) {
-			$.each(json.stylesheetFiles, function (index, stylesheetFile) {
-				if (!stylesheetFile) {
-					return;
-				}
-				var element = document.createElement('link');
-				element['rel'] = 'stylesheet';
-				element['type'] = 'text/css';
-				element['href'] = stylesheetFile;
-				$('head').get(0).appendChild(element);
-				processedCount++;
-				delete(json.stylesheetFiles[index]);
-			});
-		}
-		if (processedCount) {
-			window.setTimeout(function () {
-				inline.reprocessAjaxResponse(method, json, sourcesWaiting);
-			}, 40);
-		} else {
-			if (method) {
-				inline.unlockAjaxMethod(method);
-			}
-			if (json.scriptCall && json.scriptCall.length > 0) {
-				$.each(json.scriptCall, function (index, value) {
-					eval(value);
-				});
-			}
-			TYPO3.FormEngine.reinitialize();
-			TYPO3.FormEngine.Validation.initializeInputFields();
-			TYPO3.FormEngine.Validation.validate();
-		}
-	},
-
-	// Check if dynamically added scripts are loaded and restart inline.processAjaxResponse():
-	reprocessAjaxResponse: function (method, json, sourcesWaiting) {
-		var sourcesLoaded = true;
-		if (sourcesWaiting && sourcesWaiting.length) {
-			$.each(sourcesWaiting, function (index, source) {
-				if (!inline.sourcesLoaded[source]) {
-					sourcesLoaded = false;
-					return false;
-				}
-			});
-		}
-		if (sourcesLoaded) {
-			$.each(sourcesWaiting, function (index, source) {
-				delete(inline.sourcesLoaded[source]);
-			});
-			window.setTimeout(function () {
-				inline.processAjaxResponse(method, null, json);
-			}, 80);
-		} else {
-			window.setTimeout(function () {
-				inline.reprocessAjaxResponse(method, json, sourcesWaiting);
-			}, 40);
-		}
-	},
-
-	sourceLoadedHandler: function (element) {
-		if (element && element.src) {
-			inline.sourcesLoaded[element.src] = true;
-		}
-	},
-
-	showAjaxFailure: function (method, xhr) {
-		inline.unlockAjaxMethod(method);
-		top.TYPO3.Notification.error('Error ' + xhr.status, xhr.statusText, 0);
-	},
-
-	// foreign_selector: used by selector box (type='select')
-	importNewRecord: function (objectId) {
-		var $selector = $('#' + this.escapeObjectId(objectId) + '_selector');
-		var selectedIndex = $selector.prop('selectedIndex');
-		if (selectedIndex != -1) {
-			var context = this.getContext(objectId);
-			var selectedValue = $selector.val();
-			if (!this.data.unique || !this.data.unique[objectId]) {
-				$selector.find('option').eq(selectedIndex).prop('selected', false);
-			}
-			this.makeAjaxCall('create', [objectId, selectedValue], true, context);
-		}
-		return false;
-	},
-
-	// foreign_selector: used by element browser (type='group/db')
-	importElement: function (objectId, table, uid) {
-		var context = this.getContext(objectId);
-		inline.makeAjaxCall('create', [objectId, uid], true, context);
-	},
-
-	importElementMultiple: function (objectId, table, uidArray, type) {
-		$.each(uidArray, function (index, uid) {
-			inline.delayedImportElement(objectId, table, uid, type);
-		});
-	},
-	delayedImportElement: function (objectId, table, uid, type) {
-		if (inline.lockedAjaxMethod['create'] == true) {
-			window.setTimeout("inline.delayedImportElement('" + objectId + "','" + table + "'," + uid + ", null );",
-				300);
-		} else {
-			inline.importElement(objectId, table, uid, type);
-		}
-	},
-	// Check uniqueness for element browser:
-	checkUniqueElement: function (objectId, table, uid) {
-		if (this.checkUniqueUsed(objectId, uid, table)) {
-			return {passed: false, message: 'There is already a relation to the selected element!'};
-		} else {
-			return {passed: true};
-		}
-	},
-
-	// Checks if a record was used and should be unique:
-	checkUniqueUsed: function (objectId, uid, table) {
-		if (!this.data.unique || !this.data.unique[objectId]) {
-			return false;
-		}
-
-		var unique = this.data.unique[objectId];
-		var values = this.getValuesFromHashMap(unique.used);
-
-		// for select: only the uid is stored
-		if (unique['type'] == 'select') {
-			if (values.indexOf(uid) != -1) {
-				return true;
-			}
-
-			// for group/db: table and uid is stored in an assoc array
-		} else if (unique.type == 'groupdb') {
-			for (var i = values.length - 1; i >= 0; i--) {
-				// if the pair table:uid is already used:
-				if (values[i].table == table && values[i].uid == uid) {
-					return true;
-				}
-			}
-		}
-
-		return false;
-	},
-
-	setUniqueElement: function (objectId, table, uid, type, elName) {
-		var recordUid = this.parseFormElementName('none', elName, 1, 1);
-		this.setUnique(objectId, recordUid, uid);
-	},
-
-	getValuesFromHashMap: function (hashMap) {
-		return $.map(hashMap, function (value, key) {
-			return value;
-		});
-	},
-
-	// Remove all select items already used
-	// from a newly retrieved/expanded record
-	removeUsed: function (objectId, recordUid) {
-		if (!this.data.unique || !this.data.unique[objectId]) {
-			return;
-		}
-
-		var unique = this.data.unique[objectId];
-		if (unique.type != 'select') {
-			return;
-		}
-
-		var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']');
-		var values = this.getValuesFromHashMap(unique.used);
-		if (recordObj.length) {
-			if (recordObj[0].hasOwnProperty('options')) {
-				var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value;
-				for (var i = 0; i < values.length; i++) {
-					if (values[i] != selectedValue) {
-						var $recordObject = $(recordObj[0]);
-						this.removeSelectOption($recordObject, values[i]);
-					}
-				}
-			}
-		}
-	},
-	// this function is applied to a newly inserted record by AJAX
-	// it removes the used select items, that should be unique
-	setUnique: function (objectId, recordUid, selectedValue) {
-		if (!this.data.unique || !this.data.unique[objectId]) {
-			return;
-		}
-		var $selector = $('#' + this.escapeObjectId(objectId) + '_selector');
-
-		var unique = this.data.unique[objectId];
-		if (unique.type == 'select') {
-			if (!(unique.selector && unique.max == -1)) {
-				var formName = 'data' + this.parseObjectId('parts', objectId, 3, 1, true);
-				var formObj = document.getElementsByName(formName);
-				var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']');
-				var values = this.getValuesFromHashMap(unique.used);
-				if ($selector.length) {
-					// remove all items from the new select-item which are already used in other children
-					if (recordObj.length) {
-						var $recordObject = $(recordObj[0]);
-						for (var i = 0; i < values.length; i++) {
-							this.removeSelectOption($recordObject, values[i]);
-						}
-						// set the selected item automatically to the first of the remaining items if no selector is used
-						if (!unique.selector) {
-							selectedValue = recordObj[0].options[0].value;
-							recordObj[0].options[0].selected = true;
-							this.updateUnique(recordObj[0], objectId, formName, recordUid);
-							this.handleChangedField(recordObj[0], objectId + '[' + recordUid + ']');
-						}
-					}
-					for (var i = 0; i < values.length; i++) {
-						this.removeSelectOption($selector, values[i]);
-					}
-					if (typeof this.data.unique[objectId].used.length != 'undefined') {
-						this.data.unique[objectId].used = {};
-					}
-					this.data.unique[objectId].used[recordUid] = selectedValue;
-				}
-				// remove the newly used item from each select-field of the child records
-				if (formObj.length && selectedValue) {
-					var records = this.trimExplode(',', formObj[0].value);
-					for (var i = 0; i < records.length; i++) {
-						recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
-						if (recordObj.length && records[i] != recordUid) {
-							var $recordObject = $(recordObj[0]);
-							this.removeSelectOption($recordObject, selectedValue);
-						}
-					}
-				}
-			}
-		} else if (unique.type == 'groupdb') {
-			// add the new record to the used items:
-			this.data.unique[objectId].used[recordUid] = {'table': unique.elTable, 'uid': selectedValue};
-		}
-
-		// remove used items from a selector-box
-		if (unique.selector == 'select' && selectedValue) {
-			this.removeSelectOption($selector, selectedValue);
-			this.data.unique[objectId]['used'][recordUid] = selectedValue;
-		}
-	},
-
-	domAddNewRecord: function (method, insertObjectId, objectPrefix, htmlData) {
-		var $insertObject = $('#' + this.escapeObjectId(insertObjectId));
-		if (this.isBelowMax(objectPrefix)) {
-			if (method == 'bottom') {
-				$insertObject.append(htmlData);
-			} else if (method == 'after') {
-				$insertObject.after(htmlData);
-			}
-		} else {
-			var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectPrefix].max);
-			var title = $insertObject.data('title');
-			top.TYPO3.Notification.error(title, message);
-		}
-	},
-
-	domAddRecordDetails: function (objectId, objectPrefix, expandSingle, htmlData) {
-		var hiddenValue, formObj, valueObj;
-		var escapeObjectId = this.escapeObjectId(objectId);
-		var $objectDiv = $('#' + escapeObjectId + '_fields');
-		if ($objectDiv.length == 0 || $objectDiv.html().substr(0, 16) !== '<!--notloaded-->') {
-			return;
-		}
-
-		var elName = this.parseObjectId('full', objectId, 2, 0, true);
-
-		var $formObj = $('[data-formengine-input-name="' + elName + '[hidden]"]');
-		var $valueObj = $('[name="' + elName + '[hidden]"]');
-
-		// It might be the case that a child record
-		// cannot be hidden at all (no hidden field)
-		if ($formObj.length && $valueObj.length) {
-			hiddenValue = $formObj[0].checked;
-			$formObj.first().remove();
-			$valueObj.first().remove();
-		}
-
-		// Update DOM
-		$objectDiv.html(htmlData);
-
-		formObj = document.querySelector('[data-formengine-input-name="' + elName + '[hidden]"]');
-		valueObj = document.getElementsByName(elName + '[hidden]');
-
-		// Set the hidden value again
-		if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) {
-			valueObj[0].value = hiddenValue ? 1 : 0;
-			formObj.checked = hiddenValue;
-		}
-
-		// now that the content is loaded, set the expandState
-		this.expandCollapseRecord(objectId, expandSingle);
-	},
-
-	changeSorting: function (objectId, direction) {
-		var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true);
-		var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
-		var formObj = document.getElementsByName(objectName);
-
-		if (!formObj.length) {
-			return false;
-		}
-
-		// the uid of the calling object (last part in objectId)
-		var callingUid = this.parseObjectId('none', objectId, 1);
-		var records = this.trimExplode(',', formObj[0].value);
-		var current = records.indexOf(callingUid);
-		var changed = false;
-
-		// move up
-		if (direction > 0 && current > 0) {
-			records[current] = records[current - 1];
-			records[current - 1] = callingUid;
-			changed = true;
-
-		// move down
-		} else if (direction < 0 && current < records.length - 1) {
-			records[current] = records[current + 1];
-			records[current + 1] = callingUid;
-			changed = true;
-		}
-
-		if (changed) {
-			formObj[0].value = records.join(',');
-			var cAdj = direction > 0 ? 1 : 0; // adjustment
-			var objectIdPrefix = '#' + this.escapeObjectId(objectPrefix) + this.structureSeparator;
-			$(objectIdPrefix + records[current - cAdj] + '_div').insertBefore(
-				$(objectIdPrefix + records[current + 1 - cAdj] + '_div')
-			);
-			this.redrawSortingButtons(objectPrefix, records);
-		}
-
-		return false;
-	},
-
-	dragAndDropSorting: function (element) {
-		var objectId = element.getAttribute('id').replace(/_records$/, '');
-		var objectName = 'data' + inline.parseObjectId('parts', objectId, 3, 0, true);
-		var formObj = document.getElementsByName(objectName);
-		var $element = $(element);
-
-		if (!formObj.length) {
-			return;
-		}
-
-		var checked = [];
-		var order = [];
-		$element.find('.sortableHandle').each(function (i, e) {
-			order.push($(e).data('id').toString());
-		});
-		var records = this.trimExplode(',', formObj[0].value);
-
-		// check if ordered uid is really part of the records
-		// virtually deleted items might still be there but ordering shouldn't saved at all on them
-		for (var i = 0; i < order.length; i++) {
-			if (records.indexOf(order[i]) != -1) {
-				checked.push(order[i]);
-			}
-		}
-
-		formObj[0].value = checked.join(',');
-
-		if (inline.data.config && inline.data.config[objectId]) {
-			var table = inline.data.config[objectId].table;
-			inline.redrawSortingButtons(objectId + inline.structureSeparator + table, checked);
-		}
-	},
-
-	createDragAndDropSorting: function (objectId) {
-		require(['jquery', 'jquery-ui/sortable'], function ($) {
-			var $sortingContainer = $('#' + inline.escapeObjectId(objectId));
-
-			if ($sortingContainer.hasClass('ui-sortable')) {
-				$sortingContainer.sortable('enable');
-				return;
-			}
-
-			$sortingContainer.sortable({
-				containment: 'parent',
-				handle: '.sortableHandle',
-				zIndex: '4000',
-				axis: 'y',
-				tolerance: 'pointer',
-				stop: function () {
-					inline.dragAndDropSorting($sortingContainer[0]);
-				}
-			});
-		});
-	},
-
-	destroyDragAndDropSorting: function (objectId) {
-		require(['jquery', 'jquery-ui/sortable'], function ($) {
-			var $sortingContainer = $('#' + inline.escapeObjectId(objectId));
-			if (!$sortingContainer.hasClass('ui-sortable')) {
-				return;
-			}
-			$sortingContainer.sortable('disable');
-		});
-	},
-
-	redrawSortingButtons: function (objectPrefix, records) {
-		var i, $headerObj, sortUp, sortDown, partOfHeaderObj, iconIdentifier;
-
-		// if no records were passed, fetch them from form field
-		if (typeof records == 'undefined') {
-			records = [];
-			var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
-			var formObj = document.getElementsByName(objectName);
-			if (formObj.length) {
-				records = this.trimExplode(',', formObj[0].value);
-			}
-		}
-		partOfHeaderObj = this.escapeObjectId(objectPrefix) + this.structureSeparator;
-		require(['TYPO3/CMS/Backend/Icons'], function(Icons) {
-			for (i = 0; i < records.length; i++) {
-				if (!records[i].length) {
-					continue;
-				}
-				$headerObj = $('#' + partOfHeaderObj + records[i] + '_header');
-				sortUp = $headerObj.find('.sortingUp');
-				iconIdentifier = 'actions-move-up';
-				if (sortUp) {
-					if (i == 0) {
-						sortUp.addClass('disabled');
-						iconIdentifier = 'empty-empty';
-					} else {
-						sortUp.removeClass('disabled');
-					}
-					Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) {
-						sortUp.find('.t3js-icon').replaceWith(markup);
-					});
-				}
-				sortDown = $headerObj.find('.sortingDown');
-				iconIdentifier = 'actions-move-down';
-				if (sortDown) {
-					if (i == records.length - 1) {
-						sortDown.addClass('disabled');
-						iconIdentifier = 'empty-empty';
-					} else {
-						sortDown.removeClass('disabled');
-					}
-					Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) {
-						sortDown.find('.t3js-icon').replaceWith(markup);
-					});
-				}
-			}
-		});
-	},
-
-	memorizeAddRecord: function (objectPrefix, newUid, afterUid, selectedValue) {
-		if (this.isBelowMax(objectPrefix)) {
-			var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
-			var formObj = document.getElementsByName(objectName);
-
-			if (formObj.length) {
-				var records = [];
-				if (formObj[0].value.length) {
-					records = this.trimExplode(',', formObj[0].value);
-				}
-
-				if (afterUid) {
-					var newRecords = [];
-					for (var i = 0; i < records.length; i++) {
-						if (records[i].length) {
-							newRecords.push(records[i]);
-						}
-						if (afterUid == records[i]) {
-							newRecords.push(newUid);
-						}
-					}
-					records = newRecords;
-				} else {
-					records.push(newUid);
-				}
-				formObj[0].value = records.join(',');
-			}
-
-			this.redrawSortingButtons(objectPrefix, records);
-
-			if (this.data.unique && this.data.unique[objectPrefix]) {
-				this.setUnique(objectPrefix, newUid, selectedValue);
-			}
-		}
-
-		// if we reached the maximum of possible records after this action, hide the new buttons
-		if (!this.isBelowMax(objectPrefix)) {
-			var objectParent = this.parseObjectId('full', objectPrefix, 0, 1);
-			var md5 = this.getObjectMD5(objectParent);
-			this.hideElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.hideElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.hideElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.hideElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent);
-			this.hideElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item');
-		}
-
-		if (TBE_EDITOR) {
-			TBE_EDITOR.fieldChanged_fName(objectName, formObj);
-		}
-	},
-
-	memorizeRemoveRecord: function (objectName, removeUid) {
-		var formObj = document.getElementsByName(objectName);
-		if (formObj.length) {
-			var parts = [],
-				indexOfRemoveUid = -1;
-			if (formObj[0].value.length) {
-				parts = this.trimExplode(',', formObj[0].value);
-				indexOfRemoveUid = parts.indexOf(removeUid);
-				if (indexOfRemoveUid !== -1) {
-					delete parts[indexOfRemoveUid];
-				}
-				formObj[0].value = parts.join(',');
-				if (TBE_EDITOR) {
-					TBE_EDITOR.fieldChanged_fName(objectName, formObj);
-				}
-				return parts.length;
-			}
-		}
-		return false;
-	},
-
-	updateUnique: function (srcElement, objectPrefix, formName, recordUid) {
-		if (!this.data.unique || !this.data.unique[objectPrefix]) {
-			return;
-		}
-
-		var unique = this.data.unique[objectPrefix];
-		var oldValue = unique.used[recordUid];
-
-		if (unique.selector == 'select') {
-			var selector = $(objectPrefix + '_selector');
-			this.removeSelectOption(selector, srcElement.value);
-			if (typeof oldValue != 'undefined') {
-				this.readdSelectOption(selector, oldValue, unique);
-			}
-		}
-
-		if (unique.selector && unique.max == -1) {
-			return;
-		}
-
-		var formObj = document.getElementsByName(formName);
-		if (!unique || !formObj.length) {
-			return;
-		}
-
-		var records = this.trimExplode(',', formObj[0].value);
-		var recordObj;
-		for (var i = 0; i < records.length; i++) {
-			recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
-			if (recordObj.length && recordObj[0] != srcElement) {
-				var $recordObject = $(recordObj[0]);
-				this.removeSelectOption($recordObject, srcElement.value);
-				if (typeof oldValue != 'undefined') {
-					this.readdSelectOption($recordObject, oldValue, unique);
-				}
-			}
-		}
-		this.data.unique[objectPrefix].used[recordUid] = srcElement.value;
-	},
-
-	revertUnique: function (objectPrefix, elName, recordUid) {
-		if (!this.data.unique || !this.data.unique[objectPrefix]) {
-			return;
-		}
-
-		var unique = this.data.unique[objectPrefix];
-		var fieldObj = elName ? document.getElementsByName(elName + '[' + unique.field + ']') : null;
-
-		if (unique.type == 'select') {
-			if (!fieldObj || !fieldObj.length) {
-				return;
-			}
-
-			delete(this.data.unique[objectPrefix].used[recordUid]);
-
-			if (unique.selector == 'select') {
-				if (!isNaN(fieldObj[0].value)) {
-					var $selector = $('#' + this.escapeObjectId(objectPrefix) + '_selector');
-					this.readdSelectOption($selector, fieldObj[0].value, unique);
-				}
-			}
-
-			if (unique.selector && unique.max == -1) {
-				return;
-			}
-
-			var formName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
-			var formObj = document.getElementsByName(formName);
-			if (!formObj.length) {
-				return;
-			}
-
-			var records = this.trimExplode(',', formObj[0].value);
-			var recordObj;
-			// walk through all inline records on that level and get the select field
-			for (var i = 0; i < records.length; i++) {
-				recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
-				if (recordObj.length) {
-					var $recordObject = $(recordObj[0]);
-					this.readdSelectOption($recordObject, fieldObj[0].value, unique);
-				}
-			}
-		} else if (unique.type == 'groupdb') {
-			delete(this.data.unique[objectPrefix].used[recordUid])
-		}
-	},
-
-	enableDisableRecord: function (objectIdentifier, fieldName) {
-		var elName = this.parseObjectId('full', objectIdentifier, 2, 0, true) + '[' + fieldName + ']';
-		var formObj = document.querySelector('[data-formengine-input-name="' + elName + '"]');
-		var valueObj = document.getElementsByName(elName);
-		var escapedObjectIdentifier = this.escapeObjectId(objectIdentifier);
-		var $container = $('#' + escapedObjectIdentifier + '_div');
-		var $icon = $container.find('.t3js-' + escapedObjectIdentifier + '_disabled .t3js-icon');
-
-		// It might be the case that there's no hidden field
-		if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) {
-			formObj.click();
-			valueObj[0].value = formObj.checked ? 1 : 0;
-			TBE_EDITOR.fieldChanged_fName(elName, elName);
-		}
-
-		if ($icon.length) {
-			require(['TYPO3/CMS/Backend/Icons'], function(Icons) {
-				var hiddenClass = 't3-form-field-container-inline-hidden',
-					isHidden = $container.hasClass(hiddenClass),
-					toggleIcon;
-
-				if (isHidden) {
-					toggleIcon = 'actions-edit-hide';
-					$container.removeClass(hiddenClass);
-				} else {
-					toggleIcon = 'actions-edit-unhide';
-					$container.addClass(hiddenClass);
-				}
-
-				Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(markup) {
-					$icon.replaceWith(markup);
-				});
-			});
-		}
-
-		return false;
-	},
-
-	deleteRecord: function (objectId, options) {
-		var i, j, inlineRecords, records, childObjectId, childTable;
-		var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
-		var elName = this.parseObjectId('full', objectId, 2, 0, true);
-		var shortName = this.parseObjectId('parts', objectId, 2, 0, true);
-		var recordUid = this.parseObjectId('none', objectId, 1);
-		var beforeDeleteIsBelowMax = this.isBelowMax(objectPrefix);
-
-		// revert the unique settings if available
-		this.revertUnique(objectPrefix, elName, recordUid);
-
-		// Remove from TBE_EDITOR (required fields, required range, etc.):
-		if (TBE_EDITOR && TBE_EDITOR.removeElement) {
-			var removeStack = [];
-			// Iterate over all child records:
-			inlineRecords = $('.inlineRecord', '#' + objectId + '_div');
-			// Remove nested child records from TBE_EDITOR required/range checks:
-			for (i = inlineRecords.length - 1; i >= 0; i--) {
-				if (inlineRecords.get(i).value.length) {
-					records = this.trimExplode(',', inlineRecords.get(i).value);
-					childObjectId = this.data.map[inlineRecords.get(i).name];
-					childTable = this.data.config[childObjectId].table;
-					for (j = records.length - 1; j >= 0; j--) {
-						removeStack.push('data[' + childTable + '][' + records[j] + ']');
-					}
-				}
-			}
-			removeStack.push('data' + shortName);
-			TBE_EDITOR.removeElementArray(removeStack);
-		}
-
-		// Mark this container as deleted
-		$('#' + this.escapeObjectId(objectId) + '_div')
-			.addClass('inlineIsDeletedRecord')
-			.addClass('t3js-inline-record-deleted');
-
-		// If the record is new and was never saved before, just remove it from DOM:
-		if (this.isNewRecord(objectId) || options && options.forceDirectRemoval) {
-			this.fadeAndRemove(objectId + '_div');
-			// If the record already exists in storage, mark it to be deleted on clicking the save button:
-		} else {
-			document.getElementsByName('cmd' + shortName + '[delete]')[0].disabled = false;
-			$('#' + this.escapeObjectId(objectId) + '_div').fadeOut(200);
-		}
-
-		var recordCount = this.memorizeRemoveRecord(
-			'data' + this.parseObjectId('parts', objectId, 3, 2, true),
-			recordUid
-		);
-
-		if (recordCount <= 1) {
-			this.destroyDragAndDropSorting(this.parseObjectId('full', objectId, 0, 2) + '_records');
-		}
-		this.redrawSortingButtons(objectPrefix);
-
-		// if the NEW-button was hidden and now we can add again new children, show the button
-		if (!beforeDeleteIsBelowMax && this.isBelowMax(objectPrefix)) {
-			var objectParent = this.parseObjectId('full', objectPrefix, 0, 1);
-			var md5 = this.getObjectMD5(objectParent);
-			this.showElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.showElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.showElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent);
-			this.showElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent);
-			this.showElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item');
-		}
-		TYPO3.FormEngine.Validation.validate();
-		return false;
-	},
-
-	parseFormElementName: function (wrap, formElementName, rightCount, skipRight) {
-		var idParts = this.splitFormElementName(formElementName);
-
-		if (!wrap) {
-			wrap = 'full';
-		}
-		if (!skipRight) {
-			skipRight = 0;
-		}
-
-		var elParts = [];
-		for (var i = 0; i < skipRight; i++) {
-			idParts.pop();
-		}
-
-		if (rightCount > 0) {
-			for (var i = 0; i < rightCount; i++) {
-				elParts.unshift(idParts.pop());
-			}
-		} else {
-			for (var i = 0; i < -rightCount; i++) {
-				idParts.shift();
-			}
-			elParts = idParts;
-		}
-
-		return this.constructFormElementName(wrap, elParts);
-	},
-
-	splitFormElementName: function (formElementName) {
-		// remove left and right side "data[...|...]" -> '...|...'
-		formElementName = formElementName.substr(0, formElementName.lastIndexOf(']')).substr(formElementName.indexOf('[') + 1);
-		return formElementName.split('][');
-	},
-
-	splitObjectId: function (objectId) {
-		objectId = objectId.substr(objectId.indexOf(this.structureSeparator) + 1);
-		objectId = objectId.split(this.flexFormSeparator).join(this.flexFormSubstitute);
-		return objectId.split(this.structureSeparator);
-	},
-
-	constructFormElementName: function (wrap, parts) {
-		var elReturn;
-
-		if (wrap == 'full') {
-			elReturn = 'data[' + parts.join('][') + ']';
-			elReturn = elReturn.split(this.flexFormSubstitute).join('][');
-		} else if (wrap == 'parts') {
-			elReturn = '[' + parts.join('][') + ']';
-			elReturn = elReturn.split(this.flexFormSubstitute).join('][');
-		} else if (wrap == 'none') {
-			elReturn = parts.length > 1 ? parts : parts.join('');
-		}
-
-		return elReturn;
-	},
-
-	constructObjectId: function (wrap, parts) {
-		var elReturn;
-
-		if (wrap == 'full') {
-			elReturn = 'data' + this.structureSeparator + parts.join(this.structureSeparator);
-			elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
-		} else if (wrap == 'parts') {
-			elReturn = this.structureSeparator + parts.join(this.structureSeparator);
-			elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
-		} else if (wrap == 'none') {
-			elReturn = parts.length > 1 ? parts : parts.join('');
-		}
-
-		return elReturn;
-	},
-
-	parseObjectId: function (wrap, objectId, rightCount, skipRight, returnAsFormElementName) {
-		var idParts = this.splitObjectId(objectId);
-
-		if (!wrap) {
-			wrap = 'full';
-		}
-		if (!skipRight) {
-			skipRight = 0;
-		}
-
-		var elParts = [];
-		for (var i = 0; i < skipRight; i++) {
-			idParts.pop();
-		}
-
-		if (rightCount > 0) {
-			for (var i = 0; i < rightCount; i++) {
-				elParts.unshift(idParts.pop());
-			}
-		} else {
-			for (var i = 0; i < -rightCount; i++) {
-				idParts.shift();
-			}
-			elParts = idParts;
-		}
-
-		return returnAsFormElementName
-			? this.constructFormElementName(wrap, elParts)
-			: this.constructObjectId(wrap, elParts);
-	},
-
-	handleChangedField: function (formField, objectId) {
-		var formObj;
-		if (typeof formField == 'object') {
-			formObj = formField;
-		} else {
-			formObj = document.getElementsByName(formField);
-			if (formObj.length) {
-				formObj = formObj[0];
-			}
-		}
-
-		if (formObj != undefined) {
-			var value;
-			if (formObj.nodeName == 'SELECT') {
-				value = formObj.options[formObj.selectedIndex].text;
-			} else {
-				value = formObj.value;
-			}
-			$('#' + this.escapeObjectId(objectId) + '_label').text(value.length ? value : this.noTitleString);
-		}
-		return true;
-	},
-
-	arrayAssocCount: function (object) {
-		var count = 0;
-		if (typeof object.length != 'undefined') {
-			count = object.length;
-		} else {
-			for (var i in object) {
-				count++;
-			}
-		}
-		return count;
-	},
-
-	isBelowMax: function (objectPrefix) {
-		var isBelowMax = true;
-		var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
-		var formObj = document.getElementsByName(objectName);
-
-		if (this.data.config && this.data.config[objectPrefix] && formObj.length) {
-			var recordCount = formObj[0].value ? this.trimExplode(',', formObj[0].value).length : 0;
-			if (recordCount >= this.data.config[objectPrefix].max) {
-				isBelowMax = false;
-			}
-		}
-		if (isBelowMax && this.data.unique && this.data.unique[objectPrefix]) {
-			var unique = this.data.unique[objectPrefix];
-			if (this.arrayAssocCount(unique.used) >= unique.max && unique.max >= 0) {
-				isBelowMax = false;
-			}
-		}
-		return isBelowMax;
-	},
-
-	getOptionsHash: function ($selectObj) {
-		var optionsHash = {};
-		$selectObj.find('option').each(function (i, option) {
-			optionsHash[option.value] = i;
-		});
-		return optionsHash;
-	},
-
-	removeSelectOption: function ($selectObj, value) {
-		var optionsHash = this.getOptionsHash($selectObj);
-		if (optionsHash[value] != undefined) {
-			$selectObj.find('option').eq(optionsHash[value]).remove();
-		}
-	},
-
-	readdSelectOption: function ($selectObj, value, unique) {
-		if (!$selectObj.length) {
-			return;
-		}
-
-		var index = null;
-		var optionsHash = this.getOptionsHash($selectObj);
-
-		for (var possibleValue in unique.possible) {
-			if (possibleValue == value) {
-				break;
-			}
-			if (optionsHash[possibleValue] != undefined) {
-				index = optionsHash[possibleValue];
-			}
-		}
-
-		if (index == null) {
-			index = 0;
-		} else if (index < $selectObj.find('option').length) {
-			index++;
-		}
-		// recreate the <option> tag
-		var readdOption = document.createElement('option');
-		readdOption.text = unique.possible[value];
-		readdOption.value = value;
-		// add the <option> at the right position
-		// I didn't find a possibility to add an option to a predefined position
-		// with help of an index in jQuery. So we realized it the "old" style
-		var selectObj = $selectObj.get(0);
-		selectObj.add(readdOption, document.all ? index : selectObj.options[index]);
-	},
-
-	hideElementsWithClassName: function (selector, parentElement) {
-		$('#' + this.escapeObjectId(parentElement)).find(selector).fadeOut(200);
-	},
-
-	showElementsWithClassName: function (selector, parentElement) {
-		$('#' + this.escapeObjectId(parentElement)).find(selector).fadeIn(200);
-	},
-
-	// sets the opacity to 0.2 and then fades in to opacity 1
-	fadeOutFadeIn: function (objectId) {
-		$('#' + this.escapeObjectId(objectId)).css({opacity: 0.2}).fadeTo(200, 1, 'linear');
-	},
-
-	isNewRecord: function (objectId) {
-		var $selector = $('#' + this.escapeObjectId(objectId) + '_div');
-		return $selector.length && $selector.hasClass('inlineIsNewRecord');
-	},
-
-	// Find and fix nested of inline and tab levels if a new element was created dynamically (it doesn't know about its nesting):
-	findContinuedNestedLevel: function (nested, objectId) {
-		if (this.data.nested && this.data.nested[objectId]) {
-			// Remove the first element from the new nested stack, it's just a hint:
-			nested.shift();
-			nested = this.data.nested[objectId].concat(nested);
-		}
-		return nested;
-	},
-
-	getObjectMD5: function (objectPrefix) {
-		var md5 = false;
-		if (this.data.config && this.data.config[objectPrefix] && this.data.config[objectPrefix].md5) {
-			md5 = this.data.config[objectPrefix].md5;
-		}
-		return md5
-	},
-
-	fadeAndRemove: function (element) {
-		$('#' + this.escapeObjectId(element)).fadeOut(200, function () {
-			$(this).remove();
-			TYPO3.FormEngine.Validation.validate();
-		});
-	},
-
-	getContext: function (objectId) {
-		var result = null;
-
-		if (objectId !== '' && typeof this.data.config[objectId] !== 'undefined' && typeof this.data.config[objectId].context !== 'undefined') {
-			result = this.data.config[objectId].context;
-		}
-
-		return result;
-	},
-
-	/**
-	 * Escapes object identifiers to be used in jQuery.
-	 *
-	 * @param {String} objectId
-	 * @return string
-	 */
-	escapeObjectId: function (objectId) {
-		var escapedObjectId;
-		escapedObjectId = objectId.replace(/:/g, '\\:');
-		escapedObjectId = escapedObjectId.replace(/\./g, '\\.');
-		return escapedObjectId;
-	},
-
-	/**
-	 * Helper function to get clean trimmed array from comma list
-	 *
-	 * @param {String} delimiter
-	 * @param {String} string
-	 * @returns {Array}
-	 */
-	trimExplode: function(delimiter, string) {
-		var result = [];
-		var items = string.split(delimiter);
-		for (var i=0; i<items.length; i++) {
-			var item = items[i].trim();
-			if (item.length > 0) {
-				result.push(item);
-			}
-		}
-		return result;
-	}
+  classVisible: 'panel-visible',
+  classCollapsed: 'panel-collapsed',
+  structureSeparator: '-',
+  flexFormSeparator: '---',
+  flexFormSubstitute: ':',
+  noTitleString: (TYPO3.lang ? TYPO3.lang['FormEngine.noRecordTitle'] : '[No title]'),
+  lockedAjaxMethod: {},
+  sourcesLoaded: {},
+  data: {},
+  isLoading: false,
+
+  addToDataArray: function(object) {
+    $.each(object, function(key, value) {
+      if (!inline.data[key]) {
+        inline.data[key] = {};
+      }
+      $.extend(inline.data[key], value);
+    });
+  },
+  toggleEvent: function(event) {
+    var $triggerElement = $(event.target);
+    if ($triggerElement.parents('.t3js-formengine-irre-control').length == 1) {
+      return;
+    }
+
+    var $recordHeader = $triggerElement.closest('.panel-heading');
+    inline.expandCollapseRecord(
+      $recordHeader.attr('id').replace(/_header$/, ''),
+      $recordHeader.attr('data-expandSingle')
+    );
+  },
+  expandCollapseRecord: function(objectId, expandSingle) {
+    var currentUid = this.parseObjectId('none', objectId, 1);
+    var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
+    var escapedObjectId = this.escapeObjectId(objectId);
+
+    var $currentObject = $('#' + escapedObjectId + '_div');
+    // if content is not loaded yet, get it now from server
+    if (inline.isLoading) {
+      return false;
+    } else if ($('#' + escapedObjectId + '_fields').length > 0 && $('#' + escapedObjectId + '_fields').html().substr(0, 16) === '<!--notloaded-->') {
+      inline.isLoading = true;
+      var headerIdentifier = '#' + escapedObjectId + '_header';
+      // add loading-indicator
+      require(['nprogress'], function(NProgress) {
+        inline.progress = NProgress;
+        inline.progress.configure({parent: headerIdentifier, showSpinner: false});
+        inline.progress.start();
+      });
+      return this.getRecordDetails(objectId);
+    }
+
+    var isCollapsed = $currentObject.hasClass(this.classCollapsed);
+    var collapse = [];
+    var expand = [];
+
+    // if only a single record should be visibly for that set of records
+    // and the record clicked itself is no visible, collapse all others
+    if (expandSingle && $currentObject.hasClass(this.classCollapsed)) {
+      collapse = this.collapseAllRecords(objectId, objectPrefix, currentUid);
+    }
+
+    inline.toggleElement(objectId);
+
+    if (this.isNewRecord(objectId)) {
+      this.updateExpandedCollapsedStateLocally(objectId, isCollapsed);
+    } else if (isCollapsed) {
+      expand.push(currentUid);
+    } else if (!isCollapsed) {
+      collapse.push(currentUid);
+    }
+
+    this.setExpandedCollapsedState(objectId, expand.join(','), collapse.join(','));
+
+    return false;
+  },
+
+  toggleElement: function(objectId) {
+    var escapedObjectId = this.escapeObjectId(objectId);
+    var $jQueryObject = $('#' + escapedObjectId + '_div');
+
+    if ($jQueryObject.hasClass(this.classCollapsed)) {
+      $jQueryObject.removeClass(this.classCollapsed).addClass(this.classVisible);
+      $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-collapsed').removeClass('t3-icon-irre-collapsed').addClass('t3-icon-irre-expanded');
+    } else {
+      $jQueryObject.removeClass(this.classVisible).addClass(this.classCollapsed);
+      $jQueryObject.find('#' + escapedObjectId + '_header .t3-icon-irre-expanded').addClass('t3-icon-irre-collapsed').removeClass('t3-icon-irre-expanded');
+    }
+  },
+  collapseAllRecords: function(objectId, objectPrefix, callingUid) {
+    // get the form field, where all records are stored
+    var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true);
+    var formObj = document.getElementsByName(objectName);
+    var collapse = [];
+
+    if (formObj.length) {
+      // the uid of the calling object (last part in objectId)
+      var recObjectId = '', escapedRecordObjectId;
+
+      var records = this.trimExplode(',', formObj[0].value);
+      for (var i = 0; i < records.length; i++) {
+        recObjectId = objectPrefix + this.structureSeparator + records[i];
+        escapedRecordObjectId = this.escapeObjectId(recObjectId);
+
+        var $recordEntry = $('#' + escapedRecordObjectId + '_div');
+        if (records[i] != callingUid && $recordEntry.hasClass(this.classVisible)) {
+          $recordEntry.removeClass(this.classVisible).addClass(this.classCollapsed);
+          if (this.isNewRecord(recObjectId)) {
+            this.updateExpandedCollapsedStateLocally(recObjectId, 0);
+          } else {
+            collapse.push(records[i]);
+          }
+        }
+      }
+    }
+
+    return collapse;
+  },
+
+  updateExpandedCollapsedStateLocally: function(objectId, value) {
+    var ucName = 'uc[inlineView]' + this.parseObjectId('parts', objectId, 3, 2, true);
+    var ucFormObj = document.getElementsByName(ucName);
+    if (ucFormObj.length) {
+      ucFormObj[0].value = value;
+    }
+  },
+
+  getRecordDetails: function(objectId) {
+    var context = this.getContext(this.parseObjectId('full', objectId, 0, 1));
+    inline.makeAjaxCall('details', [objectId], true, context);
+    return false;
+  },
+
+  createNewRecord: function(objectId, recordUid) {
+    if (this.isBelowMax(objectId)) {
+      var context = this.getContext(objectId);
+      if (recordUid) {
+        objectId += this.structureSeparator + recordUid;
+      }
+      this.makeAjaxCall('create', [objectId], true, context);
+    } else {
+      var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectId].max);
+      var matches = objectId.match(/^(data-\d+-.*?-\d+-.*?)-(.*?)$/);
+      var title = '';
+      if (matches) {
+        title = $('#' + matches[1] + '_records').data('title');
+      }
+      top.TYPO3.Notification.error(title, message, 5);
+    }
+    return false;
+  },
+
+  synchronizeLocalizeRecords: function(objectId, type) {
+    var context = this.getContext(objectId);
+    this.makeAjaxCall('synchronizelocalize', [objectId, type], true, context);
+    return false;
+  },
+
+  setExpandedCollapsedState: function(objectId, expand, collapse) {
+    var context = this.getContext(objectId);
+    this.makeAjaxCall('expandcollapse', [objectId, expand, collapse], false, context);
+  },
+
+  makeAjaxCall: function(method, params, lock, context) {
+    var url = '', urlParams = '', options = {};
+    if (method && params && params.length && this.lockAjaxMethod(method, lock)) {
+      url = TYPO3.settings.ajaxUrls['record_inline_' + method];
+      urlParams = '';
+      for (var i = 0; i < params.length; i++) {
+        urlParams += '&ajax[' + i + ']=' + encodeURIComponent(params[i]);
+      }
+      if (context) {
+        urlParams += '&ajax[context]=' + encodeURIComponent(JSON.stringify(context));
+      }
+      options = {
+        type: 'POST',
+        data: urlParams,
+        success: function(data, message, jqXHR) {
+          inline.isLoading = false;
+          inline.processAjaxResponse(method, jqXHR);
+          if (inline.progress) {
+            inline.progress.done();
+          }
+        },
+        error: function(jqXHR) {
+          inline.isLoading = false;
+          inline.showAjaxFailure(method, jqXHR);
+          if (inline.progress) {
+            inline.progress.done();
+          }
+        }
+      };
+
+      $.ajax(url, options);
+    }
+  },
+
+  lockAjaxMethod: function(method, lock) {
+    if (!lock || !inline.lockedAjaxMethod[method]) {
+      inline.lockedAjaxMethod[method] = true;
+      return true;
+    } else {
+      return false;
+    }
+  },
+
+  unlockAjaxMethod: function(method) {
+    inline.lockedAjaxMethod[method] = false;
+  },
+
+  processAjaxResponse: function(method, xhr, json) {
+    var processedCount = 0, sourcesWaiting = [];
+    if (!json && xhr) {
+      json = xhr.responseJSON;
+    }
+    if (json.hasErrors) {
+      $.each(json.messages, function(position, message) {
+        top.TYPO3.Notification.error(message.title, message.message);
+      });
+    }
+    // If there are elements the should be added to the <HEAD> tag (e.g. for RTEhtmlarea):
+    if (json.stylesheetFiles) {
+      $.each(json.stylesheetFiles, function(index, stylesheetFile) {
+        if (!stylesheetFile) {
+          return;
+        }
+        var element = document.createElement('link');
+        element['rel'] = 'stylesheet';
+        element['type'] = 'text/css';
+        element['href'] = stylesheetFile;
+        $('head').get(0).appendChild(element);
+        processedCount++;
+        delete(json.stylesheetFiles[index]);
+      });
+    }
+    if (processedCount) {
+      window.setTimeout(function() {
+        inline.reprocessAjaxResponse(method, json, sourcesWaiting);
+      }, 40);
+    } else {
+      if (method) {
+        inline.unlockAjaxMethod(method);
+      }
+      if (json.scriptCall && json.scriptCall.length > 0) {
+        $.each(json.scriptCall, function(index, value) {
+          eval(value);
+        });
+      }
+      TYPO3.FormEngine.reinitialize();
+      TYPO3.FormEngine.Validation.initializeInputFields();
+      TYPO3.FormEngine.Validation.validate();
+    }
+  },
+
+  // Check if dynamically added scripts are loaded and restart inline.processAjaxResponse():
+  reprocessAjaxResponse: function(method, json, sourcesWaiting) {
+    var sourcesLoaded = true;
+    if (sourcesWaiting && sourcesWaiting.length) {
+      $.each(sourcesWaiting, function(index, source) {
+        if (!inline.sourcesLoaded[source]) {
+          sourcesLoaded = false;
+          return false;
+        }
+      });
+    }
+    if (sourcesLoaded) {
+      $.each(sourcesWaiting, function(index, source) {
+        delete(inline.sourcesLoaded[source]);
+      });
+      window.setTimeout(function() {
+        inline.processAjaxResponse(method, null, json);
+      }, 80);
+    } else {
+      window.setTimeout(function() {
+        inline.reprocessAjaxResponse(method, json, sourcesWaiting);
+      }, 40);
+    }
+  },
+
+  sourceLoadedHandler: function(element) {
+    if (element && element.src) {
+      inline.sourcesLoaded[element.src] = true;
+    }
+  },
+
+  showAjaxFailure: function(method, xhr) {
+    inline.unlockAjaxMethod(method);
+    top.TYPO3.Notification.error('Error ' + xhr.status, xhr.statusText, 0);
+  },
+
+  // foreign_selector: used by selector box (type='select')
+  importNewRecord: function(objectId) {
+    var $selector = $('#' + this.escapeObjectId(objectId) + '_selector');
+    var selectedIndex = $selector.prop('selectedIndex');
+    if (selectedIndex != -1) {
+      var context = this.getContext(objectId);
+      var selectedValue = $selector.val();
+      if (!this.data.unique || !this.data.unique[objectId]) {
+        $selector.find('option').eq(selectedIndex).prop('selected', false);
+      }
+      this.makeAjaxCall('create', [objectId, selectedValue], true, context);
+    }
+    return false;
+  },
+
+  // foreign_selector: used by element browser (type='group/db')
+  importElement: function(objectId, table, uid) {
+    var context = this.getContext(objectId);
+    inline.makeAjaxCall('create', [objectId, uid], true, context);
+  },
+
+  importElementMultiple: function(objectId, table, uidArray, type) {
+    $.each(uidArray, function(index, uid) {
+      inline.delayedImportElement(objectId, table, uid, type);
+    });
+  },
+  delayedImportElement: function(objectId, table, uid, type) {
+    if (inline.lockedAjaxMethod['create'] == true) {
+      window.setTimeout("inline.delayedImportElement('" + objectId + "','" + table + "'," + uid + ", null );",
+        300);
+    } else {
+      inline.importElement(objectId, table, uid, type);
+    }
+  },
+  // Check uniqueness for element browser:
+  checkUniqueElement: function(objectId, table, uid) {
+    if (this.checkUniqueUsed(objectId, uid, table)) {
+      return {passed: false, message: 'There is already a relation to the selected element!'};
+    } else {
+      return {passed: true};
+    }
+  },
+
+  // Checks if a record was used and should be unique:
+  checkUniqueUsed: function(objectId, uid, table) {
+    if (!this.data.unique || !this.data.unique[objectId]) {
+      return false;
+    }
+
+    var unique = this.data.unique[objectId];
+    var values = this.getValuesFromHashMap(unique.used);
+
+    // for select: only the uid is stored
+    if (unique['type'] == 'select') {
+      if (values.indexOf(uid) != -1) {
+        return true;
+      }
+
+      // for group/db: table and uid is stored in an assoc array
+    } else if (unique.type == 'groupdb') {
+      for (var i = values.length - 1; i >= 0; i--) {
+        // if the pair table:uid is already used:
+        if (values[i].table == table && values[i].uid == uid) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  },
+
+  setUniqueElement: function(objectId, table, uid, type, elName) {
+    var recordUid = this.parseFormElementName('none', elName, 1, 1);
+    this.setUnique(objectId, recordUid, uid);
+  },
+
+  getValuesFromHashMap: function(hashMap) {
+    return $.map(hashMap, function(value, key) {
+      return value;
+    });
+  },
+
+  // Remove all select items already used
+  // from a newly retrieved/expanded record
+  removeUsed: function(objectId, recordUid) {
+    if (!this.data.unique || !this.data.unique[objectId]) {
+      return;
+    }
+
+    var unique = this.data.unique[objectId];
+    if (unique.type != 'select') {
+      return;
+    }
+
+    var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']');
+    var values = this.getValuesFromHashMap(unique.used);
+    if (recordObj.length) {
+      if (recordObj[0].hasOwnProperty('options')) {
+        var selectedValue = recordObj[0].options[recordObj[0].selectedIndex].value;
+        for (var i = 0; i < values.length; i++) {
+          if (values[i] != selectedValue) {
+            var $recordObject = $(recordObj[0]);
+            this.removeSelectOption($recordObject, values[i]);
+          }
+        }
+      }
+    }
+  },
+  // this function is applied to a newly inserted record by AJAX
+  // it removes the used select items, that should be unique
+  setUnique: function(objectId, recordUid, selectedValue) {
+    if (!this.data.unique || !this.data.unique[objectId]) {
+      return;
+    }
+    var $selector = $('#' + this.escapeObjectId(objectId) + '_selector');
+
+    var unique = this.data.unique[objectId];
+    if (unique.type == 'select') {
+      if (!(unique.selector && unique.max == -1)) {
+        var formName = 'data' + this.parseObjectId('parts', objectId, 3, 1, true);
+        var formObj = document.getElementsByName(formName);
+        var recordObj = document.getElementsByName('data[' + unique.table + '][' + recordUid + '][' + unique.field + ']');
+        var values = this.getValuesFromHashMap(unique.used);
+        if ($selector.length) {
+          // remove all items from the new select-item which are already used in other children
+          if (recordObj.length) {
+            var $recordObject = $(recordObj[0]);
+            for (var i = 0; i < values.length; i++) {
+              this.removeSelectOption($recordObject, values[i]);
+            }
+            // set the selected item automatically to the first of the remaining items if no selector is used
+            if (!unique.selector) {
+              selectedValue = recordObj[0].options[0].value;
+              recordObj[0].options[0].selected = true;
+              this.updateUnique(recordObj[0], objectId, formName, recordUid);
+              this.handleChangedField(recordObj[0], objectId + '[' + recordUid + ']');
+            }
+          }
+          for (var i = 0; i < values.length; i++) {
+            this.removeSelectOption($selector, values[i]);
+          }
+          if (typeof this.data.unique[objectId].used.length != 'undefined') {
+            this.data.unique[objectId].used = {};
+          }
+          this.data.unique[objectId].used[recordUid] = selectedValue;
+        }
+        // remove the newly used item from each select-field of the child records
+        if (formObj.length && selectedValue) {
+          var records = this.trimExplode(',', formObj[0].value);
+          for (var i = 0; i < records.length; i++) {
+            recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
+            if (recordObj.length && records[i] != recordUid) {
+              var $recordObject = $(recordObj[0]);
+              this.removeSelectOption($recordObject, selectedValue);
+            }
+          }
+        }
+      }
+    } else if (unique.type == 'groupdb') {
+      // add the new record to the used items:
+      this.data.unique[objectId].used[recordUid] = {'table': unique.elTable, 'uid': selectedValue};
+    }
+
+    // remove used items from a selector-box
+    if (unique.selector == 'select' && selectedValue) {
+      this.removeSelectOption($selector, selectedValue);
+      this.data.unique[objectId]['used'][recordUid] = selectedValue;
+    }
+  },
+
+  domAddNewRecord: function(method, insertObjectId, objectPrefix, htmlData) {
+    var $insertObject = $('#' + this.escapeObjectId(insertObjectId));
+    if (this.isBelowMax(objectPrefix)) {
+      if (method == 'bottom') {
+        $insertObject.append(htmlData);
+      } else if (method == 'after') {
+        $insertObject.after(htmlData);
+      }
+    } else {
+      var message = TYPO3.lang['FormEngine.maxItemsAllowed'].replace('{0}', this.data.config[objectPrefix].max);
+      var title = $insertObject.data('title');
+      top.TYPO3.Notification.error(title, message);
+    }
+  },
+
+  domAddRecordDetails: function(objectId, objectPrefix, expandSingle, htmlData) {
+    var hiddenValue, formObj, valueObj;
+    var escapeObjectId = this.escapeObjectId(objectId);
+    var $objectDiv = $('#' + escapeObjectId + '_fields');
+    if ($objectDiv.length == 0 || $objectDiv.html().substr(0, 16) !== '<!--notloaded-->') {
+      return;
+    }
+
+    var elName = this.parseObjectId('full', objectId, 2, 0, true);
+
+    var $formObj = $('[data-formengine-input-name="' + elName + '[hidden]"]');
+    var $valueObj = $('[name="' + elName + '[hidden]"]');
+
+    // It might be the case that a child record
+    // cannot be hidden at all (no hidden field)
+    if ($formObj.length && $valueObj.length) {
+      hiddenValue = $formObj[0].checked;
+      $formObj.first().remove();
+      $valueObj.first().remove();
+    }
+
+    // Update DOM
+    $objectDiv.html(htmlData);
+
+    formObj = document.querySelector('[data-formengine-input-name="' + elName + '[hidden]"]');
+    valueObj = document.getElementsByName(elName + '[hidden]');
+
+    // Set the hidden value again
+    if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) {
+      valueObj[0].value = hiddenValue ? 1 : 0;
+      formObj.checked = hiddenValue;
+    }
+
+    // now that the content is loaded, set the expandState
+    this.expandCollapseRecord(objectId, expandSingle);
+  },
+
+  changeSorting: function(objectId, direction) {
+    var objectName = 'data' + this.parseObjectId('parts', objectId, 3, 2, true);
+    var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
+    var formObj = document.getElementsByName(objectName);
+
+    if (!formObj.length) {
+      return false;
+    }
+
+    // the uid of the calling object (last part in objectId)
+    var callingUid = this.parseObjectId('none', objectId, 1);
+    var records = this.trimExplode(',', formObj[0].value);
+    var current = records.indexOf(callingUid);
+    var changed = false;
+
+    // move up
+    if (direction > 0 && current > 0) {
+      records[current] = records[current - 1];
+      records[current - 1] = callingUid;
+      changed = true;
+
+      // move down
+    } else if (direction < 0 && current < records.length - 1) {
+      records[current] = records[current + 1];
+      records[current + 1] = callingUid;
+      changed = true;
+    }
+
+    if (changed) {
+      formObj[0].value = records.join(',');
+      var cAdj = direction > 0 ? 1 : 0; // adjustment
+      var objectIdPrefix = '#' + this.escapeObjectId(objectPrefix) + this.structureSeparator;
+      $(objectIdPrefix + records[current - cAdj] + '_div').insertBefore(
+        $(objectIdPrefix + records[current + 1 - cAdj] + '_div')
+      );
+      this.redrawSortingButtons(objectPrefix, records);
+    }
+
+    return false;
+  },
+
+  dragAndDropSorting: function(element) {
+    var objectId = element.getAttribute('id').replace(/_records$/, '');
+    var objectName = 'data' + inline.parseObjectId('parts', objectId, 3, 0, true);
+    var formObj = document.getElementsByName(objectName);
+    var $element = $(element);
+
+    if (!formObj.length) {
+      return;
+    }
+
+    var checked = [];
+    var order = [];
+    $element.find('.sortableHandle').each(function(i, e) {
+      order.push($(e).data('id').toString());
+    });
+    var records = this.trimExplode(',', formObj[0].value);
+
+    // check if ordered uid is really part of the records
+    // virtually deleted items might still be there but ordering shouldn't saved at all on them
+    for (var i = 0; i < order.length; i++) {
+      if (records.indexOf(order[i]) != -1) {
+        checked.push(order[i]);
+      }
+    }
+
+    formObj[0].value = checked.join(',');
+
+    if (inline.data.config && inline.data.config[objectId]) {
+      var table = inline.data.config[objectId].table;
+      inline.redrawSortingButtons(objectId + inline.structureSeparator + table, checked);
+    }
+  },
+
+  createDragAndDropSorting: function(objectId) {
+    require(['jquery', 'jquery-ui/sortable'], function($) {
+      var $sortingContainer = $('#' + inline.escapeObjectId(objectId));
+
+      if ($sortingContainer.hasClass('ui-sortable')) {
+        $sortingContainer.sortable('enable');
+        return;
+      }
+
+      $sortingContainer.sortable({
+        containment: 'parent',
+        handle: '.sortableHandle',
+        zIndex: '4000',
+        axis: 'y',
+        tolerance: 'pointer',
+        stop: function() {
+          inline.dragAndDropSorting($sortingContainer[0]);
+        }
+      });
+    });
+  },
+
+  destroyDragAndDropSorting: function(objectId) {
+    require(['jquery', 'jquery-ui/sortable'], function($) {
+      var $sortingContainer = $('#' + inline.escapeObjectId(objectId));
+      if (!$sortingContainer.hasClass('ui-sortable')) {
+        return;
+      }
+      $sortingContainer.sortable('disable');
+    });
+  },
+
+  redrawSortingButtons: function(objectPrefix, records) {
+    var i, $headerObj, sortUp, sortDown, partOfHeaderObj, iconIdentifier;
+
+    // if no records were passed, fetch them from form field
+    if (typeof records == 'undefined') {
+      records = [];
+      var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
+      var formObj = document.getElementsByName(objectName);
+      if (formObj.length) {
+        records = this.trimExplode(',', formObj[0].value);
+      }
+    }
+    partOfHeaderObj = this.escapeObjectId(objectPrefix) + this.structureSeparator;
+    require(['TYPO3/CMS/Backend/Icons'], function(Icons) {
+      for (i = 0; i < records.length; i++) {
+        if (!records[i].length) {
+          continue;
+        }
+        $headerObj = $('#' + partOfHeaderObj + records[i] + '_header');
+        sortUp = $headerObj.find('.sortingUp');
+        iconIdentifier = 'actions-move-up';
+        if (sortUp) {
+          if (i == 0) {
+            sortUp.addClass('disabled');
+            iconIdentifier = 'empty-empty';
+          } else {
+            sortUp.removeClass('disabled');
+          }
+          Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) {
+            sortUp.find('.t3js-icon').replaceWith(markup);
+          });
+        }
+        sortDown = $headerObj.find('.sortingDown');
+        iconIdentifier = 'actions-move-down';
+        if (sortDown) {
+          if (i == records.length - 1) {
+            sortDown.addClass('disabled');
+            iconIdentifier = 'empty-empty';
+          } else {
+            sortDown.removeClass('disabled');
+          }
+          Icons.getIcon(iconIdentifier, Icons.sizes.small).done(function(markup) {
+            sortDown.find('.t3js-icon').replaceWith(markup);
+          });
+        }
+      }
+    });
+  },
+
+  memorizeAddRecord: function(objectPrefix, newUid, afterUid, selectedValue) {
+    if (this.isBelowMax(objectPrefix)) {
+      var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
+      var formObj = document.getElementsByName(objectName);
+
+      if (formObj.length) {
+        var records = [];
+        if (formObj[0].value.length) {
+          records = this.trimExplode(',', formObj[0].value);
+        }
+
+        if (afterUid) {
+          var newRecords = [];
+          for (var i = 0; i < records.length; i++) {
+            if (records[i].length) {
+              newRecords.push(records[i]);
+            }
+            if (afterUid == records[i]) {
+              newRecords.push(newUid);
+            }
+          }
+          records = newRecords;
+        } else {
+          records.push(newUid);
+        }
+        formObj[0].value = records.join(',');
+      }
+
+      this.redrawSortingButtons(objectPrefix, records);
+
+      if (this.data.unique && this.data.unique[objectPrefix]) {
+        this.setUnique(objectPrefix, newUid, selectedValue);
+      }
+    }
+
+    // if we reached the maximum of possible records after this action, hide the new buttons
+    if (!this.isBelowMax(objectPrefix)) {
+      var objectParent = this.parseObjectId('full', objectPrefix, 0, 1);
+      var md5 = this.getObjectMD5(objectParent);
+      this.hideElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.hideElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.hideElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.hideElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent);
+      this.hideElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item');
+    }
+
+    if (TBE_EDITOR) {
+      TBE_EDITOR.fieldChanged_fName(objectName, formObj);
+    }
+  },
+
+  memorizeRemoveRecord: function(objectName, removeUid) {
+    var formObj = document.getElementsByName(objectName);
+    if (formObj.length) {
+      var parts = [],
+        indexOfRemoveUid = -1;
+      if (formObj[0].value.length) {
+        parts = this.trimExplode(',', formObj[0].value);
+        indexOfRemoveUid = parts.indexOf(removeUid);
+        if (indexOfRemoveUid !== -1) {
+          delete parts[indexOfRemoveUid];
+        }
+        formObj[0].value = parts.join(',');
+        if (TBE_EDITOR) {
+          TBE_EDITOR.fieldChanged_fName(objectName, formObj);
+        }
+        return parts.length;
+      }
+    }
+    return false;
+  },
+
+  updateUnique: function(srcElement, objectPrefix, formName, recordUid) {
+    if (!this.data.unique || !this.data.unique[objectPrefix]) {
+      return;
+    }
+
+    var unique = this.data.unique[objectPrefix];
+    var oldValue = unique.used[recordUid];
+
+    if (unique.selector == 'select') {
+      var selector = $(objectPrefix + '_selector');
+      this.removeSelectOption(selector, srcElement.value);
+      if (typeof oldValue != 'undefined') {
+        this.readdSelectOption(selector, oldValue, unique);
+      }
+    }
+
+    if (unique.selector && unique.max == -1) {
+      return;
+    }
+
+    var formObj = document.getElementsByName(formName);
+    if (!unique || !formObj.length) {
+      return;
+    }
+
+    var records = this.trimExplode(',', formObj[0].value);
+    var recordObj;
+    for (var i = 0; i < records.length; i++) {
+      recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
+      if (recordObj.length && recordObj[0] != srcElement) {
+        var $recordObject = $(recordObj[0]);
+        this.removeSelectOption($recordObject, srcElement.value);
+        if (typeof oldValue != 'undefined') {
+          this.readdSelectOption($recordObject, oldValue, unique);
+        }
+      }
+    }
+    this.data.unique[objectPrefix].used[recordUid] = srcElement.value;
+  },
+
+  revertUnique: function(objectPrefix, elName, recordUid) {
+    if (!this.data.unique || !this.data.unique[objectPrefix]) {
+      return;
+    }
+
+    var unique = this.data.unique[objectPrefix];
+    var fieldObj = elName ? document.getElementsByName(elName + '[' + unique.field + ']') : null;
+
+    if (unique.type == 'select') {
+      if (!fieldObj || !fieldObj.length) {
+        return;
+      }
+
+      delete(this.data.unique[objectPrefix].used[recordUid]);
+
+      if (unique.selector == 'select') {
+        if (!isNaN(fieldObj[0].value)) {
+          var $selector = $('#' + this.escapeObjectId(objectPrefix) + '_selector');
+          this.readdSelectOption($selector, fieldObj[0].value, unique);
+        }
+      }
+
+      if (unique.selector && unique.max == -1) {
+        return;
+      }
+
+      var formName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
+      var formObj = document.getElementsByName(formName);
+      if (!formObj.length) {
+        return;
+      }
+
+      var records = this.trimExplode(',', formObj[0].value);
+      var recordObj;
+      // walk through all inline records on that level and get the select field
+      for (var i = 0; i < records.length; i++) {
+        recordObj = document.getElementsByName('data[' + unique.table + '][' + records[i] + '][' + unique.field + ']');
+        if (recordObj.length) {
+          var $recordObject = $(recordObj[0]);
+          this.readdSelectOption($recordObject, fieldObj[0].value, unique);
+        }
+      }
+    } else if (unique.type == 'groupdb') {
+      delete(this.data.unique[objectPrefix].used[recordUid])
+    }
+  },
+
+  enableDisableRecord: function(objectIdentifier, fieldName) {
+    var elName = this.parseObjectId('full', objectIdentifier, 2, 0, true) + '[' + fieldName + ']';
+    var formObj = document.querySelector('[data-formengine-input-name="' + elName + '"]');
+    var valueObj = document.getElementsByName(elName);
+    var escapedObjectIdentifier = this.escapeObjectId(objectIdentifier);
+    var $container = $('#' + escapedObjectIdentifier + '_div');
+    var $icon = $container.find('.t3js-' + escapedObjectIdentifier + '_disabled .t3js-icon');
+
+    // It might be the case that there's no hidden field
+    if (typeof formObj !== 'undefined' && formObj !== null && valueObj.length) {
+      formObj.click();
+      valueObj[0].value = formObj.checked ? 1 : 0;
+      TBE_EDITOR.fieldChanged_fName(elName, elName);
+    }
+
+    if ($icon.length) {
+      require(['TYPO3/CMS/Backend/Icons'], function(Icons) {
+        var hiddenClass = 't3-form-field-container-inline-hidden',
+          isHidden = $container.hasClass(hiddenClass),
+          toggleIcon;
+
+        if (isHidden) {
+          toggleIcon = 'actions-edit-hide';
+          $container.removeClass(hiddenClass);
+        } else {
+          toggleIcon = 'actions-edit-unhide';
+          $container.addClass(hiddenClass);
+        }
+
+        Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(markup) {
+          $icon.replaceWith(markup);
+        });
+      });
+    }
+
+    return false;
+  },
+
+  deleteRecord: function(objectId, options) {
+    var i, j, inlineRecords, records, childObjectId, childTable;
+    var objectPrefix = this.parseObjectId('full', objectId, 0, 1);
+    var elName = this.parseObjectId('full', objectId, 2, 0, true);
+    var shortName = this.parseObjectId('parts', objectId, 2, 0, true);
+    var recordUid = this.parseObjectId('none', objectId, 1);
+    var beforeDeleteIsBelowMax = this.isBelowMax(objectPrefix);
+
+    // revert the unique settings if available
+    this.revertUnique(objectPrefix, elName, recordUid);
+
+    // Remove from TBE_EDITOR (required fields, required range, etc.):
+    if (TBE_EDITOR && TBE_EDITOR.removeElement) {
+      var removeStack = [];
+      // Iterate over all child records:
+      inlineRecords = $('.inlineRecord', '#' + objectId + '_div');
+      // Remove nested child records from TBE_EDITOR required/range checks:
+      for (i = inlineRecords.length - 1; i >= 0; i--) {
+        if (inlineRecords.get(i).value.length) {
+          records = this.trimExplode(',', inlineRecords.get(i).value);
+          childObjectId = this.data.map[inlineRecords.get(i).name];
+          childTable = this.data.config[childObjectId].table;
+          for (j = records.length - 1; j >= 0; j--) {
+            removeStack.push('data[' + childTable + '][' + records[j] + ']');
+          }
+        }
+      }
+      removeStack.push('data' + shortName);
+      TBE_EDITOR.removeElementArray(removeStack);
+    }
+
+    // Mark this container as deleted
+    $('#' + this.escapeObjectId(objectId) + '_div')
+      .addClass('inlineIsDeletedRecord')
+      .addClass('t3js-inline-record-deleted');
+
+    // If the record is new and was never saved before, just remove it from DOM:
+    if (this.isNewRecord(objectId) || options && options.forceDirectRemoval) {
+      this.fadeAndRemove(objectId + '_div');
+      // If the record already exists in storage, mark it to be deleted on clicking the save button:
+    } else {
+      document.getElementsByName('cmd' + shortName + '[delete]')[0].disabled = false;
+      $('#' + this.escapeObjectId(objectId) + '_div').fadeOut(200);
+    }
+
+    var recordCount = this.memorizeRemoveRecord(
+      'data' + this.parseObjectId('parts', objectId, 3, 2, true),
+      recordUid
+    );
+
+    if (recordCount <= 1) {
+      this.destroyDragAndDropSorting(this.parseObjectId('full', objectId, 0, 2) + '_records');
+    }
+    this.redrawSortingButtons(objectPrefix);
+
+    // if the NEW-button was hidden and now we can add again new children, show the button
+    if (!beforeDeleteIsBelowMax && this.isBelowMax(objectPrefix)) {
+      var objectParent = this.parseObjectId('full', objectPrefix, 0, 1);
+      var md5 = this.getObjectMD5(objectParent);
+      this.showElementsWithClassName('.inlineNewButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.showElementsWithClassName('.inlineNewRelationButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.showElementsWithClassName('.inlineNewFileUploadButton' + (md5 ? '.' + md5 : ''), objectParent);
+      this.showElementsWithClassName('.t3js-online-media-add-btn' + (md5 ? '.' + md5 : ''), objectParent);
+      this.showElementsWithClassName('.inlineForeignSelector' + (md5 ? '.' + md5 : ''), 't3-form-field-item');
+    }
+    TYPO3.FormEngine.Validation.validate();
+    return false;
+  },
+
+  parseFormElementName: function(wrap, formElementName, rightCount, skipRight) {
+    var idParts = this.splitFormElementName(formElementName);
+
+    if (!wrap) {
+      wrap = 'full';
+    }
+    if (!skipRight) {
+      skipRight = 0;
+    }
+
+    var elParts = [];
+    for (var i = 0; i < skipRight; i++) {
+      idParts.pop();
+    }
+
+    if (rightCount > 0) {
+      for (var i = 0; i < rightCount; i++) {
+        elParts.unshift(idParts.pop());
+      }
+    } else {
+      for (var i = 0; i < -rightCount; i++) {
+        idParts.shift();
+      }
+      elParts = idParts;
+    }
+
+    return this.constructFormElementName(wrap, elParts);
+  },
+
+  splitFormElementName: function(formElementName) {
+    // remove left and right side "data[...|...]" -> '...|...'
+    formElementName = formElementName.substr(0, formElementName.lastIndexOf(']')).substr(formElementName.indexOf('[') + 1);
+    return formElementName.split('][');
+  },
+
+  splitObjectId: function(objectId) {
+    objectId = objectId.substr(objectId.indexOf(this.structureSeparator) + 1);
+    objectId = objectId.split(this.flexFormSeparator).join(this.flexFormSubstitute);
+    return objectId.split(this.structureSeparator);
+  },
+
+  constructFormElementName: function(wrap, parts) {
+    var elReturn;
+
+    if (wrap == 'full') {
+      elReturn = 'data[' + parts.join('][') + ']';
+      elReturn = elReturn.split(this.flexFormSubstitute).join('][');
+    } else if (wrap == 'parts') {
+      elReturn = '[' + parts.join('][') + ']';
+      elReturn = elReturn.split(this.flexFormSubstitute).join('][');
+    } else if (wrap == 'none') {
+      elReturn = parts.length > 1 ? parts : parts.join('');
+    }
+
+    return elReturn;
+  },
+
+  constructObjectId: function(wrap, parts) {
+    var elReturn;
+
+    if (wrap == 'full') {
+      elReturn = 'data' + this.structureSeparator + parts.join(this.structureSeparator);
+      elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
+    } else if (wrap == 'parts') {
+      elReturn = this.structureSeparator + parts.join(this.structureSeparator);
+      elReturn = elReturn.split(this.flexFormSubstitute).join(this.flexFormSeparator);
+    } else if (wrap == 'none') {
+      elReturn = parts.length > 1 ? parts : parts.join('');
+    }
+
+    return elReturn;
+  },
+
+  parseObjectId: function(wrap, objectId, rightCount, skipRight, returnAsFormElementName) {
+    var idParts = this.splitObjectId(objectId);
+
+    if (!wrap) {
+      wrap = 'full';
+    }
+    if (!skipRight) {
+      skipRight = 0;
+    }
+
+    var elParts = [];
+    for (var i = 0; i < skipRight; i++) {
+      idParts.pop();
+    }
+
+    if (rightCount > 0) {
+      for (var i = 0; i < rightCount; i++) {
+        elParts.unshift(idParts.pop());
+      }
+    } else {
+      for (var i = 0; i < -rightCount; i++) {
+        idParts.shift();
+      }
+      elParts = idParts;
+    }
+
+    return returnAsFormElementName
+      ? this.constructFormElementName(wrap, elParts)
+      : this.constructObjectId(wrap, elParts);
+  },
+
+  handleChangedField: function(formField, objectId) {
+    var formObj;
+    if (typeof formField == 'object') {
+      formObj = formField;
+    } else {
+      formObj = document.getElementsByName(formField);
+      if (formObj.length) {
+        formObj = formObj[0];
+      }
+    }
+
+    if (formObj != undefined) {
+      var value;
+      if (formObj.nodeName == 'SELECT') {
+        value = formObj.options[formObj.selectedIndex].text;
+      } else {
+        value = formObj.value;
+      }
+      $('#' + this.escapeObjectId(objectId) + '_label').text(value.length ? value : this.noTitleString);
+    }
+    return true;
+  },
+
+  arrayAssocCount: function(object) {
+    var count = 0;
+    if (typeof object.length != 'undefined') {
+      count = object.length;
+    } else {
+      for (var i in object) {
+        count++;
+      }
+    }
+    return count;
+  },
+
+  isBelowMax: function(objectPrefix) {
+    var isBelowMax = true;
+    var objectName = 'data' + this.parseObjectId('parts', objectPrefix, 3, 1, true);
+    var formObj = document.getElementsByName(objectName);
+
+    if (this.data.config && this.data.config[objectPrefix] && formObj.length) {
+      var recordCount = formObj[0].value ? this.trimExplode(',', formObj[0].value).length : 0;
+      if (recordCount >= this.data.config[objectPrefix].max) {
+        isBelowMax = false;
+      }
+    }
+    if (isBelowMax && this.data.unique && this.data.unique[objectPrefix]) {
+      var unique = this.data.unique[objectPrefix];
+      if (this.arrayAssocCount(unique.used) >= unique.max && unique.max >= 0) {
+        isBelowMax = false;
+      }
+    }
+    return isBelowMax;
+  },
+
+  getOptionsHash: function($selectObj) {
+    var optionsHash = {};
+    $selectObj.find('option').each(function(i, option) {
+      optionsHash[option.value] = i;
+    });
+    return optionsHash;
+  },
+
+  removeSelectOption: function($selectObj, value) {
+    var optionsHash = this.getOptionsHash($selectObj);
+    if (optionsHash[value] != undefined) {
+      $selectObj.find('option').eq(optionsHash[value]).remove();
+    }
+  },
+
+  readdSelectOption: function($selectObj, value, unique) {
+    if (!$selectObj.length) {
+      return;
+    }
+
+    var index = null;
+    var optionsHash = this.getOptionsHash($selectObj);
+
+    for (var possibleValue in unique.possible) {
+      if (possibleValue == value) {
+        break;
+      }
+      if (optionsHash[possibleValue] != undefined) {
+        index = optionsHash[possibleValue];
+      }
+    }
+
+    if (index == null) {
+      index = 0;
+    } else if (index < $selectObj.find('option').length) {
+      index++;
+    }
+    // recreate the <option> tag
+    var readdOption = document.createElement('option');
+    readdOption.text = unique.possible[value];
+    readdOption.value = value;
+    // add the <option> at the right position
+    // I didn't find a possibility to add an option to a predefined position
+    // with help of an index in jQuery. So we realized it the "old" style
+    var selectObj = $selectObj.get(0);
+    selectObj.add(readdOption, document.all ? index : selectObj.options[index]);
+  },
+
+  hideElementsWithClassName: function(selector, parentElement) {
+    $('#' + this.escapeObjectId(parentElement)).find(selector).fadeOut(200);
+  },
+
+  showElementsWithClassName: function(selector, parentElement) {
+    $('#' + this.escapeObjectId(parentElement)).find(selector).fadeIn(200);
+  },
+
+  // sets the opacity to 0.2 and then fades in to opacity 1
+  fadeOutFadeIn: function(objectId) {
+    $('#' + this.escapeObjectId(objectId)).css({opacity: 0.2}).fadeTo(200, 1, 'linear');
+  },
+
+  isNewRecord: function(objectId) {
+    var $selector = $('#' + this.escapeObjectId(objectId) + '_div');
+    return $selector.length && $selector.hasClass('inlineIsNewRecord');
+  },
+
+  // Find and fix nested of inline and tab levels if a new element was created dynamically (it doesn't know about its nesting):
+  findContinuedNestedLevel: function(nested, objectId) {
+    if (this.data.nested && this.data.nested[objectId]) {
+      // Remove the first element from the new nested stack, it's just a hint:
+      nested.shift();
+      nested = this.data.nested[objectId].concat(nested);
+    }
+    return nested;
+  },
+
+  getObjectMD5: function(objectPrefix) {
+    var md5 = false;
+    if (this.data.config && this.data.config[objectPrefix] && this.data.config[objectPrefix].md5) {
+      md5 = this.data.config[objectPrefix].md5;
+    }
+    return md5
+  },
+
+  fadeAndRemove: function(element) {
+    $('#' + this.escapeObjectId(element)).fadeOut(200, function() {
+      $(this).remove();
+      TYPO3.FormEngine.Validation.validate();
+    });
+  },
+
+  getContext: function(objectId) {
+    var result = null;
+
+    if (objectId !== '' && typeof this.data.config[objectId] !== 'undefined' && typeof this.data.config[objectId].context !== 'undefined') {
+      result = this.data.config[objectId].context;
+    }
+
+    return result;
+  },
+
+  /**
+   * Escapes object identifiers to be used in jQuery.
+   *
+   * @param {String} objectId
+   * @return string
+   */
+  escapeObjectId: function(objectId) {
+    var escapedObjectId;
+    escapedObjectId = objectId.replace(/:/g, '\\:');
+    escapedObjectId = escapedObjectId.replace(/\./g, '\\.');
+    return escapedObjectId;
+  },
+
+  /**
+   * Helper function to get clean trimmed array from comma list
+   *
+   * @param {String} delimiter
+   * @param {String} string
+   * @returns {Array}
+   */
+  trimExplode: function(delimiter, string) {
+    var result = [];
+    var items = string.split(delimiter);
+    for (var i = 0; i < items.length; i++) {
+      var item = items[i].trim();
+      if (item.length > 0) {
+        result.push(item);
+      }
+    }
+    return result;
+  }
 };
 
 /*]]>*/
-$(function () {
-	$(document).on('click', '[data-toggle="formengine-inline"]', function(event) {
-		inline.toggleEvent(event);
-	});
+$(function() {
+  $(document).on('click', '[data-toggle="formengine-inline"]', function(event) {
+    inline.toggleEvent(event);
+  });
 });
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js
index 2de9c5eb3be1..9a138b1311da 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tbe_editor.js
@@ -16,229 +16,240 @@
  */
 
 var TBE_EDITOR = {
-	/* Example:
-		elements: {
-			'data-parentPid-table-uid': {
-				'field': {
-					'range':		[0, 100],
-					'rangeImg':		'',
-					'required':		true,
-					'requiredImg':	''
-				}
-			}
-		},
-	*/
+  /* Example:
+    elements: {
+      'data-parentPid-table-uid': {
+        'field': {
+          'range':		[0, 100],
+          'rangeImg':		'',
+          'required':		true,
+          'requiredImg':	''
+        }
+      }
+    },
+  */
 
-	elements: {},
-	nested: {'field':{}, 'level':{}},
-	ignoreElements: [],
-	actionChecks: { submit:	[] },
-	customEvalFunctions: {},
+  elements: {},
+  nested: {'field': {}, 'level': {}},
+  ignoreElements: [],
+  actionChecks: {submit: []},
+  customEvalFunctions: {},
 
-	formname: 'editform',
-	isChanged: 0,
+  formname: 'editform',
+  isChanged: 0,
 
-	doSaveFieldName: 0,
+  doSaveFieldName: 0,
 
-	labels: {},
+  labels: {},
 
-	clearBeforeSettingFormValueFromBrowseWin: [],
+  clearBeforeSettingFormValueFromBrowseWin: [],
 
-	// Handling of data structures:
-	removeElement: function(record) {
-		if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) {
-			delete(TBE_EDITOR.elements[record]);
-		}
-	},
-	removeElementArray: function(removeStack) {
-		if (removeStack && removeStack.length) {
-			TBE_EDITOR.ignoreElements = removeStack;
-			for (var i=removeStack.length; i>=0; i--) {
-				TBE_EDITOR.removeElement(removeStack[i]);
-			}
-			TBE_EDITOR.ignoreElements = [];
-		}
-	},
-	getElement: function(record, field, type) {
-		var result = null;
-		var element;
+  // Handling of data structures:
+  removeElement: function(record) {
+    if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) {
+      delete(TBE_EDITOR.elements[record]);
+    }
+  },
+  removeElementArray: function(removeStack) {
+    if (removeStack && removeStack.length) {
+      TBE_EDITOR.ignoreElements = removeStack;
+      for (var i = removeStack.length; i >= 0; i--) {
+        TBE_EDITOR.removeElement(removeStack[i]);
+      }
+      TBE_EDITOR.ignoreElements = [];
+    }
+  },
+  getElement: function(record, field, type) {
+    var result = null;
+    var element;
 
-		if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) {
-			element = TBE_EDITOR.elements[record][field];
-			if (type) {
-				if (element[type]) result = element;
-			} else {
-				result = element;
-			}
-		}
+    if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) {
+      element = TBE_EDITOR.elements[record][field];
+      if (type) {
+        if (element[type]) result = element;
+      } else {
+        result = element;
+      }
+    }
 
-		return result;
-	},
-	checkElements: function() {
-		return (document.getElementsByClassName('has-error').length == 0);
-	},
-	addActionChecks: function(type, checks) {
-		TBE_EDITOR.actionChecks[type].push(checks);
-	},
+    return result;
+  },
+  checkElements: function() {
+    return (document.getElementsByClassName('has-error').length == 0);
+  },
+  addActionChecks: function(type, checks) {
+    TBE_EDITOR.actionChecks[type].push(checks);
+  },
 
-	fieldChanged_fName: function(fName,el) {
-		var idx=2;
-		var table = TBE_EDITOR.split(fName, "[", idx);
-		var uid = TBE_EDITOR.split(fName, "[", idx+1);
-		var field = TBE_EDITOR.split(fName, "[", idx+2);
+  fieldChanged_fName: function(fName, el) {
+    var idx = 2;
+    var table = TBE_EDITOR.split(fName, "[", idx);
+    var uid = TBE_EDITOR.split(fName, "[", idx + 1);
+    var field = TBE_EDITOR.split(fName, "[", idx + 2);
 
-		table = table.substr(0,table.length-1);
-		uid = uid.substr(0,uid.length-1);
-		field = field.substr(0,field.length-1);
-		TBE_EDITOR.fieldChanged(table,uid,field,el);
-	},
-	fieldChanged: function(table,uid,field,el) {
-		var theField = 'data['+table+']['+uid+']['+field+']';
-		TBE_EDITOR.isChanged = 1;
+    table = table.substr(0, table.length - 1);
+    uid = uid.substr(0, uid.length - 1);
+    field = field.substr(0, field.length - 1);
+    TBE_EDITOR.fieldChanged(table, uid, field, el);
+  },
+  fieldChanged: function(table, uid, field, el) {
+    var theField = 'data[' + table + '][' + uid + '][' + field + ']';
+    TBE_EDITOR.isChanged = 1;
 
-		// modify the "field has changed" info by adding a class to the container element (based on palette or main field)
-		var $formField = $('[name="' + el + '"]');
-		var $humanReadableField = $('[data-formengine-input-name="' + el + '"]');
-		if (!$formField.is($humanReadableField)) {
-			$humanReadableField.triggerHandler('change');
-		}
-		// add class to palette field
-		$formField.closest('.t3js-formengine-palette-field').addClass('has-change');
+    // modify the "field has changed" info by adding a class to the container element (based on palette or main field)
+    var $formField = $('[name="' + el + '"]');
+    var $humanReadableField = $('[data-formengine-input-name="' + el + '"]');
+    if (!$formField.is($humanReadableField)) {
+      $humanReadableField.triggerHandler('change');
+    }
+    // add class to palette field
+    $formField.closest('.t3js-formengine-palette-field').addClass('has-change');
 
-		if (TYPO3.FormEngine && TYPO3.FormEngine.Validation) {
-			TYPO3.FormEngine.Validation.updateInputField(theField);
-			TYPO3.FormEngine.Validation.validate();
-		}
-	},
-	isFormChanged: function(noAlert) {
-		if (TBE_EDITOR.isChanged && !noAlert && confirm(TYPO3.lang['FormEngine.fieldsChanged'])) {
-			return 0;
-		}
-		return TBE_EDITOR.isChanged;
-	},
-	checkAndDoSubmit: function(sendAlert) {
-		if (TBE_EDITOR.checkSubmit(sendAlert)) { TBE_EDITOR.submitForm(); }
-	},
-	/**
-	 * Checks if the form can be submitted according to any possible restrains like required values, item numbers etc.
-	 * Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1)
-	 * If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will).
-	 * If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...)
-	 */
-	checkSubmit: function(sendAlert) {
-		var funcIndex, funcMax, funcRes;
-		var OK = 1;
-		var STOP = 0;
+    if (TYPO3.FormEngine && TYPO3.FormEngine.Validation) {
+      TYPO3.FormEngine.Validation.updateInputField(theField);
+      TYPO3.FormEngine.Validation.validate();
+    }
+  },
+  isFormChanged: function(noAlert) {
+    if (TBE_EDITOR.isChanged && !noAlert && confirm(TYPO3.lang['FormEngine.fieldsChanged'])) {
+      return 0;
+    }
+    return TBE_EDITOR.isChanged;
+  },
+  checkAndDoSubmit: function(sendAlert) {
+    if (TBE_EDITOR.checkSubmit(sendAlert)) {
+      TBE_EDITOR.submitForm();
+    }
+  },
+  /**
+   * Checks if the form can be submitted according to any possible restrains like required values, item numbers etc.
+   * Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1)
+   * If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will).
+   * If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...)
+   */
+  checkSubmit: function(sendAlert) {
+    var funcIndex, funcMax, funcRes;
+    var OK = 1;
+    var STOP = 0;
 
-		// $this->additionalJS_submit:
-		if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) {
-			for (funcIndex=0, funcMax=TBE_EDITOR.actionChecks.submit.length; funcIndex<funcMax; funcIndex++) {
-				try {
-					eval(TBE_EDITOR.actionChecks.submit[funcIndex]);
-				} catch(error) {}
-			}
-		}
+    // $this->additionalJS_submit:
+    if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) {
+      for (funcIndex = 0, funcMax = TBE_EDITOR.actionChecks.submit.length; funcIndex < funcMax; funcIndex++) {
+        try {
+          eval(TBE_EDITOR.actionChecks.submit[funcIndex]);
+        } catch (error) {
+        }
+      }
+    }
 
-		if (STOP) {
-			// return false immediately, if the code in additionalJS_submit set STOP variable.
-			return false;
-		}
+    if (STOP) {
+      // return false immediately, if the code in additionalJS_submit set STOP variable.
+      return false;
+    }
 
-		if (!OK) {
-			if (!confirm(unescape("SYSTEM ERROR: One or more Rich Text Editors on the page could not be contacted. This IS an error, although it should not be regular.\nYou can save the form now by pressing OK, but you will loose the Rich Text Editor content if you do.\n\nPlease report the error to your administrator if it persists."))) {
-				return false;
-			} else {
-				OK = 1;
-			}
-		}
-		if (!TBE_EDITOR.checkElements()) {
-			OK = 0;
-		}
+    if (!OK) {
+      if (!confirm(unescape("SYSTEM ERROR: One or more Rich Text Editors on the page could not be contacted. This IS an error, although it should not be regular.\nYou can save the form now by pressing OK, but you will loose the Rich Text Editor content if you do.\n\nPlease report the error to your administrator if it persists."))) {
+        return false;
+      } else {
+        OK = 1;
+      }
+    }
+    if (!TBE_EDITOR.checkElements()) {
+      OK = 0;
+    }
 
-		if (OK || sendAlert==-1) {
-			return true;
-		} else {
-			if (sendAlert) {
-				var t = (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top);
-				t.TYPO3.Modal.confirm(
-					t.TYPO3.lang['alert'] || 'Alert',
-					TYPO3.lang['FormEngine.fieldsMissing'],
-					t.TYPO3.Severity.error,
-					[
-						{
-							text: t.TYPO3.lang['button.ok'] || 'OK',
-							active: true,
-							btnClass: 'btn-default',
-							name: 'ok'
-						}
-					]
-				).on('button.clicked', function(e) {
-					t.TYPO3.Modal.dismiss();
-				});
-			}
-			return false;
-		}
-	},
-	submitForm: function() {
-		if (TBE_EDITOR.doSaveFieldName) {
-			document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value=1;
-		}
-		// Set a short timeout to allow other JS processes to complete, in particular those from
-		// EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755).
-		// TODO: This should be solved in a better way when this script is refactored.
-		window.setTimeout(function() {
-			document.getElementsByName(TBE_EDITOR.formname).item(0).submit();
-		}, 100);
-	},
-	split: function(theStr1, delim, index) {
-		var theStr = ""+theStr1;
-		var lengthOfDelim = delim.length;
-		sPos = -lengthOfDelim;
-		if (index<1) {index=1;}
-		for (var a=1; a<index; a++) {
-			sPos = theStr.indexOf(delim, sPos+lengthOfDelim);
-			if (sPos==-1) { return null; }
-		}
-		ePos = theStr.indexOf(delim, sPos+lengthOfDelim);
-		if(ePos == -1) { ePos = theStr.length; }
-		return (theStr.substring(sPos+lengthOfDelim,ePos));
-	},
-	curSelected: function(theField) {
-		var fObjSel = $('[data-formengine-input-name="' + theField + '"]').get(1);
-		var retVal="";
-		if (fObjSel) {
-			if (fObjSel.type=='select-multiple' || fObjSel.type=='select-one') {
-				var l=fObjSel.length;
-				for (a=0;a<l;a++) {
-					if (fObjSel.options[a].selected==1) {
-						retVal+=fObjSel.options[a].value+",";
-					}
-				}
-			}
-		}
-		return retVal;
-	},
-	rawurlencode: function(str,maxlen) {
-		var output = str;
-		if (maxlen)	output = output.substr(0,200);
-		output = encodeURIComponent(output);
-		return output;
-	},
-	str_replace: function(match,replace,string) {
-		var input = ''+string;
-		var matchStr = ''+match;
-		if (!matchStr) { return string; }
-		var output = '';
-		var pointer=0;
-		var pos = input.indexOf(matchStr);
-		while (pos!=-1) {
-			output+=''+input.substr(pointer, pos-pointer)+replace;
-			pointer=pos+matchStr.length;
-			pos = input.indexOf(match,pos+1);
-		}
-		output+=''+input.substr(pointer);
-		return output;
-	},
+    if (OK || sendAlert == -1) {
+      return true;
+    } else {
+      if (sendAlert) {
+        var t = (opener != null && typeof opener.top.TYPO3 !== 'undefined' ? opener.top : top);
+        t.TYPO3.Modal.confirm(
+          t.TYPO3.lang['alert'] || 'Alert',
+          TYPO3.lang['FormEngine.fieldsMissing'],
+          t.TYPO3.Severity.error,
+          [
+            {
+              text: t.TYPO3.lang['button.ok'] || 'OK',
+              active: true,
+              btnClass: 'btn-default',
+              name: 'ok'
+            }
+          ]
+        ).on('button.clicked', function(e) {
+          t.TYPO3.Modal.dismiss();
+        });
+      }
+      return false;
+    }
+  },
+  submitForm: function() {
+    if (TBE_EDITOR.doSaveFieldName) {
+      document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value = 1;
+    }
+    // Set a short timeout to allow other JS processes to complete, in particular those from
+    // EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755).
+    // TODO: This should be solved in a better way when this script is refactored.
+    window.setTimeout(function() {
+      document.getElementsByName(TBE_EDITOR.formname).item(0).submit();
+    }, 100);
+  },
+  split: function(theStr1, delim, index) {
+    var theStr = "" + theStr1;
+    var lengthOfDelim = delim.length;
+    sPos = -lengthOfDelim;
+    if (index < 1) {
+      index = 1;
+    }
+    for (var a = 1; a < index; a++) {
+      sPos = theStr.indexOf(delim, sPos + lengthOfDelim);
+      if (sPos == -1) {
+        return null;
+      }
+    }
+    ePos = theStr.indexOf(delim, sPos + lengthOfDelim);
+    if (ePos == -1) {
+      ePos = theStr.length;
+    }
+    return (theStr.substring(sPos + lengthOfDelim, ePos));
+  },
+  curSelected: function(theField) {
+    var fObjSel = $('[data-formengine-input-name="' + theField + '"]').get(1);
+    var retVal = "";
+    if (fObjSel) {
+      if (fObjSel.type == 'select-multiple' || fObjSel.type == 'select-one') {
+        var l = fObjSel.length;
+        for (a = 0; a < l; a++) {
+          if (fObjSel.options[a].selected == 1) {
+            retVal += fObjSel.options[a].value + ",";
+          }
+        }
+      }
+    }
+    return retVal;
+  },
+  rawurlencode: function(str, maxlen) {
+    var output = str;
+    if (maxlen) output = output.substr(0, 200);
+    output = encodeURIComponent(output);
+    return output;
+  },
+  str_replace: function(match, replace, string) {
+    var input = '' + string;
+    var matchStr = '' + match;
+    if (!matchStr) {
+      return string;
+    }
+    var output = '';
+    var pointer = 0;
+    var pos = input.indexOf(matchStr);
+    while (pos != -1) {
+      output += '' + input.substr(pointer, pos - pointer) + replace;
+      pointer = pos + matchStr.length;
+      pos = input.indexOf(match, pos + 1);
+    }
+    output += '' + input.substr(pointer);
+    return output;
+  }
 };
 
 // backwards compatibility for extensions
@@ -257,55 +268,55 @@ var TBE_EDITOR_str_replace = TBE_EDITOR.str_replace;
 
 
 var typo3form = {
-	fieldSet: function(theField, evallist, is_in, checkbox, checkboxValue) {
-		if (document[TBE_EDITOR.formname][theField]) {
-			var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-			var theValue = document[TBE_EDITOR.formname][theField].value;
-			if (checkbox && theValue==checkboxValue) {
-				document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = "";
-				if (document[TBE_EDITOR.formname][theField+"_cb"])	document[TBE_EDITOR.formname][theField+"_cb"].checked = "";
-			} else {
-				document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = evalFunc.outputObjValue(theFObj, theValue);
-				if (document[TBE_EDITOR.formname][theField+"_cb"])	document[TBE_EDITOR.formname][theField+"_cb"].checked = "on";
-			}
-		}
-	},
-	fieldGet: function(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off, checkSetValue) {
-		if (document[TBE_EDITOR.formname][theField]) {
-			var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-			if (checkbox_off) {
-				if (document[TBE_EDITOR.formname][theField+"_cb"].checked) {
-					var split = evallist.split(',');
-					for (var i = 0; split.length > i; i++) {
-						var el = split[i].replace(/ /g, '');
-						if (el == 'datetime' || el == 'date') {
-							var now = new Date();
-							checkSetValue = Date.parse(now)/1000 - now.getTimezoneOffset()*60;
-							break;
-						} else if (el == 'time' || el == 'timesec') {
-							checkSetValue = evalFunc_getTimeSecs(new Date());
-							break;
-						}
-					}
-					document[TBE_EDITOR.formname][theField].value=checkSetValue;
-				} else {
-					document[TBE_EDITOR.formname][theField].value=checkboxValue;
-				}
-			}else{
-				document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value);
-			}
-			typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue);
-		}
-	}
+  fieldSet: function(theField, evallist, is_in, checkbox, checkboxValue) {
+    if (document[TBE_EDITOR.formname][theField]) {
+      var theFObj = new evalFunc_dummy(evallist, is_in, checkbox, checkboxValue);
+      var theValue = document[TBE_EDITOR.formname][theField].value;
+      if (checkbox && theValue == checkboxValue) {
+        document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = "";
+        if (document[TBE_EDITOR.formname][theField + "_cb"]) document[TBE_EDITOR.formname][theField + "_cb"].checked = "";
+      } else {
+        document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value = evalFunc.outputObjValue(theFObj, theValue);
+        if (document[TBE_EDITOR.formname][theField + "_cb"]) document[TBE_EDITOR.formname][theField + "_cb"].checked = "on";
+      }
+    }
+  },
+  fieldGet: function(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off, checkSetValue) {
+    if (document[TBE_EDITOR.formname][theField]) {
+      var theFObj = new evalFunc_dummy(evallist, is_in, checkbox, checkboxValue);
+      if (checkbox_off) {
+        if (document[TBE_EDITOR.formname][theField + "_cb"].checked) {
+          var split = evallist.split(',');
+          for (var i = 0; split.length > i; i++) {
+            var el = split[i].replace(/ /g, '');
+            if (el == 'datetime' || el == 'date') {
+              var now = new Date();
+              checkSetValue = Date.parse(now) / 1000 - now.getTimezoneOffset() * 60;
+              break;
+            } else if (el == 'time' || el == 'timesec') {
+              checkSetValue = evalFunc_getTimeSecs(new Date());
+              break;
+            }
+          }
+          document[TBE_EDITOR.formname][theField].value = checkSetValue;
+        } else {
+          document[TBE_EDITOR.formname][theField].value = checkboxValue;
+        }
+      } else {
+        document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document.querySelector('form[name="' + TBE_EDITOR.formname + '"] [data-formengine-input-name="' + theField + '"]').value);
+      }
+      typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue);
+    }
+  }
 };
 
 // @TODO: This function is a copy from jsfunc.evalfield.js
 // @TODO: Remove it later, after TBE_EDITOR is not used anymore.
-function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) {
-	this.evallist = evallist;
-	this.is_in = is_in;
-	this.checkboxValue = checkboxValue;
-	this.checkbox = checkbox;
+function evalFunc_dummy(evallist, is_in, checkbox, checkboxValue) {
+  this.evallist = evallist;
+  this.is_in = is_in;
+  this.checkboxValue = checkboxValue;
+  this.checkbox = checkbox;
 }
 
 // backwards compatibility for extensions
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/md5.js b/typo3/sysext/backend/Resources/Public/JavaScript/md5.js
index 8ed0ad042f02..5108d176dcbf 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/md5.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/md5.js
@@ -1,207 +1,224 @@
 /**
-*
-*  MD5 (Message-Digest Algorithm)
-*  http://www.webtoolkit.info/
-*
-**/
+ *
+ *  MD5 (Message-Digest Algorithm)
+ *  http://www.webtoolkit.info/
+ *
+ **/
 
 function MD5(string) {
 
-	function RotateLeft(lValue, iShiftBits) {
-		return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
-	}
-
-	function AddUnsigned(lX,lY) {
-		var lX4,lY4,lX8,lY8,lResult;
-		lX8 = (lX & 0x80000000);
-		lY8 = (lY & 0x80000000);
-		lX4 = (lX & 0x40000000);
-		lY4 = (lY & 0x40000000);
-		lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
-		if (lX4 & lY4) {
-			return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
-		}
-		if (lX4 | lY4) {
-			if (lResult & 0x40000000) {
-				return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
-			} else {
-				return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
-			}
-		} else {
-			return (lResult ^ lX8 ^ lY8);
-		}
- 	}
-
- 	function F(x,y,z) { return (x & y) | ((~x) & z); }
- 	function G(x,y,z) { return (x & z) | (y & (~z)); }
- 	function H(x,y,z) { return (x ^ y ^ z); }
-	function I(x,y,z) { return (y ^ (x | (~z))); }
-
-	function FF(a,b,c,d,x,s,ac) {
-		a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
-		return AddUnsigned(RotateLeft(a, s), b);
-	};
-
-	function GG(a,b,c,d,x,s,ac) {
-		a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
-		return AddUnsigned(RotateLeft(a, s), b);
-	};
-
-	function HH(a,b,c,d,x,s,ac) {
-		a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
-		return AddUnsigned(RotateLeft(a, s), b);
-	};
-
-	function II(a,b,c,d,x,s,ac) {
-		a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
-		return AddUnsigned(RotateLeft(a, s), b);
-	};
-
-	function ConvertToWordArray(string) {
-		var lWordCount;
-		var lMessageLength = string.length;
-		var lNumberOfWords_temp1=lMessageLength + 8;
-		var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
-		var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
-		var lWordArray=Array(lNumberOfWords-1);
-		var lBytePosition = 0;
-		var lByteCount = 0;
-		while ( lByteCount < lMessageLength ) {
-			lWordCount = (lByteCount-(lByteCount % 4))/4;
-			lBytePosition = (lByteCount % 4)*8;
-			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
-			lByteCount++;
-		}
-		lWordCount = (lByteCount-(lByteCount % 4))/4;
-		lBytePosition = (lByteCount % 4)*8;
-		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
-		lWordArray[lNumberOfWords-2] = lMessageLength<<3;
-		lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
-		return lWordArray;
-	};
-
-	function WordToHex(lValue) {
-		var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
-		for (lCount = 0;lCount<=3;lCount++) {
-			lByte = (lValue>>>(lCount*8)) & 255;
-			WordToHexValue_temp = "0" + lByte.toString(16);
-			WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
-		}
-		return WordToHexValue;
-	};
-
-	function Utf8Encode(string) {
-		string = string.replace(/\r\n/g,"\n");
-		var utftext = "";
-
-		for (var n = 0; n < string.length; n++) {
-
-			var c = string.charCodeAt(n);
-
-			if (c < 128) {
-				utftext += String.fromCharCode(c);
-			}
-			else if((c > 127) && (c < 2048)) {
-				utftext += String.fromCharCode((c >> 6) | 192);
-				utftext += String.fromCharCode((c & 63) | 128);
-			}
-			else {
-				utftext += String.fromCharCode((c >> 12) | 224);
-				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
-				utftext += String.fromCharCode((c & 63) | 128);
-			}
-
-		}
-
-		return utftext;
-	};
-
-	var x=Array();
-	var k,AA,BB,CC,DD,a,b,c,d;
-	var S11=7, S12=12, S13=17, S14=22;
-	var S21=5, S22=9 , S23=14, S24=20;
-	var S31=4, S32=11, S33=16, S34=23;
-	var S41=6, S42=10, S43=15, S44=21;
-
-	string = Utf8Encode(string);
-
-	x = ConvertToWordArray(string);
-
-	a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
-
-	for (k=0;k<x.length;k+=16) {
-		AA=a; BB=b; CC=c; DD=d;
-		a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
-		d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
-		c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
-		b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
-		a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
-		d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
-		c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
-		b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
-		a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
-		d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
-		c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
-		b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
-		a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
-		d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
-		c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
-		b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
-		a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
-		d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
-		c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
-		b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
-		a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
-		d=GG(d,a,b,c,x[k+10],S22,0x2441453);
-		c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
-		b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
-		a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
-		d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
-		c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
-		b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
-		a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
-		d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
-		c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
-		b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
-		a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
-		d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
-		c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
-		b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
-		a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
-		d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
-		c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
-		b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
-		a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
-		d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
-		c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
-		b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
-		a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
-		d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
-		c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
-		b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
-		a=II(a,b,c,d,x[k+0], S41,0xF4292244);
-		d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
-		c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
-		b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
-		a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
-		d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
-		c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
-		b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
-		a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
-		d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
-		c=II(c,d,a,b,x[k+6], S43,0xA3014314);
-		b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
-		a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
-		d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
-		c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
-		b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
-		a=AddUnsigned(a,AA);
-		b=AddUnsigned(b,BB);
-		c=AddUnsigned(c,CC);
-		d=AddUnsigned(d,DD);
-	}
-
-	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);
-
-	return temp.toLowerCase();
-}
\ No newline at end of file
+  function RotateLeft(lValue, iShiftBits) {
+    return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
+  }
+
+  function AddUnsigned(lX, lY) {
+    var lX4, lY4, lX8, lY8, lResult;
+    lX8 = (lX & 0x80000000);
+    lY8 = (lY & 0x80000000);
+    lX4 = (lX & 0x40000000);
+    lY4 = (lY & 0x40000000);
+    lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
+    if (lX4 & lY4) {
+      return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+    }
+    if (lX4 | lY4) {
+      if (lResult & 0x40000000) {
+        return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+      } else {
+        return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+      }
+    } else {
+      return (lResult ^ lX8 ^ lY8);
+    }
+  }
+
+  function F(x, y, z) {
+    return (x & y) | ((~x) & z);
+  }
+
+  function G(x, y, z) {
+    return (x & z) | (y & (~z));
+  }
+
+  function H(x, y, z) {
+    return (x ^ y ^ z);
+  }
+
+  function I(x, y, z) {
+    return (y ^ (x | (~z)));
+  }
+
+  function FF(a, b, c, d, x, s, ac) {
+    a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
+    return AddUnsigned(RotateLeft(a, s), b);
+  };
+
+  function GG(a, b, c, d, x, s, ac) {
+    a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
+    return AddUnsigned(RotateLeft(a, s), b);
+  };
+
+  function HH(a, b, c, d, x, s, ac) {
+    a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
+    return AddUnsigned(RotateLeft(a, s), b);
+  };
+
+  function II(a, b, c, d, x, s, ac) {
+    a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
+    return AddUnsigned(RotateLeft(a, s), b);
+  };
+
+  function ConvertToWordArray(string) {
+    var lWordCount;
+    var lMessageLength = string.length;
+    var lNumberOfWords_temp1 = lMessageLength + 8;
+    var lNumberOfWords_temp2 = (lNumberOfWords_temp1 - (lNumberOfWords_temp1 % 64)) / 64;
+    var lNumberOfWords = (lNumberOfWords_temp2 + 1) * 16;
+    var lWordArray = Array(lNumberOfWords - 1);
+    var lBytePosition = 0;
+    var lByteCount = 0;
+    while (lByteCount < lMessageLength) {
+      lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+      lBytePosition = (lByteCount % 4) * 8;
+      lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
+      lByteCount++;
+    }
+    lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+    lBytePosition = (lByteCount % 4) * 8;
+    lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
+    lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
+    lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
+    return lWordArray;
+  };
+
+  function WordToHex(lValue) {
+    var WordToHexValue = "", WordToHexValue_temp = "", lByte, lCount;
+    for (lCount = 0; lCount <= 3; lCount++) {
+      lByte = (lValue >>> (lCount * 8)) & 255;
+      WordToHexValue_temp = "0" + lByte.toString(16);
+      WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length - 2, 2);
+    }
+    return WordToHexValue;
+  };
+
+  function Utf8Encode(string) {
+    string = string.replace(/\r\n/g, "\n");
+    var utftext = "";
+
+    for (var n = 0; n < string.length; n++) {
+
+      var c = string.charCodeAt(n);
+
+      if (c < 128) {
+        utftext += String.fromCharCode(c);
+      }
+      else if ((c > 127) && (c < 2048)) {
+        utftext += String.fromCharCode((c >> 6) | 192);
+        utftext += String.fromCharCode((c & 63) | 128);
+      }
+      else {
+        utftext += String.fromCharCode((c >> 12) | 224);
+        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+        utftext += String.fromCharCode((c & 63) | 128);
+      }
+
+    }
+
+    return utftext;
+  };
+
+  var x = Array();
+  var k, AA, BB, CC, DD, a, b, c, d;
+  var S11 = 7, S12 = 12, S13 = 17, S14 = 22;
+  var S21 = 5, S22 = 9, S23 = 14, S24 = 20;
+  var S31 = 4, S32 = 11, S33 = 16, S34 = 23;
+  var S41 = 6, S42 = 10, S43 = 15, S44 = 21;
+
+  string = Utf8Encode(string);
+
+  x = ConvertToWordArray(string);
+
+  a = 0x67452301;
+  b = 0xEFCDAB89;
+  c = 0x98BADCFE;
+  d = 0x10325476;
+
+  for (k = 0; k < x.length; k += 16) {
+    AA = a;
+    BB = b;
+    CC = c;
+    DD = d;
+    a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
+    d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
+    c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
+    b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
+    a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
+    d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
+    c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
+    b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
+    a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
+    d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
+    c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
+    b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
+    a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
+    d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
+    c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
+    b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
+    a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
+    d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
+    c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
+    b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
+    a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
+    d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
+    c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
+    b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
+    a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
+    d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
+    c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
+    b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
+    a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
+    d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
+    c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
+    b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
+    a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
+    d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
+    c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
+    b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
+    a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
+    d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
+    c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
+    b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
+    a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
+    d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
+    c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
+    b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
+    a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
+    d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
+    c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
+    b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
+    a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
+    d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
+    c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
+    b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
+    a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
+    d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
+    c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
+    b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
+    a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
+    d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
+    c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
+    b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
+    a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
+    d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
+    c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
+    b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
+    a = AddUnsigned(a, AA);
+    b = AddUnsigned(b, BB);
+    c = AddUnsigned(c, CC);
+    d = AddUnsigned(d, DD);
+  }
+
+  var temp = WordToHex(a) + WordToHex(b) + WordToHex(c) + WordToHex(d);
+
+  return temp.toLowerCase();
+}
diff --git a/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js b/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js
index c76186cac6fa..b9d88053ebf5 100644
--- a/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js
+++ b/typo3/sysext/backend/Tests/JavaScript/FormEngineValidationTest.js
@@ -1,413 +1,419 @@
 define(['jquery', 'TYPO3/CMS/Backend/FormEngineValidation'], function($, FormEngineValidation) {
-	'use strict';
+  'use strict';
 
-	describe('TYPO3/CMS/Backend/FormEngineValidationTest:', function() {
-		/**
-		 * @type {*[]}
-		 */
-		var formatValueDataProvider = [
-			{
-				'description': 'works for type date',
-				'type': 'date',
-				'value': 0,
-				'config': [],
-				'result': ''
-			},
-			{
-				'description': 'works for type date with timestamp',
-				'type': 'date',
-				'value': 10000000,
-				'config': [],
-				'result': '26-4-1970'
-			},
-			{
-				'description': 'works for type date with iso date',
-				'type': 'date',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '02-12-2016'
-			},
-			{
-				'description': 'works for type datetime',
-				'type': 'datetime',
-				'value': 0,
-				'config': [],
-				'result': ''
-			},
-			{
-				'description': 'works for type datetime with timestamp',
-				'type': 'datetime',
-				'value': 10000000,
-				'config': [],
-				'result': '17:46 26-4-1970'
-			},
-			{
-				'description': 'works for type datetime with iso date',
-				'type': 'datetime',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '11:16 02-12-2016'
-			},
-			{
-				'description': 'resolves to empty result for zero value',
-				'type': 'datetime',
-				'value': 0,
-				'config': [],
-				'result': ''
-			},
-			{
-				'description': 'resolves to empty result for invalid value',
-				'type': 'datetime',
-				'value': 'invalid',
-				'config': [],
-				'result': ''
-			},
-			{
-				'description': 'works for type time',
-				'type': 'time',
-				'value': 0,
-				'config': [],
-				'result': '00:00'
-			},
-			{
-				'description': 'works for type time with timestamp',
-				'type': 'time',
-				'value': 10000000,
-				'config': [],
-				'result': '17:46'
-			},
-			{
-				'description': 'works for type time with iso date',
-				'type': 'time',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '11:16'
-			}
-		];
+  describe('TYPO3/CMS/Backend/FormEngineValidationTest:', function() {
+    /**
+     * @type {*[]}
+     */
+    var formatValueDataProvider = [
+      {
+        'description': 'works for type date',
+        'type': 'date',
+        'value': 0,
+        'config': [],
+        'result': ''
+      },
+      {
+        'description': 'works for type date with timestamp',
+        'type': 'date',
+        'value': 10000000,
+        'config': [],
+        'result': '26-4-1970'
+      },
+      {
+        'description': 'works for type date with iso date',
+        'type': 'date',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '02-12-2016'
+      },
+      {
+        'description': 'works for type datetime',
+        'type': 'datetime',
+        'value': 0,
+        'config': [],
+        'result': ''
+      },
+      {
+        'description': 'works for type datetime with timestamp',
+        'type': 'datetime',
+        'value': 10000000,
+        'config': [],
+        'result': '17:46 26-4-1970'
+      },
+      {
+        'description': 'works for type datetime with iso date',
+        'type': 'datetime',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '11:16 02-12-2016'
+      },
+      {
+        'description': 'resolves to empty result for zero value',
+        'type': 'datetime',
+        'value': 0,
+        'config': [],
+        'result': ''
+      },
+      {
+        'description': 'resolves to empty result for invalid value',
+        'type': 'datetime',
+        'value': 'invalid',
+        'config': [],
+        'result': ''
+      },
+      {
+        'description': 'works for type time',
+        'type': 'time',
+        'value': 0,
+        'config': [],
+        'result': '00:00'
+      },
+      {
+        'description': 'works for type time with timestamp',
+        'type': 'time',
+        'value': 10000000,
+        'config': [],
+        'result': '17:46'
+      },
+      {
+        'description': 'works for type time with iso date',
+        'type': 'time',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '11:16'
+      }
+    ];
 
-		/**
-		 * @dataProvider formatValueDataProvider
-		 * @test
-		 */
-		describe('tests for formatValue', function() {
-			using(formatValueDataProvider, function(testCase) {
-				it(testCase.description, function() {
-					FormEngineValidation.USmode = 0;
-					var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config);
-					expect(result).toBe(testCase.result);
-				});
-			});
-		});
+    /**
+     * @dataProvider formatValueDataProvider
+     * @test
+     */
+    describe('tests for formatValue', function() {
+      using(formatValueDataProvider, function(testCase) {
+        it(testCase.description, function() {
+          FormEngineValidation.USmode = 0;
+          var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config);
+          expect(result).toBe(testCase.result);
+        });
+      });
+    });
 
-		/**
-		 * @type {*[]}
-		 */
-		var formatValueUsModeDataProvider = [
-			{
-				'description': 'works for type date with timestamp in US mode',
-				'type': 'date',
-				'value': 10000000,
-				'config': [],
-				'result': '4-26-1970'
-			},
-			{
-				'description': 'works for type date with iso date in US mode',
-				'type': 'date',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '12-02-2016'
-			},
-			{
-				'description': 'works for type datetime with timestamp in US mode',
-				'type': 'datetime',
-				'value': 10000000,
-				'config': [],
-				'result': '17:46 4-26-1970'
-			},
-			{
-				'description': 'works for type datetime with iso date in US mode',
-				'type': 'datetime',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '11:16 12-02-2016'
-			},
-			{
-				'description': 'works for type time with timestamp in US mode',
-				'type': 'time',
-				'value': 10000000,
-				'config': [],
-				'result': '17:46'
-			},
-			{
-				'description': 'works for type time with iso date in US mode',
-				'type': 'time',
-				'value': '2016-12-02T11:16:06+00:00',
-				'config': [],
-				'result': '11:16'
-			}
-		];
+    /**
+     * @type {*[]}
+     */
+    var formatValueUsModeDataProvider = [
+      {
+        'description': 'works for type date with timestamp in US mode',
+        'type': 'date',
+        'value': 10000000,
+        'config': [],
+        'result': '4-26-1970'
+      },
+      {
+        'description': 'works for type date with iso date in US mode',
+        'type': 'date',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '12-02-2016'
+      },
+      {
+        'description': 'works for type datetime with timestamp in US mode',
+        'type': 'datetime',
+        'value': 10000000,
+        'config': [],
+        'result': '17:46 4-26-1970'
+      },
+      {
+        'description': 'works for type datetime with iso date in US mode',
+        'type': 'datetime',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '11:16 12-02-2016'
+      },
+      {
+        'description': 'works for type time with timestamp in US mode',
+        'type': 'time',
+        'value': 10000000,
+        'config': [],
+        'result': '17:46'
+      },
+      {
+        'description': 'works for type time with iso date in US mode',
+        'type': 'time',
+        'value': '2016-12-02T11:16:06+00:00',
+        'config': [],
+        'result': '11:16'
+      }
+    ];
 
-		/**
-		 * @dataProvider formatValueUsModeDataProvider
-		 * @test
-		 */
-		describe('tests for formatValue in US Mode', function() {
-			using(formatValueUsModeDataProvider, function(testCase) {
-				it(testCase.description, function() {
-					FormEngineValidation.USmode = 1;
-					var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config);
-					expect(result).toBe(testCase.result);
-				});
-			});
-		});
+    /**
+     * @dataProvider formatValueUsModeDataProvider
+     * @test
+     */
+    describe('tests for formatValue in US Mode', function() {
+      using(formatValueUsModeDataProvider, function(testCase) {
+        it(testCase.description, function() {
+          FormEngineValidation.USmode = 1;
+          var result = FormEngineValidation.formatValue(testCase.type, testCase.value, testCase.config);
+          expect(result).toBe(testCase.result);
+        });
+      });
+    });
 
-		/**
-		 * @type {*[]}
-		 */
-		var processValueDataProvider = [
-			{
-				'description': 'works for command alpha with numeric value',
-				'command': 'alpha',
-				'value': '1234',
-				'config': [],
-				'result': ''
-			},
-			{
-				'description': 'works for command alpha with string value',
-				'command': 'alpha',
-				'value': 'abc',
-				'config': [],
-				'result': 'abc'
-			},
-			{
-				'description': 'works for command alpha with alphanum input',
-				'command': 'alpha',
-				'value': 'abc123',
-				'config': [],
-				'result': 'abc'
-			},
-			{
-				'description': 'works for command alpha with alphanum input',
-				'command': 'alpha',
-				'value': '123abc123',
-				'config': [],
-				'result': 'abc'
-			}
-		];
+    /**
+     * @type {*[]}
+     */
+    var processValueDataProvider = [
+      {
+        'description': 'works for command alpha with numeric value',
+        'command': 'alpha',
+        'value': '1234',
+        'config': [],
+        'result': ''
+      },
+      {
+        'description': 'works for command alpha with string value',
+        'command': 'alpha',
+        'value': 'abc',
+        'config': [],
+        'result': 'abc'
+      },
+      {
+        'description': 'works for command alpha with alphanum input',
+        'command': 'alpha',
+        'value': 'abc123',
+        'config': [],
+        'result': 'abc'
+      },
+      {
+        'description': 'works for command alpha with alphanum input',
+        'command': 'alpha',
+        'value': '123abc123',
+        'config': [],
+        'result': 'abc'
+      }
+    ];
 
-		/**
-		 * @dataProvider processValueDataProvider
-		 * @test
-		 */
-		describe('test for processValue', function() {
-			using(processValueDataProvider, function(testCase) {
-				it(testCase.description, function() {
-					var result = FormEngineValidation.processValue(testCase.command, testCase.value, testCase.config);
-					expect(result).toBe(testCase.result);
-				});
-			});
-		});
+    /**
+     * @dataProvider processValueDataProvider
+     * @test
+     */
+    describe('test for processValue', function() {
+      using(processValueDataProvider, function(testCase) {
+        it(testCase.description, function() {
+          var result = FormEngineValidation.processValue(testCase.command, testCase.value, testCase.config);
+          expect(result).toBe(testCase.result);
+        });
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for validateField', function() {});
+    /**
+     * @test
+     */
+    xdescribe('tests for validateField', function() {
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for trimExplode', function () {
-			it('works for comma as separator and list without spaces', function () {
-				expect(FormEngineValidation.trimExplode(',', 'foo,bar,baz')).toEqual(['foo', 'bar', 'baz']);
-			});
-			it('works for comma as separator and list with spaces', function () {
-				expect(FormEngineValidation.trimExplode(',', ' foo , bar , baz ')).toEqual(['foo', 'bar', 'baz']);
-			});
-			it('works for pipe as separator and list with spaces', function () {
-				expect(FormEngineValidation.trimExplode('|', ' foo | bar | baz ')).toEqual(['foo', 'bar', 'baz']);
-			});
-		});
+    /**
+     * @test
+     */
+    describe('tests for trimExplode', function() {
+      it('works for comma as separator and list without spaces', function() {
+        expect(FormEngineValidation.trimExplode(',', 'foo,bar,baz')).toEqual(['foo', 'bar', 'baz']);
+      });
+      it('works for comma as separator and list with spaces', function() {
+        expect(FormEngineValidation.trimExplode(',', ' foo , bar , baz ')).toEqual(['foo', 'bar', 'baz']);
+      });
+      it('works for pipe as separator and list with spaces', function() {
+        expect(FormEngineValidation.trimExplode('|', ' foo | bar | baz ')).toEqual(['foo', 'bar', 'baz']);
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for parseInt', function() {
-			it('works for value 0', function () {
-				expect(FormEngineValidation.parseInt(0)).toBe(0);
-			});
-			it('works for value 1', function () {
-				expect(FormEngineValidation.parseInt(1)).toBe(1);
-			});
-			it('works for value -1', function () {
-				expect(FormEngineValidation.parseInt(-1)).toBe(-1);
-			});
-			it('works for value "0"', function () {
-				expect(FormEngineValidation.parseInt('0')).toBe(0);
-			});
-			it('works for value "1"', function () {
-				expect(FormEngineValidation.parseInt('1')).toBe(1);
-			});
-			it('works for value "-1"', function () {
-				expect(FormEngineValidation.parseInt('-1')).toBe(-1);
-			});
-			it('works for value 0.5', function () {
-				expect(FormEngineValidation.parseInt(0.5)).toBe(0);
-			});
-			it('works for value "0.5"', function () {
-				expect(FormEngineValidation.parseInt('0.5')).toBe(0);
-			});
-			it('works for value "foo"', function () {
-				expect(FormEngineValidation.parseInt('foo')).toBe(0);
-			});
-			it('works for value true', function () {
-				expect(FormEngineValidation.parseInt(true)).toBe(0);
-			});
-			it('works for value false', function () {
-				expect(FormEngineValidation.parseInt(false)).toBe(0);
-			});
-			it('works for value null', function () {
-				expect(FormEngineValidation.parseInt(null)).toBe(0);
-			});
-		});
-		/**
-		 * @test
-		 */
-		describe('tests for parseDouble', function() {
-			it('works for value 0', function () {
-				expect(FormEngineValidation.parseDouble(0)).toBe('0.00');
-			});
-			it('works for value 1', function () {
-				expect(FormEngineValidation.parseDouble(1)).toBe('1.00');
-			});
-			it('works for value -1', function () {
-				expect(FormEngineValidation.parseDouble(-1)).toBe('-1.00');
-			});
-			it('works for value "0"', function () {
-				expect(FormEngineValidation.parseDouble('0')).toBe('0.00');
-			});
-			it('works for value "1"', function () {
-				expect(FormEngineValidation.parseDouble('1')).toBe('1.00');
-			});
-			it('works for value "-1"', function () {
-				expect(FormEngineValidation.parseDouble('-1')).toBe('-1.00');
-			});
-			it('works for value 0.5', function () {
-				expect(FormEngineValidation.parseDouble(0.5)).toBe('0.50');
-			});
-			it('works for value "0.5"', function () {
-				expect(FormEngineValidation.parseDouble('0.5')).toBe('0.50');
-			});
-			it('works for value "foo"', function () {
-				expect(FormEngineValidation.parseDouble('foo')).toBe('0.00');
-			});
-			it('works for value true', function () {
-				expect(FormEngineValidation.parseDouble(true)).toBe('0.00');
-			});
-			it('works for value false', function () {
-				expect(FormEngineValidation.parseDouble(false)).toBe('0.00');
-			});
-			it('works for value null', function () {
-				expect(FormEngineValidation.parseDouble(null)).toBe('0.00');
-			});
-		});
+    /**
+     * @test
+     */
+    describe('tests for parseInt', function() {
+      it('works for value 0', function() {
+        expect(FormEngineValidation.parseInt(0)).toBe(0);
+      });
+      it('works for value 1', function() {
+        expect(FormEngineValidation.parseInt(1)).toBe(1);
+      });
+      it('works for value -1', function() {
+        expect(FormEngineValidation.parseInt(-1)).toBe(-1);
+      });
+      it('works for value "0"', function() {
+        expect(FormEngineValidation.parseInt('0')).toBe(0);
+      });
+      it('works for value "1"', function() {
+        expect(FormEngineValidation.parseInt('1')).toBe(1);
+      });
+      it('works for value "-1"', function() {
+        expect(FormEngineValidation.parseInt('-1')).toBe(-1);
+      });
+      it('works for value 0.5', function() {
+        expect(FormEngineValidation.parseInt(0.5)).toBe(0);
+      });
+      it('works for value "0.5"', function() {
+        expect(FormEngineValidation.parseInt('0.5')).toBe(0);
+      });
+      it('works for value "foo"', function() {
+        expect(FormEngineValidation.parseInt('foo')).toBe(0);
+      });
+      it('works for value true', function() {
+        expect(FormEngineValidation.parseInt(true)).toBe(0);
+      });
+      it('works for value false', function() {
+        expect(FormEngineValidation.parseInt(false)).toBe(0);
+      });
+      it('works for value null', function() {
+        expect(FormEngineValidation.parseInt(null)).toBe(0);
+      });
+    });
+    /**
+     * @test
+     */
+    describe('tests for parseDouble', function() {
+      it('works for value 0', function() {
+        expect(FormEngineValidation.parseDouble(0)).toBe('0.00');
+      });
+      it('works for value 1', function() {
+        expect(FormEngineValidation.parseDouble(1)).toBe('1.00');
+      });
+      it('works for value -1', function() {
+        expect(FormEngineValidation.parseDouble(-1)).toBe('-1.00');
+      });
+      it('works for value "0"', function() {
+        expect(FormEngineValidation.parseDouble('0')).toBe('0.00');
+      });
+      it('works for value "1"', function() {
+        expect(FormEngineValidation.parseDouble('1')).toBe('1.00');
+      });
+      it('works for value "-1"', function() {
+        expect(FormEngineValidation.parseDouble('-1')).toBe('-1.00');
+      });
+      it('works for value 0.5', function() {
+        expect(FormEngineValidation.parseDouble(0.5)).toBe('0.50');
+      });
+      it('works for value "0.5"', function() {
+        expect(FormEngineValidation.parseDouble('0.5')).toBe('0.50');
+      });
+      it('works for value "foo"', function() {
+        expect(FormEngineValidation.parseDouble('foo')).toBe('0.00');
+      });
+      it('works for value true', function() {
+        expect(FormEngineValidation.parseDouble(true)).toBe('0.00');
+      });
+      it('works for value false', function() {
+        expect(FormEngineValidation.parseDouble(false)).toBe('0.00');
+      });
+      it('works for value null', function() {
+        expect(FormEngineValidation.parseDouble(null)).toBe('0.00');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for btrim', function() {
-			var result = FormEngineValidation.btrim(' test ');
+    /**
+     * @test
+     */
+    describe('tests for btrim', function() {
+      var result = FormEngineValidation.btrim(' test ');
 
-			it('works for string with whitespace in begin and end', function() {
-				expect(result).toBe(' test');
-			});
-		});
+      it('works for string with whitespace in begin and end', function() {
+        expect(result).toBe(' test');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for ltrim', function() {
-			var result = FormEngineValidation.ltrim(' test ');
+    /**
+     * @test
+     */
+    describe('tests for ltrim', function() {
+      var result = FormEngineValidation.ltrim(' test ');
 
-			it('works for string with whitespace in begin and end', function() {
-				expect(result).toBe('test ');
-			});
-		});
+      it('works for string with whitespace in begin and end', function() {
+        expect(result).toBe('test ');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for parseDateTime', function() {});
+    /**
+     * @test
+     */
+    xdescribe('tests for parseDateTime', function() {
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for parseDate', function() {});
+    /**
+     * @test
+     */
+    xdescribe('tests for parseDate', function() {
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for parseTime', function() {});
+    /**
+     * @test
+     */
+    xdescribe('tests for parseTime', function() {
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for parseYear', function() {});
+    /**
+     * @test
+     */
+    xdescribe('tests for parseYear', function() {
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for getYear', function () {
-			var currentDate = new Date();
-			afterEach(function() {
-				jasmine.clock().mockDate(currentDate);
-			});
+    /**
+     * @test
+     */
+    describe('tests for getYear', function() {
+      var currentDate = new Date();
+      afterEach(function() {
+        jasmine.clock().mockDate(currentDate);
+      });
 
-			it('works for current date', function () {
-				var date = new Date();
-				expect(FormEngineValidation.getYear(date)).toBe(date.getYear() + 1900);
-			});
-			it('works for year 2013', function () {
-				var baseTime = new Date(2013, 9, 23);
-				jasmine.clock().mockDate(baseTime);
-				expect(FormEngineValidation.getYear(baseTime)).toBe(2013);
-			})
-		});
+      it('works for current date', function() {
+        var date = new Date();
+        expect(FormEngineValidation.getYear(date)).toBe(date.getYear() + 1900);
+      });
+      it('works for year 2013', function() {
+        var baseTime = new Date(2013, 9, 23);
+        jasmine.clock().mockDate(baseTime);
+        expect(FormEngineValidation.getYear(baseTime)).toBe(2013);
+      })
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for getDate', function () {
-			var currentDate = new Date();
-			afterEach(function() {
-				jasmine.clock().mockDate(currentDate);
-			});
+    /**
+     * @test
+     */
+    describe('tests for getDate', function() {
+      var currentDate = new Date();
+      afterEach(function() {
+        jasmine.clock().mockDate(currentDate);
+      });
 
-			xit('works for year 2013', function () {
-				var baseTime = new Date(2013, 9, 23, 13, 13, 13);
-				jasmine.clock().mockDate(baseTime);
-				expect(FormEngineValidation.getDate(baseTime)).toBe(1382479200);
-			})
-		});
+      xit('works for year 2013', function() {
+        var baseTime = new Date(2013, 9, 23, 13, 13, 13);
+        jasmine.clock().mockDate(baseTime);
+        expect(FormEngineValidation.getDate(baseTime)).toBe(1382479200);
+      })
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for splitStr', function () {
-			it('works for command and index', function () {
-				expect(FormEngineValidation.splitStr('foo,bar,baz', ',', -1)).toBe('foo');
-				expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 0)).toBe('foo');
-				expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 1)).toBe('foo');
-				expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 2)).toBe('bar');
-				expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 3)).toBe('baz');
-				expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 1)).toBe(' foo ');
-				expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 2)).toBe(' bar ');
-				expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 3)).toBe(' baz ');
-			});
-		});
+    /**
+     * @test
+     */
+    describe('tests for splitStr', function() {
+      it('works for command and index', function() {
+        expect(FormEngineValidation.splitStr('foo,bar,baz', ',', -1)).toBe('foo');
+        expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 0)).toBe('foo');
+        expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 1)).toBe('foo');
+        expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 2)).toBe('bar');
+        expect(FormEngineValidation.splitStr('foo,bar,baz', ',', 3)).toBe('baz');
+        expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 1)).toBe(' foo ');
+        expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 2)).toBe(' bar ');
+        expect(FormEngineValidation.splitStr(' foo , bar , baz ', ',', 3)).toBe(' baz ');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		xdescribe('tests for split', function() {});
-	});
+    /**
+     * @test
+     */
+    xdescribe('tests for split', function() {
+    });
+  });
 });
diff --git a/typo3/sysext/backend/Tests/JavaScript/IconsTest.js b/typo3/sysext/backend/Tests/JavaScript/IconsTest.js
index 72a8dc65ac7f..cc0efde0bf60 100644
--- a/typo3/sysext/backend/Tests/JavaScript/IconsTest.js
+++ b/typo3/sysext/backend/Tests/JavaScript/IconsTest.js
@@ -1,74 +1,74 @@
 define(['jquery', 'TYPO3/CMS/Backend/Icons'], function($, Icons) {
-	'use strict';
+  'use strict';
 
-	describe('TYPO3/CMS/Backend/IconsTest:', function() {
-		/**
-		 * @test
-		 */
-		describe('tests for Icons object', function() {
-			it('has all sizes', function() {
-				expect(Icons.sizes.small).toBe('small');
-				expect(Icons.sizes.default).toBe('default');
-				expect(Icons.sizes.large).toBe('large');
-				expect(Icons.sizes.overlay).toBe('overlay');
-			});
-			it('has all states', function() {
-				expect(Icons.states.default).toBe('default');
-				expect(Icons.states.disabled).toBe('disabled');
-			});
-			it('has all markupIdentifiers', function() {
-				expect(Icons.markupIdentifiers.default).toBe('default');
-				expect(Icons.markupIdentifiers.inline).toBe('inline');
-			});
-		});
+  describe('TYPO3/CMS/Backend/IconsTest:', function() {
+    /**
+     * @test
+     */
+    describe('tests for Icons object', function() {
+      it('has all sizes', function() {
+        expect(Icons.sizes.small).toBe('small');
+        expect(Icons.sizes.default).toBe('default');
+        expect(Icons.sizes.large).toBe('large');
+        expect(Icons.sizes.overlay).toBe('overlay');
+      });
+      it('has all states', function() {
+        expect(Icons.states.default).toBe('default');
+        expect(Icons.states.disabled).toBe('disabled');
+      });
+      it('has all markupIdentifiers', function() {
+        expect(Icons.markupIdentifiers.default).toBe('default');
+        expect(Icons.markupIdentifiers.inline).toBe('inline');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for Icons::getIcon', function() {
-			beforeEach(function() {
-				spyOn(Icons, 'getIcon');
-				Icons.getIcon('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default);
-			});
+    /**
+     * @test
+     */
+    describe('tests for Icons::getIcon', function() {
+      beforeEach(function() {
+        spyOn(Icons, 'getIcon');
+        Icons.getIcon('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default);
+      });
 
-			it("tracks that the spy was called", function() {
-				expect(Icons.getIcon).toHaveBeenCalled();
-			});
-			it("tracks all the arguments of its calls", function() {
-				expect(Icons.getIcon).toHaveBeenCalledWith('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default);
-			});
-			xit('works get icon from remote server');
-		});
+      it("tracks that the spy was called", function() {
+        expect(Icons.getIcon).toHaveBeenCalled();
+      });
+      it("tracks all the arguments of its calls", function() {
+        expect(Icons.getIcon).toHaveBeenCalledWith('test', Icons.sizes.small, null, Icons.states.default, Icons.markupIdentifiers.default);
+      });
+      xit('works get icon from remote server');
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for Icons::putInCache', function() {
-			it('works for simply identifier and markup', function() {
-				Icons.putInCache('foo', 'bar');
-				expect(Icons.cache['foo']).toBe('bar');
-			});
-		});
+    /**
+     * @test
+     */
+    describe('tests for Icons::putInCache', function() {
+      it('works for simply identifier and markup', function() {
+        Icons.putInCache('foo', 'bar');
+        expect(Icons.cache['foo']).toBe('bar');
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for Icons::getFromCache', function() {
-			it('return undefined for uncached icon', function() {
-				expect(Icons.getFromCache('bar')).not.toBeDefined();
-			});
-		});
+    /**
+     * @test
+     */
+    describe('tests for Icons::getFromCache', function() {
+      it('return undefined for uncached icon', function() {
+        expect(Icons.getFromCache('bar')).not.toBeDefined();
+      });
+    });
 
-		/**
-		 * @test
-		 */
-		describe('tests for Icons::isCached', function() {
-			it('return true for cached icon', function() {
-				expect(Icons.isCached('foo')).toBe(true);
-			});
-			it('return false for uncached icon', function() {
-				expect(Icons.isCached('bar')).toBe(false);
-			});
-		});
-	});
+    /**
+     * @test
+     */
+    describe('tests for Icons::isCached', function() {
+      it('return true for cached icon', function() {
+        expect(Icons.isCached('foo')).toBe(true);
+      });
+      it('return false for uncached icon', function() {
+        expect(Icons.isCached('bar')).toBe(false);
+      });
+    });
+  });
 });
diff --git a/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js b/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js
index e213158757af..ceca7f6d44cf 100644
--- a/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js
+++ b/typo3/sysext/backend/Tests/JavaScript/PopoverTest.js
@@ -1,75 +1,75 @@
 define(['jquery', 'bootstrap', 'TYPO3/CMS/Backend/Popover'], function($, bootstrap, Popover) {
-	'use strict';
+  'use strict';
 
-	describe('TYPO3/CMS/Backend/PopoverTest:', function() {
-		/**
-		 * @test
-		 */
-		describe('initialize', function() {
-			var $body = $('body');
-			var $element = $('<div data-toggle="popover">');
-			$body.append($element);
-			it('works with default selector', function() {
-				Popover.initialize();
-				expect($element[0].outerHTML).toBe('<div data-toggle="popover" data-original-title="" title=""></div>');
-			});
+  describe('TYPO3/CMS/Backend/PopoverTest:', function() {
+    /**
+     * @test
+     */
+    describe('initialize', function() {
+      var $body = $('body');
+      var $element = $('<div data-toggle="popover">');
+      $body.append($element);
+      it('works with default selector', function() {
+        Popover.initialize();
+        expect($element[0].outerHTML).toBe('<div data-toggle="popover" data-original-title="" title=""></div>');
+      });
 
-			var $element2 = $('<div data-toggle="popover" data-title="foo">');
-			$body.append($element2);
-			it('works with default selector and title attribute', function() {
-				Popover.initialize();
-				expect($element2[0].outerHTML).toBe('<div data-toggle="popover" data-title="foo" data-original-title="" title=""></div>');
-			});
+      var $element2 = $('<div data-toggle="popover" data-title="foo">');
+      $body.append($element2);
+      it('works with default selector and title attribute', function() {
+        Popover.initialize();
+        expect($element2[0].outerHTML).toBe('<div data-toggle="popover" data-title="foo" data-original-title="" title=""></div>');
+      });
 
-			var $element3 = $('<div data-toggle="popover" data-content="foo">');
-			$body.append($element3);
-			it('works with default selector and content attribute', function() {
-				Popover.initialize();
-				expect($element3[0].outerHTML).toBe('<div data-toggle="popover" data-content="foo" data-original-title="" title=""></div>');
-			});
+      var $element3 = $('<div data-toggle="popover" data-content="foo">');
+      $body.append($element3);
+      it('works with default selector and content attribute', function() {
+        Popover.initialize();
+        expect($element3[0].outerHTML).toBe('<div data-toggle="popover" data-content="foo" data-original-title="" title=""></div>');
+      });
 
-			var $element4 = $('<div class="t3js-popover">');
-			$body.append($element4);
-			it('works with custom selector', function() {
-				Popover.initialize('.t3js-popover');
-				expect($element4[0].outerHTML).toBe('<div class="t3js-popover" data-original-title="" title=""></div>');
-			});
-		});
+      var $element4 = $('<div class="t3js-popover">');
+      $body.append($element4);
+      it('works with custom selector', function() {
+        Popover.initialize('.t3js-popover');
+        expect($element4[0].outerHTML).toBe('<div class="t3js-popover" data-original-title="" title=""></div>');
+      });
+    });
 
-		describe('call setOptions', function() {
-			var $body = $('body');
-			var $element = $('<div class="t3js-test-set-options" data-title="foo-title" data-content="foo-content">');
-			$body.append($element);
-			it('can set title', function() {
-				Popover.initialize('.t3js-test-set-options');
-				expect($element.attr('data-title')).toBe('foo-title');
-				expect($element.attr('data-content')).toBe('foo-content');
-				expect($element.attr('data-original-title')).toBe('');
-				expect($element.attr('title')).toBe('');
-				Popover.setOptions($element, {
-					'title': 'bar-title'
-				});
-				expect($element.attr('data-title')).toBe('foo-title');
-				expect($element.attr('data-content')).toBe('foo-content');
-				expect($element.attr('data-original-title')).toBe('bar-title');
-				expect($element.attr('title')).toBe('');
-			});
-			var $element2 = $('<div class="t3js-test-set-options2" data-title="foo-title" data-content="foo-content">');
-			$body.append($element2);
-			it('can set content', function() {
-				Popover.initialize('.t3js-test-set-options2');
-				expect($element2.attr('data-title')).toBe('foo-title');
-				expect($element2.attr('data-content')).toBe('foo-content');
-				expect($element2.attr('data-original-title')).toBe('');
-				expect($element2.attr('title')).toBe('');
-				Popover.setOptions($element2, {
-					'content': 'bar-content'
-				});
-				expect($element2.attr('data-title')).toBe('foo-title');
-				expect($element2.attr('data-content')).toBe('bar-content');
-				expect($element2.attr('data-original-title')).toBe('foo-title');
-				expect($element2.attr('title')).toBe('');
-			});
-		});
-	});
+    describe('call setOptions', function() {
+      var $body = $('body');
+      var $element = $('<div class="t3js-test-set-options" data-title="foo-title" data-content="foo-content">');
+      $body.append($element);
+      it('can set title', function() {
+        Popover.initialize('.t3js-test-set-options');
+        expect($element.attr('data-title')).toBe('foo-title');
+        expect($element.attr('data-content')).toBe('foo-content');
+        expect($element.attr('data-original-title')).toBe('');
+        expect($element.attr('title')).toBe('');
+        Popover.setOptions($element, {
+          'title': 'bar-title'
+        });
+        expect($element.attr('data-title')).toBe('foo-title');
+        expect($element.attr('data-content')).toBe('foo-content');
+        expect($element.attr('data-original-title')).toBe('bar-title');
+        expect($element.attr('title')).toBe('');
+      });
+      var $element2 = $('<div class="t3js-test-set-options2" data-title="foo-title" data-content="foo-content">');
+      $body.append($element2);
+      it('can set content', function() {
+        Popover.initialize('.t3js-test-set-options2');
+        expect($element2.attr('data-title')).toBe('foo-title');
+        expect($element2.attr('data-content')).toBe('foo-content');
+        expect($element2.attr('data-original-title')).toBe('');
+        expect($element2.attr('title')).toBe('');
+        Popover.setOptions($element2, {
+          'content': 'bar-content'
+        });
+        expect($element2.attr('data-title')).toBe('foo-title');
+        expect($element2.attr('data-content')).toBe('bar-content');
+        expect($element2.attr('data-original-title')).toBe('foo-title');
+        expect($element2.attr('title')).toBe('');
+      });
+    });
+  });
 });
diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js b/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js
index 6e3c1fc08d91..e0e59a66de3b 100644
--- a/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js
+++ b/typo3/sysext/beuser/Resources/Public/JavaScript/BackendUserListing.js
@@ -18,16 +18,16 @@
  */
 define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
 
-	var $searchFields = $('#tx_Beuser_username');
-	var searchResultShown = ('' !== $searchFields.first().val());
+  var $searchFields = $('#tx_Beuser_username');
+  var searchResultShown = ('' !== $searchFields.first().val());
 
-	// make search field clearable
-	$searchFields.clearable({
-		onClear: function() {
-			if (searchResultShown) {
-				$(this).closest('form').submit();
-			}
-		}
-	});
+  // make search field clearable
+  $searchFields.clearable({
+    onClear: function() {
+      if (searchResultShown) {
+        $(this).closest('form').submit();
+      }
+    }
+  });
 
 });
diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js
index 9ebe346606a0..f3eeb16c20bc 100644
--- a/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js
+++ b/typo3/sysext/beuser/Resources/Public/JavaScript/ContextMenuActions.js
@@ -17,30 +17,30 @@
  * JavaScript to handle permissions module from context menu
  * @exports TYPO3/CMS/Beuser/ContextMenuActions
  */
-define(function () {
-    'use strict';
+define(function() {
+  'use strict';
 
-    /**
-     * @exports TYPO3/CMS/Beuser/ContextMenuActions
-     */
-    var ContextMenuActions = {};
+  /**
+   * @exports TYPO3/CMS/Beuser/ContextMenuActions
+   */
+  var ContextMenuActions = {};
 
-    /**
-     * Open permission module for given uid
-     *
-     * @param {string} table
-     * @param {int} uid of the page
-     */
-    ContextMenuActions.openPermissionsModule = function (table, uid) {
-        if (table === 'pages') {
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.AccessPermissions.moduleUrl +
-                    '&id=' + uid +
-                    '&tx_beuser_system_beusertxpermission[action]=edit' +
-                    '&tx_beuser_system_beusertxpermission[controller]=Permission'
-            );
-        }
-    };
+  /**
+   * Open permission module for given uid
+   *
+   * @param {string} table
+   * @param {int} uid of the page
+   */
+  ContextMenuActions.openPermissionsModule = function(table, uid) {
+    if (table === 'pages') {
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.AccessPermissions.moduleUrl +
+        '&id=' + uid +
+        '&tx_beuser_system_beusertxpermission[action]=edit' +
+        '&tx_beuser_system_beusertxpermission[controller]=Permission'
+      );
+    }
+  };
 
-    return ContextMenuActions;
+  return ContextMenuActions;
 });
diff --git a/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js b/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js
index cb4999192018..78bdddb04418 100644
--- a/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js
+++ b/typo3/sysext/beuser/Resources/Public/JavaScript/Permissions.js
@@ -17,324 +17,324 @@
  */
 define(['jquery'], function($) {
 
-	/**
-	 *
-	 * @type {{options: {containerSelector: string}}}
-	 * @exports TYPO3/CMS/Beuser/Permissons
-	 */
-	var Permissions = {
-		options: {
-			containerSelector: '#typo3-permissionList'
-		}
-	};
-	var ajaxUrl = TYPO3.settings.ajaxUrls['user_access_permissions'];
+  /**
+   *
+   * @type {{options: {containerSelector: string}}}
+   * @exports TYPO3/CMS/Beuser/Permissons
+   */
+  var Permissions = {
+    options: {
+      containerSelector: '#typo3-permissionList'
+    }
+  };
+  var ajaxUrl = TYPO3.settings.ajaxUrls['user_access_permissions'];
 
-	/**
-	 * Changes the value of the permissions in the form
-	 *
-	 * @param {String} checknames
-	 * @param {String} varname
-	 */
-	Permissions.setCheck = function(checknames, varname) {
-		if (document.editform[varname]) {
-			var res = document.editform[varname].value;
-			for (var a = 1; a <= 5; a++) {
-				document.editform[checknames + '[' + a + ']'].checked = (res & Math.pow(2, a-1));
-			}
-		}
-	};
+  /**
+   * Changes the value of the permissions in the form
+   *
+   * @param {String} checknames
+   * @param {String} varname
+   */
+  Permissions.setCheck = function(checknames, varname) {
+    if (document.editform[varname]) {
+      var res = document.editform[varname].value;
+      for (var a = 1; a <= 5; a++) {
+        document.editform[checknames + '[' + a + ']'].checked = (res & Math.pow(2, a - 1));
+      }
+    }
+  };
 
-	/**
-	 * checks for a change of the permissions in the form
-	 *
-	 * @param {String} checknames
-	 * @param {String} varname
-	 */
-	Permissions.checkChange = function(checknames, varname) {
-		var res = 0;
-		for (var a = 1; a <= 5; a++) {
-			if (document.editform[checknames + '[' + a + ']'].checked) {
-				res |= Math.pow(2,a-1);
-			}
-		}
-		document.editform[varname].value = res | (checknames === 'tx_beuser_system_beusertxpermission[check][perms_user]' ? 1 : 0);
-		Permissions.setCheck(checknames, varname);
-	};
+  /**
+   * checks for a change of the permissions in the form
+   *
+   * @param {String} checknames
+   * @param {String} varname
+   */
+  Permissions.checkChange = function(checknames, varname) {
+    var res = 0;
+    for (var a = 1; a <= 5; a++) {
+      if (document.editform[checknames + '[' + a + ']'].checked) {
+        res |= Math.pow(2, a - 1);
+      }
+    }
+    document.editform[varname].value = res | (checknames === 'tx_beuser_system_beusertxpermission[check][perms_user]' ? 1 : 0);
+    Permissions.setCheck(checknames, varname);
+  };
 
-	/**
-	 * wrapper function to call a URL in the current frame
-	 */
-	Permissions.jumpToUrl = function(url) {
-		window.location.href = url;
-	};
+  /**
+   * wrapper function to call a URL in the current frame
+   */
+  Permissions.jumpToUrl = function(url) {
+    window.location.href = url;
+  };
 
-	/**
-	 * changes permissions by sending an AJAX request to the server
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.setPermissions = function($element) {
-		var page = $element.data('page');
-		var who = $element.data('who');
-		var elementSelector = '#' + page + '_' + who;
+  /**
+   * changes permissions by sending an AJAX request to the server
+   *
+   * @param {Object} $element
+   */
+  Permissions.setPermissions = function($element) {
+    var page = $element.data('page');
+    var who = $element.data('who');
+    var elementSelector = '#' + page + '_' + who;
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'page': page,
-				'who': who,
-				'permissions': $element.data('permissions'),
-				'mode': $element.data('mode'),
-				'bits': $element.data('bits')
-			}
-		}).done(function(data) {
-			// Replace content
-			$(elementSelector).replaceWith(data);
-			// Reinitialize tooltip
-			$(elementSelector).find('span').tooltip();
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'page': page,
+        'who': who,
+        'permissions': $element.data('permissions'),
+        'mode': $element.data('mode'),
+        'bits': $element.data('bits')
+      }
+    }).done(function(data) {
+      // Replace content
+      $(elementSelector).replaceWith(data);
+      // Reinitialize tooltip
+      $(elementSelector).find('span').tooltip();
+    });
+  };
 
-	/**
-	 * changes the flag to lock the editing on a page by sending an AJAX request
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.toggleEditLock = function($element) {
-		var page = $element.data('page');
+  /**
+   * changes the flag to lock the editing on a page by sending an AJAX request
+   *
+   * @param {Object} $element
+   */
+  Permissions.toggleEditLock = function($element) {
+    var page = $element.data('page');
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'action': 'toggle_edit_lock',
-				'page': page,
-				'editLockState': $element.data('lockstate')
-			}
-		}).done(function(data) {
-			// Replace content
-			$('#el_' + page).replaceWith(data);
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'action': 'toggle_edit_lock',
+        'page': page,
+        'editLockState': $element.data('lockstate')
+      }
+    }).done(function(data) {
+      // Replace content
+      $('#el_' + page).replaceWith(data);
+    });
+  };
 
-	/**
-	 * Owner-related: Set the new owner of a page by executing an ajax call
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.changeOwner = function($element) {
-		var page = $element.data('page');
+  /**
+   * Owner-related: Set the new owner of a page by executing an ajax call
+   *
+   * @param {Object} $element
+   */
+  Permissions.changeOwner = function($element) {
+    var page = $element.data('page');
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'action': 'change_owner',
-				'page': page,
-				'ownerUid': $element.data('owner'),
-				'newOwnerUid': $('#new_page_owner').val()
-			}
-		}).done(function(data) {
-			// Replace content
-			$('#o_' + page).replaceWith(data);
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'action': 'change_owner',
+        'page': page,
+        'ownerUid': $element.data('owner'),
+        'newOwnerUid': $('#new_page_owner').val()
+      }
+    }).done(function(data) {
+      // Replace content
+      $('#o_' + page).replaceWith(data);
+    });
+  };
 
-	/**
-	 * Owner-related: load the selector for selecting
-	 * the owner of a page by executing an ajax call
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.showChangeOwnerSelector = function($element) {
-		var page = $element.data('page');
+  /**
+   * Owner-related: load the selector for selecting
+   * the owner of a page by executing an ajax call
+   *
+   * @param {Object} $element
+   */
+  Permissions.showChangeOwnerSelector = function($element) {
+    var page = $element.data('page');
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'action': 'show_change_owner_selector',
-				'page': page,
-				'ownerUid': $element.data('owner'),
-				'username': $element.data('username')
-			}
-		}).done(function(data) {
-			// Replace content
-			$('#o_' + page).replaceWith(data);
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'action': 'show_change_owner_selector',
+        'page': page,
+        'ownerUid': $element.data('owner'),
+        'username': $element.data('username')
+      }
+    }).done(function(data) {
+      // Replace content
+      $('#o_' + page).replaceWith(data);
+    });
+  };
 
-	/**
-	 * Owner-related: Update the HTML view and show the original owner
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.restoreOwner = function($element) {
-		var page = $element.data('page');
-		var username = $element.data('username');
-		var usernameHtml = username;
-		if (typeof username === 'undefined') {
-			username = $('<span>', {
-				'class': 'not_set',
-				'text': '[not set]'
-			});
-			usernameHtml = username.html();
-			username = username.text();
-		}
+  /**
+   * Owner-related: Update the HTML view and show the original owner
+   *
+   * @param {Object} $element
+   */
+  Permissions.restoreOwner = function($element) {
+    var page = $element.data('page');
+    var username = $element.data('username');
+    var usernameHtml = username;
+    if (typeof username === 'undefined') {
+      username = $('<span>', {
+        'class': 'not_set',
+        'text': '[not set]'
+      });
+      usernameHtml = username.html();
+      username = username.text();
+    }
 
-		var html = $('<span/>', {
-			'id': 'o_' + page
-		});
-		var aSelector = $('<a/>', {
-			'class': 'ug_selector changeowner',
-			'data-page': page,
-			'data-owner': $element.data('owner'),
-			'data-username': usernameHtml,
-			'text': username
-		});
-		html.append(aSelector);
+    var html = $('<span/>', {
+      'id': 'o_' + page
+    });
+    var aSelector = $('<a/>', {
+      'class': 'ug_selector changeowner',
+      'data-page': page,
+      'data-owner': $element.data('owner'),
+      'data-username': usernameHtml,
+      'text': username
+    });
+    html.append(aSelector);
 
-		// Replace content
-		$('#o_' + page).replaceWith(html);
-	};
+    // Replace content
+    $('#o_' + page).replaceWith(html);
+  };
 
-	/**
-	 * Group-related: Set the new group by executing an ajax call
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.changeGroup = function($element) {
-		var page = $element.data('page');
+  /**
+   * Group-related: Set the new group by executing an ajax call
+   *
+   * @param {Object} $element
+   */
+  Permissions.changeGroup = function($element) {
+    var page = $element.data('page');
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'action': 'change_group',
-				'page': page,
-				'groupUid': $element.data('groupId'),
-				'newGroupUid': $('#new_page_group').val()
-			}
-		}).done(function(data) {
-			// Replace content
-			$('#g_' + page).replaceWith(data);
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'action': 'change_group',
+        'page': page,
+        'groupUid': $element.data('groupId'),
+        'newGroupUid': $('#new_page_group').val()
+      }
+    }).done(function(data) {
+      // Replace content
+      $('#g_' + page).replaceWith(data);
+    });
+  };
 
-	/**
-	 * Group-related: Load the selector by executing an ajax call
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.showChangeGroupSelector = function($element) {
-		var page = $element.data('page');
+  /**
+   * Group-related: Load the selector by executing an ajax call
+   *
+   * @param {Object} $element
+   */
+  Permissions.showChangeGroupSelector = function($element) {
+    var page = $element.data('page');
 
-		$.ajax({
-			url: ajaxUrl,
-			type: 'post',
-			dataType: 'html',
-			cache: false,
-			data: {
-				'action': 'show_change_group_selector',
-				'page': page,
-				'groupUid': $element.data('groupId'),
-				'groupname': $element.data('groupname')
-			}
-		}).done(function(data) {
-			// Replace content
-			$('#g_' + page).replaceWith(data);
-		});
-	};
+    $.ajax({
+      url: ajaxUrl,
+      type: 'post',
+      dataType: 'html',
+      cache: false,
+      data: {
+        'action': 'show_change_group_selector',
+        'page': page,
+        'groupUid': $element.data('groupId'),
+        'groupname': $element.data('groupname')
+      }
+    }).done(function(data) {
+      // Replace content
+      $('#g_' + page).replaceWith(data);
+    });
+  };
 
-	/**
-	 * Group-related: Update the HTML view and show the original group
-	 *
-	 * @param {Object} $element
-	 */
-	Permissions.restoreGroup = function($element) {
-		var page = $element.data('page');
-		var groupname = $element.data('groupname');
-		var groupnameHtml = groupname;
-		if (typeof groupname === 'undefined') {
-			groupname = $('<span>', {
-				'class': 'not_set',
-				'text': '[not set]'
-			});
-			groupnameHtml = groupname.html();
-			groupname = groupname.text();
-		}
-		var html = $('<span/>', {
-			'id': 'g_' + page
-		});
-		var aSelector = $('<a/>', {
-			'class': 'ug_selector changegroup',
-			'data-page': page,
-			'data-group': $element.data('groupId'),
-			'data-groupname': groupnameHtml,
-			'text': groupname
-		});
-		html.append(aSelector);
+  /**
+   * Group-related: Update the HTML view and show the original group
+   *
+   * @param {Object} $element
+   */
+  Permissions.restoreGroup = function($element) {
+    var page = $element.data('page');
+    var groupname = $element.data('groupname');
+    var groupnameHtml = groupname;
+    if (typeof groupname === 'undefined') {
+      groupname = $('<span>', {
+        'class': 'not_set',
+        'text': '[not set]'
+      });
+      groupnameHtml = groupname.html();
+      groupname = groupname.text();
+    }
+    var html = $('<span/>', {
+      'id': 'g_' + page
+    });
+    var aSelector = $('<a/>', {
+      'class': 'ug_selector changegroup',
+      'data-page': page,
+      'data-group': $element.data('groupId'),
+      'data-groupname': groupnameHtml,
+      'text': groupname
+    });
+    html.append(aSelector);
 
-		// Replace content
-		$('#g_' + page).replaceWith(html);
-	};
+    // Replace content
+    $('#g_' + page).replaceWith(html);
+  };
 
-	/**
-	 * initializes events using deferred bound to document
-	 * so AJAX reloads are no problem
-	 */
-	Permissions.initializeEvents = function() {
+  /**
+   * initializes events using deferred bound to document
+   * so AJAX reloads are no problem
+   */
+  Permissions.initializeEvents = function() {
 
-		// Click event to change permissions
-		$(Permissions.options.containerSelector).on('click', '.change-permission', function(evt) {
-			evt.preventDefault();
-			Permissions.setPermissions($(this));
-		}).on('click', '.editlock', function(evt) {
-			// Click event for lock state
-			evt.preventDefault();
-			Permissions.toggleEditLock($(this));
-		}).on('click', '.changeowner', function(evt) {
-			// Click event to change owner
-			evt.preventDefault();
-			Permissions.showChangeOwnerSelector($(this));
-		}).on('click', '.changegroup', function(evt) {
-			// click event to change group
-			evt.preventDefault();
-			Permissions.showChangeGroupSelector($(this));
-		}).on('click', '.restoreowner', function(evt) {
-			// Add click handler for restoring previous owner
-			evt.preventDefault();
-			Permissions.restoreOwner($(this));
-		}).on('click', '.saveowner', function(evt) {
-			// Add click handler for saving owner
-			evt.preventDefault();
-			Permissions.changeOwner($(this));
-		}).on('click', '.restoregroup', function(evt) {
-			// Add click handler for restoring previous group
-			evt.preventDefault();
-			Permissions.restoreGroup($(this));
-		}).on('click', '.savegroup', function(evt) {
-			// Add click handler for saving group
-			evt.preventDefault();
-			Permissions.changeGroup($(this));
-		});
-	};
+    // Click event to change permissions
+    $(Permissions.options.containerSelector).on('click', '.change-permission', function(evt) {
+      evt.preventDefault();
+      Permissions.setPermissions($(this));
+    }).on('click', '.editlock', function(evt) {
+      // Click event for lock state
+      evt.preventDefault();
+      Permissions.toggleEditLock($(this));
+    }).on('click', '.changeowner', function(evt) {
+      // Click event to change owner
+      evt.preventDefault();
+      Permissions.showChangeOwnerSelector($(this));
+    }).on('click', '.changegroup', function(evt) {
+      // click event to change group
+      evt.preventDefault();
+      Permissions.showChangeGroupSelector($(this));
+    }).on('click', '.restoreowner', function(evt) {
+      // Add click handler for restoring previous owner
+      evt.preventDefault();
+      Permissions.restoreOwner($(this));
+    }).on('click', '.saveowner', function(evt) {
+      // Add click handler for saving owner
+      evt.preventDefault();
+      Permissions.changeOwner($(this));
+    }).on('click', '.restoregroup', function(evt) {
+      // Add click handler for restoring previous group
+      evt.preventDefault();
+      Permissions.restoreGroup($(this));
+    }).on('click', '.savegroup', function(evt) {
+      // Add click handler for saving group
+      evt.preventDefault();
+      Permissions.changeGroup($(this));
+    });
+  };
 
-	$(Permissions.initializeEvents);
+  $(Permissions.initializeEvents);
 
-	// expose to global
-	TYPO3.Permissions = Permissions;
+  // expose to global
+  TYPO3.Permissions = Permissions;
 
-	return Permissions;
+  return Permissions;
 });
diff --git a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js
index 43a0292d4ae4..82332ad760f9 100644
--- a/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js
+++ b/typo3/sysext/documentation/Resources/Public/JavaScript/Main.js
@@ -16,135 +16,135 @@
  * JavaScript module for ext:documentation
  */
 define(['jquery', 'datatables', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Notification', 'TYPO3/CMS/Backend/Severity', 'TYPO3/CMS/Backend/jquery.clearable'], function($, DataTable, Modal, Notification, Severity) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string, deleteButtons: string}}}
-	 * @exports TYPO3/CMS/Documentation/Main
-	 */
-	var Documentation = {
-		dataTable: null,
-		searchField: null,
-		identifier: {
-			documentationList: '.t3js-documentation-list',
-			searchField: '.t3js-documentation-searchfield',
-			deleteButtons: '.t3js-documentation-delete'
-		}
-	};
+  /**
+   *
+   * @type {{dataTable: null, searchField: null, identifier: {documentationList: string, searchField: string, deleteButtons: string}}}
+   * @exports TYPO3/CMS/Documentation/Main
+   */
+  var Documentation = {
+    dataTable: null,
+    searchField: null,
+    identifier: {
+      documentationList: '.t3js-documentation-list',
+      searchField: '.t3js-documentation-searchfield',
+      deleteButtons: '.t3js-documentation-delete'
+    }
+  };
 
-	/**
-	 *  Initializes the data table, depending on the current view
-	 */
-	Documentation.initializeView = function() {
-		var getVars = Documentation.getUrlVars();
-		// init datatable
-		this.dataTable = $(this.identifier.documentationList).DataTable({
-			paging: false,
-			dom: 'lrtip',
-			lengthChange: false,
-			pageLength: 15,
-			stateSave: true,
-			order: [[ 1, 'asc' ]]
-		});
-		// search field
-		this.searchField = $(this.identifier.searchField);
-		if (this.dataTable && this.searchField.length) {
-			this.searchField.parents('form').on('submit', function() {
-				return false;
-			});
-			var currentSearch = (getVars['search'] ? getVars['search'] : this.dataTable.search());
-			this.searchField.val(currentSearch);
-			this.searchField.on('input', function(e) {
-				Documentation.dataTable.search($(this).val()).draw();
-			});
-		}
-	};
+  /**
+   *  Initializes the data table, depending on the current view
+   */
+  Documentation.initializeView = function() {
+    var getVars = Documentation.getUrlVars();
+    // init datatable
+    this.dataTable = $(this.identifier.documentationList).DataTable({
+      paging: false,
+      dom: 'lrtip',
+      lengthChange: false,
+      pageLength: 15,
+      stateSave: true,
+      order: [[1, 'asc']]
+    });
+    // search field
+    this.searchField = $(this.identifier.searchField);
+    if (this.dataTable && this.searchField.length) {
+      this.searchField.parents('form').on('submit', function() {
+        return false;
+      });
+      var currentSearch = (getVars['search'] ? getVars['search'] : this.dataTable.search());
+      this.searchField.val(currentSearch);
+      this.searchField.on('input', function(e) {
+        Documentation.dataTable.search($(this).val()).draw();
+      });
+    }
+  };
 
-	/**
-	 * Utility method to retrieve query parameters
-	 *
-	 * @returns {Array}
-	 */
-	Documentation.getUrlVars = function getUrlVars() {
-		var vars = [], hash;
-		var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
-		for (var i = 0; i < hashes.length; i++) {
-			hash = hashes[i].split('=');
-			vars.push(hash[0]);
-			vars[hash[0]] = hash[1];
-		}
-		return vars;
-	};
+  /**
+   * Utility method to retrieve query parameters
+   *
+   * @returns {Array}
+   */
+  Documentation.getUrlVars = function getUrlVars() {
+    var vars = [], hash;
+    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+    for (var i = 0; i < hashes.length; i++) {
+      hash = hashes[i].split('=');
+      vars.push(hash[0]);
+      vars[hash[0]] = hash[1];
+    }
+    return vars;
+  };
 
-	/**
-	 * Delete documentation
-	 *
-	 * @param {Object} $documentationRecord
-	 */
-	Documentation.deleteDocumentation = function($documentationRecord) {
+  /**
+   * Delete documentation
+   *
+   * @param {Object} $documentationRecord
+   */
+  Documentation.deleteDocumentation = function($documentationRecord) {
 
-		Modal.confirm($documentationRecord.data('documentationName'), $documentationRecord.data('documentationDeleteDescription'), Severity.warning, [
-			{
-				text: TYPO3.lang['cancel'],
-				active: true,
-				btnClass: 'btn-default',
-				trigger: function() {
-					Modal.dismiss();
-				}
-			}, {
-				text: TYPO3.lang['delete'],
-				btnClass: 'btn-info',
-				trigger: function() {
-					$.ajax({
-						url: TYPO3.settings.ajaxUrls['documentation_remove'],
-						data: {
-							documentationKey: $documentationRecord.data('documentationKey')
-						},
-						type: 'post',
-						cache: false
-					}).done(function(data) {
-						if(data) {
-							$documentationRecord.closest('tr').fadeOut();
-						} else {
-							Documentation.handleErrors(data);
-						}
-					});
-					Modal.dismiss();
-				}
-			}
-		]);
+    Modal.confirm($documentationRecord.data('documentationName'), $documentationRecord.data('documentationDeleteDescription'), Severity.warning, [
+      {
+        text: TYPO3.lang['cancel'],
+        active: true,
+        btnClass: 'btn-default',
+        trigger: function() {
+          Modal.dismiss();
+        }
+      }, {
+        text: TYPO3.lang['delete'],
+        btnClass: 'btn-info',
+        trigger: function() {
+          $.ajax({
+            url: TYPO3.settings.ajaxUrls['documentation_remove'],
+            data: {
+              documentationKey: $documentationRecord.data('documentationKey')
+            },
+            type: 'post',
+            cache: false
+          }).done(function(data) {
+            if (data) {
+              $documentationRecord.closest('tr').fadeOut();
+            } else {
+              Documentation.handleErrors(data);
+            }
+          });
+          Modal.dismiss();
+        }
+      }
+    ]);
 
-	};
+  };
 
-	/**
-	 * handle the errors from result object
-	 *
-	 * @param {Object} result
-	 * @private
-	 */
-	Documentation.handleErrors = function(result) {
-		$.each(result.messages, function(position, message) {
-			Notification.error(message.title, message.message);
-		});
-	};
+  /**
+   * handle the errors from result object
+   *
+   * @param {Object} result
+   * @private
+   */
+  Documentation.handleErrors = function(result) {
+    $.each(result.messages, function(position, message) {
+      Notification.error(message.title, message.message);
+    });
+  };
 
-	$(function() {
-		// Initialize the view
-		Documentation.initializeView();
+  $(function() {
+    // Initialize the view
+    Documentation.initializeView();
 
-		// Make the data table filter react to the clearing of the filter field
-		$(Documentation.identifier.searchField).clearable({
-			onClear: function() {
-				Documentation.dataTable.search('').draw();
-			}
-		});
-		$(Documentation.identifier.deleteButtons).on('click', function(e) {
-			e.preventDefault();
-			e.stopPropagation();
-			Documentation.deleteDocumentation($(this));
-		})
-	});
+    // Make the data table filter react to the clearing of the filter field
+    $(Documentation.identifier.searchField).clearable({
+      onClear: function() {
+        Documentation.dataTable.search('').draw();
+      }
+    });
+    $(Documentation.identifier.deleteButtons).on('click', function(e) {
+      e.preventDefault();
+      e.stopPropagation();
+      Documentation.deleteDocumentation($(this));
+    })
+  });
 
-	return Documentation;
+  return Documentation;
 });
diff --git a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js
index ade1fd321efd..73aa6675424b 100644
--- a/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js
+++ b/typo3/sysext/extensionmanager/Resources/Public/JavaScript/Main.js
@@ -19,712 +19,716 @@
  * ExtensionManager.uploadForm => helper to show the upload form
  */
 define([
-	'jquery',
-	'nprogress',
-	'TYPO3/CMS/Backend/Modal',
-	'TYPO3/CMS/Backend/SplitButtons',
-	'TYPO3/CMS/Backend/Tooltip',
-	'TYPO3/CMS/Backend/Notification',
-	'TYPO3/CMS/Backend/Severity',
-	'datatables',
-	'TYPO3/CMS/Backend/jquery.clearable'
+  'jquery',
+  'nprogress',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/SplitButtons',
+  'TYPO3/CMS/Backend/Tooltip',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Severity',
+  'datatables',
+  'TYPO3/CMS/Backend/jquery.clearable'
 ], function($, NProgress, Modal, SplitButtons, Tooltip, Notification, Severity) {
 
-	/**
-	 *
-	 * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}}
-	 * @exports TYPO3/CMS/Extensionmanager/Main
-	 */
-	var ExtensionManager = {
-		identifier: {
-			extensionlist: '#typo3-extension-list',
-			searchField: '#Tx_Extensionmanager_extensionkey'
-		}
-	};
-
-	/**
-	 *
-	 * @returns {Object}
-	 */
-	ExtensionManager.manageExtensionListing = function() {
-		var $searchField = $(this.identifier.searchField),
-			dataTable = $(this.identifier.extensionlist).DataTable({
-				paging: false,
-				dom: 'lrtip',
-				lengthChange: false,
-				pageLength: 15,
-				stateSave: true,
-				drawCallback: this.bindExtensionListActions,
-				columns: [
-					null,
-					null,
-					{
-						type: 'extension'
-					},
-					null,
-					{
-						type: 'version'
-					}, {
-						orderable: false
-					},
-					null,
-					null
-				]
-			});
-
-		$searchField.parents('form').on('submit', function() {
-			return false;
-		});
-
-		var getVars = ExtensionManager.getUrlVars();
-
-		// restore filter
-		var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search());
-		$searchField.val(currentSearch);
-
-		$searchField.on('input', function(e) {
-			dataTable.search($(this).val()).draw();
-		});
-
-		return dataTable;
-	};
-
-	/**
-	 *
-	 */
-	ExtensionManager.bindExtensionListActions = function() {
-		$('.removeExtension').not('.transformed').each(function() {
-			var $me = $(this);
-			$me.data('href', $me.attr('href'));
-			$me.attr('href', '#');
-			$me.addClass('transformed');
-			$me.click(function() {
-				Modal.confirm(
-					TYPO3.lang['extensionList.removalConfirmation.title'],
-					TYPO3.lang['extensionList.removalConfirmation.question'],
-					Severity.error,
-					[
-						{
-							text: TYPO3.lang['button.cancel'],
-							active: true,
-							btnClass: 'btn-default',
-							trigger: function() {
-								Modal.dismiss();
-							}
-						}, {
-							text: TYPO3.lang['button.remove'],
-							btnClass: 'btn-danger',
-							trigger: function() {
-								ExtensionManager.removeExtensionFromDisk($me);
-								Modal.dismiss();
-							}
-						}
-					]
-				);
-			});
-		});
-	};
-
-	/**
-	 *
-	 * @param {Object} $extension
-	 */
-	ExtensionManager.removeExtensionFromDisk = function($extension) {
-		$.ajax({
-			url: $extension.data('href'),
-			beforeSend: function() {
-				NProgress.start();
-			},
-			success: function() {
-				location.reload();
-			},
-			complete: function() {
-				NProgress.done();
-			}
-		});
-	};
-
-	/**
-	 *
-	 * @returns {Array}
-	 */
-	ExtensionManager.getUrlVars = function() {
-		var vars = [], hash;
-		var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
-		for (var i = 0; i < hashes.length; i++) {
-			hash = hashes[i].split('=');
-			vars.push(hash[0]);
-			vars[hash[0]] = hash[1];
-		}
-		return vars;
-	};
-
-	$.fn.dataTableExt.oSort['extension-asc'] = function(a, b) {
-		return ExtensionManager.extensionCompare(a, b);
-	};
-
-	$.fn.dataTableExt.oSort['extension-desc'] = function(a, b) {
-		var result = ExtensionManager.extensionCompare(a, b);
-		return result * -1;
-	};
-
-	$.fn.dataTableExt.oSort['version-asc'] = function(a, b) {
-		var result = ExtensionManager.versionCompare(a, b);
-		return result * -1;
-	};
-
-	$.fn.dataTableExt.oSort['version-desc'] = function(a, b) {
-		return ExtensionManager.versionCompare(a, b);
-	};
-
-	/**
-	 * Special sorting for the extension version column
-	 *
-	 * @param {String} a
-	 * @param {String} b
-	 * @returns {Number}
-	 */
-	ExtensionManager.versionCompare = function(a, b) {
-		if (a === b) {
-			return 0;
-		}
-
-		var a_components = a.split(".");
-		var b_components = b.split(".");
-
-		var len = Math.min(a_components.length, b_components.length);
-
-		// loop while the components are equal
-		for (var i = 0; i < len; i++) {
-			// A bigger than B
-			if (parseInt(a_components[i]) > parseInt(b_components[i])) {
-				return 1;
-			}
-
-			// B bigger than A
-			if (parseInt(a_components[i]) < parseInt(b_components[i])) {
-				return -1;
-			}
-		}
-
-		// If one's a prefix of the other, the longer one is greaRepository.
-		if (a_components.length > b_components.length) {
-			return 1;
-		}
-
-		if (a_components.length < b_components.length) {
-			return -1;
-		}
-		// Otherwise they are the same.
-		return 0;
-	};
-
-	/**
-	 * The extension name column can contain various forms of HTML that
-	 * break a direct comparison of values
-	 *
-	 * @param {String} a
-	 * @param {String} b
-	 * @returns {Number}
-	 */
-	ExtensionManager.extensionCompare = function(a, b) {
-		var div = document.createElement("div");
-		div.innerHTML = a;
-		var aStr = div.textContent || div.innerText || a;
-
-		div.innerHTML = b;
-		var bStr = div.textContent || div.innerText || b;
-
-		return aStr.trim().localeCompare(bStr.trim());
-	}
-
-	/**
-	 *
-	 * @param {Object} data
-	 */
-	ExtensionManager.updateExtension = function(data) {
-		var message = '<h1>' + TYPO3.lang['extensionList.updateConfirmation.title'] + '</h1>';
-		message += '<h2>' + TYPO3.lang['extensionList.updateConfirmation.message'] + '</h2>';
-		message += '<form>';
-		var i = 0;
-		$.each(data.updateComments, function(version, comment) {
-			comment = comment.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2');
-			message += '<h3><input type="radio" ' + (i === 0 ? 'checked="checked" ' : '') + 'name="version" value="' + version + '" /> ' + version + '</h3>';
-			message += '<div>' + comment + '</div>';
-			i++;
-		});
-		message += '</form>';
-
-		NProgress.done();
-
-		Modal.confirm(
-			TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'],
-			message,
-			Severity.warning,
-			[
-				{
-					text: TYPO3.lang['button.cancel'],
-					active: true,
-					btnClass: 'btn-default',
-					trigger: function() {
-						Modal.dismiss();
-					}
-				}, {
-					text: TYPO3.lang['button.updateExtension'],
-					btnClass: 'btn-warning',
-					trigger: function() {
-						$.ajax({
-							url: data.url,
-							data: {
-								tx_extensionmanager_tools_extensionmanagerextensionmanager: {
-									version: $('input:radio[name=version]:checked', Modal.currentModal).val()
-								}
-							},
-							dataType: 'json',
-							beforeSend: function() {
-								NProgress.start();
-							},
-							complete: function() {
-								location.reload();
-							}
-						});
-						Modal.dismiss();
-					}
-				}
-			]
-		);
-	};
-
-	/**
-	 *
-	 * @type {{downloadPath: string}}
-	 */
-	var Repository = {
-		downloadPath: ''
-	};
-
-	/**
-	 *
-	 */
-	Repository.initDom = function() {
-		NProgress.configure({parent: '.module-loading-indicator', showSpinner: false});
-
-		$('#terTable').DataTable({
-			lengthChange: false,
-			pageLength: 15,
-			stateSave: false,
-			info: false,
-			paging: false,
-			searching: false,
-			ordering: false,
-			drawCallback: Repository.bindDownload
-		});
-
-		$('#terVersionTable').DataTable({
-			lengthChange: false,
-			pageLength: 15,
-			stateSave: false,
-			info: false,
-			paging: false,
-			searching: false,
-			drawCallback: Repository.bindDownload,
-			order: [
-				[2, 'asc']
-			],
-			columns: [
-				{orderable: false},
-				null,
-				{type: 'version'},
-				null,
-				null,
-				null
-			]
-		});
-
-		$('#terSearchTable').DataTable({
-			paging: false,
-			lengthChange: false,
-			stateSave: false,
-			searching: false,
-			language: {
-				search: 'Filter results:'
-			},
-			ordering: false,
-			drawCallback: Repository.bindDownload
-		});
-
-		Repository.bindDownload();
-		Repository.bindSearchFieldResetter();
-	};
-
-	/**
-	 *
-	 */
-	Repository.bindDownload = function() {
-		var installButtons = $('.downloadFromTer form.download button[type=submit]');
-		installButtons.off('click');
-		installButtons.on('click', function(event) {
-			event.preventDefault();
-			var url = $(event.currentTarget.form).attr('data-href');
-			Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val();
-			$.ajax({
-				url: url,
-				dataType: 'json',
-				beforeSend: function() {
-					NProgress.start();
-				},
-				success: Repository.getDependencies
-			});
-		});
-	};
-
-	/**
-	 *
-	 * @param {Object} data
-	 * @returns {Boolean}
-	 */
-	Repository.getDependencies = function(data) {
-		NProgress.done();
-		if (data.hasDependencies) {
-			Modal.confirm(data.title, data.message, Severity.info, [
-				{
-					text: TYPO3.lang['button.cancel'],
-					active: true,
-					btnClass: 'btn-default',
-					trigger: function() {
-						Modal.dismiss();
-					}
-				}, {
-					text: TYPO3.lang['button.resolveDependencies'],
-					btnClass: 'btn-info',
-					trigger: function() {
-						Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
-						Modal.dismiss();
-					}
-				}
-			]);
-		} else {
-			if(data.hasErrors) {
-				Notification.error(data.title, data.message, 15);
-			} else {
-				Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
-			}
-		}
-		return false;
-	};
-
-	/**
-	 *
-	 * @param {String} url
-	 */
-	Repository.getResolveDependenciesAndInstallResult = function(url) {
-		$.ajax({
-			url: url,
-			dataType: 'json',
-			beforeSend: function() {
-				NProgress.start();
-			},
-			success: function (data) {
-				if (data.errorCount > 0) {
-					Modal.confirm(data.errorTitle, data.errorMessage, Severity.error, [
-						{
-							text: TYPO3.lang['button.cancel'],
-							active: true,
-							btnClass: 'btn-default',
-							trigger: function() {
-								Modal.dismiss();
-							}
-						}, {
-							text: TYPO3.lang['button.resolveDependenciesIgnore'],
-							btnClass: 'btn-danger disabled t3js-dependencies',
-							trigger: function() {
-								if (!$(this).hasClass('disabled')) {
-									Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri);
-									Modal.dismiss();
-								}
-							}
-						}
-					]);
-					Modal.currentModal.on('shown.bs.modal', function() {
-						var $actionButton = Modal.currentModal.find('.t3js-dependencies');
-						$('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() {
-							$actionButton.toggleClass('disabled', !$(this).prop('checked'));
-						});
-					});
-				} else {
-					var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension);
-
-					successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': ';
-					$.each(data.result, function(index, value) {
-						successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': ';
-						$.each(value, function(extkey) {
-							successMessage += '\n* ' + extkey
-						});
-					});
-					Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15);
-					top.TYPO3.ModuleMenu.App.refreshMenu();
-				}
-			},
-			complete: function() {
-				NProgress.done();
-			}
-		});
-	};
-
-	/**
-	 *
-	 */
-	Repository.bindSearchFieldResetter = function() {
-		var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]');
-		var searchResultShown = ('' !== $searchFields.first().val());
-
-		$searchFields.clearable(
-			{
-				onClear: function() {
-					if (searchResultShown) {
-						$(this).closest('form').submit();
-					}
-				}
-			}
-		);
-	};
-
-	/**
-	 *
-	 * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}}
-	 */
-	ExtensionManager.Update = {
-		identifier: {
-			extensionTable: '#terTable',
-			terUpdateAction: '.update-from-ter',
-			pagination: '.pagination-wrap',
-			splashscreen: '.splash-receivedata',
-			terTableWrapper: '#terTableWrapper',
-			terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper'
-		}
-	};
-
-	/**
-	 * Register "update from ter" action
-	 */
-	ExtensionManager.Update.initializeEvents = function() {
-		$(ExtensionManager.Update.identifier.terUpdateAction).each(function() {
-
-			// "this" is the form which updates the extension list from
-			// TER on submit
-			var $me = $(this),
-				updateURL = $(this).attr('action');
-
-			$me.attr('action', '#');
-			$me.submit(function() {
-				// Force update on click.
-				ExtensionManager.Update.updateFromTer(updateURL, true);
-
-				// Prevent normal submit action.
-				return false;
-			});
-
-			// This might give problems when there are more "update"-buttons,
-			// each one would trigger a TER-ExtensionManager.Update.
-			ExtensionManager.Update.updateFromTer(updateURL, false);
-		});
-	};
-
-	/**
-	 *
-	 * @param {String} url
-	 * @param {Boolean} forceUpdate
-	 */
-	ExtensionManager.Update.updateFromTer = function(url, forceUpdate) {
-		if (forceUpdate) {
-			url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1';
-		}
-
-		// Hide triggers for TER update
-		$(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden');
-
-		// Hide extension table
-		$(ExtensionManager.Update.identifier.extensionTable).hide();
-
-		// Show loaders
-		$(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown');
-		$(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading');
-		$(ExtensionManager.Update.identifier.pagination).addClass('is-loading');
-
-		var reload = false;
-
-		$.ajax({
-			url: url,
-			dataType: 'json',
-			cache: false,
-			beforeSend: function() {
-				NProgress.start();
-			},
-			success: function(data) {
-				// Something went wrong, show message
-				if (data.errorMessage.length) {
-					Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10);
-				}
-
-				// Message with latest updates
-				var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update');
-				$lastUpdate.text(data.timeSinceLastUpdate);
-				$lastUpdate.attr(
-					'title',
-					TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime
-				);
-
-				if (data.updated) {
-					// Reload page
-					reload = true;
-					window.location.replace(window.location.href);
-				}
-			},
-			error: function(jqXHR, textStatus, errorThrown) {
-				// Create an error message with diagnosis info.
-				var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText;
-
-				Notification.warning(
-					TYPO3.lang['extensionList.updateFromTerFlashMessage.title'],
-					errorMessage,
-					10
-				);
-			},
-			complete: function() {
-				NProgress.done();
-
-				if (!reload) {
-					// Hide loaders
-					$(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown');
-					$(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading');
-					$(ExtensionManager.Update.identifier.pagination).removeClass('is-loading');
-
-					// Show triggers for TER-update
-					$(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden');
-
-					// Show extension table
-					$(ExtensionManager.Update.identifier.extensionTable).show();
-				}
-			}
-		});
-	};
-
-	/**
-	 *
-	 */
-	ExtensionManager.Update.transformPaginatorToAjax = function () {
-		$(ExtensionManager.Update.identifier.pagination + ' a').each(function() {
-			var $me = $(this);
-			$me.data('href', $(this).attr('href'));
-			$me.attr('href', '#');
-			$me.click(function() {
-				var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper);
-				NProgress.start();
-				$.ajax({
-					url: $(this).data('href'),
-					dataType: 'json',
-					success: function(data) {
-						$terTableWrapper.html(data);
-						ExtensionManager.Update.transformPaginatorToAjax();
-					},
-					complete: function() {
-						NProgress.done();
-					}
-				});
-			});
-		});
-	};
-
-	/**
-	 * show the uploading form
-	 */
-	ExtensionManager.UploadForm = {
-		expandedUploadFormClass: 'transformed'
-	};
-
-	/**
-	 *
-	 */
-	ExtensionManager.UploadForm.initializeEvents = function() {
-		// Show upload form
-		$(document).on('click', '.t3js-upload', function(event) {
-			var $me = $(this),
-				$uploadForm = $('.uploadForm');
-
-			event.preventDefault();
-			if($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) {
-				$uploadForm.stop().slideUp();
-				$me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass);
-			} else {
-				$me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass);
-				$uploadForm.stop().slideDown();
-
-				$.ajax({
-					url: $me.attr('href'),
-					dataType: 'html',
-					success: function (data) {
-						$uploadForm.html(data);
-					}
-				});
-			}
-		});
-	};
-
-	$(function() {
-		var dataTable = ExtensionManager.manageExtensionListing();
-
-		$(document).on('click', '.onClickMaskExtensionManager', function() {
-			NProgress.start();
-		}).on('click', 'a[data-action=update-extension]', function(e) {
-			e.preventDefault();
-			$.ajax({
-				url: $(this).attr('href'),
-				dataType: 'json',
-				beforeSend: function() {
-					NProgress.start();
-				},
-				success: ExtensionManager.updateExtension
-			});
-		}).on('change', 'input[name=unlockDependencyIgnoreButton]', function() {
-			var $actionButton = $('.t3js-dependencies');
-			$actionButton.toggleClass('disabled', !$(this).prop('checked'));
-		});
-
-		$(ExtensionManager.identifier.searchField).clearable({
-			onClear: function() {
-				dataTable.search('').draw();
-			}
-		});
-
-		$(document).on('click', '.t3-button-action-installdistribution', function() {
-			NProgress.start();
-		});
-
-		SplitButtons.addPreSubmitCallback(function(e) {
-			if ($(e.target).hasClass('t3js-save-close')) {
-				$('#configurationform').append($('<input />', {type: 'hidden', name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]', value: 'saveAndClose'}));
-			}
-		});
-
-		// initialize the repository
-		Repository.initDom();
-
-		ExtensionManager.Update.initializeEvents();
-		ExtensionManager.UploadForm.initializeEvents();
-
-		Tooltip.initialize('#typo3-extension-list [title]', {
-			delay: {
-				show: 500,
-				hide: 100
-			},
-			trigger: 'hover',
-			container: 'body'
-		});
-	});
-
-	if (typeof TYPO3.ExtensionManager === 'undefined') {
-		TYPO3.ExtensionManager = ExtensionManager;
-	}
-
-	return ExtensionManager;
+  /**
+   *
+   * @type {{identifier: {extensionlist: string, searchField: string, extensionManager: string}}}
+   * @exports TYPO3/CMS/Extensionmanager/Main
+   */
+  var ExtensionManager = {
+    identifier: {
+      extensionlist: '#typo3-extension-list',
+      searchField: '#Tx_Extensionmanager_extensionkey'
+    }
+  };
+
+  /**
+   *
+   * @returns {Object}
+   */
+  ExtensionManager.manageExtensionListing = function() {
+    var $searchField = $(this.identifier.searchField),
+      dataTable = $(this.identifier.extensionlist).DataTable({
+        paging: false,
+        dom: 'lrtip',
+        lengthChange: false,
+        pageLength: 15,
+        stateSave: true,
+        drawCallback: this.bindExtensionListActions,
+        columns: [
+          null,
+          null,
+          {
+            type: 'extension'
+          },
+          null,
+          {
+            type: 'version'
+          }, {
+            orderable: false
+          },
+          null,
+          null
+        ]
+      });
+
+    $searchField.parents('form').on('submit', function() {
+      return false;
+    });
+
+    var getVars = ExtensionManager.getUrlVars();
+
+    // restore filter
+    var currentSearch = (getVars['search'] ? getVars['search'] : dataTable.search());
+    $searchField.val(currentSearch);
+
+    $searchField.on('input', function(e) {
+      dataTable.search($(this).val()).draw();
+    });
+
+    return dataTable;
+  };
+
+  /**
+   *
+   */
+  ExtensionManager.bindExtensionListActions = function() {
+    $('.removeExtension').not('.transformed').each(function() {
+      var $me = $(this);
+      $me.data('href', $me.attr('href'));
+      $me.attr('href', '#');
+      $me.addClass('transformed');
+      $me.click(function() {
+        Modal.confirm(
+          TYPO3.lang['extensionList.removalConfirmation.title'],
+          TYPO3.lang['extensionList.removalConfirmation.question'],
+          Severity.error,
+          [
+            {
+              text: TYPO3.lang['button.cancel'],
+              active: true,
+              btnClass: 'btn-default',
+              trigger: function() {
+                Modal.dismiss();
+              }
+            }, {
+            text: TYPO3.lang['button.remove'],
+            btnClass: 'btn-danger',
+            trigger: function() {
+              ExtensionManager.removeExtensionFromDisk($me);
+              Modal.dismiss();
+            }
+          }
+          ]
+        );
+      });
+    });
+  };
+
+  /**
+   *
+   * @param {Object} $extension
+   */
+  ExtensionManager.removeExtensionFromDisk = function($extension) {
+    $.ajax({
+      url: $extension.data('href'),
+      beforeSend: function() {
+        NProgress.start();
+      },
+      success: function() {
+        location.reload();
+      },
+      complete: function() {
+        NProgress.done();
+      }
+    });
+  };
+
+  /**
+   *
+   * @returns {Array}
+   */
+  ExtensionManager.getUrlVars = function() {
+    var vars = [], hash;
+    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+    for (var i = 0; i < hashes.length; i++) {
+      hash = hashes[i].split('=');
+      vars.push(hash[0]);
+      vars[hash[0]] = hash[1];
+    }
+    return vars;
+  };
+
+  $.fn.dataTableExt.oSort['extension-asc'] = function(a, b) {
+    return ExtensionManager.extensionCompare(a, b);
+  };
+
+  $.fn.dataTableExt.oSort['extension-desc'] = function(a, b) {
+    var result = ExtensionManager.extensionCompare(a, b);
+    return result * -1;
+  };
+
+  $.fn.dataTableExt.oSort['version-asc'] = function(a, b) {
+    var result = ExtensionManager.versionCompare(a, b);
+    return result * -1;
+  };
+
+  $.fn.dataTableExt.oSort['version-desc'] = function(a, b) {
+    return ExtensionManager.versionCompare(a, b);
+  };
+
+  /**
+   * Special sorting for the extension version column
+   *
+   * @param {String} a
+   * @param {String} b
+   * @returns {Number}
+   */
+  ExtensionManager.versionCompare = function(a, b) {
+    if (a === b) {
+      return 0;
+    }
+
+    var a_components = a.split(".");
+    var b_components = b.split(".");
+
+    var len = Math.min(a_components.length, b_components.length);
+
+    // loop while the components are equal
+    for (var i = 0; i < len; i++) {
+      // A bigger than B
+      if (parseInt(a_components[i]) > parseInt(b_components[i])) {
+        return 1;
+      }
+
+      // B bigger than A
+      if (parseInt(a_components[i]) < parseInt(b_components[i])) {
+        return -1;
+      }
+    }
+
+    // If one's a prefix of the other, the longer one is greaRepository.
+    if (a_components.length > b_components.length) {
+      return 1;
+    }
+
+    if (a_components.length < b_components.length) {
+      return -1;
+    }
+    // Otherwise they are the same.
+    return 0;
+  };
+
+  /**
+   * The extension name column can contain various forms of HTML that
+   * break a direct comparison of values
+   *
+   * @param {String} a
+   * @param {String} b
+   * @returns {Number}
+   */
+  ExtensionManager.extensionCompare = function(a, b) {
+    var div = document.createElement("div");
+    div.innerHTML = a;
+    var aStr = div.textContent || div.innerText || a;
+
+    div.innerHTML = b;
+    var bStr = div.textContent || div.innerText || b;
+
+    return aStr.trim().localeCompare(bStr.trim());
+  }
+
+  /**
+   *
+   * @param {Object} data
+   */
+  ExtensionManager.updateExtension = function(data) {
+    var message = '<h1>' + TYPO3.lang['extensionList.updateConfirmation.title'] + '</h1>';
+    message += '<h2>' + TYPO3.lang['extensionList.updateConfirmation.message'] + '</h2>';
+    message += '<form>';
+    var i = 0;
+    $.each(data.updateComments, function(version, comment) {
+      comment = comment.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2');
+      message += '<h3><input type="radio" ' + (i === 0 ? 'checked="checked" ' : '') + 'name="version" value="' + version + '" /> ' + version + '</h3>';
+      message += '<div>' + comment + '</div>';
+      i++;
+    });
+    message += '</form>';
+
+    NProgress.done();
+
+    Modal.confirm(
+      TYPO3.lang['extensionList.updateConfirmation.questionVersionComments'],
+      message,
+      Severity.warning,
+      [
+        {
+          text: TYPO3.lang['button.cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          trigger: function() {
+            Modal.dismiss();
+          }
+        }, {
+        text: TYPO3.lang['button.updateExtension'],
+        btnClass: 'btn-warning',
+        trigger: function() {
+          $.ajax({
+            url: data.url,
+            data: {
+              tx_extensionmanager_tools_extensionmanagerextensionmanager: {
+                version: $('input:radio[name=version]:checked', Modal.currentModal).val()
+              }
+            },
+            dataType: 'json',
+            beforeSend: function() {
+              NProgress.start();
+            },
+            complete: function() {
+              location.reload();
+            }
+          });
+          Modal.dismiss();
+        }
+      }
+      ]
+    );
+  };
+
+  /**
+   *
+   * @type {{downloadPath: string}}
+   */
+  var Repository = {
+    downloadPath: ''
+  };
+
+  /**
+   *
+   */
+  Repository.initDom = function() {
+    NProgress.configure({parent: '.module-loading-indicator', showSpinner: false});
+
+    $('#terTable').DataTable({
+      lengthChange: false,
+      pageLength: 15,
+      stateSave: false,
+      info: false,
+      paging: false,
+      searching: false,
+      ordering: false,
+      drawCallback: Repository.bindDownload
+    });
+
+    $('#terVersionTable').DataTable({
+      lengthChange: false,
+      pageLength: 15,
+      stateSave: false,
+      info: false,
+      paging: false,
+      searching: false,
+      drawCallback: Repository.bindDownload,
+      order: [
+        [2, 'asc']
+      ],
+      columns: [
+        {orderable: false},
+        null,
+        {type: 'version'},
+        null,
+        null,
+        null
+      ]
+    });
+
+    $('#terSearchTable').DataTable({
+      paging: false,
+      lengthChange: false,
+      stateSave: false,
+      searching: false,
+      language: {
+        search: 'Filter results:'
+      },
+      ordering: false,
+      drawCallback: Repository.bindDownload
+    });
+
+    Repository.bindDownload();
+    Repository.bindSearchFieldResetter();
+  };
+
+  /**
+   *
+   */
+  Repository.bindDownload = function() {
+    var installButtons = $('.downloadFromTer form.download button[type=submit]');
+    installButtons.off('click');
+    installButtons.on('click', function(event) {
+      event.preventDefault();
+      var url = $(event.currentTarget.form).attr('data-href');
+      Repository.downloadPath = $(event.currentTarget.form).find('input.downloadPath:checked').val();
+      $.ajax({
+        url: url,
+        dataType: 'json',
+        beforeSend: function() {
+          NProgress.start();
+        },
+        success: Repository.getDependencies
+      });
+    });
+  };
+
+  /**
+   *
+   * @param {Object} data
+   * @returns {Boolean}
+   */
+  Repository.getDependencies = function(data) {
+    NProgress.done();
+    if (data.hasDependencies) {
+      Modal.confirm(data.title, data.message, Severity.info, [
+        {
+          text: TYPO3.lang['button.cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          trigger: function() {
+            Modal.dismiss();
+          }
+        }, {
+          text: TYPO3.lang['button.resolveDependencies'],
+          btnClass: 'btn-info',
+          trigger: function() {
+            Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
+            Modal.dismiss();
+          }
+        }
+      ]);
+    } else {
+      if (data.hasErrors) {
+        Notification.error(data.title, data.message, 15);
+      } else {
+        Repository.getResolveDependenciesAndInstallResult(data.url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager[downloadPath]=' + Repository.downloadPath);
+      }
+    }
+    return false;
+  };
+
+  /**
+   *
+   * @param {String} url
+   */
+  Repository.getResolveDependenciesAndInstallResult = function(url) {
+    $.ajax({
+      url: url,
+      dataType: 'json',
+      beforeSend: function() {
+        NProgress.start();
+      },
+      success: function(data) {
+        if (data.errorCount > 0) {
+          Modal.confirm(data.errorTitle, data.errorMessage, Severity.error, [
+            {
+              text: TYPO3.lang['button.cancel'],
+              active: true,
+              btnClass: 'btn-default',
+              trigger: function() {
+                Modal.dismiss();
+              }
+            }, {
+              text: TYPO3.lang['button.resolveDependenciesIgnore'],
+              btnClass: 'btn-danger disabled t3js-dependencies',
+              trigger: function() {
+                if (!$(this).hasClass('disabled')) {
+                  Repository.getResolveDependenciesAndInstallResult(data.skipDependencyUri);
+                  Modal.dismiss();
+                }
+              }
+            }
+          ]);
+          Modal.currentModal.on('shown.bs.modal', function() {
+            var $actionButton = Modal.currentModal.find('.t3js-dependencies');
+            $('input[name="unlockDependencyIgnoreButton"]', Modal.currentModal).on('change', function() {
+              $actionButton.toggleClass('disabled', !$(this).prop('checked'));
+            });
+          });
+        } else {
+          var successMessage = TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.message' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension);
+
+          successMessage += '\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.header'] + ': ';
+          $.each(data.result, function(index, value) {
+            successMessage += '\n\n' + TYPO3.lang['extensionList.dependenciesResolveDownloadSuccess.item'] + ' ' + index + ': ';
+            $.each(value, function(extkey) {
+              successMessage += '\n* ' + extkey
+            });
+          });
+          Notification.info(TYPO3.lang['extensionList.dependenciesResolveFlashMessage.title' + data.installationTypeLanguageKey].replace(/\{0\}/g, data.extension), successMessage, 15);
+          top.TYPO3.ModuleMenu.App.refreshMenu();
+        }
+      },
+      complete: function() {
+        NProgress.done();
+      }
+    });
+  };
+
+  /**
+   *
+   */
+  Repository.bindSearchFieldResetter = function() {
+    var $searchFields = $('.typo3-extensionmanager-searchTerForm input[type="text"]');
+    var searchResultShown = ('' !== $searchFields.first().val());
+
+    $searchFields.clearable(
+      {
+        onClear: function() {
+          if (searchResultShown) {
+            $(this).closest('form').submit();
+          }
+        }
+      }
+    );
+  };
+
+  /**
+   *
+   * @type {{identifier: {extensionTable: string, terUpdateAction: string, pagination: string, splashscreen: string, terTableWrapper: string, terTableDataTableWrapper: string}}}
+   */
+  ExtensionManager.Update = {
+    identifier: {
+      extensionTable: '#terTable',
+      terUpdateAction: '.update-from-ter',
+      pagination: '.pagination-wrap',
+      splashscreen: '.splash-receivedata',
+      terTableWrapper: '#terTableWrapper',
+      terTableDataTableWrapper: '#terTableWrapper .dataTables_wrapper'
+    }
+  };
+
+  /**
+   * Register "update from ter" action
+   */
+  ExtensionManager.Update.initializeEvents = function() {
+    $(ExtensionManager.Update.identifier.terUpdateAction).each(function() {
+
+      // "this" is the form which updates the extension list from
+      // TER on submit
+      var $me = $(this),
+        updateURL = $(this).attr('action');
+
+      $me.attr('action', '#');
+      $me.submit(function() {
+        // Force update on click.
+        ExtensionManager.Update.updateFromTer(updateURL, true);
+
+        // Prevent normal submit action.
+        return false;
+      });
+
+      // This might give problems when there are more "update"-buttons,
+      // each one would trigger a TER-ExtensionManager.Update.
+      ExtensionManager.Update.updateFromTer(updateURL, false);
+    });
+  };
+
+  /**
+   *
+   * @param {String} url
+   * @param {Boolean} forceUpdate
+   */
+  ExtensionManager.Update.updateFromTer = function(url, forceUpdate) {
+    if (forceUpdate) {
+      url = url + '&tx_extensionmanager_tools_extensionmanagerextensionmanager%5BforceUpdateCheck%5D=1';
+    }
+
+    // Hide triggers for TER update
+    $(ExtensionManager.Update.identifier.terUpdateAction).addClass('is-hidden');
+
+    // Hide extension table
+    $(ExtensionManager.Update.identifier.extensionTable).hide();
+
+    // Show loaders
+    $(ExtensionManager.Update.identifier.splashscreen).addClass('is-shown');
+    $(ExtensionManager.Update.identifier.terTableDataTableWrapper).addClass('is-loading');
+    $(ExtensionManager.Update.identifier.pagination).addClass('is-loading');
+
+    var reload = false;
+
+    $.ajax({
+      url: url,
+      dataType: 'json',
+      cache: false,
+      beforeSend: function() {
+        NProgress.start();
+      },
+      success: function(data) {
+        // Something went wrong, show message
+        if (data.errorMessage.length) {
+          Notification.error(TYPO3.lang['extensionList.updateFromTerFlashMessage.title'], data.errorMessage, 10);
+        }
+
+        // Message with latest updates
+        var $lastUpdate = $(ExtensionManager.Update.identifier.terUpdateAction + ' .time-since-last-update');
+        $lastUpdate.text(data.timeSinceLastUpdate);
+        $lastUpdate.attr(
+          'title',
+          TYPO3.lang['extensionList.updateFromTer.lastUpdate.timeOfLastUpdate'] + data.lastUpdateTime
+        );
+
+        if (data.updated) {
+          // Reload page
+          reload = true;
+          window.location.replace(window.location.href);
+        }
+      },
+      error: function(jqXHR, textStatus, errorThrown) {
+        // Create an error message with diagnosis info.
+        var errorMessage = textStatus + '(' + errorThrown + '): ' + jqXHR.responseText;
+
+        Notification.warning(
+          TYPO3.lang['extensionList.updateFromTerFlashMessage.title'],
+          errorMessage,
+          10
+        );
+      },
+      complete: function() {
+        NProgress.done();
+
+        if (!reload) {
+          // Hide loaders
+          $(ExtensionManager.Update.identifier.splashscreen).removeClass('is-shown');
+          $(ExtensionManager.Update.identifier.terTableDataTableWrapper).removeClass('is-loading');
+          $(ExtensionManager.Update.identifier.pagination).removeClass('is-loading');
+
+          // Show triggers for TER-update
+          $(ExtensionManager.Update.identifier.terUpdateAction).removeClass('is-hidden');
+
+          // Show extension table
+          $(ExtensionManager.Update.identifier.extensionTable).show();
+        }
+      }
+    });
+  };
+
+  /**
+   *
+   */
+  ExtensionManager.Update.transformPaginatorToAjax = function() {
+    $(ExtensionManager.Update.identifier.pagination + ' a').each(function() {
+      var $me = $(this);
+      $me.data('href', $(this).attr('href'));
+      $me.attr('href', '#');
+      $me.click(function() {
+        var $terTableWrapper = $(ExtensionManager.Update.identifier.terTableWrapper);
+        NProgress.start();
+        $.ajax({
+          url: $(this).data('href'),
+          dataType: 'json',
+          success: function(data) {
+            $terTableWrapper.html(data);
+            ExtensionManager.Update.transformPaginatorToAjax();
+          },
+          complete: function() {
+            NProgress.done();
+          }
+        });
+      });
+    });
+  };
+
+  /**
+   * show the uploading form
+   */
+  ExtensionManager.UploadForm = {
+    expandedUploadFormClass: 'transformed'
+  };
+
+  /**
+   *
+   */
+  ExtensionManager.UploadForm.initializeEvents = function() {
+    // Show upload form
+    $(document).on('click', '.t3js-upload', function(event) {
+      var $me = $(this),
+        $uploadForm = $('.uploadForm');
+
+      event.preventDefault();
+      if ($me.hasClass(ExtensionManager.UploadForm.expandedUploadFormClass)) {
+        $uploadForm.stop().slideUp();
+        $me.removeClass(ExtensionManager.UploadForm.expandedUploadFormClass);
+      } else {
+        $me.addClass(ExtensionManager.UploadForm.expandedUploadFormClass);
+        $uploadForm.stop().slideDown();
+
+        $.ajax({
+          url: $me.attr('href'),
+          dataType: 'html',
+          success: function(data) {
+            $uploadForm.html(data);
+          }
+        });
+      }
+    });
+  };
+
+  $(function() {
+    var dataTable = ExtensionManager.manageExtensionListing();
+
+    $(document).on('click', '.onClickMaskExtensionManager', function() {
+      NProgress.start();
+    }).on('click', 'a[data-action=update-extension]', function(e) {
+      e.preventDefault();
+      $.ajax({
+        url: $(this).attr('href'),
+        dataType: 'json',
+        beforeSend: function() {
+          NProgress.start();
+        },
+        success: ExtensionManager.updateExtension
+      });
+    }).on('change', 'input[name=unlockDependencyIgnoreButton]', function() {
+      var $actionButton = $('.t3js-dependencies');
+      $actionButton.toggleClass('disabled', !$(this).prop('checked'));
+    });
+
+    $(ExtensionManager.identifier.searchField).clearable({
+      onClear: function() {
+        dataTable.search('').draw();
+      }
+    });
+
+    $(document).on('click', '.t3-button-action-installdistribution', function() {
+      NProgress.start();
+    });
+
+    SplitButtons.addPreSubmitCallback(function(e) {
+      if ($(e.target).hasClass('t3js-save-close')) {
+        $('#configurationform').append($('<input />', {
+          type: 'hidden',
+          name: 'tx_extensionmanager_tools_extensionmanagerextensionmanager[action]',
+          value: 'saveAndClose'
+        }));
+      }
+    });
+
+    // initialize the repository
+    Repository.initDom();
+
+    ExtensionManager.Update.initializeEvents();
+    ExtensionManager.UploadForm.initializeEvents();
+
+    Tooltip.initialize('#typo3-extension-list [title]', {
+      delay: {
+        show: 500,
+        hide: 100
+      },
+      trigger: 'hover',
+      container: 'body'
+    });
+  });
+
+  if (typeof TYPO3.ExtensionManager === 'undefined') {
+    TYPO3.ExtensionManager = ExtensionManager;
+  }
+
+  return ExtensionManager;
 });
diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js
index 045b826b1a51..af348f053a7d 100644
--- a/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js
+++ b/typo3/sysext/filelist/Resources/Public/JavaScript/ContextMenuActions.js
@@ -17,182 +17,181 @@
  * JavaScript to handle filelist actions from context menu
  * @exports TYPO3/CMS/Filelist/ContextMenuActions
  */
-define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) {
-    'use strict';
-
-    /**
-     * @exports TYPO3/CMS/Filelist/ContextMenuActions
-     */
-    var ContextMenuActions = {};
-    ContextMenuActions.getReturnUrl = function () {
-       return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
-    };
-
-    ContextMenuActions.renameFile = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FileRename.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.editFile = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FileEdit.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' +  ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.editFileStorage = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FormEngine.moduleUrl + '&edit[sys_file_storage][' + parseInt(uid, 10) + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.openInfoPopUp = function (table, uid) {
-        if (table === 'sys_file_storage') {
-            top.launchView(table, uid);
-        } else {
-            //files and folders
-            top.launchView('_FILE', uid);
+define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) {
+  'use strict';
+
+  /**
+   * @exports TYPO3/CMS/Filelist/ContextMenuActions
+   */
+  var ContextMenuActions = {};
+  ContextMenuActions.getReturnUrl = function() {
+    return top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
+  };
+
+  ContextMenuActions.renameFile = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FileRename.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.editFile = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FileEdit.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.editFileStorage = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FormEngine.moduleUrl + '&edit[sys_file_storage][' + parseInt(uid, 10) + ']=edit&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.openInfoPopUp = function(table, uid) {
+    if (table === 'sys_file_storage') {
+      top.launchView(table, uid);
+    } else {
+      //files and folders
+      top.launchView('_FILE', uid);
+    }
+  };
+
+  ContextMenuActions.uploadFile = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FileUpload.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.createFile = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FileCreate.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+
+  ContextMenuActions.deleteFile = function(table, uid) {
+    var $anchorElement = $(this);
+    var performDelete = function() {
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.FileCommit.moduleUrl + '&data[delete][0][data]=' + top.rawurlencode(uid) + '&data[delete][0][redirect]=' + ContextMenuActions.getReturnUrl()
+      );
+    };
+    if (!$anchorElement.data('title')) {
+      performDelete();
+      return;
+    }
+
+    var $modal = Modal.confirm(
+      $anchorElement.data('title'),
+      $anchorElement.data('message'),
+      Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
+          btnClass: 'btn-warning',
+          name: 'delete'
         }
-    };
-
-    ContextMenuActions.uploadFile = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FileUpload.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.createFile = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FileCreate.moduleUrl + '&target=' + top.rawurlencode(uid) + '&returnUrl=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-
-    ContextMenuActions.deleteFile = function (table, uid) {
-        var $anchorElement = $(this);
-        var performDelete = function () {
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.FileCommit.moduleUrl + '&data[delete][0][data]=' + top.rawurlencode(uid) + '&data[delete][0][redirect]=' + ContextMenuActions.getReturnUrl()
-            );
-        };
-        if (!$anchorElement.data('title')) {
-            performDelete();
-            return;
+      ]);
+
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'delete') {
+        performDelete();
+      }
+      Modal.dismiss();
+    });
+  };
+
+  ContextMenuActions.copyFile = function(table, uid) {
+    var shortMD5 = top.MD5(uid).substring(0, 10);
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid) + '&CB[setCopyMode]=1';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.copyReleaseFile = function(table, uid) {
+    var shortMD5 = top.MD5(uid).substring(0, 10);
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][_FILE%7C' + shortMD5 + ']=0&CB[setCopyMode]=1';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.cutFile = function(table, uid) {
+    var shortMD5 = top.MD5(uid).substring(0, 10);
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid);
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.cutReleaseFile = function(table, uid) {
+    var shortMD5 = top.MD5(uid).substring(0, 10);
+    var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
+    url += '&CB[el][_FILE%7C' + shortMD5 + ']=0';
+    $.ajax(url).always(function() {
+      top.TYPO3.Backend.ContentContainer.refresh(true);
+    });
+  };
+
+  ContextMenuActions.pasteFileInto = function(table, uid) {
+    var $anchorElement = $(this);
+    var title = $anchorElement.data('title');
+    var performPaste = function() {
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.FileCommit.moduleUrl + '&CB[paste]=FILE|' + top.rawurlencode(uid) + '&CB[pad]=normal&redirect=' + ContextMenuActions.getReturnUrl()
+      );
+    };
+    if (!$anchorElement.data('title')) {
+      performPaste();
+      return;
+    }
+    var $modal = Modal.confirm(
+      $anchorElement.data('title'),
+      $anchorElement.data('message'),
+      Severity.warning, [
+        {
+          text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel'
+        },
+        {
+          text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
+          btnClass: 'btn-warning',
+          name: 'ok'
         }
-
-        var $modal = Modal.confirm(
-            $anchorElement.data('title'),
-            $anchorElement.data('message'),
-            Severity.warning, [
-                {
-                    text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-                    active: true,
-                    btnClass: 'btn-default',
-                    name: 'cancel'
-                },
-                {
-                    text: $(this).data('button-ok-text') || TYPO3.lang['button.delete'] || 'Delete',
-                    btnClass: 'btn-warning',
-                    name: 'delete'
-                }
-            ]);
-
-        $modal.on('button.clicked', function (e) {
-            if (e.target.name === 'delete') {
-                performDelete();
-            }
-            Modal.dismiss();
-        });
-    };
-
-    ContextMenuActions.copyFile = function (table, uid) {
-        var shortMD5 = top.MD5(uid).substring(0, 10);
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid) + '&CB[setCopyMode]=1';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.copyReleaseFile = function (table, uid) {
-        var shortMD5 = top.MD5(uid).substring(0, 10);
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][_FILE%7C' + shortMD5 + ']=0&CB[setCopyMode]=1';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.cutFile = function (table, uid) {
-        var shortMD5 = top.MD5(uid).substring(0, 10);
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][_FILE%7C' + shortMD5 + ']=' + top.rawurlencode(uid);
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.cutReleaseFile = function (table, uid) {
-        var shortMD5 = top.MD5(uid).substring(0, 10);
-        var url = TYPO3.settings.ajaxUrls['contextmenu_clipboard'];
-        url += '&CB[el][_FILE%7C' + shortMD5 + ']=0';
-        $.ajax(url).always(function () {
-            top.TYPO3.Backend.ContentContainer.refresh(true);
-        });
-    };
-
-    ContextMenuActions.pasteFileInto = function (table, uid) {
-        var $anchorElement = $(this);
-        var title = $anchorElement.data('title');
-        var performPaste = function () {
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                    top.TYPO3.settings.FileCommit.moduleUrl + '&CB[paste]=FILE|' + top.rawurlencode(uid) + '&CB[pad]=normal&redirect=' + ContextMenuActions.getReturnUrl()
-            );
-        };
-        if (!$anchorElement.data('title')) {
-            performPaste();
-            return;
-        }
-        var $modal = Modal.confirm(
-            $anchorElement.data('title'),
-            $anchorElement.data('message'),
-            Severity.warning, [
-                {
-                    text: $(this).data('button-close-text') || TYPO3.lang['button.cancel'] || 'Cancel',
-                    active: true,
-                    btnClass: 'btn-default',
-                    name: 'cancel'
-                },
-                {
-                    text: $(this).data('button-ok-text') || TYPO3.lang['button.ok'] || 'OK',
-                    btnClass: 'btn-warning',
-                    name: 'ok'
-                }
-            ]);
-
-        $modal.on('button.clicked', function (e) {
-            if (e.target.name === 'ok') {
-                performPaste();
-            }
-            Modal.dismiss();
-        });
-    };
-
-
-
-    ContextMenuActions.dropInto = function (table, uid, mode) {
-        var target = $(this).data('drop-target');
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.FileCommit.moduleUrl
-            + '&file['+ mode + '][0][data]=' + top.rawurlencode(uid)
-            + '&file['+ mode + '][0][target]=' + top.rawurlencode(target)
-            + '&redirect=' + ContextMenuActions.getReturnUrl()
-        );
-    };
-    ContextMenuActions.dropMoveInto = function (table, uid) {
-        ContextMenuActions.dropInto.bind($(this))(table, uid, 'move');
-    };
-    ContextMenuActions.dropCopyInto = function (table, uid) {
-        ContextMenuActions.dropInto.bind($(this))(table, uid, 'copy');
-    };
-    return ContextMenuActions;
+      ]);
+
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'ok') {
+        performPaste();
+      }
+      Modal.dismiss();
+    });
+  };
+
+
+  ContextMenuActions.dropInto = function(table, uid, mode) {
+    var target = $(this).data('drop-target');
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.FileCommit.moduleUrl
+      + '&file[' + mode + '][0][data]=' + top.rawurlencode(uid)
+      + '&file[' + mode + '][0][target]=' + top.rawurlencode(target)
+      + '&redirect=' + ContextMenuActions.getReturnUrl()
+    );
+  };
+  ContextMenuActions.dropMoveInto = function(table, uid) {
+    ContextMenuActions.dropInto.bind($(this))(table, uid, 'move');
+  };
+  ContextMenuActions.dropCopyInto = function(table, uid) {
+    ContextMenuActions.dropInto.bind($(this))(table, uid, 'copy');
+  };
+  return ContextMenuActions;
 });
diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js
index 0dd2ec469639..d5cb054a5924 100644
--- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js
+++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileDelete.js
@@ -15,45 +15,45 @@
  * Module: TYPO3/CMS/Filelist/FileDelete
  * JavaScript for file delete
  */
-define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, Modal, Severity) {
+define(['jquery', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, Modal, Severity) {
 
-	$(document).on('click', '.t3js-filelist-delete', function(e) {
-		e.preventDefault();
-		var $anchorElement = $(this);
-		var redirectUrl = $anchorElement.data('redirectUrl');
-		if (redirectUrl) {
-			redirectUrl = top.rawurlencode(redirectUrl);
-		} else {
-			redirectUrl = top.rawurlencode(top.list_frame.document.location.pathname+top.list_frame.document.location.search);
-		}
-		var identifier = $anchorElement.data('identifier');
-		var deleteType = $anchorElement.data('deleteType');
-		var deleteUrl = $anchorElement.data('deleteUrl') + '&data[delete][0][data]=' + encodeURIComponent(identifier);
-		if ($anchorElement.data('check')) {
-			var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('content'), Severity.warning, [
-				{
-					text: TYPO3.lang['buttons.confirm.delete_file.no'] || 'Cancel',
-					active: true,
-					btnClass: 'btn-default',
-					name: 'no'
-				},
-				{
-					text: TYPO3.lang['buttons.confirm.' + deleteType + '.yes'] || 'Yes, delete this file or folder',
-					btnClass: 'btn-warning',
-					name: 'yes'
-				}
-			]);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'no') {
-					Modal.dismiss();
-				} else if (e.target.name === 'yes') {
-					Modal.dismiss();
-					top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl;
-				}
-			});
-		} else {
-			top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl;
-		}
-	});
+  $(document).on('click', '.t3js-filelist-delete', function(e) {
+    e.preventDefault();
+    var $anchorElement = $(this);
+    var redirectUrl = $anchorElement.data('redirectUrl');
+    if (redirectUrl) {
+      redirectUrl = top.rawurlencode(redirectUrl);
+    } else {
+      redirectUrl = top.rawurlencode(top.list_frame.document.location.pathname + top.list_frame.document.location.search);
+    }
+    var identifier = $anchorElement.data('identifier');
+    var deleteType = $anchorElement.data('deleteType');
+    var deleteUrl = $anchorElement.data('deleteUrl') + '&data[delete][0][data]=' + encodeURIComponent(identifier);
+    if ($anchorElement.data('check')) {
+      var $modal = Modal.confirm($anchorElement.data('title'), $anchorElement.data('content'), Severity.warning, [
+        {
+          text: TYPO3.lang['buttons.confirm.delete_file.no'] || 'Cancel',
+          active: true,
+          btnClass: 'btn-default',
+          name: 'no'
+        },
+        {
+          text: TYPO3.lang['buttons.confirm.' + deleteType + '.yes'] || 'Yes, delete this file or folder',
+          btnClass: 'btn-warning',
+          name: 'yes'
+        }
+      ]);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'no') {
+          Modal.dismiss();
+        } else if (e.target.name === 'yes') {
+          Modal.dismiss();
+          top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl;
+        }
+      });
+    } else {
+      top.list_frame.location.href = deleteUrl + '&data[delete][0][redirect]=' + redirectUrl;
+    }
+  });
 
 });
diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js
index 10eeaf83d319..ecf6d395b645 100644
--- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js
+++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileList.js
@@ -17,60 +17,60 @@
  */
 define(['jquery'], function($) {
 
-	$('a.filelist-file-title').click(function(event) {
-		event.preventDefault();
+  $('a.filelist-file-title').click(function(event) {
+    event.preventDefault();
 
-		var url = $(this).attr('data-url');
-		window.location.href=url;
-	});
+    var url = $(this).attr('data-url');
+    window.location.href = url;
+  });
 
-	$('a.btn.filelist-file-edit').click(function(event) {
-		event.preventDefault();
+  $('a.btn.filelist-file-edit').click(function(event) {
+    event.preventDefault();
 
-		var url = $(this).attr('data-url');
-		top.list_frame.location.href=url;
-	});
+    var url = $(this).attr('data-url');
+    top.list_frame.location.href = url;
+  });
 
-	$('a.btn.filelist-file-view').click(function(event) {
-		event.preventDefault();
+  $('a.btn.filelist-file-view').click(function(event) {
+    event.preventDefault();
 
-		var url = $(this).attr('data-url');
-		top.openUrlInWindow(url, 'WebFile')
-	});
+    var url = $(this).attr('data-url');
+    top.openUrlInWindow(url, 'WebFile')
+  });
 
-	$('a.btn.filelist-file-replace').click(function(event) {
-		event.preventDefault();
+  $('a.btn.filelist-file-replace').click(function(event) {
+    event.preventDefault();
 
-		var url = $(this).attr('data-url');
-		top.list_frame.location.href=url;
-	});
+    var url = $(this).attr('data-url');
+    top.list_frame.location.href = url;
+  });
 
-	$('a.btn.filelist-file-rename').click(function(event) {
-		event.preventDefault();
+  $('a.btn.filelist-file-rename').click(function(event) {
+    event.preventDefault();
 
-		var url = $(this).attr('data-url');
-		top.list_frame.location.href=url;
-	});
+    var url = $(this).attr('data-url');
+    top.list_frame.location.href = url;
+  });
 
-	$('a.btn.filelist-file-info').click(function(event) {
-		event.preventDefault();
+  $('a.btn.filelist-file-info').click(function(event) {
+    event.preventDefault();
 
-		var identifier = $(this).attr('data-identifier');
-		openFileInfoPopup(identifier);
-	});
+    var identifier = $(this).attr('data-identifier');
+    openFileInfoPopup(identifier);
+  });
 
-	$('a.filelist-file-references').click(function(event) {
-		event.preventDefault();
+  $('a.filelist-file-references').click(function(event) {
+    event.preventDefault();
 
-		var identifier = $(this).attr('data-identifier');
-		openFileInfoPopup(identifier);
-	});
+    var identifier = $(this).attr('data-identifier');
+    openFileInfoPopup(identifier);
+  });
 
-	/**
-	 * @param identifier
-	 */
-	function openFileInfoPopup(identifier) {
-		top.launchView('_FILE', identifier);
-	}
+  /**
+   * @param identifier
+   */
+  function openFileInfoPopup(identifier) {
+    top.launchView('_FILE', identifier);
+  }
 
 });
diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js
index a4cdff00961d..f94205b68d55 100644
--- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js
+++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileListLocalisation.js
@@ -17,10 +17,10 @@
  */
 define(['jquery'], function($) {
 
-	$('a.filelist-translationToggler').click(function(event) {
-		var id = $(this).attr('data-fileid');
-		$('div[data-fileid="' + id + '"]').toggle();
-	});
+  $('a.filelist-translationToggler').click(function(event) {
+    var id = $(this).attr('data-fileid');
+    $('div[data-fileid="' + id + '"]').toggle();
+  });
 
-	return null;
+  return null;
 });
diff --git a/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js b/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js
index 86b097489b44..b2a08d18f9fa 100644
--- a/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js
+++ b/typo3/sysext/filelist/Resources/Public/JavaScript/FileSearch.js
@@ -18,16 +18,16 @@
  */
 define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
 
-	var $searchFields = $('input[name="tx_filelist_file_filelistlist[searchWord]"]');
-	var searchResultShown = ('' !== $searchFields.first().val());
+  var $searchFields = $('input[name="tx_filelist_file_filelistlist[searchWord]"]');
+  var searchResultShown = ('' !== $searchFields.first().val());
 
-	// make search field clearable
-	$searchFields.clearable({
-		onClear: function() {
-			if (searchResultShown) {
-				$(this).closest('form').submit();
-			}
-		}
-	});
+  // make search field clearable
+  $searchFields.clearable({
+    onClear: function() {
+      if (searchResultShown) {
+        $(this).closest('form').submit();
+      }
+    }
+  });
 
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js
index 871120534a6b..be985682c5de 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor.js
@@ -15,1139 +15,1139 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Core',
-        ], function($, core) {
-        'use strict';
+  'TYPO3/CMS/Form/Backend/FormEditor/Core'
+], function($, core) {
+  'use strict';
+
+  /**
+   * Return a static method named "getInstance".
+   * Use this method to create the formeditor app.
+   */
+  return (function(_core) {
+
+    /**
+     * @private
+     *
+     * Hold the instance (Singleton Pattern)
+     */
+    var _formEditorInstance = null;
+
+    /**
+     * @public
+     *
+     * @param object _configuration
+     * @param object _mediator
+     * @param object _viewModel
+     * @return object
+     */
+    function FormEditor(_configuration, _mediator, _viewModel) {
+
+      /**
+       * @private
+       *
+       * @var bool
+       */
+      var _isRunning = false;
+
+      /**
+       * @private
+       *
+       * @var bool
+       */
+      var _unsavedContent = false;
+
+      /**
+       * @private
+       *
+       * @var bool
+       */
+      var _previewMode = false;
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getPublisherSubscriber() {
+        return _core.getPublisherSubscriber();
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function _saveApplicationState() {
+
+        _getApplicationStateStack().addAndReset({
+          formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(),
+          currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'),
+          currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')
+        });
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function undoApplicationState() {
+        _getApplicationStateStack().incrementCurrentStackPointer();
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function redoApplicationState() {
+        _getApplicationStateStack().decrementCurrentStackPointer();
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getMaximalApplicationStates() {
+        return _getApplicationStateStack().getMaximalStackSize();
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getCurrentApplicationStates() {
+        return _getApplicationStateStack().getCurrentStackSize();
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getCurrentApplicationStatePosition() {
+        return _getApplicationStateStack().getCurrentStackPointer();
+      };
+
+      /**
+       * @public
+       *
+       * @param string type
+       * @return object
+       * @throws 1475378543
+       */
+      function getRunningAjaxRequest(type) {
+        assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543);
+        return _core.getRunningAjaxRequest(type);
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getUtility() {
+        return _core.getUtility();
+      };
+
+      /**
+       * @public
+       *
+       * @param mixed test
+       * @param string message
+       * @param int messageCode
+       * @return void
+       */
+      function assert(test, message, messageCode) {
+        getUtility().assert(test, message, messageCode);
+      };
+
+      /**
+       * @public
+       *
+       * @param string propertyPath
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object formElement
+       * @param boolean allowEmptyReturnValue
+       * @return string
+       */
+      function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) {
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElement = getCurrentlySelectedFormElement();
+        }
+        formElement = _getRepository().findFormElement(formElement);
+        return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue);
+      };
+
+      /**
+       * @public
+       *
+       * @param string validatorIdentifier
+       * @param function func
+       * @return void
+       */
+      function addPropertyValidationValidator(validatorIdentifier, func) {
+        _getPropertyValidationService().addValidator(validatorIdentifier, func);
+      };
+
+      /**
+       * @public
+       *
+       * @param string propertyPath
+       * @return object
+       */
+      function validateCurrentlySelectedFormElementProperty(propertyPath) {
+        return validateFormElementProperty(
+          getCurrentlySelectedFormElement(),
+          propertyPath
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string propertyPath
+       * @return object
+       */
+      function validateFormElementProperty(formElement, propertyPath) {
+        formElement = _getRepository().findFormElement(formElement);
+        return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath);
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object
+       */
+      function validateFormElement(formElement) {
+        formElement = _getRepository().findFormElement(formElement);
+        return _getPropertyValidationService().validateFormElement(formElement);
+      };
+
+      /**
+       * @public
+       *
+       * @param object validationResults
+       * @return boolean
+       */
+      function validationResultsHasErrors(validationResults) {
+        return _getPropertyValidationService().validationResultsHasErrors(validationResults);
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param boolean returnAfterFirstMatch
+       * @return object
+       */
+      function validateFormElementRecursive(formElement, returnAfterFirstMatch) {
+        formElement = _getRepository().findFormElement(formElement);
+        return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch);
+      };
+
+      /**
+       * @public
+       *
+       * @param bool unsavedContent
+       * @return void
+       * @throws 1475378544
+       */
+      function setUnsavedContent(unsavedContent) {
+        assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544);
+        _unsavedContent = unsavedContent;
+      };
+
+      /**
+       * @public
+       *
+       * @return boolean
+       */
+      function getUnsavedContent() {
+        return _unsavedContent;
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getRootFormElement() {
+        return _getRepository().getRootFormElement();
+      };
+
+      /**
+       * @public
+       *
+       * @return string
+       */
+      function getCurrentlySelectedFormElement() {
+        return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath'));
+      };
+
+      /**
+       * @public
+       *
+       * @param string|object formElement
+       * @param boolean doNotRefreshCurrentlySelectedPageIndex
+       * @return void
+       * @publish core/currentlySelectedFormElementChanged
+       */
+      function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) {
+        doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex;
+
+        formElement = _getRepository().findFormElement(formElement);
+        _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath'));
+
+        if (!doNotRefreshCurrentlySelectedPageIndex) {
+          refreshCurrentlySelectedPageIndex();
+        }
+        getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]);
+      };
+
+      /**
+       * @public
+       *
+       * @param string identifierPath
+       * @return object
+       * @throws 1475378545
+       */
+      function getFormElementByIdentifierPath(identifierPath) {
+        assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545);
+        return _getRepository().findFormElementByIdentifierPath(identifierPath);
+      };
+
+      /**
+       * @public
+       *
+       * @param string identifierPath
+       * @return bool
+       */
+      function isFormElementIdentifierUsed(formElementIdentifier) {
+        return _getRepository().isFormElementIdentifierUsed(formElementIdentifier);
+      }
+
+      /**
+       * @public
+       *
+       * @param string formElementType
+       * @param string|object referenceFormElement
+       * @param boolean disablePublishersOnSet
+       * @return object
+       */
+      function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
+        var formElement;
+        formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet);
+        formElement.set('renderables', formElement.get('renderables'));
+        return formElement;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string|object referenceFormElement
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475434337
+       */
+      function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) {
+        _saveApplicationState();
+
+        if (getUtility().isUndefinedOrNull(referenceFormElement)) {
+          referenceFormElement = getCurrentlySelectedFormElement();
+        }
+        referenceFormElement = _getRepository().findFormElement(referenceFormElement);
+        assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337);
+        return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet);
+      };
+
+      /**
+       * @public
+       *
+       * @param string formElementType
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475434336
+       * @throws 1475435857
+       */
+      function createFormElement(formElementType, disablePublishersOnSet) {
+        var formElementDefinition, identifier;
+        assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336);
+
+        identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType);
+        formElementDefinition = getFormElementDefinitionByType(formElementType);
+        return _getFactory().createFormElement({
+          type: formElementType,
+          identifier: identifier,
+          label: formElementDefinition['label'] || formElementType
+        }, undefined, undefined, undefined, disablePublishersOnSet);
+      };
+
+      /**
+       * @public
+       *
+       * @param string|object formElementToRemove
+       * @param boolean disablePublishersOnSet
+       * @return object
+       */
+      function removeFormElement(formElementToRemove, disablePublishersOnSet) {
+        var parentFormElement;
+        _saveApplicationState();
+
+        formElementToRemove = _getRepository().findFormElement(formElementToRemove);
+        parentFormElement = formElementToRemove.get('__parentRenderable');
+        _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet);
+        return parentFormElement;
+      };
+
+      /**
+       * @public
+       *
+       * @param string|object formElementToMove
+       * @param string position
+       * @param string|object referenceFormElement
+       * @param boolean disablePublishersOnSet
+       * @return string
+       * @throws 1475378551
+       */
+      function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
+        _saveApplicationState();
+
+        formElementToMove = _getRepository().findFormElement(formElementToMove);
+        referenceFormElement = _getRepository().findFormElement(referenceFormElement);
+
+        assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551);
+
+        formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true);
+        disablePublishersOnSet = !!disablePublishersOnSet;
+        if (!disablePublishersOnSet) {
+          formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables'));
+        }
+        return formElementToMove;
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param string formElement
+       * @return object (dereferenced)
+       * @throws 1475378555
+       * @throws 1475378556
+       * @throws 1475446108
+       */
+      function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) {
+        var collection, collectionElement, formElementDefinition;
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElement = getCurrentlySelectedFormElement();
+        }
+        formElement = _getRepository().findFormElement(formElement);
+
+        assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556);
+
+        formElementDefinition = getFormElementDefinitionByType(formElement.get('type'));
+        if (!getUtility().isUndefinedOrNull(formElementDefinition['propertyCollections'])) {
+          collection = formElementDefinition['propertyCollections'][collectionName];
+          assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108);
+          collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection);
+          return $.extend(true, {}, collectionElement);
+        } else {
+          return {};
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param string formElement
+       * @return int
+       * @throws 1475378557
+       * @throws 1475378558
+       */
+      function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) {
+        var indexFromPropertyCollectionElement;
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElement = getCurrentlySelectedFormElement();
+        }
+        formElement = _getRepository().findFormElement(formElement);
+
+        assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558);
+
+        indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier(
+          collectionElementIdentifier,
+          collectionName,
+          formElement
+        );
+
+        return indexFromPropertyCollectionElement;
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object formElement
+       * @param object collectionElementConfiguration
+       * @param string referenceCollectionElementIdentifier
+       * @return object
+       */
+      function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) {
+        return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier);
+      };
+
+      /**
+       * @public
+       *
+       * @param object collectionElement
+       * @param string collectionName
+       * @param string|object formElement
+       * @param string referenceCollectionElementIdentifier
+       * @return object
+       * @throws 1475443300
+       * @throws 1475443301
+       */
+      function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) {
+        var collection;
+        _saveApplicationState();
+
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElement = getCurrentlySelectedFormElement();
+        }
+        formElement = _getRepository().findFormElement(formElement);
+
+        assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300);
+
+        if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) {
+          collection = formElement.get(collectionName);
+          if ('array' === $.type(collection) && collection.length > 0) {
+            referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier'];
+          }
+        }
+
+        return _getRepository().addPropertyCollectionElement(
+          collectionElement,
+          collectionName,
+          formElement,
+          referenceCollectionElementIdentifier,
+          false
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object collectionElementConfiguration
+       * @return void
+       * @throws 1475378559
+       * @throws 1475378560
+       */
+      function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) {
+        assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560);
+        if ('object' !== $.type(collectionElementConfiguration)) {
+          collectionElementConfiguration = {};
+        }
+
+        return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName);
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param string formElement
+       * @param bool disablePublishersOnSet
+       * @return void
+       * @throws 1475378561
+       * @throws 1475378562
+       */
+      function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
+        _saveApplicationState();
+
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElement = getCurrentlySelectedFormElement();
+        }
+        formElement = _getRepository().findFormElement(formElement);
+
+        assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562);
+
+        _getRepository().removePropertyCollectionElementByIdentifier(
+          formElement,
+          collectionElementIdentifier,
+          collectionName,
+          true
+        );
+
+        disablePublishersOnSet = !!disablePublishersOnSet;
+        if (!disablePublishersOnSet) {
+          getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']);
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementToMove
+       * @param string position
+       * @param string referenceCollectionElement
+       * @param string collectionName
+       * @param object formElement
+       * @param boolean disablePublishersOnSet
+       * @return string
+       * @throws 1477404352
+       * @throws 1477404353
+       * @throws 1477404354
+       * @throws 1477404355
+       */
+      function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
+        _saveApplicationState();
+
+        formElement = _getRepository().findFormElement(formElement);
+
+        assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352);
+        assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353);
+        assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354);
+        assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355);
+
+        return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet);
+      };
+
+      /**
+       * @public
+       *
+       * @param string elementType
+       * @param string formElementDefinitionKey
+       * @returnmixed
+       * @throws 1475378563
+       */
+      function getFormElementDefinitionByType(elementType, formElementDefinitionKey) {
+        var formElementDefinition;
+        assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563);
+
+        formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType);
+
+        if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) {
+          formElementDefinition = formElementDefinition[formElementDefinitionKey];
+        }
+
+        if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) {
+          return $.extend(true, {}, formElementDefinition);
+        } else {
+          return formElementDefinition;
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string formElementDefinitionKey
+       * @return mixed
+       */
+      function getFormElementDefinition(formElement, formElementDefinitionKey) {
+        formElement = _getRepository().findFormElement(formElement);
+        return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey);
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionName
+       * @param string collectionElementIdentifier
+       * @return mixed
+       */
+      function getFormEditorDefinition(definitionName, subject) {
+        return _getRepository().getFormEditorDefinition(definitionName, subject);
+      };
+
+      /**
+       * @public
+       *
+       * @param string validatorIdentifier
+       * @return object (dereferenced)
+       * @throws 1475672362
+       */
+      function getFormElementPropertyValidatorDefinition(validatorIdentifier) {
+        var validatorDefinition;
+        assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362);
+
+        validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier);
+        return $.extend(true, {}, validatorDefinition);
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getCurrentlySelectedPageIndex() {
+        return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex');
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function refreshCurrentlySelectedPageIndex() {
+        _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement()));
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       * @throws 1477786068
+       */
+      function getCurrentlySelectedPage() {
+        var currentPage;
+
+        currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()];
+        assert('object' === $.type(currentPage), 'No page found', 1477786068);
+        return currentPage;
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getLastTopLevelElementOnCurrentPage() {
+        var lastRenderable, renderables;
+
+        renderables = getCurrentlySelectedPage().get('renderables');
+        if (getUtility().isUndefinedOrNull(renderables)) {
+          return undefined;
+        }
+        lastRenderable = renderables[renderables.length - 1];
+        return lastRenderable;
+      };
+
+      /**
+       * @public
+       *
+       * @param object
+       * @return object
+       */
+      function getLastFormElementWithinParentFormElement(formElement) {
+        var lastElement;
+
+        formElement = _getRepository().findFormElement(formElement);
+        if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) {
+          return formElement;
+        }
+        return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1];
+      };
+
+      /**
+       * @public
+       *
+       * @param object
+       * @return int
+       */
+      function getPageIndexFromFormElement(formElement) {
+        formElement = _getRepository().findFormElement(formElement);
+
+        return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(
+          formElement
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function renderCurrentFormPage() {
+        renderFormPage(getCurrentlySelectedPageIndex());
+      };
+
+      /**
+       * @public
+       *
+       * @param int pageIndex
+       * @return void
+       * @throws 1475446442
+       */
+      function renderFormPage(pageIndex) {
+        assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442);
+        _getDataBackend().renderFormDefinitionPage(pageIndex);
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object|null
+       */
+      function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) {
+        return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(
+          _getRepository().findFormElement(formElement)
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object|null
+       */
+      function findEnclosingGridContainerFormElement(formElement) {
+        return _getRepository().findEnclosingGridContainerFormElement(
+          _getRepository().findFormElement(formElement)
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object|null
+       */
+      function findEnclosingGridRowFormElement(formElement) {
+        return _getRepository().findEnclosingGridRowFormElement(
+          _getRepository().findFormElement(formElement)
+        );
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getNonCompositeNonToplevelFormElements() {
+        return _getRepository().getNonCompositeNonToplevelFormElements();
+      };
+
+      /**
+       * @public
+       *
+       * @return boolean
+       */
+      function isRootFormElementSelected() {
+        return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath'));
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getViewModel() {
+        return _viewModel;
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function saveFormDefinition() {
+        _getDataBackend().saveFormDefinition();
+      };
+
+      /**
+       * @private
+       *
+       * @return object
+       */
+      function _getDataBackend() {
+        return _core.getDataBackend();
+      };
+
+      /**
+       * @private
+       *
+       * @return object
+       */
+      function _getFactory() {
+        return _core.getFactory();
+      };
+
+      /**
+       * @private
+       *
+       * @return object
+       */
+      function _getRepository() {
+        return _core.getRepository();
+      };
+
+      /**
+       * @private
+       *
+       * @return object
+       */
+      function _getPropertyValidationService() {
+        return _core.getPropertyValidationService();
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function _getApplicationStateStack() {
+        return _core.getApplicationStateStack();
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       * @publish ajax/beforeSend
+       * @publish ajax/complete
+       */
+      function _ajaxSetup() {
+        $.ajaxSetup({
+          beforeSend: function() {
+            getPublisherSubscriber().publish('ajax/beforeSend');
+          },
+          complete: function() {
+            getPublisherSubscriber().publish('ajax/complete');
+          }
+        });
+      };
+
+      /**
+       * @private
+       *
+       * @param object endpoints
+       * @param string prototypeName
+       * @param string formPersistenceIdentifier
+       * @return void
+       * @throws 1475379748
+       * @throws 1475379749
+       * @throws 1475927876
+       */
+      function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) {
+        assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748);
+        assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876);
+        assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749);
+
+        _core.getDataBackend().setEndpoints(endpoints);
+        _core.getDataBackend().setPrototypeName(prototypeName);
+        _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier);
+      };
+
+      /**
+       * @private
+       *
+       * @param object formEditorDefinitions
+       * @return void
+       * @throws 1475379750
+       */
+      function _repositorySetup(formEditorDefinitions) {
+        assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750);
+
+        _getRepository().setFormEditorDefinitions(formEditorDefinitions);
+      }
+
+      /**
+       * @private
+       *
+       * @param object additionalViewModelModules
+       * @return void
+       * @throws 1475379752
+       * @throws 1475492374
+       */
+      function _viewSetup(additionalViewModelModules) {
+        assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374);
+
+        if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) {
+          assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752);
+        } else {
+          additionalViewModelModules = [];
+        }
+        _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules);
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       * @throws 1475492032
+       */
+      function _mediatorSetup() {
+        assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032);
+        _mediator.bootstrap(_formEditorInstance, _viewModel);
+      };
+
+      /**
+       * @private
+       *
+       * @param object rootFormElement
+       * @param int maximumUndoSteps
+       * @return void
+       * @throws 1475379751
+       */
+      function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) {
+        assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751);
+
+        if ('number' !== $.type(maximumUndoSteps)) {
+          maximumUndoSteps = 10;
+        }
+        _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps);
+
+        _getApplicationStateStack().addAndReset({
+          currentlySelectedPageIndex: 0,
+          currentlySelectedFormElementIdentifierPath: rootFormElement['identifier']
+        }, true);
+
+        _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true));
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       */
+      function _bootstrap() {
+        _configuration = _configuration || {};
+
+        _mediatorSetup();
+        _ajaxSetup();
+        _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']);
+        _repositorySetup(_configuration['formEditorDefinitions']);
+        _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']);
+        setCurrentlySelectedFormElement(_getRepository().getRootFormElement());
+
+        _viewSetup(_configuration['additionalViewModelModules']);
+      };
+
+      /**
+       * @public
+       *
+       * @return TYPO3/CMS/Form/Backend/FormEditor
+       * @throws 1473200696
+       */
+      function run() {
+        if (_isRunning) {
+          throw 'You can not run the app twice (1473200696)';
+        }
+
+        _bootstrap();
+        _isRunning = true;
+        return this;
+      };
+
+      /**
+       * Publish the public methods.
+       * Implements the "Revealing Module Pattern".
+       */
+      return {
+        getRootFormElement: getRootFormElement,
+
+        createAndAddFormElement: createAndAddFormElement,
+        createFormElement: createFormElement,
+        addFormElement: addFormElement,
+        moveFormElement: moveFormElement,
+        removeFormElement: removeFormElement,
+
+        getCurrentlySelectedFormElement: getCurrentlySelectedFormElement,
+        setCurrentlySelectedFormElement: setCurrentlySelectedFormElement,
+
+        getFormElementByIdentifierPath: getFormElementByIdentifierPath,
+        isFormElementIdentifierUsed: isFormElementIdentifierUsed,
+
+        createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
+        createPropertyCollectionElement: createPropertyCollectionElement,
+        addPropertyCollectionElement: addPropertyCollectionElement,
+        removePropertyCollectionElement: removePropertyCollectionElement,
+        movePropertyCollectionElement: movePropertyCollectionElement,
+        getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement,
+        getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration,
+
+        saveFormDefinition: saveFormDefinition,
+        renderCurrentFormPage: renderCurrentFormPage,
+        renderFormPage: renderFormPage,
+
+        getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex,
+        refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex,
+        getPageIndexFromFormElement: getPageIndexFromFormElement,
+        getCurrentlySelectedPage: getCurrentlySelectedPage,
+        getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage,
+        findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel,
+        findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement,
+        findEnclosingGridRowFormElement: findEnclosingGridRowFormElement,
+        isRootFormElementSelected: isRootFormElementSelected,
+        getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement,
+        getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements,
+
+        getFormElementDefinitionByType: getFormElementDefinitionByType,
+        getFormElementDefinition: getFormElementDefinition,
+        getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition,
+        getFormEditorDefinition: getFormEditorDefinition,
+
+        getPublisherSubscriber: getPublisherSubscriber,
+        getRunningAjaxRequest: getRunningAjaxRequest,
+
+        setUnsavedContent: setUnsavedContent,
+        getUnsavedContent: getUnsavedContent,
+
+        addPropertyValidationValidator: addPropertyValidationValidator,
+        validateFormElementProperty: validateFormElementProperty,
+        validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty,
+        validateFormElement: validateFormElement,
+        validateFormElementRecursive: validateFormElementRecursive,
+        validationResultsHasErrors: validationResultsHasErrors,
+
+        getUtility: getUtility,
+        assert: assert,
+        buildPropertyPath: buildPropertyPath,
+
+        getViewModel: getViewModel,
+        undoApplicationState: undoApplicationState,
+        redoApplicationState: redoApplicationState,
+        getMaximalApplicationStates: getMaximalApplicationStates,
+        getCurrentApplicationStates: getCurrentApplicationStates,
+        getCurrentApplicationStatePosition: getCurrentApplicationStatePosition,
+
+        run: run
+      };
+    };
 
     /**
-     * Return a static method named "getInstance".
-     * Use this method to create the formeditor app.
+     * Emulation of static methods
      */
-    return (function(_core) {
-
-        /**
-         * @private
-         *
-         * Hold the instance (Singleton Pattern)
-         */
-        var _formEditorInstance = null;
-
-        /**
-         * @public
-         *
-         * @param object _configuration
-         * @param object _mediator
-         * @param object _viewModel
-         * @return object
-         */
-        function FormEditor(_configuration, _mediator, _viewModel) {
-
-            /**
-             * @private
-             *
-             * @var bool
-             */
-            var _isRunning = false;
-
-            /**
-             * @private
-             *
-             * @var bool
-             */
-            var _unsavedContent = false;
-
-            /**
-             * @private
-             *
-             * @var bool
-             */
-            var _previewMode = false;
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getPublisherSubscriber() {
-                return _core.getPublisherSubscriber();
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function _saveApplicationState() {
-
-                _getApplicationStateStack().addAndReset({
-                    formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(),
-                    currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'),
-                    currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')
-                });
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function undoApplicationState() {
-                _getApplicationStateStack().incrementCurrentStackPointer();
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function redoApplicationState() {
-                _getApplicationStateStack().decrementCurrentStackPointer();
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getMaximalApplicationStates() {
-                return _getApplicationStateStack().getMaximalStackSize();
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getCurrentApplicationStates() {
-                return _getApplicationStateStack().getCurrentStackSize();
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getCurrentApplicationStatePosition() {
-                return _getApplicationStateStack().getCurrentStackPointer();
-            };
-
-            /**
-             * @public
-             *
-             * @param string type
-             * @return object
-             * @throws 1475378543
-             */
-            function getRunningAjaxRequest(type) {
-                assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543);
-                return _core.getRunningAjaxRequest(type);
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getUtility() {
-                return _core.getUtility();
-            };
-
-            /**
-             * @public
-             *
-             * @param mixed test
-             * @param string message
-             * @param int messageCode
-             * @return void
-             */
-            function assert(test, message, messageCode) {
-                getUtility().assert(test, message, messageCode);
-            };
-
-            /**
-             * @public
-             *
-             * @param string propertyPath
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object formElement
-             * @param boolean allowEmptyReturnValue
-             * @return string
-             */
-            function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) {
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElement = getCurrentlySelectedFormElement();
-                }
-                formElement = _getRepository().findFormElement(formElement);
-                return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue);
-            };
-
-            /**
-             * @public
-             *
-             * @param string validatorIdentifier
-             * @param function func
-             * @return void
-             */
-            function addPropertyValidationValidator(validatorIdentifier, func) {
-                _getPropertyValidationService().addValidator(validatorIdentifier, func);
-            };
-
-            /**
-             * @public
-             *
-             * @param string propertyPath
-             * @return object
-             */
-            function validateCurrentlySelectedFormElementProperty(propertyPath) {
-                return validateFormElementProperty(
-                    getCurrentlySelectedFormElement(),
-                    propertyPath
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string propertyPath
-             * @return object
-             */
-            function validateFormElementProperty(formElement, propertyPath) {
-                formElement = _getRepository().findFormElement(formElement);
-                return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath);
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object
-             */
-            function validateFormElement(formElement) {
-                formElement = _getRepository().findFormElement(formElement);
-                return _getPropertyValidationService().validateFormElement(formElement);
-            };
-
-            /**
-             * @public
-             *
-             * @param object validationResults
-             * @return boolean
-             */
-            function validationResultsHasErrors(validationResults) {
-                return _getPropertyValidationService().validationResultsHasErrors(validationResults);
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param boolean returnAfterFirstMatch
-             * @return object
-             */
-            function validateFormElementRecursive(formElement, returnAfterFirstMatch) {
-                formElement = _getRepository().findFormElement(formElement);
-                return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch);
-            };
-
-            /**
-             * @public
-             *
-             * @param bool unsavedContent
-             * @return void
-             * @throws 1475378544
-             */
-            function setUnsavedContent(unsavedContent) {
-                assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544);
-                _unsavedContent = unsavedContent;
-            };
-
-            /**
-             * @public
-             *
-             * @return boolean
-             */
-            function getUnsavedContent() {
-                return _unsavedContent;
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getRootFormElement() {
-                return _getRepository().getRootFormElement();
-            };
-
-            /**
-             * @public
-             *
-             * @return string
-             */
-            function getCurrentlySelectedFormElement() {
-                return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath'));
-            };
-
-            /**
-             * @public
-             *
-             * @param string|object formElement
-             * @param boolean doNotRefreshCurrentlySelectedPageIndex
-             * @return void
-             * @publish core/currentlySelectedFormElementChanged
-             */
-            function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) {
-                doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex;
-
-                formElement = _getRepository().findFormElement(formElement);
-                _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath'));
-
-                if (!doNotRefreshCurrentlySelectedPageIndex) {
-                    refreshCurrentlySelectedPageIndex();
-                }
-                getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]);
-            };
-
-            /**
-             * @public
-             *
-             * @param string identifierPath
-             * @return object
-             * @throws 1475378545
-             */
-            function getFormElementByIdentifierPath(identifierPath) {
-                assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545);
-                return _getRepository().findFormElementByIdentifierPath(identifierPath);
-            };
-
-            /**
-             * @public
-             *
-             * @param string identifierPath
-             * @return bool
-             */
-            function isFormElementIdentifierUsed(formElementIdentifier) {
-                return _getRepository().isFormElementIdentifierUsed(formElementIdentifier);
-            }
-
-            /**
-             * @public
-             *
-             * @param string formElementType
-             * @param string|object referenceFormElement
-             * @param boolean disablePublishersOnSet
-             * @return object
-             */
-            function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
-                var formElement;
-                formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet);
-                formElement.set('renderables', formElement.get('renderables'));
-                return formElement;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string|object referenceFormElement
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475434337
-             */
-            function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) {
-                _saveApplicationState();
-
-                if (getUtility().isUndefinedOrNull(referenceFormElement)) {
-                    referenceFormElement = getCurrentlySelectedFormElement();
-                }
-                referenceFormElement = _getRepository().findFormElement(referenceFormElement);
-                assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337);
-                return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet);
-            };
-
-            /**
-             * @public
-             *
-             * @param string formElementType
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475434336
-             * @throws 1475435857
-             */
-            function createFormElement(formElementType, disablePublishersOnSet) {
-                var formElementDefinition, identifier;
-                assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336);
-
-                identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType);
-                formElementDefinition = getFormElementDefinitionByType(formElementType);
-                return _getFactory().createFormElement({
-                    type: formElementType,
-                    identifier: identifier,
-                    label: formElementDefinition['label'] || formElementType
-                }, undefined, undefined, undefined, disablePublishersOnSet);
-            };
-
-            /**
-             * @public
-             *
-             * @param string|object formElementToRemove
-             * @param boolean disablePublishersOnSet
-             * @return object
-             */
-            function removeFormElement(formElementToRemove, disablePublishersOnSet) {
-                var parentFormElement;
-                _saveApplicationState();
-
-                formElementToRemove = _getRepository().findFormElement(formElementToRemove);
-                parentFormElement = formElementToRemove.get('__parentRenderable');
-                _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet);
-                return parentFormElement;
-            };
-
-            /**
-             * @public
-             *
-             * @param string|object formElementToMove
-             * @param string position
-             * @param string|object referenceFormElement
-             * @param boolean disablePublishersOnSet
-             * @return string
-             * @throws 1475378551
-             */
-            function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
-                _saveApplicationState();
-
-                formElementToMove = _getRepository().findFormElement(formElementToMove);
-                referenceFormElement = _getRepository().findFormElement(referenceFormElement);
-
-                assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551);
-
-                formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true);
-                disablePublishersOnSet = !!disablePublishersOnSet;
-                if (!disablePublishersOnSet) {
-                    formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables'));
-                }
-                return formElementToMove;
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param string formElement
-             * @return object (dereferenced)
-             * @throws 1475378555
-             * @throws 1475378556
-             * @throws 1475446108
-             */
-            function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) {
-                var collection, collectionElement, formElementDefinition;
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElement = getCurrentlySelectedFormElement();
-                }
-                formElement = _getRepository().findFormElement(formElement);
-
-                assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556);
-
-                formElementDefinition = getFormElementDefinitionByType(formElement.get('type'));
-                if (!getUtility().isUndefinedOrNull(formElementDefinition['propertyCollections'])) {
-                    collection = formElementDefinition['propertyCollections'][collectionName];
-                    assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108);
-                    collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection);
-                    return $.extend(true, {}, collectionElement);
-                } else {
-                    return {};
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param string formElement
-             * @return int
-             * @throws 1475378557
-             * @throws 1475378558
-             */
-            function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) {
-                var indexFromPropertyCollectionElement;
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElement = getCurrentlySelectedFormElement();
-                }
-                formElement = _getRepository().findFormElement(formElement);
-
-                assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558);
-
-                indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier(
-                    collectionElementIdentifier,
-                    collectionName,
-                    formElement
-                );
-
-                return indexFromPropertyCollectionElement;
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object formElement
-             * @param object collectionElementConfiguration
-             * @param string referenceCollectionElementIdentifier
-             * @return object
-             */
-            function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) {
-                return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier);
-            };
-
-            /**
-             * @public
-             *
-             * @param object collectionElement
-             * @param string collectionName
-             * @param string|object formElement
-             * @param string referenceCollectionElementIdentifier
-             * @return object
-             * @throws 1475443300
-             * @throws 1475443301
-             */
-            function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) {
-                var collection;
-                _saveApplicationState();
-
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElement = getCurrentlySelectedFormElement();
-                }
-                formElement = _getRepository().findFormElement(formElement);
-
-                assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300);
-
-                if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) {
-                    collection = formElement.get(collectionName);
-                    if ('array' === $.type(collection) && collection.length > 0) {
-                        referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier'];
-                    }
-                }
-
-                return _getRepository().addPropertyCollectionElement(
-                    collectionElement,
-                    collectionName,
-                    formElement,
-                    referenceCollectionElementIdentifier,
-                    false
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object collectionElementConfiguration
-             * @return void
-             * @throws 1475378559
-             * @throws 1475378560
-             */
-            function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) {
-                assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560);
-                if ('object' !== $.type(collectionElementConfiguration)) {
-                    collectionElementConfiguration = {};
-                }
-
-                return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName);
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param string formElement
-             * @param bool disablePublishersOnSet
-             * @return void
-             * @throws 1475378561
-             * @throws 1475378562
-             */
-            function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
-                _saveApplicationState();
-
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElement = getCurrentlySelectedFormElement();
-                }
-                formElement = _getRepository().findFormElement(formElement);
-
-                assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562);
-
-                _getRepository().removePropertyCollectionElementByIdentifier(
-                    formElement,
-                    collectionElementIdentifier,
-                    collectionName,
-                    true
-                );
-
-                disablePublishersOnSet = !!disablePublishersOnSet;
-                if (!disablePublishersOnSet) {
-                    getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']);
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementToMove
-             * @param string position
-             * @param string referenceCollectionElement
-             * @param string collectionName
-             * @param object formElement
-             * @param boolean disablePublishersOnSet
-             * @return string
-             * @throws 1477404352
-             * @throws 1477404353
-             * @throws 1477404354
-             * @throws 1477404355
-             */
-            function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
-                _saveApplicationState();
-
-                formElement = _getRepository().findFormElement(formElement);
-
-                assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352);
-                assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353);
-                assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354);
-                assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355);
-
-                return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet);
-            };
-
-            /**
-             * @public
-             *
-             * @param string elementType
-             * @param string formElementDefinitionKey
-             * @returnmixed
-             * @throws 1475378563
-             */
-            function getFormElementDefinitionByType(elementType, formElementDefinitionKey) {
-                var formElementDefinition;
-                assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563);
-
-                formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType);
-
-                if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) {
-                    formElementDefinition = formElementDefinition[formElementDefinitionKey];
-                }
-
-                if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) {
-                    return $.extend(true, {}, formElementDefinition);
-                } else {
-                    return formElementDefinition;
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string formElementDefinitionKey
-             * @return mixed
-             */
-            function getFormElementDefinition(formElement, formElementDefinitionKey) {
-                formElement = _getRepository().findFormElement(formElement);
-                return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey);
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionName
-             * @param string collectionElementIdentifier
-             * @return mixed
-             */
-            function getFormEditorDefinition(definitionName, subject) {
-                return _getRepository().getFormEditorDefinition(definitionName, subject);
-            };
-
-            /**
-             * @public
-             *
-             * @param string validatorIdentifier
-             * @return object (dereferenced)
-             * @throws 1475672362
-             */
-            function getFormElementPropertyValidatorDefinition(validatorIdentifier) {
-                var validatorDefinition;
-                assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362);
-
-                validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier);
-                return $.extend(true, {}, validatorDefinition);
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getCurrentlySelectedPageIndex() {
-                return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex');
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function refreshCurrentlySelectedPageIndex() {
-                _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement()));
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             * @throws 1477786068
-             */
-            function getCurrentlySelectedPage() {
-                var currentPage;
-
-                currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()];
-                assert('object' === $.type(currentPage), 'No page found', 1477786068);
-                return currentPage;
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getLastTopLevelElementOnCurrentPage() {
-                var lastRenderable, renderables;
-
-                renderables = getCurrentlySelectedPage().get('renderables');
-                if (getUtility().isUndefinedOrNull(renderables)) {
-                    return undefined;
-                }
-                lastRenderable = renderables[renderables.length - 1];
-                return lastRenderable;
-            };
-
-            /**
-             * @public
-             *
-             * @param object
-             * @return object
-             */
-            function getLastFormElementWithinParentFormElement(formElement) {
-                var lastElement;
-
-                formElement = _getRepository().findFormElement(formElement);
-                if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) {
-                    return formElement;
-                }
-                return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1];
-            };
-
-            /**
-             * @public
-             *
-             * @param object
-             * @return int
-             */
-            function getPageIndexFromFormElement(formElement) {
-                formElement = _getRepository().findFormElement(formElement);
-
-                return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(
-                    formElement
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function renderCurrentFormPage() {
-                renderFormPage(getCurrentlySelectedPageIndex());
-            };
-
-            /**
-             * @public
-             *
-             * @param int pageIndex
-             * @return void
-             * @throws 1475446442
-             */
-            function renderFormPage(pageIndex) {
-                assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442);
-                _getDataBackend().renderFormDefinitionPage(pageIndex);
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object|null
-             */
-            function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) {
-                return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(
-                    _getRepository().findFormElement(formElement)
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object|null
-             */
-            function findEnclosingGridContainerFormElement(formElement) {
-                return _getRepository().findEnclosingGridContainerFormElement(
-                    _getRepository().findFormElement(formElement)
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object|null
-             */
-            function findEnclosingGridRowFormElement(formElement) {
-                return _getRepository().findEnclosingGridRowFormElement(
-                    _getRepository().findFormElement(formElement)
-                );
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getNonCompositeNonToplevelFormElements() {
-                return _getRepository().getNonCompositeNonToplevelFormElements();
-            };
-
-            /**
-             * @public
-             *
-             * @return boolean
-             */
-            function isRootFormElementSelected() {
-                return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath'));
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getViewModel() {
-                return _viewModel;
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function saveFormDefinition() {
-                _getDataBackend().saveFormDefinition();
-            };
-
-            /**
-             * @private
-             *
-             * @return object
-             */
-            function _getDataBackend() {
-                return _core.getDataBackend();
-            };
-
-            /**
-             * @private
-             *
-             * @return object
-             */
-            function _getFactory() {
-                return _core.getFactory();
-            };
-
-            /**
-             * @private
-             *
-             * @return object
-             */
-            function _getRepository() {
-                return _core.getRepository();
-            };
-
-            /**
-             * @private
-             *
-             * @return object
-             */
-            function _getPropertyValidationService() {
-                return _core.getPropertyValidationService();
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function _getApplicationStateStack() {
-                return _core.getApplicationStateStack();
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             * @publish ajax/beforeSend
-             * @publish ajax/complete
-             */
-            function _ajaxSetup() {
-                $.ajaxSetup({
-                    beforeSend: function() {
-                        getPublisherSubscriber().publish('ajax/beforeSend');
-                    },
-                    complete: function() {
-                        getPublisherSubscriber().publish('ajax/complete');
-                    }
-                });
-            };
-
-            /**
-             * @private
-             *
-             * @param object endpoints
-             * @param string prototypeName
-             * @param string formPersistenceIdentifier
-             * @return void
-             * @throws 1475379748
-             * @throws 1475379749
-             * @throws 1475927876
-             */
-            function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) {
-                assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748);
-                assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876);
-                assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749);
-
-                _core.getDataBackend().setEndpoints(endpoints);
-                _core.getDataBackend().setPrototypeName(prototypeName);
-                _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier);
-            };
-
-            /**
-             * @private
-             *
-             * @param object formEditorDefinitions
-             * @return void
-             * @throws 1475379750
-             */
-            function _repositorySetup(formEditorDefinitions) {
-                assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750);
-
-                _getRepository().setFormEditorDefinitions(formEditorDefinitions);
-            }
-
-            /**
-             * @private
-             *
-             * @param object additionalViewModelModules
-             * @return void
-             * @throws 1475379752
-             * @throws 1475492374
-             */
-            function _viewSetup(additionalViewModelModules) {
-                assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374);
-
-                if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) {
-                    assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752);
-                } else {
-                    additionalViewModelModules = [];
-                }
-                _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules);
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             * @throws 1475492032
-             */
-            function _mediatorSetup() {
-                assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032);
-                _mediator.bootstrap(_formEditorInstance, _viewModel);
-            };
-
-            /**
-             * @private
-             *
-             * @param object rootFormElement
-             * @param int maximumUndoSteps
-             * @return void
-             * @throws 1475379751
-             */
-            function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) {
-                assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751);
-
-                if ('number' !== $.type(maximumUndoSteps)) {
-                    maximumUndoSteps = 10;
-                }
-                _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps);
-
-                _getApplicationStateStack().addAndReset({
-                    currentlySelectedPageIndex: 0,
-                    currentlySelectedFormElementIdentifierPath: rootFormElement['identifier']
-                }, true);
-
-                _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true));
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             */
-            function _bootstrap() {
-                _configuration = _configuration || {};
-
-                _mediatorSetup();
-                _ajaxSetup();
-                _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']);
-                _repositorySetup(_configuration['formEditorDefinitions']);
-                _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']);
-                setCurrentlySelectedFormElement(_getRepository().getRootFormElement());
-
-                _viewSetup(_configuration['additionalViewModelModules']);
-            };
-
-            /**
-             * @public
-             *
-             * @return TYPO3/CMS/Form/Backend/FormEditor
-             * @throws 1473200696
-             */
-            function run() {
-                if (_isRunning) {
-                    throw 'You can not run the app twice (1473200696)';
-                }
-
-                _bootstrap();
-                _isRunning = true;
-                return this;
-            };
-
-            /**
-             * Publish the public methods.
-             * Implements the "Revealing Module Pattern".
-             */
-            return {
-                getRootFormElement: getRootFormElement,
-
-                createAndAddFormElement: createAndAddFormElement,
-                createFormElement: createFormElement,
-                addFormElement: addFormElement,
-                moveFormElement: moveFormElement,
-                removeFormElement: removeFormElement,
-
-                getCurrentlySelectedFormElement: getCurrentlySelectedFormElement,
-                setCurrentlySelectedFormElement: setCurrentlySelectedFormElement,
-
-                getFormElementByIdentifierPath: getFormElementByIdentifierPath,
-                isFormElementIdentifierUsed: isFormElementIdentifierUsed,
-
-                createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
-                createPropertyCollectionElement: createPropertyCollectionElement,
-                addPropertyCollectionElement: addPropertyCollectionElement,
-                removePropertyCollectionElement: removePropertyCollectionElement,
-                movePropertyCollectionElement: movePropertyCollectionElement,
-                getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement,
-                getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration,
-
-                saveFormDefinition: saveFormDefinition,
-                renderCurrentFormPage: renderCurrentFormPage,
-                renderFormPage: renderFormPage,
-
-                getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex,
-                refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex,
-                getPageIndexFromFormElement: getPageIndexFromFormElement,
-                getCurrentlySelectedPage: getCurrentlySelectedPage,
-                getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage,
-                findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel,
-                findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement,
-                findEnclosingGridRowFormElement: findEnclosingGridRowFormElement,
-                isRootFormElementSelected: isRootFormElementSelected,
-                getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement,
-                getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements,
-
-                getFormElementDefinitionByType: getFormElementDefinitionByType,
-                getFormElementDefinition: getFormElementDefinition,
-                getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition,
-                getFormEditorDefinition: getFormEditorDefinition,
-
-                getPublisherSubscriber: getPublisherSubscriber,
-                getRunningAjaxRequest: getRunningAjaxRequest,
-
-                setUnsavedContent: setUnsavedContent,
-                getUnsavedContent: getUnsavedContent,
-
-                addPropertyValidationValidator: addPropertyValidationValidator,
-                validateFormElementProperty: validateFormElementProperty,
-                validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty,
-                validateFormElement: validateFormElement,
-                validateFormElementRecursive: validateFormElementRecursive,
-                validationResultsHasErrors: validationResultsHasErrors,
-
-                getUtility: getUtility,
-                assert: assert,
-                buildPropertyPath: buildPropertyPath,
-
-                getViewModel: getViewModel,
-                undoApplicationState: undoApplicationState,
-                redoApplicationState: redoApplicationState,
-                getMaximalApplicationStates: getMaximalApplicationStates,
-                getCurrentApplicationStates: getCurrentApplicationStates,
-                getCurrentApplicationStatePosition: getCurrentApplicationStatePosition,
-
-                run: run
-            };
-        };
-
-        /**
-         * Emulation of static methods
-         */
-        return {
-            /**
-             * @public
-             * @static
-             *
-             * Implement the "Singleton Pattern".
-             *
-             * Return a singleton instance of a
-             * "FormEditor" object.
-             *
-             * @param object configuration
-             * @param object mediator
-             * @param object viewModel
-             * @return object
-             */
-            getInstance: function(configuration, mediator, viewModel) {
-                if(_formEditorInstance === null) {
-                    _formEditorInstance = new FormEditor(configuration, mediator, viewModel);
-                }
-                return _formEditorInstance;
-            }
-        };
-    })(core);
+    return {
+      /**
+       * @public
+       * @static
+       *
+       * Implement the "Singleton Pattern".
+       *
+       * Return a singleton instance of a
+       * "FormEditor" object.
+       *
+       * @param object configuration
+       * @param object mediator
+       * @param object viewModel
+       * @return object
+       */
+      getInstance: function(configuration, mediator, viewModel) {
+        if (_formEditorInstance === null) {
+          _formEditorInstance = new FormEditor(configuration, mediator, viewModel);
+        }
+        return _formEditorInstance;
+      }
+    };
+  })(core);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js
index b135e577d524..965fe93ce525 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Core.js
@@ -15,1739 +15,923 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/Core
  */
 define(['jquery'], function($) {
-        'use strict';
-
-    return (function($) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _dataBackendEndpoints = {};
-
-        /**
-         * @private
-         *
-         * @var string
-         */
-        var _dataBackendPrototypeName = null;
-
-        /**
-         * @private
-         *
-         * @var string
-         */
-        var _dataBackendPersistenceIdentifier = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _publisherSubscriberTopics = {};
-
-        /**
-         * @private
-         *
-         * @var int
-         */
-        var _publisherSubscriberUid = -1;
+  'use strict';
+
+  return (function($) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _dataBackendEndpoints = {};
+
+    /**
+     * @private
+     *
+     * @var string
+     */
+    var _dataBackendPrototypeName = null;
+
+    /**
+     * @private
+     *
+     * @var string
+     */
+    var _dataBackendPersistenceIdentifier = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _publisherSubscriberTopics = {};
+
+    /**
+     * @private
+     *
+     * @var int
+     */
+    var _publisherSubscriberUid = -1;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _repositoryFormEditorDefinitions = {};
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _runningAjaxRequests = [];
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _propertyValidationServiceValidators = {};
+
+    /**
+     * @private
+     *
+     * @var int
+     */
+    var _applicationStateStackSize = 10;
+
+    /**
+     * @private
+     *
+     * @var int
+     */
+    var _applicationStateStackPointer = 0;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _applicationStateStack = [];
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function utility() {
+
+      /**
+       * @public
+       *
+       * @param mixed test
+       * @param string message
+       * @param int messageCode
+       * @return void
+       */
+      function assert(test, message, messageCode) {
+        if ('function' === $.type(test)) {
+          test = (test() !== false);
+        }
+        if (!test) {
+          message = message || "Assertion failed";
+          if (messageCode) {
+            message = message + ' (' + messageCode + ')';
+          }
+          if ('undefined' !== typeof Error) {
+            throw new Error(message);
+          }
+          throw message;
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param mixed value
+       * @return bool
+       */
+      function isUndefinedOrNull(value) {
+        return ('undefined' === $.type(value) || 'null' === $.type(value));
+      };
+
+      /**
+       * @public
+       *
+       * @param mixed value
+       * @return bool
+       */
+      function isNonEmptyString(value) {
+        return ('string' === $.type(value) && value.length > 0);
+      };
+
+      /**
+       * @public
+       *
+       * @param string propertyPath
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object formElement
+       * @param boolean allowEmptyReturnValue
+       * @return string
+       * @throws 1475412569
+       * @throws 1475412570
+       * @throws 1475415988
+       * @throws 1475663210
+       */
+      function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) {
+        var newPropertyPath = '';
+
+        allowEmptyReturnValue = !!allowEmptyReturnValue;
+        if (isNonEmptyString(collectionElementIdentifier) || isNonEmptyString(collectionName)) {
+          assert(isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475412569);
+          assert(isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475412570);
+          newPropertyPath = collectionName + '.' + repository().getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement);
+        } else {
+          newPropertyPath = '';
+        }
+
+        if (!isUndefinedOrNull(propertyPath)) {
+          assert(isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475415988);
+          if (isNonEmptyString(newPropertyPath)) {
+            newPropertyPath = newPropertyPath + '.' + propertyPath;
+          } else {
+            newPropertyPath = propertyPath;
+          }
+        }
+
+        if (!allowEmptyReturnValue) {
+          assert(isNonEmptyString(newPropertyPath), 'The property path could not be resolved', 1475663210);
+        }
+        return newPropertyPath;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object
+       * @throws 1475377782
+       */
+      function convertToSimpleObject(formElement) {
+        var childFormElements, simpleObject, objectData;
+        assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475377782);
+
+        simpleObject = {};
+        objectData = ('function' === $.type(formElement.getObjectData)) ? formElement.getObjectData() : formElement;
+        childFormElements = objectData['renderables'];
+        delete objectData['renderables'];
+
+        for (var key in objectData) {
+          if (!objectData.hasOwnProperty(key)) {
+            continue;
+          }
+          var value = objectData[key];
+          if (key.match(/^__/)) {
+            continue;
+          }
+
+          if ('object' === $.type(value)) {
+            simpleObject[key] = convertToSimpleObject(value);
+          } else if ('function' !== $.type(value) && 'undefined' !== $.type(value)) {
+            simpleObject[key] = value;
+          }
+        }
+
+        if ('array' === $.type(childFormElements)) {
+          simpleObject['renderables'] = [];
+          for (var i = 0, len = childFormElements.length; i < len; ++i) {
+            simpleObject['renderables'].push(convertToSimpleObject(childFormElements[i]));
+          }
+        }
+
+        return simpleObject;
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        assert: assert,
+        convertToSimpleObject: convertToSimpleObject,
+        isNonEmptyString: isNonEmptyString,
+        isUndefinedOrNull: isUndefinedOrNull,
+        buildPropertyPath: buildPropertyPath
+      };
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function propertyValidationService() {
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param object validators
+       * @param string propertyPath
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object configuration
+       * @return void
+       * @throws 1475661025
+       * @throws 1475661026
+       * @throws 1479238074
+       */
+      function addValidatorIdentifiersToFormElementProperty(formElement, validators, propertyPath, collectionElementIdentifier, collectionName, configuration) {
+        var formElementIdentifierPath, propertyPath, propertyValidationServiceRegisteredValidators;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475661025);
+        utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1475661026);
+        utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1479238074);
+
+        formElementIdentifierPath = formElement.get('__identifierPath');
+        propertyPath = utility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement);
+
+        propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+        if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) {
+          propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = {};
+        }
+        if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])) {
+          propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath] = {
+            validators: [],
+            configuration: configuration
+          };
+        }
+        for (var i = 0, len = validators.length; i < len; ++i) {
+          if (propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].indexOf(validators[i]) === -1) {
+            propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].push(validators[i]);
+          }
+        }
+        getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string propertyPath
+       * @return void
+       * @throws 1475700618
+       * @throws 1475706896
+       */
+      function removeValidatorIdentifiersFromFormElementProperty(formElement, propertyPath) {
+        var formElementIdentifierPath, propertyValidationServiceRegisteredValidators,
+          registeredValidators;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475700618);
+        utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475706896);
+
+        formElementIdentifierPath = formElement.get('__identifierPath');
+
+        registeredValidators = {};
+        propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+        for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) {
+          if (
+            !propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)
+            || registeredPropertyPath.indexOf(propertyPath) > -1
+          ) {
+            continue;
+          }
+          registeredValidators[registeredPropertyPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][registeredPropertyPath];
+        }
+        propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = registeredValidators;
+        getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
+      };
+
+      /**
+       * @public
+       *
+       * @param string|object formElement
+       * @return void
+       * @throws 1475668189
+       */
+      function removeAllValidatorIdentifiersFromFormElement(formElement) {
+        var propertyValidationServiceRegisteredValidators, registeredValidators;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475668189);
+
+        registeredValidators = {};
+        propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+        for (var formElementIdentifierPath in propertyValidationServiceRegisteredValidators) {
+          if (
+            !propertyValidationServiceRegisteredValidators.hasOwnProperty(formElementIdentifierPath)
+            || formElementIdentifierPath === formElement.get('__identifierPath')
+            || formElementIdentifierPath.indexOf(formElement.get('__identifierPath') + '/') > -1
+          ) {
+            continue;
+          }
+          registeredValidators[formElementIdentifierPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath];
+        }
+        getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', registeredValidators);
+      };
+
+      /**
+       * @public
+       *
+       * @param string validatorIdentifier
+       * @param function func
+       * @return void
+       * @throws 1475669143
+       * @throws 1475669144
+       * @throws 1475669145
+       */
+      function addValidator(validatorIdentifier, func) {
+        utility().assert(utility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475669143);
+        utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475669144);
+        utility().assert('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier]), 'The validator "' + validatorIdentifier + '" is already registered', 1475669145);
+
+        _propertyValidationServiceValidators[validatorIdentifier] = func;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string propertyPath
+       * @param string errorMessage
+       * @return object
+       * @throws 1475676517
+       * @throws 1475676518
+       */
+      function validateFormElementProperty(formElement, propertyPath) {
+        var configuration, formElementIdentifierPath, propertyValidationServiceRegisteredValidators,
+          validationResults;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475676517);
+        utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475676518);
+
+        formElementIdentifierPath = formElement.get('__identifierPath');
+
+        validationResults = [];
+        propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+        configuration = {
+          propertyValidatorsMode: 'AND'
+        };
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-         var _repositoryFormEditorDefinitions = {};
+        if (
+          !utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])
+          && 'object' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])
+          && 'array' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'])
+        ) {
+          configuration = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['configuration'];
+          for (var i = 0, len = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length; i < len; ++i) {
+            var validatorIdentifier, validationResult;
+
+            validatorIdentifier = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'][i];
+            if ('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier])) {
+              continue;
+            }
+            validationResult = _propertyValidationServiceValidators[validatorIdentifier](formElement, propertyPath);
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _runningAjaxRequests = [];
+            if (utility().isNonEmptyString(validationResult)) {
+              validationResults.push(validationResult);
+            }
+          }
+        }
+
+        if (
+          validationResults.length > 0
+          && configuration['propertyValidatorsMode'] === 'OR'
+          && validationResults.length !== propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length
+        ) {
+          return [];
+        }
+
+        return validationResults;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return object
+       * @throws 1475749668
+       */
+      function validateFormElement(formElement) {
+        var formElementIdentifierPath, propertyValidationServiceRegisteredValidators,
+          validationResults;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475749668);
+
+        formElementIdentifierPath = formElement.get('__identifierPath');
+
+        validationResults = [];
+        propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+        if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) {
+          for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) {
+            var validationResult;
+            if (!propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)) {
+              continue;
+            }
+            validationResult = {
+              propertyPath: registeredPropertyPath,
+              validationResults: validateFormElementProperty(formElement, registeredPropertyPath)
+            };
+            validationResults.push(validationResult);
+          }
+        }
+        return validationResults;
+      };
+
+      /**
+       * @public
+       *
+       * @param array validationResults
+       * @return bool
+       * @throws 1478613477
+       */
+      function validationResultsHasErrors(validationResults) {
+        utility().assert('array' === $.type(validationResults), 'Invalid parameter "validationResults"', 1478613477);
+
+        for (var i = 0, len = validationResults.length; i < len; ++i) {
+          for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
+            if (
+              validationResults[i]['validationResults'][j]['validationResults']
+              && validationResults[i]['validationResults'][j]['validationResults'].length > 0
+            ) {
+              return true;
+            }
+          }
+        }
+        return false;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param boolean returnAfterFirstMatch
+       * @param object validationResults
+       * @return object
+       * @throws 1475749668
+       */
+      function validateFormElementRecursive(formElement, returnAfterFirstMatch, validationResults) {
+        var formElements, validationResult, validationResults;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475756764);
+        returnAfterFirstMatch = !!returnAfterFirstMatch;
+
+        validationResults = validationResults || [];
+        validationResult = {
+          formElementIdentifierPath: formElement.get('__identifierPath'),
+          validationResults: validateFormElement(formElement)
+        };
+        validationResults.push(validationResult);
+
+        if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) {
+          return validationResults;
+        }
+
+        formElements = formElement.get('renderables');
+        if ('array' === $.type(formElements)) {
+          for (var i = 0, len = formElements.length; i < len; ++i) {
+            validateFormElementRecursive(formElements[i], returnAfterFirstMatch, validationResults);
+            if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) {
+              return validationResults;
+            }
+          }
+        }
+
+        return validationResults;
+      }
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @return void
+       * @throws 1475707334
+       */
+      function addValidatorIdentifiersFromFormElementPropertyCollections(formElement) {
+        var formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475707334);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+
+        if (!utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'])) {
+          for (var collectionName in formElementTypeDefinition['propertyCollections']) {
+            if (
+              !formElementTypeDefinition['propertyCollections'].hasOwnProperty(collectionName)
+              || 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName])
+            ) {
+              continue;
+            }
+            for (var i = 0, len1 = formElementTypeDefinition['propertyCollections'][collectionName].length; i < len1; ++i) {
+              if (
+                'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'])
+                || repository().getIndexFromPropertyCollectionElementByIdentifier(formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], collectionName, formElement) === -1
+              ) {
+                continue;
+              }
+              for (var j = 0, len2 = formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'].length; j < len2; ++j) {
+                var configuration = {};
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _propertyValidationServiceValidators = {};
+                if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) {
+                  continue;
+                }
 
-        /**
-         * @private
-         *
-         * @var int
-         */
-        var _applicationStateStackSize = 10;
+                if (
+                  !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'])
+                  && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR'
+                ) {
+                  configuration['propertyValidatorsMode'] = 'OR';
+                } else {
+                  configuration['propertyValidatorsMode'] = 'AND';
+                }
+                addValidatorIdentifiersToFormElementProperty(
+                  formElement,
+                  formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'],
+                  formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyPath'],
+                  formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'],
+                  collectionName,
+                  configuration
+                );
+              }
+            }
+          }
+        }
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        addValidatorIdentifiersToFormElementProperty: addValidatorIdentifiersToFormElementProperty,
+        removeValidatorIdentifiersFromFormElementProperty: removeValidatorIdentifiersFromFormElementProperty,
+        removeAllValidatorIdentifiersFromFormElement: removeAllValidatorIdentifiersFromFormElement,
+        validateFormElementProperty: validateFormElementProperty,
+        validateFormElement: validateFormElement,
+        validateFormElementRecursive: validateFormElementRecursive,
+        validationResultsHasErrors: validationResultsHasErrors,
+        addValidator: addValidator,
+        addValidatorIdentifiersFromFormElementPropertyCollections: addValidatorIdentifiersFromFormElementPropertyCollections
+      };
+    };
+
+    /**
+     * @public
+     *
+     * @param string ajaxRequestIdentifier
+     * @return object|null
+     * @throws 1475358064
+     */
+    function getRunningAjaxRequest(ajaxRequestIdentifier) {
+      utility().assert(utility().isNonEmptyString(ajaxRequestIdentifier), 'Invalid parameter "ajaxRequestIdentifier"', 1475358064);
+      return _runningAjaxRequests[ajaxRequestIdentifier] || null;
+    };
+
+    /**
+     * @public
+     *
+     * Implements the "Publish/Subscribe Pattern"
+     *
+     * @return object
+     * @credits Addy Osmani https://addyosmani.com/resources/essentialjsdesignpatterns/book/#highlighter_634280
+     */
+    function publisherSubscriber() {
+
+      /**
+       * @public
+       *
+       * @param string topic
+       * @param mixed args
+       * @return void
+       * @throws 1475358066
+       */
+      function publish(topic, args) {
+        utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358066);
+        if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) {
+          return;
+        }
+
+        for (var i = 0, len = _publisherSubscriberTopics[topic].length; i < len; ++i) {
+          _publisherSubscriberTopics[topic][i].func(topic, args);
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param string topic
+       * @param function func
+       * @return string
+       * @throws 1475358067
+       */
+      function subscribe(topic, func) {
+        utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358067);
+        utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475411986);
+
+        if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) {
+          _publisherSubscriberTopics[topic] = [];
+        }
+
+        var token = (++_publisherSubscriberUid).toString();
+        _publisherSubscriberTopics[topic].push({
+          token: token,
+          func: func
+        });
+        return token;
+      };
+
+      /**
+       * @public
+       *
+       * @param string token
+       * @return null|string
+       * @throws 1475358068
+       */
+      function unsubscribe(token) {
+        utility().assert(utility().isNonEmptyString(token), 'Invalid parameter "token"', 1475358068);
+
+        for (var key in _publisherSubscriberTopics) {
+          if (!_publisherSubscriberTopics.hasOwnProperty(key)) {
+            continue;
+          }
+          for (var i = 0, len = _publisherSubscriberTopics[key].length; i < len; ++i) {
+            if (_publisherSubscriberTopics[key][i].token === token) {
+              _publisherSubscriberTopics[key].splice(i, 1);
+              return token;
+            }
+          }
+        }
+        return null;
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        publish: publish,
+        subscribe: subscribe,
+        unsubscribe: unsubscribe
+      };
+    };
+
+    /**
+     * @private
+     *
+     * @param object modelToExtend
+     * @param object modelExtension
+     * @param string pathPrefix
+     * @return void
+     * @throws 1474640022
+     * @throws 1475358069
+     * @throws 1475358070
+     * @publish core/formElement/somePropertyChanged
+     */
+    function extendModel(modelToExtend, modelExtension, pathPrefix, disablePublishersOnSet) {
+      utility().assert('object' === $.type(modelToExtend), 'Invalid parameter "modelToExtend"', 1475358069);
+      utility().assert('object' === $.type(modelExtension) || 'array' === $.type(modelExtension), 'Invalid parameter "modelExtension"', 1475358070);
+
+      disablePublishersOnSet = !!disablePublishersOnSet;
+      pathPrefix = pathPrefix || '';
+
+      if ($.isEmptyObject(modelExtension)) {
+        utility().assert('' !== pathPrefix, 'Empty path is not allowed', 1474640022);
+        modelToExtend.on(pathPrefix, 'core/formElement/somePropertyChanged');
+        modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet);
+      } else {
+        for (var key in modelExtension) {
+          if (!modelExtension.hasOwnProperty(key)) {
+            continue;
+          }
+          var path = (pathPrefix === '') ? key : pathPrefix + '.' + key;
+
+          modelToExtend.on(path, 'core/formElement/somePropertyChanged');
+
+          if ('object' === $.type(modelExtension[key]) || 'array' === $.type(modelExtension[key])) {
+            extendModel(modelToExtend, modelExtension[key], path, disablePublishersOnSet);
+          } else if (pathPrefix === 'properties.options') {
+            modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet);
+          } else {
+            modelToExtend.set(path, modelExtension[key], disablePublishersOnSet);
+          }
+        }
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @param object modelExtension
+     * @return object
+     */
+    function createModel(modelExtension) {
+      var newModel;
+
+      modelExtension = modelExtension || {};
+
+      function M() {
 
         /**
          * @private
-         *
-         * @var int
          */
-        var _applicationStateStackPointer = 0;
+        var _objectData = {};
 
         /**
          * @private
-         *
-         * @var object
          */
-        var _applicationStateStack = [];
+        var _publisherTopics = {};
 
         /**
          * @public
          *
-         * @return object
+         * @param string key
+         * @return mixed|undefined
+         * @throws 1475361755
          */
-        function utility() {
-
-            /**
-             * @public
-             *
-             * @param mixed test
-             * @param string message
-             * @param int messageCode
-             * @return void
-             */
-            function assert(test, message, messageCode) {
-                if ('function' === $.type(test)) {
-                    test = (test() !== false);
-                }
-                if (!test) {
-                    message = message || "Assertion failed";
-                    if (messageCode) {
-                        message = message + ' (' + messageCode + ')';
-                    }
-                    if ('undefined' !== typeof Error) {
-                        throw new Error(message);
-                    }
-                    throw message;
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param mixed value
-             * @return bool
-             */
-            function isUndefinedOrNull(value) {
-                return ('undefined' === $.type(value) || 'null' === $.type(value));
-            };
-
-            /**
-             * @public
-             *
-             * @param mixed value
-             * @return bool
-             */
-            function isNonEmptyString(value) {
-                return ('string' === $.type(value) && value.length > 0);
-            };
-
-            /**
-             * @public
-             *
-             * @param string propertyPath
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object formElement
-             * @param boolean allowEmptyReturnValue
-             * @return string
-             * @throws 1475412569
-             * @throws 1475412570
-             * @throws 1475415988
-             * @throws 1475663210
-             */
-            function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) {
-                var newPropertyPath = '';
-
-                allowEmptyReturnValue = !!allowEmptyReturnValue;
-                if (isNonEmptyString(collectionElementIdentifier) || isNonEmptyString(collectionName)) {
-                    assert(isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475412569);
-                    assert(isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475412570);
-                    newPropertyPath = collectionName + '.' + repository().getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement);
-                } else {
-                    newPropertyPath = '';
-                }
-
-                if (!isUndefinedOrNull(propertyPath)) {
-                    assert(isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475415988);
-                    if (isNonEmptyString(newPropertyPath)) {
-                        newPropertyPath = newPropertyPath + '.' + propertyPath;
-                    } else {
-                        newPropertyPath = propertyPath;
-                    }
-                }
-
-                if (!allowEmptyReturnValue) {
-                    assert(isNonEmptyString(newPropertyPath), 'The property path could not be resolved', 1475663210);
-                }
-                return newPropertyPath;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object
-             * @throws 1475377782
-             */
-            function convertToSimpleObject(formElement) {
-                var childFormElements, simpleObject, objectData;
-                assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475377782);
-
-                simpleObject = {};
-                objectData = ('function' === $.type(formElement.getObjectData)) ? formElement.getObjectData() : formElement;
-                childFormElements = objectData['renderables'];
-                delete objectData['renderables'];
-
-                for (var key in objectData) {
-                    if (!objectData.hasOwnProperty(key)) {
-                        continue;
-                    }
-                    var value = objectData[key];
-                    if (key.match(/^__/)) {
-                        continue;
-                    }
-
-                    if ('object' === $.type(value)) {
-                        simpleObject[key] = convertToSimpleObject(value);
-                    } else if ('function' !== $.type(value) && 'undefined' !== $.type(value)) {
-                        simpleObject[key] = value;
-                    }
-                }
-
-                if ('array' === $.type(childFormElements)) {
-                    simpleObject['renderables'] = [];
-                    for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                        simpleObject['renderables'].push(convertToSimpleObject(childFormElements[i]));
-                    }
-                }
-
-                return simpleObject;
-            };
+        function get(key) {
+          var firstPartOfPath, obj;
+          utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361755);
+
+          obj = _objectData;
+          while (key.indexOf('.') > 0) {
+            firstPartOfPath = key.slice(0, key.indexOf('.'));
+            key = key.slice(firstPartOfPath.length + 1);
+            if (!obj.hasOwnProperty(firstPartOfPath)) {
+              return undefined;
+            }
+            obj = obj[firstPartOfPath];
+          }
 
-            /**
-             * Publish the public methods.
-             */
-            return {
-                assert: assert,
-                convertToSimpleObject: convertToSimpleObject,
-                isNonEmptyString: isNonEmptyString,
-                isUndefinedOrNull: isUndefinedOrNull,
-                buildPropertyPath: buildPropertyPath
-            };
+          return obj[key];
         };
 
         /**
          * @public
          *
-         * @return object
+         * @param string key
+         * @param mixed value
+         * @param bool disablePublishersOnSet
+         * @return void
+         * @throws 1475361756
+         * @publish mixed
          */
-        function propertyValidationService() {
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param object validators
-             * @param string propertyPath
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object configuration
-             * @return void
-             * @throws 1475661025
-             * @throws 1475661026
-             * @throws 1479238074
-             */
-            function addValidatorIdentifiersToFormElementProperty(formElement, validators, propertyPath, collectionElementIdentifier, collectionName, configuration) {
-                var formElementIdentifierPath, propertyPath, propertyValidationServiceRegisteredValidators;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475661025);
-                utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1475661026);
-                utility().assert('array' === $.type(validators), 'Invalid parameter "validators"', 1479238074);
-
-                formElementIdentifierPath = formElement.get('__identifierPath');
-                propertyPath = utility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement);
-
-                propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) {
-                    propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = {};
-                }
-                if (utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])) {
-                    propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath] = {
-                        validators: [],
-                        configuration: configuration
-                    };
-                }
-                for (var i = 0, len = validators.length; i < len; ++i) {
-                    if (propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].indexOf(validators[i]) === -1) {
-                        propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].push(validators[i]);
-                    }
-                }
-                getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string propertyPath
-             * @return void
-             * @throws 1475700618
-             * @throws 1475706896
-             */
-            function removeValidatorIdentifiersFromFormElementProperty(formElement, propertyPath) {
-                var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, registeredValidators;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475700618);
-                utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475706896);
-
-                formElementIdentifierPath = formElement.get('__identifierPath');
-
-                registeredValidators = {};
-                propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) {
-                    if (
-                        !propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)
-                        || registeredPropertyPath.indexOf(propertyPath) > -1
-                    ) {
-                        continue;
-                    }
-                    registeredValidators[registeredPropertyPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][registeredPropertyPath];
-                }
-                propertyValidationServiceRegisteredValidators[formElementIdentifierPath] = registeredValidators;
-                getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
-            };
-
-            /**
-             * @public
-             *
-             * @param string|object formElement
-             * @return void
-             * @throws 1475668189
-             */
-            function removeAllValidatorIdentifiersFromFormElement(formElement) {
-                var propertyValidationServiceRegisteredValidators, registeredValidators;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475668189);
-
-                registeredValidators = {};
-                propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                for (var formElementIdentifierPath in propertyValidationServiceRegisteredValidators) {
-                    if (
-                        !propertyValidationServiceRegisteredValidators.hasOwnProperty(formElementIdentifierPath)
-                        || formElementIdentifierPath === formElement.get('__identifierPath')
-                        || formElementIdentifierPath.indexOf(formElement.get('__identifierPath') + '/') > -1
-                    ) {
-                        continue;
-                    }
-                    registeredValidators[formElementIdentifierPath] = propertyValidationServiceRegisteredValidators[formElementIdentifierPath];
-                }
-                getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', registeredValidators);
-            };
-
-            /**
-             * @public
-             *
-             * @param string validatorIdentifier
-             * @param function func
-             * @return void
-             * @throws 1475669143
-             * @throws 1475669144
-             * @throws 1475669145
-             */
-            function addValidator(validatorIdentifier, func) {
-                utility().assert(utility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475669143);
-                utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475669144);
-                utility().assert('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier]), 'The validator "' + validatorIdentifier + '" is already registered', 1475669145);
-
-                _propertyValidationServiceValidators[validatorIdentifier] = func;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string propertyPath
-             * @param string errorMessage
-             * @return object
-             * @throws 1475676517
-             * @throws 1475676518
-             */
-            function validateFormElementProperty(formElement, propertyPath) {
-                var configuration, formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475676517);
-                utility().assert(utility().isNonEmptyString(propertyPath), 'Invalid parameter "propertyPath"', 1475676518);
-
-                formElementIdentifierPath = formElement.get('__identifierPath');
-
-                validationResults = [];
-                propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                configuration = {
-                    propertyValidatorsMode: 'AND'
-                };
-
-                if (
-                    !utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])
-                    && 'object' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath])
-                    && 'array' === $.type(propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'])
-                ) {
-                    configuration = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['configuration'];
-                    for (var i = 0, len = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length; i < len; ++i) {
-                        var validatorIdentifier, validationResult;
-
-                        validatorIdentifier = propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'][i];
-                        if ('function' !== $.type(_propertyValidationServiceValidators[validatorIdentifier])) {
-                            continue;
-                        }
-                        validationResult = _propertyValidationServiceValidators[validatorIdentifier](formElement, propertyPath);
-
-                        if (utility().isNonEmptyString(validationResult)) {
-                            validationResults.push(validationResult);
-                        }
-                    }
-                }
-
-                if (
-                    validationResults.length > 0
-                    && configuration['propertyValidatorsMode'] === 'OR'
-                    && validationResults.length !== propertyValidationServiceRegisteredValidators[formElementIdentifierPath][propertyPath]['validators'].length
-                ) {
-                    return [];
-                }
-
-                return validationResults;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return object
-             * @throws 1475749668
-             */
-            function validateFormElement(formElement) {
-                var formElementIdentifierPath, propertyValidationServiceRegisteredValidators, validationResults;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475749668);
-
-                formElementIdentifierPath = formElement.get('__identifierPath');
-
-                validationResults = [];
-                propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[formElementIdentifierPath])) {
-                    for (var registeredPropertyPath in propertyValidationServiceRegisteredValidators[formElementIdentifierPath]) {
-                        var validationResult;
-                        if (!propertyValidationServiceRegisteredValidators[formElementIdentifierPath].hasOwnProperty(registeredPropertyPath)) {
-                            continue;
-                        }
-                        validationResult = {
-                            propertyPath: registeredPropertyPath,
-                            validationResults: validateFormElementProperty(formElement, registeredPropertyPath)
-                        };
-                        validationResults.push(validationResult);
-                    }
-                }
-                return validationResults;
-            };
-
-            /**
-             * @public
-             *
-             * @param array validationResults
-             * @return bool
-             * @throws 1478613477
-             */
-            function validationResultsHasErrors(validationResults) {
-                utility().assert('array' === $.type(validationResults), 'Invalid parameter "validationResults"', 1478613477);
-
-                for (var i = 0, len = validationResults.length; i < len; ++i) {
-                    for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
-                        if (
-                            validationResults[i]['validationResults'][j]['validationResults']
-                            && validationResults[i]['validationResults'][j]['validationResults'].length > 0
-                        ) {
-                            return true;
-                        }
-                    }
-                }
-                return false;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param boolean returnAfterFirstMatch
-             * @param object validationResults
-             * @return object
-             * @throws 1475749668
-             */
-            function validateFormElementRecursive(formElement, returnAfterFirstMatch, validationResults) {
-                var formElements, validationResult, validationResults;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475756764);
-                returnAfterFirstMatch = !!returnAfterFirstMatch;
-
-                validationResults = validationResults || [];
-                validationResult = {
-                    formElementIdentifierPath: formElement.get('__identifierPath'),
-                    validationResults: validateFormElement(formElement)
-                };
-                validationResults.push(validationResult);
-
-                if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) {
-                    return validationResults;
-                }
-
-                formElements = formElement.get('renderables');
-                if ('array' === $.type(formElements)) {
-                    for (var i = 0, len = formElements.length; i < len; ++i) {
-                        validateFormElementRecursive(formElements[i], returnAfterFirstMatch, validationResults);
-                        if (returnAfterFirstMatch && validationResultsHasErrors(validationResults)) {
-                            return validationResults;
-                        }
-                    }
-                }
-
-                return validationResults;
+        function set(key, value, disablePublishersOnSet) {
+          var obj, oldValue, path;
+          utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361756);
+          disablePublishersOnSet = !!disablePublishersOnSet;
+
+          oldValue = get(key);
+          obj = _objectData;
+          path = key;
+
+          while (path.indexOf('.') > 0) {
+            var firstPartOfPath, nextPartOfPath;
+
+            firstPartOfPath = path.slice(0, path.indexOf('.'));
+            path = path.slice(firstPartOfPath.length + 1);
+            if ($.isNumeric(firstPartOfPath)) {
+              firstPartOfPath = parseInt(firstPartOfPath);
             }
+            if ('undefined' === $.type(obj[firstPartOfPath])) {
+              nextPartOfPath = path.slice(0, path.indexOf('.'));
+              if ($.isNumeric(nextPartOfPath)) {
+                obj[firstPartOfPath] = [];
+              } else {
+                obj[firstPartOfPath] = {};
+              }
+            }
+            obj = obj[firstPartOfPath];
+          }
+          obj[path] = value;
 
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @return void
-             * @throws 1475707334
-             */
-            function addValidatorIdentifiersFromFormElementPropertyCollections(formElement) {
-                var formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475707334);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-
-                if (!utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'])) {
-                    for (var collectionName in formElementTypeDefinition['propertyCollections']) {
-                        if (
-                            !formElementTypeDefinition['propertyCollections'].hasOwnProperty(collectionName)
-                            || 'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName])
-                        ) {
-                            continue;
-                        }
-                        for (var i = 0, len1 = formElementTypeDefinition['propertyCollections'][collectionName].length; i < len1; ++i) {
-                            if (
-                                'array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'])
-                                || repository().getIndexFromPropertyCollectionElementByIdentifier(formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'], collectionName, formElement) === -1
-                            ) {
-                                continue;
-                            }
-                            for (var j = 0, len2 = formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'].length; j < len2; ++j) {
-                                var configuration = {};
-
-                                if ('array' !== $.type(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'])) {
-                                    continue;
-                                }
-
-                                if (
-                                    !utility().isUndefinedOrNull(formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'])
-                                    && formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidatorsMode'] === 'OR'
-                                ) {
-                                    configuration['propertyValidatorsMode'] = 'OR';
-                                } else {
-                                    configuration['propertyValidatorsMode'] = 'AND';
-                                }
-                                addValidatorIdentifiersToFormElementProperty(
-                                    formElement,
-                                    formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyValidators'],
-                                    formElementTypeDefinition['propertyCollections'][collectionName][i]['editors'][j]['propertyPath'],
-                                    formElementTypeDefinition['propertyCollections'][collectionName][i]['identifier'],
-                                    collectionName,
-                                    configuration
-                                );
-                            }
-                        }
-                    }
-                }
-            };
-
-            /**
-             * Publish the public methods.
-             */
-            return {
-                addValidatorIdentifiersToFormElementProperty: addValidatorIdentifiersToFormElementProperty,
-                removeValidatorIdentifiersFromFormElementProperty: removeValidatorIdentifiersFromFormElementProperty,
-                removeAllValidatorIdentifiersFromFormElement: removeAllValidatorIdentifiersFromFormElement,
-                validateFormElementProperty: validateFormElementProperty,
-                validateFormElement: validateFormElement,
-                validateFormElementRecursive: validateFormElementRecursive,
-                validationResultsHasErrors: validationResultsHasErrors,
-                addValidator: addValidator,
-                addValidatorIdentifiersFromFormElementPropertyCollections: addValidatorIdentifiersFromFormElementPropertyCollections
-            };
+          if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) {
+            for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) {
+              publisherSubscriber().publish(_publisherTopics[key][i], [key, value, oldValue, _objectData['__identifierPath']]);
+            }
+          }
         };
 
         /**
          * @public
          *
-         * @param string ajaxRequestIdentifier
-         * @return object|null
-         * @throws 1475358064
+         * @param string key
+         * @param bool disablePublishersOnSet
+         * @return void
+         * @throws 1489321637
+         * @throws 1489319753
+         * @publish mixed
          */
-        function getRunningAjaxRequest(ajaxRequestIdentifier) {
-            utility().assert(utility().isNonEmptyString(ajaxRequestIdentifier), 'Invalid parameter "ajaxRequestIdentifier"', 1475358064);
-            return _runningAjaxRequests[ajaxRequestIdentifier] || null;
+        function unset(key, disablePublishersOnSet) {
+          var obj, oldValue, parentPropertyData, parentPropertyPath, propertyToRemove;
+          utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1489321637);
+          disablePublishersOnSet = !!disablePublishersOnSet;
+
+          oldValue = get(key);
+
+          if (key.indexOf('.') > 0) {
+            parentPropertyPath = key.split('.');
+            propertyToRemove = parentPropertyPath.pop();
+            parentPropertyPath = parentPropertyPath.join('.');
+            parentPropertyData = get(parentPropertyPath);
+            delete parentPropertyData[propertyToRemove];
+          } else {
+            assert(false, 'remove toplevel properties is not supported', 1489319753);
+          }
+
+          if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) {
+            for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) {
+              publisherSubscriber().publish(_publisherTopics[key][i], [key, undefined, oldValue, _objectData['__identifierPath']]);
+            }
+          }
         };
 
         /**
          * @public
          *
-         * Implements the "Publish/Subscribe Pattern"
-         *
-         * @return object
-         * @credits Addy Osmani https://addyosmani.com/resources/essentialjsdesignpatterns/book/#highlighter_634280
+         * @param string key
+         * @param string topicName
+         * @return void
+         * @throws 1475361757
+         * @throws 1475361758
          */
-        function publisherSubscriber() {
-
-            /**
-             * @public
-             *
-             * @param string topic
-             * @param mixed args
-             * @return void
-             * @throws 1475358066
-             */
-            function publish(topic, args) {
-                utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358066);
-                if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) {
-                    return;
-                }
-
-                for (var i = 0, len = _publisherSubscriberTopics[topic].length; i < len; ++i) {
-                    _publisherSubscriberTopics[topic][i].func(topic, args);
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param string topic
-             * @param function func
-             * @return string
-             * @throws 1475358067
-             */
-            function subscribe(topic, func) {
-                utility().assert(utility().isNonEmptyString(topic), 'Invalid parameter "topic"', 1475358067);
-                utility().assert('function' === $.type(func), 'Invalid parameter "func"', 1475411986);
-
-                if (utility().isUndefinedOrNull(_publisherSubscriberTopics[topic])) {
-                    _publisherSubscriberTopics[topic] = [];
-                }
-
-                var token = (++_publisherSubscriberUid).toString();
-                _publisherSubscriberTopics[topic].push({
-                    token: token,
-                    func: func
-                });
-                return token;
-            };
-
-            /**
-             * @public
-             *
-             * @param string token
-             * @return null|string
-             * @throws 1475358068
-             */
-            function unsubscribe(token) {
-                utility().assert(utility().isNonEmptyString(token), 'Invalid parameter "token"', 1475358068);
-
-                for (var key in _publisherSubscriberTopics) {
-                    if (!_publisherSubscriberTopics.hasOwnProperty(key)) {
-                        continue;
-                    }
-                    for (var i = 0, len = _publisherSubscriberTopics[key].length; i < len; ++i) {
-                        if (_publisherSubscriberTopics[key][i].token === token) {
-                            _publisherSubscriberTopics[key].splice(i, 1);
-                            return token;
-                        }
-                    }
-                }
-                return null;
-            };
-
-            /**
-             * Publish the public methods.
-             */
-            return {
-                publish: publish,
-                subscribe: subscribe,
-                unsubscribe: unsubscribe
-            };
+        function on(key, topicName) {
+          utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361757);
+          utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361758);
+
+          if ('array' !== $.type(_publisherTopics[key])) {
+            _publisherTopics[key] = [];
+          }
+          if (_publisherTopics[key].indexOf(topicName) === -1) {
+            _publisherTopics[key].push(topicName);
+          }
         };
 
         /**
-         * @private
+         * @public
          *
-         * @param object modelToExtend
-         * @param object modelExtension
-         * @param string pathPrefix
+         * @param string key
+         * @param string topicName
          * @return void
-         * @throws 1474640022
-         * @throws 1475358069
-         * @throws 1475358070
-         * @publish core/formElement/somePropertyChanged
+         * @throws 1475361759
+         * @throws 1475361760
          */
-        function extendModel(modelToExtend, modelExtension, pathPrefix, disablePublishersOnSet) {
-            utility().assert('object' === $.type(modelToExtend), 'Invalid parameter "modelToExtend"', 1475358069);
-            utility().assert('object' === $.type(modelExtension) || 'array' === $.type(modelExtension), 'Invalid parameter "modelExtension"', 1475358070);
-
-            disablePublishersOnSet = !!disablePublishersOnSet;
-            pathPrefix = pathPrefix || '';
-
-            if ($.isEmptyObject(modelExtension)) {
-                utility().assert('' !== pathPrefix, 'Empty path is not allowed', 1474640022);
-                modelToExtend.on(pathPrefix, 'core/formElement/somePropertyChanged');
-                modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet);
-            } else {
-                for (var key in modelExtension) {
-                    if (!modelExtension.hasOwnProperty(key)) {
-                        continue;
-                    }
-                    var path = (pathPrefix === '') ? key : pathPrefix + '.' + key;
-
-                    modelToExtend.on(path, 'core/formElement/somePropertyChanged');
-
-                    if ('object' === $.type(modelExtension[key]) || 'array' === $.type(modelExtension[key])) {
-                        extendModel(modelToExtend, modelExtension[key], path, disablePublishersOnSet);
-                    } else if (pathPrefix === 'properties.options') {
-                        modelToExtend.set(pathPrefix, modelExtension, disablePublishersOnSet);
-                    } else {
-                        modelToExtend.set(path, modelExtension[key], disablePublishersOnSet);
-                    }
-                }
-            }
+        function off(key, topicName) {
+          utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361759);
+          utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361760);
+
+          if ('array' === $.type(_publisherTopics[key])) {
+            _publisherTopics[key] = _publisherTopics[key].filter(function(topicName) {
+              return topicName !== topicName;
+            });
+          }
         };
 
         /**
-         * @private
+         * @public
          *
-         * @param object modelExtension
-         * @return object
+         * @return object (dereferenced)
          */
-        function createModel(modelExtension) {
-            var newModel;
-
-            modelExtension = modelExtension || {};
-
-            function M() {
-
-                /**
-                 * @private
-                 */
-                var _objectData = {};
-
-                /**
-                 * @private
-                 */
-                var _publisherTopics = {};
-
-                /**
-                 * @public
-                 *
-                 * @param string key
-                 * @return mixed|undefined
-                 * @throws 1475361755
-                 */
-                function get(key) {
-                    var firstPartOfPath, obj;
-                    utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361755);
-
-                    obj = _objectData;
-                    while (key.indexOf('.') > 0) {
-                        firstPartOfPath = key.slice(0, key.indexOf('.'));
-                        key = key.slice(firstPartOfPath.length + 1);
-                        if (!obj.hasOwnProperty(firstPartOfPath)) {
-                            return undefined;
-                        }
-                        obj = obj[firstPartOfPath];
-                    }
-
-                    return obj[key];
-                };
-
-                /**
-                 * @public
-                 *
-                 * @param string key
-                 * @param mixed value
-                 * @param bool disablePublishersOnSet
-                 * @return void
-                 * @throws 1475361756
-                 * @publish mixed
-                 */
-                function set(key, value, disablePublishersOnSet) {
-                    var obj, oldValue, path;
-                    utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361756);
-                    disablePublishersOnSet = !!disablePublishersOnSet;
-
-                    oldValue = get(key);
-                    obj = _objectData;
-                    path = key;
-
-                    while (path.indexOf('.') > 0) {
-                        var firstPartOfPath, nextPartOfPath;
-
-                        firstPartOfPath = path.slice(0, path.indexOf('.'));
-                        path = path.slice(firstPartOfPath.length + 1);
-                        if ($.isNumeric(firstPartOfPath)) {
-                            firstPartOfPath = parseInt(firstPartOfPath);
-                        }
-                        if ('undefined' === $.type(obj[firstPartOfPath])) {
-                            nextPartOfPath = path.slice(0, path.indexOf('.'));
-                            if ($.isNumeric(nextPartOfPath)) {
-                                obj[firstPartOfPath] = [];
-                            } else {
-                                obj[firstPartOfPath] = {};
-                            }
-                        }
-                        obj = obj[firstPartOfPath];
-                    }
-                    obj[path] = value;
-
-                    if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) {
-                        for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) {
-                            publisherSubscriber().publish(_publisherTopics[key][i], [key, value, oldValue, _objectData['__identifierPath']]);
-                        }
-                    }
-                };
-
-                /**
-                 * @public
-                 *
-                 * @param string key
-                 * @param bool disablePublishersOnSet
-                 * @return void
-                 * @throws 1489321637
-                 * @throws 1489319753
-                 * @publish mixed
-                 */
-                function unset(key, disablePublishersOnSet) {
-                    var obj, oldValue, parentPropertyData, parentPropertyPath, propertyToRemove;
-                    utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1489321637);
-                    disablePublishersOnSet = !!disablePublishersOnSet;
-
-                    oldValue = get(key);
-
-                    if (key.indexOf('.') > 0) {
-                        parentPropertyPath = key.split('.');
-                        propertyToRemove = parentPropertyPath.pop();
-                        parentPropertyPath = parentPropertyPath.join('.');
-                        parentPropertyData = get(parentPropertyPath);
-                        delete parentPropertyData[propertyToRemove];
-                    } else {
-                        assert(false, 'remove toplevel properties is not supported', 1489319753);
-                    }
-
-                    if (!utility().isUndefinedOrNull(_publisherTopics[key]) && !disablePublishersOnSet) {
-                        for (var i = 0, len = _publisherTopics[key].length; i < len; ++i) {
-                            publisherSubscriber().publish(_publisherTopics[key][i], [key, undefined, oldValue, _objectData['__identifierPath']]);
-                        }
-                    }
-                };
-
-                /**
-                 * @public
-                 *
-                 * @param string key
-                 * @param string topicName
-                 * @return void
-                 * @throws 1475361757
-                 * @throws 1475361758
-                 */
-                function on(key, topicName) {
-                    utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361757);
-                    utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361758);
-
-                    if ('array' !== $.type(_publisherTopics[key])) {
-                        _publisherTopics[key] = [];
-                    }
-                    if (_publisherTopics[key].indexOf(topicName) === -1) {
-                        _publisherTopics[key].push(topicName);
-                    }
-                };
-
-                /**
-                 * @public
-                 *
-                 * @param string key
-                 * @param string topicName
-                 * @return void
-                 * @throws 1475361759
-                 * @throws 1475361760
-                 */
-                function off(key, topicName) {
-                    utility().assert(utility().isNonEmptyString(key), 'Invalid parameter "key"', 1475361759);
-                    utility().assert(utility().isNonEmptyString(topicName), 'Invalid parameter "topicName"', 1475361760);
-
-                    if ('array' === $.type(_publisherTopics[key])) {
-                        _publisherTopics[key] = _publisherTopics[key].filter(function (topicName) {
-                            return topicName !== topicName;
-                        });
-                    }
-                };
-
-                /**
-                 * @public
-                 *
-                 * @return object (dereferenced)
-                 */
-                function getObjectData() {
-                    return $.extend(true, {}, _objectData);
-                };
-
-                /**
-                 * @public
-                 *
-                 * @return string
-                 */
-                function toString() {
-                    var childFormElements, objectData;
-
-                    objectData = getObjectData();
-                    childFormElements = objectData['renderables'] || null;
-                    delete objectData['renderables'];
-
-                    if (!utility().isUndefinedOrNull(objectData['__parentRenderable'])) {
-                        objectData['__parentRenderable'] = objectData['__parentRenderable'].getObjectData()['__identifierPath'] + ' (filtered)';
-                    }
-
-                    if (null !== childFormElements) {
-                        objectData['renderables'] = [];
-                        for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                            var childFormElement = childFormElements[i];
-                            objectData['renderables'].push(JSON.parse(childFormElement.toString()));
-                        }
-                    }
-
-                    return JSON.stringify(objectData, null, 2);
-                };
-
-                /**
-                 * @public
-                 *
-                 * @return object
-                 */
-                function clone() {
-                    var childFormElements, newModel, newRenderables, objectData;
-
-                    objectData = getObjectData();
-                    childFormElements = objectData['renderables'] || null;
-                    delete objectData['renderables'];
-                    delete objectData['__parentRenderable'];
-                    objectData['renderables'] = (childFormElements) ? true : null,
-
-                    newModel = new M();
-                    extendModel(newModel, objectData, '', true);
-
-                    if (null !== childFormElements) {
-                        newRenderables = [];
-                        for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                            var childFormElement = childFormElements[i];
-
-                            childFormElement = childFormElement.clone();
-                            childFormElement.set('__parentRenderable', newModel, true);
-                            newRenderables.push(childFormElement);
-                        }
-                        newModel.set('renderables', newRenderables, true);
-                    }
-
-                    return newModel;
-                };
-
-                /**
-                 * Publish the public methods.
-                 */
-                return {
-                    get: get,
-                    set: set,
-                    unset: unset,
-
-                    on: on,
-                    off: off,
-
-                    getObjectData: getObjectData,
-                    toString: toString,
-                    clone: clone
-                };
-            };
-
-            newModel = new M();
-            extendModel(newModel, modelExtension, '', true);
-
-            return newModel;
+        function getObjectData() {
+          return $.extend(true, {}, _objectData);
         };
 
         /**
          * @public
          *
-         * @return object
+         * @return string
          */
-        function repository() {
-
-            /**
-             * @public
-             *
-             * @param object typeDefinitions
-             * @return void
-             * @throws 1475364394
-             */
-            function setFormEditorDefinitions(formEditorDefinitions) {
-                utility().assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475364394);
-
-                for (var key1 in formEditorDefinitions) {
-                    if (!formEditorDefinitions.hasOwnProperty(key1) || 'object' !== $.type(formEditorDefinitions[key1])) {
-                        continue;
-                    }
-                    for (var key2 in formEditorDefinitions[key1]) {
-                        if (!formEditorDefinitions[key1].hasOwnProperty(key2)) {
-                            continue;
-                        }
-                        if ('object' !== $.type(formEditorDefinitions[key1][key2])) {
-                            formEditorDefinitions[key1][key2] = {};
-                        }
-                    }
-                }
-                _repositoryFormEditorDefinitions = formEditorDefinitions;
-            };
-
-            /**
-             * @public
-             *
-             * @param string typeName
-             * @param string subject
-             * @return object (dereferenced)
-             * @throws 1475364952
-             * @throws 1475364953
-             */
-            function getFormEditorDefinition(definitionName, subject) {
-                utility().assert(utility().isNonEmptyString(definitionName), 'Invalid parameter "definitionName"', 1475364952);
-                utility().assert(utility().isNonEmptyString(subject), 'Invalid parameter "subject"', 1475364953);
-                return $.extend(true, {}, _repositoryFormEditorDefinitions[definitionName][subject]);
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getRootFormElement() {
-                return getApplicationStateStack().getCurrentState('formDefinition');
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param object referenceFormElement
-             * @param boolean registerPropertyValidators
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475436224
-             * @throws 1475364956
-             */
-            function addFormElement(formElement, referenceFormElement, registerPropertyValidators, disablePublishersOnSet) {
-                var enclosingCompositeFormElement, identifier, formElementTypeDefinition, parentFormElementsArray, parentFormElementTypeDefinition, referenceFormElementElements, referenceFormElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475436224);
-                utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364956);
-
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                registerPropertyValidators = !!registerPropertyValidators;
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type'));
-
-                // formElement != Page / SummaryPage && referenceFormElement == Page / Fieldset / GridContainer / GridRow
-                if (!formElementTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isCompositeFormElement']) {
-                    if ('array' !== $.type(referenceFormElement.get('renderables'))) {
-                        referenceFormElement.set('renderables', [], disablePublishersOnSet);
-                    }
-
-                    formElement.set('__parentRenderable', referenceFormElement, disablePublishersOnSet);
-                    formElement.set('__identifierPath', referenceFormElement.get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet);
-                    referenceFormElement.get('renderables').push(formElement);
-                } else {
-                    // referenceFormElement == root form element
-                    if (referenceFormElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) {
-                        referenceFormElementElements = referenceFormElement.get('renderables');
-                        // referenceFormElement = last page
-                        referenceFormElement = referenceFormElementElements[referenceFormElementElements.length - 1];
-                    // if formElement == Page / SummaryPage && referenceFormElement != Page / SummaryPage
-                    } else if (formElementTypeDefinition['_isTopLevelFormElement'] && !referenceFormElementTypeDefinition['_isTopLevelFormElement']) {
-                        // referenceFormElement = parent Page
-                        referenceFormElement = findEnclosingCompositeFormElementWhichIsOnTopLevel(referenceFormElement);
-                    // formElement == Page / SummaryPage / Fieldset / GridContainer / GridRow
-                    } else if (formElementTypeDefinition['_isCompositeFormElement']) {
-                        enclosingCompositeFormElement = findEnclosingCompositeFormElementWhichIsNotOnTopLevel(referenceFormElement);
-                        if (enclosingCompositeFormElement) {
-                            // referenceFormElement = parent Fieldset / GridContainer / GridRow
-                            referenceFormElement = enclosingCompositeFormElement;
-                        }
-                    }
-
-                    formElement.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet);
-                    formElement.set('__identifierPath', referenceFormElement.get('__parentRenderable').get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet);
-                    parentFormElementsArray = referenceFormElement.get('__parentRenderable').get('renderables');
-                    parentFormElementsArray.splice(parentFormElementsArray.indexOf(referenceFormElement) + 1, 0, formElement);
-                }
-
-                if (registerPropertyValidators) {
-                    if ('array' === $.type(formElementTypeDefinition['editors'])) {
-                        for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) {
-                            var configuration = {};
-
-                            if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) {
-                                continue;
-                            }
-
-                            if (
-                                !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode'])
-                                && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR'
-                            ) {
-                                configuration['propertyValidatorsMode'] = 'OR';
-                            } else {
-                                configuration['propertyValidatorsMode'] = 'AND';
-                            }
-
-                            propertyValidationService().addValidatorIdentifiersToFormElementProperty(
-                                formElement,
-                                formElementTypeDefinition['editors'][i]['propertyValidators'],
-                                formElementTypeDefinition['editors'][i]['propertyPath'],
-                                undefined,
-                                undefined,
-                                configuration
-                            );
-                        }
-                    }
-                }
-
-                return formElement;
-            };
-
-            /**
-             * @param object formElement
-             * @param boolean removeRegisteredPropertyValidators
-             * @param boolean disablePublishersOnSet
-             * @return void
-             * @throws 1472553024
-             * @throws 1475364957
-             */
-            function removeFormElement(formElement, removeRegisteredPropertyValidators, disablePublishersOnSet) {
-                var parentFormElementElements;
-
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-                removeRegisteredPropertyValidators = !!removeRegisteredPropertyValidators;
-
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364957);
-                utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'Removing the root element is not allowed', 1472553024);
-
-                parentFormElementElements = formElement.get('__parentRenderable').get('renderables');
-                parentFormElementElements.splice(parentFormElementElements.indexOf(formElement), 1);
-                formElement.get('__parentRenderable').set('renderables', parentFormElementElements, disablePublishersOnSet);
-
-                if (removeRegisteredPropertyValidators) {
-                    propertyValidationService().removeAllValidatorIdentifiersFromFormElement(formElement);
-                }
-            };
-
-            /**
-             * @param object formElementToMove
-             * @param string position
-             * @param object referenceFormElement
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475364958
-             * @throws 1475364959
-             * @throws 1475364960
-             * @throws 1475364961
-             * @throws 1475364962
-             * @throws 1476993731
-             * @throws 1476993732
-             */
-            function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
-                var formElementToMoveTypeDefinition, referenceFormElementParentElements, referenceFormElementElements, referenceFormElementIndex, referenceFormElementTypeDefinition, reSetIdentifierPath;
-                utility().assert('object' === $.type(formElementToMove), 'Invalid parameter "formElementToMove"', 1475364958);
-                utility().assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475364959);
-                utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364960);
-
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                formElementToMoveTypeDefinition = repository().getFormEditorDefinition('formElements', formElementToMove.get('type'));
-                referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type'));
-
-                removeFormElement(formElementToMove, false);
-                reSetIdentifierPath = function(formElement, pathPrefix) {
-                    var formElements, newIdentifierPath, oldIdentifierPath, propertyValidationServiceRegisteredValidators;
-                    utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961);
-                    utility().assert(utility().isNonEmptyString(pathPrefix), 'Invalid parameter "pathPrefix"', 1475364962);
-
-                    oldIdentifierPath = formElement.get('__identifierPath');
-                    newIdentifierPath = pathPrefix + '/' + formElement.get('identifier');
-
-                    propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
-                    if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[oldIdentifierPath])) {
-                        propertyValidationServiceRegisteredValidators[newIdentifierPath] = propertyValidationServiceRegisteredValidators[oldIdentifierPath];
-                        delete propertyValidationServiceRegisteredValidators[oldIdentifierPath];
-                    }
-                    getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
-
-                    formElement.set('__identifierPath', newIdentifierPath, disablePublishersOnSet);
-                    formElements = formElement.get('renderables');
-                    if ('array' === $.type(formElements)) {
-                        for (var i = 0, len = formElements.length; i < len; ++i) {
-                            reSetIdentifierPath(formElements[i], formElement.get('__identifierPath'));
-                        }
-                    }
-                };
-
-                /**
-                 * This is true on:
-                 * * Drag a Element on a Page Element (tree)
-                 * * Drag a Element on a Section Element (tree)
-                 */
-                if (position === 'inside') {
-                    // formElementToMove == Page / SummaryPage
-                    utility().assert(!formElementToMoveTypeDefinition['_isTopLevelFormElement'], 'This move is not allowed', 1476993731);
-                    // referenceFormElement != Page / Fieldset / GridContainer / GridRow
-                    utility().assert(referenceFormElementTypeDefinition['_isCompositeFormElement'], 'This move is not allowed', 1476993732);
-
-                    formElementToMove.set('__parentRenderable', referenceFormElement, disablePublishersOnSet);
-                    reSetIdentifierPath(formElementToMove, referenceFormElement.get('__identifierPath'));
-
-                    referenceFormElementElements = referenceFormElement.get('renderables');
-                    if (utility().isUndefinedOrNull(referenceFormElementElements)) {
-                        referenceFormElementElements = [];
-                    }
-                    referenceFormElementElements.splice(0, 0, formElementToMove);
-                    referenceFormElement.set('renderables', referenceFormElementElements, disablePublishersOnSet);
-                } else {
-                    /**
-                     * This is true on:
-                     * * Drag a Page before another Page (tree)
-                     * * Drag a Page after another Page (tree)
-                     */
-                    if (formElementToMoveTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isTopLevelFormElement']) {
-                        referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
-                        referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
-
-                        if (position === 'after') {
-                            referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove);
-                        } else {
-                            referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove);
-                        }
-
-                        referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet);
-                    } else {
-                        /**
-                         * This is true on:
-                         * * Drag a Element before another Element within the same level (tree)
-                         * * Drag a Element after another Element within the same level (tree)
-                         * * Drag a Element before another Element (stage)
-                         * * Drag a Element after another Element (stage)
-                         */
-                        if (formElementToMove.get('__parentRenderable').get('identifier') === referenceFormElement.get('__parentRenderable').get('identifier')) {
-                            referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
-                            referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
-                        } else {
-                            /**
-                             * This is true on:
-                             * * Drag a Element before an Element on another page (tree / stage)
-                             * * Drag a Element after an Element on another page (tree / stage)
-                             */
-                            formElementToMove.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet);
-                            reSetIdentifierPath(formElementToMove, referenceFormElement.get('__parentRenderable').get('__identifierPath'));
-
-                            referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
-                            referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
-                        }
-
-                        if (position === 'after') {
-                            referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove);
-                        } else {
-                            referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove);
-                        }
-
-                        referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet);
-                    }
-                }
-
-                return formElementToMove;
-            };
-
-            /**
-             * @param object formElement
-             * @return int
-             * @throws 1475364963
-             */
-            function getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(formElement) {
-                var enclosingCompositeFormElementWhichIsOnTopLevel, formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364963);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-
-                if (formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) {
-                    enclosingCompositeFormElementWhichIsOnTopLevel = formElement;
-                } else if (formElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) {
-                    enclosingCompositeFormElementWhichIsOnTopLevel = getApplicationStateStack().getCurrentState('formDefinition').get('renderables')[0];
-                } else {
-                    enclosingCompositeFormElementWhichIsOnTopLevel = findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement);
-                }
-                return enclosingCompositeFormElementWhichIsOnTopLevel.get('__parentRenderable').get('renderables').indexOf(enclosingCompositeFormElementWhichIsOnTopLevel);
-            };
-
-            /**
-             * @param object formElement
-             * @return object
-             * @throws 1472556223
-             * @throws 1475364964
-             */
-            function findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement) {
-                var formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364964);
-                utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'The root element is never encloused by anything', 1472556223);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                while (!formElementTypeDefinition['_isTopLevelFormElement']) {
-                    formElement = formElement.get('__parentRenderable');
-                    formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                }
-
-                return formElement;
-            };
-
-            /**
-             * @param object formElement
-             * @return object|null
-             * @throws 1489447996
-             */
-            function findEnclosingGridContainerFormElement(formElement) {
-                var formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1489447996);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                while (!formElementTypeDefinition['_isGridContainerFormElement']) {
-                    if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                        return null;
-                    }
-                    formElement = formElement.get('__parentRenderable');
-                    formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                }
-                if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                    return null;
-                }
-                return formElement;
-            };
-
-            /**
-             * @param object formElement
-             * @return object|null
-             * @throws 1490520271
-             */
-            function findEnclosingGridRowFormElement(formElement) {
-                var formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1490520271);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                while (!formElementTypeDefinition['_isGridRowFormElement']) {
-                    if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                        return null;
-                    }
-                    formElement = formElement.get('__parentRenderable');
-                    formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                }
-                if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                    return null;
-                }
-                return formElement;
-            };
-
-            /**
-             * @param object formElement
-             * @return object|null
-             * @throws 1475364965
-             */
-            function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) {
-                var formElementTypeDefinition;
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364965);
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                while (!formElementTypeDefinition['_isCompositeFormElement']) {
-                    if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                        return null;
-                    }
-                    formElement = formElement.get('__parentRenderable');
-                    formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-                }
-                if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                    return null;
-                }
-                return formElement;
-            };
-
-            /**
-             * @return object
-             */
-            function getNonCompositeNonToplevelFormElements() {
-                var collect, nonCompositeNonToplevelFormElements;
-
-                collect = function(formElement) {
-                    var formElements, formElementTypeDefinition;
-                    utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961);
-
-                    formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
-
-                    if (!formElementTypeDefinition['_isTopLevelFormElement'] && !formElementTypeDefinition['_isCompositeFormElement']) {
-                        nonCompositeNonToplevelFormElements.push(formElement);
-                    }
-
-                    formElements = formElement.get('renderables');
-                    if ('array' === $.type(formElements)) {
-                        for (var i = 0, len = formElements.length; i < len; ++i) {
-                            collect(formElements[i]);
-                        }
-                    }
-                };
-
-                nonCompositeNonToplevelFormElements = [];
-                collect(getRootFormElement());
-                return nonCompositeNonToplevelFormElements;
-            };
-
-            /**
-             * @param string identifier
-             * @returl bool
-             * @throws 1475364966
-             */
-            function isFormElementIdentifierUsed(identifier) {
-                var checkIdentifier, identifierFound;
-                utility().assert(utility().isNonEmptyString(identifier), 'Invalid parameter "identifier"', 1475364966);
-
-                checkIdentifier = function(formElement) {
-                    var formElements;
-
-                    if (formElement.get('identifier') === identifier) {
-                        identifierFound = true;
-                    }
-
-                    if (!identifierFound) {
-                        formElements = formElement.get('renderables');
-                        if ('array' === $.type(formElements)) {
-                            for (var i = 0, len = formElements.length; i < len; ++i) {
-                                checkIdentifier(formElements[i]);
-                                if (identifierFound) {
-                                    break;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                checkIdentifier(getApplicationStateStack().getCurrentState('formDefinition'));
-                return identifierFound;
-            };
-
-            /**
-             * @param string formElementType
-             * @return string
-             * @throws 1475373676
-             */
-            function getNextFreeFormElementIdentifier(formElementType) {
-                var i, prefix;
-                utility().assert(utility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475373676);
-
-                prefix = formElementType.toLowerCase().replace(/[^a-z0-9]/g, '-') + '-';
-                i = 1;
-                while (isFormElementIdentifierUsed(prefix + i)) {
-                    i++;
-                }
-                return prefix + i;
-            };
-
-            /**
-             * @param string identifierPath
-             * @return object
-             * @throws 1472424333
-             * @throws 1472424334
-             * @throws 1472424330
-             * @throws 1475373677
-             */
-            function findFormElementByIdentifierPath(identifierPath) {
-                var obj, pathParts, pathPartsLength, formElement, formElements;
-
-                utility().assert(utility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475373677);
-
-                formElement = getApplicationStateStack().getCurrentState('formDefinition');
-                pathParts = identifierPath.split('/');
-                pathPartsLength = pathParts.length;
-
-                for (var i = 0; i < pathPartsLength; ++i) {
-                    var key = pathParts[i];
-                    if (i === 0 || i === pathPartsLength) {
-                        utility().assert(key === formElement.get('identifier'), '"' + key + '" does not exist in path "' + identifierPath + '"', 1472424333);
-                        continue;
-                    }
-
-                    formElements = formElement.get('renderables');
-                    if ('array' === $.type(formElements)) {
-                        obj = null;
-                        for (var j = 0, len = formElements.length; j < len; ++j) {
-                            if (key === formElements[j].get('identifier')) {
-                                obj = formElements[j];
-                                break;
-                            }
-                        }
-
-                        utility().assert('null' !== $.type(obj), 'Could not find form element "' + key + '" in path "' + identifierPath + '"', 1472424334);
-                        formElement = obj;
-                    } else {
-                        utility().assert(false, 'No form elements found', 1472424330);
-                    }
-                }
-                return formElement;
-            };
-
-            /**
-             * @param string|object formElement
-             * @return object
-             */
-            function findFormElement(formElement) {
-                if ('object' === $.type(formElement)) {
-                    formElement = formElement.get('__identifierPath');
-                }
-                return findFormElementByIdentifierPath(formElement);
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param object collection
-             * @return undefined|object
-             * @throws 1475375281
-             * @throws 1475375282
-             */
-            function findCollectionElementByIdentifierPath(collectionElementIdentifier, collection) {
-                utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375281);
-                utility().assert('array' === $.type(collection), 'Invalid parameter "collection"', 1475375282);
-
-                for (var i = 0, len = collection.length; i < len; ++i) {
-                    if (collection[i]['identifier'] === collectionElementIdentifier) {
-                        return collection[i];
-                    }
-                }
-
-                return undefined;
-            };
-
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param object formElement
-             * @return int
-             * @throws 1475375283
-             * @throws 1475375284
-             * @throws 1475375285
-             */
-            function getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement) {
-                var collection;
-                utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375283);
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375284);
-                utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375285);
-
-                collection = formElement.get(collectionName);
-                if ('array' === $.type(collection)) {
-                    for (var i = 0, len = collection.length; i < len; ++i) {
-                        if (collection[i]['identifier'] === collectionElementIdentifier) {
-                            return i;
-                        }
-                    }
-                }
-                return -1;
-            };
-
-            /**
-             * @public
-             *
-             * @param object collectionElementToAdd
-             * @param string collectionName
-             * @param object formElement
-             * @param string referenceCollectionElementIdentifier
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475375686
-             * @throws 1475375687
-             * @throws 1475375688
-             * @throws 1477413154
-             */
-            function addPropertyCollectionElement(collectionElementToAdd, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) {
-                var collection, formElementTypeDefinition, newCollection, newCollectionElementIndex;
-                utility().assert('object' === $.type(collectionElementToAdd), 'Invalid parameter "collectionElementToAdd"', 1475375686);
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375687);
-                utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375688);
-
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                collection = formElement.get(collectionName);
-                if ('array' !== $.type(collection)) {
-                    extendModel(formElement, [], collectionName, true);
-                    collection = formElement.get(collectionName);
-                }
-
-                if (utility().isUndefinedOrNull(referenceCollectionElementIdentifier)) {
-                    newCollectionElementIndex = 0;
-                } else {
-                    newCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement) + 1;
-                    utility().assert(-1 < newCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477413154);
-                }
-
-                collection.splice(newCollectionElementIndex, 0, collectionElementToAdd);
-                formElement.set(collectionName, collection, true);
-
-                propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName);
-
-                for (var i = 0, len = collection.length; i < len; ++i) {
-                    extendModel(formElement, collection[i], collectionName + '.' + i, true);
-                }
-
-                formElement.set(collectionName, collection, true);
-                propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement);
-                formElement.set(collectionName, collection, disablePublishersOnSet);
-
-                return formElement;
-            };
-
-            /**
-             * @public
-             *
-             * @param object formElement
-             * @param string collectionElementIdentifier
-             * @param string collectionName
-             * @param boolean disablePublishersOnSet
-             * @return void
-             * @throws 1475375689
-             * @throws 1475375690
-             * @throws 1475375691
-             * @throws 1475375692
-             */
-            function removePropertyCollectionElementByIdentifier(formElement, collectionElementIdentifier, collectionName, disablePublishersOnSet) {
-                var collection, collectionElementIndex;
-                utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375689);
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375690);
-                utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375691);
-
-                collection = formElement.get(collectionName);
-                utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1475375692);
-
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName);
-                collectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement);
-                collection.splice(collectionElementIndex, 1);
-                formElement.set(collectionName, collection, disablePublishersOnSet);
-                propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement);
-            };
-
-            /**
-             * @param string collectionElementToMoveIdentifier
-             * @param string position
-             * @param string referenceCollectionElementIdentifier
-             * @param string position
-             * @param object formElement
-             * @param boolean disablePublishersOnSet
-             * @return void
-             * @throws 1477404484
-             * @throws 1477404485
-             * @throws 1477404486
-             * @throws 1477404488
-             * @throws 1477404489
-             * @throws 1477404490
-             */
-            function movePropertyCollectionElement(collectionElementToMoveIdentifier, position, referenceCollectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
-                var collection, collectionElementToMove, referenceCollectionElement, referenceCollectionElementIndex;
-
-                utility().assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404485);
-                utility().assert('string' === $.type(referenceCollectionElementIdentifier), 'Invalid parameter "referenceCollectionElementIdentifier"', 1477404486);
-                utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1477404488);
-
-                collection = formElement.get(collectionName);
-                utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1477404490);
-
-                collectionElementToMove = findCollectionElementByIdentifierPath(collectionElementToMoveIdentifier, collection);
-                utility().assert('object' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404484);
-
-                removePropertyCollectionElementByIdentifier(formElement, collectionElementToMoveIdentifier, collectionName);
-
-                referenceCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement);
-                utility().assert(-1 < referenceCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477404489);
-
-                if ('before' === position) {
-                    referenceCollectionElement = collection[referenceCollectionElementIndex - 1];
-                    if (utility().isUndefinedOrNull(referenceCollectionElement)) {
-                        referenceCollectionElementIdentifier = undefined;
-                    } else {
-                        referenceCollectionElementIdentifier = referenceCollectionElement['identifier'];
-                    }
-                }
-
-                addPropertyCollectionElement(collectionElementToMove, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet)
-            };
+        function toString() {
+          var childFormElements, objectData;
+
+          objectData = getObjectData();
+          childFormElements = objectData['renderables'] || null;
+          delete objectData['renderables'];
+
+          if (!utility().isUndefinedOrNull(objectData['__parentRenderable'])) {
+            objectData['__parentRenderable'] = objectData['__parentRenderable'].getObjectData()['__identifierPath'] + ' (filtered)';
+          }
+
+          if (null !== childFormElements) {
+            objectData['renderables'] = [];
+            for (var i = 0, len = childFormElements.length; i < len; ++i) {
+              var childFormElement = childFormElements[i];
+              objectData['renderables'].push(JSON.parse(childFormElement.toString()));
+            }
+          }
 
-            /**
-             * Publish the public methods.
-             */
-            return {
-                getRootFormElement: getRootFormElement,
-
-                getFormEditorDefinition: getFormEditorDefinition,
-                setFormEditorDefinitions: setFormEditorDefinitions,
-
-                findFormElement: findFormElement,
-                findFormElementByIdentifierPath: findFormElementByIdentifierPath,
-                findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel,
-                findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel,
-                findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement,
-                findEnclosingGridRowFormElement: findEnclosingGridRowFormElement,
-                getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement,
-                getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements,
-
-                getNextFreeFormElementIdentifier: getNextFreeFormElementIdentifier,
-                isFormElementIdentifierUsed: isFormElementIdentifierUsed,
-
-                addFormElement: addFormElement,
-                moveFormElement: moveFormElement,
-                removeFormElement: removeFormElement,
-
-                findCollectionElementByIdentifierPath: findCollectionElementByIdentifierPath,
-                getIndexFromPropertyCollectionElementByIdentifier: getIndexFromPropertyCollectionElementByIdentifier,
-                addPropertyCollectionElement: addPropertyCollectionElement,
-                removePropertyCollectionElementByIdentifier: removePropertyCollectionElementByIdentifier,
-                movePropertyCollectionElement: movePropertyCollectionElement
-            };
+          return JSON.stringify(objectData, null, 2);
         };
 
         /**
@@ -1755,509 +939,1335 @@ define(['jquery'], function($) {
          *
          * @return object
          */
-        function factory() {
+        function clone() {
+          var childFormElements, newModel, newRenderables, objectData;
 
-            /**
-             * @public
-             *
-             * @param object configuration
-             * @param string identifierPathPrefix
-             * @param object parentFormElement
-             * @param boolean registerPropertyValidators
-             * @param boolean disablePublishersOnSet
-             * @return object
-             * @throws 1475375693
-             * @throws 1475436040
-             * @throws 1475604050
-             */
-            function createFormElement(configuration, identifierPathPrefix, parentFormElement, registerPropertyValidators, disablePublishersOnSet) {
-                var currentChildFormElements, collections, formElementTypeDefinition, identifierPath, rawChildFormElements, formElement, predefinedDefaults;
-                utility().assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1475375693);
-                utility().assert(utility().isNonEmptyString(configuration['identifier']), '"identifier" must not be empty', 1475436040);
-                utility().assert(utility().isNonEmptyString(configuration['type']), '"type" must not be empty', 1475604050);
-
-                registerPropertyValidators = !!registerPropertyValidators;
-                if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
-                    disablePublishersOnSet = true;
-                }
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                formElementTypeDefinition = repository().getFormEditorDefinition('formElements', configuration['type']);
-                rawChildFormElements = configuration['renderables'];
-                delete configuration['renderables'];
-
-                collections = {};
-                predefinedDefaults = formElementTypeDefinition['predefinedDefaults'] || {};
-                for (var collectionName in configuration) {
-                    if (!configuration.hasOwnProperty(collectionName)) {
-                        continue;
-                    }
-                    if (utility().isUndefinedOrNull(_repositoryFormEditorDefinitions[collectionName])) {
-                        continue;
-                    }
-
-                    predefinedDefaults[collectionName] = predefinedDefaults[collectionName] || {};
-                    collections[collectionName] = $.extend(
-                        predefinedDefaults[collectionName] || {},
-                        configuration[collectionName]
-                    );
-
-                    delete predefinedDefaults[collectionName];
-                    delete configuration[collectionName];
-                }
-
-                identifierPathPrefix = identifierPathPrefix || '';
-                identifierPath = (identifierPathPrefix === '') ? configuration['identifier'] : identifierPathPrefix + '/' + configuration['identifier'];
-
-                configuration = $.extend(
-                    predefinedDefaults,
-                    configuration,
-                    {
-                        renderables: (rawChildFormElements) ? true : null,
-                        __parentRenderable: null,
-                        __identifierPath: identifierPath
-                    }
-                );
-
-                formElement = createModel(configuration);
-                formElement.set('__parentRenderable', parentFormElement || null, disablePublishersOnSet);
-
-                for (var collectionName in collections) {
-                    if (!collections.hasOwnProperty(collectionName)) {
-                        continue;
-                    }
-
-                    for (var i in collections[collectionName]) {
-                        var previousCreatePropertyCollectionElementIdentifier, propertyCollectionElement;
-                        if (!collections[collectionName].hasOwnProperty(i)) {
-                            continue;
-                        }
-                        propertyCollectionElement = createPropertyCollectionElement(
-                            collections[collectionName][i]['identifier'],
-                            collections[collectionName][i],
-                            collectionName
-                        );
-                        if (i > 0) {
-                            previousCreatePropertyCollectionElementIdentifier = collections[collectionName][i - 1]['identifier']
-                        }
-                        repository().addPropertyCollectionElement(propertyCollectionElement, collectionName, formElement, previousCreatePropertyCollectionElementIdentifier, true);
-                    }
-                }
+          objectData = getObjectData();
+          childFormElements = objectData['renderables'] || null;
+          delete objectData['renderables'];
+          delete objectData['__parentRenderable'];
+          objectData['renderables'] = (childFormElements) ? true : null,
 
-                if (registerPropertyValidators) {
-                    if ('array' === $.type(formElementTypeDefinition['editors'])) {
-                        for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) {
-                            var configuration = {};
-
-                            if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) {
-                                continue;
-                            }
-
-                            if (
-                                !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode'])
-                                && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR'
-                            ) {
-                                configuration['propertyValidatorsMode'] = 'OR';
-                            } else {
-                                configuration['propertyValidatorsMode'] = 'AND';
-                            }
-
-                            propertyValidationService().addValidatorIdentifiersToFormElementProperty(
-                                formElement,
-                                formElementTypeDefinition['editors'][i]['propertyValidators'],
-                                formElementTypeDefinition['editors'][i]['propertyPath'],
-                                undefined,
-                                undefined,
-                                configuration
-                            );
-                        }
-                    }
-                }
-
-                if ('array' === $.type(rawChildFormElements)) {
-                    currentChildFormElements = [];
-                    for (var i = 0, len = rawChildFormElements.length; i < len; ++i) {
-                        currentChildFormElements.push(createFormElement(rawChildFormElements[i], identifierPath, formElement, registerPropertyValidators, disablePublishersOnSet));
-                    }
-                    formElement.set('renderables', currentChildFormElements, disablePublishersOnSet);
-                }
-                return formElement;
-            };
+            newModel = new M();
+          extendModel(newModel, objectData, '', true);
 
-            /**
-             * @public
-             *
-             * @param string collectionElementIdentifier
-             * @param object collectionElementConfiguration
-             * @param string collectionName
-             * @return object
-             * @throws 1475377160
-             * @throws 1475377161
-             * @throws 1475377162
-             */
-            function createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName) {
-                var collectionDefinition, collectionElementPresets;
-                utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475377160);
-                utility().assert('object' === $.type(collectionElementConfiguration), 'Invalid parameter "collectionElementConfiguration"', 1475377161);
-                utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475377162);
-
-                collectionElementConfiguration['identifier'] = collectionElementIdentifier;
-                collectionDefinition = repository().getFormEditorDefinition(collectionName, collectionElementIdentifier);
-                if (collectionDefinition['predefinedDefaults']) {
-                    collectionElementPresets = collectionDefinition['predefinedDefaults'];
-                } else {
-                    collectionElementPresets = {};
-                }
+          if (null !== childFormElements) {
+            newRenderables = [];
+            for (var i = 0, len = childFormElements.length; i < len; ++i) {
+              var childFormElement = childFormElements[i];
 
-                return $.extend(collectionElementPresets, collectionElementConfiguration);
-            };
+              childFormElement = childFormElement.clone();
+              childFormElement.set('__parentRenderable', newModel, true);
+              newRenderables.push(childFormElement);
+            }
+            newModel.set('renderables', newRenderables, true);
+          }
 
-            /**
-             * Publish the public methods.
-             */
-            return {
-                createFormElement: createFormElement,
-                createPropertyCollectionElement: createPropertyCollectionElement
-            };
+          return newModel;
         };
 
         /**
-         * @public
-         *
-         * @return object
+         * Publish the public methods.
          */
-        function dataBackend() {
-
-            /**
-             * @public
-             *
-             * @param object endpoints
-             * @return void
-             * @throws 1475377488
-             */
-            function setEndpoints(endpoints) {
-                utility().assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475377488);
-                _dataBackendEndpoints = endpoints;
-            };
-
-            /**
-             * @public
-             *
-             * @param string prototypeName
-             * @return void
-             * @throws 1475377489
-             */
-            function setPrototypeName(prototypeName) {
-                utility().assert(utility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475928095);
-                _dataBackendPrototypeName = prototypeName;
-            };
-
-            /**
-             * @public
-             *
-             * @param string persistenceIdentifier
-             * @return void
-             * @throws 1475377489
-             */
-            function setPersistenceIdentifier(persistenceIdentifier) {
-                utility().assert(utility().isNonEmptyString(persistenceIdentifier), 'Invalid parameter "persistenceIdentifier"', 1475377489);
-                _dataBackendPersistenceIdentifier = persistenceIdentifier;
-            };
-
-            /**
-             * @public
-             *
-             * @return void
-             * @publish core/ajax/saveFormDefinition/success
-             * @publish core/ajax/error
-             * @throws 1475520918
-             */
-            function saveFormDefinition() {
-                utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['saveForm']), 'The endpoint "saveForm" is not configured', 1475520918);
-
-                if (_runningAjaxRequests['saveForm']) {
-                    _runningAjaxRequests['saveForm'].abort();
-                }
-
-                _runningAjaxRequests['saveForm'] = $.post(_dataBackendEndpoints['saveForm'], {
-                    tx_form_web_formformbuilder: {
-                        formPersistenceIdentifier: _dataBackendPersistenceIdentifier,
-                        formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition')))
-                    }
-                }, function(data, textStatus, jqXHR) {
-                    if (_runningAjaxRequests['saveForm'] !== jqXHR) {
-                        return;
-                    }
-                    _runningAjaxRequests['saveForm'] = null;
-                    if (data['status'] === 'success') {
-                        publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]);
-                    } else {
-                        publisherSubscriber().publish('core/ajax/saveFormDefinition/error', [data]);
-                    }
-                }).fail(function(jqXHR, textStatus, errorThrown) {
-                    publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]);
-                });
-            };
-
-            /**
-             * @public
-             *
-             * @param int pageIndex
-             * @return void
-             * @publish core/ajax/renderFormDefinitionPage/success
-             * @publish core/ajax/error
-             * @throws 1473447677
-             * @throws 1475377781
-             * @throws 1475377782
-             */
-            function renderFormDefinitionPage(pageIndex) {
-                utility().assert($.isNumeric(pageIndex), 'Invalid parameter "pageIndex"', 1475377781);
-                utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['formPageRenderer']), 'The endpoint "formPageRenderer" is not configured', 1473447677);
-
-                if (_runningAjaxRequests['renderFormDefinitionPage']) {
-                    _runningAjaxRequests['renderFormDefinitionPage'].abort();
-                }
+        return {
+          get: get,
+          set: set,
+          unset: unset,
 
-                _runningAjaxRequests['renderFormDefinitionPage'] = $.post(_dataBackendEndpoints['formPageRenderer'], {
-                    tx_form_web_formformbuilder: {
-                        formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))),
-                        pageIndex: pageIndex,
-                        prototypeName: _dataBackendPrototypeName
-                    }
-                }, function(data, textStatus, jqXHR) {
-                    if (_runningAjaxRequests['renderFormDefinitionPage'] !== jqXHR) {
-                        return;
-                    }
-                    _runningAjaxRequests['renderFormDefinitionPage'] = null;
-                    publisherSubscriber().publish('core/ajax/renderFormDefinitionPage/success', [data, pageIndex]);
-                }).fail(function(jqXHR, textStatus, errorThrown) {
-                    publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]);
-                });
-            };
+          on: on,
+          off: off,
 
-            /**
-             * Publish the public methods.
-             */
-            return {
-                renderFormDefinitionPage: renderFormDefinitionPage,
-                saveFormDefinition: saveFormDefinition,
-                setEndpoints: setEndpoints,
-                setPersistenceIdentifier: setPersistenceIdentifier,
-                setPrototypeName: setPrototypeName
-            };
+          getObjectData: getObjectData,
+          toString: toString,
+          clone: clone
+        };
+      };
+
+      newModel = new M();
+      extendModel(newModel, modelExtension, '', true);
+
+      return newModel;
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function repository() {
+
+      /**
+       * @public
+       *
+       * @param object typeDefinitions
+       * @return void
+       * @throws 1475364394
+       */
+      function setFormEditorDefinitions(formEditorDefinitions) {
+        utility().assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475364394);
+
+        for (var key1 in formEditorDefinitions) {
+          if (!formEditorDefinitions.hasOwnProperty(key1) || 'object' !== $.type(formEditorDefinitions[key1])) {
+            continue;
+          }
+          for (var key2 in formEditorDefinitions[key1]) {
+            if (!formEditorDefinitions[key1].hasOwnProperty(key2)) {
+              continue;
+            }
+            if ('object' !== $.type(formEditorDefinitions[key1][key2])) {
+              formEditorDefinitions[key1][key2] = {};
+            }
+          }
+        }
+        _repositoryFormEditorDefinitions = formEditorDefinitions;
+      };
+
+      /**
+       * @public
+       *
+       * @param string typeName
+       * @param string subject
+       * @return object (dereferenced)
+       * @throws 1475364952
+       * @throws 1475364953
+       */
+      function getFormEditorDefinition(definitionName, subject) {
+        utility().assert(utility().isNonEmptyString(definitionName), 'Invalid parameter "definitionName"', 1475364952);
+        utility().assert(utility().isNonEmptyString(subject), 'Invalid parameter "subject"', 1475364953);
+        return $.extend(true, {}, _repositoryFormEditorDefinitions[definitionName][subject]);
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getRootFormElement() {
+        return getApplicationStateStack().getCurrentState('formDefinition');
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param object referenceFormElement
+       * @param boolean registerPropertyValidators
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475436224
+       * @throws 1475364956
+       */
+      function addFormElement(formElement, referenceFormElement, registerPropertyValidators, disablePublishersOnSet) {
+        var enclosingCompositeFormElement, identifier, formElementTypeDefinition,
+          parentFormElementsArray, parentFormElementTypeDefinition, referenceFormElementElements,
+          referenceFormElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475436224);
+        utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364956);
+
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        registerPropertyValidators = !!registerPropertyValidators;
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type'));
+
+        // formElement != Page / SummaryPage && referenceFormElement == Page / Fieldset / GridContainer / GridRow
+        if (!formElementTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isCompositeFormElement']) {
+          if ('array' !== $.type(referenceFormElement.get('renderables'))) {
+            referenceFormElement.set('renderables', [], disablePublishersOnSet);
+          }
+
+          formElement.set('__parentRenderable', referenceFormElement, disablePublishersOnSet);
+          formElement.set('__identifierPath', referenceFormElement.get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet);
+          referenceFormElement.get('renderables').push(formElement);
+        } else {
+          // referenceFormElement == root form element
+          if (referenceFormElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) {
+            referenceFormElementElements = referenceFormElement.get('renderables');
+            // referenceFormElement = last page
+            referenceFormElement = referenceFormElementElements[referenceFormElementElements.length - 1];
+            // if formElement == Page / SummaryPage && referenceFormElement != Page / SummaryPage
+          } else if (formElementTypeDefinition['_isTopLevelFormElement'] && !referenceFormElementTypeDefinition['_isTopLevelFormElement']) {
+            // referenceFormElement = parent Page
+            referenceFormElement = findEnclosingCompositeFormElementWhichIsOnTopLevel(referenceFormElement);
+            // formElement == Page / SummaryPage / Fieldset / GridContainer / GridRow
+          } else if (formElementTypeDefinition['_isCompositeFormElement']) {
+            enclosingCompositeFormElement = findEnclosingCompositeFormElementWhichIsNotOnTopLevel(referenceFormElement);
+            if (enclosingCompositeFormElement) {
+              // referenceFormElement = parent Fieldset / GridContainer / GridRow
+              referenceFormElement = enclosingCompositeFormElement;
+            }
+          }
+
+          formElement.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet);
+          formElement.set('__identifierPath', referenceFormElement.get('__parentRenderable').get('__identifierPath') + '/' + formElement.get('identifier'), disablePublishersOnSet);
+          parentFormElementsArray = referenceFormElement.get('__parentRenderable').get('renderables');
+          parentFormElementsArray.splice(parentFormElementsArray.indexOf(referenceFormElement) + 1, 0, formElement);
+        }
+
+        if (registerPropertyValidators) {
+          if ('array' === $.type(formElementTypeDefinition['editors'])) {
+            for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) {
+              var configuration = {};
+
+              if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) {
+                continue;
+              }
+
+              if (
+                !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode'])
+                && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR'
+              ) {
+                configuration['propertyValidatorsMode'] = 'OR';
+              } else {
+                configuration['propertyValidatorsMode'] = 'AND';
+              }
+
+              propertyValidationService().addValidatorIdentifiersToFormElementProperty(
+                formElement,
+                formElementTypeDefinition['editors'][i]['propertyValidators'],
+                formElementTypeDefinition['editors'][i]['propertyPath'],
+                undefined,
+                undefined,
+                configuration
+              );
+            }
+          }
+        }
+
+        return formElement;
+      };
+
+      /**
+       * @param object formElement
+       * @param boolean removeRegisteredPropertyValidators
+       * @param boolean disablePublishersOnSet
+       * @return void
+       * @throws 1472553024
+       * @throws 1475364957
+       */
+      function removeFormElement(formElement, removeRegisteredPropertyValidators, disablePublishersOnSet) {
+        var parentFormElementElements;
+
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+        removeRegisteredPropertyValidators = !!removeRegisteredPropertyValidators;
+
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364957);
+        utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'Removing the root element is not allowed', 1472553024);
+
+        parentFormElementElements = formElement.get('__parentRenderable').get('renderables');
+        parentFormElementElements.splice(parentFormElementElements.indexOf(formElement), 1);
+        formElement.get('__parentRenderable').set('renderables', parentFormElementElements, disablePublishersOnSet);
+
+        if (removeRegisteredPropertyValidators) {
+          propertyValidationService().removeAllValidatorIdentifiersFromFormElement(formElement);
+        }
+      };
+
+      /**
+       * @param object formElementToMove
+       * @param string position
+       * @param object referenceFormElement
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475364958
+       * @throws 1475364959
+       * @throws 1475364960
+       * @throws 1475364961
+       * @throws 1475364962
+       * @throws 1476993731
+       * @throws 1476993732
+       */
+      function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
+        var formElementToMoveTypeDefinition, referenceFormElementParentElements,
+          referenceFormElementElements, referenceFormElementIndex,
+          referenceFormElementTypeDefinition, reSetIdentifierPath;
+        utility().assert('object' === $.type(formElementToMove), 'Invalid parameter "formElementToMove"', 1475364958);
+        utility().assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475364959);
+        utility().assert('object' === $.type(referenceFormElement), 'Invalid parameter "referenceFormElement"', 1475364960);
+
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        formElementToMoveTypeDefinition = repository().getFormEditorDefinition('formElements', formElementToMove.get('type'));
+        referenceFormElementTypeDefinition = repository().getFormEditorDefinition('formElements', referenceFormElement.get('type'));
+
+        removeFormElement(formElementToMove, false);
+        reSetIdentifierPath = function(formElement, pathPrefix) {
+          var formElements, newIdentifierPath, oldIdentifierPath,
+            propertyValidationServiceRegisteredValidators;
+          utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961);
+          utility().assert(utility().isNonEmptyString(pathPrefix), 'Invalid parameter "pathPrefix"', 1475364962);
+
+          oldIdentifierPath = formElement.get('__identifierPath');
+          newIdentifierPath = pathPrefix + '/' + formElement.get('identifier');
+
+          propertyValidationServiceRegisteredValidators = getApplicationStateStack().getCurrentState('propertyValidationServiceRegisteredValidators');
+          if (!utility().isUndefinedOrNull(propertyValidationServiceRegisteredValidators[oldIdentifierPath])) {
+            propertyValidationServiceRegisteredValidators[newIdentifierPath] = propertyValidationServiceRegisteredValidators[oldIdentifierPath];
+            delete propertyValidationServiceRegisteredValidators[oldIdentifierPath];
+          }
+          getApplicationStateStack().setCurrentState('propertyValidationServiceRegisteredValidators', propertyValidationServiceRegisteredValidators);
+
+          formElement.set('__identifierPath', newIdentifierPath, disablePublishersOnSet);
+          formElements = formElement.get('renderables');
+          if ('array' === $.type(formElements)) {
+            for (var i = 0, len = formElements.length; i < len; ++i) {
+              reSetIdentifierPath(formElements[i], formElement.get('__identifierPath'));
+            }
+          }
         };
 
         /**
-         * @public
-         *
-         * @return object
+         * This is true on:
+         * * Drag a Element on a Page Element (tree)
+         * * Drag a Element on a Section Element (tree)
          */
-        function getApplicationStateStack() {
-
-            /**
-             * @public
-             *
-             * @param object applicationState
-             * @param bool disablePublishersOnSet
-             * @return void
-             * @publish core/applicationState/add
-             * @throws 1477847415
-             */
-            function add(applicationState, disablePublishersOnSet) {
-                utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477847415);
-                disablePublishersOnSet = !!disablePublishersOnSet;
-
-                $.extend(applicationState, {
-                    propertyValidationServiceRegisteredValidators: $.extend(true, {}, getCurrentState('propertyValidationServiceRegisteredValidators'))
-                });
-
-                _applicationStateStack.splice(0, 0, applicationState);
-                if (_applicationStateStack.length > _applicationStateStackSize) {
-                    _applicationStateStack.splice(_applicationStateStackSize - 1, (_applicationStateStack.length - _applicationStateStackSize));
-                }
-
-                if (!disablePublishersOnSet) {
-                    publisherSubscriber().publish('core/applicationState/add', [applicationState, getCurrentStackPointer(), getCurrentStackSize()]);
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param applicationState
-             * @param bool disablePublishersOnSet
-             * @return void
-             * @publish core/applicationState/add
-             * @throws 1477872641
-             */
-            function addAndReset(applicationState, disablePublishersOnSet) {
-                utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477872641);
-
-                if (_applicationStateStackPointer > 0) {
-                    _applicationStateStack.splice(0, _applicationStateStackPointer);
-                }
-
-                _applicationStateStackPointer = 0;
-                add(applicationState, true);
-
-                if (!disablePublishersOnSet) {
-                    publisherSubscriber().publish('core/applicationState/add', [getCurrentState(), getCurrentStackPointer(), getCurrentStackSize()]);
-                }
-            };
-
-            /**
-             * @public
-             *
-             * @param string
-             * @return object
-             * @throws 1477932754
-             */
-            function getCurrentState(type) {
-                if (!utility().isUndefinedOrNull(type)) {
-                    utility().assert(
-                        'formDefinition' === type
-                        || 'currentlySelectedPageIndex' === type
-                        || 'currentlySelectedFormElementIdentifierPath' === type
-                        || 'propertyValidationServiceRegisteredValidators' === type,
-
-                        'Invalid parameter "type"', 1477932754
-                    );
-
-                    if ('undefined' === $.type(_applicationStateStack[_applicationStateStackPointer])) {
-                        return undefined;
-                    }
-                    return _applicationStateStack[_applicationStateStackPointer][type];
-                }
-                return _applicationStateStack[_applicationStateStackPointer];
-            };
-
-            /**
-             * @public
-             *
-             * @param string
-             * @param mixed
-             * @return void
-             * @throws 1477934111
-             */
-            function setCurrentState(type, value) {
-                utility().assert(
-                    'formDefinition' === type
-                    || 'currentlySelectedPageIndex' === type
-                    || 'currentlySelectedFormElementIdentifierPath' === type
-                    || 'propertyValidationServiceRegisteredValidators' === type,
-
-                    'Invalid parameter "type"', 1477934111
-                );
-                _applicationStateStack[_applicationStateStackPointer][type] = value;
-            };
-
-            /**
-             * @public
-             *
-             * @param int
-             * @return void
-             * @throws 1477846933
-             */
-            function setMaximalStackSize(stackSize) {
-                utility().assert('number' === $.type(stackSize), 'Invalid parameter "size"', 1477846933);
-                _applicationStateStackSize = stackSize;
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getMaximalStackSize() {
-                return _applicationStateStackSize;
-            };
-
-            /**
-             * @public
-             *
-             * @return int
-             */
-            function getCurrentStackSize() {
-                return _applicationStateStack.length;
-            };
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getCurrentStackPointer() {
-                return _applicationStateStackPointer;
-            };
-
-            /**
-             * @public
-             *
-             * @param int
-             * @return void
-             * @throws 1477852138
-             */
-            function setCurrentStackPointer(stackPointer) {
-                utility().assert('number' === $.type(stackPointer), 'Invalid parameter "size"', 1477852138);
-                if (stackPointer < 0) {
-                    _applicationStateStackPointer = 0;
-                } else if (stackPointer > _applicationStateStack.length - 1) {
-                    _applicationStateStackPointer = _applicationStateStack.length - 1;
-                } else {
-                    _applicationStateStackPointer = stackPointer;
-                }
-            };
-
+        if (position === 'inside') {
+          // formElementToMove == Page / SummaryPage
+          utility().assert(!formElementToMoveTypeDefinition['_isTopLevelFormElement'], 'This move is not allowed', 1476993731);
+          // referenceFormElement != Page / Fieldset / GridContainer / GridRow
+          utility().assert(referenceFormElementTypeDefinition['_isCompositeFormElement'], 'This move is not allowed', 1476993732);
+
+          formElementToMove.set('__parentRenderable', referenceFormElement, disablePublishersOnSet);
+          reSetIdentifierPath(formElementToMove, referenceFormElement.get('__identifierPath'));
+
+          referenceFormElementElements = referenceFormElement.get('renderables');
+          if (utility().isUndefinedOrNull(referenceFormElementElements)) {
+            referenceFormElementElements = [];
+          }
+          referenceFormElementElements.splice(0, 0, formElementToMove);
+          referenceFormElement.set('renderables', referenceFormElementElements, disablePublishersOnSet);
+        } else {
+          /**
+           * This is true on:
+           * * Drag a Page before another Page (tree)
+           * * Drag a Page after another Page (tree)
+           */
+          if (formElementToMoveTypeDefinition['_isTopLevelFormElement'] && referenceFormElementTypeDefinition['_isTopLevelFormElement']) {
+            referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
+            referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
+
+            if (position === 'after') {
+              referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove);
+            } else {
+              referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove);
+            }
 
+            referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet);
+          } else {
             /**
-             * @public
-             *
-             * @return void
+             * This is true on:
+             * * Drag a Element before another Element within the same level (tree)
+             * * Drag a Element after another Element within the same level (tree)
+             * * Drag a Element before another Element (stage)
+             * * Drag a Element after another Element (stage)
              */
-            function decrementCurrentStackPointer() {
-                setCurrentStackPointer(--_applicationStateStackPointer);
-            };
+            if (formElementToMove.get('__parentRenderable').get('identifier') === referenceFormElement.get('__parentRenderable').get('identifier')) {
+              referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
+              referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
+            } else {
+              /**
+               * This is true on:
+               * * Drag a Element before an Element on another page (tree / stage)
+               * * Drag a Element after an Element on another page (tree / stage)
+               */
+              formElementToMove.set('__parentRenderable', referenceFormElement.get('__parentRenderable'), disablePublishersOnSet);
+              reSetIdentifierPath(formElementToMove, referenceFormElement.get('__parentRenderable').get('__identifierPath'));
+
+              referenceFormElementParentElements = referenceFormElement.get('__parentRenderable').get('renderables');
+              referenceFormElementIndex = referenceFormElementParentElements.indexOf(referenceFormElement);
+            }
 
-            /**
-             * @public
-             *
-             * @return void
-             */
-            function incrementCurrentStackPointer() {
-                setCurrentStackPointer(++_applicationStateStackPointer);
-            };
+            if (position === 'after') {
+              referenceFormElementParentElements.splice(referenceFormElementIndex + 1, 0, formElementToMove);
+            } else {
+              referenceFormElementParentElements.splice(referenceFormElementIndex, 0, formElementToMove);
+            }
 
-            /**
-             * Publish the public methods.
-             */
-            return {
-                add: add,
-                addAndReset: addAndReset,
-                getCurrentState: getCurrentState,
-                setCurrentState: setCurrentState,
-                getCurrentStackPointer: getCurrentStackPointer,
-                setCurrentStackPointer: setCurrentStackPointer,
-                decrementCurrentStackPointer: decrementCurrentStackPointer,
-                incrementCurrentStackPointer: incrementCurrentStackPointer,
-                setMaximalStackSize: setMaximalStackSize,
-                getMaximalStackSize: getMaximalStackSize,
-                getCurrentStackSize: getCurrentStackSize
-            };
+            referenceFormElement.get('__parentRenderable').set('renderables', referenceFormElementParentElements, disablePublishersOnSet);
+          }
+        }
+
+        return formElementToMove;
+      };
+
+      /**
+       * @param object formElement
+       * @return int
+       * @throws 1475364963
+       */
+      function getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(formElement) {
+        var enclosingCompositeFormElementWhichIsOnTopLevel, formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364963);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+
+        if (formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) {
+          enclosingCompositeFormElementWhichIsOnTopLevel = formElement;
+        } else if (formElement.get('__identifierPath') === getApplicationStateStack().getCurrentState('formDefinition').get('__identifierPath')) {
+          enclosingCompositeFormElementWhichIsOnTopLevel = getApplicationStateStack().getCurrentState('formDefinition').get('renderables')[0];
+        } else {
+          enclosingCompositeFormElementWhichIsOnTopLevel = findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement);
+        }
+        return enclosingCompositeFormElementWhichIsOnTopLevel.get('__parentRenderable').get('renderables').indexOf(enclosingCompositeFormElementWhichIsOnTopLevel);
+      };
+
+      /**
+       * @param object formElement
+       * @return object
+       * @throws 1472556223
+       * @throws 1475364964
+       */
+      function findEnclosingCompositeFormElementWhichIsOnTopLevel(formElement) {
+        var formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364964);
+        utility().assert('object' === $.type(formElement.get('__parentRenderable')), 'The root element is never encloused by anything', 1472556223);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        while (!formElementTypeDefinition['_isTopLevelFormElement']) {
+          formElement = formElement.get('__parentRenderable');
+          formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        }
+
+        return formElement;
+      };
+
+      /**
+       * @param object formElement
+       * @return object|null
+       * @throws 1489447996
+       */
+      function findEnclosingGridContainerFormElement(formElement) {
+        var formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1489447996);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        while (!formElementTypeDefinition['_isGridContainerFormElement']) {
+          if (formElementTypeDefinition['_isTopLevelFormElement']) {
+            return null;
+          }
+          formElement = formElement.get('__parentRenderable');
+          formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        }
+        if (formElementTypeDefinition['_isTopLevelFormElement']) {
+          return null;
+        }
+        return formElement;
+      };
+
+      /**
+       * @param object formElement
+       * @return object|null
+       * @throws 1490520271
+       */
+      function findEnclosingGridRowFormElement(formElement) {
+        var formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1490520271);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        while (!formElementTypeDefinition['_isGridRowFormElement']) {
+          if (formElementTypeDefinition['_isTopLevelFormElement']) {
+            return null;
+          }
+          formElement = formElement.get('__parentRenderable');
+          formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        }
+        if (formElementTypeDefinition['_isTopLevelFormElement']) {
+          return null;
+        }
+        return formElement;
+      };
+
+      /**
+       * @param object formElement
+       * @return object|null
+       * @throws 1475364965
+       */
+      function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) {
+        var formElementTypeDefinition;
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364965);
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        while (!formElementTypeDefinition['_isCompositeFormElement']) {
+          if (formElementTypeDefinition['_isTopLevelFormElement']) {
+            return null;
+          }
+          formElement = formElement.get('__parentRenderable');
+          formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+        }
+        if (formElementTypeDefinition['_isTopLevelFormElement']) {
+          return null;
+        }
+        return formElement;
+      };
+
+      /**
+       * @return object
+       */
+      function getNonCompositeNonToplevelFormElements() {
+        var collect, nonCompositeNonToplevelFormElements;
+
+        collect = function(formElement) {
+          var formElements, formElementTypeDefinition;
+          utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475364961);
+
+          formElementTypeDefinition = repository().getFormEditorDefinition('formElements', formElement.get('type'));
+
+          if (!formElementTypeDefinition['_isTopLevelFormElement'] && !formElementTypeDefinition['_isCompositeFormElement']) {
+            nonCompositeNonToplevelFormElements.push(formElement);
+          }
+
+          formElements = formElement.get('renderables');
+          if ('array' === $.type(formElements)) {
+            for (var i = 0, len = formElements.length; i < len; ++i) {
+              collect(formElements[i]);
+            }
+          }
         };
 
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            getDataBackend: dataBackend,
-            getFactory: factory,
-            getPublisherSubscriber: publisherSubscriber,
-            getRepository: repository,
-            getUtility: utility,
-            getPropertyValidationService: propertyValidationService,
-            getRunningAjaxRequest: getRunningAjaxRequest,
-            getApplicationStateStack: getApplicationStateStack
-        };
-    })($);
+        nonCompositeNonToplevelFormElements = [];
+        collect(getRootFormElement());
+        return nonCompositeNonToplevelFormElements;
+      };
+
+      /**
+       * @param string identifier
+       * @returl bool
+       * @throws 1475364966
+       */
+      function isFormElementIdentifierUsed(identifier) {
+        var checkIdentifier, identifierFound;
+        utility().assert(utility().isNonEmptyString(identifier), 'Invalid parameter "identifier"', 1475364966);
+
+        checkIdentifier = function(formElement) {
+          var formElements;
+
+          if (formElement.get('identifier') === identifier) {
+            identifierFound = true;
+          }
+
+          if (!identifierFound) {
+            formElements = formElement.get('renderables');
+            if ('array' === $.type(formElements)) {
+              for (var i = 0, len = formElements.length; i < len; ++i) {
+                checkIdentifier(formElements[i]);
+                if (identifierFound) {
+                  break;
+                }
+              }
+            }
+          }
+        }
+
+        checkIdentifier(getApplicationStateStack().getCurrentState('formDefinition'));
+        return identifierFound;
+      };
+
+      /**
+       * @param string formElementType
+       * @return string
+       * @throws 1475373676
+       */
+      function getNextFreeFormElementIdentifier(formElementType) {
+        var i, prefix;
+        utility().assert(utility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475373676);
+
+        prefix = formElementType.toLowerCase().replace(/[^a-z0-9]/g, '-') + '-';
+        i = 1;
+        while (isFormElementIdentifierUsed(prefix + i)) {
+          i++;
+        }
+        return prefix + i;
+      };
+
+      /**
+       * @param string identifierPath
+       * @return object
+       * @throws 1472424333
+       * @throws 1472424334
+       * @throws 1472424330
+       * @throws 1475373677
+       */
+      function findFormElementByIdentifierPath(identifierPath) {
+        var obj, pathParts, pathPartsLength, formElement, formElements;
+
+        utility().assert(utility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475373677);
+
+        formElement = getApplicationStateStack().getCurrentState('formDefinition');
+        pathParts = identifierPath.split('/');
+        pathPartsLength = pathParts.length;
+
+        for (var i = 0; i < pathPartsLength; ++i) {
+          var key = pathParts[i];
+          if (i === 0 || i === pathPartsLength) {
+            utility().assert(key === formElement.get('identifier'), '"' + key + '" does not exist in path "' + identifierPath + '"', 1472424333);
+            continue;
+          }
+
+          formElements = formElement.get('renderables');
+          if ('array' === $.type(formElements)) {
+            obj = null;
+            for (var j = 0, len = formElements.length; j < len; ++j) {
+              if (key === formElements[j].get('identifier')) {
+                obj = formElements[j];
+                break;
+              }
+            }
+
+            utility().assert('null' !== $.type(obj), 'Could not find form element "' + key + '" in path "' + identifierPath + '"', 1472424334);
+            formElement = obj;
+          } else {
+            utility().assert(false, 'No form elements found', 1472424330);
+          }
+        }
+        return formElement;
+      };
+
+      /**
+       * @param string|object formElement
+       * @return object
+       */
+      function findFormElement(formElement) {
+        if ('object' === $.type(formElement)) {
+          formElement = formElement.get('__identifierPath');
+        }
+        return findFormElementByIdentifierPath(formElement);
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param object collection
+       * @return undefined|object
+       * @throws 1475375281
+       * @throws 1475375282
+       */
+      function findCollectionElementByIdentifierPath(collectionElementIdentifier, collection) {
+        utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375281);
+        utility().assert('array' === $.type(collection), 'Invalid parameter "collection"', 1475375282);
+
+        for (var i = 0, len = collection.length; i < len; ++i) {
+          if (collection[i]['identifier'] === collectionElementIdentifier) {
+            return collection[i];
+          }
+        }
+
+        return undefined;
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param object formElement
+       * @return int
+       * @throws 1475375283
+       * @throws 1475375284
+       * @throws 1475375285
+       */
+      function getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement) {
+        var collection;
+        utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375283);
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375284);
+        utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375285);
+
+        collection = formElement.get(collectionName);
+        if ('array' === $.type(collection)) {
+          for (var i = 0, len = collection.length; i < len; ++i) {
+            if (collection[i]['identifier'] === collectionElementIdentifier) {
+              return i;
+            }
+          }
+        }
+        return -1;
+      };
+
+      /**
+       * @public
+       *
+       * @param object collectionElementToAdd
+       * @param string collectionName
+       * @param object formElement
+       * @param string referenceCollectionElementIdentifier
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475375686
+       * @throws 1475375687
+       * @throws 1475375688
+       * @throws 1477413154
+       */
+      function addPropertyCollectionElement(collectionElementToAdd, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet) {
+        var collection, formElementTypeDefinition, newCollection, newCollectionElementIndex;
+        utility().assert('object' === $.type(collectionElementToAdd), 'Invalid parameter "collectionElementToAdd"', 1475375686);
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375687);
+        utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375688);
+
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        collection = formElement.get(collectionName);
+        if ('array' !== $.type(collection)) {
+          extendModel(formElement, [], collectionName, true);
+          collection = formElement.get(collectionName);
+        }
+
+        if (utility().isUndefinedOrNull(referenceCollectionElementIdentifier)) {
+          newCollectionElementIndex = 0;
+        } else {
+          newCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement) + 1;
+          utility().assert(-1 < newCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477413154);
+        }
+
+        collection.splice(newCollectionElementIndex, 0, collectionElementToAdd);
+        formElement.set(collectionName, collection, true);
+
+        propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName);
+
+        for (var i = 0, len = collection.length; i < len; ++i) {
+          extendModel(formElement, collection[i], collectionName + '.' + i, true);
+        }
+
+        formElement.set(collectionName, collection, true);
+        propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement);
+        formElement.set(collectionName, collection, disablePublishersOnSet);
+
+        return formElement;
+      };
+
+      /**
+       * @public
+       *
+       * @param object formElement
+       * @param string collectionElementIdentifier
+       * @param string collectionName
+       * @param boolean disablePublishersOnSet
+       * @return void
+       * @throws 1475375689
+       * @throws 1475375690
+       * @throws 1475375691
+       * @throws 1475375692
+       */
+      function removePropertyCollectionElementByIdentifier(formElement, collectionElementIdentifier, collectionName, disablePublishersOnSet) {
+        var collection, collectionElementIndex;
+        utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475375689);
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475375690);
+        utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475375691);
+
+        collection = formElement.get(collectionName);
+        utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1475375692);
+
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        propertyValidationService().removeValidatorIdentifiersFromFormElementProperty(formElement, collectionName);
+        collectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(collectionElementIdentifier, collectionName, formElement);
+        collection.splice(collectionElementIndex, 1);
+        formElement.set(collectionName, collection, disablePublishersOnSet);
+        propertyValidationService().addValidatorIdentifiersFromFormElementPropertyCollections(formElement);
+      };
+
+      /**
+       * @param string collectionElementToMoveIdentifier
+       * @param string position
+       * @param string referenceCollectionElementIdentifier
+       * @param string position
+       * @param object formElement
+       * @param boolean disablePublishersOnSet
+       * @return void
+       * @throws 1477404484
+       * @throws 1477404485
+       * @throws 1477404486
+       * @throws 1477404488
+       * @throws 1477404489
+       * @throws 1477404490
+       */
+      function movePropertyCollectionElement(collectionElementToMoveIdentifier, position, referenceCollectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
+        var collection, collectionElementToMove, referenceCollectionElement,
+          referenceCollectionElementIndex;
+
+        utility().assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404485);
+        utility().assert('string' === $.type(referenceCollectionElementIdentifier), 'Invalid parameter "referenceCollectionElementIdentifier"', 1477404486);
+        utility().assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1477404488);
+
+        collection = formElement.get(collectionName);
+        utility().assert('array' === $.type(collection), 'The collection "' + collectionName + '" does not exist', 1477404490);
+
+        collectionElementToMove = findCollectionElementByIdentifierPath(collectionElementToMoveIdentifier, collection);
+        utility().assert('object' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404484);
+
+        removePropertyCollectionElementByIdentifier(formElement, collectionElementToMoveIdentifier, collectionName);
+
+        referenceCollectionElementIndex = getIndexFromPropertyCollectionElementByIdentifier(referenceCollectionElementIdentifier, collectionName, formElement);
+        utility().assert(-1 < referenceCollectionElementIndex, 'Could not find collection element ' + referenceCollectionElementIdentifier + ' within collection ' + collectionName, 1477404489);
+
+        if ('before' === position) {
+          referenceCollectionElement = collection[referenceCollectionElementIndex - 1];
+          if (utility().isUndefinedOrNull(referenceCollectionElement)) {
+            referenceCollectionElementIdentifier = undefined;
+          } else {
+            referenceCollectionElementIdentifier = referenceCollectionElement['identifier'];
+          }
+        }
+
+        addPropertyCollectionElement(collectionElementToMove, collectionName, formElement, referenceCollectionElementIdentifier, disablePublishersOnSet)
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        getRootFormElement: getRootFormElement,
+
+        getFormEditorDefinition: getFormEditorDefinition,
+        setFormEditorDefinitions: setFormEditorDefinitions,
+
+        findFormElement: findFormElement,
+        findFormElementByIdentifierPath: findFormElementByIdentifierPath,
+        findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel,
+        findEnclosingCompositeFormElementWhichIsOnTopLevel: findEnclosingCompositeFormElementWhichIsOnTopLevel,
+        findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement,
+        findEnclosingGridRowFormElement: findEnclosingGridRowFormElement,
+        getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement: getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement,
+        getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements,
+
+        getNextFreeFormElementIdentifier: getNextFreeFormElementIdentifier,
+        isFormElementIdentifierUsed: isFormElementIdentifierUsed,
+
+        addFormElement: addFormElement,
+        moveFormElement: moveFormElement,
+        removeFormElement: removeFormElement,
+
+        findCollectionElementByIdentifierPath: findCollectionElementByIdentifierPath,
+        getIndexFromPropertyCollectionElementByIdentifier: getIndexFromPropertyCollectionElementByIdentifier,
+        addPropertyCollectionElement: addPropertyCollectionElement,
+        removePropertyCollectionElementByIdentifier: removePropertyCollectionElementByIdentifier,
+        movePropertyCollectionElement: movePropertyCollectionElement
+      };
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function factory() {
+
+      /**
+       * @public
+       *
+       * @param object configuration
+       * @param string identifierPathPrefix
+       * @param object parentFormElement
+       * @param boolean registerPropertyValidators
+       * @param boolean disablePublishersOnSet
+       * @return object
+       * @throws 1475375693
+       * @throws 1475436040
+       * @throws 1475604050
+       */
+      function createFormElement(configuration, identifierPathPrefix, parentFormElement, registerPropertyValidators, disablePublishersOnSet) {
+        var currentChildFormElements, collections, formElementTypeDefinition, identifierPath,
+          rawChildFormElements, formElement, predefinedDefaults;
+        utility().assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1475375693);
+        utility().assert(utility().isNonEmptyString(configuration['identifier']), '"identifier" must not be empty', 1475436040);
+        utility().assert(utility().isNonEmptyString(configuration['type']), '"type" must not be empty', 1475604050);
+
+        registerPropertyValidators = !!registerPropertyValidators;
+        if (utility().isUndefinedOrNull(disablePublishersOnSet)) {
+          disablePublishersOnSet = true;
+        }
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        formElementTypeDefinition = repository().getFormEditorDefinition('formElements', configuration['type']);
+        rawChildFormElements = configuration['renderables'];
+        delete configuration['renderables'];
+
+        collections = {};
+        predefinedDefaults = formElementTypeDefinition['predefinedDefaults'] || {};
+        for (var collectionName in configuration) {
+          if (!configuration.hasOwnProperty(collectionName)) {
+            continue;
+          }
+          if (utility().isUndefinedOrNull(_repositoryFormEditorDefinitions[collectionName])) {
+            continue;
+          }
+
+          predefinedDefaults[collectionName] = predefinedDefaults[collectionName] || {};
+          collections[collectionName] = $.extend(
+            predefinedDefaults[collectionName] || {},
+            configuration[collectionName]
+          );
+
+          delete predefinedDefaults[collectionName];
+          delete configuration[collectionName];
+        }
+
+        identifierPathPrefix = identifierPathPrefix || '';
+        identifierPath = (identifierPathPrefix === '') ? configuration['identifier'] : identifierPathPrefix + '/' + configuration['identifier'];
+
+        configuration = $.extend(
+          predefinedDefaults,
+          configuration,
+          {
+            renderables: (rawChildFormElements) ? true : null,
+            __parentRenderable: null,
+            __identifierPath: identifierPath
+          }
+        );
+
+        formElement = createModel(configuration);
+        formElement.set('__parentRenderable', parentFormElement || null, disablePublishersOnSet);
+
+        for (var collectionName in collections) {
+          if (!collections.hasOwnProperty(collectionName)) {
+            continue;
+          }
+
+          for (var i in collections[collectionName]) {
+            var previousCreatePropertyCollectionElementIdentifier, propertyCollectionElement;
+            if (!collections[collectionName].hasOwnProperty(i)) {
+              continue;
+            }
+            propertyCollectionElement = createPropertyCollectionElement(
+              collections[collectionName][i]['identifier'],
+              collections[collectionName][i],
+              collectionName
+            );
+            if (i > 0) {
+              previousCreatePropertyCollectionElementIdentifier = collections[collectionName][i - 1]['identifier']
+            }
+            repository().addPropertyCollectionElement(propertyCollectionElement, collectionName, formElement, previousCreatePropertyCollectionElementIdentifier, true);
+          }
+        }
+
+        if (registerPropertyValidators) {
+          if ('array' === $.type(formElementTypeDefinition['editors'])) {
+            for (var i = 0, len1 = formElementTypeDefinition['editors'].length; i < len1; ++i) {
+              var configuration = {};
+
+              if ('array' !== $.type(formElementTypeDefinition['editors'][i]['propertyValidators'])) {
+                continue;
+              }
+
+              if (
+                !utility().isUndefinedOrNull(formElementTypeDefinition['editors'][i]['propertyValidatorsMode'])
+                && formElementTypeDefinition['editors'][i]['propertyValidatorsMode'] === 'OR'
+              ) {
+                configuration['propertyValidatorsMode'] = 'OR';
+              } else {
+                configuration['propertyValidatorsMode'] = 'AND';
+              }
+
+              propertyValidationService().addValidatorIdentifiersToFormElementProperty(
+                formElement,
+                formElementTypeDefinition['editors'][i]['propertyValidators'],
+                formElementTypeDefinition['editors'][i]['propertyPath'],
+                undefined,
+                undefined,
+                configuration
+              );
+            }
+          }
+        }
+
+        if ('array' === $.type(rawChildFormElements)) {
+          currentChildFormElements = [];
+          for (var i = 0, len = rawChildFormElements.length; i < len; ++i) {
+            currentChildFormElements.push(createFormElement(rawChildFormElements[i], identifierPath, formElement, registerPropertyValidators, disablePublishersOnSet));
+          }
+          formElement.set('renderables', currentChildFormElements, disablePublishersOnSet);
+        }
+        return formElement;
+      };
+
+      /**
+       * @public
+       *
+       * @param string collectionElementIdentifier
+       * @param object collectionElementConfiguration
+       * @param string collectionName
+       * @return object
+       * @throws 1475377160
+       * @throws 1475377161
+       * @throws 1475377162
+       */
+      function createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName) {
+        var collectionDefinition, collectionElementPresets;
+        utility().assert(utility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475377160);
+        utility().assert('object' === $.type(collectionElementConfiguration), 'Invalid parameter "collectionElementConfiguration"', 1475377161);
+        utility().assert(utility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475377162);
+
+        collectionElementConfiguration['identifier'] = collectionElementIdentifier;
+        collectionDefinition = repository().getFormEditorDefinition(collectionName, collectionElementIdentifier);
+        if (collectionDefinition['predefinedDefaults']) {
+          collectionElementPresets = collectionDefinition['predefinedDefaults'];
+        } else {
+          collectionElementPresets = {};
+        }
+
+        return $.extend(collectionElementPresets, collectionElementConfiguration);
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        createFormElement: createFormElement,
+        createPropertyCollectionElement: createPropertyCollectionElement
+      };
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function dataBackend() {
+
+      /**
+       * @public
+       *
+       * @param object endpoints
+       * @return void
+       * @throws 1475377488
+       */
+      function setEndpoints(endpoints) {
+        utility().assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475377488);
+        _dataBackendEndpoints = endpoints;
+      };
+
+      /**
+       * @public
+       *
+       * @param string prototypeName
+       * @return void
+       * @throws 1475377489
+       */
+      function setPrototypeName(prototypeName) {
+        utility().assert(utility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475928095);
+        _dataBackendPrototypeName = prototypeName;
+      };
+
+      /**
+       * @public
+       *
+       * @param string persistenceIdentifier
+       * @return void
+       * @throws 1475377489
+       */
+      function setPersistenceIdentifier(persistenceIdentifier) {
+        utility().assert(utility().isNonEmptyString(persistenceIdentifier), 'Invalid parameter "persistenceIdentifier"', 1475377489);
+        _dataBackendPersistenceIdentifier = persistenceIdentifier;
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       * @publish core/ajax/saveFormDefinition/success
+       * @publish core/ajax/error
+       * @throws 1475520918
+       */
+      function saveFormDefinition() {
+        utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['saveForm']), 'The endpoint "saveForm" is not configured', 1475520918);
+
+        if (_runningAjaxRequests['saveForm']) {
+          _runningAjaxRequests['saveForm'].abort();
+        }
+
+        _runningAjaxRequests['saveForm'] = $.post(_dataBackendEndpoints['saveForm'], {
+          tx_form_web_formformbuilder: {
+            formPersistenceIdentifier: _dataBackendPersistenceIdentifier,
+            formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition')))
+          }
+        }, function(data, textStatus, jqXHR) {
+          if (_runningAjaxRequests['saveForm'] !== jqXHR) {
+            return;
+          }
+          _runningAjaxRequests['saveForm'] = null;
+          if (data['status'] === 'success') {
+            publisherSubscriber().publish('core/ajax/saveFormDefinition/success', [data]);
+          } else {
+            publisherSubscriber().publish('core/ajax/saveFormDefinition/error', [data]);
+          }
+        }).fail(function(jqXHR, textStatus, errorThrown) {
+          publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]);
+        });
+      };
+
+      /**
+       * @public
+       *
+       * @param int pageIndex
+       * @return void
+       * @publish core/ajax/renderFormDefinitionPage/success
+       * @publish core/ajax/error
+       * @throws 1473447677
+       * @throws 1475377781
+       * @throws 1475377782
+       */
+      function renderFormDefinitionPage(pageIndex) {
+        utility().assert($.isNumeric(pageIndex), 'Invalid parameter "pageIndex"', 1475377781);
+        utility().assert(utility().isNonEmptyString(_dataBackendEndpoints['formPageRenderer']), 'The endpoint "formPageRenderer" is not configured', 1473447677);
+
+        if (_runningAjaxRequests['renderFormDefinitionPage']) {
+          _runningAjaxRequests['renderFormDefinitionPage'].abort();
+        }
+
+        _runningAjaxRequests['renderFormDefinitionPage'] = $.post(_dataBackendEndpoints['formPageRenderer'], {
+          tx_form_web_formformbuilder: {
+            formDefinition: JSON.stringify(utility().convertToSimpleObject(getApplicationStateStack().getCurrentState('formDefinition'))),
+            pageIndex: pageIndex,
+            prototypeName: _dataBackendPrototypeName
+          }
+        }, function(data, textStatus, jqXHR) {
+          if (_runningAjaxRequests['renderFormDefinitionPage'] !== jqXHR) {
+            return;
+          }
+          _runningAjaxRequests['renderFormDefinitionPage'] = null;
+          publisherSubscriber().publish('core/ajax/renderFormDefinitionPage/success', [data, pageIndex]);
+        }).fail(function(jqXHR, textStatus, errorThrown) {
+          publisherSubscriber().publish('core/ajax/error', [jqXHR, textStatus, errorThrown]);
+        });
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        renderFormDefinitionPage: renderFormDefinitionPage,
+        saveFormDefinition: saveFormDefinition,
+        setEndpoints: setEndpoints,
+        setPersistenceIdentifier: setPersistenceIdentifier,
+        setPrototypeName: setPrototypeName
+      };
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getApplicationStateStack() {
+
+      /**
+       * @public
+       *
+       * @param object applicationState
+       * @param bool disablePublishersOnSet
+       * @return void
+       * @publish core/applicationState/add
+       * @throws 1477847415
+       */
+      function add(applicationState, disablePublishersOnSet) {
+        utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477847415);
+        disablePublishersOnSet = !!disablePublishersOnSet;
+
+        $.extend(applicationState, {
+          propertyValidationServiceRegisteredValidators: $.extend(true, {}, getCurrentState('propertyValidationServiceRegisteredValidators'))
+        });
+
+        _applicationStateStack.splice(0, 0, applicationState);
+        if (_applicationStateStack.length > _applicationStateStackSize) {
+          _applicationStateStack.splice(_applicationStateStackSize - 1, (_applicationStateStack.length - _applicationStateStackSize));
+        }
+
+        if (!disablePublishersOnSet) {
+          publisherSubscriber().publish('core/applicationState/add', [applicationState, getCurrentStackPointer(), getCurrentStackSize()]);
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param applicationState
+       * @param bool disablePublishersOnSet
+       * @return void
+       * @publish core/applicationState/add
+       * @throws 1477872641
+       */
+      function addAndReset(applicationState, disablePublishersOnSet) {
+        utility().assert('object' === $.type(applicationState), 'Invalid parameter "applicationState"', 1477872641);
+
+        if (_applicationStateStackPointer > 0) {
+          _applicationStateStack.splice(0, _applicationStateStackPointer);
+        }
+
+        _applicationStateStackPointer = 0;
+        add(applicationState, true);
+
+        if (!disablePublishersOnSet) {
+          publisherSubscriber().publish('core/applicationState/add', [getCurrentState(), getCurrentStackPointer(), getCurrentStackSize()]);
+        }
+      };
+
+      /**
+       * @public
+       *
+       * @param string
+       * @return object
+       * @throws 1477932754
+       */
+      function getCurrentState(type) {
+        if (!utility().isUndefinedOrNull(type)) {
+          utility().assert(
+            'formDefinition' === type
+            || 'currentlySelectedPageIndex' === type
+            || 'currentlySelectedFormElementIdentifierPath' === type
+            || 'propertyValidationServiceRegisteredValidators' === type,
+
+            'Invalid parameter "type"', 1477932754
+          );
+
+          if ('undefined' === $.type(_applicationStateStack[_applicationStateStackPointer])) {
+            return undefined;
+          }
+          return _applicationStateStack[_applicationStateStackPointer][type];
+        }
+        return _applicationStateStack[_applicationStateStackPointer];
+      };
+
+      /**
+       * @public
+       *
+       * @param string
+       * @param mixed
+       * @return void
+       * @throws 1477934111
+       */
+      function setCurrentState(type, value) {
+        utility().assert(
+          'formDefinition' === type
+          || 'currentlySelectedPageIndex' === type
+          || 'currentlySelectedFormElementIdentifierPath' === type
+          || 'propertyValidationServiceRegisteredValidators' === type,
+
+          'Invalid parameter "type"', 1477934111
+        );
+        _applicationStateStack[_applicationStateStackPointer][type] = value;
+      };
+
+      /**
+       * @public
+       *
+       * @param int
+       * @return void
+       * @throws 1477846933
+       */
+      function setMaximalStackSize(stackSize) {
+        utility().assert('number' === $.type(stackSize), 'Invalid parameter "size"', 1477846933);
+        _applicationStateStackSize = stackSize;
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getMaximalStackSize() {
+        return _applicationStateStackSize;
+      };
+
+      /**
+       * @public
+       *
+       * @return int
+       */
+      function getCurrentStackSize() {
+        return _applicationStateStack.length;
+      };
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getCurrentStackPointer() {
+        return _applicationStateStackPointer;
+      };
+
+      /**
+       * @public
+       *
+       * @param int
+       * @return void
+       * @throws 1477852138
+       */
+      function setCurrentStackPointer(stackPointer) {
+        utility().assert('number' === $.type(stackPointer), 'Invalid parameter "size"', 1477852138);
+        if (stackPointer < 0) {
+          _applicationStateStackPointer = 0;
+        } else if (stackPointer > _applicationStateStack.length - 1) {
+          _applicationStateStackPointer = _applicationStateStack.length - 1;
+        } else {
+          _applicationStateStackPointer = stackPointer;
+        }
+      };
+
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function decrementCurrentStackPointer() {
+        setCurrentStackPointer(--_applicationStateStackPointer);
+      };
+
+      /**
+       * @public
+       *
+       * @return void
+       */
+      function incrementCurrentStackPointer() {
+        setCurrentStackPointer(++_applicationStateStackPointer);
+      };
+
+      /**
+       * Publish the public methods.
+       */
+      return {
+        add: add,
+        addAndReset: addAndReset,
+        getCurrentState: getCurrentState,
+        setCurrentState: setCurrentState,
+        getCurrentStackPointer: getCurrentStackPointer,
+        setCurrentStackPointer: setCurrentStackPointer,
+        decrementCurrentStackPointer: decrementCurrentStackPointer,
+        incrementCurrentStackPointer: incrementCurrentStackPointer,
+        setMaximalStackSize: setMaximalStackSize,
+        getMaximalStackSize: getMaximalStackSize,
+        getCurrentStackSize: getCurrentStackSize
+      };
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      getDataBackend: dataBackend,
+      getFactory: factory,
+      getPublisherSubscriber: publisherSubscriber,
+      getRepository: repository,
+      getUtility: utility,
+      getPropertyValidationService: propertyValidationService,
+      getRunningAjaxRequest: getRunningAjaxRequest,
+      getApplicationStateStack: getApplicationStateStack
+    };
+  })($);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js
index 2f300caf7138..f6305edcb726 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Helper.js
@@ -15,300 +15,300 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/Helper
  */
 define(['jquery'], function($) {
-        'use strict';
+  'use strict';
 
-    return (function($) {
+  return (function($) {
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = {};
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = {};
 
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _defaultConfiguration = {
-            domElementClassNames: {
-                active: 'active',
-                buttonCollectionElementRemove: 't3-form-collection-element-remove-button',
-                buttonFormEditor: 't3-form-button',
-                disabled: 'disabled',
-                hidden: 'hidden',
-                icon: 't3-form-icon',
-                jQueryUiStateDisabled: 'ui-state-disabled',
-                sortableHover: 'sortable-hover'
-            },
-            domElementDataAttributeNames: {
-                elementIdentifier: 'data-element-identifier-path',
-                identifier: 'data-identifier',
-                template: 'data-template-name',
-                templateProperty: 'data-template-property'
-            },
-            domElementSelectorPattern: {
-                bracesWithKey: '[{0}]',
-                bracesWithKeyValue: '[{0}="{1}"]',
-                class: '.{0}',
-                id: '#{0}',
-                keyValue: '{0}="{1}"'
-            }
-        };
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _defaultConfiguration = {
+      domElementClassNames: {
+        active: 'active',
+        buttonCollectionElementRemove: 't3-form-collection-element-remove-button',
+        buttonFormEditor: 't3-form-button',
+        disabled: 'disabled',
+        hidden: 'hidden',
+        icon: 't3-form-icon',
+        jQueryUiStateDisabled: 'ui-state-disabled',
+        sortableHover: 'sortable-hover'
+      },
+      domElementDataAttributeNames: {
+        elementIdentifier: 'data-element-identifier-path',
+        identifier: 'data-identifier',
+        template: 'data-template-name',
+        templateProperty: 'data-template-property'
+      },
+      domElementSelectorPattern: {
+        bracesWithKey: '[{0}]',
+        bracesWithKeyValue: '[{0}="{1}"]',
+        class: '.{0}',
+        id: '#{0}',
+        keyValue: '{0}="{1}"'
+      }
+    };
 
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
 
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
 
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
 
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
 
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
 
-        /**
-         * @public
-         *
-         * @param object
-         * @return this
-         * @throws 1478950623
-         */
-        function setConfiguration(configuration) {
-            assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1478950623);
-            _configuration = $.extend(true, _defaultConfiguration, configuration);
-            return this;
-        };
+    /**
+     * @public
+     *
+     * @param object
+     * @return this
+     * @throws 1478950623
+     */
+    function setConfiguration(configuration) {
+      assert('object' === $.type(configuration), 'Invalid parameter "configuration"', 1478950623);
+      _configuration = $.extend(true, _defaultConfiguration, configuration);
+      return this;
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param array
-         * @return string
-         * @throws 1478801251
-         * @throws 1478801252
-         */
-        function buildDomElementSelectorHelper(patternIdentifier, replacements) {
-            var newString;
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][patternIdentifier]),
-                'Invalid parameter "patternIdentifier" (' + patternIdentifier + ')',
-                1478801251
-            );
-            assert('array' === $.type(replacements), 'Invalid parameter "replacements"', 1478801252);
+    /**
+     * @public
+     *
+     * @param string
+     * @param array
+     * @return string
+     * @throws 1478801251
+     * @throws 1478801252
+     */
+    function buildDomElementSelectorHelper(patternIdentifier, replacements) {
+      var newString;
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][patternIdentifier]),
+        'Invalid parameter "patternIdentifier" (' + patternIdentifier + ')',
+        1478801251
+      );
+      assert('array' === $.type(replacements), 'Invalid parameter "replacements"', 1478801252);
 
-            newString = _configuration['domElementSelectorPattern'][patternIdentifier];
-            for (var i = 0, len = replacements.length; i < len; ++i) {
-                newString = newString.replace('{' + i + '}', replacements[i]);
-            }
-            return newString;
-        };
+      newString = _configuration['domElementSelectorPattern'][patternIdentifier];
+      for (var i = 0, len = replacements.length; i < len; ++i) {
+        newString = newString.replace('{' + i + '}', replacements[i]);
+      }
+      return newString;
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param array
-         * @return string
-         * @throws 1478372374
-         */
-        function getDomElementSelector(selectorIdentifier, args) {
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][selectorIdentifier]),
-                'Invalid parameter "selectorIdentifier" (' + selectorIdentifier + ')',
-                1478372374
-            );
-            return buildDomElementSelectorHelper(selectorIdentifier, args);
-        };
+    /**
+     * @public
+     *
+     * @param string
+     * @param array
+     * @return string
+     * @throws 1478372374
+     */
+    function getDomElementSelector(selectorIdentifier, args) {
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementSelectorPattern'][selectorIdentifier]),
+        'Invalid parameter "selectorIdentifier" (' + selectorIdentifier + ')',
+        1478372374
+      );
+      return buildDomElementSelectorHelper(selectorIdentifier, args);
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param bool
-         * @return string
-         * @throws 1478803906
-         */
-        function getDomElementClassName(classNameIdentifier, asSelector) {
-            var className;
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementClassNames'][classNameIdentifier]),
-                'Invalid parameter "classNameIdentifier" (' + classNameIdentifier + ')',
-                1478803906
-            );
+    /**
+     * @public
+     *
+     * @param string
+     * @param bool
+     * @return string
+     * @throws 1478803906
+     */
+    function getDomElementClassName(classNameIdentifier, asSelector) {
+      var className;
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementClassNames'][classNameIdentifier]),
+        'Invalid parameter "classNameIdentifier" (' + classNameIdentifier + ')',
+        1478803906
+      );
 
-            className = _configuration['domElementClassNames'][classNameIdentifier];
-            if (!!asSelector) {
-                className = getDomElementSelector('class', [className]);
-            }
-            return className;
-        };
+      className = _configuration['domElementClassNames'][classNameIdentifier];
+      if (!!asSelector) {
+        className = getDomElementSelector('class', [className]);
+      }
+      return className;
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param bool
-         * @return string
-         * @throws 1479251518
-         */
-        function getDomElementIdName(idNameIdentifier, asSelector) {
-            var idName;
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementIdNames'][idNameIdentifier]),
-                'Invalid parameter "domElementIdNames" (' + idNameIdentifier + ')',
-                1479251518
-            );
+    /**
+     * @public
+     *
+     * @param string
+     * @param bool
+     * @return string
+     * @throws 1479251518
+     */
+    function getDomElementIdName(idNameIdentifier, asSelector) {
+      var idName;
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementIdNames'][idNameIdentifier]),
+        'Invalid parameter "domElementIdNames" (' + idNameIdentifier + ')',
+        1479251518
+      );
 
-            idName = _configuration['domElementIdNames'][idNameIdentifier];
-            if (!!asSelector) {
-                idName = getDomElementSelector('id', [idName]);
-            }
-            return idName;
-        };
+      idName = _configuration['domElementIdNames'][idNameIdentifier];
+      if (!!asSelector) {
+        idName = getDomElementSelector('id', [idName]);
+      }
+      return idName;
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param bool
-         * @return string
-         * @throws 1478806884
-         */
-        function getDomElementDataAttributeValue(dataAttributeValueIdentifier) {
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]),
-                'Invalid parameter "dataAttributeValueIdentifier" (' + dataAttributeValueIdentifier + ')',
-                1478806884
-            );
-            return _configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier];
-        };
+    /**
+     * @public
+     *
+     * @param string
+     * @param bool
+     * @return string
+     * @throws 1478806884
+     */
+    function getDomElementDataAttributeValue(dataAttributeValueIdentifier) {
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier]),
+        'Invalid parameter "dataAttributeValueIdentifier" (' + dataAttributeValueIdentifier + ')',
+        1478806884
+      );
+      return _configuration['domElementDataAttributeValues'][dataAttributeValueIdentifier];
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param string
-         * @param array
-         * @return string
-         * @throws 1478808035
-         */
-        function getDomElementDataAttribute(dataAttributeIdentifier, selectorIdentifier, additionalSelectorArgs) {
-            assert(
-                !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]),
-                'Invalid parameter "dataAttributeIdentifier" (' + dataAttributeIdentifier + ')',
-                1478808035
-            );
+    /**
+     * @public
+     *
+     * @param string
+     * @param string
+     * @param array
+     * @return string
+     * @throws 1478808035
+     */
+    function getDomElementDataAttribute(dataAttributeIdentifier, selectorIdentifier, additionalSelectorArgs) {
+      assert(
+        !getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]),
+        'Invalid parameter "dataAttributeIdentifier" (' + dataAttributeIdentifier + ')',
+        1478808035
+      );
 
-            if (getUtility().isUndefinedOrNull(selectorIdentifier)) {
-                return _configuration['domElementDataAttributeNames'][dataAttributeIdentifier];
-            }
+      if (getUtility().isUndefinedOrNull(selectorIdentifier)) {
+        return _configuration['domElementDataAttributeNames'][dataAttributeIdentifier];
+      }
 
-            additionalSelectorArgs = additionalSelectorArgs || [];
-            return getDomElementSelector(
-                selectorIdentifier,
-                [_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]].concat(additionalSelectorArgs)
-            );
-        };
+      additionalSelectorArgs = additionalSelectorArgs || [];
+      return getDomElementSelector(
+        selectorIdentifier,
+        [_configuration['domElementDataAttributeNames'][dataAttributeIdentifier]].concat(additionalSelectorArgs)
+      );
+    };
 
-        /**
-         * @public
-         *
-         * Return a string like [data-identifier="someValue"]
-         * 
-         * @return string
-         */
-        function getDomElementDataIdentifierSelector(dataAttributeValueIdentifier) {
-            return getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [getDomElementDataAttributeValue(dataAttributeValueIdentifier)]);
-        };
+    /**
+     * @public
+     *
+     * Return a string like [data-identifier="someValue"]
+     *
+     * @return string
+     */
+    function getDomElementDataIdentifierSelector(dataAttributeValueIdentifier) {
+      return getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [getDomElementDataAttributeValue(dataAttributeValueIdentifier)]);
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @return object
-         */
-        function getTemplate(templateName) {
-            if (!getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][templateName])) {
-                templateName = getDomElementDataAttributeValue(templateName);
-            }
+    /**
+     * @public
+     *
+     * @param string
+     * @return object
+     */
+    function getTemplate(templateName) {
+      if (!getUtility().isUndefinedOrNull(_configuration['domElementDataAttributeValues'][templateName])) {
+        templateName = getDomElementDataAttributeValue(templateName);
+      }
 
-            return $(getDomElementDataAttribute('template', 'bracesWithKeyValue', [templateName]));
-        };
+      return $(getDomElementDataAttribute('template', 'bracesWithKeyValue', [templateName]));
+    };
 
-        /**
-         * @public
-         *
-         * @param string
-         * @param object
-         * @return object
-         */
-        function getTemplatePropertyDomElement(templatePropertyName, templateDomElement) {
-            return $(getDomElementDataAttribute('templateProperty', 'bracesWithKeyValue', [templatePropertyName]), $(templateDomElement));
-        };
+    /**
+     * @public
+     *
+     * @param string
+     * @param object
+     * @return object
+     */
+    function getTemplatePropertyDomElement(templatePropertyName, templateDomElement) {
+      return $(getDomElementDataAttribute('templateProperty', 'bracesWithKeyValue', [templatePropertyName]), $(templateDomElement));
+    };
 
-        /**
-         * @public
-         *
-         * @param object formEditorApp
-         * @return void
-         */
-        function bootstrap(formEditorApp) {
-            _formEditorApp = formEditorApp;
-        };
+    /**
+     * @public
+     *
+     * @param object formEditorApp
+     * @return void
+     */
+    function bootstrap(formEditorApp) {
+      _formEditorApp = formEditorApp;
+    };
 
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            bootstrap: bootstrap,
-            buildDomElementSelectorHelper: buildDomElementSelectorHelper,
-            getDomElementClassName: getDomElementClassName,
-            getDomElementIdName: getDomElementIdName,
-            getDomElementDataAttribute: getDomElementDataAttribute,
-            getDomElementDataAttributeValue: getDomElementDataAttributeValue,
-            getDomElementDataIdentifierSelector: getDomElementDataIdentifierSelector,
-            getDomElementSelector: getDomElementSelector,
-            getTemplate: getTemplate,
-            getTemplatePropertyDomElement: getTemplatePropertyDomElement,
-            setConfiguration: setConfiguration
-        };
-    })($);
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap,
+      buildDomElementSelectorHelper: buildDomElementSelectorHelper,
+      getDomElementClassName: getDomElementClassName,
+      getDomElementIdName: getDomElementIdName,
+      getDomElementDataAttribute: getDomElementDataAttribute,
+      getDomElementDataAttributeValue: getDomElementDataAttributeValue,
+      getDomElementDataIdentifierSelector: getDomElementDataIdentifierSelector,
+      getDomElementSelector: getDomElementSelector,
+      getTemplate: getTemplate,
+      getTemplatePropertyDomElement: getTemplatePropertyDomElement,
+      setConfiguration: setConfiguration
+    };
+  })($);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js
index d4d843cc4432..5a7cadd086a1 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/InspectorComponent.js
@@ -22,2199 +22,2205 @@
 var setFormValueFromBrowseWin;
 
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper',
-        'TYPO3/CMS/Backend/Icons',
-        'TYPO3/CMS/Backend/Notification',
-        'TYPO3/CMS/Backend/Modal',
-        'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
-        ], function($, Helper, Icons, Notification, Modal) {
-        'use strict';
-
-    return (function($, Helper, Icons, Notification) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _defaultConfiguration = {
-            domElementClassNames: {
-                buttonFormElementRemove: 't3-form-remove-element-button',
-                collectionElement: 't3-form-collection-element',
-                finisherEditorPrefix: 't3-form-inspector-finishers-editor-',
-                inspectorEditor: 'form-editor',
-                inspectorInputGroup: 'input-group',
-                validatorEditorPrefix: 't3-form-inspector-validators-editor-'
-            },
-            domElementDataAttributeNames: {
-                contentElementSelectorTarget: 'data-insert-target',
-                finisher: 'data-finisher-identifier',
-                validator: 'data-validator-identifier'
-            },
-            domElementDataAttributeValues: {
-                collapse: 'actions-view-table-expand',
-                editorControlsInputGroup: 'inspectorEditorControlsGroup',
-                editorWrapper: 'editorWrapper',
-                editorControlsWrapper: 'inspectorEditorControlsWrapper',
-                formElementHeaderEditor: 'inspectorFormElementHeaderEditor',
-                formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper',
-                formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer',
-                formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer',
-                iconNotAvailable: 'actions-close',
-                iconPage: 'apps-pagetree-page-default',
-                iconTtContent: 'mimetypes-x-content-text',
-                inspector: 'inspector',
-                'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor',
-                'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor',
-                'Inspector-FinishersEditor': 'Inspector-FinishersEditor',
-                'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor',
-                'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor',
-                'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor',
-                'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor',
-                'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor',
-                'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor',
-                'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor',
-                'Inspector-TextareaEditor': 'Inspector-TextareaEditor',
-                'Inspector-TextEditor': 'Inspector-TextEditor',
-                'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor',
-                'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor',
-                inspectorFinishers: 'inspectorFinishers',
-                inspectorValidators: 'inspectorValidators',
-                propertyGridEditorAddRow: 'addRow',
-                propertyGridEditorAddRowItem: 'addRowItem',
-                propertyGridEditorContainer: 'propertyGridContainer',
-                propertyGridEditorDeleteRow: 'deleteRow',
-                propertyGridEditorLabel: 'label',
-                propertyGridEditorRowItem: 'rowItem',
-                propertyGridEditorSelectValue: 'selectValue',
-                propertyGridEditorSortRow: 'sortRow',
-                propertyGridEditorValue: 'value',
-                viewportButton: 'viewportButton'
-            },
-            domElementIdNames: {
-                finisherPrefix: 't3-form-inspector-finishers-',
-                validatorPrefix: 't3-form-inspector-validators-'
-            },
-            isSortable: true
-        };
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getViewModel() {
-            return getFormEditorApp().getViewModel();
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(_configuration);
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getCurrentlySelectedFormElement() {
-            return getFormEditorApp().getCurrentlySelectedFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return mixed
-         */
-        function getFormElementDefinition(formElement, formElementDefinitionKey) {
-            return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param object
-         * @param string
-         * @param string
-         * @return void
-         * @publish view/inspector/editor/insert/perform
-         */
-        function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            switch (editorConfiguration['templateName']) {
-                case 'Inspector-FormElementHeaderEditor':
-                    renderFormElementHeaderEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-CollectionElementHeaderEditor':
-                    renderCollectionElementHeaderEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-TextEditor':
-                    renderTextEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-FinishersEditor':
-                    renderCollectionElementSelectionEditor(
-                        'finishers',
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-ValidatorsEditor':
-                    renderCollectionElementSelectionEditor(
-                        'validators',
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-RemoveElementEditor':
-                    renderRemoveElementEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-RequiredValidatorEditor':
-                    renderRequiredValidatorEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-CheckboxEditor':
-                    renderCheckboxEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-SingleSelectEditor':
-                    renderSingleSelectEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-MultiSelectEditor':
-                    renderMultiSelectEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-GridColumnViewPortConfigurationEditor':
-                    renderGridColumnViewPortConfigurationEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-PropertyGridEditor':
-                    renderPropertyGridEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-TextareaEditor':
-                    renderTextareaEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-                case 'Inspector-Typo3WinBrowserEditor':
-                    renderTypo3WinBrowserEditor(
-                        editorConfiguration,
-                        editorHtml,
-                        collectionElementIdentifier,
-                        collectionName
-                    );
-                    break;
-            }
-            getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [
-                editorConfiguration, editorHtml, collectionElementIdentifier, collectionName
-            ]);
-        };
-
-        /**
-         * @private
-         *
-         * opens a popup window with the element browser
-         *
-         * @param string mode
-         * @param string params
-         */
-        function _openTypo3WinBrowser(mode, params) {
-            Modal.advanced({
-                type: Modal.types.iframe,
-                content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params,
-                size: Modal.sizes.large
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @param string
-         * @param string
-         * @return object
-         */
-        function _getCollectionElementClass(collectionName, collectionElementIdentifier) {
-            if (collectionName === 'finishers') {
-                return getHelper()
-                    .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier;
-            } else {
-                return getHelper()
-                    .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier;
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @param string
-         * @param string
-         * @param bool
-         * @return object
-         */
-        function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) {
-            if (collectionName === 'finishers') {
-                return getHelper()
-                    .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier;
-            } else {
-                return getHelper()
-                    .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier;
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return void
-         */
-        function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) {
-            sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({
-                revert: 'true',
-                items: getHelper().getDomElementClassName('collectionElement', true),
-                cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,textarea,select',
-                delay: 200,
-                update: function(e, o) {
-                    var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier, previousCollectionElementIdentifier;
-
-                    if (collectionName === 'finishers') {
-                        dataAttributeName = getHelper().getDomElementDataAttribute('finisher');
-                    } else {
-                        dataAttributeName = getHelper().getDomElementDataAttribute('validator');
-                    }
-
-                    movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName);
-                    previousCollectionElementIdentifier = $(o.item)
-                        .prevAll(getHelper().getDomElementClassName('collectionElement', true))
-                        .first()
-                        .attr(dataAttributeName);
-                    nextCollectionElementIdentifier = $(o.item)
-                        .nextAll(getHelper().getDomElementClassName('collectionElement', true))
-                        .first()
-                        .attr(dataAttributeName);
-
-                    getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [
-                        movedCollectionElementIdentifier,
-                        previousCollectionElementIdentifier,
-                        nextCollectionElementIdentifier,
-                        collectionName
-                    ]);
-                }
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @param object editorHtml
-         * @param bool multiSelection
-         * @param string propertyPath
-         * @param string propertyPathPrefix
-         * @return void
-         */
-        function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) {
-            var defaultValue, newPropertyData;
-
-            if (multiSelection) {
-                defaultValue = [];
-
-                $(  getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
-                    getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
-                    $(editorHtml)
-                ).each(function(i) {
-                    defaultValue.push(
-                        $(this)
-                            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
-                            .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
-                            .val()
-                        );
-                });
-                getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue);
-            } else {
-                getCurrentlySelectedFormElement().set(
-                    propertyPathPrefix + 'defaultValue',
-                    $(
-                        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
-                        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
-                        $(editorHtml)
-                    ).first()
-                        .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
-                        .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
-                        .val(),
-                    true
-                );
-            }
-
-            newPropertyData = [];
-            $(
-                getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
-                getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
-                $(editorHtml)
-            ).each(function(i) {
-                var value, label, tmpObject;
-
-                value = $(this)
-                    .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
-                    .val();
-                label = $(this)
-                    .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'))
-                    .val();
-
-                if ('' === value) {
-                    value = label;
-                }
-
-                tmpObject = {};
-                tmpObject[value] = label;
-                newPropertyData.push({
-                    _label: label,
-                    _value: value
-                });
-            });
-
-            getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData);
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         */
-        function _getEditorWrapperDomElement(editorDomElement) {
-            return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement));
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         */
-        function _getEditorControlsWrapperDomElement(editorDomElement) {
-            return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement));
-        };
-
-        /**
-         * @private
-         *
-         * @param string
-         * @param object
-         * @return void
-         */
-        function _validateCollectionElement(propertyPath, editorHtml) {
-            var hasError, propertyPrefix, validationResults;
-
-            validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath);
-
-            if (validationResults.length > 0) {
-                getHelper()
-                    .getTemplatePropertyDomElement('validationErrors', editorHtml)
-                    .text(validationResults[0]);
-                getViewModel().setElementValidationErrorClass(
-                    getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
-                );
-                getViewModel().setElementValidationErrorClass(
-                    _getEditorControlsWrapperDomElement(editorHtml),
-                    'hasError'
-                );
-            } else {
-                getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text('');
-                getViewModel().removeElementValidationErrorClass(
-                    getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
-                );
-                getViewModel().removeElementValidationErrorClass(
-                    _getEditorControlsWrapperDomElement(editorHtml),
-                    'hasError'
-                );
-            }
-
-            validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement());
-            propertyPrefix = propertyPath.split('.');
-            propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1];
-
-            hasError = false;
-            for (var i = 0, len = validationResults.length; i < len; ++i) {
-                if (
-                    validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0
-                    && validationResults[i]['validationResults']
-                    && validationResults[i]['validationResults'].length > 0
-                ) {
-                    hasError = true;
-                    break;
-                }
-            }
-
-            if (hasError) {
-                getViewModel().setElementValidationErrorClass(
-                    _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
-                );
-            } else {
-                getViewModel().removeElementValidationErrorClass(
-                    _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
-                );
-            }
-        };
-
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * callback from TYPO3/CMS/Recordlist/ElementBrowser
-         *
-         * @param string fieldReference
-         * @param string elValue
-         * @param string elName
-         * @return void
-         */
-        setFormValueFromBrowseWin = function(fieldReference, elValue, elName) {
-            var result;
-            result = elValue.split('_');
-
-            $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference]))
-                .val(result.pop())
-                .trigger('paste');
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getInspectorDomElement() {
-            return $(getHelper().getDomElementDataIdentifierSelector('inspector'));
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getFinishersContainerDomElement() {
-            return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement());
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getValidatorsContainerDomElement() {
-            return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement());
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @param string
-         * @return object
-         */
-        function getCollectionElementDomElement(collectionName, collectionElementIdentifier) {
-            if (collectionName === 'finishers') {
-                return $(getHelper().getDomElementDataAttribute(
-                            'finisher',
-                            'bracesWithKeyValue',
-                            [collectionElementIdentifier]
-                        ), getFinishersContainerDomElement());
-            } else {
-                return $(getHelper().getDomElementDataAttribute(
-                        'validator',
-                        'bracesWithKeyValue',
-                        [collectionElementIdentifier]
-                    ), getValidatorsContainerDomElement());
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param function
-         * @return void
-         */
-        function renderEditors(formElement, callback) {
-            var formElementTypeDefinition;
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-
-            getInspectorDomElement().off().empty();
-
-            formElementTypeDefinition = getFormElementDefinition(formElement);
-            if ('array' !== $.type(formElementTypeDefinition['editors'])) {
-                return;
-            }
-
-            for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) {
-                var html, template;
-
-                template = getHelper()
-                    .getTemplate(formElementTypeDefinition['editors'][i]['templateName'])
-                    .clone();
-                if (!template.length) {
-                    continue;
-                }
-                html = $(template.html());
-
-                $(html)
-                    .first()
-                    .addClass(getHelper().getDomElementClassName('inspectorEditor'));
-                getInspectorDomElement().append($(html));
-
-                _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html);
-            }
-
-            if ('function' === $.type(callback)) {
-                callback();
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionName
-         * @param string collectionElementIdentifier
-         * @return void
-         * @publish view/inspector/collectionElements/dnd/update
-         * @throws 1478354853
-         * @throws 1478354854
-         */
-        function renderCollectionElementEditors(collectionName, collectionElementIdentifier) {
-            var collapseWrapper, collectionContainer, collectionContainerElementWrapper, collectionElementConfiguration, collectionElementEditorsLength;
-
-            assert(
-                getUtility().isNonEmptyString(collectionName),
-                'Invalid parameter "collectionName"',
-                1478354853
-            );
-            assert(
-                getUtility().isNonEmptyString(collectionElementIdentifier),
-                'Invalid parameter "collectionElementIdentifier"',
-                1478354854
-            );
-
-            collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
-                collectionElementIdentifier,
-                collectionName
-            );
-            if ('array' !== $.type(collectionElementConfiguration['editors'])) {
-                return;
-            }
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
+], function($, Helper, Icons, Notification, Modal) {
+  'use strict';
+
+  return (function($, Helper, Icons, Notification) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _defaultConfiguration = {
+      domElementClassNames: {
+        buttonFormElementRemove: 't3-form-remove-element-button',
+        collectionElement: 't3-form-collection-element',
+        finisherEditorPrefix: 't3-form-inspector-finishers-editor-',
+        inspectorEditor: 'form-editor',
+        inspectorInputGroup: 'input-group',
+        validatorEditorPrefix: 't3-form-inspector-validators-editor-'
+      },
+      domElementDataAttributeNames: {
+        contentElementSelectorTarget: 'data-insert-target',
+        finisher: 'data-finisher-identifier',
+        validator: 'data-validator-identifier'
+      },
+      domElementDataAttributeValues: {
+        collapse: 'actions-view-table-expand',
+        editorControlsInputGroup: 'inspectorEditorControlsGroup',
+        editorWrapper: 'editorWrapper',
+        editorControlsWrapper: 'inspectorEditorControlsWrapper',
+        formElementHeaderEditor: 'inspectorFormElementHeaderEditor',
+        formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper',
+        formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer',
+        formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer',
+        iconNotAvailable: 'actions-close',
+        iconPage: 'apps-pagetree-page-default',
+        iconTtContent: 'mimetypes-x-content-text',
+        inspector: 'inspector',
+        'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor',
+        'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor',
+        'Inspector-FinishersEditor': 'Inspector-FinishersEditor',
+        'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor',
+        'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor',
+        'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor',
+        'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor',
+        'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor',
+        'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor',
+        'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor',
+        'Inspector-TextareaEditor': 'Inspector-TextareaEditor',
+        'Inspector-TextEditor': 'Inspector-TextEditor',
+        'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor',
+        'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor',
+        inspectorFinishers: 'inspectorFinishers',
+        inspectorValidators: 'inspectorValidators',
+        propertyGridEditorAddRow: 'addRow',
+        propertyGridEditorAddRowItem: 'addRowItem',
+        propertyGridEditorContainer: 'propertyGridContainer',
+        propertyGridEditorDeleteRow: 'deleteRow',
+        propertyGridEditorLabel: 'label',
+        propertyGridEditorRowItem: 'rowItem',
+        propertyGridEditorSelectValue: 'selectValue',
+        propertyGridEditorSortRow: 'sortRow',
+        propertyGridEditorValue: 'value',
+        viewportButton: 'viewportButton'
+      },
+      domElementIdNames: {
+        finisherPrefix: 't3-form-inspector-finishers-',
+        validatorPrefix: 't3-form-inspector-validators-'
+      },
+      isSortable: true
+    };
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getViewModel() {
+      return getFormEditorApp().getViewModel();
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(_configuration);
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getCurrentlySelectedFormElement() {
+      return getFormEditorApp().getCurrentlySelectedFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return mixed
+     */
+    function getFormElementDefinition(formElement, formElementDefinitionKey) {
+      return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param object
+     * @param string
+     * @param string
+     * @return void
+     * @publish view/inspector/editor/insert/perform
+     */
+    function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      switch (editorConfiguration['templateName']) {
+        case 'Inspector-FormElementHeaderEditor':
+          renderFormElementHeaderEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-CollectionElementHeaderEditor':
+          renderCollectionElementHeaderEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-TextEditor':
+          renderTextEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-FinishersEditor':
+          renderCollectionElementSelectionEditor(
+            'finishers',
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-ValidatorsEditor':
+          renderCollectionElementSelectionEditor(
+            'validators',
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-RemoveElementEditor':
+          renderRemoveElementEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-RequiredValidatorEditor':
+          renderRequiredValidatorEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-CheckboxEditor':
+          renderCheckboxEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-SingleSelectEditor':
+          renderSingleSelectEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-MultiSelectEditor':
+          renderMultiSelectEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-GridColumnViewPortConfigurationEditor':
+          renderGridColumnViewPortConfigurationEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-PropertyGridEditor':
+          renderPropertyGridEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-TextareaEditor':
+          renderTextareaEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+        case 'Inspector-Typo3WinBrowserEditor':
+          renderTypo3WinBrowserEditor(
+            editorConfiguration,
+            editorHtml,
+            collectionElementIdentifier,
+            collectionName
+          );
+          break;
+      }
+      getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [
+        editorConfiguration, editorHtml, collectionElementIdentifier, collectionName
+      ]);
+    };
+
+    /**
+     * @private
+     *
+     * opens a popup window with the element browser
+     *
+     * @param string mode
+     * @param string params
+     */
+    function _openTypo3WinBrowser(mode, params) {
+      Modal.advanced({
+        type: Modal.types.iframe,
+        content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params,
+        size: Modal.sizes.large
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @param string
+     * @param string
+     * @return object
+     */
+    function _getCollectionElementClass(collectionName, collectionElementIdentifier) {
+      if (collectionName === 'finishers') {
+        return getHelper()
+          .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier;
+      } else {
+        return getHelper()
+          .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier;
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @param string
+     * @param string
+     * @param bool
+     * @return object
+     */
+    function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) {
+      if (collectionName === 'finishers') {
+        return getHelper()
+          .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier;
+      } else {
+        return getHelper()
+          .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier;
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return void
+     */
+    function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) {
+      sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({
+        revert: 'true',
+        items: getHelper().getDomElementClassName('collectionElement', true),
+        cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,textarea,select',
+        delay: 200,
+        update: function(e, o) {
+          var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier,
+            previousCollectionElementIdentifier;
+
+          if (collectionName === 'finishers') {
+            dataAttributeName = getHelper().getDomElementDataAttribute('finisher');
+          } else {
+            dataAttributeName = getHelper().getDomElementDataAttribute('validator');
+          }
+
+          movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName);
+          previousCollectionElementIdentifier = $(o.item)
+            .prevAll(getHelper().getDomElementClassName('collectionElement', true))
+            .first()
+            .attr(dataAttributeName);
+          nextCollectionElementIdentifier = $(o.item)
+            .nextAll(getHelper().getDomElementClassName('collectionElement', true))
+            .first()
+            .attr(dataAttributeName);
+
+          getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [
+            movedCollectionElementIdentifier,
+            previousCollectionElementIdentifier,
+            nextCollectionElementIdentifier,
+            collectionName
+          ]);
+        }
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @param object editorHtml
+     * @param bool multiSelection
+     * @param string propertyPath
+     * @param string propertyPathPrefix
+     * @return void
+     */
+    function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) {
+      var defaultValue, newPropertyData;
+
+      if (multiSelection) {
+        defaultValue = [];
+
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
+          getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
+          $(editorHtml)
+        ).each(function(i) {
+          defaultValue.push(
+            $(this)
+              .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
+              .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
+              .val()
+          );
+        });
+        getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue);
+      } else {
+        getCurrentlySelectedFormElement().set(
+          propertyPathPrefix + 'defaultValue',
+          $(
+            getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
+            getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
+            $(editorHtml)
+          ).first()
+            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
+            .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
+            .val(),
+          true
+        );
+      }
+
+      newPropertyData = [];
+      $(
+        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
+        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
+        $(editorHtml)
+      ).each(function(i) {
+        var value, label, tmpObject;
+
+        value = $(this)
+          .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
+          .val();
+        label = $(this)
+          .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'))
+          .val();
+
+        if ('' === value) {
+          value = label;
+        }
 
-            collectionContainerElementWrapper = $('<div></div>').
-                addClass(getHelper().getDomElementClassName('collectionElement'));
-            if (collectionName === 'finishers') {
-                collectionContainer = getFinishersContainerDomElement();
-                collectionContainerElementWrapper
-                    .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier);
-            } else {
-                collectionContainer = getValidatorsContainerDomElement();
-                collectionContainerElementWrapper
-                    .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier);
-            }
-            collectionContainer.append(collectionContainerElementWrapper);
+        tmpObject = {};
+        tmpObject[value] = label;
+        newPropertyData.push({
+          _label: label,
+          _value: value
+        });
+      });
+
+      getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData);
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     */
+    function _getEditorWrapperDomElement(editorDomElement) {
+      return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement));
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     */
+    function _getEditorControlsWrapperDomElement(editorDomElement) {
+      return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement));
+    };
+
+    /**
+     * @private
+     *
+     * @param string
+     * @param object
+     * @return void
+     */
+    function _validateCollectionElement(propertyPath, editorHtml) {
+      var hasError, propertyPrefix, validationResults;
+
+      validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath);
+
+      if (validationResults.length > 0) {
+        getHelper()
+          .getTemplatePropertyDomElement('validationErrors', editorHtml)
+          .text(validationResults[0]);
+        getViewModel().setElementValidationErrorClass(
+          getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
+        );
+        getViewModel().setElementValidationErrorClass(
+          _getEditorControlsWrapperDomElement(editorHtml),
+          'hasError'
+        );
+      } else {
+        getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text('');
+        getViewModel().removeElementValidationErrorClass(
+          getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
+        );
+        getViewModel().removeElementValidationErrorClass(
+          _getEditorControlsWrapperDomElement(editorHtml),
+          'hasError'
+        );
+      }
+
+      validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement());
+      propertyPrefix = propertyPath.split('.');
+      propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1];
+
+      hasError = false;
+      for (var i = 0, len = validationResults.length; i < len; ++i) {
+        if (
+          validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0
+          && validationResults[i]['validationResults']
+          && validationResults[i]['validationResults'].length > 0
+        ) {
+          hasError = true;
+          break;
+        }
+      }
+
+      if (hasError) {
+        getViewModel().setElementValidationErrorClass(
+          _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
+        );
+      } else {
+        getViewModel().removeElementValidationErrorClass(
+          _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
+        );
+      }
+    };
+
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * callback from TYPO3/CMS/Recordlist/ElementBrowser
+     *
+     * @param string fieldReference
+     * @param string elValue
+     * @param string elName
+     * @return void
+     */
+    setFormValueFromBrowseWin = function(fieldReference, elValue, elName) {
+      var result;
+      result = elValue.split('_');
+
+      $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference]))
+        .val(result.pop())
+        .trigger('paste');
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getInspectorDomElement() {
+      return $(getHelper().getDomElementDataIdentifierSelector('inspector'));
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getFinishersContainerDomElement() {
+      return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement());
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getValidatorsContainerDomElement() {
+      return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement());
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @param string
+     * @return object
+     */
+    function getCollectionElementDomElement(collectionName, collectionElementIdentifier) {
+      if (collectionName === 'finishers') {
+        return $(getHelper().getDomElementDataAttribute(
+          'finisher',
+          'bracesWithKeyValue',
+          [collectionElementIdentifier]
+        ), getFinishersContainerDomElement());
+      } else {
+        return $(getHelper().getDomElementDataAttribute(
+          'validator',
+          'bracesWithKeyValue',
+          [collectionElementIdentifier]
+        ), getValidatorsContainerDomElement());
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param function
+     * @return void
+     */
+    function renderEditors(formElement, callback) {
+      var formElementTypeDefinition;
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+
+      getInspectorDomElement().off().empty();
+
+      formElementTypeDefinition = getFormElementDefinition(formElement);
+      if ('array' !== $.type(formElementTypeDefinition['editors'])) {
+        return;
+      }
+
+      for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) {
+        var html, template;
+
+        template = getHelper()
+          .getTemplate(formElementTypeDefinition['editors'][i]['templateName'])
+          .clone();
+        if (!template.length) {
+          continue;
+        }
+        html = $(template.html());
+
+        $(html)
+          .first()
+          .addClass(getHelper().getDomElementClassName('inspectorEditor'));
+        getInspectorDomElement().append($(html));
+
+        _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html);
+      }
+
+      if ('function' === $.type(callback)) {
+        callback();
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionName
+     * @param string collectionElementIdentifier
+     * @return void
+     * @publish view/inspector/collectionElements/dnd/update
+     * @throws 1478354853
+     * @throws 1478354854
+     */
+    function renderCollectionElementEditors(collectionName, collectionElementIdentifier) {
+      var collapseWrapper, collectionContainer, collectionContainerElementWrapper,
+        collectionElementConfiguration, collectionElementEditorsLength;
+
+      assert(
+        getUtility().isNonEmptyString(collectionName),
+        'Invalid parameter "collectionName"',
+        1478354853
+      );
+      assert(
+        getUtility().isNonEmptyString(collectionElementIdentifier),
+        'Invalid parameter "collectionElementIdentifier"',
+        1478354854
+      );
+
+      collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
+        collectionElementIdentifier,
+        collectionName
+      );
+      if ('array' !== $.type(collectionElementConfiguration['editors'])) {
+        return;
+      }
+
+      collectionContainerElementWrapper = $('<div></div>').addClass(getHelper().getDomElementClassName('collectionElement'));
+      if (collectionName === 'finishers') {
+        collectionContainer = getFinishersContainerDomElement();
+        collectionContainerElementWrapper
+          .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier);
+      } else {
+        collectionContainer = getValidatorsContainerDomElement();
+        collectionContainerElementWrapper
+          .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier);
+      }
+      collectionContainer.append(collectionContainerElementWrapper);
+
+      collectionElementEditorsLength = collectionElementConfiguration['editors'].length;
+      if (
+        collectionElementEditorsLength > 0
+        && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
+      ) {
+        collapseWrapper = $('<div role="tabpanel"></div>')
+          .addClass('panel-collapse collapse')
+          .prop('id', _getCollectionElementId(
+            collectionName,
+            collectionElementIdentifier
+          ));
+      }
+
+      for (var i = 0; i < collectionElementEditorsLength; ++i) {
+        var html, template;
+
+        template = getHelper()
+          .getTemplate(collectionElementConfiguration['editors'][i]['templateName'])
+          .clone();
+        if (!template.length) {
+          continue;
+        }
+        html = $(template.html());
+
+        $(html).first()
+          .addClass(_getCollectionElementClass(
+            collectionName,
+            collectionElementConfiguration['editors'][i]['identifier']
+          ))
+          .addClass(getHelper().getDomElementClassName('inspectorEditor'));
+
+        if (i === 0 && collapseWrapper) {
+          getCollectionElementDomElement(collectionName, collectionElementIdentifier)
+            .append(html)
+            .append(collapseWrapper);
+        } else if (
+          i === (collectionElementEditorsLength - 1)
+          && collapseWrapper
+          && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton'
+        ) {
+          getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
+        } else if (i > 0 && collapseWrapper) {
+          collapseWrapper.append(html);
+        } else {
+          getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
+        }
 
-            collectionElementEditorsLength = collectionElementConfiguration['editors'].length;
-            if (
-                collectionElementEditorsLength > 0
-                && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
-            ) {
-                collapseWrapper = $('<div role="tabpanel"></div>')
-                    .addClass('panel-collapse collapse')
-                    .prop('id', _getCollectionElementId(
-                        collectionName,
-                        collectionElementIdentifier
-                    ));
+        _renderEditorDispatcher(
+          collectionElementConfiguration['editors'][i],
+          html,
+          collectionElementIdentifier,
+          collectionName
+        );
+      }
+
+      if (
+        (
+          collectionElementEditorsLength === 2
+          && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
+          && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton'
+        ) || (
+          collectionElementEditorsLength === 1
+          && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
+        )
+      ) {
+        $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove();
+      }
+
+      if (_configuration['isSortable']) {
+        _addSortableCollectionElementsEvents(collectionContainer, collectionName);
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @string collectionName
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @return void
+     * @publish view/inspector/collectionElement/existing/selected
+     * @publish view/inspector/collectionElement/new/selected
+     * @throws 1475423098
+     * @throws 1475423099
+     * @throws 1475423100
+     * @throws 1475423101
+     * @throws 1478362968
+     */
+    function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) {
+      var alreadySelectedCollectionElements, selectElement, collectionContainer,
+        removeSelectElement;
+      assert(
+        getUtility().isNonEmptyString(collectionName),
+        'Invalid configuration "collectionName"',
+        1478362968
+      );
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475423098
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475423099
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475423100
+      );
+      assert(
+        'array' === $.type(editorConfiguration['selectOptions']),
+        'Invalid configuration "selectOptions"',
+        1475423101
+      );
+
+      if (collectionName === 'finishers') {
+        collectionContainer = getFinishersContainerDomElement();
+        alreadySelectedCollectionElements = getRootFormElement().get(collectionName);
+      } else {
+        collectionContainer = getValidatorsContainerDomElement();
+        alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName);
+      }
+
+      collectionContainer.off().empty();
+
+      getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']);
+      selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml);
+
+      if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
+        for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) {
+          getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [
+            alreadySelectedCollectionElements[i]['identifier'],
+            collectionName
+          ]);
+        }
+      }
+
+      removeSelectElement = true;
+      for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
+        var appendOption = true;
+        if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
+          for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) {
+            if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) {
+              appendOption = false;
+              break;
             }
+          }
+        }
+        if (appendOption) {
+          selectElement.append(new Option(
+            editorConfiguration['selectOptions'][i]['label'],
+            editorConfiguration['selectOptions'][i]['value']
+          ));
+          if (editorConfiguration['selectOptions'][i]['value'] !== '') {
+            removeSelectElement = false;
+          }
+        }
+      }
 
-            for (var i = 0; i < collectionElementEditorsLength; ++i) {
-                var html, template;
-
-                template = getHelper()
-                    .getTemplate(collectionElementConfiguration['editors'][i]['templateName'])
-                    .clone();
-                if (!template.length) {
-                    continue;
-                }
-                html = $(template.html());
-
-                $(html).first()
-                    .addClass(_getCollectionElementClass(
-                        collectionName,
-                        collectionElementConfiguration['editors'][i]['identifier']
-                    ))
-                    .addClass(getHelper().getDomElementClassName('inspectorEditor'));
-
-                if (i === 0 && collapseWrapper) {
-                    getCollectionElementDomElement(collectionName, collectionElementIdentifier)
-                        .append(html)
-                        .append(collapseWrapper);
-                } else if (
-                    i === (collectionElementEditorsLength - 1)
-                    && collapseWrapper
-                    && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton'
-                ) {
-                    getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
-                } else if (i > 0 && collapseWrapper) {
-                    collapseWrapper.append(html);
-                } else {
-                    getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
-                }
+      if (removeSelectElement) {
+        selectElement.off().empty().remove();
+      }
 
-                _renderEditorDispatcher(
-                    collectionElementConfiguration['editors'][i],
-                    html,
-                    collectionElementIdentifier,
-                    collectionName
-                );
-            }
+      selectElement.on('change', function() {
+        if ($(this).val() !== '') {
+          var value = $(this).val();
+          $('option[value="' + value + '"]', $(this)).remove();
 
+          getFormEditorApp().getPublisherSubscriber().publish(
+            'view/inspector/collectionElement/new/selected',
+            [value, collectionName]
+          );
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475421525
+     * @throws 1475421526
+     * @throws 1475421527
+     * @throws 1475421528
+     */
+    function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525);
+      assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526);
+
+      Icons.getIcon(
+        getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'),
+        Icons.sizes.small,
+        null,
+        Icons.states.default
+      ).done(function(icon) {
+        getHelper().getTemplatePropertyDomElement('header-label', editorHtml)
+          .append($(icon).addClass(getHelper().getDomElementClassName('icon')))
+          .append(buildTitleByFormElement());
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475421257
+     * @throws 1475421258
+     * @throws 1475421259
+     */
+    function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var collectionElementConfiguration, setData;
+
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475421258
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475421257
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475421259
+      );
+
+      setData = function(icon) {
+        getHelper()
+          .getTemplatePropertyDomElement('header-label', editorHtml)
+          .prepend($(icon));
+
+        Icons.getIcon(
+          getHelper().getDomElementDataAttributeValue('collapse'),
+          Icons.sizes.small,
+          null,
+          Icons.states.default,
+          Icons.markupIdentifiers.inline
+        ).done(function(icon) {
+          var iconWrap;
+          iconWrap = $('<a></a>')
+            .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true))
+            .attr('data-toggle', 'collapse')
+            .attr('aria-expanded', 'true')
+            .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier))
+            .addClass('collapsed')
+            .append($(icon));
+
+          getHelper()
+            .getTemplatePropertyDomElement('header-label', editorHtml)
+            .prepend(iconWrap);
+        });
+      };
+
+      collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier);
+      if (collectionName === 'validators') {
+        Icons.getIcon(
+          collectionElementConfiguration['iconIdentifier'],
+          Icons.sizes.small,
+          null,
+          Icons.states.default
+        ).done(function(icon) {
+          setData(icon);
+        });
+      } else {
+        Icons.getIcon(
+          collectionElementConfiguration['iconIdentifier'],
+          Icons.sizes.small,
+          null,
+          Icons.states.default
+        ).done(function(icon) {
+          setData(icon);
+        });
+      }
+
+      if (editorConfiguration['label']) {
+        getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475421053
+     * @throws 1475421054
+     * @throws 1475421055
+     * @throws 1475421056
+     */
+    function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyData, propertyPath;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475421053
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475421054
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475421055
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1475421056
+      );
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+      if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .text(editorConfiguration['fieldExplanationText']);
+      } else {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .remove();
+      }
+
+      propertyPath = getFormEditorApp().buildPropertyPath(
+        editorConfiguration['propertyPath'],
+        collectionElementIdentifier,
+        collectionName
+      );
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+
+      _validateCollectionElement(propertyPath, editorHtml);
+
+      getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
+
+      renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath);
+
+      getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
+        if (
+          !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
+          && !getUtility().isNonEmptyString($(this).val())
+        ) {
+          getCurrentlySelectedFormElement().unset(propertyPath);
+        } else {
+          getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
+        }
+        _validateCollectionElement(propertyPath, editorHtml);
+        if (
+          !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths'])
+          && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths'])
+        ) {
+          for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) {
             if (
-                (
-                    collectionElementEditorsLength === 2
-                    && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
-                    && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton'
-                ) || (
-                    collectionElementEditorsLength === 1
-                    && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
-                )
+              !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
+              && !getUtility().isNonEmptyString($(this).val())
             ) {
-                $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove();
-            }
-
-            if (_configuration['isSortable']) {
-                _addSortableCollectionElementsEvents(collectionContainer, collectionName);
-            }
-        };
-
-       /**
-         * @public
-         *
-         * @string collectionName
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @return void
-         * @publish view/inspector/collectionElement/existing/selected
-         * @publish view/inspector/collectionElement/new/selected
-         * @throws 1475423098
-         * @throws 1475423099
-         * @throws 1475423100
-         * @throws 1475423101
-         * @throws 1478362968
-         */
-        function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) {
-            var alreadySelectedCollectionElements, selectElement, collectionContainer, removeSelectElement;
-            assert(
-                getUtility().isNonEmptyString(collectionName),
-                'Invalid configuration "collectionName"',
-                1478362968
-            );
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475423098
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475423099
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475423100
-            );
-            assert(
-                'array' === $.type(editorConfiguration['selectOptions']),
-                'Invalid configuration "selectOptions"',
-                1475423101
-            );
-
-            if (collectionName === 'finishers') {
-                collectionContainer = getFinishersContainerDomElement();
-                alreadySelectedCollectionElements = getRootFormElement().get(collectionName);
+              getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]);
             } else {
-                collectionContainer = getValidatorsContainerDomElement();
-                alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName);
+              getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val());
             }
+          }
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475421048
+     * @throws 1475421049
+     * @throws 1475421050
+     * @throws 1475421051
+     * @throws 1475421052
+     */
+    function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyData, propertyPath, selectElement;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475421048
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475421049
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475421050
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1475421051
+      );
+      assert(
+        'array' === $.type(editorConfiguration['selectOptions']),
+        'Invalid configuration "selectOptions"',
+        1475421052
+      );
+
+      propertyPath = getFormEditorApp().buildPropertyPath(
+        editorConfiguration['propertyPath'],
+        collectionElementIdentifier,
+        collectionName
+      );
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+
+      selectElement = getHelper()
+        .getTemplatePropertyDomElement('selectOptions', editorHtml);
+
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+
+      for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) {
+        var option;
+
+        if (editorConfiguration['selectOptions'][i]['value'] === propertyData) {
+          option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
+        } else {
+          option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
+        }
+        $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
+        selectElement.append(option);
+      }
+
+      selectElement.on('change', function() {
+        getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value'));
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1485712399
+     * @throws 1485712400
+     * @throws 1485712401
+     * @throws 1485712402
+     * @throws 1485712403
+     */
+    function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyData, propertyPath, selectElement;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1485712399
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1485712400
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1485712401
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1485712402
+      );
+      assert(
+        'array' === $.type(editorConfiguration['selectOptions']),
+        'Invalid configuration "selectOptions"',
+        1485712403
+      );
+
+      propertyPath = getFormEditorApp().buildPropertyPath(
+        editorConfiguration['propertyPath'],
+        collectionElementIdentifier,
+        collectionName
+      );
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+
+      selectElement = getHelper()
+        .getTemplatePropertyDomElement('selectOptions', editorHtml);
+
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+
+      for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
+        var option, value;
+
+        option = null;
+        for (var propertyDataKey in propertyData) {
+          if (!propertyData.hasOwnProperty(propertyDataKey)) {
+            continue;
+          }
+          if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) {
+            option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
+            break;
+          }
+        }
 
-            collectionContainer.off().empty();
-
-            getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']);
-            selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml);
-
-            if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
-                for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) {
-                    getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [
-                        alreadySelectedCollectionElements[i]['identifier'],
-                        collectionName
-                    ]);
-                }
-            }
+        if (!option) {
+          option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
+        }
 
-            removeSelectElement = true;
-            for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
-                var appendOption = true;
-                if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
-                    for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) {
-                        if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) {
-                            appendOption = false;
-                            break;
-                        }
-                    }
-                }
-                if (appendOption) {
-                    selectElement.append(new Option(
-                        editorConfiguration['selectOptions'][i]['label'],
-                        editorConfiguration['selectOptions'][i]['value']
-                    ));
-                    if (editorConfiguration['selectOptions'][i]['value'] !== '') {
-                        removeSelectElement = false;
-                    }
-                }
-            }
+        $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
+
+        selectElement.append(option);
+      }
+
+      selectElement.on('change', function() {
+        var selectValues = [];
+        $('option:selected', $(this)).each(function(i) {
+          selectValues.push($(this).data('value'));
+        });
+
+        getCurrentlySelectedFormElement().set(propertyPath, selectValues);
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1489528242
+     * @throws 1489528243
+     * @throws 1489528244
+     * @throws 1489528245
+     * @throws 1489528246
+     * @throws 1489528247
+     */
+    function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement,
+        viewportButtonTemplate;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1489528242
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1489528243
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1489528244
+      );
+      assert(
+        'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']),
+        'Invalid configurationOptions "viewPorts"',
+        1489528245
+      );
+      assert(
+        !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']),
+        'Invalid configurationOptions "numbersOfColumnsToUse"',
+        1489528246
+      );
+      assert(
+        !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']),
+        'Invalid configuration "selectOptions"',
+        1489528247
+      );
+
+      if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) {
+        editorHtml.remove();
+        return;
+      }
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+
+
+      viewportButtonTemplate = $(getHelper()
+        .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
+        .clone();
+
+      $(getHelper()
+        .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
+        .remove();
+
+      numbersOfColumnsTemplate = getHelper()
+        .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
+        .clone();
+
+      getHelper()
+        .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
+        .remove();
+
+      editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml);
+
+      initNumbersOfColumnsField = function(element) {
+        var numbersOfColumnsTemplateClone, propertyPath;
+
+        getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
+          .off()
+          .empty()
+          .remove();
+
+        numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
+        _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
+
+        $('input', numbersOfColumnsTemplateClone).focus();
+
+        getHelper()
+          .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone)
+          .append(
+            editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']
+              .replace('{@viewPortLabel}', element.data('viewPortLabel'))
+          );
+
+        getHelper()
+          .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone)
+          .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']);
+
+        propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']
+          .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier'));
+
+        getHelper()
+          .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone)
+          .val(getCurrentlySelectedFormElement().get(propertyPath));
+
+        getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() {
+          var that = $(this);
+          if (!$.isNumeric(that.val())) {
+            that.val('');
+          } else {
+            getCurrentlySelectedFormElement().set(propertyPath, that.val());
+          }
+        });
+      };
+
+      for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) {
+        var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier,
+          viewPortLabel;
+
+        viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier'];
+        viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label'];
+
+        viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true);
+        viewportButtonTemplateClone.text(viewPortLabel);
+        viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier);
+        viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel);
+        editorControlsWrapper.append(viewportButtonTemplateClone);
+
+        if (i === (len - 1)) {
+          numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
+          _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
+          initNumbersOfColumnsField(viewportButtonTemplateClone);
+          viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active'));
+        }
 
-            if (removeSelectElement) {
-                selectElement.off().empty().remove();
+        $('button', editorControlsWrapper).on('click', function() {
+          var that = $(this);
+
+          $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active'));
+          that.addClass(getHelper().getDomElementClassName('active'));
+
+          initNumbersOfColumnsField(that);
+        });
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475419226
+     * @throws 1475419227
+     * @throws 1475419228
+     * @throws 1475419229
+     * @throws 1475419230
+     * @throws 1475419231
+     * @throws 1475419232
+     */
+    function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix,
+        rowItemTemplate, setData;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475419226
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475419227
+      );
+      assert(
+        'boolean' === $.type(editorConfiguration['enableAddRow']),
+        'Invalid configuration "enableAddRow"',
+        1475419228
+      );
+      assert(
+        'boolean' === $.type(editorConfiguration['enableDeleteRow']),
+        'Invalid configuration "enableDeleteRow"',
+        1475419230
+      );
+      assert(
+        'boolean' === $.type(editorConfiguration['isSortable']),
+        'Invalid configuration "isSortable"',
+        1475419229
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1475419231
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475419232
+      );
+
+      getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
+      propertyPathPrefix = getFormEditorApp().buildPropertyPath(
+        undefined,
+        collectionElementIdentifier,
+        collectionName,
+        undefined,
+        true
+      );
+      if (getUtility().isNonEmptyString(propertyPathPrefix)) {
+        propertyPathPrefix = propertyPathPrefix + '.';
+      }
+
+      if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) {
+        multiSelection = false;
+      } else {
+        multiSelection = !!editorConfiguration['multiSelection'];
+      }
+
+      rowItemTemplate = $(
+        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
+        $(editorHtml)
+      ).clone();
+      $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove();
+
+      if (!!editorConfiguration['enableDeleteRow']) {
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'),
+          $(rowItemTemplate)
+        ).on('click', function() {
+          if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) {
+            $(this)
+              .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
+              .off()
+              .empty()
+              .remove();
+
+            _setPropertyGridData(
+              $(editorHtml),
+              multiSelection,
+              editorConfiguration['propertyPath'],
+              propertyPathPrefix
+            );
+          } else {
+            Notification.error(
+              editorConfiguration['removeLastAvailableRowFlashMessageTitle'],
+              editorConfiguration['removeLastAvailableRowFlashMessageMessage'],
+              2
+            );
+          }
+        });
+      } else {
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate))
+          .parent()
+          .off()
+          .empty();
+      }
+
+      if (!!editorConfiguration['isSortable']) {
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
+          .addClass(getHelper().getDomElementClassName('sortable'))
+          .sortable({
+            revert: 'true',
+            items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
+            update: function(e, o) {
+              _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
             }
+          });
+      } else {
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate))
+          .parent()
+          .off()
+          .empty();
+      }
+
+      $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'),
+        $(rowItemTemplate)
+      ).on('change', function() {
+        if (!multiSelection) {
+          $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml))
+            .not($(this))
+            .prop('checked', false);
+        }
+        _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' +
+        getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'),
+        $(rowItemTemplate)
+      ).on('keyup paste', function() {
+        _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'),
+        $(rowItemTemplate)
+      ).on('focusout', function() {
+        if ('' === $(this)
+            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
+            .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
+            .val()
+        ) {
+          $(this)
+            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
+            .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
+            .val($(this).val());
+        }
+      });
+
+      if (!!editorConfiguration['enableAddRow']) {
+        addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone();
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
+
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() {
+          $(this)
+            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'))
+            .before($(rowItemTemplate).clone(true, true));
+        });
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
+          .prepend($(addRowTemplate).clone(true, true));
+      } else {
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
+      }
+
+      defaultValue = {};
+      if (multiSelection) {
+        if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
+          defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue');
+        }
+      } else {
+        if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
+          defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')};
+        }
+      }
+      propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {};
+
+      setData = function(label, value) {
+        var isPreselected, newRowTemplate;
+
+        isPreselected = false;
+        newRowTemplate = $(rowItemTemplate).clone(true, true);
+
+        for (var defaultValueKey in defaultValue) {
+          if (!defaultValue.hasOwnProperty(defaultValueKey)) {
+            continue;
+          }
+          if (defaultValue[defaultValueKey] === value) {
+            isPreselected = true;
+            break;
+          }
+        }
 
-            selectElement.on('change', function() {
-                if ($(this).val() !== '') {
-                    var value = $(this).val();
-                    $('option[value="' + value + '"]', $(this)).remove();
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label);
+        $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value);
+        if (isPreselected) {
+          $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate))
+            .prop('checked', true);
+        }
 
-                    getFormEditorApp().getPublisherSubscriber().publish(
-                        'view/inspector/collectionElement/new/selected',
-                        [value, collectionName]
-                    );
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475421525
-         * @throws 1475421526
-         * @throws 1475421527
-         * @throws 1475421528
-         */
-        function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525);
-            assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526);
+        if (!!editorConfiguration['enableAddRow']) {
+          $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml))
+            .before($(newRowTemplate));
+        } else {
+          $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
+            .prepend($(newRowTemplate));
+        }
+      };
+
+      if ('object' === $.type(propertyData)) {
+        for (var propertyDataKey in propertyData) {
+          if (!propertyData.hasOwnProperty(propertyDataKey)) {
+            continue;
+          }
+          setData(propertyData[propertyDataKey], propertyDataKey);
+        }
+      } else if ('array' === $.type(propertyData)) {
+        for (var propertyDataKey in propertyData) {
+          if (!propertyData.hasOwnProperty(propertyDataKey)) {
+            continue;
+          }
+          if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) {
+            setData(propertyData[propertyDataKey], propertyDataKey);
+          } else {
+            setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']);
+          }
+        }
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @publish view/inspector/collectionElement/new/selected
+     * @publish view/inspector/removeCollectionElement/perform
+     * @throws 1475417093
+     * @throws 1475417094
+     * @throws 1475417095
+     * @throws 1475417096
+     */
+    function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyPath, propertyValue, validatorIdentifier;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475417093
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475417094
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']),
+        'Invalid configuration "validatorIdentifier"',
+        1475417095
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475417096
+      );
+
+      validatorIdentifier = editorConfiguration['validatorIdentifier'];
+      getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
+
+      if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) {
+        propertyPath = getFormEditorApp()
+          .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
+      }
+      if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) {
+        propertyValue = editorConfiguration['propertyValue'];
+      } else {
+        propertyValue = '';
+      }
+
+      if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) {
+        $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
+        if (getUtility().isNonEmptyString(propertyPath)) {
+          getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
+        }
+      }
+
+      $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
+        if ($(this).is(":checked")) {
+          getPublisherSubscriber().publish(
+            'view/inspector/collectionElement/new/selected',
+            [validatorIdentifier, 'validators']
+          );
+
+          if (getUtility().isNonEmptyString(propertyPath)) {
+            getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
+          }
+        } else {
+          getPublisherSubscriber().publish(
+            'view/inspector/removeCollectionElement/perform',
+            [validatorIdentifier, 'validators']
+          );
+          if (getUtility().isNonEmptyString(propertyPath)) {
+            getCurrentlySelectedFormElement().unset(propertyPath);
+          }
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1476218671
+     * @throws 1476218672
+     * @throws 1476218673
+     * @throws 1476218674
+     */
+    function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyData, propertyPath;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1476218671
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1476218672
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1476218673
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1476218674
+      );
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+
+      propertyPath = getFormEditorApp()
+        .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+
+      if (
+        ('boolean' === $.type(propertyData) && propertyData)
+        || propertyData === 'true'
+        || propertyData === 1
+        || propertyData === "1"
+      ) {
+        $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
+      }
+
+      $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
+        if ($(this).is(":checked")) {
+          getCurrentlySelectedFormElement().set(propertyPath, true);
+        } else {
+          getCurrentlySelectedFormElement().set(propertyPath, false);
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475412567
+     * @throws 1475412568
+     * @throws 1475416098
+     * @throws 1475416099
+     */
+    function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var propertyPath, propertyData;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1475412567
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1475412568
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1475416098
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1475416099
+      );
+
+      propertyPath = getFormEditorApp()
+        .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
+
+      if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .text(editorConfiguration['fieldExplanationText']);
+      } else {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .remove();
+      }
+
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+      $('textarea', $(editorHtml)).val(propertyData);
+
+      $('textarea', $(editorHtml)).on('keyup paste', function() {
+        getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1477300587
+     * @throws 1477300588
+     * @throws 1477300589
+     * @throws 1477300590
+     * @throws 1477318981
+     * @throws 1477319859
+     */
+    function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      var iconType, propertyPath, propertyData;
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1477300587
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1477300588
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['label']),
+        'Invalid configuration "label"',
+        1477300589
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['buttonLabel']),
+        'Invalid configuration "buttonLabel"',
+        1477318981
+      );
+      assert(
+        getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
+        'Invalid configuration "propertyPath"',
+        1477300590
+      );
+      assert(
+        'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'],
+        'Invalid configuration "browsableType"',
+        1477319859
+      );
+
+      getHelper()
+        .getTemplatePropertyDomElement('label', editorHtml)
+        .append(editorConfiguration['label']);
+      getHelper()
+        .getTemplatePropertyDomElement('buttonLabel', editorHtml)
+        .append(editorConfiguration['buttonLabel']);
+
+      if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .text(editorConfiguration['fieldExplanationText']);
+      } else {
+        getHelper()
+          .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
+          .remove();
+      }
+
+      $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']);
+
+      iconType = ('tt_content' === editorConfiguration['browsableType'])
+        ? getHelper().getDomElementDataAttributeValue('iconTtContent')
+        : getHelper().getDomElementDataAttributeValue('iconPage');
+      Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) {
+        getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon));
+      });
+
+      getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() {
+        var insertTarget, randomIdentifier;
+
+        randomIdentifier = Math.floor((Math.random() * 100000) + 1);
+        insertTarget = $(this)
+          .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'))
+          .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey'));
+
+        insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier);
+        _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']);
+      });
+
+      propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
+      propertyData = getCurrentlySelectedFormElement().get(propertyPath);
+
+      _validateCollectionElement(propertyPath, editorHtml);
+      getHelper()
+        .getTemplatePropertyDomElement('propertyPath', editorHtml)
+        .val(propertyData);
+
+      getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
+        getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
+        _validateCollectionElement(propertyPath, editorHtml);
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @return void
+     * @throws 1475412563
+     * @throws 1475412564
+     */
+    function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
+      assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563);
+      assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564);
+
+      if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
+
+        $('button', $(editorHtml))
+          .addClass(
+            getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' +
+            getHelper().getDomElementClassName('buttonFormEditor')
+          );
+      } else {
+        $('button', $(editorHtml)).addClass(
+          getHelper().getDomElementClassName('buttonCollectionElementRemove')
+        );
+      }
+
+      $('button', $(editorHtml)).on('click', function(e) {
+        if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
+          getViewModel().showRemoveFormElementModal();
+        } else {
+          getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName);
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object editorConfiguration
+     * @param object editorHtml
+     * @param string propertyPath
+     * @return void
+     * @throws 1484574704
+     * @throws 1484574705
+     * @throws 1484574706
+     */
+    function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) {
+      var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper,
+        formElementSelectorSplitButtonListContainer, itemTemplate;
+
+      assert(
+        'object' === $.type(editorConfiguration),
+        'Invalid parameter "editorConfiguration"',
+        1484574704
+      );
+      assert(
+        'object' === $.type(editorHtml),
+        'Invalid parameter "editorHtml"',
+        1484574705
+      );
+      assert(
+        getUtility().isNonEmptyString(propertyPath),
+        'Invalid parameter "propertyPath"',
+        1484574706
+      );
+
+      formElementSelectorControlsWrapper = $(
+        getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml
+      );
+
+      if (editorConfiguration['enableFormelementSelectionButton'] === true) {
+        if (formElementSelectorControlsWrapper.length === 0) {
+          return;
+        }
 
+        formElementSelectorSplitButtonListContainer = $(
+          getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml
+        );
+
+        formElementSelectorSplitButtonListContainer.off().empty();
+        nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements();
+
+        if (nonCompositeNonToplevelFormElements.length === 0) {
+          Icons.getIcon(
+            getHelper().getDomElementDataAttributeValue('iconNotAvailable'),
+            Icons.sizes.small,
+            null,
+            Icons.states.default
+          ).done(function(icon) {
+            itemTemplate = $('<li data-no-sorting>'
+              + '<a href="#"></a>'
+              + '</li>');
+
+            itemTemplate
+              .append($(icon))
+              .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements'));
+            formElementSelectorSplitButtonListContainer.append(itemTemplate);
+          });
+        } else {
+          for (var i = 0, len = nonCompositeNonToplevelFormElements.length; i < len; ++i) {
+            var nonCompositeNonToplevelFormElement;
+
+            nonCompositeNonToplevelFormElement = nonCompositeNonToplevelFormElements[i];
             Icons.getIcon(
-                getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'),
-                Icons.sizes.small,
-                null,
-                Icons.states.default
+              getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'),
+              Icons.sizes.small,
+              null,
+              Icons.states.default
             ).done(function(icon) {
-                getHelper().getTemplatePropertyDomElement('header-label', editorHtml)
-                    .append($(icon).addClass(getHelper().getDomElementClassName('icon')))
-                    .append(buildTitleByFormElement());
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475421257
-         * @throws 1475421258
-         * @throws 1475421259
-         */
-        function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var collectionElementConfiguration, setData;
-
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475421258
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475421257
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475421259
-            );
-
-            setData = function(icon) {
-                getHelper()
-                    .getTemplatePropertyDomElement('header-label', editorHtml)
-                    .prepend($(icon));
-
-                Icons.getIcon(
-                    getHelper().getDomElementDataAttributeValue('collapse'),
-                    Icons.sizes.small,
-                    null,
-                    Icons.states.default,
-                    Icons.markupIdentifiers.inline
-                ).done(function(icon) {
-                    var iconWrap;
-                    iconWrap = $('<a></a>')
-                        .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true))
-                        .attr('data-toggle', 'collapse')
-                        .attr('aria-expanded', 'true')
-                        .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier))
-                        .addClass('collapsed')
-                        .append($(icon));
-
-                    getHelper()
-                        .getTemplatePropertyDomElement('header-label', editorHtml)
-                        .prepend(iconWrap);
-                });
-            };
-
-            collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier);
-            if (collectionName === 'validators') {
-                Icons.getIcon(
-                    collectionElementConfiguration['iconIdentifier'],
-                    Icons.sizes.small,
-                    null,
-                    Icons.states.default
-                ).done(function(icon) {
-                    setData(icon);
-                });
-            } else {
-                Icons.getIcon(
-                    collectionElementConfiguration['iconIdentifier'],
-                    Icons.sizes.small,
-                    null,
-                    Icons.states.default
-                ).done(function(icon) {
-                    setData(icon);
-                });
-            }
-
-            if (editorConfiguration['label']) {
-                getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475421053
-         * @throws 1475421054
-         * @throws 1475421055
-         * @throws 1475421056
-         */
-        function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyData, propertyPath;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475421053
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475421054
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475421055
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1475421056
-            );
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-            if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .text(editorConfiguration['fieldExplanationText']);
-            } else {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .remove();
-            }
-
-            propertyPath = getFormEditorApp().buildPropertyPath(
-                editorConfiguration['propertyPath'],
-                collectionElementIdentifier,
-                collectionName
-            );
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-            _validateCollectionElement(propertyPath, editorHtml);
+              itemTemplate = $('<li data-no-sorting>'
+                + '<a href="#" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">'
+                + '</a>'
+                + '</li>');
 
-            getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
+              $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate)
+                .append($(icon))
+                .append(' ' + nonCompositeNonToplevelFormElement.get('label'));
 
-            renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath);
+              $('a', itemTemplate).on('click', function() {
+                var propertyData;
 
-            getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
-                if (
-                    !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
-                    && !getUtility().isNonEmptyString($(this).val())
-                ) {
-                    getCurrentlySelectedFormElement().unset(propertyPath);
-                } else {
-                    getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
-                }
-                _validateCollectionElement(propertyPath, editorHtml);
-                if (
-                    !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths'])
-                    && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths'])
-                ) {
-                    for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) {
-                        if (
-                            !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
-                            && !getUtility().isNonEmptyString($(this).val())
-                        ) {
-                            getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]);
-                        } else {
-                            getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val());
-                        }
-                    }
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475421048
-         * @throws 1475421049
-         * @throws 1475421050
-         * @throws 1475421051
-         * @throws 1475421052
-         */
-        function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyData, propertyPath, selectElement;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475421048
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475421049
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475421050
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1475421051
-            );
-            assert(
-                'array' === $.type(editorConfiguration['selectOptions']),
-                'Invalid configuration "selectOptions"',
-                1475421052
-            );
+                propertyData = getCurrentlySelectedFormElement().get(propertyPath);
 
-            propertyPath = getFormEditorApp().buildPropertyPath(
-                editorConfiguration['propertyPath'],
-                collectionElementIdentifier,
-                collectionName
-            );
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-
-            selectElement = getHelper()
-                .getTemplatePropertyDomElement('selectOptions', editorHtml);
-
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-            for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) {
-                var option;
-
-                if (editorConfiguration['selectOptions'][i]['value'] === propertyData) {
-                    option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
+                if (propertyData.length === 0) {
+                  propertyData = '{' + $(this).attr('data-formelement-identifier') + '}';
                 } else {
-                    option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
-                }
-                $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
-                selectElement.append(option);
-            }
-
-            selectElement.on('change', function() {
-                getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value'));
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1485712399
-         * @throws 1485712400
-         * @throws 1485712401
-         * @throws 1485712402
-         * @throws 1485712403
-         */
-        function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyData, propertyPath, selectElement;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1485712399
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1485712400
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1485712401
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1485712402
-            );
-            assert(
-                'array' === $.type(editorConfiguration['selectOptions']),
-                'Invalid configuration "selectOptions"',
-                1485712403
-            );
-
-            propertyPath = getFormEditorApp().buildPropertyPath(
-                editorConfiguration['propertyPath'],
-                collectionElementIdentifier,
-                collectionName
-            );
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-
-            selectElement = getHelper()
-                .getTemplatePropertyDomElement('selectOptions', editorHtml);
-
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-            for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
-                var option, value;
-
-                option = null;
-                for (var propertyDataKey in propertyData) {
-                    if (!propertyData.hasOwnProperty(propertyDataKey)) {
-                        continue;
-                    }
-                    if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) {
-                        option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
-                        break;
-                    }
+                  propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}';
                 }
 
-                if (!option) {
-                    option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
-                }
-
-                $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
-
-                selectElement.append(option);
-            }
-
-            selectElement.on('change', function() {
-                var selectValues = [];
-                $('option:selected', $(this)).each(function(i) {
-                    selectValues.push($(this).data('value'));
-                });
-
-                getCurrentlySelectedFormElement().set(propertyPath, selectValues);
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1489528242
-         * @throws 1489528243
-         * @throws 1489528244
-         * @throws 1489528245
-         * @throws 1489528246
-         * @throws 1489528247
-         */
-        function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement, viewportButtonTemplate;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1489528242
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1489528243
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1489528244
-            );
-            assert(
-                'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']),
-                'Invalid configurationOptions "viewPorts"',
-                1489528245
-            );
-            assert(
-                !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']),
-                'Invalid configurationOptions "numbersOfColumnsToUse"',
-                1489528246
-            );
-            assert(
-                !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']),
-                'Invalid configuration "selectOptions"',
-                1489528247
-            );
-
-            if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) {
-                editorHtml.remove();
-                return;
-            }
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-
-
-            viewportButtonTemplate = $(getHelper()
-                .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
-                .clone();
-
-            $(getHelper()
-                .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
-                .remove();
-
-            numbersOfColumnsTemplate = getHelper()
-                .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
-                .clone();
-
-            getHelper()
-                .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
-                .remove();
-
-            editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml);
-
-            initNumbersOfColumnsField = function(element) {
-                var numbersOfColumnsTemplateClone, propertyPath;
-
-                getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
-                    .off()
-                    .empty()
-                    .remove();
-
-                numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
-                _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
-
-                $('input', numbersOfColumnsTemplateClone).focus();
-
-                getHelper()
-                    .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone)
-                    .append(
-                        editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']
-                            .replace('{@viewPortLabel}', element.data('viewPortLabel'))
-                    );
-
-                getHelper()
-                    .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone)
-                    .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']);
-
-                propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']
-                    .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier'));
-
-                getHelper()
-                    .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone)
-                    .val(getCurrentlySelectedFormElement().get(propertyPath));
-
-                getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() {
-                    var that = $(this);
-                    if (!$.isNumeric(that.val())) {
-                        that.val('');
-                    } else {
-                        getCurrentlySelectedFormElement().set(propertyPath, that.val());
-                    }
-                });
-            };
-
-            for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) {
-                var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier, viewPortLabel;
-
-                viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier'];
-                viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label'];
-
-                viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true);
-                viewportButtonTemplateClone.text(viewPortLabel);
-                viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier);
-                viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel);
-                editorControlsWrapper.append(viewportButtonTemplateClone);
-
-                if (i === (len - 1)) {
-                    numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
-                    _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
-                    initNumbersOfColumnsField(viewportButtonTemplateClone);
-                    viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active'));
-                }
-
-                $('button', editorControlsWrapper).on('click', function() {
-                    var that = $(this);
-
-                    $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active'));
-                    that.addClass(getHelper().getDomElementClassName('active'));
-
-                    initNumbersOfColumnsField(that);
-                });
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475419226
-         * @throws 1475419227
-         * @throws 1475419228
-         * @throws 1475419229
-         * @throws 1475419230
-         * @throws 1475419231
-         * @throws 1475419232
-         */
-        function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix, rowItemTemplate, setData;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475419226
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475419227
-            );
-            assert(
-                'boolean' === $.type(editorConfiguration['enableAddRow']),
-                'Invalid configuration "enableAddRow"',
-                1475419228
-            );
-            assert(
-                'boolean' === $.type(editorConfiguration['enableDeleteRow']),
-                'Invalid configuration "enableDeleteRow"',
-                1475419230
-            );
-            assert(
-                'boolean' === $.type(editorConfiguration['isSortable']),
-                'Invalid configuration "isSortable"',
-                1475419229
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1475419231
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475419232
-            );
-
-            getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
-            propertyPathPrefix = getFormEditorApp().buildPropertyPath(
-                undefined,
-                collectionElementIdentifier,
-                collectionName,
-                undefined,
-                true
-            );
-            if (getUtility().isNonEmptyString(propertyPathPrefix)) {
-                propertyPathPrefix = propertyPathPrefix + '.';
-            }
-
-            if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) {
-                multiSelection = false;
-            } else {
-                multiSelection = !!editorConfiguration['multiSelection'];
-            }
-
-            rowItemTemplate = $(
-                getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
-                $(editorHtml)
-            ).clone();
-            $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove();
-
-            if (!!editorConfiguration['enableDeleteRow']) {
-                $(  getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'),
-                    $(rowItemTemplate)
-                ).on('click', function() {
-                    if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) {
-                        $(this)
-                            .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
-                            .off()
-                            .empty()
-                            .remove();
-
-                        _setPropertyGridData(
-                            $(editorHtml),
-                            multiSelection,
-                            editorConfiguration['propertyPath'],
-                            propertyPathPrefix
-                        );
-                    } else {
-                        Notification.error(
-                            editorConfiguration['removeLastAvailableRowFlashMessageTitle'],
-                            editorConfiguration['removeLastAvailableRowFlashMessageMessage'],
-                            2
-                        );
-                    }
-                });
-            } else {
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate))
-                    .parent()
-                    .off()
-                    .empty();
-            }
-
-            if (!!editorConfiguration['isSortable']) {
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
-                    .addClass(getHelper().getDomElementClassName('sortable'))
-                    .sortable({
-                        revert: 'true',
-                        items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
-                        update: function(e, o) {
-                            _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
-                        }
-                    });
-            } else {
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate))
-                    .parent()
-                    .off()
-                    .empty();
-            }
-
-            $(  getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'),
-                $(rowItemTemplate)
-            ).on('change', function() {
-                if (!multiSelection) {
-                    $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml))
-                        .not($(this))
-                        .prop('checked', false);
-                }
-                _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
-            });
-
-            $(  getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' +
-                getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'),
-                $(rowItemTemplate)
-            ).on('keyup paste', function() {
-                _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
-            });
-
-            $(  getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'),
-                $(rowItemTemplate)
-            ).on('focusout', function() {
-                if ('' === $(this)
-                                .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
-                                .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
-                                .val()
-                ) {
-                    $(this)
-                        .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
-                        .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
-                        .val($(this).val());
-                }
-            });
-
-            if (!!editorConfiguration['enableAddRow']) {
-                addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone();
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
-
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() {
-                    $(this)
-                        .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'))
-                        .before($(rowItemTemplate).clone(true, true));
-                });
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
-                    .prepend($(addRowTemplate).clone(true, true));
-            } else {
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
-            }
-
-            defaultValue = {};
-            if (multiSelection) {
-                if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
-                    defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue');
-                }
-            } else {
-                if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
-                    defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')};
-                }
-            }
-            propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {};
-
-            setData = function(label, value) {
-                var isPreselected, newRowTemplate;
-
-                isPreselected = false;
-                newRowTemplate = $(rowItemTemplate).clone(true, true);
-
-                for (var defaultValueKey in defaultValue) {
-                    if (!defaultValue.hasOwnProperty(defaultValueKey)) {
-                        continue;
-                    }
-                    if (defaultValue[defaultValueKey] === value) {
-                        isPreselected = true;
-                        break;
-                    }
-                }
-
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label);
-                $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value);
-                if (isPreselected) {
-                    $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate))
-                        .prop('checked', true);
-                }
-
-                if (!!editorConfiguration['enableAddRow']) {
-                    $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml))
-                        .before($(newRowTemplate));
-                } else {
-                    $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
-                        .prepend($(newRowTemplate));
-                }
-            };
-
-            if ('object' === $.type(propertyData)) {
-                for (var propertyDataKey in propertyData) {
-                    if (!propertyData.hasOwnProperty(propertyDataKey)) {
-                        continue;
-                    }
-                    setData(propertyData[propertyDataKey], propertyDataKey);
-                }
-            } else if ('array' === $.type(propertyData)) {
-                for (var propertyDataKey in propertyData) {
-                    if (!propertyData.hasOwnProperty(propertyDataKey)) {
-                        continue;
-                    }
-                    if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) {
-                        setData(propertyData[propertyDataKey], propertyDataKey);
-                    } else {
-                        setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']);
-                    }
-                }
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @publish view/inspector/collectionElement/new/selected
-         * @publish view/inspector/removeCollectionElement/perform
-         * @throws 1475417093
-         * @throws 1475417094
-         * @throws 1475417095
-         * @throws 1475417096
-         */
-        function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyPath, propertyValue, validatorIdentifier;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475417093
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475417094
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']),
-                'Invalid configuration "validatorIdentifier"',
-                1475417095
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475417096
-            );
-
-            validatorIdentifier = editorConfiguration['validatorIdentifier'];
-            getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
-
-            if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) {
-                propertyPath = getFormEditorApp()
-                    .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
-            }
-            if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) {
-                propertyValue = editorConfiguration['propertyValue'];
-            } else {
-                propertyValue = '';
-            }
-
-            if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) {
-                $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
-                if (getUtility().isNonEmptyString(propertyPath)) {
-                    getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
-                }
-            }
-
-            $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
-                if ($(this).is(":checked")) {
-                    getPublisherSubscriber().publish(
-                        'view/inspector/collectionElement/new/selected',
-                        [validatorIdentifier, 'validators']
-                    );
-
-                    if (getUtility().isNonEmptyString(propertyPath)) {
-                        getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
-                    }
-                } else {
-                    getPublisherSubscriber().publish(
-                        'view/inspector/removeCollectionElement/perform',
-                        [validatorIdentifier, 'validators']
-                    );
-                    if (getUtility().isNonEmptyString(propertyPath)) {
-                        getCurrentlySelectedFormElement().unset(propertyPath);
-                    }
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1476218671
-         * @throws 1476218672
-         * @throws 1476218673
-         * @throws 1476218674
-         */
-        function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyData, propertyPath;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1476218671
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1476218672
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1476218673
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1476218674
-            );
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-
-            propertyPath = getFormEditorApp()
-                .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-            if (
-                ('boolean' === $.type(propertyData) && propertyData)
-                || propertyData === 'true'
-                || propertyData === 1
-                || propertyData === "1"
-            ) {
-                $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
-            }
-
-            $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
-                if ($(this).is(":checked")) {
-                    getCurrentlySelectedFormElement().set(propertyPath, true);
-                } else {
-                    getCurrentlySelectedFormElement().set(propertyPath, false);
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475412567
-         * @throws 1475412568
-         * @throws 1475416098
-         * @throws 1475416099
-         */
-        function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var propertyPath, propertyData;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1475412567
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1475412568
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1475416098
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1475416099
-            );
-
-            propertyPath = getFormEditorApp()
-                .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
-
-            if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .text(editorConfiguration['fieldExplanationText']);
-            } else {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .remove();
-            }
-
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-            $('textarea', $(editorHtml)).val(propertyData);
-
-            $('textarea', $(editorHtml)).on('keyup paste', function() {
-                getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1477300587
-         * @throws 1477300588
-         * @throws 1477300589
-         * @throws 1477300590
-         * @throws 1477318981
-         * @throws 1477319859
-         */
-        function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            var iconType, propertyPath, propertyData;
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1477300587
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1477300588
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['label']),
-                'Invalid configuration "label"',
-                1477300589
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['buttonLabel']),
-                'Invalid configuration "buttonLabel"',
-                1477318981
-            );
-            assert(
-                getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
-                'Invalid configuration "propertyPath"',
-                1477300590
-            );
-            assert(
-                'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'],
-                'Invalid configuration "browsableType"',
-                1477319859
-            );
-
-            getHelper()
-                .getTemplatePropertyDomElement('label', editorHtml)
-                .append(editorConfiguration['label']);
-            getHelper()
-                .getTemplatePropertyDomElement('buttonLabel', editorHtml)
-                .append(editorConfiguration['buttonLabel']);
-
-            if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .text(editorConfiguration['fieldExplanationText']);
-            } else {
-                getHelper()
-                    .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
-                    .remove();
-            }
-
-            $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']);
-
-            iconType = ('tt_content' === editorConfiguration['browsableType'])
-                ? getHelper().getDomElementDataAttributeValue('iconTtContent')
-                : getHelper().getDomElementDataAttributeValue('iconPage');
-            Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) {
-                getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon));
-            });
-
-            getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() {
-                var insertTarget, randomIdentifier;
-
-                randomIdentifier = Math.floor((Math.random() * 100000) + 1);
-                insertTarget = $(this)
-                    .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'))
-                    .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey'));
-
-                insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier);
-                _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']);
-            });
-
-            propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
-            propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-            _validateCollectionElement(propertyPath, editorHtml);
-            getHelper()
-                .getTemplatePropertyDomElement('propertyPath', editorHtml)
-                .val(propertyData);
-
-            getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
-                getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
+                getCurrentlySelectedFormElement().set(propertyPath, propertyData);
+                getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
                 _validateCollectionElement(propertyPath, editorHtml);
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @return void
-         * @throws 1475412563
-         * @throws 1475412564
-         */
-        function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
-            assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563);
-            assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564);
-
-            if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
-
-                $('button', $(editorHtml))
-                    .addClass(
-                        getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' +
-                        getHelper().getDomElementClassName('buttonFormEditor')
-                    );
-            } else {
-                $('button', $(editorHtml)).addClass(
-                    getHelper().getDomElementClassName('buttonCollectionElementRemove')
-                );
-            }
+              });
 
-            $('button', $(editorHtml)).on('click', function(e) {
-                if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
-                    getViewModel().showRemoveFormElementModal();
-                } else {
-                    getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName);
-                }
+              formElementSelectorSplitButtonListContainer.append(itemTemplate);
             });
-        };
-
-        /**
-         * @public
-         *
-         * @param object editorConfiguration
-         * @param object editorHtml
-         * @param string propertyPath
-         * @return void
-         * @throws 1484574704
-         * @throws 1484574705
-         * @throws 1484574706
-         */
-        function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) {
-            var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper, formElementSelectorSplitButtonListContainer, itemTemplate;
-
-            assert(
-                'object' === $.type(editorConfiguration),
-                'Invalid parameter "editorConfiguration"',
-                1484574704
-            );
-            assert(
-                'object' === $.type(editorHtml),
-                'Invalid parameter "editorHtml"',
-                1484574705
-            );
-            assert(
-                getUtility().isNonEmptyString(propertyPath),
-                'Invalid parameter "propertyPath"',
-                1484574706
-            );
-
-            formElementSelectorControlsWrapper = $(
-                getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml
-            );
-
-            if (editorConfiguration['enableFormelementSelectionButton'] === true) {
-                if (formElementSelectorControlsWrapper.length === 0) {
-                    return;
-                }
-
-                formElementSelectorSplitButtonListContainer = $(
-                    getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml
-                );
-
-                formElementSelectorSplitButtonListContainer.off().empty();
-                nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements();
-
-                if (nonCompositeNonToplevelFormElements.length === 0) {
-                    Icons.getIcon(
-                        getHelper().getDomElementDataAttributeValue('iconNotAvailable'),
-                        Icons.sizes.small,
-                        null,
-                        Icons.states.default
-                    ).done(function(icon) {
-                        itemTemplate = $('<li data-no-sorting>'
-                                         +   '<a href="#"></a>'
-                                     +   '</li>');
-
-                        itemTemplate
-                            .append($(icon))
-                            .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements'));
-                        formElementSelectorSplitButtonListContainer.append(itemTemplate);
-                    });
-                } else {
-                    for (var i = 0, len = nonCompositeNonToplevelFormElements.length; i < len; ++i) {
-                        var nonCompositeNonToplevelFormElement;
-
-                        nonCompositeNonToplevelFormElement = nonCompositeNonToplevelFormElements[i];
-                        Icons.getIcon(
-                            getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'),
-                            Icons.sizes.small,
-                            null,
-                            Icons.states.default
-                        ).done(function(icon) {
-                            itemTemplate = $('<li data-no-sorting>'
-                                             +   '<a href="#" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">'
-                                             +   '</a>'
-                                         +   '</li>');
-
-                            $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate)
-                                .append($(icon))
-                                .append(' ' + nonCompositeNonToplevelFormElement.get('label'));
-
-                            $('a', itemTemplate).on('click', function() {
-                                var propertyData;
-
-                                propertyData = getCurrentlySelectedFormElement().get(propertyPath);
-
-                                if (propertyData.length === 0) {
-                                    propertyData = '{' + $(this).attr('data-formelement-identifier') + '}';
-                                } else {
-                                    propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}';
-                                }
-
-                                getCurrentlySelectedFormElement().set(propertyPath, propertyData);
-                                getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
-                                _validateCollectionElement(propertyPath, editorHtml);
-                            });
-
-                            formElementSelectorSplitButtonListContainer.append(itemTemplate);
-                        });
-                    }
-                }
-            } else {
-                $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml)
-                    .removeClass(getHelper().getDomElementClassName('inspectorInputGroup'));
-                formElementSelectorControlsWrapper.off().empty().remove();
-            }
+          }
         }
-
-        /**
-         * @public
-         *
-         * @param string content
-         * @return void
-         */
-        function setFormElementHeaderEditorContent(content) {
-            if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) {
-                content = buildTitleByFormElement();
-            }
-
-            $(getHelper()
-                .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement())
-                .html(content);
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         * @throws 1478967319
-         */
-        function buildTitleByFormElement(formElement) {
-            var label;
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319);
-
-            return $('<span></span>').text((formElement.get('label')
-                ? formElement.get('label')
-                : formElement.get('identifier')));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @return this
-         */
-        function bootstrap(formEditorApp, configuration) {
-            _formEditorApp = formEditorApp;
-            _configuration = $.extend(true, _defaultConfiguration, configuration || {});
-            _helperSetup();
-            return this;
-        };
-
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            bootstrap: bootstrap,
-            buildTitleByFormElement: buildTitleByFormElement,
-            getCollectionElementDomElement: getCollectionElementDomElement,
-            getFinishersContainerDomElement: getFinishersContainerDomElement,
-            getInspectorDomElement: getInspectorDomElement,
-            getValidatorsContainerDomElement: getValidatorsContainerDomElement,
-            renderCheckboxEditor: renderCheckboxEditor,
-            renderCollectionElementEditors: renderCollectionElementEditors,
-            renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor,
-            renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor,
-            renderEditors: renderEditors,
-            renderFormElementHeaderEditor: renderFormElementHeaderEditor,
-            renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition,
-            renderPropertyGridEditor: renderPropertyGridEditor,
-            renderRemoveElementEditor: renderRemoveElementEditor,
-            renderRequiredValidatorEditor: renderRequiredValidatorEditor,
-            renderSingleSelectEditor: renderSingleSelectEditor,
-            renderMultiSelectEditor: renderMultiSelectEditor,
-            renderTextareaEditor: renderTextareaEditor,
-            renderTextEditor: renderTextEditor,
-            renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor,
-            setFormElementHeaderEditorContent: setFormElementHeaderEditorContent
-        };
-    })($, Helper, Icons, Notification);
+      } else {
+        $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml)
+          .removeClass(getHelper().getDomElementClassName('inspectorInputGroup'));
+        formElementSelectorControlsWrapper.off().empty().remove();
+      }
+    }
+
+    /**
+     * @public
+     *
+     * @param string content
+     * @return void
+     */
+    function setFormElementHeaderEditorContent(content) {
+      if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) {
+        content = buildTitleByFormElement();
+      }
+
+      $(getHelper()
+        .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement())
+        .html(content);
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     * @throws 1478967319
+     */
+    function buildTitleByFormElement(formElement) {
+      var label;
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319);
+
+      return $('<span></span>').text((formElement.get('label')
+        ? formElement.get('label')
+        : formElement.get('identifier')));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @return this
+     */
+    function bootstrap(formEditorApp, configuration) {
+      _formEditorApp = formEditorApp;
+      _configuration = $.extend(true, _defaultConfiguration, configuration || {});
+      _helperSetup();
+      return this;
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap,
+      buildTitleByFormElement: buildTitleByFormElement,
+      getCollectionElementDomElement: getCollectionElementDomElement,
+      getFinishersContainerDomElement: getFinishersContainerDomElement,
+      getInspectorDomElement: getInspectorDomElement,
+      getValidatorsContainerDomElement: getValidatorsContainerDomElement,
+      renderCheckboxEditor: renderCheckboxEditor,
+      renderCollectionElementEditors: renderCollectionElementEditors,
+      renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor,
+      renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor,
+      renderEditors: renderEditors,
+      renderFormElementHeaderEditor: renderFormElementHeaderEditor,
+      renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition,
+      renderPropertyGridEditor: renderPropertyGridEditor,
+      renderRemoveElementEditor: renderRemoveElementEditor,
+      renderRequiredValidatorEditor: renderRequiredValidatorEditor,
+      renderSingleSelectEditor: renderSingleSelectEditor,
+      renderMultiSelectEditor: renderMultiSelectEditor,
+      renderTextareaEditor: renderTextareaEditor,
+      renderTextEditor: renderTextEditor,
+      renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor,
+      setFormElementHeaderEditorContent: setFormElementHeaderEditorContent
+    };
+  })($, Helper, Icons, Notification);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js
index 8a30e1068131..f698da186a96 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/Mediator.js
@@ -15,1077 +15,1077 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/Mediator
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper'
-        ], function($, Helper) {
-        'use strict';
-
-    return (function($, Helper) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _viewModel = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getViewModel() {
-            return _viewModel;
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(getViewModel().getConfiguration());
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getCurrentlySelectedFormElement() {
-            return getFormEditorApp().getCurrentlySelectedFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         */
-        function _subscribeEvents() {
-
-            /* *********************************************************
-             * Misc
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @return string
-             */
-            window.onbeforeunload = function(e) {
-                if (!getFormEditorApp().getUnsavedContent()) {
-                    return;
-                }
-                e = e || window.event;
-                if (e) {
-                    e.returnValue = getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage');
-                }
-                return getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle');
-            };
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/ready
-             */
-            getPublisherSubscriber().subscribe('view/ready', function(topic, args) {
-                getViewModel().onViewReadyBatch();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = applicationState
-             *              args[1] = stackPointer
-             *              args[2] = stackSize
-             * @return void
-             * @subscribe core/applicationState/add
-             */
-            getPublisherSubscriber().subscribe('core/applicationState/add', function(topic, args) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-                if (args[2] > 1 && args[1] <= args[2]) {
-                    getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-                } else {
-                    getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-                }
-            });
-
-            /* *********************************************************
-             * Ajax
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = html
-             * @return void
-             * @subscribe core/ajax/saveFormDefinition/success
-             */
-            getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/success', function(topic, args) {
-                getFormEditorApp().setUnsavedContent(false);
-                getViewModel().showSaveSuccessMessage();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = object
-             * @return void
-             * @subscribe core/ajax/saveFormDefinition/error
-             */
-            getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/error', function(topic, args) {
-                getViewModel().showSaveErrorMessage(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = html
-             *              args[1] = pageIndex
-             * @return void
-             * @subscribe core/ajax/renderFormDefinitionPage/success
-             */
-            getPublisherSubscriber().subscribe('core/ajax/renderFormDefinitionPage/success', function(topic, args) {
-                getViewModel().renderPreviewStageArea(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = jqXHR
-             *              args[1] = textStatus
-             *              args[2] = errorThrown
-             * @return void
-             * @subscribe core/ajax/saveFormDefinition/error
-             */
-            getPublisherSubscriber().subscribe('core/ajax/error', function(topic, args) {
-                if (args[0].status !== 0) {
-                    getViewModel().showErrorFlashMessage(args[1], args[2]);
-                    getViewModel().renderPreviewStageArea(args[0].responseText);
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe ajax/beforeSend
-             */
-            getPublisherSubscriber().subscribe('ajax/beforeSend', function(topic, args) {
-                getViewModel().showSaveButtonSpinnerIcon();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe ajax/complete
-             */
-            getPublisherSubscriber().subscribe('ajax/complete', function(topic, args) {
-                getViewModel().showSaveButtonSaveIcon();
-            });
-
-            /* *********************************************************
-             * Header
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/header/button/save/clicked
-             */
-            getPublisherSubscriber().subscribe('view/header/button/save/clicked', function(topic, args) {
-                if (getFormEditorApp().validationResultsHasErrors(getFormEditorApp().validateFormElementRecursive(getRootFormElement(), true))) {
-                    getViewModel().showValidationErrorsModal();
-                } else {
-                    getFormEditorApp().saveFormDefinition();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/header/formSettings/clicked
-             */
-            getPublisherSubscriber().subscribe('view/header/formSettings/clicked', function(topic, args) {
-                getViewModel().addStructureRootElementSelection();
-                getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement());
-                getViewModel().renderAbstractStageArea();
-                getViewModel().renewStructure();
-                getViewModel().renderPagination();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = targetEvent
-             * @return void
-             * @subscribe view/header/button/newPage/clicked
-             */
-            getPublisherSubscriber().subscribe('view/header/button/newPage/clicked', function(topic, args) {
-                if (getFormEditorApp().isRootFormElementSelected()) {
-                    getViewModel().selectPageBatch(0);
-                }
-                getViewModel().showInsertPagesModal(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/header/button/close/clicked
-             */
-            getPublisherSubscriber().subscribe('view/header/button/close/clicked', function(topic, args) {
-                getViewModel().showCloseConfirmationModal();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/undoButton/clicked
-             */
-            getPublisherSubscriber().subscribe('view/undoButton/clicked', function(topic, args) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-                getFormEditorApp().undoApplicationState();
-
-                if (getViewModel().getPreviewMode()) {
-                    getFormEditorApp().renderCurrentFormPage();
-                } else {
-                    getViewModel().renderAbstractStageArea();
-                }
-                getFormEditorApp().setUnsavedContent(true);
-
-                getViewModel().renewStructure();
-                getViewModel().renderPagination();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/redoButton/clicked
-             */
-            getPublisherSubscriber().subscribe('view/redoButton/clicked', function(topic, args) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-                getFormEditorApp().redoApplicationState();
-
-                if (getViewModel().getPreviewMode()) {
-                    getFormEditorApp().renderCurrentFormPage();
-                } else {
-                    getViewModel().renderAbstractStageArea();
-                }
-                getFormEditorApp().setUnsavedContent(true);
-
-                getViewModel().renewStructure();
-                getViewModel().renderPagination();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /* *********************************************************
-             * Stage
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementIdentifierPath
-             * @return void
-             * @subscribe view/stage/element/clicked
-             */
-            getPublisherSubscriber().subscribe('view/stage/element/clicked', function(topic, args) {
-                if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
-                    getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                    getViewModel().renewStructure();
-                    getViewModel().refreshSelectedElementItemsBatch();
-                    getViewModel().addAbstractViewValidationResults();
-                    getViewModel().renderInspectorEditors();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = targetEvent
-             *              args[1] = configuration
-             * @return void
-             * @subscribe view/stage/abstract/elementToolbar/button/newElement/clicked
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/elementToolbar/button/newElement/clicked', function(topic, args) {
-                if (getFormEditorApp().isRootFormElementSelected()) {
-                    getViewModel().selectPageBatch(0);
-                }
-                getViewModel().showInsertElementsModal(args[0], args[1]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = targetEvent
-             *              args[1] = configuration
-             * @return void
-             * @subscribe view/newElementButton/clicked
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/button/newElement/clicked', function(topic, args) {
-                if (getFormEditorApp().isRootFormElementSelected()) {
-                    getViewModel().selectPageBatch(0);
-                }
-                getViewModel().showInsertElementsModal(args[0], args[1]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = draggedFormElementDomElement
-             *              args[1] = draggedFormPlaceholderDomElement
-             * @return void
-             * @subscribe view/stage/abstract/dnd/start
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/dnd/start', function(topic, args) {
-                getViewModel().onAbstractViewDndStartBatch(args[0], args[1]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = draggedFormElementIdentifierPath
-             * @return void
-             * @subscribe view/stage/abstract/dnd/stop
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/dnd/stop', function(topic, args) {
-                getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                getViewModel().renewStructure();
-                getViewModel().renderAbstractStageArea(false, false);
-                getViewModel().refreshSelectedElementItemsBatch();
-                getViewModel().addAbstractViewValidationResults();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = placeholderDomElement
-             *              args[1] = parentFormElementIdentifierPath
-             *              args[2] = enclosingCompositeFormElement
-             * @return void
-             * @subscribe view/stage/abstract/dnd/change
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/dnd/change', function(topic, args) {
-                getViewModel().onAbstractViewDndChangeBatch(args[0], args[1], args[2]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = movedDomElement
-             *              args[1] = movedFormElementIdentifierPath
-             *              args[2] = previousFormElementIdentifierPath
-             *              args[3] = nextFormElementIdentifierPath
-             * @return void
-             * @subscribe view/stage/abstract/dnd/update
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/dnd/update', function(topic, args) {
-                getViewModel().onAbstractViewDndUpdateBatch(args[0], args[1], args[2], args[3]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/viewModeButton/abstract/clicked
-             */
-            getPublisherSubscriber().subscribe('view/viewModeButton/abstract/clicked', function(topic, args) {
-                if (getViewModel().getPreviewMode()) {
-                    getViewModel().setPreviewMode(false);
-                    getViewModel().renderAbstractStageArea();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/viewModeButton/preview/clicked
-             */
-            getPublisherSubscriber().subscribe('view/viewModeButton/preview/clicked', function(topic, args) {
-                if (!getViewModel().getPreviewMode()) {
-                    getViewModel().setPreviewMode(true);
-                    getFormEditorApp().renderCurrentFormPage();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/paginationPrevious/clicked
-             */
-            getPublisherSubscriber().subscribe('view/paginationPrevious/clicked', function(topic, args) {
-                getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() - 1);
-                if (getViewModel().getPreviewMode()) {
-                    getFormEditorApp().renderCurrentFormPage();
-                } else {
-                    getViewModel().renderAbstractStageArea();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/paginationNext/clicked
-             */
-            getPublisherSubscriber().subscribe('view/paginationNext/clicked', function(topic, args) {
-                getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() + 1);
-                if (getViewModel().getPreviewMode()) {
-                    getFormEditorApp().renderCurrentFormPage();
-                } else {
-                    getViewModel().renderAbstractStageArea();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/stage/abstract/render/postProcess
-             */
-            getPublisherSubscriber().subscribe('view/stage/abstract/render/postProcess', function(topic, args) {
-                getViewModel().renderUndoRedo();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/stage/preview/render/postProcess
-             */
-            getPublisherSubscriber().subscribe('view/stage/preview/render/postProcess', function(topic, args) {
-                getViewModel().renderUndoRedo();
-            });
-
-            /* *********************************************************
-             * Structure
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementIdentifierPath
-             * @return void
-             * @subscribe view/tree/node/clicked
-             */
-            getPublisherSubscriber().subscribe('view/tree/node/clicked', function(topic, args) {
-                var oldPageIndex;
-                if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
-                    oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
-                    getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                    if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) {
-                        getViewModel().renderAbstractStageArea();
-                    } else {
-                        getViewModel().renderAbstractStageArea(false);
-                    }
-                    getViewModel().renderPagination();
-                    getViewModel().renderInspectorEditors();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/structure/root/selected
-             */
-            getPublisherSubscriber().subscribe('view/structure/root/selected', function(topic, args) {
-                if (!getFormEditorApp().isRootFormElementSelected()) {
-                    getViewModel().addStructureRootElementSelection();
-                    getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement());
-                    getViewModel().renderAbstractStageArea();
-                    getViewModel().renewStructure();
-                    getViewModel().renderPagination();
-                    getViewModel().renderInspectorEditors();
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = targetEvent
-             * @return void
-             * @subscribe view/header/button/newPage/clicked
-             */
-            getPublisherSubscriber().subscribe('view/structure/button/newPage/clicked', function(topic, args) {
-                if (getFormEditorApp().isRootFormElementSelected()) {
-                    getViewModel().selectPageBatch(0);
-                }
-                getViewModel().showInsertPagesModal(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = draggedFormElementIdentifierPath
-             * @return void
-             * @subscribe view/tree/dnd/stop
-             */
-            getPublisherSubscriber().subscribe('view/tree/dnd/stop', function(topic, args) {
-                getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                getViewModel().renewStructure();
-                getViewModel().renderPagination();
-                getViewModel().renderAbstractStageArea();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = placeholderDomElement
-             *              args[1] = parentFormElementIdentifierPath
-             *              args[2] = enclosingCompositeFormElement
-             * @return void
-             * @subscribe view/tree/dnd/change
-             */
-            getPublisherSubscriber().subscribe('view/tree/dnd/change', function(topic, args) {
-                getViewModel().onStructureDndChangeBatch(args[0], args[1], args[2]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = movedDomElement
-             *              args[1] = movedFormElementIdentifierPath
-             *              args[2] = previousFormElementIdentifierPath
-             *              args[3] = nextFormElementIdentifierPath
-             * @return void
-             * @subscribe view/tree/dnd/update
-             */
-            getPublisherSubscriber().subscribe('view/tree/dnd/update', function(topic, args) {
-                getViewModel().onStructureDndUpdateBatch(args[0], args[1], args[2], args[3]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/structure/renew/postProcess
-             */
-            getPublisherSubscriber().subscribe('view/structure/renew/postProcess', function(topic, args) {
-                getViewModel().addStructureValidationResults();
-            });
-
-            /* *********************************************************
-             * Inspector
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             *              args[2] = formElement
-             * @return void
-             * @subscribe view/inspector/removeCollectionElement/perform
-             */
-            getPublisherSubscriber().subscribe('view/inspector/removeCollectionElement/perform', function(topic, args) {
-                getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             * @return void
-             * @subscribe view/inspector/collectionElement/selected
-             */
-            getPublisherSubscriber().subscribe('view/inspector/collectionElement/new/selected', function(topic, args) {
-                getViewModel().createAndAddPropertyCollectionElement(args[0], args[1]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             * @return void
-             * @subscribe view/inspector/collectionElement/selected
-             */
-            getPublisherSubscriber().subscribe('view/inspector/collectionElement/existing/selected', function(topic, args) {
-                getViewModel().renderInspectorCollectionElementEditors(args[1], args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = movedCollectionElementIdentifier
-             *              args[1] = previousCollectionElementIdentifier
-             *              args[2] = nextCollectionElementIdentifier
-             *              args[3] = collectionName
-             * @return void
-             * @subscribe view/inspector/collectionElements/dnd/update
-             * @throws 1477407673
-             */
-            getPublisherSubscriber().subscribe('view/inspector/collectionElements/dnd/update', function(topic, args) {
-                if (args[2]) {
-                    getViewModel().movePropertyCollectionElement(args[0], 'before', args[2], args[3]);
-                } else if (args[1]) {
-                    getViewModel().movePropertyCollectionElement(args[0], 'after', args[1], args[3]);
-                } else {
-                    assert(false, 'Next element or previous element need to be set.', 1477407673);
-                }
-            });
-
-            /* *********************************************************
-             * Form element
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = propertyPath
-             *              args[1] = value
-             *              args[2] = oldValue
-             *              args[3] = formElementIdentifierPath
-             * @return void
-             * @subscribe core/formElement/somePropertyChanged
-             */
-            getPublisherSubscriber().subscribe('core/formElement/somePropertyChanged', function(topic, args) {
-                var hasError, validationElement, validationResults;
-
-                validationResults = [];
-                if ('renderables' !== args[0]) {
-                    if (!getFormEditorApp().isRootFormElementSelected() && 'label' === args[0]) {
-                        getViewModel().getStructure().setTreeNodeTitle();
-                        getViewModel().setInspectorFormElementHeaderEditorContent();
-                    } else if (!getFormEditorApp().getUtility().isUndefinedOrNull(args[3]) && getRootFormElement().get('__identifierPath') === args[3]) {
-                        getViewModel().setStructureRootElementTitle();
-                        getViewModel().setStageHeadline();
-                        getViewModel().setInspectorFormElementHeaderEditorContent();
-                    }
-
-                    if (getViewModel().getPreviewMode()) {
-                        getFormEditorApp().renderCurrentFormPage();
-                    } else {
-                        getViewModel().renderAbstractStageArea(false, false);
-                    }
-                    getViewModel().addStructureValidationResults();
-                }
-
-                getFormEditorApp().setUnsavedContent(true);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = parentFormElement
-             * @return void
-             * @subscribe view/formElement/removed
-             */
-            getPublisherSubscriber().subscribe('view/formElement/removed', function(topic, args) {
-                getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                getViewModel().renewStructure();
-                getViewModel().renderAbstractStageArea();
-                getViewModel().renderPagination();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = newFormElement
-             * @return void
-             * @subscribe view/formElement/inserted
-             */
-            getPublisherSubscriber().subscribe('view/formElement/inserted', function(topic, args) {
-                getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-                getViewModel().renewStructure();
-                getViewModel().renderAbstractStageArea();
-                getViewModel().renderPagination();
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             *              args[2] = formElement
-             *              args[3] = collectionElementConfiguration
-             *              args[4] = referenceCollectionElementIdentifier
-             * @return void
-             * @subscribe view/collectionElement/new/added
-             */
-            getPublisherSubscriber().subscribe('view/collectionElement/new/added', function(topic, args) {
-                getViewModel().renderInspectorEditors();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = movedCollectionElementIdentifier
-             *              args[1] = previousCollectionElementIdentifier
-             *              args[2] = nextCollectionElementIdentifier
-             *              args[3] = collectionName
-             * @return void
-             * @subscribe view/collectionElement/moved
-             * @throws 1477407673
-             */
-            getPublisherSubscriber().subscribe('view/collectionElement/moved', function(topic, args) {
-                getViewModel().renderInspectorEditors(undefined, false);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             *              args[2] = formElement
-             * @return void
-             * @subscribe view/collectionElement/removed
-             */
-            getPublisherSubscriber().subscribe('view/collectionElement/removed', function(topic, args) {
-                getViewModel().renderInspectorEditors(undefined, false);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementType
-             * @return void
-             * @subscribe view/insertElements/perform/bottom
-             */
-            getPublisherSubscriber().subscribe('view/insertElements/perform/bottom', function(topic, args) {
-                var lastRenderable;
-
-                lastRenderable = getFormEditorApp().getLastTopLevelElementOnCurrentPage();
-                if (!lastRenderable) {
-                    getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage());
-                } else {
-                    if (
-                        !getFormEditorApp().getFormElementDefinition(lastRenderable, '_isTopLevelFormElement')
-                        && getFormEditorApp().getFormElementDefinition(lastRenderable, '_isCompositeFormElement')
-                    ) {
-                        getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage());
-                    } else {
-                        getViewModel().createAndAddFormElement(args[0], lastRenderable);
-                    }
-                }
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementType
-             * @return void
-             * @publish view/formElement/inserted
-             * @subscribe view/insertElements/perform/after
-             */
-            getPublisherSubscriber().subscribe('view/insertElements/perform/after', function(topic, args) {
-                var newFormElement;
-                newFormElement = getViewModel().createAndAddFormElement(args[0], undefined, true);
-                newFormElement = getViewModel().moveFormElement(newFormElement, 'after', getFormEditorApp().getCurrentlySelectedFormElement());
-                getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementType
-             * @return void
-             * @subscribe view/insertElements/perform/inside
-             */
-            getPublisherSubscriber().subscribe('view/insertElements/perform/inside', function(topic, args) {
-                getViewModel().createAndAddFormElement(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementType
-             * @return void
-             * @subscribe view/insertElements/perform/after
-             */
-            getPublisherSubscriber().subscribe('view/insertPages/perform', function(topic, args) {
-                getViewModel().createAndAddFormElement(args[0]);
-            });
-
-            /* *********************************************************
-             * Modals
-             * ********************************************************/
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             * @return void
-             * @subscribe view/modal/close/perform
-             */
-            getPublisherSubscriber().subscribe('view/modal/close/perform', function(topic, args) {
-                getFormEditorApp().setUnsavedContent(false);
-                getViewModel().closeEditor();
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElement
-             * @return void
-             * @subscribe view/modal/removeFormElement/perform
-             */
-            getPublisherSubscriber().subscribe('view/modal/removeFormElement/perform', function(topic, args) {
-                getViewModel().removeFormElement(args[0]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = collectionElementIdentifier
-             *              args[1] = collectionName
-             *              args[2] = formElement
-             * @return void
-             * @subscribe view/modal/removeCollectionElement/perform
-             */
-            getPublisherSubscriber().subscribe('view/modal/removeCollectionElement/perform', function(topic, args) {
-                getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]);
-            });
-
-            /**
-             * @private
-             *
-             * @param string
-             * @param array
-             *              args[0] = formElementIdentifierPath
-             * @return void
-             * @subscribe view/modal/validationErrors/element/clicked
-             */
-            getPublisherSubscriber().subscribe('view/modal/validationErrors/element/clicked', function(topic, args) {
-                var oldPageIndex;
-                if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
-                    oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
-                    getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
-
-                    if (getViewModel().getPreviewMode()) {
-                        getViewModel().setPreviewMode(false);
-                    }
-
-                    if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) {
-                        getViewModel().renderAbstractStageArea();
-                    } else {
-                        getViewModel().renderAbstractStageArea(false);
-                    }
-
-                    getViewModel().renderPagination();
-                    getViewModel().renderInspectorEditors();
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @return void
-         */
-        function bootstrap(formEditorApp, viewModel) {
-            _formEditorApp = formEditorApp;
-            _viewModel = viewModel;
-            _helperSetup();
-            _subscribeEvents();
-        };
-
-        /**
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            /**
-             * Publish the public methods.
-             */
-            bootstrap: bootstrap
-        };
-    })($, Helper);
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper'
+], function($, Helper) {
+  'use strict';
+
+  return (function($, Helper) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _viewModel = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getViewModel() {
+      return _viewModel;
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(getViewModel().getConfiguration());
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getCurrentlySelectedFormElement() {
+      return getFormEditorApp().getCurrentlySelectedFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _subscribeEvents() {
+
+      /* *********************************************************
+       * Misc
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @return string
+       */
+      window.onbeforeunload = function(e) {
+        if (!getFormEditorApp().getUnsavedContent()) {
+          return;
+        }
+        e = e || window.event;
+        if (e) {
+          e.returnValue = getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage');
+        }
+        return getFormEditorApp().getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle');
+      };
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/ready
+       */
+      getPublisherSubscriber().subscribe('view/ready', function(topic, args) {
+        getViewModel().onViewReadyBatch();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = applicationState
+       *              args[1] = stackPointer
+       *              args[2] = stackSize
+       * @return void
+       * @subscribe core/applicationState/add
+       */
+      getPublisherSubscriber().subscribe('core/applicationState/add', function(topic, args) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+        if (args[2] > 1 && args[1] <= args[2]) {
+          getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+        } else {
+          getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+        }
+      });
+
+      /* *********************************************************
+       * Ajax
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = html
+       * @return void
+       * @subscribe core/ajax/saveFormDefinition/success
+       */
+      getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/success', function(topic, args) {
+        getFormEditorApp().setUnsavedContent(false);
+        getViewModel().showSaveSuccessMessage();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = object
+       * @return void
+       * @subscribe core/ajax/saveFormDefinition/error
+       */
+      getPublisherSubscriber().subscribe('core/ajax/saveFormDefinition/error', function(topic, args) {
+        getViewModel().showSaveErrorMessage(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = html
+       *              args[1] = pageIndex
+       * @return void
+       * @subscribe core/ajax/renderFormDefinitionPage/success
+       */
+      getPublisherSubscriber().subscribe('core/ajax/renderFormDefinitionPage/success', function(topic, args) {
+        getViewModel().renderPreviewStageArea(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = jqXHR
+       *              args[1] = textStatus
+       *              args[2] = errorThrown
+       * @return void
+       * @subscribe core/ajax/saveFormDefinition/error
+       */
+      getPublisherSubscriber().subscribe('core/ajax/error', function(topic, args) {
+        if (args[0].status !== 0) {
+          getViewModel().showErrorFlashMessage(args[1], args[2]);
+          getViewModel().renderPreviewStageArea(args[0].responseText);
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe ajax/beforeSend
+       */
+      getPublisherSubscriber().subscribe('ajax/beforeSend', function(topic, args) {
+        getViewModel().showSaveButtonSpinnerIcon();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe ajax/complete
+       */
+      getPublisherSubscriber().subscribe('ajax/complete', function(topic, args) {
+        getViewModel().showSaveButtonSaveIcon();
+      });
+
+      /* *********************************************************
+       * Header
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/header/button/save/clicked
+       */
+      getPublisherSubscriber().subscribe('view/header/button/save/clicked', function(topic, args) {
+        if (getFormEditorApp().validationResultsHasErrors(getFormEditorApp().validateFormElementRecursive(getRootFormElement(), true))) {
+          getViewModel().showValidationErrorsModal();
+        } else {
+          getFormEditorApp().saveFormDefinition();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/header/formSettings/clicked
+       */
+      getPublisherSubscriber().subscribe('view/header/formSettings/clicked', function(topic, args) {
+        getViewModel().addStructureRootElementSelection();
+        getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement());
+        getViewModel().renderAbstractStageArea();
+        getViewModel().renewStructure();
+        getViewModel().renderPagination();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = targetEvent
+       * @return void
+       * @subscribe view/header/button/newPage/clicked
+       */
+      getPublisherSubscriber().subscribe('view/header/button/newPage/clicked', function(topic, args) {
+        if (getFormEditorApp().isRootFormElementSelected()) {
+          getViewModel().selectPageBatch(0);
+        }
+        getViewModel().showInsertPagesModal(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/header/button/close/clicked
+       */
+      getPublisherSubscriber().subscribe('view/header/button/close/clicked', function(topic, args) {
+        getViewModel().showCloseConfirmationModal();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/undoButton/clicked
+       */
+      getPublisherSubscriber().subscribe('view/undoButton/clicked', function(topic, args) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+        getFormEditorApp().undoApplicationState();
+
+        if (getViewModel().getPreviewMode()) {
+          getFormEditorApp().renderCurrentFormPage();
+        } else {
+          getViewModel().renderAbstractStageArea();
+        }
+        getFormEditorApp().setUnsavedContent(true);
+
+        getViewModel().renewStructure();
+        getViewModel().renderPagination();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/redoButton/clicked
+       */
+      getPublisherSubscriber().subscribe('view/redoButton/clicked', function(topic, args) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+        getFormEditorApp().redoApplicationState();
+
+        if (getViewModel().getPreviewMode()) {
+          getFormEditorApp().renderCurrentFormPage();
+        } else {
+          getViewModel().renderAbstractStageArea();
+        }
+        getFormEditorApp().setUnsavedContent(true);
+
+        getViewModel().renewStructure();
+        getViewModel().renderPagination();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /* *********************************************************
+       * Stage
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementIdentifierPath
+       * @return void
+       * @subscribe view/stage/element/clicked
+       */
+      getPublisherSubscriber().subscribe('view/stage/element/clicked', function(topic, args) {
+        if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
+          getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+          getViewModel().renewStructure();
+          getViewModel().refreshSelectedElementItemsBatch();
+          getViewModel().addAbstractViewValidationResults();
+          getViewModel().renderInspectorEditors();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = targetEvent
+       *              args[1] = configuration
+       * @return void
+       * @subscribe view/stage/abstract/elementToolbar/button/newElement/clicked
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/elementToolbar/button/newElement/clicked', function(topic, args) {
+        if (getFormEditorApp().isRootFormElementSelected()) {
+          getViewModel().selectPageBatch(0);
+        }
+        getViewModel().showInsertElementsModal(args[0], args[1]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = targetEvent
+       *              args[1] = configuration
+       * @return void
+       * @subscribe view/newElementButton/clicked
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/button/newElement/clicked', function(topic, args) {
+        if (getFormEditorApp().isRootFormElementSelected()) {
+          getViewModel().selectPageBatch(0);
+        }
+        getViewModel().showInsertElementsModal(args[0], args[1]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = draggedFormElementDomElement
+       *              args[1] = draggedFormPlaceholderDomElement
+       * @return void
+       * @subscribe view/stage/abstract/dnd/start
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/dnd/start', function(topic, args) {
+        getViewModel().onAbstractViewDndStartBatch(args[0], args[1]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = draggedFormElementIdentifierPath
+       * @return void
+       * @subscribe view/stage/abstract/dnd/stop
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/dnd/stop', function(topic, args) {
+        getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+        getViewModel().renewStructure();
+        getViewModel().renderAbstractStageArea(false, false);
+        getViewModel().refreshSelectedElementItemsBatch();
+        getViewModel().addAbstractViewValidationResults();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = placeholderDomElement
+       *              args[1] = parentFormElementIdentifierPath
+       *              args[2] = enclosingCompositeFormElement
+       * @return void
+       * @subscribe view/stage/abstract/dnd/change
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/dnd/change', function(topic, args) {
+        getViewModel().onAbstractViewDndChangeBatch(args[0], args[1], args[2]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = movedDomElement
+       *              args[1] = movedFormElementIdentifierPath
+       *              args[2] = previousFormElementIdentifierPath
+       *              args[3] = nextFormElementIdentifierPath
+       * @return void
+       * @subscribe view/stage/abstract/dnd/update
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/dnd/update', function(topic, args) {
+        getViewModel().onAbstractViewDndUpdateBatch(args[0], args[1], args[2], args[3]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/viewModeButton/abstract/clicked
+       */
+      getPublisherSubscriber().subscribe('view/viewModeButton/abstract/clicked', function(topic, args) {
+        if (getViewModel().getPreviewMode()) {
+          getViewModel().setPreviewMode(false);
+          getViewModel().renderAbstractStageArea();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/viewModeButton/preview/clicked
+       */
+      getPublisherSubscriber().subscribe('view/viewModeButton/preview/clicked', function(topic, args) {
+        if (!getViewModel().getPreviewMode()) {
+          getViewModel().setPreviewMode(true);
+          getFormEditorApp().renderCurrentFormPage();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/paginationPrevious/clicked
+       */
+      getPublisherSubscriber().subscribe('view/paginationPrevious/clicked', function(topic, args) {
+        getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() - 1);
+        if (getViewModel().getPreviewMode()) {
+          getFormEditorApp().renderCurrentFormPage();
+        } else {
+          getViewModel().renderAbstractStageArea();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/paginationNext/clicked
+       */
+      getPublisherSubscriber().subscribe('view/paginationNext/clicked', function(topic, args) {
+        getViewModel().selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex() + 1);
+        if (getViewModel().getPreviewMode()) {
+          getFormEditorApp().renderCurrentFormPage();
+        } else {
+          getViewModel().renderAbstractStageArea();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/stage/abstract/render/postProcess
+       */
+      getPublisherSubscriber().subscribe('view/stage/abstract/render/postProcess', function(topic, args) {
+        getViewModel().renderUndoRedo();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/stage/preview/render/postProcess
+       */
+      getPublisherSubscriber().subscribe('view/stage/preview/render/postProcess', function(topic, args) {
+        getViewModel().renderUndoRedo();
+      });
+
+      /* *********************************************************
+       * Structure
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementIdentifierPath
+       * @return void
+       * @subscribe view/tree/node/clicked
+       */
+      getPublisherSubscriber().subscribe('view/tree/node/clicked', function(topic, args) {
+        var oldPageIndex;
+        if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
+          oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
+          getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+          if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) {
+            getViewModel().renderAbstractStageArea();
+          } else {
+            getViewModel().renderAbstractStageArea(false);
+          }
+          getViewModel().renderPagination();
+          getViewModel().renderInspectorEditors();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/structure/root/selected
+       */
+      getPublisherSubscriber().subscribe('view/structure/root/selected', function(topic, args) {
+        if (!getFormEditorApp().isRootFormElementSelected()) {
+          getViewModel().addStructureRootElementSelection();
+          getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement());
+          getViewModel().renderAbstractStageArea();
+          getViewModel().renewStructure();
+          getViewModel().renderPagination();
+          getViewModel().renderInspectorEditors();
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = targetEvent
+       * @return void
+       * @subscribe view/header/button/newPage/clicked
+       */
+      getPublisherSubscriber().subscribe('view/structure/button/newPage/clicked', function(topic, args) {
+        if (getFormEditorApp().isRootFormElementSelected()) {
+          getViewModel().selectPageBatch(0);
+        }
+        getViewModel().showInsertPagesModal(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = draggedFormElementIdentifierPath
+       * @return void
+       * @subscribe view/tree/dnd/stop
+       */
+      getPublisherSubscriber().subscribe('view/tree/dnd/stop', function(topic, args) {
+        getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+        getViewModel().renewStructure();
+        getViewModel().renderPagination();
+        getViewModel().renderAbstractStageArea();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = placeholderDomElement
+       *              args[1] = parentFormElementIdentifierPath
+       *              args[2] = enclosingCompositeFormElement
+       * @return void
+       * @subscribe view/tree/dnd/change
+       */
+      getPublisherSubscriber().subscribe('view/tree/dnd/change', function(topic, args) {
+        getViewModel().onStructureDndChangeBatch(args[0], args[1], args[2]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = movedDomElement
+       *              args[1] = movedFormElementIdentifierPath
+       *              args[2] = previousFormElementIdentifierPath
+       *              args[3] = nextFormElementIdentifierPath
+       * @return void
+       * @subscribe view/tree/dnd/update
+       */
+      getPublisherSubscriber().subscribe('view/tree/dnd/update', function(topic, args) {
+        getViewModel().onStructureDndUpdateBatch(args[0], args[1], args[2], args[3]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/structure/renew/postProcess
+       */
+      getPublisherSubscriber().subscribe('view/structure/renew/postProcess', function(topic, args) {
+        getViewModel().addStructureValidationResults();
+      });
+
+      /* *********************************************************
+       * Inspector
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       *              args[2] = formElement
+       * @return void
+       * @subscribe view/inspector/removeCollectionElement/perform
+       */
+      getPublisherSubscriber().subscribe('view/inspector/removeCollectionElement/perform', function(topic, args) {
+        getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       * @return void
+       * @subscribe view/inspector/collectionElement/selected
+       */
+      getPublisherSubscriber().subscribe('view/inspector/collectionElement/new/selected', function(topic, args) {
+        getViewModel().createAndAddPropertyCollectionElement(args[0], args[1]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       * @return void
+       * @subscribe view/inspector/collectionElement/selected
+       */
+      getPublisherSubscriber().subscribe('view/inspector/collectionElement/existing/selected', function(topic, args) {
+        getViewModel().renderInspectorCollectionElementEditors(args[1], args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = movedCollectionElementIdentifier
+       *              args[1] = previousCollectionElementIdentifier
+       *              args[2] = nextCollectionElementIdentifier
+       *              args[3] = collectionName
+       * @return void
+       * @subscribe view/inspector/collectionElements/dnd/update
+       * @throws 1477407673
+       */
+      getPublisherSubscriber().subscribe('view/inspector/collectionElements/dnd/update', function(topic, args) {
+        if (args[2]) {
+          getViewModel().movePropertyCollectionElement(args[0], 'before', args[2], args[3]);
+        } else if (args[1]) {
+          getViewModel().movePropertyCollectionElement(args[0], 'after', args[1], args[3]);
+        } else {
+          assert(false, 'Next element or previous element need to be set.', 1477407673);
+        }
+      });
+
+      /* *********************************************************
+       * Form element
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = propertyPath
+       *              args[1] = value
+       *              args[2] = oldValue
+       *              args[3] = formElementIdentifierPath
+       * @return void
+       * @subscribe core/formElement/somePropertyChanged
+       */
+      getPublisherSubscriber().subscribe('core/formElement/somePropertyChanged', function(topic, args) {
+        var hasError, validationElement, validationResults;
+
+        validationResults = [];
+        if ('renderables' !== args[0]) {
+          if (!getFormEditorApp().isRootFormElementSelected() && 'label' === args[0]) {
+            getViewModel().getStructure().setTreeNodeTitle();
+            getViewModel().setInspectorFormElementHeaderEditorContent();
+          } else if (!getFormEditorApp().getUtility().isUndefinedOrNull(args[3]) && getRootFormElement().get('__identifierPath') === args[3]) {
+            getViewModel().setStructureRootElementTitle();
+            getViewModel().setStageHeadline();
+            getViewModel().setInspectorFormElementHeaderEditorContent();
+          }
+
+          if (getViewModel().getPreviewMode()) {
+            getFormEditorApp().renderCurrentFormPage();
+          } else {
+            getViewModel().renderAbstractStageArea(false, false);
+          }
+          getViewModel().addStructureValidationResults();
+        }
+
+        getFormEditorApp().setUnsavedContent(true);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = parentFormElement
+       * @return void
+       * @subscribe view/formElement/removed
+       */
+      getPublisherSubscriber().subscribe('view/formElement/removed', function(topic, args) {
+        getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+        getViewModel().renewStructure();
+        getViewModel().renderAbstractStageArea();
+        getViewModel().renderPagination();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = newFormElement
+       * @return void
+       * @subscribe view/formElement/inserted
+       */
+      getPublisherSubscriber().subscribe('view/formElement/inserted', function(topic, args) {
+        getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+        getViewModel().renewStructure();
+        getViewModel().renderAbstractStageArea();
+        getViewModel().renderPagination();
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       *              args[2] = formElement
+       *              args[3] = collectionElementConfiguration
+       *              args[4] = referenceCollectionElementIdentifier
+       * @return void
+       * @subscribe view/collectionElement/new/added
+       */
+      getPublisherSubscriber().subscribe('view/collectionElement/new/added', function(topic, args) {
+        getViewModel().renderInspectorEditors();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = movedCollectionElementIdentifier
+       *              args[1] = previousCollectionElementIdentifier
+       *              args[2] = nextCollectionElementIdentifier
+       *              args[3] = collectionName
+       * @return void
+       * @subscribe view/collectionElement/moved
+       * @throws 1477407673
+       */
+      getPublisherSubscriber().subscribe('view/collectionElement/moved', function(topic, args) {
+        getViewModel().renderInspectorEditors(undefined, false);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       *              args[2] = formElement
+       * @return void
+       * @subscribe view/collectionElement/removed
+       */
+      getPublisherSubscriber().subscribe('view/collectionElement/removed', function(topic, args) {
+        getViewModel().renderInspectorEditors(undefined, false);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementType
+       * @return void
+       * @subscribe view/insertElements/perform/bottom
+       */
+      getPublisherSubscriber().subscribe('view/insertElements/perform/bottom', function(topic, args) {
+        var lastRenderable;
+
+        lastRenderable = getFormEditorApp().getLastTopLevelElementOnCurrentPage();
+        if (!lastRenderable) {
+          getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage());
+        } else {
+          if (
+            !getFormEditorApp().getFormElementDefinition(lastRenderable, '_isTopLevelFormElement')
+            && getFormEditorApp().getFormElementDefinition(lastRenderable, '_isCompositeFormElement')
+          ) {
+            getViewModel().createAndAddFormElement(args[0], getFormEditorApp().getCurrentlySelectedPage());
+          } else {
+            getViewModel().createAndAddFormElement(args[0], lastRenderable);
+          }
+        }
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementType
+       * @return void
+       * @publish view/formElement/inserted
+       * @subscribe view/insertElements/perform/after
+       */
+      getPublisherSubscriber().subscribe('view/insertElements/perform/after', function(topic, args) {
+        var newFormElement;
+        newFormElement = getViewModel().createAndAddFormElement(args[0], undefined, true);
+        newFormElement = getViewModel().moveFormElement(newFormElement, 'after', getFormEditorApp().getCurrentlySelectedFormElement());
+        getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementType
+       * @return void
+       * @subscribe view/insertElements/perform/inside
+       */
+      getPublisherSubscriber().subscribe('view/insertElements/perform/inside', function(topic, args) {
+        getViewModel().createAndAddFormElement(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementType
+       * @return void
+       * @subscribe view/insertElements/perform/after
+       */
+      getPublisherSubscriber().subscribe('view/insertPages/perform', function(topic, args) {
+        getViewModel().createAndAddFormElement(args[0]);
+      });
+
+      /* *********************************************************
+       * Modals
+       * ********************************************************/
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       * @return void
+       * @subscribe view/modal/close/perform
+       */
+      getPublisherSubscriber().subscribe('view/modal/close/perform', function(topic, args) {
+        getFormEditorApp().setUnsavedContent(false);
+        getViewModel().closeEditor();
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElement
+       * @return void
+       * @subscribe view/modal/removeFormElement/perform
+       */
+      getPublisherSubscriber().subscribe('view/modal/removeFormElement/perform', function(topic, args) {
+        getViewModel().removeFormElement(args[0]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = collectionElementIdentifier
+       *              args[1] = collectionName
+       *              args[2] = formElement
+       * @return void
+       * @subscribe view/modal/removeCollectionElement/perform
+       */
+      getPublisherSubscriber().subscribe('view/modal/removeCollectionElement/perform', function(topic, args) {
+        getViewModel().removePropertyCollectionElement(args[0], args[1], args[2]);
+      });
+
+      /**
+       * @private
+       *
+       * @param string
+       * @param array
+       *              args[0] = formElementIdentifierPath
+       * @return void
+       * @subscribe view/modal/validationErrors/element/clicked
+       */
+      getPublisherSubscriber().subscribe('view/modal/validationErrors/element/clicked', function(topic, args) {
+        var oldPageIndex;
+        if (getCurrentlySelectedFormElement().get('__identifierPath') !== args[0]) {
+          oldPageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
+          getFormEditorApp().setCurrentlySelectedFormElement(args[0]);
+
+          if (getViewModel().getPreviewMode()) {
+            getViewModel().setPreviewMode(false);
+          }
+
+          if (oldPageIndex !== getFormEditorApp().getCurrentlySelectedPageIndex()) {
+            getViewModel().renderAbstractStageArea();
+          } else {
+            getViewModel().renderAbstractStageArea(false);
+          }
+
+          getViewModel().renderPagination();
+          getViewModel().renderInspectorEditors();
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @return void
+     */
+    function bootstrap(formEditorApp, viewModel) {
+      _formEditorApp = formEditorApp;
+      _viewModel = viewModel;
+      _helperSetup();
+      _subscribeEvents();
+    };
+
+    /**
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      /**
+       * Publish the public methods.
+       */
+      bootstrap: bootstrap
+    };
+  })($, Helper);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js
index 9030bd1f72f4..0c89d51e8bf9 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ModalsComponent.js
@@ -15,524 +15,524 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper',
-        'TYPO3/CMS/Backend/Modal',
-        'TYPO3/CMS/Backend/Severity',
-        'TYPO3/CMS/Backend/Icons'
-        ], function($, Helper, Modal, Severity, Icons) {
-        'use strict';
-
-    return (function($, Helper, Modal, Severity, Icons) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _defaultConfiguration = {
-            domElementClassNames: {
-                buttonDefault: 'btn-default',
-                buttonInfo: 'btn-info',
-                buttonWarning: 'btn-warning'
-            },
-            domElementDataAttributeNames: {
-                elementType: 'element-type',
-                fullElementType: 'data-element-type'
-            },
-            domElementDataAttributeValues: {
-                rowItem: 'rowItem',
-                rowLink: 'rowLink',
-                rowsContainer: 'rowsContainer',
-                templateInsertElements: 'Modal-InsertElements',
-                templateInsertPages: 'Modal-InsertPages',
-                templateValidationErrors: 'Modal-ValidationErrors'
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(_configuration);
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return mixed
-         */
-        function getFormElementDefinition(formElement, formElementDefinitionKey) {
-            return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
-        };
-
-        /**
-         * @public
-         *
-         * @param string publisherTopicName
-         * @param object publisherTopicArguments
-         * @return void
-         * @throws 1478889044
-         * @throws 1478889049
-         */
-        function _showRemoveElementModal(publisherTopicName, publisherTopicArguments) {
-            var modalButtons = [];
-
-            assert(
-                getUtility().isNonEmptyString(publisherTopicName),
-                'Invalid parameter "publisherTopicName"',
-                1478889049
-            );
-            assert(
-                'array' === $.type(publisherTopicArguments),
-                'Invalid parameter "formElement"',
-                1478889044
-            );
-
-            modalButtons.push({
-                text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementCancleButton'),
-                active: true,
-                btnClass: getHelper().getDomElementClassName('buttonDefault'),
-                name: 'cancel',
-                trigger: function () {
-                    Modal.currentModal.trigger('modal-dismiss');
-                }
-            });
-
-            modalButtons.push({
-                text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementConfirmButton'),
-                active: true,
-                btnClass: getHelper().getDomElementClassName('buttonWarning'),
-                name: 'confirm',
-                trigger: function () {
-                    getPublisherSubscriber().publish(publisherTopicName, publisherTopicArguments);
-                    Modal.currentModal.trigger('modal-dismiss');
-                }
-            });
-
-            Modal.show(
-                getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogTitle'),
-                getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogMessage'),
-                Severity.warning,
-                modalButtons
-            );
-        };
-
-        /**
-         * @private
-         *
-         * @param object modalContent
-         * @param string publisherTopicName
-         * @param object configuration
-         * @return void
-         * @publish mixed
-         * @throws 1478910954
-         */
-        function _insertElementsModalSetup(modalContent, publisherTopicName, configuration) {
-            var formElementItems;
-
-            assert(
-                getUtility().isNonEmptyString(publisherTopicName),
-                'Invalid parameter "publisherTopicName"',
-                1478910954
-            );
-
-            if ('object' === $.type(configuration)) {
-                for (var key in configuration) {
-                    if (!configuration.hasOwnProperty(key)) {
-                        continue;
-                    }
-                    if (
-                        key === 'disableElementTypes'
-                        && 'array' === $.type(configuration[key])
-                    ) {
-                        for (var i = 0, len = configuration[key].length; i < len; ++i) {
-                            $(
-                                getHelper().getDomElementDataAttribute(
-                                    'fullElementType',
-                                    'bracesWithKeyValue', [configuration[key][i]]
-                                ),
-                                modalContent
-                            ).addClass(getHelper().getDomElementClassName('disabled'));
-                        }
-                    }
-
-                    if (
-                        key === 'onlyEnableElementTypes'
-                        && 'array' === $.type(configuration[key])
-                    ) {
-                        $(
-                            getHelper().getDomElementDataAttribute(
-                                'fullElementType',
-                                'bracesWithKey'
-                            ),
-                            modalContent
-                        ).each(function(i, element) {
-                            for (var i = 0, len = configuration[key].length; i < len; ++i) {
-                                var that = $(this);
-                                if (that.data(getHelper().getDomElementDataAttribute('elementType')) !== configuration[key][i]) {
-                                    that.addClass(getHelper().getDomElementClassName('disabled'));
-                                }
-                            }
-                        });
-                    }
-                }
-            }
-
-            $('a', modalContent).on("click", function(e) {
-                getPublisherSubscriber().publish(publisherTopicName, [$(this).data(getHelper().getDomElementDataAttribute('elementType'))]);
-                $('a', modalContent).off();
-                Modal.currentModal.trigger('modal-dismiss');
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @param object modalContent
-         * @param object validationResults
-         * @return void
-         * @publish view/modal/validationErrors/element/clicked
-         * @throws 1479161268
-         */
-        function _validationErrorsModalSetup(modalContent, validationResults) {
-            var formElement, newRowItem, rowItemTemplate;
-
-            assert(
-                'array' === $.type(validationResults),
-                'Invalid parameter "validationResults"',
-                1479161268
-            );
-
-            rowItemTemplate = $(
-                getHelper().getDomElementDataIdentifierSelector('rowItem'),
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Icons'
+], function($, Helper, Modal, Severity, Icons) {
+  'use strict';
+
+  return (function($, Helper, Modal, Severity, Icons) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _defaultConfiguration = {
+      domElementClassNames: {
+        buttonDefault: 'btn-default',
+        buttonInfo: 'btn-info',
+        buttonWarning: 'btn-warning'
+      },
+      domElementDataAttributeNames: {
+        elementType: 'element-type',
+        fullElementType: 'data-element-type'
+      },
+      domElementDataAttributeValues: {
+        rowItem: 'rowItem',
+        rowLink: 'rowLink',
+        rowsContainer: 'rowsContainer',
+        templateInsertElements: 'Modal-InsertElements',
+        templateInsertPages: 'Modal-InsertPages',
+        templateValidationErrors: 'Modal-ValidationErrors'
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(_configuration);
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return mixed
+     */
+    function getFormElementDefinition(formElement, formElementDefinitionKey) {
+      return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
+    };
+
+    /**
+     * @public
+     *
+     * @param string publisherTopicName
+     * @param object publisherTopicArguments
+     * @return void
+     * @throws 1478889044
+     * @throws 1478889049
+     */
+    function _showRemoveElementModal(publisherTopicName, publisherTopicArguments) {
+      var modalButtons = [];
+
+      assert(
+        getUtility().isNonEmptyString(publisherTopicName),
+        'Invalid parameter "publisherTopicName"',
+        1478889049
+      );
+      assert(
+        'array' === $.type(publisherTopicArguments),
+        'Invalid parameter "formElement"',
+        1478889044
+      );
+
+      modalButtons.push({
+        text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementCancleButton'),
+        active: true,
+        btnClass: getHelper().getDomElementClassName('buttonDefault'),
+        name: 'cancel',
+        trigger: function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      modalButtons.push({
+        text: getFormElementDefinition(getRootFormElement(), 'modalRemoveElementConfirmButton'),
+        active: true,
+        btnClass: getHelper().getDomElementClassName('buttonWarning'),
+        name: 'confirm',
+        trigger: function() {
+          getPublisherSubscriber().publish(publisherTopicName, publisherTopicArguments);
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      Modal.show(
+        getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogTitle'),
+        getFormElementDefinition(getRootFormElement(), 'modalRemoveElementDialogMessage'),
+        Severity.warning,
+        modalButtons
+      );
+    };
+
+    /**
+     * @private
+     *
+     * @param object modalContent
+     * @param string publisherTopicName
+     * @param object configuration
+     * @return void
+     * @publish mixed
+     * @throws 1478910954
+     */
+    function _insertElementsModalSetup(modalContent, publisherTopicName, configuration) {
+      var formElementItems;
+
+      assert(
+        getUtility().isNonEmptyString(publisherTopicName),
+        'Invalid parameter "publisherTopicName"',
+        1478910954
+      );
+
+      if ('object' === $.type(configuration)) {
+        for (var key in configuration) {
+          if (!configuration.hasOwnProperty(key)) {
+            continue;
+          }
+          if (
+            key === 'disableElementTypes'
+            && 'array' === $.type(configuration[key])
+          ) {
+            for (var i = 0, len = configuration[key].length; i < len; ++i) {
+              $(
+                getHelper().getDomElementDataAttribute(
+                  'fullElementType',
+                  'bracesWithKeyValue', [configuration[key][i]]
+                ),
                 modalContent
-            ).clone();
-
-            $(getHelper().getDomElementDataIdentifierSelector('rowItem'), modalContent).remove();
-
-            for (var i = 0, len = validationResults.length; i < len; ++i) {
-                var hasError = false, validationElement;
-                for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
-                    if (
-                        validationResults[i]['validationResults'][j]['validationResults']
-                        && validationResults[i]['validationResults'][j]['validationResults'].length > 0
-                    ) {
-                        hasError = true;
-                        break;
-                    }
-                }
-
-                if (hasError) {
-                    formElement = getFormEditorApp()
-                        .getFormElementByIdentifierPath(validationResults[i]['formElementIdentifierPath']);
-                    newRowItem = rowItemTemplate.clone();
-                    $(getHelper().getDomElementDataIdentifierSelector('rowLink'), newRowItem)
-                        .attr(
-                            getHelper().getDomElementDataAttribute('elementIdentifier'),
-                            validationResults[i]['formElementIdentifierPath']
-                        )
-                        .html(_buildTitleByFormElement(formElement));
-                    $(getHelper().getDomElementDataIdentifierSelector('rowsContainer'), modalContent)
-                        .append(newRowItem);
-                }
+              ).addClass(getHelper().getDomElementClassName('disabled'));
             }
-
-            $('a', modalContent).on("click", function(e) {
-                getPublisherSubscriber().publish('view/modal/validationErrors/element/clicked', [
-                    $(this).attr(getHelper().getDomElementDataAttribute('elementIdentifier'))
-                ]);
-                $('a', modalContent).off();
-                Modal.currentModal.trigger('modal-dismiss');
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         * @throws 1479162557
-         */
-        function _buildTitleByFormElement(formElement) {
-            var label;
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479162557);
-
-            return $('<span></span>').text((formElement.get('label')
-                ? formElement.get('label')
-                : formElement.get('identifier')));
-        };
-
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param object formElement
-         * @return void
-         * @publish view/modal/removeFormElement/perform
-         */
-        function showRemoveFormElementModal(formElement) {
-            _showRemoveElementModal('view/modal/removeFormElement/perform', [formElement]);
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @param object formElement
-         * @return void
-         * @publish view/modal/removeCollectionElement/perform
-         * @throws 1478894420
-         * @throws 1478894421
-         */
-        function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) {
-            assert(
-                getUtility().isNonEmptyString(collectionElementIdentifier),
-                'Invalid parameter "collectionElementIdentifier"',
-                1478894420
-            );
-            assert(
-                getUtility().isNonEmptyString(collectionName),
-                'Invalid parameter "collectionName"',
-                1478894421
-            );
-
-            _showRemoveElementModal('view/modal/removeCollectionElement/perform', [collectionElementIdentifier, collectionName, formElement]);
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         * @publish view/modal/close/perform
-         */
-        function showCloseConfirmationModal() {
-            var  modalButtons = [];
-
-            modalButtons.push({
-                text: getFormElementDefinition(getRootFormElement(), 'modalCloseCancleButton'),
-                active: true,
-                btnClass: getHelper().getDomElementClassName('buttonDefault'),
-                name: 'cancel',
-                trigger: function () {
-                    Modal.currentModal.trigger('modal-dismiss');
-                }
-            });
-
-            modalButtons.push({
-                text: getFormElementDefinition(getRootFormElement(), 'modalCloseConfirmButton'),
-                active: true,
-                btnClass: getHelper().getDomElementClassName('buttonWarning'),
-                name: 'confirm',
-                trigger: function () {
-                    getPublisherSubscriber().publish('view/modal/close/perform', []);
-                    Modal.currentModal.trigger('modal-dismiss');
+          }
+
+          if (
+            key === 'onlyEnableElementTypes'
+            && 'array' === $.type(configuration[key])
+          ) {
+            $(
+              getHelper().getDomElementDataAttribute(
+                'fullElementType',
+                'bracesWithKey'
+              ),
+              modalContent
+            ).each(function(i, element) {
+              for (var i = 0, len = configuration[key].length; i < len; ++i) {
+                var that = $(this);
+                if (that.data(getHelper().getDomElementDataAttribute('elementType')) !== configuration[key][i]) {
+                  that.addClass(getHelper().getDomElementClassName('disabled'));
                 }
+              }
             });
-
-            Modal.show(
-                getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'),
-                getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'),
-                Severity.warning,
-                modalButtons
-            );
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @param object
-         * @return void
-         */
-        function showInsertElementsModal(publisherTopicName, configuration) {
-            var html, template;
-
-            template = getHelper().getTemplate('templateInsertElements');
-            if (template.length > 0) {
-                html = $(template.html());
-                _insertElementsModalSetup(html, publisherTopicName, configuration);
-
-                Modal.show(
-                    getFormElementDefinition(getRootFormElement(), 'modalInsertElementsDialogTitle'),
-                    $(html),
-                    Severity.info
-                );
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @return void
-         */
-        function showInsertPagesModal(publisherTopicName) {
-            var html, template;
-
-            template = getHelper().getTemplate('templateInsertPages');
-            if (template.length > 0) {
-                html = $(template.html());
-                _insertElementsModalSetup(html, publisherTopicName);
-
-                Modal.show(
-                    getFormElementDefinition(getRootFormElement(), 'modalInsertPagesDialogTitle'),
-                    $(html),
-                    Severity.info
-                );
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function showValidationErrorsModal(validationResults) {
-            var html, template, modalButtons = [];
-
-            modalButtons.push({
-                text: getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsConfirmButton'),
-                active: true,
-                btnClass: getHelper().getDomElementClassName('buttonDefault'),
-                name: 'confirm',
-                trigger: function () {
-                    Modal.currentModal.trigger('modal-dismiss');
-                }
-            });
-
-            template = getHelper().getTemplate('templateValidationErrors');
-            if (template.length > 0) {
-                html = $(template.html()).clone();
-                _validationErrorsModalSetup(html, validationResults);
-
-                Modal.show(
-                    getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsDialogTitle'),
-                    html,
-                    Severity.error,
-                    modalButtons
-                );
-            }
+          }
+        }
+      }
+
+      $('a', modalContent).on("click", function(e) {
+        getPublisherSubscriber().publish(publisherTopicName, [$(this).data(getHelper().getDomElementDataAttribute('elementType'))]);
+        $('a', modalContent).off();
+        Modal.currentModal.trigger('modal-dismiss');
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @param object modalContent
+     * @param object validationResults
+     * @return void
+     * @publish view/modal/validationErrors/element/clicked
+     * @throws 1479161268
+     */
+    function _validationErrorsModalSetup(modalContent, validationResults) {
+      var formElement, newRowItem, rowItemTemplate;
+
+      assert(
+        'array' === $.type(validationResults),
+        'Invalid parameter "validationResults"',
+        1479161268
+      );
+
+      rowItemTemplate = $(
+        getHelper().getDomElementDataIdentifierSelector('rowItem'),
+        modalContent
+      ).clone();
+
+      $(getHelper().getDomElementDataIdentifierSelector('rowItem'), modalContent).remove();
+
+      for (var i = 0, len = validationResults.length; i < len; ++i) {
+        var hasError = false, validationElement;
+        for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
+          if (
+            validationResults[i]['validationResults'][j]['validationResults']
+            && validationResults[i]['validationResults'][j]['validationResults'].length > 0
+          ) {
+            hasError = true;
+            break;
+          }
         }
 
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @return this
-         */
-        function bootstrap(formEditorApp, configuration) {
-            _formEditorApp = formEditorApp;
-            _configuration = $.extend(true, _defaultConfiguration, configuration || {});
-            _helperSetup();
-            return this;
-        };
-
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            bootstrap: bootstrap,
-            showCloseConfirmationModal: showCloseConfirmationModal,
-            showInsertElementsModal: showInsertElementsModal,
-            showInsertPagesModal: showInsertPagesModal,
-            showRemoveCollectionElementModal: showRemoveCollectionElementModal,
-            showRemoveFormElementModal: showRemoveFormElementModal,
-            showValidationErrorsModal: showValidationErrorsModal
-        };
-    })($, Helper, Modal, Severity, Icons);
+        if (hasError) {
+          formElement = getFormEditorApp()
+            .getFormElementByIdentifierPath(validationResults[i]['formElementIdentifierPath']);
+          newRowItem = rowItemTemplate.clone();
+          $(getHelper().getDomElementDataIdentifierSelector('rowLink'), newRowItem)
+            .attr(
+              getHelper().getDomElementDataAttribute('elementIdentifier'),
+              validationResults[i]['formElementIdentifierPath']
+            )
+            .html(_buildTitleByFormElement(formElement));
+          $(getHelper().getDomElementDataIdentifierSelector('rowsContainer'), modalContent)
+            .append(newRowItem);
+        }
+      }
+
+      $('a', modalContent).on("click", function(e) {
+        getPublisherSubscriber().publish('view/modal/validationErrors/element/clicked', [
+          $(this).attr(getHelper().getDomElementDataAttribute('elementIdentifier'))
+        ]);
+        $('a', modalContent).off();
+        Modal.currentModal.trigger('modal-dismiss');
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     * @throws 1479162557
+     */
+    function _buildTitleByFormElement(formElement) {
+      var label;
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479162557);
+
+      return $('<span></span>').text((formElement.get('label')
+        ? formElement.get('label')
+        : formElement.get('identifier')));
+    };
+
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param object formElement
+     * @return void
+     * @publish view/modal/removeFormElement/perform
+     */
+    function showRemoveFormElementModal(formElement) {
+      _showRemoveElementModal('view/modal/removeFormElement/perform', [formElement]);
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @param object formElement
+     * @return void
+     * @publish view/modal/removeCollectionElement/perform
+     * @throws 1478894420
+     * @throws 1478894421
+     */
+    function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) {
+      assert(
+        getUtility().isNonEmptyString(collectionElementIdentifier),
+        'Invalid parameter "collectionElementIdentifier"',
+        1478894420
+      );
+      assert(
+        getUtility().isNonEmptyString(collectionName),
+        'Invalid parameter "collectionName"',
+        1478894421
+      );
+
+      _showRemoveElementModal('view/modal/removeCollectionElement/perform', [collectionElementIdentifier, collectionName, formElement]);
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     * @publish view/modal/close/perform
+     */
+    function showCloseConfirmationModal() {
+      var modalButtons = [];
+
+      modalButtons.push({
+        text: getFormElementDefinition(getRootFormElement(), 'modalCloseCancleButton'),
+        active: true,
+        btnClass: getHelper().getDomElementClassName('buttonDefault'),
+        name: 'cancel',
+        trigger: function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      modalButtons.push({
+        text: getFormElementDefinition(getRootFormElement(), 'modalCloseConfirmButton'),
+        active: true,
+        btnClass: getHelper().getDomElementClassName('buttonWarning'),
+        name: 'confirm',
+        trigger: function() {
+          getPublisherSubscriber().publish('view/modal/close/perform', []);
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      Modal.show(
+        getFormElementDefinition(getRootFormElement(), 'modalCloseDialogTitle'),
+        getFormElementDefinition(getRootFormElement(), 'modalCloseDialogMessage'),
+        Severity.warning,
+        modalButtons
+      );
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @param object
+     * @return void
+     */
+    function showInsertElementsModal(publisherTopicName, configuration) {
+      var html, template;
+
+      template = getHelper().getTemplate('templateInsertElements');
+      if (template.length > 0) {
+        html = $(template.html());
+        _insertElementsModalSetup(html, publisherTopicName, configuration);
+
+        Modal.show(
+          getFormElementDefinition(getRootFormElement(), 'modalInsertElementsDialogTitle'),
+          $(html),
+          Severity.info
+        );
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @return void
+     */
+    function showInsertPagesModal(publisherTopicName) {
+      var html, template;
+
+      template = getHelper().getTemplate('templateInsertPages');
+      if (template.length > 0) {
+        html = $(template.html());
+        _insertElementsModalSetup(html, publisherTopicName);
+
+        Modal.show(
+          getFormElementDefinition(getRootFormElement(), 'modalInsertPagesDialogTitle'),
+          $(html),
+          Severity.info
+        );
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function showValidationErrorsModal(validationResults) {
+      var html, template, modalButtons = [];
+
+      modalButtons.push({
+        text: getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsConfirmButton'),
+        active: true,
+        btnClass: getHelper().getDomElementClassName('buttonDefault'),
+        name: 'confirm',
+        trigger: function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      template = getHelper().getTemplate('templateValidationErrors');
+      if (template.length > 0) {
+        html = $(template.html()).clone();
+        _validationErrorsModalSetup(html, validationResults);
+
+        Modal.show(
+          getFormElementDefinition(getRootFormElement(), 'modalValidationErrorsDialogTitle'),
+          html,
+          Severity.error,
+          modalButtons
+        );
+      }
+    }
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @return this
+     */
+    function bootstrap(formEditorApp, configuration) {
+      _formEditorApp = formEditorApp;
+      _configuration = $.extend(true, _defaultConfiguration, configuration || {});
+      _helperSetup();
+      return this;
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap,
+      showCloseConfirmationModal: showCloseConfirmationModal,
+      showInsertElementsModal: showInsertElementsModal,
+      showInsertPagesModal: showInsertPagesModal,
+      showRemoveCollectionElementModal: showRemoveCollectionElementModal,
+      showRemoveFormElementModal: showRemoveFormElementModal,
+      showValidationErrorsModal: showValidationErrorsModal
+    };
+  })($, Helper, Modal, Severity, Icons);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js
index 793c1499325e..31b238433d88 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/StageComponent.js
@@ -15,1223 +15,1225 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/StageComponent
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper',
-        'TYPO3/CMS/Backend/Icons',
-        'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
-        ], function($, Helper, Icons) {
-        'use strict';
-
-    return (function($, Helper, Icons) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _defaultConfiguration = {
-            domElementClassNames: {
-                formElementIsComposit: 't3-form-element-composit',
-                formElementIsTopLevel: 't3-form-element-toplevel',
-                noNesting: 'mjs-nestedSortable-no-nesting',
-                selected: 'selected',
-                sortable: 'sortable',
-                previewViewPreviewElement: 't3-form-element-preview'
-            },
-            domElementDataAttributeNames: {
-                abstractType: 'data-element-abstract-type',
-                noSorting: 'data-no-sorting'
-            },
-            domElementDataAttributeValues: {
-                abstractViewToolbar: 'elementToolbar',
-                abstractViewToolbarNewElement: 'stageElementToolbarNewElement',
-                abstractViewToolbarNewElementSplitButton: 'stageElementToolbarNewElementSplitButton',
-                abstractViewToolbarNewElementSplitButtonAfter: 'stageElementToolbarNewElementSplitButtonAfter',
-                abstractViewToolbarNewElementSplitButtonInside: 'stageElementToolbarNewElementSplitButtonInside',
-                abstractViewToolbarRemoveElement: 'stageElementToolbarRemoveElement',
-                buttonHeaderRedo: 'redoButton',
-                buttonHeaderUndo: 'undoButton',
-                buttonPaginationPrevious: 'buttonPaginationPrevious',
-                buttonPaginationNext: 'buttonPaginationNext',
-                'FormElement-_ElementToolbar': 'FormElement-_ElementToolbar',
-                'FormElement-_UnknownElement': 'FormElement-_UnknownElement',
-                'FormElement-AdvancedPassword': 'FormElement-AdvancedPassword',
-                'FormElement-Checkbox': 'FormElement-Checkbox',
-                'FormElement-ContentElement': 'FormElement-ContentElement',
-                'FormElement-DatePicker': 'FormElement-DatePicker',
-                'FormElement-Fieldset': 'FormElement-Fieldset',
-                'FormElement-GridContainer': 'FormElement-GridContainer',
-                'FormElement-GridRow': 'FormElement-GridRow',
-                'FormElement-FileUpload': 'FormElement-FileUpload',
-                'FormElement-Hidden': 'FormElement-Hidden',
-                'FormElement-ImageUpload': 'FormElement-ImageUpload',
-                'FormElement-MultiCheckbox': 'FormElement-MultiCheckbox',
-                'FormElement-MultiSelect': 'FormElement-MultiSelect',
-                'FormElement-Page': 'FormElement-Page',
-                'FormElement-Password': 'FormElement-Password',
-                'FormElement-RadioButton': 'FormElement-RadioButton',
-                'FormElement-SingleSelect': 'FormElement-SingleSelect',
-                'FormElement-StaticText': 'FormElement-StaticText',
-                'FormElement-SummaryPage': 'FormElement-SummaryPage',
-                'FormElement-Text': 'FormElement-Text',
-                'FormElement-Textarea': 'FormElement-Textarea',
-                'FormElement-Email': 'FormElement-Email',
-                'FormElement-Url': 'FormElement-Url',
-                'FormElement-Telephone': 'FormElement-Telephone',
-                'FormElement-Number': 'FormElement-Number',
-                formElementIcon: 'elementIcon',
-                iconValidator: 't3-form-icon-validator',
-                multiValueContainer: 'multiValueContainer',
-                paginationTitle: 'paginationTitle',
-                stageHeadline: 'formDefinitionLabel',
-                stagePanel: 'stagePanel',
-                validatorsContainer: 'validatorsContainer',
-                validatorIcon: 'validatorIcon'
-            },
-            isSortable: true
-        };
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _stageDomElement = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(_configuration);
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getViewModel() {
-            return getFormEditorApp().getViewModel();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getCurrentlySelectedFormElement() {
-            return getFormEditorApp().getCurrentlySelectedFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return mixed
-         */
-        function getFormElementDefinition(formElement, formElementDefinitionKey) {
-            return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         * @return string
-         * @return void
-         */
-        function _setTemplateTextContent(domElement, content) {
-            if (getUtility().isNonEmptyString(content)) {
-                $(domElement).text(content);
-            }
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
+], function($, Helper, Icons) {
+  'use strict';
+
+  return (function($, Helper, Icons) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _defaultConfiguration = {
+      domElementClassNames: {
+        formElementIsComposit: 't3-form-element-composit',
+        formElementIsTopLevel: 't3-form-element-toplevel',
+        noNesting: 'mjs-nestedSortable-no-nesting',
+        selected: 'selected',
+        sortable: 'sortable',
+        previewViewPreviewElement: 't3-form-element-preview'
+      },
+      domElementDataAttributeNames: {
+        abstractType: 'data-element-abstract-type',
+        noSorting: 'data-no-sorting'
+      },
+      domElementDataAttributeValues: {
+        abstractViewToolbar: 'elementToolbar',
+        abstractViewToolbarNewElement: 'stageElementToolbarNewElement',
+        abstractViewToolbarNewElementSplitButton: 'stageElementToolbarNewElementSplitButton',
+        abstractViewToolbarNewElementSplitButtonAfter: 'stageElementToolbarNewElementSplitButtonAfter',
+        abstractViewToolbarNewElementSplitButtonInside: 'stageElementToolbarNewElementSplitButtonInside',
+        abstractViewToolbarRemoveElement: 'stageElementToolbarRemoveElement',
+        buttonHeaderRedo: 'redoButton',
+        buttonHeaderUndo: 'undoButton',
+        buttonPaginationPrevious: 'buttonPaginationPrevious',
+        buttonPaginationNext: 'buttonPaginationNext',
+        'FormElement-_ElementToolbar': 'FormElement-_ElementToolbar',
+        'FormElement-_UnknownElement': 'FormElement-_UnknownElement',
+        'FormElement-AdvancedPassword': 'FormElement-AdvancedPassword',
+        'FormElement-Checkbox': 'FormElement-Checkbox',
+        'FormElement-ContentElement': 'FormElement-ContentElement',
+        'FormElement-DatePicker': 'FormElement-DatePicker',
+        'FormElement-Fieldset': 'FormElement-Fieldset',
+        'FormElement-GridContainer': 'FormElement-GridContainer',
+        'FormElement-GridRow': 'FormElement-GridRow',
+        'FormElement-FileUpload': 'FormElement-FileUpload',
+        'FormElement-Hidden': 'FormElement-Hidden',
+        'FormElement-ImageUpload': 'FormElement-ImageUpload',
+        'FormElement-MultiCheckbox': 'FormElement-MultiCheckbox',
+        'FormElement-MultiSelect': 'FormElement-MultiSelect',
+        'FormElement-Page': 'FormElement-Page',
+        'FormElement-Password': 'FormElement-Password',
+        'FormElement-RadioButton': 'FormElement-RadioButton',
+        'FormElement-SingleSelect': 'FormElement-SingleSelect',
+        'FormElement-StaticText': 'FormElement-StaticText',
+        'FormElement-SummaryPage': 'FormElement-SummaryPage',
+        'FormElement-Text': 'FormElement-Text',
+        'FormElement-Textarea': 'FormElement-Textarea',
+        'FormElement-Email': 'FormElement-Email',
+        'FormElement-Url': 'FormElement-Url',
+        'FormElement-Telephone': 'FormElement-Telephone',
+        'FormElement-Number': 'FormElement-Number',
+        formElementIcon: 'elementIcon',
+        iconValidator: 't3-form-icon-validator',
+        multiValueContainer: 'multiValueContainer',
+        paginationTitle: 'paginationTitle',
+        stageHeadline: 'formDefinitionLabel',
+        stagePanel: 'stagePanel',
+        validatorsContainer: 'validatorsContainer',
+        validatorIcon: 'validatorIcon'
+      },
+      isSortable: true
+    };
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _stageDomElement = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(_configuration);
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getViewModel() {
+      return getFormEditorApp().getViewModel();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getCurrentlySelectedFormElement() {
+      return getFormEditorApp().getCurrentlySelectedFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return mixed
+     */
+    function getFormElementDefinition(formElement, formElementDefinitionKey) {
+      return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     * @return string
+     * @return void
+     */
+    function _setTemplateTextContent(domElement, content) {
+      if (getUtility().isNonEmptyString(content)) {
+        $(domElement).text(content);
+      }
+    }
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param object
+     * @return void
+     * @publish view/stage/abstract/render/template/perform
+     */
+    function _renderTemplateDispatcher(formElement, template) {
+      switch (formElement.get('type')) {
+        case 'Checkbox':
+          renderCheckboxTemplate(formElement, template);
+          break;
+        case 'FileUpload':
+        case 'ImageUpload':
+          renderFileUploadTemplates(formElement, template);
+          break;
+        case 'SingleSelect':
+        case 'RadioButton':
+        case 'MultiSelect':
+        case 'MultiCheckbox':
+          renderSelectTemplates(formElement, template);
+          break;
+        case 'Textarea':
+        case 'AdvancedPassword':
+        case 'Password':
+        case 'Text':
+        case 'Email':
+        case 'Url':
+        case 'Telephone':
+        case 'Number':
+        case 'DatePicker':
+          renderSimpleTemplateWithValidators(formElement, template);
+          break;
+        case 'Fieldset':
+        case 'GridContainer':
+        case 'GridRow':
+        case 'SummaryPage':
+        case 'Page':
+        case 'StaticText':
+        case 'Hidden':
+        case 'ContentElement':
+          renderSimpleTemplate(formElement, template);
+          break;
+      }
+      getPublisherSubscriber().publish('view/stage/abstract/render/template/perform', [formElement, template]);
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     * @throws 1478987818
+     */
+    function _renderNestedSortableListItem(formElement) {
+      var childFormElements, childList, listItem, template;
+
+      listItem = $('<li></li>');
+      if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+        listItem.addClass(getHelper().getDomElementClassName('noNesting'));
+      }
+
+      if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
+        listItem.addClass(getHelper().getDomElementClassName('formElementIsTopLevel'));
+      }
+      if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+        listItem.addClass(getHelper().getDomElementClassName('formElementIsComposit'));
+      }
+
+      try {
+        template = getHelper().getTemplate('FormElement-' + formElement.get('type')).clone();
+      } catch (error) {
+        template = getHelper().getTemplate('FormElement-_UnknownElement').clone();
+        assert(
+          template.length,
+          'No template found for element "' + formElement.get('__identifierPath') + '"',
+          1478987818
+        );
+      }
+
+      template = $('<div></div>')
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath'))
+        .append($(template.html()));
+
+      if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+        template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement');
+      }
+      if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
+        template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement');
+      }
+      listItem.append(template);
+
+      _renderTemplateDispatcher(formElement, template);
+
+      childFormElements = formElement.get('renderables');
+      childList = null;
+      if ('array' === $.type(childFormElements)) {
+        childList = $('<ol></ol>');
+        if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
+          childList.addClass(getHelper().getDomElementClassName('sortable'));
         }
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param object
-         * @return void
-         * @publish view/stage/abstract/render/template/perform
-         */
-        function _renderTemplateDispatcher(formElement, template) {
-            switch (formElement.get('type')) {
-                case 'Checkbox':
-                    renderCheckboxTemplate(formElement, template);
-                    break;
-                case 'FileUpload':
-                case 'ImageUpload':
-                    renderFileUploadTemplates(formElement, template);
-                    break;
-                case 'SingleSelect':
-                case 'RadioButton':
-                case 'MultiSelect':
-                case 'MultiCheckbox':
-                    renderSelectTemplates(formElement, template);
-                    break;
-                case 'Textarea':
-                case 'AdvancedPassword':
-                case 'Password':
-                case 'Text':
-                case 'Email':
-                case 'Url':
-                case 'Telephone':
-                case 'Number':
-                case 'DatePicker':
-                    renderSimpleTemplateWithValidators(formElement, template);
-                    break;
-                case 'Fieldset':
-                case 'GridContainer':
-                case 'GridRow':
-                case 'SummaryPage':
-                case 'Page':
-                case 'StaticText':
-                case 'Hidden':
-                case 'ContentElement':
-                    renderSimpleTemplate(formElement, template);
-                    break;
-            }
-            getPublisherSubscriber().publish('view/stage/abstract/render/template/perform', [formElement, template]);
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         * @throws 1478987818
-         */
-        function _renderNestedSortableListItem(formElement) {
-            var childFormElements, childList, listItem, template;
-
-            listItem = $('<li></li>');
-            if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                listItem.addClass(getHelper().getDomElementClassName('noNesting'));
-            }
-
-            if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
-                listItem.addClass(getHelper().getDomElementClassName('formElementIsTopLevel'));
-            }
-            if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                listItem.addClass(getHelper().getDomElementClassName('formElementIsComposit'));
-            }
-
-            try {
-                template = getHelper().getTemplate('FormElement-' + formElement.get('type')).clone();
-            } catch(error) {
-                template = getHelper().getTemplate('FormElement-_UnknownElement').clone();
-                assert(
-                    template.length,
-                    'No template found for element "' + formElement.get('__identifierPath') + '"',
-                    1478987818
-                );
-            }
-
-            template = $('<div></div>')
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath'))
-                .append($(template.html()));
-
-            if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement');
-            }
-            if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
-                template.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement');
-            }
-            listItem.append(template);
-
-            _renderTemplateDispatcher(formElement, template);
-
-            childFormElements = formElement.get('renderables');
-            childList = null;
-            if ('array' === $.type(childFormElements)) {
-                childList = $('<ol></ol>');
-                if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
-                    childList.addClass(getHelper().getDomElementClassName('sortable'));
-                }
-                for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                    childList.append(_renderNestedSortableListItem(childFormElements[i]));
-                }
-            }
-
-            if (childList) {
-                listItem.append(childList);
-            }
-            return listItem;
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @publish view/stage/abstract/dnd/start
-         * @publish view/stage/abstract/dnd/stop
-         * @publish view/stage/abstract/dnd/change
-         * @publish view/stage/abstract/dnd/update
-         */
-        function _addSortableEvents() {
-            $('ol.' + getHelper().getDomElementClassName('sortable'), _stageDomElement).nestedSortable({
-                forcePlaceholderSize: true,
-                handle: 'div'  + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
-                helper:	'clone',
-                items: 'li:not(' + getHelper().getDomElementDataAttribute('noSorting', 'bracesWithKey') + ')',
-                opacity: .6,
-                revert: 250,
-                delay: 200,
-                tolerance: 'pointer',
-                toleranceElement: '> div',
-
-                isAllowed: function (placeholder, placeholderParent, currentItem) {
-                    var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, targetFormElementTypeDefinition;
-
-                    formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(currentItem));
-                    targetFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(placeholderParent));
-                    if (!targetFormElementIdentifierPath) {
-                        targetFormElementIdentifierPath = getFormEditorApp().getCurrentlySelectedPage();
-                    }
-
-                    formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath);
-                    targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath);
-
-                    if (
-                        formElementTypeDefinition['_isGridContainerFormElement']
-                        && (
-                            getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath)
-                            || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath)
-                        )
-                    ) {
-                        return false;
-                    }
-
-                    if (
-                        !formElementTypeDefinition['_isGridContainerFormElement']
-                        && !formElementTypeDefinition['_isGridRowFormElement']
-                        && targetFormElementTypeDefinition['_isGridContainerFormElement']
-                    ) {
-                        return false;
-                    }
-
-                    return true;
-                },
-                start: function(e, o) {
-                    getPublisherSubscriber().publish('view/stage/abstract/dnd/start', [$(o.item), $(o.placeholder)]);
-                },
-                stop: function(e, o) {
-                    getPublisherSubscriber().publish('view/stage/abstract/dnd/stop', [
-                        getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item))
-                    ]);
-                },
-                change: function(e, o) {
-                    var enclosingCompositeFormElement, parentFormElementIdentifierPath;
-
-                    parentFormElementIdentifierPath = getAbstractViewParentFormElementIdentifierPathWithinDomElement($(o.placeholder));
-                    if (parentFormElementIdentifierPath) {
-                        enclosingCompositeFormElement = getFormEditorApp()
-                            .findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath);
-                    }
-                    getPublisherSubscriber().publish('view/stage/abstract/dnd/change', [
-                        $(o.placeholder),
-                        parentFormElementIdentifierPath, enclosingCompositeFormElement
-                    ]);
-                },
-                update: function(e, o) {
-                    var nextFormElementIdentifierPath, movedFormElement, movedFormElementIdentifierPath, parentFormElementIdentifierPath, previousFormElementIdentifierPath;
-
-                    movedFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item));
-                    previousFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'prev');
-                    nextFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'next');
-
-                    getPublisherSubscriber().publish('view/stage/abstract/dnd/update', [
-                        $(o.item),
-                        movedFormElementIdentifierPath,
-                        previousFormElementIdentifierPath,
-                        nextFormElementIdentifierPath
-                    ]);
-                }
-            });
-        };
-
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getStageDomElement() {
-            return _stageDomElement;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         * @throws 1479037151
-         */
-        function buildTitleByFormElement(formElement) {
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getRootFormElement();
-            }
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479037151);
-
-            return $('<span></span>')
-                .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier')));
-        };
-
-        /**
-         * @public
-         *
-         * @param string title
-         * @return void
-         */
-        function setStageHeadline(title) {
-            if (getUtility().isUndefinedOrNull(title)) {
-                title = buildTitleByFormElement();
-            }
-
-            $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title);
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getStagePanelDomElement() {
-            return $(getHelper().getDomElementDataIdentifierSelector('stagePanel'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function renderPagination() {
-            var pageCount;
-
-            pageCount = getRootFormElement().get('renderables').length;
-
-            getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious')));
-            getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext')));
-
-            if (getFormEditorApp().getCurrentlySelectedPageIndex() === 0) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious')));
-            }
-
-            if (pageCount === 1 || getFormEditorApp().getCurrentlySelectedPageIndex() === (pageCount - 1)) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext')));
-            }
-
-            $(getHelper().getDomElementDataIdentifierSelector('paginationTitle')).text(
-                getFormElementDefinition(getRootFormElement(), 'paginationTitle')
-                    .replace('{0}', getFormEditorApp().getCurrentlySelectedPageIndex() + 1)
-                    .replace('{1}', pageCount)
-            );
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function renderUndoRedo() {
-            getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-            getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-
-            if (getFormEditorApp().getCurrentApplicationStatePosition() + 1 >= getFormEditorApp().getCurrentApplicationStates()) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-            }
-            if (getFormEditorApp().getCurrentApplicationStatePosition() === 0) {
-                getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAllFormElementDomElements() {
-            return $(   getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
-                        _stageDomElement
-                    );
-        };
-
-        /* *************************************************************
-         * Abstract stage
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param int
-         * @return object
-         * @throws 1478721208
-         */
-        function renderFormDefinitionPageAsSortableList(pageIndex) {
-            assert(
-                'number' === $.type(pageIndex),
-                'Invalid parameter "pageIndex"',
-                1478721208
-            );
-
-            return $('<ol></ol>')
-                .append(_renderNestedSortableListItem(getRootFormElement().get('renderables')[pageIndex]));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAbstractViewParentFormElementWithinDomElement(element) {
-            return $(element)
-                .parent()
-                .closest('li')
-                .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                .first();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAbstractViewParentFormElementIdentifierPathWithinDomElement(element) {
-            return getAbstractViewParentFormElementWithinDomElement(element)
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAbstractViewFormElementWithinDomElement(element) {
-            return $(element)
-                .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                .first();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAbstractViewFormElementIdentifierPathWithinDomElement(element) {
-            return getAbstractViewFormElementWithinDomElement($(element))
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return string
-         */
-        function getAbstractViewSiblingFormElementIdentifierPathWithinDomElement(element, position) {
-            var formElementIdentifierPath;
-
-            if (getUtility().isUndefinedOrNull(position)) {
-                position = 'prev';
-            }
-            formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement(element);
-            element = (position === 'prev') ? $(element).prev('li') : $(element).next('li');
-            return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]))
-                .first()
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @public
-         *
-         * @param string|object
-         * @return object
-         */
-        function getAbstractViewFormElementDomElement(formElement) {
-            var formElementIdentifierPath;
-
-            if ('string' === $.type(formElement)) {
-                formElementIdentifierPath = formElement;
-            } else {
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath');
-                } else {
-                    formElementIdentifierPath = formElement.get('__identifierPath');
-                }
-            }
-            return $(getHelper()
-                .getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _stageDomElement);
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function removeAllStageToolbars() {
-            $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), _stageDomElement).off().empty().remove();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         * @publish view/insertElements/perform/after
-         * @publish view/insertElements/perform/inside
-         * @throws 1479035778
-         */
-        function createAbstractViewFormElementToolbar(formElement) {
-            var formElementTypeDefinition, template;
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035778);
-
-            formElementTypeDefinition = getFormElementDefinition(formElement);
-            if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                return $();
-            }
-
-            template = getHelper().getTemplate('FormElement-_ElementToolbar').clone();
-            if (!template.length) {
-                return $();
-            }
-
-            template = $($(template.html()));
-
-            getHelper().getTemplatePropertyDomElement('_type', template).text(formElement.get('type'));
-            getHelper().getTemplatePropertyDomElement('_identifier', template).text(formElement.get('identifier'));
-
-            if (formElementTypeDefinition['_isCompositeFormElement']) {
-                getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template));
-
-                $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonAfter'), template).on('click', function(e) {
-                    var disableElementTypes, onlyEnableElementTypes;
-
-                    disableElementTypes = [];
-                    onlyEnableElementTypes = [];
-                    if (formElementTypeDefinition['_isGridRowFormElement']) {
-                        if (getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())) {
-                            onlyEnableElementTypes = ['GridRow'];
-                        } else if (getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement().get('__parentRenderable'))) {
-                            disableElementTypes = ['GridContainer'];
-                        }
-                    } else {
-                        if (
-                            !formElementTypeDefinition['_isGridContainerFormElement']
-                            && (
-                                getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())
-                                || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement())
-                            )
-                        ) {
-                            disableElementTypes = ['GridContainer'];
-                        }
-                    }
-
-                    getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [
-                            'view/insertElements/perform/after',
-                            {
-                                disableElementTypes: disableElementTypes,
-                                onlyEnableElementTypes: onlyEnableElementTypes
-                            }
-                        ]
-                    );
-                });
-                $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) {
-                    var disableElementTypes, onlyEnableElementTypes;
-
-                    disableElementTypes = [];
-                    onlyEnableElementTypes = [];
-                    if (formElementTypeDefinition['_isGridContainerFormElement']) {
-                        onlyEnableElementTypes = ['GridRow'];
-                    } else if (
-                        formElementTypeDefinition['_isGridRowFormElement']
-                        || (
-                            getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())
-                            || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement())
-                        )
-                    ) {
-                        disableElementTypes = ['GridContainer'];
-                    }
-
-                    getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [
-                            'view/insertElements/perform/inside',
-                            {
-                                disableElementTypes: disableElementTypes,
-                                onlyEnableElementTypes: onlyEnableElementTypes
-                            }
-                        ]
-                    );
-                });
-            } else {
-                getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template));
-
-                $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) {
-                    var disableElementTypes;
-
-                    disableElementTypes = [];
-                    if (getFormEditorApp().findEnclosingGridRowFormElement(formElement)) {
-                        disableElementTypes = ['GridContainer'];
-                    }
-
-                    getPublisherSubscriber().publish(
-                        'view/stage/abstract/elementToolbar/button/newElement/clicked', [
-                            'view/insertElements/perform/after',
-                            {
-                                disableElementTypes: disableElementTypes
-                            }
-                        ]
-                    );
-                });
-            }
-
-            $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarRemoveElement'), template).on('click', function(e) {
-                getViewModel().showRemoveFormElementModal();
-            });
-
-            return template;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @param bool
-         * @return void
-         */
-        function createAndAddAbstractViewFormElementToolbar(selectedFormElementDomElement, formElement, useFadeEffect) {
-            var toolbar;
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-
-            if (useFadeEffect) {
-                createAbstractViewFormElementToolbar(formElement).fadeOut(0, function() {
-                    selectedFormElementDomElement.prepend($(this));
-                    $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), selectedFormElementDomElement).fadeIn('fast');
-                });
-            } else {
-                selectedFormElementDomElement.prepend(createAbstractViewFormElementToolbar(formElement));
+        for (var i = 0, len = childFormElements.length; i < len; ++i) {
+          childList.append(_renderNestedSortableListItem(childFormElements[i]));
+        }
+      }
+
+      if (childList) {
+        listItem.append(childList);
+      }
+      return listItem;
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @publish view/stage/abstract/dnd/start
+     * @publish view/stage/abstract/dnd/stop
+     * @publish view/stage/abstract/dnd/change
+     * @publish view/stage/abstract/dnd/update
+     */
+    function _addSortableEvents() {
+      $('ol.' + getHelper().getDomElementClassName('sortable'), _stageDomElement).nestedSortable({
+        forcePlaceholderSize: true,
+        handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
+        helper: 'clone',
+        items: 'li:not(' + getHelper().getDomElementDataAttribute('noSorting', 'bracesWithKey') + ')',
+        opacity: .6,
+        revert: 250,
+        delay: 200,
+        tolerance: 'pointer',
+        toleranceElement: '> div',
+
+        isAllowed: function(placeholder, placeholderParent, currentItem) {
+          var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath,
+            targetFormElementTypeDefinition;
+
+          formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(currentItem));
+          targetFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(placeholderParent));
+          if (!targetFormElementIdentifierPath) {
+            targetFormElementIdentifierPath = getFormEditorApp().getCurrentlySelectedPage();
+          }
+
+          formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath);
+          targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath);
+
+          if (
+            formElementTypeDefinition['_isGridContainerFormElement']
+            && (
+              getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath)
+              || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath)
+            )
+          ) {
+            return false;
+          }
+
+          if (
+            !formElementTypeDefinition['_isGridContainerFormElement']
+            && !formElementTypeDefinition['_isGridRowFormElement']
+            && targetFormElementTypeDefinition['_isGridContainerFormElement']
+          ) {
+            return false;
+          }
+
+          return true;
+        },
+        start: function(e, o) {
+          getPublisherSubscriber().publish('view/stage/abstract/dnd/start', [$(o.item), $(o.placeholder)]);
+        },
+        stop: function(e, o) {
+          getPublisherSubscriber().publish('view/stage/abstract/dnd/stop', [
+            getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item))
+          ]);
+        },
+        change: function(e, o) {
+          var enclosingCompositeFormElement, parentFormElementIdentifierPath;
+
+          parentFormElementIdentifierPath = getAbstractViewParentFormElementIdentifierPathWithinDomElement($(o.placeholder));
+          if (parentFormElementIdentifierPath) {
+            enclosingCompositeFormElement = getFormEditorApp()
+              .findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath);
+          }
+          getPublisherSubscriber().publish('view/stage/abstract/dnd/change', [
+            $(o.placeholder),
+            parentFormElementIdentifierPath, enclosingCompositeFormElement
+          ]);
+        },
+        update: function(e, o) {
+          var nextFormElementIdentifierPath, movedFormElement, movedFormElementIdentifierPath,
+            parentFormElementIdentifierPath, previousFormElementIdentifierPath;
+
+          movedFormElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement($(o.item));
+          previousFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'prev');
+          nextFormElementIdentifierPath = getAbstractViewSiblingFormElementIdentifierPathWithinDomElement($(o.item), 'next');
+
+          getPublisherSubscriber().publish('view/stage/abstract/dnd/update', [
+            $(o.item),
+            movedFormElementIdentifierPath,
+            previousFormElementIdentifierPath,
+            nextFormElementIdentifierPath
+          ]);
+        }
+      });
+    };
+
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getStageDomElement() {
+      return _stageDomElement;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     * @throws 1479037151
+     */
+    function buildTitleByFormElement(formElement) {
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getRootFormElement();
+      }
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479037151);
+
+      return $('<span></span>')
+        .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier')));
+    };
+
+    /**
+     * @public
+     *
+     * @param string title
+     * @return void
+     */
+    function setStageHeadline(title) {
+      if (getUtility().isUndefinedOrNull(title)) {
+        title = buildTitleByFormElement();
+      }
+
+      $(getHelper().getDomElementDataIdentifierSelector('stageHeadline')).html(title);
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getStagePanelDomElement() {
+      return $(getHelper().getDomElementDataIdentifierSelector('stagePanel'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function renderPagination() {
+      var pageCount;
+
+      pageCount = getRootFormElement().get('renderables').length;
+
+      getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious')));
+      getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext')));
+
+      if (getFormEditorApp().getCurrentlySelectedPageIndex() === 0) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationPrevious')));
+      }
+
+      if (pageCount === 1 || getFormEditorApp().getCurrentlySelectedPageIndex() === (pageCount - 1)) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonPaginationNext')));
+      }
+
+      $(getHelper().getDomElementDataIdentifierSelector('paginationTitle')).text(
+        getFormElementDefinition(getRootFormElement(), 'paginationTitle')
+          .replace('{0}', getFormEditorApp().getCurrentlySelectedPageIndex() + 1)
+          .replace('{1}', pageCount)
+      );
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function renderUndoRedo() {
+      getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+      getViewModel().enableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+
+      if (getFormEditorApp().getCurrentApplicationStatePosition() + 1 >= getFormEditorApp().getCurrentApplicationStates()) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+      }
+      if (getFormEditorApp().getCurrentApplicationStatePosition() === 0) {
+        getViewModel().disableButton($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAllFormElementDomElements() {
+      return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
+        _stageDomElement
+      );
+    };
+
+    /* *************************************************************
+     * Abstract stage
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param int
+     * @return object
+     * @throws 1478721208
+     */
+    function renderFormDefinitionPageAsSortableList(pageIndex) {
+      assert(
+        'number' === $.type(pageIndex),
+        'Invalid parameter "pageIndex"',
+        1478721208
+      );
+
+      return $('<ol></ol>')
+        .append(_renderNestedSortableListItem(getRootFormElement().get('renderables')[pageIndex]));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAbstractViewParentFormElementWithinDomElement(element) {
+      return $(element)
+        .parent()
+        .closest('li')
+        .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+        .first();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAbstractViewParentFormElementIdentifierPathWithinDomElement(element) {
+      return getAbstractViewParentFormElementWithinDomElement(element)
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAbstractViewFormElementWithinDomElement(element) {
+      return $(element)
+        .find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+        .first();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAbstractViewFormElementIdentifierPathWithinDomElement(element) {
+      return getAbstractViewFormElementWithinDomElement($(element))
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return string
+     */
+    function getAbstractViewSiblingFormElementIdentifierPathWithinDomElement(element, position) {
+      var formElementIdentifierPath;
+
+      if (getUtility().isUndefinedOrNull(position)) {
+        position = 'prev';
+      }
+      formElementIdentifierPath = getAbstractViewFormElementIdentifierPathWithinDomElement(element);
+      element = (position === 'prev') ? $(element).prev('li') : $(element).next('li');
+      return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+        .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]))
+        .first()
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @public
+     *
+     * @param string|object
+     * @return object
+     */
+    function getAbstractViewFormElementDomElement(formElement) {
+      var formElementIdentifierPath;
+
+      if ('string' === $.type(formElement)) {
+        formElementIdentifierPath = formElement;
+      } else {
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath');
+        } else {
+          formElementIdentifierPath = formElement.get('__identifierPath');
+        }
+      }
+      return $(getHelper()
+        .getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _stageDomElement);
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function removeAllStageToolbars() {
+      $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), _stageDomElement).off().empty().remove();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     * @publish view/insertElements/perform/after
+     * @publish view/insertElements/perform/inside
+     * @throws 1479035778
+     */
+    function createAbstractViewFormElementToolbar(formElement) {
+      var formElementTypeDefinition, template;
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035778);
+
+      formElementTypeDefinition = getFormElementDefinition(formElement);
+      if (formElementTypeDefinition['_isTopLevelFormElement']) {
+        return $();
+      }
+
+      template = getHelper().getTemplate('FormElement-_ElementToolbar').clone();
+      if (!template.length) {
+        return $();
+      }
+
+      template = $($(template.html()));
+
+      getHelper().getTemplatePropertyDomElement('_type', template).text(formElement.get('type'));
+      getHelper().getTemplatePropertyDomElement('_identifier', template).text(formElement.get('identifier'));
+
+      if (formElementTypeDefinition['_isCompositeFormElement']) {
+        getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template));
+
+        $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonAfter'), template).on('click', function(e) {
+          var disableElementTypes, onlyEnableElementTypes;
+
+          disableElementTypes = [];
+          onlyEnableElementTypes = [];
+          if (formElementTypeDefinition['_isGridRowFormElement']) {
+            if (getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())) {
+              onlyEnableElementTypes = ['GridRow'];
+            } else if (getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement().get('__parentRenderable'))) {
+              disableElementTypes = ['GridContainer'];
             }
-
-        };
-
-        /**
-         * @public
-         *
-         * @param int
-         * @param function
-         * @return void
-         * @publish view/stage/dnd/stop
-         * @publish view/stage/element/clicked
-         * @throws 1478169511
-         */
-        function renderAbstractStageArea(pageIndex, callback) {
-            if (getUtility().isUndefinedOrNull(pageIndex)) {
-                pageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
+          } else {
+            if (
+              !formElementTypeDefinition['_isGridContainerFormElement']
+              && (
+                getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())
+                || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement())
+              )
+            ) {
+              disableElementTypes = ['GridContainer'];
             }
-            _stageDomElement.off().empty().append(renderFormDefinitionPageAsSortableList(pageIndex));
-
-            _stageDomElement.on("click", function(e) {
-                var formElementIdentifierPath;
-
-                formElementIdentifierPath = $(e.target)
-                    .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                    .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-                if (
-                    getUtility().isUndefinedOrNull(formElementIdentifierPath)
-                    || !getUtility().isNonEmptyString(formElementIdentifierPath)
-                ) {
-                    return;
-                }
-
-                getPublisherSubscriber().publish('view/stage/element/clicked', [formElementIdentifierPath]);
-            });
+          }
+
+          getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [
+              'view/insertElements/perform/after',
+              {
+                disableElementTypes: disableElementTypes,
+                onlyEnableElementTypes: onlyEnableElementTypes
+              }
+            ]
+          );
+        });
+        $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButtonInside'), template).on('click', function(e) {
+          var disableElementTypes, onlyEnableElementTypes;
+
+          disableElementTypes = [];
+          onlyEnableElementTypes = [];
+          if (formElementTypeDefinition['_isGridContainerFormElement']) {
+            onlyEnableElementTypes = ['GridRow'];
+          } else if (
+            formElementTypeDefinition['_isGridRowFormElement']
+            || (
+              getFormEditorApp().findEnclosingGridContainerFormElement(getCurrentlySelectedFormElement())
+              || getFormEditorApp().findEnclosingGridRowFormElement(getCurrentlySelectedFormElement())
+            )
+          ) {
+            disableElementTypes = ['GridContainer'];
+          }
+
+          getPublisherSubscriber().publish('view/stage/abstract/elementToolbar/button/newElement/clicked', [
+              'view/insertElements/perform/inside',
+              {
+                disableElementTypes: disableElementTypes,
+                onlyEnableElementTypes: onlyEnableElementTypes
+              }
+            ]
+          );
+        });
+      } else {
+        getViewModel().hideComponent($(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElementSplitButton'), template));
+
+        $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarNewElement'), template).on('click', function(e) {
+          var disableElementTypes;
+
+          disableElementTypes = [];
+          if (getFormEditorApp().findEnclosingGridRowFormElement(formElement)) {
+            disableElementTypes = ['GridContainer'];
+          }
+
+          getPublisherSubscriber().publish(
+            'view/stage/abstract/elementToolbar/button/newElement/clicked', [
+              'view/insertElements/perform/after',
+              {
+                disableElementTypes: disableElementTypes
+              }
+            ]
+          );
+        });
+      }
+
+      $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbarRemoveElement'), template).on('click', function(e) {
+        getViewModel().showRemoveFormElementModal();
+      });
+
+      return template;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @param bool
+     * @return void
+     */
+    function createAndAddAbstractViewFormElementToolbar(selectedFormElementDomElement, formElement, useFadeEffect) {
+      var toolbar;
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+
+      if (useFadeEffect) {
+        createAbstractViewFormElementToolbar(formElement).fadeOut(0, function() {
+          selectedFormElementDomElement.prepend($(this));
+          $(getHelper().getDomElementDataIdentifierSelector('abstractViewToolbar'), selectedFormElementDomElement).fadeIn('fast');
+        });
+      } else {
+        selectedFormElementDomElement.prepend(createAbstractViewFormElementToolbar(formElement));
+      }
+
+    };
+
+    /**
+     * @public
+     *
+     * @param int
+     * @param function
+     * @return void
+     * @publish view/stage/dnd/stop
+     * @publish view/stage/element/clicked
+     * @throws 1478169511
+     */
+    function renderAbstractStageArea(pageIndex, callback) {
+      if (getUtility().isUndefinedOrNull(pageIndex)) {
+        pageIndex = getFormEditorApp().getCurrentlySelectedPageIndex();
+      }
+      _stageDomElement.off().empty().append(renderFormDefinitionPageAsSortableList(pageIndex));
+
+      _stageDomElement.on("click", function(e) {
+        var formElementIdentifierPath;
+
+        formElementIdentifierPath = $(e.target)
+          .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+          .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+        if (
+          getUtility().isUndefinedOrNull(formElementIdentifierPath)
+          || !getUtility().isNonEmptyString(formElementIdentifierPath)
+        ) {
+          return;
+        }
 
-            if (_configuration['isSortable']) {
-                _addSortableEvents();
-            }
+        getPublisherSubscriber().publish('view/stage/element/clicked', [formElementIdentifierPath]);
+      });
+
+      if (_configuration['isSortable']) {
+        _addSortableEvents();
+      }
+
+      if ('function' === $.type(callback)) {
+        callback();
+      }
+    };
+
+
+    /* *************************************************************
+     * Preview stage
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param string html
+     * @return void
+     * @throws 1475424409
+     */
+    function renderPreviewStageArea(html) {
+      assert(getUtility().isNonEmptyString(html), 'Invalid parameter "html"', 1475424409);
+
+      _stageDomElement.off().empty().html(html);
+
+      $(':input', _stageDomElement).prop('disabled', 'disabled').on('click dblclick select focus keydown keypress keyup mousedown mouseup', function(e) {
+        return e.preventDefault();
+      });
+
+      $('form', _stageDomElement).submit(function(e) {
+        return e.preventDefault();
+      });
+
+      getAllFormElementDomElements().each(function(i, element) {
+        var formElement, metaLabel;
+
+        formElement = getFormEditorApp()
+          .getFormElementByIdentifierPath($(this).data('elementIdentifierPath'));
+
+        if (
+          !getFormElementDefinition(formElement, '_isTopLevelFormElement')
+          && getFormElementDefinition(formElement, '_isCompositeFormElement')
+          && !getFormElementDefinition(formElement, '_isGridContainerFormElement')
+        ) {
+          $(this).tooltip({
+            title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')',
+            placement: 'rigth'
+          });
+        } else if (
+          !getFormElementDefinition(formElement, '_isTopLevelFormElement')
+          && !getFormElementDefinition(formElement, '_isCompositeFormElement')
+        ) {
+          $(this).tooltip({
+            title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')',
+            placement: 'left'
+          });
+        }
 
-            if ('function' === $.type(callback)) {
-                callback();
+        if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
+          $(this).addClass(getHelper().getDomElementClassName('formElementIsTopLevel'));
+        }
+        if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+          $(this).addClass(getHelper().getDomElementClassName('formElementIsComposit'));
+        }
+      });
+
+    };
+
+    /* *************************************************************
+     * Template rendering
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param template
+     * @param function
+     * @return void
+     */
+    function eachTemplateProperty(formElement, template, callback) {
+      $(getHelper().getDomElementDataAttribute('templateProperty', 'bracesWithKey'), template).each(function(i, element) {
+        var propertyPath, propertyValue;
+
+        propertyPath = $(element).attr(getHelper().getDomElementDataAttribute('templateProperty'));
+        propertyValue = formElement.get(propertyPath);
+
+        if ('function' === $.type(callback)) {
+          callback(propertyPath, propertyValue, element);
+        }
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     * @return object
+     * @return void
+     */
+    function renderCheckboxTemplate(formElement, template) {
+      renderSimpleTemplateWithValidators(formElement, template);
+
+      eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) {
+        if (
+          ('boolean' === $.type(propertyValue) && propertyValue)
+          || propertyValue === 'true'
+          || propertyValue === 1
+          || propertyValue === "1"
+        ) {
+          $(domElement).addClass(getHelper().getDomElementClassName('noNesting'));
+        }
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     * @return object
+     * @return void
+     * @throws 1479035696
+     */
+    function renderSimpleTemplate(formElement, template) {
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035696);
+
+      eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) {
+        _setTemplateTextContent(domElement, propertyValue);
+      });
+
+      Icons.getIcon(
+        getFormElementDefinition(formElement, 'iconIdentifier'),
+        Icons.sizes.small,
+        null,
+        Icons.states.default,
+        Icons.markupIdentifiers.inline
+      ).done(function(icon) {
+        $(getHelper().getDomElementDataIdentifierSelector('formElementIcon'), template)
+          .append($(icon).addClass(getHelper().getDomElementClassName('icon')));
+      });
+
+      getHelper()
+        .getTemplatePropertyDomElement('_type', template)
+        .append(formElement.get('type'));
+      getHelper()
+        .getTemplatePropertyDomElement('_identifier', template)
+        .append(formElement.get('identifier'));
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     * @return object
+     * @return void
+     * @throws 1479035674
+     */
+    function renderSimpleTemplateWithValidators(formElement, template) {
+      var validators, validatorsCountWithoutRequired, validatorsTemplateContent;
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035674);
+
+      renderSimpleTemplate(formElement, template);
+
+      validatorsTemplateContent = $(
+        getHelper().getDomElementDataIdentifierSelector('validatorsContainer'),
+        $(template)
+      ).clone();
+
+      $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)).empty();
+      validators = formElement.get('validators');
+
+      if ('array' === $.type(validators)) {
+        validatorsCountWithoutRequired = 0;
+        if (validators.length > 0) {
+          for (var i = 0, len = validators.length; i < len; ++i) {
+            var collectionElementConfiguration, rowTemplate;
+
+            if ('NotEmpty' === validators[i]['identifier']) {
+              getHelper()
+                .getTemplatePropertyDomElement('_required', template)
+                .text('*');
+              continue;
             }
-        };
-
+            validatorsCountWithoutRequired++;
 
-        /* *************************************************************
-         * Preview stage
-         * ************************************************************/
+            collectionElementConfiguration = getFormEditorApp()
+              .getFormEditorDefinition('validators', validators[i]['identifier']);
+            rowTemplate = $($(validatorsTemplateContent).clone());
 
-        /**
-         * @public
-         *
-         * @param string html
-         * @return void
-         * @throws 1475424409
-         */
-        function renderPreviewStageArea(html) {
-            assert(getUtility().isNonEmptyString(html), 'Invalid parameter "html"', 1475424409);
-
-            _stageDomElement.off().empty().html(html);
+            getHelper()
+              .getTemplatePropertyDomElement('_label', rowTemplate)
+              .append(collectionElementConfiguration['label']);
+            $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template))
+              .append(rowTemplate.html());
+          }
 
-            $(':input', _stageDomElement).prop('disabled', 'disabled').on('click dblclick select focus keydown keypress keyup mousedown mouseup', function(e) {
-                return e.preventDefault();
+          if (validatorsCountWithoutRequired > 0) {
+            Icons.getIcon(
+              getHelper().getDomElementDataAttributeValue('iconValidator'),
+              Icons.sizes.small,
+              null,
+              Icons.states.default,
+              Icons.markupIdentifiers.inline
+            ).done(function(icon) {
+              $(getHelper().getDomElementDataIdentifierSelector('validatorIcon'), $(template))
+                .append($(icon).addClass(getHelper().getDomElementClassName('icon')));
             });
+          }
+        }
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     * @return object
+     * @return void
+     */
+    function renderSelectTemplates(formElement, template) {
+      var appendMultiValue, defaultValue, multiValueTemplateContent, propertyPath, propertyValue;
+
+      multiValueTemplateContent = $(
+        getHelper().getDomElementDataIdentifierSelector('multiValueContainer'),
+        $(template)
+      ).clone();
+      $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty();
+
+      renderSimpleTemplateWithValidators(formElement, template);
+
+      propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
+        .attr(getHelper().getDomElementDataAttribute('templateProperty'));
+
+      propertyValue = formElement.get(propertyPath);
+
+      appendMultiValue = function(label, value, defaultValue) {
+        var isPreselected, rowTemplate;
+
+        isPreselected = false;
+        rowTemplate = $($(multiValueTemplateContent).clone());
+
+        for (var defaultValueKey in defaultValue) {
+          if (!defaultValue.hasOwnProperty(defaultValueKey)) {
+            continue;
+          }
+          if (defaultValue[defaultValueKey] === value) {
+            isPreselected = true;
+            break;
+          }
+        }
 
-            $('form', _stageDomElement).submit(function(e) {
-                return e.preventDefault();
-            });
+        getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label);
 
-            getAllFormElementDomElements().each(function(i, element) {
-                var formElement, metaLabel;
-
-                formElement = getFormEditorApp()
-                    .getFormElementByIdentifierPath($(this).data('elementIdentifierPath'));
-
-                if (
-                    !getFormElementDefinition(formElement, '_isTopLevelFormElement')
-                    && getFormElementDefinition(formElement, '_isCompositeFormElement')
-                    && !getFormElementDefinition(formElement, '_isGridContainerFormElement')
-                ) {
-                    $(this).tooltip({
-                        title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')',
-                        placement : 'rigth'
-                    });
-                } else if (
-                    !getFormElementDefinition(formElement, '_isTopLevelFormElement')
-                    && !getFormElementDefinition(formElement, '_isCompositeFormElement')
-                ) {
-                    $(this).tooltip({
-                        title: 'identifier: ' + formElement.get('identifier') + ' (type: ' + formElement.get('type') + ')',
-                        placement : 'left'
-                    });
-                }
-
-                if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
-                    $(this).addClass(getHelper().getDomElementClassName('formElementIsTopLevel'));
-                }
-                if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                    $(this).addClass(getHelper().getDomElementClassName('formElementIsComposit'));
-                }
-            });
+        if (isPreselected) {
+          getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass(
+            getHelper().getDomElementClassName('selected')
+          );
+        }
 
-        };
-
-        /* *************************************************************
-         * Template rendering
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param template
-         * @param function
-         * @return void
-         */
-        function eachTemplateProperty(formElement, template, callback) {
-            $(getHelper().getDomElementDataAttribute('templateProperty', 'bracesWithKey'), template).each(function(i, element) {
-                var propertyPath, propertyValue;
-
-                propertyPath = $(element).attr(getHelper().getDomElementDataAttribute('templateProperty'));
-                propertyValue = formElement.get(propertyPath);
-
-                if ('function' === $.type(callback)) {
-                    callback(propertyPath, propertyValue, element);
-                }
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         * @return object
-         * @return void
-         */
-        function renderCheckboxTemplate(formElement, template) {
-            renderSimpleTemplateWithValidators(formElement, template);
-
-            eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) {
-                if (
-                    ('boolean' === $.type(propertyValue) && propertyValue)
-                    || propertyValue === 'true'
-                    || propertyValue === 1
-                    || propertyValue === "1"
-                ) {
-                    $(domElement).addClass(getHelper().getDomElementClassName('noNesting'));
-                }
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         * @return object
-         * @return void
-         * @throws 1479035696
-         */
-        function renderSimpleTemplate(formElement, template) {
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035696);
-
-            eachTemplateProperty(formElement, template, function(propertyPath, propertyValue, domElement) {
-                _setTemplateTextContent(domElement, propertyValue);
-            });
+        $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
+          .append(rowTemplate.html());
+      };
 
-            Icons.getIcon(
-                getFormElementDefinition(formElement, 'iconIdentifier'),
-                Icons.sizes.small,
-                null,
-                Icons.states.default,
-                Icons.markupIdentifiers.inline
-            ).done(function(icon) {
-                $(getHelper().getDomElementDataIdentifierSelector('formElementIcon'), template)
-                    .append($(icon).addClass(getHelper().getDomElementClassName('icon')));
-            });
+      defaultValue = formElement.get('defaultValue');
 
-            getHelper()
-                .getTemplatePropertyDomElement('_type', template)
-                .append(formElement.get('type'));
-            getHelper()
-                .getTemplatePropertyDomElement('_identifier', template)
-                .append(formElement.get('identifier'));
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         * @return object
-         * @return void
-         * @throws 1479035674
-         */
-        function renderSimpleTemplateWithValidators(formElement, template) {
-            var validators, validatorsCountWithoutRequired, validatorsTemplateContent;
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1479035674);
-
-            renderSimpleTemplate(formElement, template);
-
-            validatorsTemplateContent = $(
-                getHelper().getDomElementDataIdentifierSelector('validatorsContainer'),
-                $(template)
-            ).clone();
-
-            $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template)).empty();
-            validators = formElement.get('validators');
-
-            if ('array' === $.type(validators)) {
-                validatorsCountWithoutRequired = 0;
-                if (validators.length > 0) {
-                    for (var i = 0, len = validators.length; i < len; ++i) {
-                        var collectionElementConfiguration, rowTemplate;
-
-                        if ('NotEmpty' === validators[i]['identifier']) {
-                            getHelper()
-                                .getTemplatePropertyDomElement('_required', template)
-                                .text('*');
-                            continue;
-                        }
-                        validatorsCountWithoutRequired++;
-
-                        collectionElementConfiguration = getFormEditorApp()
-                            .getFormEditorDefinition('validators', validators[i]['identifier']);
-                        rowTemplate = $($(validatorsTemplateContent).clone());
-
-                        getHelper()
-                            .getTemplatePropertyDomElement('_label', rowTemplate)
-                            .append(collectionElementConfiguration['label']);
-                        $(getHelper().getDomElementDataIdentifierSelector('validatorsContainer'), $(template))
-                            .append(rowTemplate.html());
-                    }
-
-                    if (validatorsCountWithoutRequired > 0) {
-                        Icons.getIcon(
-                            getHelper().getDomElementDataAttributeValue('iconValidator'),
-                            Icons.sizes.small,
-                            null,
-                            Icons.states.default,
-                            Icons.markupIdentifiers.inline
-                        ).done(function(icon) {
-                            $(getHelper().getDomElementDataIdentifierSelector('validatorIcon'), $(template))
-                                .append($(icon).addClass(getHelper().getDomElementClassName('icon')));
-                        });
-                    }
-                }
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         * @return object
-         * @return void
-         */
-        function renderSelectTemplates(formElement, template) {
-            var appendMultiValue, defaultValue, multiValueTemplateContent, propertyPath, propertyValue;
-
-            multiValueTemplateContent = $(
-                getHelper().getDomElementDataIdentifierSelector('multiValueContainer'),
-                $(template)
-            ).clone();
-            $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty();
-
-            renderSimpleTemplateWithValidators(formElement, template);
-
-            propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
-                .attr(getHelper().getDomElementDataAttribute('templateProperty'));
-
-            propertyValue = formElement.get(propertyPath);
-
-            appendMultiValue = function(label, value, defaultValue) {
-                var isPreselected, rowTemplate;
-
-                isPreselected = false;
-                rowTemplate = $($(multiValueTemplateContent).clone());
-
-                for (var defaultValueKey in defaultValue) {
-                    if (!defaultValue.hasOwnProperty(defaultValueKey)) {
-                        continue;
-                    }
-                    if (defaultValue[defaultValueKey] === value) {
-                        isPreselected = true;
-                        break;
-                    }
-                }
-
-                getHelper().getTemplatePropertyDomElement('_label', rowTemplate).append(label);
-
-                if (isPreselected) {
-                    getHelper().getTemplatePropertyDomElement('_label', rowTemplate).addClass(
-                        getHelper().getDomElementClassName('selected')
-                    );
-                }
-
-                $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
-                    .append(rowTemplate.html());
-            };
-
-            defaultValue = formElement.get('defaultValue');
-
-            if (getFormEditorApp().getUtility().isUndefinedOrNull(defaultValue)) {
-                defaultValue = {};
-            } else if ('string' === $.type(defaultValue)) {
-                defaultValue = {0: defaultValue};
-            }
+      if (getFormEditorApp().getUtility().isUndefinedOrNull(defaultValue)) {
+        defaultValue = {};
+      } else if ('string' === $.type(defaultValue)) {
+        defaultValue = {0: defaultValue};
+      }
 
-            if ('object' === $.type(propertyValue)) {
-                for (var propertyValueKey in propertyValue) {
-                    if (!propertyValue.hasOwnProperty(propertyValueKey)) {
-                        continue;
-                    }
-                    appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue);
-                }
-            } else if ('array' === $.type(propertyValue)) {
-                for (var propertyValueKey in propertyValue) {
-                    if (!propertyValue.hasOwnProperty(propertyValueKey)) {
-                        continue;
-                    }
-                    if (getUtility().isUndefinedOrNull(propertyValue[propertyValueKey]['_label'])) {
-                        appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue);
-                    } else {
-                        appendMultiValue(propertyValue[propertyValueKey]['_label'], propertyValue[propertyValueKey]['_value'], defaultValue);
-                    }
-                }
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         * @return object
-         * @return void
-         */
-        function renderFileUploadTemplates(formElement, template) {
-            var appendMultiValue, multiValueTemplateContent, propertyPath, propertyValue;
-
-            multiValueTemplateContent = $(
-                getHelper().getDomElementDataIdentifierSelector('multiValueContainer'),
-                $(template)
-            ).clone();
-            $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty();
-
-            renderSimpleTemplateWithValidators(formElement, template);
-
-            propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
-                .attr(getHelper().getDomElementDataAttribute('templateProperty'));
-            propertyValue = formElement.get(propertyPath);
-
-            appendMultiValue = function(value) {
-                var rowTemplate;
-
-                rowTemplate = $($(multiValueTemplateContent).clone());
-
-                getHelper().getTemplatePropertyDomElement('_value', rowTemplate).append(value);
-                $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
-                    .append(rowTemplate.html());
-            };
-
-            if ('object' === $.type(propertyValue)) {
-                for (var propertyValueKey in propertyValue) {
-                    if (!propertyValue.hasOwnProperty(propertyValueKey)) {
-                        continue;
-                    }
-                    appendMultiValue(propertyValue[propertyValueKey]);
-                }
-            } else if ('array' === $.type(propertyValue)) {
-                for (var i = 0, len = propertyValue.length; i < len; ++i) {
-                    appendMultiValue(propertyValue[i]);
-                }
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @param object
-         * @return this
-         * @throws 1478992119
-         */
-        function bootstrap(formEditorApp, appendToDomElement, configuration) {
-            _formEditorApp = formEditorApp;
-            assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478992119);
-
-            _stageDomElement = $(appendToDomElement);
-            _configuration = $.extend(true, _defaultConfiguration, configuration || {});
-            _helperSetup();
-            return this;
-        };
-
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            bootstrap: bootstrap,
-            buildTitleByFormElement: buildTitleByFormElement,
-            createAndAddAbstractViewFormElementToolbar: createAndAddAbstractViewFormElementToolbar,
-            createAbstractViewFormElementToolbar: createAbstractViewFormElementToolbar,
-            eachTemplateProperty: eachTemplateProperty,
-            getAbstractViewFormElementDomElement: getAbstractViewFormElementDomElement,
-            getAbstractViewFormElementWithinDomElement: getAbstractViewFormElementWithinDomElement,
-            getAbstractViewFormElementIdentifierPathWithinDomElement: getAbstractViewFormElementIdentifierPathWithinDomElement,
-            getAbstractViewParentFormElementWithinDomElement: getAbstractViewParentFormElementWithinDomElement,
-            getAbstractViewParentFormElementIdentifierPathWithinDomElement: getAbstractViewParentFormElementIdentifierPathWithinDomElement,
-            getAbstractViewSiblingFormElementIdentifierPathWithinDomElement: getAbstractViewSiblingFormElementIdentifierPathWithinDomElement,
-            getAllFormElementDomElements: getAllFormElementDomElements,
-            getStageDomElement: getStageDomElement,
-            getStagePanelDomElement: getStagePanelDomElement,
-            removeAllStageToolbars: removeAllStageToolbars,
-            renderAbstractStageArea: renderAbstractStageArea,
-            renderCheckboxTemplate: renderCheckboxTemplate,
-            renderFileUploadTemplates: renderFileUploadTemplates,
-            renderFormDefinitionPageAsSortableList: renderFormDefinitionPageAsSortableList,
-            renderPagination: renderPagination,
-            renderPreviewStageArea: renderPreviewStageArea,
-            renderSelectTemplates: renderSelectTemplates,
-            renderSimpleTemplate: renderSimpleTemplate,
-            renderSimpleTemplateWithValidators: renderSimpleTemplateWithValidators,
-            renderUndoRedo: renderUndoRedo,
-            setStageHeadline: setStageHeadline
-        };
-    })($, Helper, Icons);
+      if ('object' === $.type(propertyValue)) {
+        for (var propertyValueKey in propertyValue) {
+          if (!propertyValue.hasOwnProperty(propertyValueKey)) {
+            continue;
+          }
+          appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue);
+        }
+      } else if ('array' === $.type(propertyValue)) {
+        for (var propertyValueKey in propertyValue) {
+          if (!propertyValue.hasOwnProperty(propertyValueKey)) {
+            continue;
+          }
+          if (getUtility().isUndefinedOrNull(propertyValue[propertyValueKey]['_label'])) {
+            appendMultiValue(propertyValue[propertyValueKey], propertyValueKey, defaultValue);
+          } else {
+            appendMultiValue(propertyValue[propertyValueKey]['_label'], propertyValue[propertyValueKey]['_value'], defaultValue);
+          }
+        }
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     * @return object
+     * @return void
+     */
+    function renderFileUploadTemplates(formElement, template) {
+      var appendMultiValue, multiValueTemplateContent, propertyPath, propertyValue;
+
+      multiValueTemplateContent = $(
+        getHelper().getDomElementDataIdentifierSelector('multiValueContainer'),
+        $(template)
+      ).clone();
+      $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template)).empty();
+
+      renderSimpleTemplateWithValidators(formElement, template);
+
+      propertyPath = $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
+        .attr(getHelper().getDomElementDataAttribute('templateProperty'));
+      propertyValue = formElement.get(propertyPath);
+
+      appendMultiValue = function(value) {
+        var rowTemplate;
+
+        rowTemplate = $($(multiValueTemplateContent).clone());
+
+        getHelper().getTemplatePropertyDomElement('_value', rowTemplate).append(value);
+        $(getHelper().getDomElementDataIdentifierSelector('multiValueContainer'), $(template))
+          .append(rowTemplate.html());
+      };
+
+      if ('object' === $.type(propertyValue)) {
+        for (var propertyValueKey in propertyValue) {
+          if (!propertyValue.hasOwnProperty(propertyValueKey)) {
+            continue;
+          }
+          appendMultiValue(propertyValue[propertyValueKey]);
+        }
+      } else if ('array' === $.type(propertyValue)) {
+        for (var i = 0, len = propertyValue.length; i < len; ++i) {
+          appendMultiValue(propertyValue[i]);
+        }
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @param object
+     * @return this
+     * @throws 1478992119
+     */
+    function bootstrap(formEditorApp, appendToDomElement, configuration) {
+      _formEditorApp = formEditorApp;
+      assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478992119);
+
+      _stageDomElement = $(appendToDomElement);
+      _configuration = $.extend(true, _defaultConfiguration, configuration || {});
+      _helperSetup();
+      return this;
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap,
+      buildTitleByFormElement: buildTitleByFormElement,
+      createAndAddAbstractViewFormElementToolbar: createAndAddAbstractViewFormElementToolbar,
+      createAbstractViewFormElementToolbar: createAbstractViewFormElementToolbar,
+      eachTemplateProperty: eachTemplateProperty,
+      getAbstractViewFormElementDomElement: getAbstractViewFormElementDomElement,
+      getAbstractViewFormElementWithinDomElement: getAbstractViewFormElementWithinDomElement,
+      getAbstractViewFormElementIdentifierPathWithinDomElement: getAbstractViewFormElementIdentifierPathWithinDomElement,
+      getAbstractViewParentFormElementWithinDomElement: getAbstractViewParentFormElementWithinDomElement,
+      getAbstractViewParentFormElementIdentifierPathWithinDomElement: getAbstractViewParentFormElementIdentifierPathWithinDomElement,
+      getAbstractViewSiblingFormElementIdentifierPathWithinDomElement: getAbstractViewSiblingFormElementIdentifierPathWithinDomElement,
+      getAllFormElementDomElements: getAllFormElementDomElements,
+      getStageDomElement: getStageDomElement,
+      getStagePanelDomElement: getStagePanelDomElement,
+      removeAllStageToolbars: removeAllStageToolbars,
+      renderAbstractStageArea: renderAbstractStageArea,
+      renderCheckboxTemplate: renderCheckboxTemplate,
+      renderFileUploadTemplates: renderFileUploadTemplates,
+      renderFormDefinitionPageAsSortableList: renderFormDefinitionPageAsSortableList,
+      renderPagination: renderPagination,
+      renderPreviewStageArea: renderPreviewStageArea,
+      renderSelectTemplates: renderSelectTemplates,
+      renderSimpleTemplate: renderSimpleTemplate,
+      renderSimpleTemplateWithValidators: renderSimpleTemplateWithValidators,
+      renderUndoRedo: renderUndoRedo,
+      setStageHeadline: setStageHeadline
+    };
+  })($, Helper, Icons);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js
index 902125cbeca4..b296c8452ca0 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/TreeComponent.js
@@ -15,674 +15,677 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/TreeComponent
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper',
-        'TYPO3/CMS/Backend/Icons',
-        'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
-        ], function($, Helper, Icons) {
-        'use strict';
-
-    return (function($, Helper, Icons) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _expanderStates = {};
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _defaultConfiguration = {
-            domElementClassNames: {
-                collapsed: 'mjs-nestedSortable-collapsed',
-                expanded: 'mjs-nestedSortable-expanded',
-                hasChildren: 't3-form-element-has-children',
-                sortable: 'sortable',
-                svgLinkWrapper: 'svg-wrapper',
-                noNesting: 'mjs-nestedSortable-no-nesting'
-            },
-            domElementDataAttributeNames: {
-                abstractType: 'data-element-abstract-type'
-            },
-            domElementDataAttributeValues: {
-                collapse: 'actions-pagetree-collapse',
-                expander: 'treeExpander',
-                title: 'treeTitle'
-            },
-            isSortable: true,
-            svgLink: {
-                height: 15,
-                paths: {
-                    angle: 'M0 0 V20 H15',
-                    vertical: 'M0 0 V20 H0',
-                    hidden: 'M0 0 V0 H0'
-                },
-                width: 15
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _treeDomElement = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(_configuration);
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getCurrentlySelectedFormElement() {
-            return getFormEditorApp().getCurrentlySelectedFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return mixed
-         */
-        function getFormElementDefinition(formElement, formElementDefinitionKey) {
-            return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function _getLinkSvg(type) {
-            return $('<span class="' + getHelper().getDomElementClassName('svgLinkWrapper') + '">'
-                       + '<svg version="1.1" width="' + _configuration['svgLink']['width'] + '" height="' + _configuration['svgLink']['height'] + '">'
-                           + '<path class="link" d="' + _configuration['svgLink']['paths'][type] + '">'
-                       + '</svg>'
-                   + '</span>');
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @return object
-         * @publish view/tree/render/listItemAdded
-         * @throws 1478715704
-         */
-        function _renderNestedSortableListItem(formElement) {
-            var childFormElements, childList, expanderItem, isLastFormElementWithinParentFormElement, listItem, listItemContent, searchElement;
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478715704);
-
-            isLastFormElementWithinParentFormElement = false;
-            if (formElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(formElement).get('__identifierPath')) {
-                isLastFormElementWithinParentFormElement = true;
-            }
-
-            listItem = $('<li></li>');
-            if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                listItem.addClass(getHelper().getDomElementClassName('noNesting'));
-            }
-
-            listItemContent = $('<div></div>')
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath'))
-                .append(
-                    $('<span></span>')
-                        .attr(getHelper().getDomElementDataAttribute('identifier'), getHelper().getDomElementDataAttributeValue('title'))
-                        .html(buildTitleByFormElement(formElement))
-                );
-
-            if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement');
-            }
-            if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
-                listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement');
-            }
-
-            expanderItem = $('<span></span>').attr('data-identifier', getHelper().getDomElementDataAttributeValue('expander'));
-            listItemContent.prepend(expanderItem);
-
-            Icons.getIcon(getFormElementDefinition(formElement, 'iconIdentifier'), Icons.sizes.small, null, Icons.states.default).done(function(icon) {
-                expanderItem.after(
-                    $(icon).addClass(getHelper().getDomElementClassName('icon'))
-                        .tooltip({
-                            title: 'identifier: ' + formElement.get('identifier'),
-                            placement: 'right'
-                        })
-                );
-
-                if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                    if (formElement.get('renderables') && formElement.get('renderables').length > 0) {
-                        Icons.getIcon(getHelper().getDomElementDataAttributeValue('collapse'), Icons.sizes.small).done(function(icon) {
-                            expanderItem.before(_getLinkSvg('angle')).html($(icon));
-                            listItem.addClass(getHelper().getDomElementClassName('hasChildren'));
-                        });
-                    } else {
-                        expanderItem.before(_getLinkSvg('angle')).remove();
-                    }
-                } else {
-                    listItemContent.prepend(_getLinkSvg('angle'));
-                    expanderItem.remove();
-                }
-
-                searchElement = formElement.get('__parentRenderable');
-                while (searchElement) {
-                    if (searchElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) {
-                        break;
-                    }
-
-                    if (searchElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(searchElement).get('__identifierPath')) {
-                        listItemContent.prepend(_getLinkSvg('hidden'));
-                    } else {
-                        listItemContent.prepend(_getLinkSvg('vertical'));
-                    }
-                    searchElement = searchElement.get('__parentRenderable');
-                }
-            });
-            listItem.append(listItemContent);
-
-            getPublisherSubscriber().publish('view/tree/render/listItemAdded', [listItem, formElement]);
-            childFormElements = formElement.get('renderables');
-            childList = null;
-            if ('array' === $.type(childFormElements)) {
-                childList = $('<ol></ol>');
-                for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                    childList.append(_renderNestedSortableListItem(childFormElements[i]));
-                }
-            }
-
-            if (childList) {
-                listItem.append(childList);
-            }
-            return listItem;
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @publish view/tree/dnd/stop
-         * @publish view/tree/dnd/change
-         * @publish view/tree/dnd/update
-         */
-        function _addSortableEvents() {
-            $('ol.' + getHelper().getDomElementClassName('sortable'), _treeDomElement).nestedSortable({
-                forcePlaceholderSize: true,
-                protectRoot: true,
-                isTree: true,
-                handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
-                helper: 'clone',
-                items: 'li',
-                opacity: .6,
-                revert: 250,
-                delay: 200,
-                tolerance: 'pointer',
-                toleranceElement: '> div',
-
-                isAllowed: function (placeholder, placeholderParent, currentItem) {
-                    var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath, targetFormElementTypeDefinition;
-
-                    if (typeof placeholderParent === 'undefined') {
-                        return true;
-                    }
-
-                    formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(currentItem));
-                    targetFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(placeholderParent));
-
-                    formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath);
-                    targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath);
-
-                    if (
-                        targetFormElementTypeDefinition['_isTopLevelFormElement']
-                        && !targetFormElementTypeDefinition['_isCompositeFormElement']
-                    ) {
-                        return false;
-                    }
-
-                    if (
-                        formElementTypeDefinition['_isGridContainerFormElement']
-                        && (
-                            getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath)
-                            || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath)
-                        )
-                    ) {
-                        return false;
-                    }
-
-                    if (
-                        !formElementTypeDefinition['_isGridContainerFormElement']
-                        && !formElementTypeDefinition['_isGridRowFormElement']
-                        && targetFormElementTypeDefinition['_isGridContainerFormElement']
-                    ) {
-                        return false;
-                    }
-
-                    return true;
-                },
-                stop: function(e, o) {
-                    getPublisherSubscriber().publish('view/tree/dnd/stop', [getTreeNodeIdentifierPathWithinDomElement($(o.item))]);
-                },
-                change: function(e, o) {
-                    var enclosingCompositeFormElement, parentFormElementIdentifierPath;
-
-                    parentFormElementIdentifierPath = getParentTreeNodeIdentifierPathWithinDomElement($(o.placeholder));
-                    if (parentFormElementIdentifierPath) {
-                        enclosingCompositeFormElement = getFormEditorApp().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath);
-                    }
-                    getPublisherSubscriber().publish('view/tree/dnd/change', [$(o.placeholder), parentFormElementIdentifierPath, enclosingCompositeFormElement]);
-                },
-                update: function(e, o) {
-                    var nextFormElementIdentifierPath, movedFormElementIdentifierPath, previousFormElementIdentifierPath;
-
-                    movedFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(o.item));
-                    previousFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'prev');
-                    nextFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'next');
-
-                    getPublisherSubscriber().publish('view/tree/dnd/update', [$(o.item), movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath]);
-                }
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Form/Backend/Vendor/jquery.mjs.nestedSortable'
+], function($, Helper, Icons) {
+  'use strict';
+
+  return (function($, Helper, Icons) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _expanderStates = {};
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _defaultConfiguration = {
+      domElementClassNames: {
+        collapsed: 'mjs-nestedSortable-collapsed',
+        expanded: 'mjs-nestedSortable-expanded',
+        hasChildren: 't3-form-element-has-children',
+        sortable: 'sortable',
+        svgLinkWrapper: 'svg-wrapper',
+        noNesting: 'mjs-nestedSortable-no-nesting'
+      },
+      domElementDataAttributeNames: {
+        abstractType: 'data-element-abstract-type'
+      },
+      domElementDataAttributeValues: {
+        collapse: 'actions-pagetree-collapse',
+        expander: 'treeExpander',
+        title: 'treeTitle'
+      },
+      isSortable: true,
+      svgLink: {
+        height: 15,
+        paths: {
+          angle: 'M0 0 V20 H15',
+          vertical: 'M0 0 V20 H0',
+          hidden: 'M0 0 V0 H0'
+        },
+        width: 15
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _treeDomElement = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(_configuration);
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getCurrentlySelectedFormElement() {
+      return getFormEditorApp().getCurrentlySelectedFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return mixed
+     */
+    function getFormElementDefinition(formElement, formElementDefinitionKey) {
+      return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function _getLinkSvg(type) {
+      return $('<span class="' + getHelper().getDomElementClassName('svgLinkWrapper') + '">'
+        + '<svg version="1.1" width="' + _configuration['svgLink']['width'] + '" height="' + _configuration['svgLink']['height'] + '">'
+        + '<path class="link" d="' + _configuration['svgLink']['paths'][type] + '">'
+        + '</svg>'
+        + '</span>');
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @return object
+     * @publish view/tree/render/listItemAdded
+     * @throws 1478715704
+     */
+    function _renderNestedSortableListItem(formElement) {
+      var childFormElements, childList, expanderItem, isLastFormElementWithinParentFormElement,
+        listItem, listItemContent, searchElement;
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478715704);
+
+      isLastFormElementWithinParentFormElement = false;
+      if (formElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(formElement).get('__identifierPath')) {
+        isLastFormElementWithinParentFormElement = true;
+      }
+
+      listItem = $('<li></li>');
+      if (!getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+        listItem.addClass(getHelper().getDomElementClassName('noNesting'));
+      }
+
+      listItemContent = $('<div></div>')
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'), formElement.get('__identifierPath'))
+        .append(
+          $('<span></span>')
+            .attr(getHelper().getDomElementDataAttribute('identifier'), getHelper().getDomElementDataAttributeValue('title'))
+            .html(buildTitleByFormElement(formElement))
+        );
+
+      if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+        listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isCompositeFormElement');
+      }
+      if (getFormElementDefinition(formElement, '_isTopLevelFormElement')) {
+        listItemContent.attr(getHelper().getDomElementDataAttribute('abstractType'), 'isTopLevelFormElement');
+      }
+
+      expanderItem = $('<span></span>').attr('data-identifier', getHelper().getDomElementDataAttributeValue('expander'));
+      listItemContent.prepend(expanderItem);
+
+      Icons.getIcon(getFormElementDefinition(formElement, 'iconIdentifier'), Icons.sizes.small, null, Icons.states.default).done(function(icon) {
+        expanderItem.after(
+          $(icon).addClass(getHelper().getDomElementClassName('icon'))
+            .tooltip({
+              title: 'identifier: ' + formElement.get('identifier'),
+              placement: 'right'
+            })
+        );
+
+        if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+          if (formElement.get('renderables') && formElement.get('renderables').length > 0) {
+            Icons.getIcon(getHelper().getDomElementDataAttributeValue('collapse'), Icons.sizes.small).done(function(icon) {
+              expanderItem.before(_getLinkSvg('angle')).html($(icon));
+              listItem.addClass(getHelper().getDomElementClassName('hasChildren'));
             });
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         */
-        function _saveExpanderStates() {
-            var addStates;
-
-            addStates = function(formElement) {
-                var childFormElements, treeNode;
-
-                if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
-                    treeNode = getTreeNode(formElement);
-                    if (treeNode.length) {
-                        if (treeNode.closest('li').hasClass(getHelper().getDomElementClassName('expanded'))) {
-                            _expanderStates[formElement.get('__identifierPath')] = true;
-                        } else {
-                            _expanderStates[formElement.get('__identifierPath')] = false;
-                        }
-                    }
-
-                    if (getUtility().isUndefinedOrNull(_expanderStates[formElement.get('__identifierPath')])) {
-                        _expanderStates[formElement.get('__identifierPath')] = true; 
-                    }
-                }
-
-                childFormElements = formElement.get('renderables');
-                if ('array' === $.type(childFormElements)) {
-                    for (var i = 0, len = childFormElements.length; i < len; ++i) {
-                        addStates(childFormElements[i]);
-                    }
-                }
-            };
-            addStates(getRootFormElement());
-
-            for (var identifierPath in _expanderStates) {
-                if (!_expanderStates.hasOwnProperty(identifierPath)) {
-                    continue;
-                }
-                try {
-                    getFormEditorApp().getFormElementByIdentifierPath(identifierPath);
-                } catch(error) {
-                    delete _expanderStates[identifierPath];
-                }
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         */
-        function _loadExpanderStates() {
-            for (var identifierPath in _expanderStates) {
-                var treeNode;
-
-                if (!_expanderStates.hasOwnProperty(identifierPath)) {
-                    continue;
-                }
-                treeNode = getTreeNode(identifierPath);
-                if (treeNode.length) {
-                    if (_expanderStates[identifierPath]) {
-                        treeNode.closest('li')
-                            .removeClass(getHelper().getDomElementClassName('collapsed'))
-                            .addClass(getHelper().getDomElementClassName('expanded'));
-                    } else {
-                        treeNode.closest('li')
-                            .addClass(getHelper().getDomElementClassName('collapsed'))
-                            .removeClass(getHelper().getDomElementClassName('expanded'));
-                    }
-                }
-            }
-        };
-
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         * @throws 1478721208
-         */
-        function renderCompositeFormElementChildsAsSortableList(formElement) {
-            var elementList;
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478721208);
-
-            elementList = $('<ol></ol>').addClass(getHelper().getDomElementClassName('sortable'));
-            if ('array' === $.type(formElement.get('renderables'))) {
-                for (var i = 0, len = formElement.get('renderables').length; i < len; ++i) {
-                    elementList.append(_renderNestedSortableListItem(formElement.get('renderables')[i]));
-                }
-            }
-            return elementList;
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         * @param object
-         * @publish view/tree/node/clicked
-         */
-        function renew(formElement) {
-            if (getFormEditorApp().getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getRootFormElement();
-            }
-            _saveExpanderStates();
-            _treeDomElement.off().empty().append(renderCompositeFormElementChildsAsSortableList(formElement));
-
-            _treeDomElement.on("click", function(e) {
-                var formElementIdentifierPath;
-
-                formElementIdentifierPath = $(e.target)
-                    .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                    .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-                if (getUtility().isUndefinedOrNull(formElementIdentifierPath) || !getUtility().isNonEmptyString(formElementIdentifierPath)) {
-                    return;
-                }
-                getPublisherSubscriber().publish('view/tree/node/clicked', [formElementIdentifierPath]);
-            });
-
-			$(getHelper().getDomElementDataIdentifierSelector('expander'), _treeDomElement).on('click', function() {
-				$(this).closest('li').toggleClass(getHelper().getDomElementClassName('collapsed')).toggleClass(getHelper().getDomElementClassName('expanded'));
-			});
-
-            if (_configuration['isSortable']) {
-                _addSortableEvents();
-            }
-            _loadExpanderStates();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getAllTreeNodes() {
-            return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), _treeDomElement);
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getTreeNodeWithinDomElement(element) {
-            return $(element).find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getTreeNodeIdentifierPathWithinDomElement(element) {
-            return getTreeNodeWithinDomElement($(element)).attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getParentTreeNodeWithinDomElement(element) {
-            return $(element).parent().closest('li').find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return string
-         */
-        function getParentTreeNodeIdentifierPathWithinDomElement(element) {
-            return getParentTreeNodeWithinDomElement(element).attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @private
-         *
-         * @param object
-         * @param string
-         * @return string
-         */
-        function getSiblingTreeNodeIdentifierPathWithinDomElement(element, position) {
-            var formElementIdentifierPath;
-
-            if (getUtility().isUndefinedOrNull(position)) {
-                position = 'prev';
-            }
-            formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement(element);
-            element = (position === 'prev') ? $(element).prev('li') : $(element).next('li');
-            return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
-                .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]))
-                .first()
-                .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @param object
-         * @return void
-         */
-        function setTreeNodeTitle(title, formElement) {
-            if (getUtility().isUndefinedOrNull(title)) {
-                title = buildTitleByFormElement(formElement);
-            }
-
-            $(getHelper().getDomElementDataIdentifierSelector('title'), getTreeNode(formElement)).html(title);
-        };
-
-        /**
-         * @public
-         *
-         * @param string|object
-         * @return object
-         */
-        function getTreeNode(formElement) {
-            var formElementIdentifierPath;
-
-            if ('string' === $.type(formElement)) {
-                formElementIdentifierPath = formElement;
+          } else {
+            expanderItem.before(_getLinkSvg('angle')).remove();
+          }
+        } else {
+          listItemContent.prepend(_getLinkSvg('angle'));
+          expanderItem.remove();
+        }
+
+        searchElement = formElement.get('__parentRenderable');
+        while (searchElement) {
+          if (searchElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) {
+            break;
+          }
+
+          if (searchElement.get('__identifierPath') === getFormEditorApp().getLastFormElementWithinParentFormElement(searchElement).get('__identifierPath')) {
+            listItemContent.prepend(_getLinkSvg('hidden'));
+          } else {
+            listItemContent.prepend(_getLinkSvg('vertical'));
+          }
+          searchElement = searchElement.get('__parentRenderable');
+        }
+      });
+      listItem.append(listItemContent);
+
+      getPublisherSubscriber().publish('view/tree/render/listItemAdded', [listItem, formElement]);
+      childFormElements = formElement.get('renderables');
+      childList = null;
+      if ('array' === $.type(childFormElements)) {
+        childList = $('<ol></ol>');
+        for (var i = 0, len = childFormElements.length; i < len; ++i) {
+          childList.append(_renderNestedSortableListItem(childFormElements[i]));
+        }
+      }
+
+      if (childList) {
+        listItem.append(childList);
+      }
+      return listItem;
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @publish view/tree/dnd/stop
+     * @publish view/tree/dnd/change
+     * @publish view/tree/dnd/update
+     */
+    function _addSortableEvents() {
+      $('ol.' + getHelper().getDomElementClassName('sortable'), _treeDomElement).nestedSortable({
+        forcePlaceholderSize: true,
+        protectRoot: true,
+        isTree: true,
+        handle: 'div' + getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'),
+        helper: 'clone',
+        items: 'li',
+        opacity: .6,
+        revert: 250,
+        delay: 200,
+        tolerance: 'pointer',
+        toleranceElement: '> div',
+
+        isAllowed: function(placeholder, placeholderParent, currentItem) {
+          var formElementIdentifierPath, formElementTypeDefinition, targetFormElementIdentifierPath,
+            targetFormElementTypeDefinition;
+
+          if (typeof placeholderParent === 'undefined') {
+            return true;
+          }
+
+          formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(currentItem));
+          targetFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(placeholderParent));
+
+          formElementTypeDefinition = getFormElementDefinition(formElementIdentifierPath);
+          targetFormElementTypeDefinition = getFormElementDefinition(targetFormElementIdentifierPath);
+
+          if (
+            targetFormElementTypeDefinition['_isTopLevelFormElement']
+            && !targetFormElementTypeDefinition['_isCompositeFormElement']
+          ) {
+            return false;
+          }
+
+          if (
+            formElementTypeDefinition['_isGridContainerFormElement']
+            && (
+              getFormEditorApp().findEnclosingGridContainerFormElement(targetFormElementIdentifierPath)
+              || getFormEditorApp().findEnclosingGridRowFormElement(targetFormElementIdentifierPath)
+            )
+          ) {
+            return false;
+          }
+
+          if (
+            !formElementTypeDefinition['_isGridContainerFormElement']
+            && !formElementTypeDefinition['_isGridRowFormElement']
+            && targetFormElementTypeDefinition['_isGridContainerFormElement']
+          ) {
+            return false;
+          }
+
+          return true;
+        },
+        stop: function(e, o) {
+          getPublisherSubscriber().publish('view/tree/dnd/stop', [getTreeNodeIdentifierPathWithinDomElement($(o.item))]);
+        },
+        change: function(e, o) {
+          var enclosingCompositeFormElement, parentFormElementIdentifierPath;
+
+          parentFormElementIdentifierPath = getParentTreeNodeIdentifierPathWithinDomElement($(o.placeholder));
+          if (parentFormElementIdentifierPath) {
+            enclosingCompositeFormElement = getFormEditorApp().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(parentFormElementIdentifierPath);
+          }
+          getPublisherSubscriber().publish('view/tree/dnd/change', [$(o.placeholder), parentFormElementIdentifierPath, enclosingCompositeFormElement]);
+        },
+        update: function(e, o) {
+          var nextFormElementIdentifierPath, movedFormElementIdentifierPath,
+            previousFormElementIdentifierPath;
+
+          movedFormElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement($(o.item));
+          previousFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'prev');
+          nextFormElementIdentifierPath = getSiblingTreeNodeIdentifierPathWithinDomElement($(o.item), 'next');
+
+          getPublisherSubscriber().publish('view/tree/dnd/update', [$(o.item), movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath]);
+        }
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _saveExpanderStates() {
+      var addStates;
+
+      addStates = function(formElement) {
+        var childFormElements, treeNode;
+
+        if (getFormElementDefinition(formElement, '_isCompositeFormElement')) {
+          treeNode = getTreeNode(formElement);
+          if (treeNode.length) {
+            if (treeNode.closest('li').hasClass(getHelper().getDomElementClassName('expanded'))) {
+              _expanderStates[formElement.get('__identifierPath')] = true;
             } else {
-                if (getUtility().isUndefinedOrNull(formElement)) {
-                    formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath');
-                } else {
-                    formElementIdentifierPath = formElement.get('__identifierPath');
-                }
-            }
-            return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _treeDomElement);
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         * @throws 1478719287
-         */
-        function buildTitleByFormElement(formElement) {
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
+              _expanderStates[formElement.get('__identifierPath')] = false;
             }
-            assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478719287);
-
-            return $('<span></span>')
-                .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier')))
-                .append($('<small></small>').text("(" + getFormElementDefinition(formElement, 'label') + ")"));
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getTreeDomElement() {
-            return _treeDomElement;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @param object
-         * @return this
-         * @throws 1478714814
-         */
-        function bootstrap(formEditorApp, appendToDomElement, configuration) {
-            _formEditorApp = formEditorApp;
-            assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478714814);
-
-            _treeDomElement = $(appendToDomElement);
-            _configuration = $.extend(true, _defaultConfiguration, configuration || {});
-            _helperSetup();
-            return this;
-        };
-
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            bootstrap: bootstrap,
-            buildTitleByFormElement: buildTitleByFormElement,
-            getAllTreeNodes: getAllTreeNodes,
-            getParentTreeNodeWithinDomElement: getParentTreeNodeWithinDomElement,
-            getParentTreeNodeIdentifierPathWithinDomElement: getParentTreeNodeIdentifierPathWithinDomElement,
-            getSiblingTreeNodeIdentifierPathWithinDomElement: getSiblingTreeNodeIdentifierPathWithinDomElement,
-            getTreeDomElement: getTreeDomElement,
-            getTreeNode: getTreeNode,
-            getTreeNodeWithinDomElement: getTreeNodeWithinDomElement,
-            getTreeNodeIdentifierPathWithinDomElement: getTreeNodeIdentifierPathWithinDomElement,
-            renderCompositeFormElementChildsAsSortableList: renderCompositeFormElementChildsAsSortableList,
-            renew: renew,
-            setTreeNodeTitle: setTreeNodeTitle
-        };
-    })($, Helper, Icons);
+          }
+
+          if (getUtility().isUndefinedOrNull(_expanderStates[formElement.get('__identifierPath')])) {
+            _expanderStates[formElement.get('__identifierPath')] = true;
+          }
+        }
+
+        childFormElements = formElement.get('renderables');
+        if ('array' === $.type(childFormElements)) {
+          for (var i = 0, len = childFormElements.length; i < len; ++i) {
+            addStates(childFormElements[i]);
+          }
+        }
+      };
+      addStates(getRootFormElement());
+
+      for (var identifierPath in _expanderStates) {
+        if (!_expanderStates.hasOwnProperty(identifierPath)) {
+          continue;
+        }
+        try {
+          getFormEditorApp().getFormElementByIdentifierPath(identifierPath);
+        } catch (error) {
+          delete _expanderStates[identifierPath];
+        }
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _loadExpanderStates() {
+      for (var identifierPath in _expanderStates) {
+        var treeNode;
+
+        if (!_expanderStates.hasOwnProperty(identifierPath)) {
+          continue;
+        }
+        treeNode = getTreeNode(identifierPath);
+        if (treeNode.length) {
+          if (_expanderStates[identifierPath]) {
+            treeNode.closest('li')
+              .removeClass(getHelper().getDomElementClassName('collapsed'))
+              .addClass(getHelper().getDomElementClassName('expanded'));
+          } else {
+            treeNode.closest('li')
+              .addClass(getHelper().getDomElementClassName('collapsed'))
+              .removeClass(getHelper().getDomElementClassName('expanded'));
+          }
+        }
+      }
+    };
+
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     * @throws 1478721208
+     */
+    function renderCompositeFormElementChildsAsSortableList(formElement) {
+      var elementList;
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478721208);
+
+      elementList = $('<ol></ol>').addClass(getHelper().getDomElementClassName('sortable'));
+      if ('array' === $.type(formElement.get('renderables'))) {
+        for (var i = 0, len = formElement.get('renderables').length; i < len; ++i) {
+          elementList.append(_renderNestedSortableListItem(formElement.get('renderables')[i]));
+        }
+      }
+      return elementList;
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     * @param object
+     * @publish view/tree/node/clicked
+     */
+    function renew(formElement) {
+      if (getFormEditorApp().getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getRootFormElement();
+      }
+      _saveExpanderStates();
+      _treeDomElement.off().empty().append(renderCompositeFormElementChildsAsSortableList(formElement));
+
+      _treeDomElement.on("click", function(e) {
+        var formElementIdentifierPath;
+
+        formElementIdentifierPath = $(e.target)
+          .closest(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+          .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+        if (getUtility().isUndefinedOrNull(formElementIdentifierPath) || !getUtility().isNonEmptyString(formElementIdentifierPath)) {
+          return;
+        }
+        getPublisherSubscriber().publish('view/tree/node/clicked', [formElementIdentifierPath]);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('expander'), _treeDomElement).on('click', function() {
+        $(this).closest('li').toggleClass(getHelper().getDomElementClassName('collapsed')).toggleClass(getHelper().getDomElementClassName('expanded'));
+      });
+
+      if (_configuration['isSortable']) {
+        _addSortableEvents();
+      }
+      _loadExpanderStates();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getAllTreeNodes() {
+      return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'), _treeDomElement);
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getTreeNodeWithinDomElement(element) {
+      return $(element).find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getTreeNodeIdentifierPathWithinDomElement(element) {
+      return getTreeNodeWithinDomElement($(element)).attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getParentTreeNodeWithinDomElement(element) {
+      return $(element).parent().closest('li').find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey')).first();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return string
+     */
+    function getParentTreeNodeIdentifierPathWithinDomElement(element) {
+      return getParentTreeNodeWithinDomElement(element).attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @private
+     *
+     * @param object
+     * @param string
+     * @return string
+     */
+    function getSiblingTreeNodeIdentifierPathWithinDomElement(element, position) {
+      var formElementIdentifierPath;
+
+      if (getUtility().isUndefinedOrNull(position)) {
+        position = 'prev';
+      }
+      formElementIdentifierPath = getTreeNodeIdentifierPathWithinDomElement(element);
+      element = (position === 'prev') ? $(element).prev('li') : $(element).next('li');
+      return element.find(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKey'))
+        .not(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]))
+        .first()
+        .attr(getHelper().getDomElementDataAttribute('elementIdentifier'));
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @param object
+     * @return void
+     */
+    function setTreeNodeTitle(title, formElement) {
+      if (getUtility().isUndefinedOrNull(title)) {
+        title = buildTitleByFormElement(formElement);
+      }
+
+      $(getHelper().getDomElementDataIdentifierSelector('title'), getTreeNode(formElement)).html(title);
+    };
+
+    /**
+     * @public
+     *
+     * @param string|object
+     * @return object
+     */
+    function getTreeNode(formElement) {
+      var formElementIdentifierPath;
+
+      if ('string' === $.type(formElement)) {
+        formElementIdentifierPath = formElement;
+      } else {
+        if (getUtility().isUndefinedOrNull(formElement)) {
+          formElementIdentifierPath = getCurrentlySelectedFormElement().get('__identifierPath');
+        } else {
+          formElementIdentifierPath = formElement.get('__identifierPath');
+        }
+      }
+      return $(getHelper().getDomElementDataAttribute('elementIdentifier', 'bracesWithKeyValue', [formElementIdentifierPath]), _treeDomElement);
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     * @throws 1478719287
+     */
+    function buildTitleByFormElement(formElement) {
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+      assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478719287);
+
+      return $('<span></span>')
+        .text((formElement.get('label') ? formElement.get('label') : formElement.get('identifier')))
+        .append($('<small></small>').text("(" + getFormElementDefinition(formElement, 'label') + ")"));
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getTreeDomElement() {
+      return _treeDomElement;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @param object
+     * @return this
+     * @throws 1478714814
+     */
+    function bootstrap(formEditorApp, appendToDomElement, configuration) {
+      _formEditorApp = formEditorApp;
+      assert('object' === $.type(appendToDomElement), 'Invalid parameter "appendToDomElement"', 1478714814);
+
+      _treeDomElement = $(appendToDomElement);
+      _configuration = $.extend(true, _defaultConfiguration, configuration || {});
+      _helperSetup();
+      return this;
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap,
+      buildTitleByFormElement: buildTitleByFormElement,
+      getAllTreeNodes: getAllTreeNodes,
+      getParentTreeNodeWithinDomElement: getParentTreeNodeWithinDomElement,
+      getParentTreeNodeIdentifierPathWithinDomElement: getParentTreeNodeIdentifierPathWithinDomElement,
+      getSiblingTreeNodeIdentifierPathWithinDomElement: getSiblingTreeNodeIdentifierPathWithinDomElement,
+      getTreeDomElement: getTreeDomElement,
+      getTreeNode: getTreeNode,
+      getTreeNodeWithinDomElement: getTreeNodeWithinDomElement,
+      getTreeNodeIdentifierPathWithinDomElement: getTreeNodeIdentifierPathWithinDomElement,
+      renderCompositeFormElementChildsAsSortableList: renderCompositeFormElementChildsAsSortableList,
+      renew: renew,
+      setTreeNodeTitle: setTreeNodeTitle
+    };
+  })($, Helper, Icons);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js
index 2ee4e2763d3d..201ef7d193d4 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormEditor/ViewModel.js
@@ -15,1757 +15,1757 @@
  * Module: TYPO3/CMS/Form/Backend/FormEditor/ViewModel
  */
 define(['jquery',
-        'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent',
-        'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent',
-        'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent',
-        'TYPO3/CMS/Form/Backend/FormEditor/StageComponent',
-        'TYPO3/CMS/Form/Backend/FormEditor/Helper',
-        'TYPO3/CMS/Backend/Icons',
-        'TYPO3/CMS/Backend/Notification'
-        ], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
-        'use strict';
-
-    return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _configuration = {
-            domElementClassNames: {
-                formElementIsComposit: 't3-form-element-composit',
-                formElementIsTopLevel: 't3-form-element-toplevel',
-                hasError: 'has-error',
-                headerButtonBar: 'module-docheader-bar-column-left',
-                selectedCompositFormElement: 't3-form-form-composit-element-selected',
-                selectedFormElement: 't3-form-form-element-selected',
-                selectedRootFormElement: 't3-form-root-element-selected',
-                selectedStagePanel: 't3-form-form-stage-selected',
-                sortableHover: 'sortable-hover',
-                stageViewModeAbstract: 't3-form-stage-viewmode-abstract',
-                stageViewModePreview: 't3-form-stage-viewmode-preview',
-                validationErrors: 't3-form-validation-errors',
-                validationChildHasErrors: 't3-form-validation-child-has-error'
-            },
-            domElementDataAttributeNames: {
-                abstractType: 'data-element-abstract-type'
-            },
-            domElementDataAttributeValues: {
-                buttonHeaderClose: 'closeButton',
-                buttonHeaderNewPage: 'headerNewPage',
-                buttonHeaderPaginationNext: 'buttonPaginationNext',
-                buttonHeaderPaginationPrevious: 'buttonPaginationPrevious',
-                buttonHeaderRedo: 'redoButton',
-                buttonHeaderSave: 'saveButton',
-                buttonHeaderSettings: 'formSettingsButton',
-                buttonHeaderUndo: 'undoButton',
-                buttonHeaderViewModeAbstract: 'buttonViewModeAbstract',
-                buttonHeaderViewModePreview: 'buttonViewModePreview',
-                buttonStageNewElementBottom: 'stageNewElementBottom',
-                buttonStructureNewPage: 'treeNewPageBottom',
-                iconMailform: 'content-elements-mailform',
-                iconSave: 'actions-document-save',
-                iconSaveSpinner: 'spinner-circle-dark',
-                inspectorSection: 'inspectorSection',
-                moduleLoadingIndicator: 'moduleLoadingIndicator',
-                moduleWrapper: 'moduleWrapper',
-                stageArea: 'stageArea',
-                stageContainer: 'stageContainer',
-                stageContainerInner: 'stageContainerInner',
-                stageNewElementRow: 'stageNewElementRow',
-                stagePanelHeading: 'panelHeading',
-                stageSection: 'stageSection',
-                structure: 'structure-element',
-                structureSection: 'structureSection',
-                structureRootContainer: 'treeRootContainer',
-                structureRootElement: 'treeRootElement'
-            },
-            panels: {
-                structure: {
-                    width: 300
-                },
-                stage: {
-                    marginLeft: 300,
-                    marginRight: 325,
-                    marginLeftCollapsed: 0,
-                    marginRightCollapsed: -25,
-                    maxWidthPreview: 1000,
-                    maxWidthAbstract: 800
-                },
-                inspector: {
-                    width: 350
-                }
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @var bool
-         */
-        var _previewMode = false;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formEditorApp = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _structureComponent = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _modalsComponent = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _inspectorsComponent = null;
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _stageComponent = null;
-
-        /* *************************************************************
-         * Private Methodes
-         * ************************************************************/
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getRootFormElement() {
-            return getFormEditorApp().getRootFormElement();
-        };
-
-        /**
-         * @private
-         *
-         * @param mixed test
-         * @param string message
-         * @param int messageCode
-         * @return void
-         */
-        function assert(test, message, messageCode) {
-            return getFormEditorApp().assert(test, message, messageCode);
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getUtility() {
-            return getFormEditorApp().getUtility();
-        };
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getCurrentlySelectedFormElement() {
-            return getFormEditorApp().getCurrentlySelectedFormElement();
-        };
-
-
-        /**
-         * @private
-         *
-         * @return object
-         */
-        function getPublisherSubscriber() {
-            return getFormEditorApp().getPublisherSubscriber();
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         */
-        function _addPropertyValidators() {
-            getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) {
-                if (formElement.get(propertyPath) === '') {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) {
-                if (!$.isNumeric(formElement.get(propertyPath))) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('IntegerOrEmpty', function(formElement, propertyPath) {
-                if (formElement.get(propertyPath).length > 0 && !$.isNumeric(formElement.get(propertyPath))) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) {
-                if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) {
-                if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) {
-                var match, regex;
-                regex = /\{([a-z0-9-_]+)?\}/gi;
-                match = regex.exec(formElement.get(propertyPath));
-                if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) {
-                var match, regex;
-                regex = /^\{([a-z0-9-_]+)?\}$/i;
-                match = regex.exec(formElement.get(propertyPath));
-                if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
-                }
-            });
-
-            getFormEditorApp().addPropertyValidationValidator('FileSize', function(formElement, propertyPath) {
-                if (!formElement.get(propertyPath).match(/^(\d*\.?\d+)(B|K|M|G)$/i)) {
-                    return getFormEditorApp().getFormElementPropertyValidatorDefinition('FileSize')['errorMessage'] || 'invalid value';
-                }
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @param object additionalViewModelModules
-         * @return void
-         * @publish view/ready
-         * @throws 1475425785
-         */
-        function _loadAdditionalModules(additionalViewModelModules) {
-            var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules;
-
-            if ('array' !== $.type(additionalViewModelModules)) {
-                return;
-            }
-            additionalViewModelModulesLength = additionalViewModelModules.length;
-
-            if (additionalViewModelModulesLength > 0) {
-                loadedAdditionalViewModelModules = 0;
-                for (var i = 0; i < additionalViewModelModulesLength; ++i) {
-                    require([additionalViewModelModules[i]], function (additionalViewModelModule) {
-                        assert(
-                            'function' === $.type(additionalViewModelModule.bootstrap),
-                            'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"',
-                            1475425785
-                        );
-                        additionalViewModelModule.bootstrap(getFormEditorApp());
-
-                        loadedAdditionalViewModelModules++;
-                        if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) {
-                            getPublisherSubscriber().publish('view/ready');
-                        }
-                    });
-                }
-            } else {
-                getPublisherSubscriber().publish('view/ready');
-            }
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268638
-         */
-        function _helperSetup() {
-            assert('function' === $.type(Helper.bootstrap),
-                'The view model helper does not implement the method "bootstrap"',
-                1478268638
-            );
-
-            Helper.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478268639
-         */
-        function _structureComponentSetup() {
-            assert(
-                'function' === $.type(TreeComponent.bootstrap),
-                'The structure component does not implement the method "bootstrap"',
-                1478268639
-            );
-
-            _structureComponent = TreeComponent.bootstrap(
-                getFormEditorApp(),
-                $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
-                    getHelper().getDomElementDataAttributeValue('structure')
-                ]))
-            );
-
-            $(  getHelper().getDomElementDataIdentifierSelector('iconMailform'),
-                $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer'))
-            ).tooltip({
-                title: 'identifier: ' + getRootFormElement().get('identifier'),
-                placement: 'right'
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478895106
-         */
-        function _modalsComponentSetup() {
-            assert(
-                'function' === $.type(ModalsComponent.bootstrap),
-                'The modals component does not implement the method "bootstrap"',
-                1478895106
-            );
-            _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478895106
-         */
-        function _inspectorsComponentSetup() {
-            assert(
-                'function' === $.type(InspectorComponent.bootstrap),
-                'The inspector component does not implement the method "bootstrap"',
-                1478895106
-            );
-            _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp());
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1478986610
-         */
-        function _stageComponentSetup() {
+  'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent',
+  'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent',
+  'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent',
+  'TYPO3/CMS/Form/Backend/FormEditor/StageComponent',
+  'TYPO3/CMS/Form/Backend/FormEditor/Helper',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification'
+], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
+  'use strict';
+
+  return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _configuration = {
+      domElementClassNames: {
+        formElementIsComposit: 't3-form-element-composit',
+        formElementIsTopLevel: 't3-form-element-toplevel',
+        hasError: 'has-error',
+        headerButtonBar: 'module-docheader-bar-column-left',
+        selectedCompositFormElement: 't3-form-form-composit-element-selected',
+        selectedFormElement: 't3-form-form-element-selected',
+        selectedRootFormElement: 't3-form-root-element-selected',
+        selectedStagePanel: 't3-form-form-stage-selected',
+        sortableHover: 'sortable-hover',
+        stageViewModeAbstract: 't3-form-stage-viewmode-abstract',
+        stageViewModePreview: 't3-form-stage-viewmode-preview',
+        validationErrors: 't3-form-validation-errors',
+        validationChildHasErrors: 't3-form-validation-child-has-error'
+      },
+      domElementDataAttributeNames: {
+        abstractType: 'data-element-abstract-type'
+      },
+      domElementDataAttributeValues: {
+        buttonHeaderClose: 'closeButton',
+        buttonHeaderNewPage: 'headerNewPage',
+        buttonHeaderPaginationNext: 'buttonPaginationNext',
+        buttonHeaderPaginationPrevious: 'buttonPaginationPrevious',
+        buttonHeaderRedo: 'redoButton',
+        buttonHeaderSave: 'saveButton',
+        buttonHeaderSettings: 'formSettingsButton',
+        buttonHeaderUndo: 'undoButton',
+        buttonHeaderViewModeAbstract: 'buttonViewModeAbstract',
+        buttonHeaderViewModePreview: 'buttonViewModePreview',
+        buttonStageNewElementBottom: 'stageNewElementBottom',
+        buttonStructureNewPage: 'treeNewPageBottom',
+        iconMailform: 'content-elements-mailform',
+        iconSave: 'actions-document-save',
+        iconSaveSpinner: 'spinner-circle-dark',
+        inspectorSection: 'inspectorSection',
+        moduleLoadingIndicator: 'moduleLoadingIndicator',
+        moduleWrapper: 'moduleWrapper',
+        stageArea: 'stageArea',
+        stageContainer: 'stageContainer',
+        stageContainerInner: 'stageContainerInner',
+        stageNewElementRow: 'stageNewElementRow',
+        stagePanelHeading: 'panelHeading',
+        stageSection: 'stageSection',
+        structure: 'structure-element',
+        structureSection: 'structureSection',
+        structureRootContainer: 'treeRootContainer',
+        structureRootElement: 'treeRootElement'
+      },
+      panels: {
+        structure: {
+          width: 300
+        },
+        stage: {
+          marginLeft: 300,
+          marginRight: 325,
+          marginLeftCollapsed: 0,
+          marginRightCollapsed: -25,
+          maxWidthPreview: 1000,
+          maxWidthAbstract: 800
+        },
+        inspector: {
+          width: 350
+        }
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @var bool
+     */
+    var _previewMode = false;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formEditorApp = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _structureComponent = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _modalsComponent = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _inspectorsComponent = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _stageComponent = null;
+
+    /* *************************************************************
+     * Private Methodes
+     * ************************************************************/
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getRootFormElement() {
+      return getFormEditorApp().getRootFormElement();
+    };
+
+    /**
+     * @private
+     *
+     * @param mixed test
+     * @param string message
+     * @param int messageCode
+     * @return void
+     */
+    function assert(test, message, messageCode) {
+      return getFormEditorApp().assert(test, message, messageCode);
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getUtility() {
+      return getFormEditorApp().getUtility();
+    };
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getCurrentlySelectedFormElement() {
+      return getFormEditorApp().getCurrentlySelectedFormElement();
+    };
+
+
+    /**
+     * @private
+     *
+     * @return object
+     */
+    function getPublisherSubscriber() {
+      return getFormEditorApp().getPublisherSubscriber();
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _addPropertyValidators() {
+      getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) {
+        if (formElement.get(propertyPath) === '') {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) {
+        if (!$.isNumeric(formElement.get(propertyPath))) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('IntegerOrEmpty', function(formElement, propertyPath) {
+        if (formElement.get(propertyPath).length > 0 && !$.isNumeric(formElement.get(propertyPath))) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) {
+        if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) {
+        if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) {
+        var match, regex;
+        regex = /\{([a-z0-9-_]+)?\}/gi;
+        match = regex.exec(formElement.get(propertyPath));
+        if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) {
+        var match, regex;
+        regex = /^\{([a-z0-9-_]+)?\}$/i;
+        match = regex.exec(formElement.get(propertyPath));
+        if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
+        }
+      });
+
+      getFormEditorApp().addPropertyValidationValidator('FileSize', function(formElement, propertyPath) {
+        if (!formElement.get(propertyPath).match(/^(\d*\.?\d+)(B|K|M|G)$/i)) {
+          return getFormEditorApp().getFormElementPropertyValidatorDefinition('FileSize')['errorMessage'] || 'invalid value';
+        }
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @param object additionalViewModelModules
+     * @return void
+     * @publish view/ready
+     * @throws 1475425785
+     */
+    function _loadAdditionalModules(additionalViewModelModules) {
+      var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules;
+
+      if ('array' !== $.type(additionalViewModelModules)) {
+        return;
+      }
+      additionalViewModelModulesLength = additionalViewModelModules.length;
+
+      if (additionalViewModelModulesLength > 0) {
+        loadedAdditionalViewModelModules = 0;
+        for (var i = 0; i < additionalViewModelModulesLength; ++i) {
+          require([additionalViewModelModules[i]], function(additionalViewModelModule) {
             assert(
-                'function' === $.type(InspectorComponent.bootstrap),
-                'The stage component does not implement the method "bootstrap"',
-                1478986610
+              'function' === $.type(additionalViewModelModule.bootstrap),
+              'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"',
+              1475425785
             );
-            _stageComponent = StageComponent.bootstrap(
-                getFormEditorApp(),
-                $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
-                    getHelper().getDomElementDataAttributeValue('stageArea')
-                ]))
-            );
-
-            getStage().getStagePanelDomElement().on("click", function(e) {
-                if (
-                    $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) ===  getHelper().getDomElementDataAttributeValue('stagePanelHeading')
-                    || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) ===  getHelper().getDomElementDataAttributeValue('stageSection')
-                    || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) ===  getHelper().getDomElementDataAttributeValue('stageArea')
-                ) {
-                    selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex());
-                }
-                getPublisherSubscriber().publish('view/stage/panel/clicked', []);
-            });
-        };
-
-        /**
-         * @private
-         *
-         * @return void
-         * @publish view/header/button/save/clicked
-         * @publish view/stage/abstract/button/newElement/clicked
-         * @publish view/header/button/newPage/clicked
-         * @publish view/structure/button/newPage/clicked
-         * @publish view/header/button/close/clicked
-         */
-        function _buttonsSetup() {
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) {
-                getPublisherSubscriber().publish('view/header/button/save/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/header/formSettings/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) {
-                getPublisherSubscriber().publish(
-                    'view/stage/abstract/button/newElement/clicked', [
-                        'view/insertElements/perform/bottom'
-                    ]
-                );
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) {
-                if (!getFormEditorApp().getUnsavedContent()) {
-                    return;
-                }
-                e.preventDefault();
-                getPublisherSubscriber().publish('view/header/button/close/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/undoButton/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/redoButton/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) {
-                getPublisherSubscriber().publish('view/structure/root/selected');
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/paginationNext/clicked', []);
-            });
-
-            $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) {
-                getPublisherSubscriber().publish('view/paginationPrevious/clicked', []);
-            });
-        };
-
-        /* *************************************************************
-         * Public Methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getFormEditorApp() {
-            return _formEditorApp;
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return object
-         */
-        function getHelper(configuration) {
-            if (getUtility().isUndefinedOrNull(configuration)) {
-                return Helper.setConfiguration(_configuration);
-            }
-            return Helper.setConfiguration(configuration);
-        };
-
-        /**
-         * @public
-         *
-         * @param object formElement
-         * @param string formElementDefinitionKey
-         * @return mixed
-         */
-        function getFormElementDefinition(formElement, formElementDefinitionKey) {
-            return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
-        };
-
-        /**
-         * @public
-         *
-         * @return object (derefernced)
-         */
-        function getConfiguration() {
-            return $.extend(true, {}, _configuration);
-        };
-
-        /**
-         * @public
-         *
-         * @return int
-         */
-        function getPreviewMode() {
-            return _previewMode;
-        };
-
-        /**
-         * @public
-         *
-         * @param bool
-         * @return void
-         */
-        function setPreviewMode(previewMode) {
-            _previewMode = !!previewMode;
-        };
-
-        /* *************************************************************
-         * Structure
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getStructure() {
-            return _structureComponent;
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         * @publish view/structure/renew/postProcess
-         */
-        function renewStructure() {
-            getStructure().renew();
-            getPublisherSubscriber().publish('view/structure/renew/postProcess');
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function addStructureSelection(formElement) {
-            getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function removeStructureSelection(formElement) {
-            getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function removeAllStructureSelections() {
-            $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement())
-                .removeClass(getHelper().getDomElementClassName('selectedFormElement'));
-        };
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getStructureRootElement() {
-            return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
-                getHelper().getDomElementDataAttributeValue('structureRootElement')
-            ]));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function removeStructureRootElementSelection() {
-            $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
-                getHelper().getDomElementDataAttributeValue('structureRootContainer')
-            ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function addStructureRootElementSelection() {
-            $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
-                getHelper().getDomElementDataAttributeValue('structureRootContainer')
-            ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement'));
-        };
-
-        /**
-         * @public
-         *
-         * @param string title
-         * @return void
-         */
-        function setStructureRootElementTitle(title) {
-            if (getUtility().isUndefinedOrNull(title)) {
-                title = $('<span></span>')
-                    .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier')))
-                    .text();
-            }
-            getStructureRootElement().text(title);
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function addStructureValidationResults() {
-            var validationResults;
-
-            getStructure().getAllTreeNodes()
-                .removeClass(getHelper().getDomElementClassName('validationErrors'))
-                .removeClass(getHelper().getDomElementClassName('validationChildHasErrors'));
-
-            removeElementValidationErrorClass(getStructureRootElement());
-
-            validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
-            for (var i = 0, len = validationResults.length; i < len; ++i) {
-                var hasError = false, pathParts, validationElement;
-                for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
-                    if (
-                        validationResults[i]['validationResults'][j]['validationResults']
-                        && validationResults[i]['validationResults'][j]['validationResults'].length > 0
-                    ) {
-                        hasError = true;
-                        break;
-                    }
-                }
-
-                if (hasError) {
-                    if (i === 0) {
-                        setElementValidationErrorClass(getStructureRootElement());
-                    } else {
-                        validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']);
-                        setElementValidationErrorClass(validationElement);
-
-                        pathParts = validationResults[i]['formElementIdentifierPath'].split('/');
-                        while(pathParts.pop()) {
-                            validationElement = getStructure().getTreeNode(pathParts.join('/'));
-                            if ('object' === $.type(validationElement)) {
-                                setElementValidationErrorClass(validationElement, 'validationChildHasErrors');
-                            }
-                        }
-                    }
-                }
-            }
-        };
-
-        /* *************************************************************
-         * Modals
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getModals() {
-            return _modalsComponent
-        };
-
-        /**
-         * @public
-         *
-         * @param object formElement
-         * @return void
-         */
-        function showRemoveFormElementModal(formElement) {
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-            getModals().showRemoveFormElementModal(formElement);
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @param object formElement
-         * @return void
-         */
-        function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) {
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-            getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement);
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function showCloseConfirmationModal() {
-            getModals().showCloseConfirmationModal();
-        };
-
-        /**
-         * @public
-         *
-         * @param string targetEvent
-         * @param object configuration
-         * @return void
-         */
-        function showInsertElementsModal(targetEvent, configuration) {
-            getModals().showInsertElementsModal(targetEvent, configuration);
-        };
-
-        /**
-         * @public
-         *
-         * @param string targetEvent
-         * @return void
-         */
-        function showInsertPagesModal(targetEvent) {
-            getModals().showInsertPagesModal(targetEvent);
-        };
-
-        /**
-         * @public
-         *
-         * @param bool
-         * @return void
-         */
-        function showValidationErrorsModal() {
-            var validationResults;
-            validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
-
-            getModals().showValidationErrorsModal(validationResults);
-        };
-
-        /* *************************************************************
-         * Inspector
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getInspector() {
-            return _inspectorsComponent
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param bool
-         * @return void
-         */
-        function renderInspectorEditors(formElement, useFadeEffect) {
-            var render;
-            if (getUtility().isUndefinedOrNull(useFadeEffect)) {
-                useFadeEffect = true;
-            }
+            additionalViewModelModule.bootstrap(getFormEditorApp());
 
-            /**
-             * @private
-             *
-             * @param function
-             * @return void
-             */
-            render = function(callback) {
-                getInspector().renderEditors(formElement, callback);
-            };
-
-            if (!!useFadeEffect) {
-                getInspector().getInspectorDomElement().fadeOut('fast', function() {
-                    render(function() {
-                        getInspector().getInspectorDomElement().fadeIn('fast');
-                    });
-                });
-            } else {
-                render();
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @param string
-         * @return void
-         */
-        function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) {
-            getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier);
-        };
-
-        /**
-         * @public
-         *
-         * @param string content
-         * @return void
-         */
-        function setInspectorFormElementHeaderEditorContent(content) {
-            getInspector().setFormElementHeaderEditorContent(content);
-        };
-
-        /* *************************************************************
-         * Stage
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return object
-         */
-        function getStage() {
-            return _stageComponent;
-        };
-
-        /**
-         * @public
-         *
-         * @param string title
-         * @return void
-         */
-        function setStageHeadline(title) {
-            getStage().setStageHeadline(title);
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function addStagePanelSelection() {
-            getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function removeStagePanelSelection() {
-            getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function renderPagination() {
-            getStage().renderPagination();
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function renderUndoRedo() {
-            getStage().renderUndoRedo();
-        };
-
-        /**
-         * @public
-         *
-         * @param bool
-         * @param bool
-         * @return void
-         * @publish view/stage/abstract/render/postProcess
-         * @publish view/stage/abstract/render/preProcess
-         */
-        function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) {
-            var render, renderPostProcess;
-
-            $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
-                .animate({
-                    'left': '0px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
-                .animate({
-                    'right': '0px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
-                .animate({
-                    'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
-                    'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
-                .animate({
-                    'max-width': _configuration['panels']['stage']['maxWidthAbstract'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementClassName('headerButtonBar', true))
-                .animate({
-                    'margin-left': _configuration['panels']['structure']['width'] + 'px'
-                }, 'slow');
-
-            if (getUtility().isUndefinedOrNull(useFadeEffect)) {
-                useFadeEffect = true;
-            }
-
-            if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
-                toolbarUseFadeEffect = true;
-            }
-
-            setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
-            removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
-
-            /**
-             * @private
-             *
-             * @param function
-             * @return void
-             */
-            render = function(callback) {
-                $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
-                    .addClass(getHelper().getDomElementClassName('stageViewModeAbstract'))
-                    .removeClass(getHelper().getDomElementClassName('stageViewModePreview'));
-
-                getStage().renderAbstractStageArea(undefined, callback);
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             */
-            renderPostProcess = function() {
-                var formElementTypeDefinition;
-
-                formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
-                getStage().getAllFormElementDomElements().hover(function() {
-                    getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
-                    if (
-                        $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit'))
-                        && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel'))
-                    ) {
-                        $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
-                    }
-                });
-
-                showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
-                if (
-                    formElementTypeDefinition['_isTopLevelFormElement']
-                    && !formElementTypeDefinition['_isCompositeFormElement']
-                    && !getFormEditorApp().isRootFormElementSelected()
-                ) {
-                    hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
-                    hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
-                } else {
-                    showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
-                    showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
-                }
-
-                refreshSelectedElementItemsBatch(toolbarUseFadeEffect);
-                getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
-            };
-
-            if (useFadeEffect) {
-                $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
-                    render(function() {
-                        getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
-                        $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
-                        renderPostProcess();
-                        getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
-                    });
-                });
-            } else {
-                render(function() {
-                    getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
-                    renderPostProcess();
-                    getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
-                });
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string html
-         * @return void
-         * @publish view/stage/preview/render/postProcess
-         */
-        function renderPreviewStageArea(html) {
-            $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
-                .animate({
-                    'left': '-=' + _configuration['panels']['structure']['width'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
-                .animate({
-                    'right': '-=' + _configuration['panels']['inspector']['width'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
-                .animate({
-                    'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px',
-                    'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
-                .animate({
-                    'max-width': _configuration['panels']['stage']['maxWidthPreview'] + 'px'
-                }, 'slow');
-            $(getHelper().getDomElementClassName('headerButtonBar', true))
-                .animate({
-                    'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px'
-                }, 'slow');
-
-            setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
-            removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
-
-            $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
-                $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
-                    .addClass(getHelper().getDomElementClassName('stageViewModePreview'))
-                    .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract'));
-
-                hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
-                hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
-
-                getStage().renderPreviewStageArea(html);
-                $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
-                getPublisherSubscriber().publish('view/stage/preview/render/postProcess');
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function addAbstractViewValidationResults() {
-            var validationResults;
-
-            validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
-            for (var i = 0, len = validationResults.length; i < len; ++i) {
-                var hasError = false, validationElement;
-                for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
-                    if (
-                        validationResults[i]['validationResults'][j]['validationResults']
-                        && validationResults[i]['validationResults'][j]['validationResults'].length > 0
-                    ) {
-                        hasError = true;
-                        break;
-                    }
-                }
-
-                if (hasError) {
-                    if (i > 0) {
-                        validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']);
-                        setElementValidationErrorClass(validationElement);
-                    }
-                }
-            }
-        };
-
-        /* *************************************************************
-         * Form element methods
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param string formElementType
-         * @param string|object referenceFormElement
-         * @param bool
-         * @return object
-         * @publish view/formElement/inserted
-         */
-        function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
-            var newFormElement;
-
-            newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement);
-            if (!!!disablePublishersOnSet) {
-                getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]);
+            loadedAdditionalViewModelModules++;
+            if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) {
+              getPublisherSubscriber().publish('view/ready');
             }
-            return newFormElement;
-        };
-
-        /**
-         * @public
-         *
-         * @param string|object formElementToMove
-         * @param string position
-         * @param string|object referenceFormElement
-         * @param bool
-         * @return object
-         * @publish view/formElement/moved
-         */
-        function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
-            var movedFormElement;
-
-            movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false);
-            if (!!!disablePublishersOnSet) {
-                getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]);
+          });
+        }
+      } else {
+        getPublisherSubscriber().publish('view/ready');
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268638
+     */
+    function _helperSetup() {
+      assert('function' === $.type(Helper.bootstrap),
+        'The view model helper does not implement the method "bootstrap"',
+        1478268638
+      );
+
+      Helper.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478268639
+     */
+    function _structureComponentSetup() {
+      assert(
+        'function' === $.type(TreeComponent.bootstrap),
+        'The structure component does not implement the method "bootstrap"',
+        1478268639
+      );
+
+      _structureComponent = TreeComponent.bootstrap(
+        getFormEditorApp(),
+        $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
+          getHelper().getDomElementDataAttributeValue('structure')
+        ]))
+      );
+
+      $(getHelper().getDomElementDataIdentifierSelector('iconMailform'),
+        $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer'))
+      ).tooltip({
+        title: 'identifier: ' + getRootFormElement().get('identifier'),
+        placement: 'right'
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478895106
+     */
+    function _modalsComponentSetup() {
+      assert(
+        'function' === $.type(ModalsComponent.bootstrap),
+        'The modals component does not implement the method "bootstrap"',
+        1478895106
+      );
+      _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478895106
+     */
+    function _inspectorsComponentSetup() {
+      assert(
+        'function' === $.type(InspectorComponent.bootstrap),
+        'The inspector component does not implement the method "bootstrap"',
+        1478895106
+      );
+      _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp());
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1478986610
+     */
+    function _stageComponentSetup() {
+      assert(
+        'function' === $.type(InspectorComponent.bootstrap),
+        'The stage component does not implement the method "bootstrap"',
+        1478986610
+      );
+      _stageComponent = StageComponent.bootstrap(
+        getFormEditorApp(),
+        $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
+          getHelper().getDomElementDataAttributeValue('stageArea')
+        ]))
+      );
+
+      getStage().getStagePanelDomElement().on("click", function(e) {
+        if (
+          $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stagePanelHeading')
+          || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageSection')
+          || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageArea')
+        ) {
+          selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex());
+        }
+        getPublisherSubscriber().publish('view/stage/panel/clicked', []);
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @publish view/header/button/save/clicked
+     * @publish view/stage/abstract/button/newElement/clicked
+     * @publish view/header/button/newPage/clicked
+     * @publish view/structure/button/newPage/clicked
+     * @publish view/header/button/close/clicked
+     */
+    function _buttonsSetup() {
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) {
+        getPublisherSubscriber().publish('view/header/button/save/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/header/formSettings/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) {
+        getPublisherSubscriber().publish(
+          'view/stage/abstract/button/newElement/clicked', [
+            'view/insertElements/perform/bottom'
+          ]
+        );
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) {
+        if (!getFormEditorApp().getUnsavedContent()) {
+          return;
+        }
+        e.preventDefault();
+        getPublisherSubscriber().publish('view/header/button/close/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/undoButton/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/redoButton/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) {
+        getPublisherSubscriber().publish('view/structure/root/selected');
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/paginationNext/clicked', []);
+      });
+
+      $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) {
+        getPublisherSubscriber().publish('view/paginationPrevious/clicked', []);
+      });
+    };
+
+    /* *************************************************************
+     * Public Methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getFormEditorApp() {
+      return _formEditorApp;
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return object
+     */
+    function getHelper(configuration) {
+      if (getUtility().isUndefinedOrNull(configuration)) {
+        return Helper.setConfiguration(_configuration);
+      }
+      return Helper.setConfiguration(configuration);
+    };
+
+    /**
+     * @public
+     *
+     * @param object formElement
+     * @param string formElementDefinitionKey
+     * @return mixed
+     */
+    function getFormElementDefinition(formElement, formElementDefinitionKey) {
+      return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
+    };
+
+    /**
+     * @public
+     *
+     * @return object (derefernced)
+     */
+    function getConfiguration() {
+      return $.extend(true, {}, _configuration);
+    };
+
+    /**
+     * @public
+     *
+     * @return int
+     */
+    function getPreviewMode() {
+      return _previewMode;
+    };
+
+    /**
+     * @public
+     *
+     * @param bool
+     * @return void
+     */
+    function setPreviewMode(previewMode) {
+      _previewMode = !!previewMode;
+    };
+
+    /* *************************************************************
+     * Structure
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getStructure() {
+      return _structureComponent;
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     * @publish view/structure/renew/postProcess
+     */
+    function renewStructure() {
+      getStructure().renew();
+      getPublisherSubscriber().publish('view/structure/renew/postProcess');
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function addStructureSelection(formElement) {
+      getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function removeStructureSelection(formElement) {
+      getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function removeAllStructureSelections() {
+      $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement())
+        .removeClass(getHelper().getDomElementClassName('selectedFormElement'));
+    };
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getStructureRootElement() {
+      return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
+        getHelper().getDomElementDataAttributeValue('structureRootElement')
+      ]));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function removeStructureRootElementSelection() {
+      $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
+        getHelper().getDomElementDataAttributeValue('structureRootContainer')
+      ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function addStructureRootElementSelection() {
+      $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
+        getHelper().getDomElementDataAttributeValue('structureRootContainer')
+      ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement'));
+    };
+
+    /**
+     * @public
+     *
+     * @param string title
+     * @return void
+     */
+    function setStructureRootElementTitle(title) {
+      if (getUtility().isUndefinedOrNull(title)) {
+        title = $('<span></span>')
+          .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier')))
+          .text();
+      }
+      getStructureRootElement().text(title);
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function addStructureValidationResults() {
+      var validationResults;
+
+      getStructure().getAllTreeNodes()
+        .removeClass(getHelper().getDomElementClassName('validationErrors'))
+        .removeClass(getHelper().getDomElementClassName('validationChildHasErrors'));
+
+      removeElementValidationErrorClass(getStructureRootElement());
+
+      validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
+      for (var i = 0, len = validationResults.length; i < len; ++i) {
+        var hasError = false, pathParts, validationElement;
+        for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
+          if (
+            validationResults[i]['validationResults'][j]['validationResults']
+            && validationResults[i]['validationResults'][j]['validationResults'].length > 0
+          ) {
+            hasError = true;
+            break;
+          }
+        }
+
+        if (hasError) {
+          if (i === 0) {
+            setElementValidationErrorClass(getStructureRootElement());
+          } else {
+            validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']);
+            setElementValidationErrorClass(validationElement);
+
+            pathParts = validationResults[i]['formElementIdentifierPath'].split('/');
+            while (pathParts.pop()) {
+              validationElement = getStructure().getTreeNode(pathParts.join('/'));
+              if ('object' === $.type(validationElement)) {
+                setElementValidationErrorClass(validationElement, 'validationChildHasErrors');
+              }
             }
-            return movedFormElement;
-        };
-
-        /**
-         * @public
-         *
-         * @param object formElement
-         * @param bool
-         * @return object
-         * @publish view/formElement/removed
-         */
-        function removeFormElement(formElement, disablePublishersOnSet) {
-            var parentFormElement;
-
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
+          }
+        }
+      }
+    };
+
+    /* *************************************************************
+     * Modals
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getModals() {
+      return _modalsComponent
+    };
+
+    /**
+     * @public
+     *
+     * @param object formElement
+     * @return void
+     */
+    function showRemoveFormElementModal(formElement) {
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+      getModals().showRemoveFormElementModal(formElement);
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @param object formElement
+     * @return void
+     */
+    function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) {
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+      getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement);
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function showCloseConfirmationModal() {
+      getModals().showCloseConfirmationModal();
+    };
+
+    /**
+     * @public
+     *
+     * @param string targetEvent
+     * @param object configuration
+     * @return void
+     */
+    function showInsertElementsModal(targetEvent, configuration) {
+      getModals().showInsertElementsModal(targetEvent, configuration);
+    };
+
+    /**
+     * @public
+     *
+     * @param string targetEvent
+     * @return void
+     */
+    function showInsertPagesModal(targetEvent) {
+      getModals().showInsertPagesModal(targetEvent);
+    };
+
+    /**
+     * @public
+     *
+     * @param bool
+     * @return void
+     */
+    function showValidationErrorsModal() {
+      var validationResults;
+      validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
+
+      getModals().showValidationErrorsModal(validationResults);
+    };
+
+    /* *************************************************************
+     * Inspector
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getInspector() {
+      return _inspectorsComponent
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param bool
+     * @return void
+     */
+    function renderInspectorEditors(formElement, useFadeEffect) {
+      var render;
+      if (getUtility().isUndefinedOrNull(useFadeEffect)) {
+        useFadeEffect = true;
+      }
+
+      /**
+       * @private
+       *
+       * @param function
+       * @return void
+       */
+      render = function(callback) {
+        getInspector().renderEditors(formElement, callback);
+      };
+
+      if (!!useFadeEffect) {
+        getInspector().getInspectorDomElement().fadeOut('fast', function() {
+          render(function() {
+            getInspector().getInspectorDomElement().fadeIn('fast');
+          });
+        });
+      } else {
+        render();
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @param string
+     * @return void
+     */
+    function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) {
+      getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier);
+    };
+
+    /**
+     * @public
+     *
+     * @param string content
+     * @return void
+     */
+    function setInspectorFormElementHeaderEditorContent(content) {
+      getInspector().setFormElementHeaderEditorContent(content);
+    };
+
+    /* *************************************************************
+     * Stage
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return object
+     */
+    function getStage() {
+      return _stageComponent;
+    };
+
+    /**
+     * @public
+     *
+     * @param string title
+     * @return void
+     */
+    function setStageHeadline(title) {
+      getStage().setStageHeadline(title);
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function addStagePanelSelection() {
+      getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function removeStagePanelSelection() {
+      getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function renderPagination() {
+      getStage().renderPagination();
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function renderUndoRedo() {
+      getStage().renderUndoRedo();
+    };
+
+    /**
+     * @public
+     *
+     * @param bool
+     * @param bool
+     * @return void
+     * @publish view/stage/abstract/render/postProcess
+     * @publish view/stage/abstract/render/preProcess
+     */
+    function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) {
+      var render, renderPostProcess;
+
+      $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
+        .animate({
+          'left': '0px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
+        .animate({
+          'right': '0px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
+        .animate({
+          'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
+          'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
+        .animate({
+          'max-width': _configuration['panels']['stage']['maxWidthAbstract'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementClassName('headerButtonBar', true))
+        .animate({
+          'margin-left': _configuration['panels']['structure']['width'] + 'px'
+        }, 'slow');
+
+      if (getUtility().isUndefinedOrNull(useFadeEffect)) {
+        useFadeEffect = true;
+      }
+
+      if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
+        toolbarUseFadeEffect = true;
+      }
+
+      setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
+      removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
+
+      /**
+       * @private
+       *
+       * @param function
+       * @return void
+       */
+      render = function(callback) {
+        $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
+          .addClass(getHelper().getDomElementClassName('stageViewModeAbstract'))
+          .removeClass(getHelper().getDomElementClassName('stageViewModePreview'));
+
+        getStage().renderAbstractStageArea(undefined, callback);
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       */
+      renderPostProcess = function() {
+        var formElementTypeDefinition;
+
+        formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
+        getStage().getAllFormElementDomElements().hover(function() {
+          getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
+          if (
+            $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit'))
+            && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel'))
+          ) {
+            $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
+          }
+        });
+
+        showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
+        if (
+          formElementTypeDefinition['_isTopLevelFormElement']
+          && !formElementTypeDefinition['_isCompositeFormElement']
+          && !getFormEditorApp().isRootFormElementSelected()
+        ) {
+          hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
+          hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
+        } else {
+          showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
+          showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
+        }
+
+        refreshSelectedElementItemsBatch(toolbarUseFadeEffect);
+        getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
+      };
+
+      if (useFadeEffect) {
+        $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
+          render(function() {
+            getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
+            $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
+            renderPostProcess();
+            getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
+          });
+        });
+      } else {
+        render(function() {
+          getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
+          renderPostProcess();
+          getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
+        });
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string html
+     * @return void
+     * @publish view/stage/preview/render/postProcess
+     */
+    function renderPreviewStageArea(html) {
+      $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
+        .animate({
+          'left': '-=' + _configuration['panels']['structure']['width'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
+        .animate({
+          'right': '-=' + _configuration['panels']['inspector']['width'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
+        .animate({
+          'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px',
+          'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
+        .animate({
+          'max-width': _configuration['panels']['stage']['maxWidthPreview'] + 'px'
+        }, 'slow');
+      $(getHelper().getDomElementClassName('headerButtonBar', true))
+        .animate({
+          'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px'
+        }, 'slow');
+
+      setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
+      removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
+
+      $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
+        $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
+          .addClass(getHelper().getDomElementClassName('stageViewModePreview'))
+          .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract'));
+
+        hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
+        hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
+
+        getStage().renderPreviewStageArea(html);
+        $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
+        getPublisherSubscriber().publish('view/stage/preview/render/postProcess');
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function addAbstractViewValidationResults() {
+      var validationResults;
+
+      validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
+      for (var i = 0, len = validationResults.length; i < len; ++i) {
+        var hasError = false, validationElement;
+        for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
+          if (
+            validationResults[i]['validationResults'][j]['validationResults']
+            && validationResults[i]['validationResults'][j]['validationResults'].length > 0
+          ) {
+            hasError = true;
+            break;
+          }
+        }
+
+        if (hasError) {
+          if (i > 0) {
+            validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']);
+            setElementValidationErrorClass(validationElement);
+          }
+        }
+      }
+    };
+
+    /* *************************************************************
+     * Form element methods
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param string formElementType
+     * @param string|object referenceFormElement
+     * @param bool
+     * @return object
+     * @publish view/formElement/inserted
+     */
+    function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
+      var newFormElement;
+
+      newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement);
+      if (!!!disablePublishersOnSet) {
+        getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]);
+      }
+      return newFormElement;
+    };
+
+    /**
+     * @public
+     *
+     * @param string|object formElementToMove
+     * @param string position
+     * @param string|object referenceFormElement
+     * @param bool
+     * @return object
+     * @publish view/formElement/moved
+     */
+    function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
+      var movedFormElement;
+
+      movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false);
+      if (!!!disablePublishersOnSet) {
+        getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]);
+      }
+      return movedFormElement;
+    };
+
+    /**
+     * @public
+     *
+     * @param object formElement
+     * @param bool
+     * @return object
+     * @publish view/formElement/removed
+     */
+    function removeFormElement(formElement, disablePublishersOnSet) {
+      var parentFormElement;
+
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+
+      if (
+        getFormElementDefinition(formElement, '_isTopLevelFormElement')
+        && getFormElementDefinition(formElement, '_isCompositeFormElement')
+        && getRootFormElement().get('renderables').length === 1
+      ) {
+        Notification.error(
+          getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'),
+          getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'),
+          2
+        );
+      } else {
+        parentFormElement = getFormEditorApp().removeFormElement(formElement, false);
+        if (!!!disablePublishersOnSet) {
+          getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]);
+        }
+      }
+      return parentFormElement;
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @param object formElement
+     * @param object collectionElementConfiguration
+     * @param string referenceCollectionElementIdentifier
+     * @param bool
+     * @return void
+     * @publish view/collectionElement/new/added
+     */
+    function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) {
+      getFormEditorApp().createAndAddPropertyCollectionElement(
+        collectionElementIdentifier,
+        collectionName,
+        formElement,
+        collectionElementConfiguration,
+        referenceCollectionElementIdentifier
+      );
+      if (!!!disablePublishersOnSet) {
+        getPublisherSubscriber().publish('view/collectionElement/new/added', [
+          collectionElementIdentifier,
+          collectionName,
+          formElement,
+          collectionElementConfiguration,
+          referenceCollectionElementIdentifier
+        ]);
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionElementToMove
+     * @param string position
+     * @param string referenceCollectionElement
+     * @param string collectionName
+     * @param object formElement
+     * @param bool
+     * @return void
+     */
+    function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
+      if (getUtility().isUndefinedOrNull(formElement)) {
+        formElement = getCurrentlySelectedFormElement();
+      }
+      getFormEditorApp().movePropertyCollectionElement(
+        collectionElementToMove,
+        position,
+        referenceCollectionElement,
+        collectionName,
+        formElement,
+        false
+      );
+      if (!!!disablePublishersOnSet) {
+        getPublisherSubscriber().publish('view/collectionElement/moved', [
+          collectionElementToMove,
+          position,
+          referenceCollectionElement,
+          collectionName,
+          formElement]
+        );
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param string collectionElementIdentifier
+     * @param string collectionName
+     * @param object formElement
+     * @param bool
+     * @return void
+     * @publish view/collectionElement/removed
+     */
+    function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
+      var collectionElementConfiguration;
+
+      getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement);
+
+      collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
+        collectionElementIdentifier,
+        collectionName
+      );
+      if ('array' === $.type(collectionElementConfiguration['editors'])) {
+        for (var i = 0, len1 = collectionElementConfiguration['editors'].length; i < len1; ++i) {
+          if ('array' === $.type(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'])) {
+            for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'].length; j < len2; ++j) {
+              getCurrentlySelectedFormElement().unset(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'][j], true);
             }
-
-            if (
-                getFormElementDefinition(formElement, '_isTopLevelFormElement')
-                && getFormElementDefinition(formElement, '_isCompositeFormElement')
-                && getRootFormElement().get('renderables').length === 1
-            ) {
-                Notification.error(
-                    getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'),
-                    getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'),
-                    2
-                );
-            } else {
-                parentFormElement = getFormEditorApp().removeFormElement(formElement, false);
-                if (!!!disablePublishersOnSet) {
-                    getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]);
-                }
-            }
-            return parentFormElement;
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @param object formElement
-         * @param object collectionElementConfiguration
-         * @param string referenceCollectionElementIdentifier
-         * @param bool
-         * @return void
-         * @publish view/collectionElement/new/added
-         */
-        function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) {
-            getFormEditorApp().createAndAddPropertyCollectionElement(
-                collectionElementIdentifier,
-                collectionName,
-                formElement,
-                collectionElementConfiguration,
-                referenceCollectionElementIdentifier
-            );
-            if (!!!disablePublishersOnSet) {
-                getPublisherSubscriber().publish('view/collectionElement/new/added', [
-                    collectionElementIdentifier,
-                    collectionName,
-                    formElement,
-                    collectionElementConfiguration,
-                    referenceCollectionElementIdentifier
-                ]);
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionElementToMove
-         * @param string position
-         * @param string referenceCollectionElement
-         * @param string collectionName
-         * @param object formElement
-         * @param bool
-         * @return void
-         */
-        function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
-            if (getUtility().isUndefinedOrNull(formElement)) {
-                formElement = getCurrentlySelectedFormElement();
-            }
-            getFormEditorApp().movePropertyCollectionElement(
-                collectionElementToMove,
-                position,
-                referenceCollectionElement,
-                collectionName,
-                formElement,
-                false
-            );
-            if (!!!disablePublishersOnSet) {
-                getPublisherSubscriber().publish('view/collectionElement/moved', [
-                    collectionElementToMove,
-                    position,
-                    referenceCollectionElement,
-                    collectionName,
-                    formElement]
-                );
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param string collectionElementIdentifier
-         * @param string collectionName
-         * @param object formElement
-         * @param bool
-         * @return void
-         * @publish view/collectionElement/removed
-         */
-        function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
-            var collectionElementConfiguration;
-
-            getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement);
-
-            collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
-                collectionElementIdentifier,
-                collectionName
-            );
-            if ('array' === $.type(collectionElementConfiguration['editors'])) {
-                for (var i = 0, len1 = collectionElementConfiguration['editors'].length; i < len1; ++i) {
-                    if ('array' === $.type(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'])) {
-                        for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'].length; j < len2; ++j) {
-                            getCurrentlySelectedFormElement().unset(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'][j], true);
-                        }
-                    }
-                }
-            }
-
-            if (!!!disablePublishersOnSet) {
-                getPublisherSubscriber().publish('view/collectionElement/removed', [
-                    collectionElementIdentifier,
-                    collectionName,
-                    formElement]
-                );
-            }
-        };
-
-        /* *************************************************************
-         * Batch methodes
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @param bool
-         * @return void
-         */
-        function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) {
-            var formElementTypeDefinition, selectedElement;
-
-            if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
-                toolbarUseFadeEffect = true;
-            }
-
-            formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
-
-            getStage().removeAllStageToolbars();
-            removeAllStageElementSelectionsBatch();
-            removeAllStructureSelections();
-
-            if (!getFormEditorApp().isRootFormElementSelected()) {
-                removeStructureRootElementSelection();
-                addStructureSelection();
-
-                selectedElement = getStage().getAbstractViewFormElementDomElement();
-
-                if (formElementTypeDefinition['_isTopLevelFormElement']) {
-                    addStagePanelSelection();
-                } else {
-                    selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement'));
-                    getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect);
-                }
-
-                getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
-                if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) {
-                    selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
-                }
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param int
-         * @return void
-         * @throws 1478651732
-         * @throws 1478651733
-         * @throws 1478651734
-         */
-        function selectPageBatch(pageIndex) {
-            assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732);
-            assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733);
-            assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734);
-
-            getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]);
-            renewStructure();
-            renderPagination()
-            refreshSelectedElementItemsBatch();
-            renderInspectorEditors();
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function removeAllStageElementSelectionsBatch() {
-            getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement'));
-            removeStagePanelSelection();
-            getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function onViewReadyBatch() {
-            $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
-                .css({
-                    width: _configuration['panels']['structure']['width'] + 'px',
-                    left: '-=' + _configuration['panels']['structure']['width'] + 'px'
-                });
-            $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
-                .css({
-                    width: _configuration['panels']['inspector']['width'] + 'px',
-                    right: '-=' + _configuration['panels']['inspector']['width'] + 'px'
-                });
-
-            $(getHelper().getDomElementClassName('headerButtonBar', true))
-                .css({
-                    'margin-left': _configuration['panels']['structure']['width'] + 'px'
-                });
-
-            $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
-                .css({
-                    'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
-                    'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
-                });
-
-            hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
-            hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
-
-            setStageHeadline();
-            setStructureRootElementTitle();
-            renderAbstractStageArea(false);
-            renewStructure();
-            addStructureRootElementSelection();
-            renderInspectorEditors();
-            renderPagination();
-
-            hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
-            showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
-            setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param object
-         * @return void
-         */
-        function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) {
-            draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @param object
-         * @return void
-         */
-        function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
-            getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
-            if (enclosingCompositeFormElement) {
-                getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @param string
-         * @param string
-         * @return void
-         * @throws 1472502237
-         */
-        function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
-            var movedFormElement, parentFormElementIdentifierPath;
-            if (nextFormElementIdentifierPath) {
-                movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
-            } else if (previousFormElementIdentifierPath) {
-                movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
-            } else {
-                parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement);
-                if (parentFormElementIdentifierPath) {
-                    movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
-                } else {
-                    assert(false, 'Next element, previous or parent element need to be set.', 1472502237);
-                }
-            }
-
-            getStage()
-                .getAbstractViewFormElementWithinDomElement(movedDomElement)
-                .attr(
-                    getHelper().getDomElementDataAttribute('elementIdentifier'),
-                    movedFormElement.get('__identifierPath')
-                );
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @param object
-         * @return void
-         */
-        function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
-            getStructure()
-                .getAllTreeNodes()
-                .parent()
-                .removeClass(getHelper().getDomElementClassName('sortableHover'));
-
-            getStage()
-                .getAllFormElementDomElements()
-                .parent()
-                .removeClass(getHelper().getDomElementClassName('sortableHover'));
-
-            if (enclosingCompositeFormElement) {
-                getStructure()
-                    .getParentTreeNodeWithinDomElement(placeholderDomElement)
-                    .parent()
-                    .addClass(getHelper().getDomElementClassName('sortableHover'));
-
-                getStage()
-                    .getAbstractViewFormElementDomElement(enclosingCompositeFormElement)
-                    .parent()
-                    .addClass(getHelper().getDomElementClassName('sortableHover'));
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @param string
-         * @param string
-         * @return void
-         * @throws 1479048646
-         */
-        function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
-            var movedFormElement, parentFormElementIdentifierPath;
-            if (nextFormElementIdentifierPath) {
-                movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
-            } else if (previousFormElementIdentifierPath) {
-                movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
-            } else {
-                parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement);
-                if (parentFormElementIdentifierPath) {
-                    movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
-                } else {
-                    getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646);
-                }
-            }
-
-            getStructure()
-                .getTreeNodeWithinDomElement(movedDomElement)
-                .attr(
-                    getHelper().getDomElementDataAttribute('elementIdentifier'),
-                    movedFormElement.get('__identifierPath')
-                );
-        };
-
-        /* *************************************************************
-         * Misc
-         * ************************************************************/
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function closeEditor() {
-            document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href');
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @return void
-         */
-        function setElementValidationErrorClass(element, classIdentifier) {
-            if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
-                element.addClass(getHelper().getDomElementClassName('validationErrors'));
-            } else {
-                element.addClass(getHelper().getDomElementClassName(classIdentifier));
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @param string
-         * @return void
-         */
-        function removeElementValidationErrorClass(element, classIdentifier) {
-            if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
-                element.removeClass(getHelper().getDomElementClassName('validationErrors'));
-            } else {
-                element.removeClass(getHelper().getDomElementClassName(classIdentifier));
-            }
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function showComponent(element) {
-            element.removeClass(getHelper().getDomElementClassName('hidden')).show();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function hideComponent(element) {
-            element.addClass(getHelper().getDomElementClassName('hidden')).hide();
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function enableButton(buttonElement) {
-            buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function disableButton(buttonElement) {
-            buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function setButtonActive(buttonElement) {
-            buttonElement.addClass(getHelper().getDomElementClassName('active'));
-        };
-
-        /**
-         * @public
-         *
-         * @param object
-         * @return void
-         */
-        function removeButtonActive(buttonElement) {
-            buttonElement.removeClass(getHelper().getDomElementClassName('active'));
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function showSaveButtonSpinnerIcon() {
-            Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) {
-                $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup));
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function showSaveButtonSaveIcon() {
-            Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) {
-                $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup));
-            });
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function showSaveSuccessMessage() {
-            Notification.success(
-                getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'),
-                getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'),
-                2
-            );
-        };
-
-        /**
-         * @public
-         *
-         * @return void
-         */
-        function showSaveErrorMessage(response) {
-            Notification.error(
-                getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'),
-                getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') +
-                  " " +
-                  response.message
-            );
-        };
-
-        /**
-         * @public
-         *
-         * @param string
-         * @param string
-         * @return void
-         */
-        function showErrorFlashMessage(title, message) {
-            Notification.error(title, message, 2);
-        };
-
-        /**
-         * @public
-         *
-         * @param object formEditorApp
-         * @param object additionalViewModelModules
-         * @return void
-         */
-        function bootstrap(formEditorApp, additionalViewModelModules) {
-            _formEditorApp = formEditorApp;
-
-            _helperSetup();
-            _structureComponentSetup();
-            _modalsComponentSetup();
-            _inspectorsComponentSetup();
-            _stageComponentSetup();
-            _buttonsSetup();
-            _addPropertyValidators();
-            _loadAdditionalModules(additionalViewModelModules);
-        };
-
-        /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
-         */
-        return {
-            addAbstractViewValidationResults: addAbstractViewValidationResults,
-            addStagePanelSelection: addStagePanelSelection,
-            addStructureRootElementSelection: addStructureRootElementSelection,
-            addStructureSelection: addStructureSelection,
-            addStructureValidationResults: addStructureValidationResults,
-            bootstrap: bootstrap,
-            closeEditor: closeEditor,
-            createAndAddFormElement: createAndAddFormElement,
-            createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
-            disableButton: disableButton,
-            enableButton: enableButton,
-            getConfiguration: getConfiguration,
-            getFormEditorApp: getFormEditorApp,
-            getFormElementDefinition: getFormElementDefinition,
-            getHelper: getHelper,
-            getInspector: getInspector,
-            getModals: getModals,
-            getPreviewMode: getPreviewMode,
-            getStage: getStage,
-            getStructure: getStructure,
-            getStructureRootElement: getStructureRootElement,
-            hideComponent: hideComponent,
-            moveFormElement: moveFormElement,
-            movePropertyCollectionElement: movePropertyCollectionElement,
-            onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch,
-            onAbstractViewDndStartBatch: onAbstractViewDndStartBatch,
-            onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch,
-            onStructureDndChangeBatch: onStructureDndChangeBatch,
-            onStructureDndUpdateBatch: onStructureDndUpdateBatch,
-            onViewReadyBatch: onViewReadyBatch,
-            refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch,
-            removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch,
-            removeAllStructureSelections: removeAllStructureSelections,
-            removeButtonActive: removeButtonActive,
-            removeElementValidationErrorClass: removeElementValidationErrorClass,
-            removeFormElement: removeFormElement,
-            removePropertyCollectionElement: removePropertyCollectionElement,
-            removeStagePanelSelection: removeStagePanelSelection,
-            removeStructureRootElementSelection: removeStructureRootElementSelection,
-            removeStructureSelection: removeStructureSelection,
-            renderAbstractStageArea: renderAbstractStageArea,
-            renderInspectorEditors: renderInspectorEditors,
-            renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors,
-            renderPagination: renderPagination,
-            renderPreviewStageArea: renderPreviewStageArea,
-            renewStructure: renewStructure,
-            renderUndoRedo: renderUndoRedo,
-            selectPageBatch: selectPageBatch,
-            setButtonActive: setButtonActive,
-            setElementValidationErrorClass: setElementValidationErrorClass,
-            setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent,
-            setPreviewMode: setPreviewMode,
-            setStageHeadline: setStageHeadline,
-            setStructureRootElementTitle: setStructureRootElementTitle,
-            showCloseConfirmationModal: showCloseConfirmationModal,
-            showComponent: showComponent,
-            showErrorFlashMessage: showErrorFlashMessage,
-            showInsertElementsModal: showInsertElementsModal,
-            showInsertPagesModal: showInsertPagesModal,
-            showRemoveFormElementModal: showRemoveFormElementModal,
-            showRemoveCollectionElementModal: showRemoveCollectionElementModal,
-            showSaveButtonSaveIcon: showSaveButtonSaveIcon,
-            showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon,
-            showSaveSuccessMessage: showSaveSuccessMessage,
-            showSaveErrorMessage: showSaveErrorMessage,
-            showValidationErrorsModal: showValidationErrorsModal
-        };
-    })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification);
+          }
+        }
+      }
+
+      if (!!!disablePublishersOnSet) {
+        getPublisherSubscriber().publish('view/collectionElement/removed', [
+          collectionElementIdentifier,
+          collectionName,
+          formElement]
+        );
+      }
+    };
+
+    /* *************************************************************
+     * Batch methodes
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @param bool
+     * @return void
+     */
+    function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) {
+      var formElementTypeDefinition, selectedElement;
+
+      if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
+        toolbarUseFadeEffect = true;
+      }
+
+      formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
+
+      getStage().removeAllStageToolbars();
+      removeAllStageElementSelectionsBatch();
+      removeAllStructureSelections();
+
+      if (!getFormEditorApp().isRootFormElementSelected()) {
+        removeStructureRootElementSelection();
+        addStructureSelection();
+
+        selectedElement = getStage().getAbstractViewFormElementDomElement();
+
+        if (formElementTypeDefinition['_isTopLevelFormElement']) {
+          addStagePanelSelection();
+        } else {
+          selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement'));
+          getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect);
+        }
+
+        getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
+        if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) {
+          selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
+        }
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param int
+     * @return void
+     * @throws 1478651732
+     * @throws 1478651733
+     * @throws 1478651734
+     */
+    function selectPageBatch(pageIndex) {
+      assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732);
+      assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733);
+      assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734);
+
+      getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]);
+      renewStructure();
+      renderPagination()
+      refreshSelectedElementItemsBatch();
+      renderInspectorEditors();
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function removeAllStageElementSelectionsBatch() {
+      getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement'));
+      removeStagePanelSelection();
+      getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function onViewReadyBatch() {
+      $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
+        .css({
+          width: _configuration['panels']['structure']['width'] + 'px',
+          left: '-=' + _configuration['panels']['structure']['width'] + 'px'
+        });
+      $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
+        .css({
+          width: _configuration['panels']['inspector']['width'] + 'px',
+          right: '-=' + _configuration['panels']['inspector']['width'] + 'px'
+        });
+
+      $(getHelper().getDomElementClassName('headerButtonBar', true))
+        .css({
+          'margin-left': _configuration['panels']['structure']['width'] + 'px'
+        });
+
+      $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
+        .css({
+          'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
+          'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
+        });
+
+      hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
+      hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
+
+      setStageHeadline();
+      setStructureRootElementTitle();
+      renderAbstractStageArea(false);
+      renewStructure();
+      addStructureRootElementSelection();
+      renderInspectorEditors();
+      renderPagination();
+
+      hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
+      showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
+      setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param object
+     * @return void
+     */
+    function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) {
+      draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @param object
+     * @return void
+     */
+    function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
+      getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
+      if (enclosingCompositeFormElement) {
+        getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @param string
+     * @param string
+     * @return void
+     * @throws 1472502237
+     */
+    function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
+      var movedFormElement, parentFormElementIdentifierPath;
+      if (nextFormElementIdentifierPath) {
+        movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
+      } else if (previousFormElementIdentifierPath) {
+        movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
+      } else {
+        parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement);
+        if (parentFormElementIdentifierPath) {
+          movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
+        } else {
+          assert(false, 'Next element, previous or parent element need to be set.', 1472502237);
+        }
+      }
+
+      getStage()
+        .getAbstractViewFormElementWithinDomElement(movedDomElement)
+        .attr(
+          getHelper().getDomElementDataAttribute('elementIdentifier'),
+          movedFormElement.get('__identifierPath')
+        );
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @param object
+     * @return void
+     */
+    function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
+      getStructure()
+        .getAllTreeNodes()
+        .parent()
+        .removeClass(getHelper().getDomElementClassName('sortableHover'));
+
+      getStage()
+        .getAllFormElementDomElements()
+        .parent()
+        .removeClass(getHelper().getDomElementClassName('sortableHover'));
+
+      if (enclosingCompositeFormElement) {
+        getStructure()
+          .getParentTreeNodeWithinDomElement(placeholderDomElement)
+          .parent()
+          .addClass(getHelper().getDomElementClassName('sortableHover'));
+
+        getStage()
+          .getAbstractViewFormElementDomElement(enclosingCompositeFormElement)
+          .parent()
+          .addClass(getHelper().getDomElementClassName('sortableHover'));
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @param string
+     * @param string
+     * @return void
+     * @throws 1479048646
+     */
+    function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
+      var movedFormElement, parentFormElementIdentifierPath;
+      if (nextFormElementIdentifierPath) {
+        movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
+      } else if (previousFormElementIdentifierPath) {
+        movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
+      } else {
+        parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement);
+        if (parentFormElementIdentifierPath) {
+          movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
+        } else {
+          getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646);
+        }
+      }
+
+      getStructure()
+        .getTreeNodeWithinDomElement(movedDomElement)
+        .attr(
+          getHelper().getDomElementDataAttribute('elementIdentifier'),
+          movedFormElement.get('__identifierPath')
+        );
+    };
+
+    /* *************************************************************
+     * Misc
+     * ************************************************************/
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function closeEditor() {
+      document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href');
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @return void
+     */
+    function setElementValidationErrorClass(element, classIdentifier) {
+      if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
+        element.addClass(getHelper().getDomElementClassName('validationErrors'));
+      } else {
+        element.addClass(getHelper().getDomElementClassName(classIdentifier));
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @param string
+     * @return void
+     */
+    function removeElementValidationErrorClass(element, classIdentifier) {
+      if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
+        element.removeClass(getHelper().getDomElementClassName('validationErrors'));
+      } else {
+        element.removeClass(getHelper().getDomElementClassName(classIdentifier));
+      }
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function showComponent(element) {
+      element.removeClass(getHelper().getDomElementClassName('hidden')).show();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function hideComponent(element) {
+      element.addClass(getHelper().getDomElementClassName('hidden')).hide();
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function enableButton(buttonElement) {
+      buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function disableButton(buttonElement) {
+      buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function setButtonActive(buttonElement) {
+      buttonElement.addClass(getHelper().getDomElementClassName('active'));
+    };
+
+    /**
+     * @public
+     *
+     * @param object
+     * @return void
+     */
+    function removeButtonActive(buttonElement) {
+      buttonElement.removeClass(getHelper().getDomElementClassName('active'));
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function showSaveButtonSpinnerIcon() {
+      Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) {
+        $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup));
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function showSaveButtonSaveIcon() {
+      Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) {
+        $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup));
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function showSaveSuccessMessage() {
+      Notification.success(
+        getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'),
+        getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'),
+        2
+      );
+    };
+
+    /**
+     * @public
+     *
+     * @return void
+     */
+    function showSaveErrorMessage(response) {
+      Notification.error(
+        getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'),
+        getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') +
+        " " +
+        response.message
+      );
+    };
+
+    /**
+     * @public
+     *
+     * @param string
+     * @param string
+     * @return void
+     */
+    function showErrorFlashMessage(title, message) {
+      Notification.error(title, message, 2);
+    };
+
+    /**
+     * @public
+     *
+     * @param object formEditorApp
+     * @param object additionalViewModelModules
+     * @return void
+     */
+    function bootstrap(formEditorApp, additionalViewModelModules) {
+      _formEditorApp = formEditorApp;
+
+      _helperSetup();
+      _structureComponentSetup();
+      _modalsComponentSetup();
+      _inspectorsComponentSetup();
+      _stageComponentSetup();
+      _buttonsSetup();
+      _addPropertyValidators();
+      _loadAdditionalModules(additionalViewModelModules);
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      addAbstractViewValidationResults: addAbstractViewValidationResults,
+      addStagePanelSelection: addStagePanelSelection,
+      addStructureRootElementSelection: addStructureRootElementSelection,
+      addStructureSelection: addStructureSelection,
+      addStructureValidationResults: addStructureValidationResults,
+      bootstrap: bootstrap,
+      closeEditor: closeEditor,
+      createAndAddFormElement: createAndAddFormElement,
+      createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
+      disableButton: disableButton,
+      enableButton: enableButton,
+      getConfiguration: getConfiguration,
+      getFormEditorApp: getFormEditorApp,
+      getFormElementDefinition: getFormElementDefinition,
+      getHelper: getHelper,
+      getInspector: getInspector,
+      getModals: getModals,
+      getPreviewMode: getPreviewMode,
+      getStage: getStage,
+      getStructure: getStructure,
+      getStructureRootElement: getStructureRootElement,
+      hideComponent: hideComponent,
+      moveFormElement: moveFormElement,
+      movePropertyCollectionElement: movePropertyCollectionElement,
+      onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch,
+      onAbstractViewDndStartBatch: onAbstractViewDndStartBatch,
+      onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch,
+      onStructureDndChangeBatch: onStructureDndChangeBatch,
+      onStructureDndUpdateBatch: onStructureDndUpdateBatch,
+      onViewReadyBatch: onViewReadyBatch,
+      refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch,
+      removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch,
+      removeAllStructureSelections: removeAllStructureSelections,
+      removeButtonActive: removeButtonActive,
+      removeElementValidationErrorClass: removeElementValidationErrorClass,
+      removeFormElement: removeFormElement,
+      removePropertyCollectionElement: removePropertyCollectionElement,
+      removeStagePanelSelection: removeStagePanelSelection,
+      removeStructureRootElementSelection: removeStructureRootElementSelection,
+      removeStructureSelection: removeStructureSelection,
+      renderAbstractStageArea: renderAbstractStageArea,
+      renderInspectorEditors: renderInspectorEditors,
+      renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors,
+      renderPagination: renderPagination,
+      renderPreviewStageArea: renderPreviewStageArea,
+      renewStructure: renewStructure,
+      renderUndoRedo: renderUndoRedo,
+      selectPageBatch: selectPageBatch,
+      setButtonActive: setButtonActive,
+      setElementValidationErrorClass: setElementValidationErrorClass,
+      setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent,
+      setPreviewMode: setPreviewMode,
+      setStageHeadline: setStageHeadline,
+      setStructureRootElementTitle: setStructureRootElementTitle,
+      showCloseConfirmationModal: showCloseConfirmationModal,
+      showComponent: showComponent,
+      showErrorFlashMessage: showErrorFlashMessage,
+      showInsertElementsModal: showInsertElementsModal,
+      showInsertPagesModal: showInsertPagesModal,
+      showRemoveFormElementModal: showRemoveFormElementModal,
+      showRemoveCollectionElementModal: showRemoveCollectionElementModal,
+      showSaveButtonSaveIcon: showSaveButtonSaveIcon,
+      showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon,
+      showSaveSuccessMessage: showSaveSuccessMessage,
+      showSaveErrorMessage: showSaveErrorMessage,
+      showValidationErrorsModal: showValidationErrorsModal
+    };
+  })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js
index 26a70aa1941d..eb0a8c3f2e59 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager.js
@@ -15,226 +15,226 @@
  * Module: TYPO3/CMS/Form/Backend/FormManager
  */
 define(['jquery'], function($) {
-        'use strict';
+  'use strict';
+
+  /**
+   * Return a static method named "getInstance".
+   * Use this method to create the formmanager app.
+   */
+  return (function() {
+
+    /**
+     * @private
+     *
+     * Hold the instance (Singleton Pattern)
+     */
+    var _formManagerInstance = null;
 
     /**
-     * Return a static method named "getInstance".
-     * Use this method to create the formmanager app.
+     * @public
+     *
+     * @param object _configuration
+     * @param object _viewModel
+     * @return object
      */
-    return (function() {
-
-        /**
-         * @private
-         *
-         * Hold the instance (Singleton Pattern)
-         */
-        var _formManagerInstance = null;
-
-        /**
-         * @public
-         *
-         * @param object _configuration
-         * @param object _viewModel
-         * @return object
-         */
-        function FormManager(_configuration, _viewModel) {
-
-            /**
-             * @private
-             *
-             * @var bool
-             */
-            var _isRunning = false;
-
-            /**
-             * @public
-             *
-             * @param mixed test
-             * @param string message
-             * @param int messageCode
-             * @return void
-             */
-            function assert(test, message, messageCode) {
-                if ('function' === $.type(test)) {
-                    test = (test() !== false);
-                }
-                if (!test) {
-                    message = message || "Assertion failed";
-                    if (messageCode) {
-                        message = message + ' (' + messageCode + ')';
-                    }
-                    if ('undefined' !== typeof Error) {
-                        throw new Error(message);
-                    }
-                    throw message;
-                }
-            };
-
-            /**
-             * @private
-             *
-             * @var bool
-             */
-            var _isRunning = false;
-
-            /**
-             * @public
-             *
-             * @return object
-             */
-            function getPrototypes() {
-                var prototypes = [];
-
-                if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) {
-                    for (var i = 0, len = _configuration['selectablePrototypesConfiguration'].length; i < len; ++i) {
-                        prototypes.push({
-                            label: _configuration['selectablePrototypesConfiguration'][i]['label'],
-                            value: _configuration['selectablePrototypesConfiguration'][i]['identifier'],
-                        });
-                    }
-                }
-                return prototypes;
-            };
-
-            /**
-             * @public
-             *
-             * @param string prototypeName
-             * @return object
-             */
-            function getTemplatesForPrototype(prototypeName) {
-                var templates = [];
-                assert('string' === $.type(prototypeName), 'Invalid parameter "prototypeName"', 1475945286);
-                if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) {
-                    for (var i = 0, len1 = _configuration['selectablePrototypesConfiguration'].length; i < len1; ++i) {
-                        if (_configuration['selectablePrototypesConfiguration'][i]['identifier'] !== prototypeName) {
-                            continue;
-                        }
-                        if ('array' === $.type(_configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'])) {
-                            for (var j = 0, len2 = _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'].length; j < len2; ++j) {
-                                templates.push({
-                                    label: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['label'],
-                                    value: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['templatePath'],
-                                });
-                            }
-                        }
-                    }
-                }
-
-                return templates;
-            };
-
-            /**
-             * @public
-             *
-             * @param string prototypeName
-             * @return object
-             */
-            function getAccessibleFormStorageFolders() {
-                var folders = [];
-
-                if ('array' === $.type(_configuration['accessibleFormStorageFolders'])) {
-                    for (var i = 0, len1 = _configuration['accessibleFormStorageFolders'].length; i < len1; ++i) {
-                        folders.push({
-                            label: _configuration['accessibleFormStorageFolders'][i]['label'],
-                            value: _configuration['accessibleFormStorageFolders'][i]['value'],
-                        });
-                    }
-                }
-                return folders;
-            };
-
-            /**
-             * @public
-             *
-             * @param string prototypeName
-             * @return object
-             * @throws 1477506508
-             */
-            function getAjaxEndpoint(endpointName) {
-                var templates = [];
-                assert(typeof _configuration['endpoints'][endpointName] !== 'undefined', 'Endpoint ' + endpointName + ' does not exist', 1477506508);
-
-                return _configuration['endpoints'][endpointName];
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             * @throws 1475942906
-             */
-            function _viewSetup() {
-                assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475942906);
-                _viewModel.bootstrap(_formManagerInstance);
-            };
-
-            /**
-             * @private
-             *
-             * @return void
-             * @throws 1477506504
-             */
-            function _bootstrap() {
-                _configuration = _configuration || {};
-                assert('object' === $.type(_configuration['endpoints']), 'Invalid parameter "endpoints"', 1477506504);
-                _viewSetup();
-            };
-
-            /**
-             * @public
-             *
-             * @return TYPO3/CMS/Form/Backend/FormManager
-             * @throws 1475942618
-             */
-            function run() {
-                if (_isRunning) {
-                    throw 'You can not run the app twice (1475942618)';
-                }
-
-                _bootstrap();
-                _isRunning = true;
-                return this;
-            };
-
-            /**
-             * Publish the public methods.
-             * Implements the "Revealing Module Pattern".
-             */
-            return {
-                getPrototypes: getPrototypes,
-                getTemplatesForPrototype: getTemplatesForPrototype,
-                getAccessibleFormStorageFolders: getAccessibleFormStorageFolders,
-                getAjaxEndpoint: getAjaxEndpoint,
-
-                assert: assert,
-                run: run
-            };
-        };
-
-        /**
-         * Emulation of static methods
-         */
-        return {
-            /**
-             * @public
-             * @static
-             *
-             * Implement the "Singleton Pattern".
-             *
-             * Return a singleton instance of a
-             * "FormManager" object.
-             *
-             * @param object configuration
-             * @param object viewModel
-             * @return object
-             */
-            getInstance: function(configuration, viewModel) {
-                if(_formManagerInstance === null) {
-                    _formManagerInstance = new FormManager(configuration, viewModel);
-                }
-                return _formManagerInstance;
+    function FormManager(_configuration, _viewModel) {
+
+      /**
+       * @private
+       *
+       * @var bool
+       */
+      var _isRunning = false;
+
+      /**
+       * @public
+       *
+       * @param mixed test
+       * @param string message
+       * @param int messageCode
+       * @return void
+       */
+      function assert(test, message, messageCode) {
+        if ('function' === $.type(test)) {
+          test = (test() !== false);
+        }
+        if (!test) {
+          message = message || "Assertion failed";
+          if (messageCode) {
+            message = message + ' (' + messageCode + ')';
+          }
+          if ('undefined' !== typeof Error) {
+            throw new Error(message);
+          }
+          throw message;
+        }
+      };
+
+      /**
+       * @private
+       *
+       * @var bool
+       */
+      var _isRunning = false;
+
+      /**
+       * @public
+       *
+       * @return object
+       */
+      function getPrototypes() {
+        var prototypes = [];
+
+        if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) {
+          for (var i = 0, len = _configuration['selectablePrototypesConfiguration'].length; i < len; ++i) {
+            prototypes.push({
+              label: _configuration['selectablePrototypesConfiguration'][i]['label'],
+              value: _configuration['selectablePrototypesConfiguration'][i]['identifier']
+            });
+          }
+        }
+        return prototypes;
+      };
+
+      /**
+       * @public
+       *
+       * @param string prototypeName
+       * @return object
+       */
+      function getTemplatesForPrototype(prototypeName) {
+        var templates = [];
+        assert('string' === $.type(prototypeName), 'Invalid parameter "prototypeName"', 1475945286);
+        if ('array' === $.type(_configuration['selectablePrototypesConfiguration'])) {
+          for (var i = 0, len1 = _configuration['selectablePrototypesConfiguration'].length; i < len1; ++i) {
+            if (_configuration['selectablePrototypesConfiguration'][i]['identifier'] !== prototypeName) {
+              continue;
             }
-        };
-    })();
+            if ('array' === $.type(_configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'])) {
+              for (var j = 0, len2 = _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'].length; j < len2; ++j) {
+                templates.push({
+                  label: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['label'],
+                  value: _configuration['selectablePrototypesConfiguration'][i]['newFormTemplates'][j]['templatePath']
+                });
+              }
+            }
+          }
+        }
+
+        return templates;
+      };
+
+      /**
+       * @public
+       *
+       * @param string prototypeName
+       * @return object
+       */
+      function getAccessibleFormStorageFolders() {
+        var folders = [];
+
+        if ('array' === $.type(_configuration['accessibleFormStorageFolders'])) {
+          for (var i = 0, len1 = _configuration['accessibleFormStorageFolders'].length; i < len1; ++i) {
+            folders.push({
+              label: _configuration['accessibleFormStorageFolders'][i]['label'],
+              value: _configuration['accessibleFormStorageFolders'][i]['value']
+            });
+          }
+        }
+        return folders;
+      };
+
+      /**
+       * @public
+       *
+       * @param string prototypeName
+       * @return object
+       * @throws 1477506508
+       */
+      function getAjaxEndpoint(endpointName) {
+        var templates = [];
+        assert(typeof _configuration['endpoints'][endpointName] !== 'undefined', 'Endpoint ' + endpointName + ' does not exist', 1477506508);
+
+        return _configuration['endpoints'][endpointName];
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       * @throws 1475942906
+       */
+      function _viewSetup() {
+        assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475942906);
+        _viewModel.bootstrap(_formManagerInstance);
+      };
+
+      /**
+       * @private
+       *
+       * @return void
+       * @throws 1477506504
+       */
+      function _bootstrap() {
+        _configuration = _configuration || {};
+        assert('object' === $.type(_configuration['endpoints']), 'Invalid parameter "endpoints"', 1477506504);
+        _viewSetup();
+      };
+
+      /**
+       * @public
+       *
+       * @return TYPO3/CMS/Form/Backend/FormManager
+       * @throws 1475942618
+       */
+      function run() {
+        if (_isRunning) {
+          throw 'You can not run the app twice (1475942618)';
+        }
+
+        _bootstrap();
+        _isRunning = true;
+        return this;
+      };
+
+      /**
+       * Publish the public methods.
+       * Implements the "Revealing Module Pattern".
+       */
+      return {
+        getPrototypes: getPrototypes,
+        getTemplatesForPrototype: getTemplatesForPrototype,
+        getAccessibleFormStorageFolders: getAccessibleFormStorageFolders,
+        getAjaxEndpoint: getAjaxEndpoint,
+
+        assert: assert,
+        run: run
+      };
+    };
+
+    /**
+     * Emulation of static methods
+     */
+    return {
+      /**
+       * @public
+       * @static
+       *
+       * Implement the "Singleton Pattern".
+       *
+       * Return a singleton instance of a
+       * "FormManager" object.
+       *
+       * @param object configuration
+       * @param object viewModel
+       * @return object
+       */
+      getInstance: function(configuration, viewModel) {
+        if (_formManagerInstance === null) {
+          _formManagerInstance = new FormManager(configuration, viewModel);
+        }
+        return _formManagerInstance;
+      }
+    };
+  })();
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js
index b7f5225870fe..19edf1e16344 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/FormManager/ViewModel.js
@@ -15,559 +15,561 @@
  * Module: TYPO3/CMS/Form/Backend/FormManager/ViewModel
  */
 define(['jquery',
-        'TYPO3/CMS/Backend/Modal',
-        'TYPO3/CMS/Backend/Severity',
-        'TYPO3/CMS/Backend/Wizard',
-        'TYPO3/CMS/Backend/Icons',
-        'TYPO3/CMS/Backend/Notification'
-        ], function($, Modal, Severity, Wizard, Icons, Notification) {
-        'use strict';
-
-    return (function($, Modal, Severity, Wizard, Icons,Notification) {
-
-        /**
-         * @private
-         *
-         * @var object
-         */
-        var _formManagerApp = null;
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Wizard',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification'
+], function($, Modal, Severity, Wizard, Icons, Notification) {
+  'use strict';
+
+  return (function($, Modal, Severity, Wizard, Icons, Notification) {
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _formManagerApp = null;
+
+    /**
+     * @private
+     *
+     * @var object
+     */
+    var _domElementIdentifierCache = {};
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _domElementIdentifierCacheSetup() {
+      _domElementIdentifierCache = {
+        newFormModalTrigger: {identifier: '[data-identifier="newForm"]'},
+        duplicateFormModalTrigger: {identifier: '[data-identifier="duplicateForm"]'},
+        removeFormModalTrigger: {identifier: '[data-identifier="removeForm"]'},
+
+        newFormName: {identifier: '[data-identifier="newFormName"]'},
+        newFormSavePath: {identifier: '[data-identifier="newFormSavePath"]'},
+        advancedWizard: {identifier: '[data-identifier="advancedWizard"]'},
+        newFormPrototypeName: {identifier: '[data-identifier="newFormPrototypeName"]'},
+        newFormTemplate: {identifier: '[data-identifier="newFormTemplate"]'},
+
+        duplicateFormName: {identifier: '[data-identifier="duplicateFormName"]'},
+        duplicateFormSavePath: {identifier: '[data-identifier="duplicateFormSavePath"]'},
+
+        showReferences: {identifier: '[data-identifier="showReferences"]'},
+        referenceLink: {identifier: '[data-identifier="referenceLink"]'},
+
+        tooltip: {identifier: '[data-toggle="tooltip"]'},
+
+        moduleBody: {class: '.module-body.t3js-module-body'},
+        t3Logo: {class: '.t3-message-page-logo'},
+        t3Footer: {id: '#t3-footer'}
+      }
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1477506500
+     * @throws 1477506501
+     * @throws 1477506502
+     */
+    function _newFormSetup() {
+      $(getDomElementIdentifier('newFormModalTrigger')).on('click', function(e) {
+        e.preventDefault();
 
         /**
-         * @private
-         *
-         * @var object
+         * Wizard step 1
          */
-        var _domElementIdentifierCache = {};
-
-        /**
-         * @private
-         *
-         * @return void
-         */
-        function _domElementIdentifierCacheSetup() {
-            _domElementIdentifierCache = {
-                newFormModalTrigger: { identifier: '[data-identifier="newForm"]' },
-                duplicateFormModalTrigger: { identifier: '[data-identifier="duplicateForm"]' },
-                removeFormModalTrigger: { identifier: '[data-identifier="removeForm"]' },
-
-                newFormName: { identifier: '[data-identifier="newFormName"]' },
-                newFormSavePath: { identifier: '[data-identifier="newFormSavePath"]' },
-                advancedWizard: { identifier: '[data-identifier="advancedWizard"]' },
-                newFormPrototypeName: { identifier: '[data-identifier="newFormPrototypeName"]' },
-                newFormTemplate: { identifier: '[data-identifier="newFormTemplate"]' },
-
-                duplicateFormName: { identifier: '[data-identifier="duplicateFormName"]' },
-                duplicateFormSavePath: { identifier: '[data-identifier="duplicateFormSavePath"]' },
-
-                showReferences: { identifier: '[data-identifier="showReferences"]' },
-                referenceLink: { identifier: '[data-identifier="referenceLink"]' },
+        Wizard.addSlide('new-form-step-1', TYPO3.lang['formManager.newFormWizard.step1.title'], '', Severity.info, function(slide) {
+          var advandecWizardHasOptions, folders, html, modal, nextButton, prototypes,
+            savePathSelect, templates;
+
+          modal = Wizard.setup.$carousel.closest('.modal');
+          nextButton = modal.find('.modal-footer').find('button[name="next"]');
+
+          folders = _formManagerApp.getAccessibleFormStorageFolders();
+          if (folders.length === 0) {
+            html = '<div class="new-form-modal">'
+              + '<div class="form-horizontal">'
+              + '<div>'
+              + '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.noStorages'] + '</label>'
+              + '</div>'
+              + '</div>'
+              + '</div>';
+
+            slide.html(html);
+            _formManagerApp.assert(false, 'No accessible form storage folders', 1477506500);
+          }
+
+          Wizard.set('savePath', folders[0]['value']);
+          if (folders.length > 1) {
+            savePathSelect = $('<select class="new-form-save-path form-control" data-identifier="newFormSavePath" />');
+            for (var i = 0, len = folders.length; i < len; ++i) {
+              var option = new Option(folders[i]['label'], folders[i]['value']);
+              $(savePathSelect).append(option);
+            }
+          }
+
+          prototypes = _formManagerApp.getPrototypes();
+
+          _formManagerApp.assert(prototypes.length > 0, 'No prototypes available', 1477506501);
+          Wizard.set('prototypeName', prototypes[0]['value']);
+
+          templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']);
+          _formManagerApp.assert(templates.length > 0, 'No templates available', 1477506502);
+          Wizard.set('templatePath', templates[0]['value']);
+
+          html = '<div class="new-form-modal">'
+            + '<div class="form-horizontal">'
+            + '<div>'
+            + '<label class="control-label">' + TYPO3.lang['formManager.form_name'] + '</label>'
+            + '<input class="new-form-name form-control has-error" data-identifier="newFormName" />';
+
+          if (savePathSelect) {
+            html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML;
+          }
+
+          if (prototypes.length > 1 || templates.length > 1) {
+            html += '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.advanced'] + '</label>'
+              + '<div class="t3-form-controls"><input type="checkbox" class="new-form-advance-wizard" data-identifier="advancedWizard" /></div>';
+          }
+
+          html += '</div>'
+            + '</div>'
+            + '</div>';
+
+          slide.html(html);
+          $(getDomElementIdentifier('newFormName'), modal).focus();
+
+          $(getDomElementIdentifier('newFormName'), modal).on('keyup paste', function(e) {
+            if ($(this).val().length > 0) {
+              $(this).removeClass('has-error');
+              Wizard.unlockNextStep();
+              Wizard.set('formName', $(this).val());
+            } else {
+              $(this).addClass('has-error');
+              Wizard.lockNextStep();
+            }
+          });
 
-                tooltip: { identifier: '[data-toggle="tooltip"]' },
+          $(getDomElementIdentifier('newFormSavePath'), modal).on('change', function(e) {
+            Wizard.set('savePath', $(getDomElementIdentifier('newFormSavePath') + ' option:selected', modal).val());
+          });
 
-                moduleBody: { class: '.module-body.t3js-module-body' },
-                t3Logo: { class: '.t3-message-page-logo' },
-                t3Footer: { id: '#t3-footer' }
+          $(getDomElementIdentifier('advancedWizard'), modal).on('change', function(e) {
+            if ($(this).is(':checked')) {
+              Wizard.set('advancedWizard', true);
+            } else {
+              Wizard.set('advancedWizard', false);
             }
-        };
+          });
 
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1477506500
-         * @throws 1477506501
-         * @throws 1477506502
-         */
-        function _newFormSetup() {
-            $(getDomElementIdentifier('newFormModalTrigger')).on('click', function(e) {
-                e.preventDefault();
-
-                /**
-                 * Wizard step 1
-                 */
-                Wizard.addSlide('new-form-step-1', TYPO3.lang['formManager.newFormWizard.step1.title'], '', Severity.info, function(slide) {
-                    var advandecWizardHasOptions, folders, html, modal, nextButton, prototypes, savePathSelect, templates;
-
-                    modal = Wizard.setup.$carousel.closest('.modal');
-                    nextButton = modal.find('.modal-footer').find('button[name="next"]');
-
-                    folders = _formManagerApp.getAccessibleFormStorageFolders();
-                    if (folders.length === 0) {
-                        html = '<div class="new-form-modal">'
-                                 + '<div class="form-horizontal">'
-                                     + '<div>'
-                                         + '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.noStorages'] + '</label>'
-                                     + '</div>'
-                                 + '</div>'
-                             + '</div>';
-
-                        slide.html(html);
-                        _formManagerApp.assert(false, 'No accessible form storage folders', 1477506500);
-                    }
-
-                    Wizard.set('savePath', folders[0]['value']);
-                    if (folders.length > 1) {
-                        savePathSelect = $('<select class="new-form-save-path form-control" data-identifier="newFormSavePath" />');
-                        for (var i = 0, len = folders.length; i < len; ++i) {
-                            var option = new Option(folders[i]['label'], folders[i]['value']);
-                            $(savePathSelect).append(option);
-                        }
-                    }
-
-                    prototypes = _formManagerApp.getPrototypes();
-
-                    _formManagerApp.assert(prototypes.length > 0, 'No prototypes available', 1477506501);
-                    Wizard.set('prototypeName', prototypes[0]['value']);
-
-                    templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']);
-                    _formManagerApp.assert(templates.length > 0, 'No templates available', 1477506502);
-                    Wizard.set('templatePath', templates[0]['value']);
-
-                    html = '<div class="new-form-modal">'
-                             + '<div class="form-horizontal">'
-                                 + '<div>'
-                                     + '<label class="control-label">' + TYPO3.lang['formManager.form_name'] + '</label>'
-                                     + '<input class="new-form-name form-control has-error" data-identifier="newFormName" />';
-
-                    if (savePathSelect) {
-                        html +=        '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML;
-                    }
-
-                    if (prototypes.length > 1 || templates.length > 1) {
-                        html +=        '<label class="control-label">' + TYPO3.lang['formManager.newFormWizard.step1.advanced'] + '</label>'
-                                     + '<div class="t3-form-controls"><input type="checkbox" class="new-form-advance-wizard" data-identifier="advancedWizard" /></div>';
-                    }
-
-                    html +=        '</div>'
-                             + '</div>'
-                         + '</div>';
-
-                    slide.html(html);
-                    $(getDomElementIdentifier('newFormName'), modal).focus();
-
-                    $(getDomElementIdentifier('newFormName'), modal).on('keyup paste', function(e) {
-                        if ($(this).val().length > 0) {
-                            $(this).removeClass('has-error');
-                            Wizard.unlockNextStep();
-                            Wizard.set('formName', $(this).val());
-                        } else {
-                            $(this).addClass('has-error');
-                            Wizard.lockNextStep();
-                        }
-                    });
-
-                    $(getDomElementIdentifier('newFormSavePath'), modal).on('change', function(e) {
-                        Wizard.set('savePath', $(getDomElementIdentifier('newFormSavePath') + ' option:selected', modal).val());
-                    });
-
-                    $(getDomElementIdentifier('advancedWizard'), modal).on('change', function(e) {
-                        if ($(this).is(':checked')) {
-                            Wizard.set('advancedWizard', true);
-                        } else {
-                            Wizard.set('advancedWizard', false);
-                        }
-                    });
-
-                    nextButton.on('click', function() {
-                        Wizard.setup.forceSelection = false;
-                        Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
-                            slide.html($('<div />', {class: 'text-center'}).append(markup));
-                        });
-                    });
-                });
-
-                /**
-                 * Wizard step 2
-                 */
-                Wizard.addSlide('new-form-step-2', TYPO3.lang['formManager.newFormWizard.step2.title'], '', Severity.info, function(slide, settings) {
-                    var addOnTemplateChangeEvents, html, modal, nextButton, prototypes, prototypeNameSelect, templates, templateSelect;
-
-                    if (settings['advancedWizard'] !== true) {
-                        Wizard.unlockNextStep().trigger('click');
-                        return;
-                    }
-
-                    modal = Wizard.setup.$carousel.closest('.modal');
-                    nextButton = modal.find('.modal-footer').find('button[name="next"]');
-
-                    prototypeNameSelect = $('<select class="new-form-prototype-name form-control" data-identifier="newFormPrototypeName" />');
-                    templateSelect = $('<select class="new-form-template form-control" data-identifier="newFormTemplate" />');
-
-                    prototypes = _formManagerApp.getPrototypes();
-                    templates = {};
-                    if (prototypes.length > 0) {
-                        for (var i = 0, len = prototypes.length; i < len; ++i) {
-                            var option = new Option(prototypes[i]['label'], prototypes[i]['value']);
-                            $(prototypeNameSelect).append(option);
-                        }
-
-                        templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']);
-                        for (var i = 0, len = templates.length; i < len; ++i) {
-                            var option = new Option(templates[i]['label'], templates[i]['value']);
-                            $(templateSelect).append(option);
-                        }
-                    }
-
-                    html = '<div class="new-form-modal">'
-                             + '<div class="form-horizontal">'
-                                 + '<div>';
-
-                    if (prototypes.length > 1) {
-                        html +=        '<label class="control-label">' + TYPO3.lang['formManager.form_prototype'] + '</label>' + $(prototypeNameSelect)[0].outerHTML;
-                    }
-                    if (templates.length > 1) {
-                        html +=        '<label class="control-label">' + TYPO3.lang['formManager.form_template'] + '</label>' + $(templateSelect)[0].outerHTML;
-                    }
-
-                    html +=        '</div>'
-                             + '</div>'
-                         + '</div>';
-
-                    slide.html(html);
-                    if (prototypes.length > 1) {
-                        $(getDomElementIdentifier('newFormPrototypeName'), modal).focus();
-                    } else if (templates.length > 1) {
-                        $(getDomElementIdentifier('newFormTemplate'), modal).focus();
-                    }
-
-                    addOnTemplateChangeEvents = function() {
-                        $(getDomElementIdentifier('newFormTemplate'), modal).on('change', function(e) {
-                            Wizard.set('templatePath', $(getDomElementIdentifier('newFormTemplate') + ' option:selected', modal).val());
-                        });
-                    };
-
-                    $(getDomElementIdentifier('newFormPrototypeName'), modal).on('change', function(e) {
-                        Wizard.set('prototypeName', $(this).val());
-                        templates = _formManagerApp.getTemplatesForPrototype($(this).val());
-                        $(getDomElementIdentifier('newFormTemplate'), modal).off().empty();
-                        for (var i = 0, len = templates.length; i < len; ++i) {
-                            var option = new Option(templates[i]['label'], templates[i]['value']);
-                            $(getDomElementIdentifier('newFormTemplate'), modal).append(option);
-                            Wizard.set('templatePath', templates[0]['value']);
-                        }
-                        addOnTemplateChangeEvents();
-                    });
-
-                    addOnTemplateChangeEvents();
-
-                    nextButton.on('click', function() {
-                        Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
-                            slide.html($('<div />', {class: 'text-center'}).append(markup));
-                        });
-                    });
-                });
-
-                /**
-                 * Wizard step 3
-                 */
-                Wizard.addSlide('new-form-step-3', TYPO3.lang['formManager.newFormWizard.step3.title'], TYPO3.lang['formManager.newFormWizard.step3.message'], Severity.info);
-
-                /**
-                 * Wizard step 4
-                 */
-                Wizard.addFinalProcessingSlide(function() {
-                    $.post(_formManagerApp.getAjaxEndpoint('create'), {
-                        tx_form_web_formformbuilder: {
-                            formName: Wizard.setup.settings['formName'],
-                            templatePath: Wizard.setup.settings['templatePath'],
-                            prototypeName: Wizard.setup.settings['prototypeName'],
-                            savePath: Wizard.setup.settings['savePath']
-                        }
-                    }, function(data, textStatus, jqXHR) {
-                        if (data['status'] === 'success') {
-                            document.location = data.url;
-                        } else {
-                            Notification.error(TYPO3.lang['formManager.newFormWizard.step4.errorTitle'], TYPO3.lang['formManager.newFormWizard.step4.errorMessage'] + " " + data['message']);
-                        }
-                        Wizard.dismiss();
-                    }).fail(function(jqXHR, textStatus, errorThrown) {
-                        var parser = new DOMParser(),
-                            responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"),
-                            responseBody = $(responseDocument.body);
-
-                        Notification.error(textStatus, errorThrown, 2);
-                        Wizard.dismiss();
-
-                        $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove();
-                        $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove();
-                        $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html());
-                    });
-                }).done(function() {
-                    Wizard.show();
-                });
+          nextButton.on('click', function() {
+            Wizard.setup.forceSelection = false;
+            Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
+              slide.html($('<div />', {class: 'text-center'}).append(markup));
             });
-        };
+          });
+        });
 
         /**
-         * @private
-         *
-         * @return void
+         * Wizard step 2
          */
-        function _removeFormSetup() {
-            $(getDomElementIdentifier('removeFormModalTrigger')).on('click', function(e) {
-                var modalButtons = [], that;
-
-                e.preventDefault();
-                that = $(this)
-
-                modalButtons.push({
-                    text: TYPO3.lang['formManager.cancel'],
-                    active: true,
-                    btnClass: 'btn-default',
-                    name: 'cancel',
-                    trigger: function () {
-                        Modal.currentModal.trigger('modal-dismiss');
-                    }
-                });
-
-                modalButtons.push({
-                    text: TYPO3.lang['formManager.remove_form'],
-                    active: true,
-                    btnClass: 'btn-warning',
-                    name: 'createform',
-                    trigger: function () {
-                        document.location = _formManagerApp.getAjaxEndpoint('delete') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + that.data('formPersistenceIdentifier');
-                        Modal.currentModal.trigger('modal-dismiss');
-                    }
-                });
-
-                Modal.show(
-                    TYPO3.lang['formManager.remove_form_title'],
-                    TYPO3.lang['formManager.remove_form_message'],
-                    Severity.warning,
-                    modalButtons
-                );
+        Wizard.addSlide('new-form-step-2', TYPO3.lang['formManager.newFormWizard.step2.title'], '', Severity.info, function(slide, settings) {
+          var addOnTemplateChangeEvents, html, modal, nextButton, prototypes, prototypeNameSelect,
+            templates, templateSelect;
+
+          if (settings['advancedWizard'] !== true) {
+            Wizard.unlockNextStep().trigger('click');
+            return;
+          }
+
+          modal = Wizard.setup.$carousel.closest('.modal');
+          nextButton = modal.find('.modal-footer').find('button[name="next"]');
+
+          prototypeNameSelect = $('<select class="new-form-prototype-name form-control" data-identifier="newFormPrototypeName" />');
+          templateSelect = $('<select class="new-form-template form-control" data-identifier="newFormTemplate" />');
+
+          prototypes = _formManagerApp.getPrototypes();
+          templates = {};
+          if (prototypes.length > 0) {
+            for (var i = 0, len = prototypes.length; i < len; ++i) {
+              var option = new Option(prototypes[i]['label'], prototypes[i]['value']);
+              $(prototypeNameSelect).append(option);
+            }
+
+            templates = _formManagerApp.getTemplatesForPrototype(prototypes[0]['value']);
+            for (var i = 0, len = templates.length; i < len; ++i) {
+              var option = new Option(templates[i]['label'], templates[i]['value']);
+              $(templateSelect).append(option);
+            }
+          }
+
+          html = '<div class="new-form-modal">'
+            + '<div class="form-horizontal">'
+            + '<div>';
+
+          if (prototypes.length > 1) {
+            html += '<label class="control-label">' + TYPO3.lang['formManager.form_prototype'] + '</label>' + $(prototypeNameSelect)[0].outerHTML;
+          }
+          if (templates.length > 1) {
+            html += '<label class="control-label">' + TYPO3.lang['formManager.form_template'] + '</label>' + $(templateSelect)[0].outerHTML;
+          }
+
+          html += '</div>'
+            + '</div>'
+            + '</div>';
+
+          slide.html(html);
+          if (prototypes.length > 1) {
+            $(getDomElementIdentifier('newFormPrototypeName'), modal).focus();
+          } else if (templates.length > 1) {
+            $(getDomElementIdentifier('newFormTemplate'), modal).focus();
+          }
+
+          addOnTemplateChangeEvents = function() {
+            $(getDomElementIdentifier('newFormTemplate'), modal).on('change', function(e) {
+              Wizard.set('templatePath', $(getDomElementIdentifier('newFormTemplate') + ' option:selected', modal).val());
             });
-        };
+          };
+
+          $(getDomElementIdentifier('newFormPrototypeName'), modal).on('change', function(e) {
+            Wizard.set('prototypeName', $(this).val());
+            templates = _formManagerApp.getTemplatesForPrototype($(this).val());
+            $(getDomElementIdentifier('newFormTemplate'), modal).off().empty();
+            for (var i = 0, len = templates.length; i < len; ++i) {
+              var option = new Option(templates[i]['label'], templates[i]['value']);
+              $(getDomElementIdentifier('newFormTemplate'), modal).append(option);
+              Wizard.set('templatePath', templates[0]['value']);
+            }
+            addOnTemplateChangeEvents();
+          });
 
-        /**
-         * @private
-         *
-         * @return void
-         * @throws 1477649539
-         */
-        function _duplicateFormSetup() {
-            $(getDomElementIdentifier('duplicateFormModalTrigger')).on('click', function(e) {
-                var that;
-
-                e.preventDefault();
-                that = $(this);
-
-                /**
-                 * Wizard step 1
-                 */
-                Wizard.addSlide('duplicate-form-step-1', TYPO3.lang['formManager.duplicateFormWizard.step1.title'].replace('{0}', that.data('formName')), '', Severity.info, function(slide) {
-                    var folders, html, modal, nextButton, savePathSelect;
-
-                    modal = Wizard.setup.$carousel.closest('.modal');
-                    nextButton = modal.find('.modal-footer').find('button[name="next"]');
-
-                    folders = _formManagerApp.getAccessibleFormStorageFolders();
-                    _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477649539);
-
-                    Wizard.set('formPersistenceIdentifier', that.data('formPersistenceIdentifier'));
-                    Wizard.set('savePath', folders[0]['value']);
-                    if (folders.length > 1) {
-                        savePathSelect = $('<select class="duplicate-form-save-path form-control" data-identifier="duplicateFormSavePath" />');
-                        for (var i = 0, len = folders.length; i < len; ++i) {
-                            var option = new Option(folders[i]['label'], folders[i]['value']);
-                            $(savePathSelect).append(option);
-                        }
-                    }
-
-                    html = '<div class="duplicate-form-modal">'
-                             + '<div class="form-horizontal">'
-                                 + '<div>'
-                                     + '<label class="control-label">' + TYPO3.lang['formManager.new_form_name'] + '</label>'
-                                     + '<input class="duplicate-form-name form-control has-error" data-identifier="duplicateFormName" />';
-
-                    if (savePathSelect) {
-                        html +=        '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML;
-                    }
-
-                    html +=        '</div>'
-                             + '</div>'
-                         + '</div>';
-
-                    slide.html(html);
-                    $(getDomElementIdentifier('duplicateFormName'), modal).focus();
-
-                    $(getDomElementIdentifier('duplicateFormName'), modal).on('keyup paste', function(e) {
-                        if ($(this).val().length > 0) {
-                            $(this).removeClass('has-error');
-                            Wizard.unlockNextStep();
-                            Wizard.set('formName', $(this).val());
-                        } else {
-                            $(this).addClass('has-error');
-                            Wizard.lockNextStep();
-                        }
-                    });
-
-                    $(getDomElementIdentifier('duplicateFormSavePath'), modal).on('change', function(e) {
-                        Wizard.set('savePath', $(getDomElementIdentifier('duplicateFormSavePath') + ' option:selected', modal).val());
-                    });
-                });
-
-                /**
-                 * Wizard step 2
-                 */
-                Wizard.addFinalProcessingSlide(function() {
-                    $.post(_formManagerApp.getAjaxEndpoint('duplicate'), {
-                        tx_form_web_formformbuilder: {
-                            formName: Wizard.setup.settings['formName'],
-                            formPersistenceIdentifier: Wizard.setup.settings['formPersistenceIdentifier'],
-                            savePath: Wizard.setup.settings['savePath']
-                        }
-                    }, function(data, textStatus, jqXHR) {
-                        if (data['status'] === 'success') {
-                            document.location = data.url;
-                        } else {
-                            Notification.error(TYPO3.lang['formManager.duplicateFormWizard.step2.errorTitle'], TYPO3.lang['formManager.duplicateFormWizard.step2.errorMessage'] + " " + data['message']);
-                        }
-                        Wizard.dismiss();
-                    }).fail(function(jqXHR, textStatus, errorThrown) {
-                        var parser = new DOMParser(),
-                            responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"),
-                            responseBody = $(responseDocument.body);
-
-                        Notification.error(textStatus, errorThrown, 2);
-                        Wizard.dismiss();
-
-                        $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove();
-                        $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove();
-                        $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html());
-                    });
-                }).done(function() {
-                    Wizard.show();
-                });
+          addOnTemplateChangeEvents();
+
+          nextButton.on('click', function() {
+            Icons.getIcon('spinner-circle-dark', Icons.sizes.large, null, null).done(function(markup) {
+              slide.html($('<div />', {class: 'text-center'}).append(markup));
             });
-        };
+          });
+        });
 
         /**
-         * @private
-         *
-         * @return void
+         * Wizard step 3
          */
-        function _showReferencesSetup() {
-            $(getDomElementIdentifier('showReferences')).on('click', function(e) {
-                var that, url;
-
-                e.preventDefault();
-                that = this;
-                url = _formManagerApp.getAjaxEndpoint('references') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + $(this).data('formPersistenceIdentifier');
-
-                $.get(url, function(data, textStatus, jqXHR) {
-                    var html, modalButtons = [], referencesLength;
-
-                    modalButtons.push({
-                        text: TYPO3.lang['formManager.cancel'],
-                        active: true,
-                        btnClass: 'btn-default',
-                        name: 'cancel',
-                        trigger: function () {
-                            Modal.currentModal.trigger('modal-dismiss');
-                        }
-                    });
-
-                    referencesLength = data['references'].length;
-                    if (referencesLength > 0) {
-                        html = '<div>'
-                                 + '<h3>' + TYPO3.lang['formManager.references.headline'].replace('{0}', $(that).data('formName')) + '</h3>'
-                             + '</div>'
-                             + '<div class="table-fit">'
-                                 + '<table id="forms" class="table table-striped table-condensed">'
-                                     + '<thead>'
-                                         + '<tr>'
-                                             + '<th>' + TYPO3.lang['formManager.page'] + '</th>'
-                                             + '<th>' + TYPO3.lang['formManager.record'] + '</th>'
-                                         + '</tr>'
-                                     + '</thead>'
-                                     + '<tbody>';
-
-                        for (var i = 0, len = data['references'].length; i < len; ++i) {
-                            html +=        '<tr>'
-                                             + '<td>' + data['references'][i]['recordPageTitle'] + '</td>'
-                                             + '<td>'
-                                                 + data['references'][i]['recordIcon']
-                                                 + '<a href="' + data['references'][i]['recordEditUrl'] + '" data-identifier="referenceLink">'
-                                                     + data['references'][i]['recordTitle'] + ' (uid: ' + data['references'][i]['recordUid'] + ')'
-                                                 + '</a>'
-                                             + '</td>'
-                                         + '</tr>';
-                        }
-
-                        html +=        '</tbody>'
-                                 + '</table>'
-                             + '</div>';
-                    } else {
-                        html = '<div>'
-                                 + '<h1>' + TYPO3.lang['formManager.references.title'].replace('{0}', data['formPersistenceIdentifier']) + '</h1>'
-                             + '</div>'
-                             + '<div>' + TYPO3.lang['formManager.no_references'] + '</div>';
-                    }
-
-                    html = $(html);
-                    $(getDomElementIdentifier('referenceLink'), html).on('click', function(e) {
-                        e.preventDefault();
-                        Modal.currentModal.trigger('modal-dismiss');
-                        document.location = $(this).prop('href');
-                    });
-
-                    Modal.show(
-                        TYPO3.lang['formManager.references.title'],
-                        html,
-                        Severity.info,
-                        modalButtons
-                    );
-                }).fail(function(jqXHR, textStatus, errorThrown) {
-                    if (jqXHR.status !== 0) {
-                        Notification.error(textStatus, errorThrown, 2);
-                    }
-                });
-            });
-        };
+        Wizard.addSlide('new-form-step-3', TYPO3.lang['formManager.newFormWizard.step3.title'], TYPO3.lang['formManager.newFormWizard.step3.message'], Severity.info);
 
         /**
-         * @public
-         *
-         * @param string elementIdentifier
-         * @param string type
-         * @return mixed|undefined
-         * @throws 1477506413
-         * @throws 1477506414
+         * Wizard step 4
          */
-        function getDomElementIdentifier(elementIdentifier, type) {
-            _formManagerApp.assert(elementIdentifier.length > 0, 'Invalid parameter "elementIdentifier"', 1477506413);
-            _formManagerApp.assert(typeof _domElementIdentifierCache[elementIdentifier] !== "undefined", 'elementIdentifier "' + elementIdentifier + '" does not exist', 1477506414);
-            if (typeof type === "undefined") {
-                type = 'identifier';
+        Wizard.addFinalProcessingSlide(function() {
+          $.post(_formManagerApp.getAjaxEndpoint('create'), {
+            tx_form_web_formformbuilder: {
+              formName: Wizard.setup.settings['formName'],
+              templatePath: Wizard.setup.settings['templatePath'],
+              prototypeName: Wizard.setup.settings['prototypeName'],
+              savePath: Wizard.setup.settings['savePath']
             }
-
-            return _domElementIdentifierCache[elementIdentifier][type] || undefined;
-        };
+          }, function(data, textStatus, jqXHR) {
+            if (data['status'] === 'success') {
+              document.location = data.url;
+            } else {
+              Notification.error(TYPO3.lang['formManager.newFormWizard.step4.errorTitle'], TYPO3.lang['formManager.newFormWizard.step4.errorMessage'] + " " + data['message']);
+            }
+            Wizard.dismiss();
+          }).fail(function(jqXHR, textStatus, errorThrown) {
+            var parser = new DOMParser(),
+              responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"),
+              responseBody = $(responseDocument.body);
+
+            Notification.error(textStatus, errorThrown, 2);
+            Wizard.dismiss();
+
+            $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove();
+            $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove();
+            $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html());
+          });
+        }).done(function() {
+          Wizard.show();
+        });
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _removeFormSetup() {
+      $(getDomElementIdentifier('removeFormModalTrigger')).on('click', function(e) {
+        var modalButtons = [], that;
+
+        e.preventDefault();
+        that = $(this)
+
+        modalButtons.push({
+          text: TYPO3.lang['formManager.cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel',
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+          }
+        });
+
+        modalButtons.push({
+          text: TYPO3.lang['formManager.remove_form'],
+          active: true,
+          btnClass: 'btn-warning',
+          name: 'createform',
+          trigger: function() {
+            document.location = _formManagerApp.getAjaxEndpoint('delete') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + that.data('formPersistenceIdentifier');
+            Modal.currentModal.trigger('modal-dismiss');
+          }
+        });
+
+        Modal.show(
+          TYPO3.lang['formManager.remove_form_title'],
+          TYPO3.lang['formManager.remove_form_message'],
+          Severity.warning,
+          modalButtons
+        );
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     * @throws 1477649539
+     */
+    function _duplicateFormSetup() {
+      $(getDomElementIdentifier('duplicateFormModalTrigger')).on('click', function(e) {
+        var that;
+
+        e.preventDefault();
+        that = $(this);
 
         /**
-         * @public
-         *
-         * @param object formManagerApp
-         * @return void
+         * Wizard step 1
          */
-        function bootstrap(formManagerApp) {
-            _formManagerApp = formManagerApp;
-            _domElementIdentifierCacheSetup();
-            _removeFormSetup();
-            _newFormSetup();
-            _duplicateFormSetup();
-            _showReferencesSetup();
-            $(getDomElementIdentifier('tooltip')).tooltip();
-        };
+        Wizard.addSlide('duplicate-form-step-1', TYPO3.lang['formManager.duplicateFormWizard.step1.title'].replace('{0}', that.data('formName')), '', Severity.info, function(slide) {
+          var folders, html, modal, nextButton, savePathSelect;
+
+          modal = Wizard.setup.$carousel.closest('.modal');
+          nextButton = modal.find('.modal-footer').find('button[name="next"]');
+
+          folders = _formManagerApp.getAccessibleFormStorageFolders();
+          _formManagerApp.assert(folders.length > 0, 'No accessible form storage folders', 1477649539);
+
+          Wizard.set('formPersistenceIdentifier', that.data('formPersistenceIdentifier'));
+          Wizard.set('savePath', folders[0]['value']);
+          if (folders.length > 1) {
+            savePathSelect = $('<select class="duplicate-form-save-path form-control" data-identifier="duplicateFormSavePath" />');
+            for (var i = 0, len = folders.length; i < len; ++i) {
+              var option = new Option(folders[i]['label'], folders[i]['value']);
+              $(savePathSelect).append(option);
+            }
+          }
+
+          html = '<div class="duplicate-form-modal">'
+            + '<div class="form-horizontal">'
+            + '<div>'
+            + '<label class="control-label">' + TYPO3.lang['formManager.new_form_name'] + '</label>'
+            + '<input class="duplicate-form-name form-control has-error" data-identifier="duplicateFormName" />';
+
+          if (savePathSelect) {
+            html += '<label class="control-label">' + TYPO3.lang['formManager.form_save_path'] + '</label>' + $(savePathSelect)[0].outerHTML;
+          }
+
+          html += '</div>'
+            + '</div>'
+            + '</div>';
+
+          slide.html(html);
+          $(getDomElementIdentifier('duplicateFormName'), modal).focus();
+
+          $(getDomElementIdentifier('duplicateFormName'), modal).on('keyup paste', function(e) {
+            if ($(this).val().length > 0) {
+              $(this).removeClass('has-error');
+              Wizard.unlockNextStep();
+              Wizard.set('formName', $(this).val());
+            } else {
+              $(this).addClass('has-error');
+              Wizard.lockNextStep();
+            }
+          });
+
+          $(getDomElementIdentifier('duplicateFormSavePath'), modal).on('change', function(e) {
+            Wizard.set('savePath', $(getDomElementIdentifier('duplicateFormSavePath') + ' option:selected', modal).val());
+          });
+        });
 
         /**
-         * Publish the public methods.
-         * Implements the "Revealing Module Pattern".
+         * Wizard step 2
          */
-        return {
-            bootstrap: bootstrap,
-        };
-    })($, Modal, Severity, Wizard, Icons, Notification);
+        Wizard.addFinalProcessingSlide(function() {
+          $.post(_formManagerApp.getAjaxEndpoint('duplicate'), {
+            tx_form_web_formformbuilder: {
+              formName: Wizard.setup.settings['formName'],
+              formPersistenceIdentifier: Wizard.setup.settings['formPersistenceIdentifier'],
+              savePath: Wizard.setup.settings['savePath']
+            }
+          }, function(data, textStatus, jqXHR) {
+            if (data['status'] === 'success') {
+              document.location = data.url;
+            } else {
+              Notification.error(TYPO3.lang['formManager.duplicateFormWizard.step2.errorTitle'], TYPO3.lang['formManager.duplicateFormWizard.step2.errorMessage'] + " " + data['message']);
+            }
+            Wizard.dismiss();
+          }).fail(function(jqXHR, textStatus, errorThrown) {
+            var parser = new DOMParser(),
+              responseDocument = parser.parseFromString(jqXHR.responseText, "text/html"),
+              responseBody = $(responseDocument.body);
+
+            Notification.error(textStatus, errorThrown, 2);
+            Wizard.dismiss();
+
+            $(getDomElementIdentifier('t3Logo', 'class'), responseBody).remove();
+            $(getDomElementIdentifier('t3Footer', 'id'), responseBody).remove();
+            $(getDomElementIdentifier('moduleBody', 'class')).html(responseBody.html());
+          });
+        }).done(function() {
+          Wizard.show();
+        });
+      });
+    };
+
+    /**
+     * @private
+     *
+     * @return void
+     */
+    function _showReferencesSetup() {
+      $(getDomElementIdentifier('showReferences')).on('click', function(e) {
+        var that, url;
+
+        e.preventDefault();
+        that = this;
+        url = _formManagerApp.getAjaxEndpoint('references') + '&tx_form_web_formformbuilder[formPersistenceIdentifier]=' + $(this).data('formPersistenceIdentifier');
+
+        $.get(url, function(data, textStatus, jqXHR) {
+          var html, modalButtons = [], referencesLength;
+
+          modalButtons.push({
+            text: TYPO3.lang['formManager.cancel'],
+            active: true,
+            btnClass: 'btn-default',
+            name: 'cancel',
+            trigger: function() {
+              Modal.currentModal.trigger('modal-dismiss');
+            }
+          });
+
+          referencesLength = data['references'].length;
+          if (referencesLength > 0) {
+            html = '<div>'
+              + '<h3>' + TYPO3.lang['formManager.references.headline'].replace('{0}', $(that).data('formName')) + '</h3>'
+              + '</div>'
+              + '<div class="table-fit">'
+              + '<table id="forms" class="table table-striped table-condensed">'
+              + '<thead>'
+              + '<tr>'
+              + '<th>' + TYPO3.lang['formManager.page'] + '</th>'
+              + '<th>' + TYPO3.lang['formManager.record'] + '</th>'
+              + '</tr>'
+              + '</thead>'
+              + '<tbody>';
+
+            for (var i = 0, len = data['references'].length; i < len; ++i) {
+              html += '<tr>'
+                + '<td>' + data['references'][i]['recordPageTitle'] + '</td>'
+                + '<td>'
+                + data['references'][i]['recordIcon']
+                + '<a href="' + data['references'][i]['recordEditUrl'] + '" data-identifier="referenceLink">'
+                + data['references'][i]['recordTitle'] + ' (uid: ' + data['references'][i]['recordUid'] + ')'
+                + '</a>'
+                + '</td>'
+                + '</tr>';
+            }
+
+            html += '</tbody>'
+              + '</table>'
+              + '</div>';
+          } else {
+            html = '<div>'
+              + '<h1>' + TYPO3.lang['formManager.references.title'].replace('{0}', data['formPersistenceIdentifier']) + '</h1>'
+              + '</div>'
+              + '<div>' + TYPO3.lang['formManager.no_references'] + '</div>';
+          }
+
+          html = $(html);
+          $(getDomElementIdentifier('referenceLink'), html).on('click', function(e) {
+            e.preventDefault();
+            Modal.currentModal.trigger('modal-dismiss');
+            document.location = $(this).prop('href');
+          });
+
+          Modal.show(
+            TYPO3.lang['formManager.references.title'],
+            html,
+            Severity.info,
+            modalButtons
+          );
+        }).fail(function(jqXHR, textStatus, errorThrown) {
+          if (jqXHR.status !== 0) {
+            Notification.error(textStatus, errorThrown, 2);
+          }
+        });
+      });
+    };
+
+    /**
+     * @public
+     *
+     * @param string elementIdentifier
+     * @param string type
+     * @return mixed|undefined
+     * @throws 1477506413
+     * @throws 1477506414
+     */
+    function getDomElementIdentifier(elementIdentifier, type) {
+      _formManagerApp.assert(elementIdentifier.length > 0, 'Invalid parameter "elementIdentifier"', 1477506413);
+      _formManagerApp.assert(typeof _domElementIdentifierCache[elementIdentifier] !== "undefined", 'elementIdentifier "' + elementIdentifier + '" does not exist', 1477506414);
+      if (typeof type === "undefined") {
+        type = 'identifier';
+      }
+
+      return _domElementIdentifierCache[elementIdentifier][type] || undefined;
+    };
+
+    /**
+     * @public
+     *
+     * @param object formManagerApp
+     * @return void
+     */
+    function bootstrap(formManagerApp) {
+      _formManagerApp = formManagerApp;
+      _domElementIdentifierCacheSetup();
+      _removeFormSetup();
+      _newFormSetup();
+      _duplicateFormSetup();
+      _showReferencesSetup();
+      $(getDomElementIdentifier('tooltip')).tooltip();
+    };
+
+    /**
+     * Publish the public methods.
+     * Implements the "Revealing Module Pattern".
+     */
+    return {
+      bootstrap: bootstrap
+    };
+  })($, Modal, Severity, Wizard, Icons, Notification);
 });
diff --git a/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js
index 38bf5f7eb0d7..7758ecba0a08 100644
--- a/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js
+++ b/typo3/sysext/form/Resources/Public/JavaScript/Backend/Vendor/jquery.mjs.nestedSortable.js
@@ -10,898 +10,902 @@
  * Licensed under the MIT License
  * http://www.opensource.org/licenses/mit-license.php
  */
-(function( factory ) {
-	"use strict";
+(function(factory) {
+  "use strict";
 
-	if ( typeof define === "function" && define.amd ) {
+  if (typeof define === "function" && define.amd) {
 
-		// AMD. Register as an anonymous module.
-		define([
-			"jquery",
-			"jquery-ui/sortable"
-		], factory );
-	} else {
+    // AMD. Register as an anonymous module.
+    define([
+      "jquery",
+      "jquery-ui/sortable"
+    ], factory);
+  } else {
 
-		// Browser globals
-		factory( window.jQuery );
-	}
+    // Browser globals
+    factory(window.jQuery);
+  }
 }(function($) {
-	"use strict";
-
-	function isOverAxis( x, reference, size ) {
-		return ( x > reference ) && ( x < ( reference + size ) );
-	}
-
-	$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
-
-		options: {
-			disableParentChange: false,
-			doNotClear: false,
-			expandOnHover: 700,
-			isAllowed: function() { return true; },
-			isTree: false,
-			listType: "ol",
-			maxLevels: 0,
-			protectRoot: false,
-			rootID: null,
-			rtl: false,
-			startCollapsed: false,
-			tabSize: 20,
-
-			branchClass: "mjs-nestedSortable-branch",
-			collapsedClass: "mjs-nestedSortable-collapsed",
-			disableNestingClass: "mjs-nestedSortable-no-nesting",
-			errorClass: "mjs-nestedSortable-error",
-			expandedClass: "mjs-nestedSortable-expanded",
-			hoveringClass: "mjs-nestedSortable-hovering",
-			leafClass: "mjs-nestedSortable-leaf",
-			disabledClass: "mjs-nestedSortable-disabled"
-		},
-
-		_create: function() {
-			var self = this,
-				err;
-
-			this.element.data("ui-sortable", this.element.data("mjs-nestedSortable"));
-
-			// mjs - prevent browser from freezing if the HTML is not correct
-			if (!this.element.is(this.options.listType)) {
-				err = "nestedSortable: " +
-					"Please check that the listType option is set to your actual list type";
-
-				throw new Error(err);
-			}
-
-			// if we have a tree with expanding/collapsing functionality,
-			// force 'intersect' tolerance method
-			if (this.options.isTree && this.options.expandOnHover) {
-				this.options.tolerance = "intersect";
-			}
-
-			$.ui.sortable.prototype._create.apply(this, arguments);
-
-			// prepare the tree by applying the right classes
-			// (the CSS is responsible for actual hide/show functionality)
-			if (this.options.isTree) {
-				$(this.items).each(function() {
-					var $li = this.item,
-						hasCollapsedClass = $li.hasClass(self.options.collapsedClass),
-						hasExpandedClass = $li.hasClass(self.options.expandedClass);
-
-					if ($li.children(self.options.listType).length) {
-						$li.addClass(self.options.branchClass);
-						// expand/collapse class only if they have children
-
-						if ( !hasCollapsedClass && !hasExpandedClass ) {
-							if (self.options.startCollapsed) {
-								$li.addClass(self.options.collapsedClass);
-							} else {
-								$li.addClass(self.options.expandedClass);
-							}
-						}
-					} else {
-						$li.addClass(self.options.leafClass);
-					}
-				});
-			}
-		},
-
-		_destroy: function() {
-			this.element
-				.removeData("mjs-nestedSortable")
-				.removeData("ui-sortable");
-			return $.ui.sortable.prototype._destroy.apply(this, arguments);
-		},
-
-		_mouseDrag: function(event) {
-			var i,
-				item,
-				itemElement,
-				intersection,
-				self = this,
-				o = this.options,
-				scrolled = false,
-				$document = $(document),
-				previousTopOffset,
-				parentItem,
-				level,
-				childLevels,
-				itemAfter,
-				itemBefore,
-				newList,
-				method,
-				a,
-				previousItem,
-				nextItem,
-				helperIsNotSibling;
-
-			//Compute the helpers position
-			this.position = this._generatePosition(event);
-			this.positionAbs = this._convertPositionTo("absolute");
-
-			if (!this.lastPositionAbs) {
-				this.lastPositionAbs = this.positionAbs;
-			}
-
-			//Do scrolling
-			if (this.options.scroll) {
-				if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
-
-					if (
-						(
-							this.overflowOffset.top +
-							this.scrollParent[0].offsetHeight
-						) -
-						event.pageY <
-						o.scrollSensitivity
-					) {
-						scrolled = this.scrollParent.scrollTop() + o.scrollSpeed;
-						this.scrollParent.scrollTop(scrolled);
-					} else if (
-						event.pageY -
-						this.overflowOffset.top <
-						o.scrollSensitivity
-					) {
-						scrolled = this.scrollParent.scrollTop() - o.scrollSpeed;
-						this.scrollParent.scrollTop(scrolled);
-					}
-
-					if (
-						(
-							this.overflowOffset.left +
-							this.scrollParent[0].offsetWidth
-						) -
-						event.pageX <
-						o.scrollSensitivity
-					) {
-						scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed;
-						this.scrollParent.scrollLeft(scrolled);
-					} else if (
-						event.pageX -
-						this.overflowOffset.left <
-						o.scrollSensitivity
-					) {
-						scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed;
-						this.scrollParent.scrollLeft(scrolled);
-					}
-
-				} else {
-
-					if (
-						event.pageY -
-						$document.scrollTop() <
-						o.scrollSensitivity
-					) {
-						scrolled = $document.scrollTop() - o.scrollSpeed;
-						$document.scrollTop(scrolled);
-					} else if (
-						$(window).height() -
-						(
-							event.pageY -
-							$document.scrollTop()
-						) <
-						o.scrollSensitivity
-					) {
-						scrolled = $document.scrollTop() + o.scrollSpeed;
-						$document.scrollTop(scrolled);
-					}
-
-					if (
-						event.pageX -
-						$document.scrollLeft() <
-						o.scrollSensitivity
-					) {
-						scrolled = $document.scrollLeft() - o.scrollSpeed;
-						$document.scrollLeft(scrolled);
-					} else if (
-						$(window).width() -
-						(
-							event.pageX -
-							$document.scrollLeft()
-						) <
-						o.scrollSensitivity
-					) {
-						scrolled = $document.scrollLeft() + o.scrollSpeed;
-						$document.scrollLeft(scrolled);
-					}
-
-				}
-
-				if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
-					$.ui.ddmanager.prepareOffsets(this, event);
-				}
-			}
-
-			//Regenerate the absolute position used for position checks
-			this.positionAbs = this._convertPositionTo("absolute");
-
-			// mjs - find the top offset before rearrangement,
-			previousTopOffset = this.placeholder.offset().top;
-
-			//Set the helper position
-			if (!this.options.axis || this.options.axis !== "y") {
-				this.helper[0].style.left = this.position.left + "px";
-			}
-			if (!this.options.axis || this.options.axis !== "x") {
-				this.helper[0].style.top = (this.position.top) + "px";
-			}
-
-			// mjs - check and reset hovering state at each cycle
-			this.hovering = this.hovering ? this.hovering : null;
-			this.mouseentered = this.mouseentered ? this.mouseentered : false;
-
-			// mjs - let's start caching some variables
-			(function() {
-				var _parentItem = this.placeholder.parent().parent();
-				if (_parentItem && _parentItem.closest(".ui-sortable").length) {
-					parentItem = _parentItem;
-				}
-			}.call(this));
-
-			level = this._getLevel(this.placeholder);
-			childLevels = this._getChildLevels(this.helper);
-			newList = document.createElement(o.listType);
-
-			//Rearrange
-			for (i = this.items.length - 1; i >= 0; i--) {
-
-				//Cache variables and intersection, continue if no intersection
-				item = this.items[i];
-				itemElement = item.item[0];
-				intersection = this._intersectsWithPointer(item);
-				if (!intersection) {
-					continue;
-				}
-
-				// Only put the placeholder inside the current Container, skip all
-				// items form other containers. This works because when moving
-				// an item from one container to another the
-				// currentContainer is switched before the placeholder is moved.
-				//
-				// Without this moving items in "sub-sortables" can cause the placeholder to jitter
-				// beetween the outer and inner container.
-				if (item.instance !== this.currentContainer) {
-					continue;
-				}
-
-				// No action if intersected item is disabled
-				// and the element above or below in the direction we're going is also disabled
-				if (itemElement.className.indexOf(o.disabledClass) !== -1) {
-					// Note: intersection hardcoded direction values from
-					// jquery.ui.sortable.js:_intersectsWithPointer
-					if (intersection === 2) {
-						// Going down
-						itemAfter = this.items[i + 1];
-						if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) {
-							continue;
-						}
-
-					} else if (intersection === 1) {
-						// Going up
-						itemBefore = this.items[i - 1];
-						if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) {
-							continue;
-						}
-					}
-				}
-
-				method = intersection === 1 ? "next" : "prev";
-
-				// cannot intersect with itself
-				// no useless actions that have been done before
-				// no action if the item moved is the parent of the item checked
-				if (itemElement !== this.currentItem[0] &&
-					this.placeholder[method]()[0] !== itemElement &&
-					!$.contains(this.placeholder[0], itemElement) &&
-					(
-						this.options.type === "semi-dynamic" ?
-							!$.contains(this.element[0], itemElement) :
-							true
-					)
-				) {
-
-					// mjs - we are intersecting an element:
-					// trigger the mouseenter event and store this state
-					if (!this.mouseentered) {
-						$(itemElement).mouseenter();
-						this.mouseentered = true;
-					}
-
-					// mjs - if the element has children and they are hidden,
-					// show them after a delay (CSS responsible)
-					if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
-						if (!this.hovering) {
-							$(itemElement).addClass(o.hoveringClass);
-							this.hovering = window.setTimeout(function() {
-								$(itemElement)
-									.removeClass(o.collapsedClass)
-									.addClass(o.expandedClass);
-
-								self.refreshPositions();
-								self._trigger("expand", event, self._uiHash());
-							}, o.expandOnHover);
-						}
-					}
-
-					this.direction = intersection === 1 ? "down" : "up";
-
-					// mjs - rearrange the elements and reset timeouts and hovering state
-					if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
-						$(itemElement).mouseleave();
-						this.mouseentered = false;
-						$(itemElement).removeClass(o.hoveringClass);
-						if (this.hovering) {
-							window.clearTimeout(this.hovering);
-						}
-						this.hovering = null;
-
-						// mjs - do not switch container if
-						// it's a root item and 'protectRoot' is true
-						// or if it's not a root item but we are trying to make it root
-						if (o.protectRoot &&
-							!(
-								this.currentItem[0].parentNode === this.element[0] &&
-								// it's a root item
-								itemElement.parentNode !== this.element[0]
-								// it's intersecting a non-root item
-							)
-						) {
-							if (this.currentItem[0].parentNode !== this.element[0] &&
-								itemElement.parentNode === this.element[0]
-							) {
-
-								if ( !$(itemElement).children(o.listType).length) {
-									itemElement.appendChild(newList);
-									if (o.isTree) {
-										$(itemElement)
-											.removeClass(o.leafClass)
-											.addClass(o.branchClass + " " + o.expandedClass);
-									}
-								}
-
-								if (this.direction === "down") {
-									a = $(itemElement).prev().children(o.listType);
-								} else {
-									a = $(itemElement).children(o.listType);
-								}
-
-								if (a[0] !== undefined) {
-									this._rearrange(event, null, a);
-								}
-
-							} else {
-								this._rearrange(event, item);
-							}
-						} else if (!o.protectRoot) {
-							this._rearrange(event, item);
-						}
-					} else {
-						break;
-					}
-
-					// Clear emtpy ul's/ol's
-					this._clearEmpty(itemElement);
-
-					this._trigger("change", event, this._uiHash());
-					break;
-				}
-			}
-
-			// mjs - to find the previous sibling in the list,
-			// keep backtracking until we hit a valid list item.
-			(function() {
-				var _previousItem = this.placeholder.prev();
-				if (_previousItem.length) {
-					previousItem = _previousItem;
-				} else {
-					previousItem = null;
-				}
-			}.call(this));
-
-			if (previousItem != null) {
-				while (
-					previousItem[0].nodeName.toLowerCase() !== "li" ||
-					previousItem[0].className.indexOf(o.disabledClass) !== -1 ||
-					previousItem[0] === this.currentItem[0] ||
-					previousItem[0] === this.helper[0]
-				) {
-					if (previousItem[0].previousSibling) {
-						previousItem = $(previousItem[0].previousSibling);
-					} else {
-						previousItem = null;
-						break;
-					}
-				}
-			}
-
-			// mjs - to find the next sibling in the list,
-			// keep stepping forward until we hit a valid list item.
-			(function() {
-				var _nextItem = this.placeholder.next();
-				if (_nextItem.length) {
-					nextItem = _nextItem;
-				} else {
-					nextItem = null;
-				}
-			}.call(this));
-
-			if (nextItem != null) {
-				while (
-					nextItem[0].nodeName.toLowerCase() !== "li" ||
-					nextItem[0].className.indexOf(o.disabledClass) !== -1 ||
-					nextItem[0] === this.currentItem[0] ||
-					nextItem[0] === this.helper[0]
-				) {
-					if (nextItem[0].nextSibling) {
-						nextItem = $(nextItem[0].nextSibling);
-					} else {
-						nextItem = null;
-						break;
-					}
-				}
-			}
-
-			this.beyondMaxLevels = 0;
-
-			// mjs - if the item is moved to the left, send it one level up
-			// but only if it's at the bottom of the list
-			if (parentItem != null &&
-				nextItem == null &&
-				!(o.protectRoot && parentItem[0].parentNode == this.element[0]) &&
-				(
-					o.rtl &&
-					(
-						this.positionAbs.left +
-						this.helper.outerWidth() > parentItem.offset().left +
-						parentItem.outerWidth()
-					) ||
-					!o.rtl && (this.positionAbs.left < parentItem.offset().left)
-				)
-			) {
-
-				parentItem.after(this.placeholder[0]);
-				helperIsNotSibling = !parentItem
-											.children(o.listItem)
-											.children("li:visible:not(.ui-sortable-helper)")
-											.length;
-				if (o.isTree && helperIsNotSibling) {
-					parentItem
-						.removeClass(this.options.branchClass + " " + this.options.expandedClass)
-						.addClass(this.options.leafClass);
-				}
-                if(typeof parentItem !== 'undefined')
-				    this._clearEmpty(parentItem[0]);
-				this._trigger("change", event, this._uiHash());
-				// mjs - if the item is below a sibling and is moved to the right,
-				// make it a child of that sibling
-			} else if (previousItem != null &&
-				!previousItem.hasClass(o.disableNestingClass) &&
-				(
-					previousItem.children(o.listType).length &&
-					previousItem.children(o.listType).is(":visible") ||
-					!previousItem.children(o.listType).length
-				) &&
-				!(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) &&
-				(
-					o.rtl &&
-					(
-						this.positionAbs.left +
-						this.helper.outerWidth() <
-						previousItem.offset().left +
-						previousItem.outerWidth() -
-						o.tabSize
-					) ||
-					!o.rtl &&
-					(this.positionAbs.left > previousItem.offset().left + o.tabSize)
-				)
-			) {
-
-				this._isAllowed(previousItem, level, level + childLevels + 1);
-
-				if (!previousItem.children(o.listType).length) {
-					previousItem[0].appendChild(newList);
-					if (o.isTree) {
-						previousItem
-							.removeClass(o.leafClass)
-							.addClass(o.branchClass + " " + o.expandedClass);
-					}
-				}
-
-				// mjs - if this item is being moved from the top, add it to the top of the list.
-				if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
-					previousItem.children(o.listType).prepend(this.placeholder);
-				} else {
-					// mjs - otherwise, add it to the bottom of the list.
-					previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
-				}
-                if(typeof parentItem !== 'undefined')
-				    this._clearEmpty(parentItem[0]);
-				this._trigger("change", event, this._uiHash());
-			} else {
-				this._isAllowed(parentItem, level, level + childLevels);
-			}
-
-			//Post events to containers
-			this._contactContainers(event);
-
-			//Interconnect with droppables
-			if ($.ui.ddmanager) {
-				$.ui.ddmanager.drag(this, event);
-			}
-
-			//Call callbacks
-			this._trigger("sort", event, this._uiHash());
-
-			this.lastPositionAbs = this.positionAbs;
-			return false;
-
-		},
-
-		_mouseStop: function(event) {
-			// mjs - if the item is in a position not allowed, send it back
-			if (this.beyondMaxLevels) {
-
-				this.placeholder.removeClass(this.options.errorClass);
-
-				if (this.domPosition.prev) {
-					$(this.domPosition.prev).after(this.placeholder);
-				} else {
-					$(this.domPosition.parent).prepend(this.placeholder);
-				}
-
-				this._trigger("revert", event, this._uiHash());
-
-			}
-
-			// mjs - clear the hovering timeout, just to be sure
-			$("." + this.options.hoveringClass)
-				.mouseleave()
-				.removeClass(this.options.hoveringClass);
-
-			this.mouseentered = false;
-			if (this.hovering) {
-				window.clearTimeout(this.hovering);
-			}
-			this.hovering = null;
-
-			this._relocate_event = event;
-			this._pid_current = $(this.domPosition.parent).parent().attr("id");
-			this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0;
-			$.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event.
-		},
-
-		// mjs - this function is slightly modified
-		// to make it easier to hover over a collapsed element and have it expand
-		_intersectsWithSides: function(item) {
-
-			var half = this.options.isTree ? .8 : .5,
-				isOverBottomHalf = isOverAxis(
-					this.positionAbs.top + this.offset.click.top,
-					item.top + (item.height * half),
-					item.height
-				),
-				isOverTopHalf = isOverAxis(
-					this.positionAbs.top + this.offset.click.top,
-					item.top - (item.height * half),
-					item.height
-				),
-				isOverRightHalf = isOverAxis(
-					this.positionAbs.left + this.offset.click.left,
-					item.left + (item.width / 2),
-					item.width
-				),
-				verticalDirection = this._getDragVerticalDirection(),
-				horizontalDirection = this._getDragHorizontalDirection();
-
-			if (this.floating && horizontalDirection) {
-				return (
-					(horizontalDirection === "right" && isOverRightHalf) ||
-					(horizontalDirection === "left" && !isOverRightHalf)
-				);
-			} else {
-				return verticalDirection && (
-					(verticalDirection === "down" && isOverBottomHalf) ||
-					(verticalDirection === "up" && isOverTopHalf)
-				);
-			}
-
-		},
-
-		_contactContainers: function() {
-
-			if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) {
-				return;
-			}
-
-			$.ui.sortable.prototype._contactContainers.apply(this, arguments);
-
-		},
-
-		_clear: function() {
-			var i,
-				item;
-
-			$.ui.sortable.prototype._clear.apply(this, arguments);
-
-			//relocate event
-			if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") &&
-				this._sort_current === this._uiHash().item.index())) {
-				this._trigger("relocate", this._relocate_event, this._uiHash());
-			}
-
-			// mjs - clean last empty ul/ol
-			for (i = this.items.length - 1; i >= 0; i--) {
-				item = this.items[i].item[0];
-				this._clearEmpty(item);
-			}
-
-		},
-
-		serialize: function(options) {
-
-			var o = $.extend({}, this.options, options),
-				items = this._getItemsAsjQuery(o && o.connected),
-				str = [];
-
-			$(items).each(function() {
-				var res = ($(o.item || this).attr(o.attribute || "id") || "")
-						.match(o.expression || (/(.+)[-=_](.+)/)),
-					pid = ($(o.item || this).parent(o.listType)
-						.parent(o.items)
-						.attr(o.attribute || "id") || "")
-						.match(o.expression || (/(.+)[-=_](.+)/));
-
-				if (res) {
-					str.push(
-						(
-							(o.key || res[1]) +
-							"[" +
-							(o.key && o.expression ? res[1] : res[2]) + "]"
-						) +
-						"=" +
-						(pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
-				}
-			});
-
-			if (!str.length && o.key) {
-				str.push(o.key + "=");
-			}
-
-			return str.join("&");
-
-		},
-
-		toHierarchy: function(options) {
-
-			var o = $.extend({}, this.options, options),
-				ret = [];
-
-			$(this.element).children(o.items).each(function() {
-				var level = _recursiveItems(this);
-				ret.push(level);
-			});
-
-			return ret;
-
-			function _recursiveItems(item) {
-				var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)),
-					currentItem;
-
-				var data = $(item).data();
-				if (data.nestedSortableItem) {
-					delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data
-				}
-
-				if (id) {
-					currentItem = {
-						"id": id[2]
-					};
-
-					currentItem = $.extend({}, currentItem, data); // Combine the two objects
-
-					if ($(item).children(o.listType).children(o.items).length > 0) {
-						currentItem.children = [];
-						$(item).children(o.listType).children(o.items).each(function() {
-							var level = _recursiveItems(this);
-							currentItem.children.push(level);
-						});
-					}
-					return currentItem;
-				}
-			}
-		},
-
-		toArray: function(options) {
-
-			var o = $.extend({}, this.options, options),
-				sDepth = o.startDepthCount || 0,
-				ret = [],
-				left = 1;
-
-			if (!o.excludeRoot) {
-				ret.push({
-					"item_id": o.rootID,
-					"parent_id": null,
-					"depth": sDepth,
-					"left": left,
-					"right": ($(o.items, this.element).length + 1) * 2
-				});
-				left++;
-			}
-
-			$(this.element).children(o.items).each(function() {
-				left = _recursiveArray(this, sDepth, left);
-			});
-
-			ret = ret.sort(function(a, b) { return (a.left - b.left); });
-
-			return ret;
-
-			function _recursiveArray(item, depth, _left) {
-
-				var right = _left + 1,
-					id,
-					pid,
-					parentItem;
-
-				if ($(item).children(o.listType).children(o.items).length > 0) {
-					depth++;
-					$(item).children(o.listType).children(o.items).each(function() {
-						right = _recursiveArray($(this), depth, right);
-					});
-					depth--;
-				}
-
-				id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/));
-
-				if (depth === sDepth) {
-					pid = o.rootID;
-				} else {
-					parentItem = ($(item).parent(o.listType)
-											.parent(o.items)
-											.attr(o.attribute || "id"))
-											.match(o.expression || (/(.+)[-=_](.+)/));
-					pid = parentItem[2];
-				}
-
-				if (id) {
-					var data = $(item).children('div').data();
-					var itemObj = $.extend( data, {
-						"id":id[2],
-						"parent_id":pid,
-						"depth":depth,
-						"left":_left,
-						"right":right
-						} );
-					ret.push( itemObj );
-				}
-
-				_left = right + 1;
-				return _left;
-			}
-
-		},
-
-		_clearEmpty: function (item) {
-			function replaceClass(elem, search, replace, swap) {
-				if (swap) {
-					search = [replace, replace = search][0];
-				}
-
-				$(elem).removeClass(search).addClass(replace);
-			}
-
-			var o = this.options,
-				childrenList = $(item).children(o.listType),
-				hasChildren = childrenList.has('li').length;
-
-			var doNotClear =
-				o.doNotClear ||
-				hasChildren ||
-				o.protectRoot && $(item)[0] === this.element[0];
-
-			if (o.isTree) {
-				replaceClass(item, o.branchClass, o.leafClass, doNotClear);
-			}
-
-			if (!doNotClear) {
-				childrenList.parent().removeClass(o.expandedClass);
-				childrenList.remove();
-			}
-		},
-
-		_getLevel: function(item) {
-
-			var level = 1,
-				list;
-
-			if (this.options.listType) {
-				list = item.closest(this.options.listType);
-				while (list && list.length > 0 && !list.is(".ui-sortable")) {
-					level++;
-					list = list.parent().closest(this.options.listType);
-				}
-			}
-
-			return level;
-		},
-
-		_getChildLevels: function(parent, depth) {
-			var self = this,
-				o = this.options,
-				result = 0;
-			depth = depth || 0;
-
-			$(parent).children(o.listType).children(o.items).each(function(index, child) {
-				result = Math.max(self._getChildLevels(child, depth + 1), result);
-			});
-
-			return depth ? result + 1 : result;
-		},
-
-		_isAllowed: function(parentItem, level, levels) {
-			var o = this.options,
-				// this takes into account the maxLevels set to the recipient list
-				maxLevels = this
-					.placeholder
-					.closest(".ui-sortable")
-					.nestedSortable("option", "maxLevels"),
-
-				// Check if the parent has changed to prevent it, when o.disableParentChange is true
-				oldParent = this.currentItem.parent().parent(),
-				disabledByParentchange = o.disableParentChange && (
-					//From somewhere to somewhere else, except the root
-					typeof parentItem !== 'undefined' && !oldParent.is(parentItem) ||
-					typeof parentItem === 'undefined' && oldParent.is("li")	//From somewhere to the root
-				);
-			// mjs - is the root protected?
-			// mjs - are we nesting too deep?
-			if (
-				disabledByParentchange ||
-				!o.isAllowed(this.placeholder, parentItem, this.currentItem)
-			) {
-				this.placeholder.addClass(o.errorClass);
-				if (maxLevels < levels && maxLevels !== 0) {
-					this.beyondMaxLevels = levels - maxLevels;
-				} else {
-					this.beyondMaxLevels = 1;
-				}
-			} else {
-				if (maxLevels < levels && maxLevels !== 0) {
-					this.placeholder.addClass(o.errorClass);
-					this.beyondMaxLevels = levels - maxLevels;
-				} else {
-					this.placeholder.removeClass(o.errorClass);
-					this.beyondMaxLevels = 0;
-				}
-			}
-		}
-
-	}));
-
-	$.mjs.nestedSortable.prototype.options = $.extend(
-		{},
-		$.ui.sortable.prototype.options,
-		$.mjs.nestedSortable.prototype.options
-	);
+  "use strict";
+
+  function isOverAxis(x, reference, size) {
+    return (x > reference) && (x < (reference + size));
+  }
+
+  $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
+
+    options: {
+      disableParentChange: false,
+      doNotClear: false,
+      expandOnHover: 700,
+      isAllowed: function() {
+        return true;
+      },
+      isTree: false,
+      listType: "ol",
+      maxLevels: 0,
+      protectRoot: false,
+      rootID: null,
+      rtl: false,
+      startCollapsed: false,
+      tabSize: 20,
+
+      branchClass: "mjs-nestedSortable-branch",
+      collapsedClass: "mjs-nestedSortable-collapsed",
+      disableNestingClass: "mjs-nestedSortable-no-nesting",
+      errorClass: "mjs-nestedSortable-error",
+      expandedClass: "mjs-nestedSortable-expanded",
+      hoveringClass: "mjs-nestedSortable-hovering",
+      leafClass: "mjs-nestedSortable-leaf",
+      disabledClass: "mjs-nestedSortable-disabled"
+    },
+
+    _create: function() {
+      var self = this,
+        err;
+
+      this.element.data("ui-sortable", this.element.data("mjs-nestedSortable"));
+
+      // mjs - prevent browser from freezing if the HTML is not correct
+      if (!this.element.is(this.options.listType)) {
+        err = "nestedSortable: " +
+          "Please check that the listType option is set to your actual list type";
+
+        throw new Error(err);
+      }
+
+      // if we have a tree with expanding/collapsing functionality,
+      // force 'intersect' tolerance method
+      if (this.options.isTree && this.options.expandOnHover) {
+        this.options.tolerance = "intersect";
+      }
+
+      $.ui.sortable.prototype._create.apply(this, arguments);
+
+      // prepare the tree by applying the right classes
+      // (the CSS is responsible for actual hide/show functionality)
+      if (this.options.isTree) {
+        $(this.items).each(function() {
+          var $li = this.item,
+            hasCollapsedClass = $li.hasClass(self.options.collapsedClass),
+            hasExpandedClass = $li.hasClass(self.options.expandedClass);
+
+          if ($li.children(self.options.listType).length) {
+            $li.addClass(self.options.branchClass);
+            // expand/collapse class only if they have children
+
+            if (!hasCollapsedClass && !hasExpandedClass) {
+              if (self.options.startCollapsed) {
+                $li.addClass(self.options.collapsedClass);
+              } else {
+                $li.addClass(self.options.expandedClass);
+              }
+            }
+          } else {
+            $li.addClass(self.options.leafClass);
+          }
+        });
+      }
+    },
+
+    _destroy: function() {
+      this.element
+        .removeData("mjs-nestedSortable")
+        .removeData("ui-sortable");
+      return $.ui.sortable.prototype._destroy.apply(this, arguments);
+    },
+
+    _mouseDrag: function(event) {
+      var i,
+        item,
+        itemElement,
+        intersection,
+        self = this,
+        o = this.options,
+        scrolled = false,
+        $document = $(document),
+        previousTopOffset,
+        parentItem,
+        level,
+        childLevels,
+        itemAfter,
+        itemBefore,
+        newList,
+        method,
+        a,
+        previousItem,
+        nextItem,
+        helperIsNotSibling;
+
+      //Compute the helpers position
+      this.position = this._generatePosition(event);
+      this.positionAbs = this._convertPositionTo("absolute");
+
+      if (!this.lastPositionAbs) {
+        this.lastPositionAbs = this.positionAbs;
+      }
+
+      //Do scrolling
+      if (this.options.scroll) {
+        if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
+
+          if (
+            (
+              this.overflowOffset.top +
+              this.scrollParent[0].offsetHeight
+            ) -
+            event.pageY <
+            o.scrollSensitivity
+          ) {
+            scrolled = this.scrollParent.scrollTop() + o.scrollSpeed;
+            this.scrollParent.scrollTop(scrolled);
+          } else if (
+            event.pageY -
+            this.overflowOffset.top <
+            o.scrollSensitivity
+          ) {
+            scrolled = this.scrollParent.scrollTop() - o.scrollSpeed;
+            this.scrollParent.scrollTop(scrolled);
+          }
+
+          if (
+            (
+              this.overflowOffset.left +
+              this.scrollParent[0].offsetWidth
+            ) -
+            event.pageX <
+            o.scrollSensitivity
+          ) {
+            scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed;
+            this.scrollParent.scrollLeft(scrolled);
+          } else if (
+            event.pageX -
+            this.overflowOffset.left <
+            o.scrollSensitivity
+          ) {
+            scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed;
+            this.scrollParent.scrollLeft(scrolled);
+          }
+
+        } else {
+
+          if (
+            event.pageY -
+            $document.scrollTop() <
+            o.scrollSensitivity
+          ) {
+            scrolled = $document.scrollTop() - o.scrollSpeed;
+            $document.scrollTop(scrolled);
+          } else if (
+            $(window).height() -
+            (
+              event.pageY -
+              $document.scrollTop()
+            ) <
+            o.scrollSensitivity
+          ) {
+            scrolled = $document.scrollTop() + o.scrollSpeed;
+            $document.scrollTop(scrolled);
+          }
+
+          if (
+            event.pageX -
+            $document.scrollLeft() <
+            o.scrollSensitivity
+          ) {
+            scrolled = $document.scrollLeft() - o.scrollSpeed;
+            $document.scrollLeft(scrolled);
+          } else if (
+            $(window).width() -
+            (
+              event.pageX -
+              $document.scrollLeft()
+            ) <
+            o.scrollSensitivity
+          ) {
+            scrolled = $document.scrollLeft() + o.scrollSpeed;
+            $document.scrollLeft(scrolled);
+          }
+
+        }
+
+        if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
+          $.ui.ddmanager.prepareOffsets(this, event);
+        }
+      }
+
+      //Regenerate the absolute position used for position checks
+      this.positionAbs = this._convertPositionTo("absolute");
+
+      // mjs - find the top offset before rearrangement,
+      previousTopOffset = this.placeholder.offset().top;
+
+      //Set the helper position
+      if (!this.options.axis || this.options.axis !== "y") {
+        this.helper[0].style.left = this.position.left + "px";
+      }
+      if (!this.options.axis || this.options.axis !== "x") {
+        this.helper[0].style.top = (this.position.top) + "px";
+      }
+
+      // mjs - check and reset hovering state at each cycle
+      this.hovering = this.hovering ? this.hovering : null;
+      this.mouseentered = this.mouseentered ? this.mouseentered : false;
+
+      // mjs - let's start caching some variables
+      (function() {
+        var _parentItem = this.placeholder.parent().parent();
+        if (_parentItem && _parentItem.closest(".ui-sortable").length) {
+          parentItem = _parentItem;
+        }
+      }.call(this));
+
+      level = this._getLevel(this.placeholder);
+      childLevels = this._getChildLevels(this.helper);
+      newList = document.createElement(o.listType);
+
+      //Rearrange
+      for (i = this.items.length - 1; i >= 0; i--) {
+
+        //Cache variables and intersection, continue if no intersection
+        item = this.items[i];
+        itemElement = item.item[0];
+        intersection = this._intersectsWithPointer(item);
+        if (!intersection) {
+          continue;
+        }
+
+        // Only put the placeholder inside the current Container, skip all
+        // items form other containers. This works because when moving
+        // an item from one container to another the
+        // currentContainer is switched before the placeholder is moved.
+        //
+        // Without this moving items in "sub-sortables" can cause the placeholder to jitter
+        // beetween the outer and inner container.
+        if (item.instance !== this.currentContainer) {
+          continue;
+        }
+
+        // No action if intersected item is disabled
+        // and the element above or below in the direction we're going is also disabled
+        if (itemElement.className.indexOf(o.disabledClass) !== -1) {
+          // Note: intersection hardcoded direction values from
+          // jquery.ui.sortable.js:_intersectsWithPointer
+          if (intersection === 2) {
+            // Going down
+            itemAfter = this.items[i + 1];
+            if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) {
+              continue;
+            }
+
+          } else if (intersection === 1) {
+            // Going up
+            itemBefore = this.items[i - 1];
+            if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) {
+              continue;
+            }
+          }
+        }
+
+        method = intersection === 1 ? "next" : "prev";
+
+        // cannot intersect with itself
+        // no useless actions that have been done before
+        // no action if the item moved is the parent of the item checked
+        if (itemElement !== this.currentItem[0] &&
+          this.placeholder[method]()[0] !== itemElement &&
+          !$.contains(this.placeholder[0], itemElement) &&
+          (
+            this.options.type === "semi-dynamic" ?
+              !$.contains(this.element[0], itemElement) :
+              true
+          )
+        ) {
+
+          // mjs - we are intersecting an element:
+          // trigger the mouseenter event and store this state
+          if (!this.mouseentered) {
+            $(itemElement).mouseenter();
+            this.mouseentered = true;
+          }
+
+          // mjs - if the element has children and they are hidden,
+          // show them after a delay (CSS responsible)
+          if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
+            if (!this.hovering) {
+              $(itemElement).addClass(o.hoveringClass);
+              this.hovering = window.setTimeout(function() {
+                $(itemElement)
+                  .removeClass(o.collapsedClass)
+                  .addClass(o.expandedClass);
+
+                self.refreshPositions();
+                self._trigger("expand", event, self._uiHash());
+              }, o.expandOnHover);
+            }
+          }
+
+          this.direction = intersection === 1 ? "down" : "up";
+
+          // mjs - rearrange the elements and reset timeouts and hovering state
+          if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
+            $(itemElement).mouseleave();
+            this.mouseentered = false;
+            $(itemElement).removeClass(o.hoveringClass);
+            if (this.hovering) {
+              window.clearTimeout(this.hovering);
+            }
+            this.hovering = null;
+
+            // mjs - do not switch container if
+            // it's a root item and 'protectRoot' is true
+            // or if it's not a root item but we are trying to make it root
+            if (o.protectRoot &&
+              !(
+                this.currentItem[0].parentNode === this.element[0] &&
+                // it's a root item
+                itemElement.parentNode !== this.element[0]
+                // it's intersecting a non-root item
+              )
+            ) {
+              if (this.currentItem[0].parentNode !== this.element[0] &&
+                itemElement.parentNode === this.element[0]
+              ) {
+
+                if (!$(itemElement).children(o.listType).length) {
+                  itemElement.appendChild(newList);
+                  if (o.isTree) {
+                    $(itemElement)
+                      .removeClass(o.leafClass)
+                      .addClass(o.branchClass + " " + o.expandedClass);
+                  }
+                }
+
+                if (this.direction === "down") {
+                  a = $(itemElement).prev().children(o.listType);
+                } else {
+                  a = $(itemElement).children(o.listType);
+                }
+
+                if (a[0] !== undefined) {
+                  this._rearrange(event, null, a);
+                }
+
+              } else {
+                this._rearrange(event, item);
+              }
+            } else if (!o.protectRoot) {
+              this._rearrange(event, item);
+            }
+          } else {
+            break;
+          }
+
+          // Clear emtpy ul's/ol's
+          this._clearEmpty(itemElement);
+
+          this._trigger("change", event, this._uiHash());
+          break;
+        }
+      }
+
+      // mjs - to find the previous sibling in the list,
+      // keep backtracking until we hit a valid list item.
+      (function() {
+        var _previousItem = this.placeholder.prev();
+        if (_previousItem.length) {
+          previousItem = _previousItem;
+        } else {
+          previousItem = null;
+        }
+      }.call(this));
+
+      if (previousItem != null) {
+        while (
+          previousItem[0].nodeName.toLowerCase() !== "li" ||
+          previousItem[0].className.indexOf(o.disabledClass) !== -1 ||
+          previousItem[0] === this.currentItem[0] ||
+          previousItem[0] === this.helper[0]
+          ) {
+          if (previousItem[0].previousSibling) {
+            previousItem = $(previousItem[0].previousSibling);
+          } else {
+            previousItem = null;
+            break;
+          }
+        }
+      }
+
+      // mjs - to find the next sibling in the list,
+      // keep stepping forward until we hit a valid list item.
+      (function() {
+        var _nextItem = this.placeholder.next();
+        if (_nextItem.length) {
+          nextItem = _nextItem;
+        } else {
+          nextItem = null;
+        }
+      }.call(this));
+
+      if (nextItem != null) {
+        while (
+          nextItem[0].nodeName.toLowerCase() !== "li" ||
+          nextItem[0].className.indexOf(o.disabledClass) !== -1 ||
+          nextItem[0] === this.currentItem[0] ||
+          nextItem[0] === this.helper[0]
+          ) {
+          if (nextItem[0].nextSibling) {
+            nextItem = $(nextItem[0].nextSibling);
+          } else {
+            nextItem = null;
+            break;
+          }
+        }
+      }
+
+      this.beyondMaxLevels = 0;
+
+      // mjs - if the item is moved to the left, send it one level up
+      // but only if it's at the bottom of the list
+      if (parentItem != null &&
+        nextItem == null &&
+        !(o.protectRoot && parentItem[0].parentNode == this.element[0]) &&
+        (
+          o.rtl &&
+          (
+            this.positionAbs.left +
+            this.helper.outerWidth() > parentItem.offset().left +
+            parentItem.outerWidth()
+          ) ||
+          !o.rtl && (this.positionAbs.left < parentItem.offset().left)
+        )
+      ) {
+
+        parentItem.after(this.placeholder[0]);
+        helperIsNotSibling = !parentItem
+          .children(o.listItem)
+          .children("li:visible:not(.ui-sortable-helper)")
+          .length;
+        if (o.isTree && helperIsNotSibling) {
+          parentItem
+            .removeClass(this.options.branchClass + " " + this.options.expandedClass)
+            .addClass(this.options.leafClass);
+        }
+        if (typeof parentItem !== 'undefined')
+          this._clearEmpty(parentItem[0]);
+        this._trigger("change", event, this._uiHash());
+        // mjs - if the item is below a sibling and is moved to the right,
+        // make it a child of that sibling
+      } else if (previousItem != null &&
+        !previousItem.hasClass(o.disableNestingClass) &&
+        (
+          previousItem.children(o.listType).length &&
+          previousItem.children(o.listType).is(":visible") ||
+          !previousItem.children(o.listType).length
+        ) &&
+        !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) &&
+        (
+          o.rtl &&
+          (
+            this.positionAbs.left +
+            this.helper.outerWidth() <
+            previousItem.offset().left +
+            previousItem.outerWidth() -
+            o.tabSize
+          ) ||
+          !o.rtl &&
+          (this.positionAbs.left > previousItem.offset().left + o.tabSize)
+        )
+      ) {
+
+        this._isAllowed(previousItem, level, level + childLevels + 1);
+
+        if (!previousItem.children(o.listType).length) {
+          previousItem[0].appendChild(newList);
+          if (o.isTree) {
+            previousItem
+              .removeClass(o.leafClass)
+              .addClass(o.branchClass + " " + o.expandedClass);
+          }
+        }
+
+        // mjs - if this item is being moved from the top, add it to the top of the list.
+        if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
+          previousItem.children(o.listType).prepend(this.placeholder);
+        } else {
+          // mjs - otherwise, add it to the bottom of the list.
+          previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
+        }
+        if (typeof parentItem !== 'undefined')
+          this._clearEmpty(parentItem[0]);
+        this._trigger("change", event, this._uiHash());
+      } else {
+        this._isAllowed(parentItem, level, level + childLevels);
+      }
+
+      //Post events to containers
+      this._contactContainers(event);
+
+      //Interconnect with droppables
+      if ($.ui.ddmanager) {
+        $.ui.ddmanager.drag(this, event);
+      }
+
+      //Call callbacks
+      this._trigger("sort", event, this._uiHash());
+
+      this.lastPositionAbs = this.positionAbs;
+      return false;
+
+    },
+
+    _mouseStop: function(event) {
+      // mjs - if the item is in a position not allowed, send it back
+      if (this.beyondMaxLevels) {
+
+        this.placeholder.removeClass(this.options.errorClass);
+
+        if (this.domPosition.prev) {
+          $(this.domPosition.prev).after(this.placeholder);
+        } else {
+          $(this.domPosition.parent).prepend(this.placeholder);
+        }
+
+        this._trigger("revert", event, this._uiHash());
+
+      }
+
+      // mjs - clear the hovering timeout, just to be sure
+      $("." + this.options.hoveringClass)
+        .mouseleave()
+        .removeClass(this.options.hoveringClass);
+
+      this.mouseentered = false;
+      if (this.hovering) {
+        window.clearTimeout(this.hovering);
+      }
+      this.hovering = null;
+
+      this._relocate_event = event;
+      this._pid_current = $(this.domPosition.parent).parent().attr("id");
+      this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0;
+      $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event.
+    },
+
+    // mjs - this function is slightly modified
+    // to make it easier to hover over a collapsed element and have it expand
+    _intersectsWithSides: function(item) {
+
+      var half = this.options.isTree ? .8 : .5,
+        isOverBottomHalf = isOverAxis(
+          this.positionAbs.top + this.offset.click.top,
+          item.top + (item.height * half),
+          item.height
+        ),
+        isOverTopHalf = isOverAxis(
+          this.positionAbs.top + this.offset.click.top,
+          item.top - (item.height * half),
+          item.height
+        ),
+        isOverRightHalf = isOverAxis(
+          this.positionAbs.left + this.offset.click.left,
+          item.left + (item.width / 2),
+          item.width
+        ),
+        verticalDirection = this._getDragVerticalDirection(),
+        horizontalDirection = this._getDragHorizontalDirection();
+
+      if (this.floating && horizontalDirection) {
+        return (
+          (horizontalDirection === "right" && isOverRightHalf) ||
+          (horizontalDirection === "left" && !isOverRightHalf)
+        );
+      } else {
+        return verticalDirection && (
+          (verticalDirection === "down" && isOverBottomHalf) ||
+          (verticalDirection === "up" && isOverTopHalf)
+        );
+      }
+
+    },
+
+    _contactContainers: function() {
+
+      if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0]) {
+        return;
+      }
+
+      $.ui.sortable.prototype._contactContainers.apply(this, arguments);
+
+    },
+
+    _clear: function() {
+      var i,
+        item;
+
+      $.ui.sortable.prototype._clear.apply(this, arguments);
+
+      //relocate event
+      if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") &&
+          this._sort_current === this._uiHash().item.index())) {
+        this._trigger("relocate", this._relocate_event, this._uiHash());
+      }
+
+      // mjs - clean last empty ul/ol
+      for (i = this.items.length - 1; i >= 0; i--) {
+        item = this.items[i].item[0];
+        this._clearEmpty(item);
+      }
+
+    },
+
+    serialize: function(options) {
+
+      var o = $.extend({}, this.options, options),
+        items = this._getItemsAsjQuery(o && o.connected),
+        str = [];
+
+      $(items).each(function() {
+        var res = ($(o.item || this).attr(o.attribute || "id") || "")
+            .match(o.expression || (/(.+)[-=_](.+)/)),
+          pid = ($(o.item || this).parent(o.listType)
+            .parent(o.items)
+            .attr(o.attribute || "id") || "")
+            .match(o.expression || (/(.+)[-=_](.+)/));
+
+        if (res) {
+          str.push(
+            (
+              (o.key || res[1]) +
+              "[" +
+              (o.key && o.expression ? res[1] : res[2]) + "]"
+            ) +
+            "=" +
+            (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
+        }
+      });
+
+      if (!str.length && o.key) {
+        str.push(o.key + "=");
+      }
+
+      return str.join("&");
+
+    },
+
+    toHierarchy: function(options) {
+
+      var o = $.extend({}, this.options, options),
+        ret = [];
+
+      $(this.element).children(o.items).each(function() {
+        var level = _recursiveItems(this);
+        ret.push(level);
+      });
+
+      return ret;
+
+      function _recursiveItems(item) {
+        var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)),
+          currentItem;
+
+        var data = $(item).data();
+        if (data.nestedSortableItem) {
+          delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data
+        }
+
+        if (id) {
+          currentItem = {
+            "id": id[2]
+          };
+
+          currentItem = $.extend({}, currentItem, data); // Combine the two objects
+
+          if ($(item).children(o.listType).children(o.items).length > 0) {
+            currentItem.children = [];
+            $(item).children(o.listType).children(o.items).each(function() {
+              var level = _recursiveItems(this);
+              currentItem.children.push(level);
+            });
+          }
+          return currentItem;
+        }
+      }
+    },
+
+    toArray: function(options) {
+
+      var o = $.extend({}, this.options, options),
+        sDepth = o.startDepthCount || 0,
+        ret = [],
+        left = 1;
+
+      if (!o.excludeRoot) {
+        ret.push({
+          "item_id": o.rootID,
+          "parent_id": null,
+          "depth": sDepth,
+          "left": left,
+          "right": ($(o.items, this.element).length + 1) * 2
+        });
+        left++;
+      }
+
+      $(this.element).children(o.items).each(function() {
+        left = _recursiveArray(this, sDepth, left);
+      });
+
+      ret = ret.sort(function(a, b) {
+        return (a.left - b.left);
+      });
+
+      return ret;
+
+      function _recursiveArray(item, depth, _left) {
+
+        var right = _left + 1,
+          id,
+          pid,
+          parentItem;
+
+        if ($(item).children(o.listType).children(o.items).length > 0) {
+          depth++;
+          $(item).children(o.listType).children(o.items).each(function() {
+            right = _recursiveArray($(this), depth, right);
+          });
+          depth--;
+        }
+
+        id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/));
+
+        if (depth === sDepth) {
+          pid = o.rootID;
+        } else {
+          parentItem = ($(item).parent(o.listType)
+            .parent(o.items)
+            .attr(o.attribute || "id"))
+            .match(o.expression || (/(.+)[-=_](.+)/));
+          pid = parentItem[2];
+        }
+
+        if (id) {
+          var data = $(item).children('div').data();
+          var itemObj = $.extend(data, {
+            "id": id[2],
+            "parent_id": pid,
+            "depth": depth,
+            "left": _left,
+            "right": right
+          });
+          ret.push(itemObj);
+        }
+
+        _left = right + 1;
+        return _left;
+      }
+
+    },
+
+    _clearEmpty: function(item) {
+      function replaceClass(elem, search, replace, swap) {
+        if (swap) {
+          search = [replace, replace = search][0];
+        }
+
+        $(elem).removeClass(search).addClass(replace);
+      }
+
+      var o = this.options,
+        childrenList = $(item).children(o.listType),
+        hasChildren = childrenList.has('li').length;
+
+      var doNotClear =
+        o.doNotClear ||
+        hasChildren ||
+        o.protectRoot && $(item)[0] === this.element[0];
+
+      if (o.isTree) {
+        replaceClass(item, o.branchClass, o.leafClass, doNotClear);
+      }
+
+      if (!doNotClear) {
+        childrenList.parent().removeClass(o.expandedClass);
+        childrenList.remove();
+      }
+    },
+
+    _getLevel: function(item) {
+
+      var level = 1,
+        list;
+
+      if (this.options.listType) {
+        list = item.closest(this.options.listType);
+        while (list && list.length > 0 && !list.is(".ui-sortable")) {
+          level++;
+          list = list.parent().closest(this.options.listType);
+        }
+      }
+
+      return level;
+    },
+
+    _getChildLevels: function(parent, depth) {
+      var self = this,
+        o = this.options,
+        result = 0;
+      depth = depth || 0;
+
+      $(parent).children(o.listType).children(o.items).each(function(index, child) {
+        result = Math.max(self._getChildLevels(child, depth + 1), result);
+      });
+
+      return depth ? result + 1 : result;
+    },
+
+    _isAllowed: function(parentItem, level, levels) {
+      var o = this.options,
+        // this takes into account the maxLevels set to the recipient list
+        maxLevels = this
+          .placeholder
+          .closest(".ui-sortable")
+          .nestedSortable("option", "maxLevels"),
+
+        // Check if the parent has changed to prevent it, when o.disableParentChange is true
+        oldParent = this.currentItem.parent().parent(),
+        disabledByParentchange = o.disableParentChange && (
+          //From somewhere to somewhere else, except the root
+          typeof parentItem !== 'undefined' && !oldParent.is(parentItem) ||
+          typeof parentItem === 'undefined' && oldParent.is("li")	//From somewhere to the root
+        );
+      // mjs - is the root protected?
+      // mjs - are we nesting too deep?
+      if (
+        disabledByParentchange ||
+        !o.isAllowed(this.placeholder, parentItem, this.currentItem)
+      ) {
+        this.placeholder.addClass(o.errorClass);
+        if (maxLevels < levels && maxLevels !== 0) {
+          this.beyondMaxLevels = levels - maxLevels;
+        } else {
+          this.beyondMaxLevels = 1;
+        }
+      } else {
+        if (maxLevels < levels && maxLevels !== 0) {
+          this.placeholder.addClass(o.errorClass);
+          this.beyondMaxLevels = levels - maxLevels;
+        } else {
+          this.placeholder.removeClass(o.errorClass);
+          this.beyondMaxLevels = 0;
+        }
+      }
+    }
+
+  }));
+
+  $.mjs.nestedSortable.prototype.options = $.extend(
+    {},
+    $.ui.sortable.prototype.options,
+    $.mjs.nestedSortable.prototype.options
+  );
 }));
diff --git a/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js b/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js
index 7ad63b57787f..02c0ac543ca2 100644
--- a/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js
+++ b/typo3/sysext/impexp/Resources/Public/JavaScript/ContextMenuActions.js
@@ -17,40 +17,40 @@
  * JavaScript to handle import/export actions from context menu
  * @exports TYPO3/CMS/Impexp/ContextMenuActions
  */
-define(function () {
-    'use strict';
+define(function() {
+  'use strict';
 
-    /**
-     * @exports TYPO3/CMS/Impexp/ContextMenuActions
-     */
-    var ContextMenuActions = {};
+  /**
+   * @exports TYPO3/CMS/Impexp/ContextMenuActions
+   */
+  var ContextMenuActions = {};
 
-    ContextMenuActions.exportT3d = function (table, uid) {
-        if (table === 'pages') {
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.ImportExport.moduleUrl +
-                '&tx_impexp[action]=export&' +
-                'id=0&tx_impexp[pagetree][id]=' + uid +
-                '&tx_impexp[pagetree][levels]=0' +
-                '&tx_impexp[pagetree][tables][]=_ALL'
-            );
-        } else {
-            top.TYPO3.Backend.ContentContainer.setUrl(
-                top.TYPO3.settings.ImportExport.moduleUrl +
-                '&tx_impexp[action]=export' +
-                '&tx_impexp[record][]=' + table + ':' + uid +
-                '&tx_impexp[external_ref][tables][]=_ALL'
-            );
-        }
-    };
+  ContextMenuActions.exportT3d = function(table, uid) {
+    if (table === 'pages') {
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.ImportExport.moduleUrl +
+        '&tx_impexp[action]=export&' +
+        'id=0&tx_impexp[pagetree][id]=' + uid +
+        '&tx_impexp[pagetree][levels]=0' +
+        '&tx_impexp[pagetree][tables][]=_ALL'
+      );
+    } else {
+      top.TYPO3.Backend.ContentContainer.setUrl(
+        top.TYPO3.settings.ImportExport.moduleUrl +
+        '&tx_impexp[action]=export' +
+        '&tx_impexp[record][]=' + table + ':' + uid +
+        '&tx_impexp[external_ref][tables][]=_ALL'
+      );
+    }
+  };
 
-    ContextMenuActions.importT3d = function (table, uid) {
-        top.TYPO3.Backend.ContentContainer.setUrl(
-            top.TYPO3.settings.ImportExport.moduleUrl +
-            '&id=' + uid +
-            '&table=' + table + '&tx_impexp[action]=import'
-        );
-    };
+  ContextMenuActions.importT3d = function(table, uid) {
+    top.TYPO3.Backend.ContentContainer.setUrl(
+      top.TYPO3.settings.ImportExport.moduleUrl +
+      '&id=' + uid +
+      '&table=' + table + '&tx_impexp[action]=import'
+    );
+  };
 
-    return ContextMenuActions;
+  return ContextMenuActions;
 });
diff --git a/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js b/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js
index 7dba828d44ac..a1643a063dd0 100644
--- a/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js
+++ b/typo3/sysext/impexp/Resources/Public/JavaScript/ImportExport.js
@@ -16,29 +16,29 @@
  * JavaScript to handle confirm windows in the Import/Export module
  * @exports TYPO3/CMS/Impexp/ImportExport
  */
-define(['jquery', 'TYPO3/CMS/Backend/Modal'], function ($, Modal) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Backend/Modal'], function($, Modal) {
+  'use strict';
 
-	$(function() {
-		$(document).on('click', '.t3js-confirm-trigger', function() {
-			var $button = $(this);
-			Modal.confirm($button.data('title'), $button.data('message'))
-				.on('confirm.button.ok', function() {
-					$('#t3js-submit-field')
-						.attr('name', $button.attr('name'))
-						.closest('form').submit();
-					Modal.currentModal.trigger('modal-dismiss');
-				})
-				.on('confirm.button.cancel', function() {
-					Modal.currentModal.trigger('modal-dismiss');
-				});
-		});
+  $(function() {
+    $(document).on('click', '.t3js-confirm-trigger', function() {
+      var $button = $(this);
+      Modal.confirm($button.data('title'), $button.data('message'))
+        .on('confirm.button.ok', function() {
+          $('#t3js-submit-field')
+            .attr('name', $button.attr('name'))
+            .closest('form').submit();
+          Modal.currentModal.trigger('modal-dismiss');
+        })
+        .on('confirm.button.cancel', function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        });
+    });
 
-		$('.t3js-impexp-toggledisabled').on('click', function() {
-			var $checkboxes = $('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');
-			if ($checkboxes.length) {
-				$checkboxes.prop('checked', !$checkboxes.get(0).checked);
-			}
-		});
-	});
+    $('.t3js-impexp-toggledisabled').on('click', function() {
+      var $checkboxes = $('table.t3js-impexp-preview tr[data-active="hidden"] input.t3js-exclude-checkbox');
+      if ($checkboxes.length) {
+        $checkboxes.prop('checked', !$checkboxes.get(0).checked);
+      }
+    });
+  });
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Install.js b/typo3/sysext/install/Resources/Public/JavaScript/Install.js
index 0b96aad1608d..2dc48c2203f7 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Install.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Install.js
@@ -12,12 +12,12 @@
  */
 
 require([
-	'jquery',
-	'TYPO3/CMS/Install/Router'
+  'jquery',
+  'TYPO3/CMS/Install/Router'
 ], function($, Router) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		Router.initialize();
-	});
+  $(function() {
+    Router.initialize();
+  });
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Installer.js b/typo3/sysext/install/Resources/Public/JavaScript/Installer.js
index 3213fe76b4f7..e5cdaf00fc63 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Installer.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Installer.js
@@ -15,464 +15,464 @@
  * Walk through the installation process of TYPO3
  */
 require([
-	'jquery',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/PasswordStrength'
+  'jquery',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/PasswordStrength'
 ], function($, InfoBox, Severity, ProgressBar, PasswordStrength) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		Installer.initialize();
-	});
+  $(function() {
+    Installer.initialize();
+  });
 
-	var Installer = {
-		selectorBody: '.t3js-body',
-		selectorMainContent: '.t3js-installer-content',
-		selectorProgressBar: '.t3js-installer-progress',
-		selectorExecuteDatabaseConnectToken: '#t3js-installer-databaseConnect-execute-token',
-		selectorExecuteDatabaseSelectToken: '#t3js-installer-databaseSelect-execute-token',
-		selectorExecuteDatabaseDataToken: '#t3js-installer-databaseData-execute-token',
-		selectorExecuteDefaultConfigurationToken: '#t3js-installer-defaultConfiguration-execute-token',
-		selectorDatabaseConnectOutput: '.t3js-installer-databaseConnect-output',
-		selectorDatabaseSelectOutput: '.t3js-installer-databaseSelect-output',
-		selectorDatabaseDataOutput: '.t3js-installer-databaseData-output',
-		selectorDefaultConfigurationOutput: '.t3js-installer-defaultConfiguration-output',
+  var Installer = {
+    selectorBody: '.t3js-body',
+    selectorMainContent: '.t3js-installer-content',
+    selectorProgressBar: '.t3js-installer-progress',
+    selectorExecuteDatabaseConnectToken: '#t3js-installer-databaseConnect-execute-token',
+    selectorExecuteDatabaseSelectToken: '#t3js-installer-databaseSelect-execute-token',
+    selectorExecuteDatabaseDataToken: '#t3js-installer-databaseData-execute-token',
+    selectorExecuteDefaultConfigurationToken: '#t3js-installer-defaultConfiguration-execute-token',
+    selectorDatabaseConnectOutput: '.t3js-installer-databaseConnect-output',
+    selectorDatabaseSelectOutput: '.t3js-installer-databaseSelect-output',
+    selectorDatabaseDataOutput: '.t3js-installer-databaseData-output',
+    selectorDefaultConfigurationOutput: '.t3js-installer-defaultConfiguration-output',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			$(document).on('click', '.t3js-installer-environmentFolders-retry', function(e) {
-				e.preventDefault();
-				self.showEnvironmentAndFolders();
-			});
-			$(document).on('click', '.t3js-installer-environmentFolders-execute', function(e) {
-				e.preventDefault();
-				self.executeEnvironmentAndFolders();
-			});
-			$(document).on('click', '.t3js-installer-databaseConnect-execute', function(e) {
-				e.preventDefault();
-				self.executeDatabaseConnect();
-			});
-			$(document).on('click', '.t3js-installer-databaseSelect-execute', function(e) {
-				e.preventDefault();
-				self.executeDatabaseSelect();
-			});
-			$(document).on('click', '.t3js-installer-databaseData-execute', function(e) {
-				e.preventDefault();
-				self.executeDatabaseData();
-			});
-			$(document).on('click', '.t3js-installer-defaultConfiguration-execute', function(e) {
-				e.preventDefault();
-				self.executeDefaultConfiguration();
-			});
+      $(document).on('click', '.t3js-installer-environmentFolders-retry', function(e) {
+        e.preventDefault();
+        self.showEnvironmentAndFolders();
+      });
+      $(document).on('click', '.t3js-installer-environmentFolders-execute', function(e) {
+        e.preventDefault();
+        self.executeEnvironmentAndFolders();
+      });
+      $(document).on('click', '.t3js-installer-databaseConnect-execute', function(e) {
+        e.preventDefault();
+        self.executeDatabaseConnect();
+      });
+      $(document).on('click', '.t3js-installer-databaseSelect-execute', function(e) {
+        e.preventDefault();
+        self.executeDatabaseSelect();
+      });
+      $(document).on('click', '.t3js-installer-databaseData-execute', function(e) {
+        e.preventDefault();
+        self.executeDatabaseData();
+      });
+      $(document).on('click', '.t3js-installer-defaultConfiguration-execute', function(e) {
+        e.preventDefault();
+        self.executeDefaultConfiguration();
+      });
 
-			$(document).on('keyup', '.t3-install-form-password-strength', function() {
-				PasswordStrength.initialize('.t3-install-form-password-strength');
-			});
+      $(document).on('keyup', '.t3-install-form-password-strength', function() {
+        PasswordStrength.initialize('.t3-install-form-password-strength');
+      });
 
-			// Database connect db driver selection
-			$(document).on('change', '#t3js-connect-database-driver', function() {
-				var driver = $(this).val();
-				$('.t3-install-driver-data').hide();
-				$('.t3-install-driver-data input').attr('disabled', 'disabled');
-				$('#' + driver + ' input').attr('disabled', false);
-				$('#' + driver).show();
-			});
+      // Database connect db driver selection
+      $(document).on('change', '#t3js-connect-database-driver', function() {
+        var driver = $(this).val();
+        $('.t3-install-driver-data').hide();
+        $('.t3-install-driver-data input').attr('disabled', 'disabled');
+        $('#' + driver + ' input').attr('disabled', false);
+        $('#' + driver).show();
+      });
 
-			this.setProgress(0);
-			this.getMainLayout();
-		},
+      this.setProgress(0);
+      this.getMainLayout();
+    },
 
-		getUrl: function(action) {
-			var url = location.href;
-			url = url.replace(location.search, '');
-			if (action !== undefined) {
-				url = url + '?install[action]=' + action;
-			}
-			return url;
-		},
+    getUrl: function(action) {
+      var url = location.href;
+      url = url.replace(location.search, '');
+      if (action !== undefined) {
+        url = url + '?install[action]=' + action;
+      }
+      return url;
+    },
 
-		setProgress: function(done) {
-			var $progressBar = $(this.selectorProgressBar);
-			var percent = 0;
-			if (done !== 0) {
-				percent = (done / 5) * 100;
-				$progressBar.find('.progress-bar').empty().text(done + ' / 5 - ' + percent + '% Complete');
-			}
-			$progressBar
-				.find('.progress-bar')
-				.css('width', percent + '%')
-				.attr('aria-valuenow', percent);
-		},
+    setProgress: function(done) {
+      var $progressBar = $(this.selectorProgressBar);
+      var percent = 0;
+      if (done !== 0) {
+        percent = (done / 5) * 100;
+        $progressBar.find('.progress-bar').empty().text(done + ' / 5 - ' + percent + '% Complete');
+      }
+      $progressBar
+        .find('.progress-bar')
+        .css('width', percent + '%')
+        .attr('aria-valuenow', percent);
+    },
 
-		getMainLayout: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('mainLayout'),
-				cache: false,
-				success: function(data) {
-					$(self.selectorBody).empty().append(data.html);
-					self.checkInstallerAvailable();
-				}
-			})
-		},
+    getMainLayout: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('mainLayout'),
+        cache: false,
+        success: function(data) {
+          $(self.selectorBody).empty().append(data.html);
+          self.checkInstallerAvailable();
+        }
+      })
+    },
 
-		checkInstallerAvailable: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('checkInstallerAvailable'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkEnvironmentAndFolders();
-					} else {
-						self.showInstallerNotAvailable();
-					}
-				}
-			});
-		},
+    checkInstallerAvailable: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('checkInstallerAvailable'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkEnvironmentAndFolders();
+          } else {
+            self.showInstallerNotAvailable();
+          }
+        }
+      });
+    },
 
-		showInstallerNotAvailable: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('showInstallerNotAvailable'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().append(data.html);
-					}
-				}
-			});
-		},
+    showInstallerNotAvailable: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('showInstallerNotAvailable'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().append(data.html);
+          }
+        }
+      });
+    },
 
-		checkEnvironmentAndFolders: function() {
-			var self = this;
-			this.setProgress(1);
-			$.ajax({
-				url: this.getUrl('checkEnvironmentAndFolders'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkTrustedHostsPattern();
-					} else {
-						self.showEnvironmentAndFolders();
-					}
-				}
-			});
-		},
+    checkEnvironmentAndFolders: function() {
+      var self = this;
+      this.setProgress(1);
+      $.ajax({
+        url: this.getUrl('checkEnvironmentAndFolders'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkTrustedHostsPattern();
+          } else {
+            self.showEnvironmentAndFolders();
+          }
+        }
+      });
+    },
 
-		showEnvironmentAndFolders: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('showEnvironmentAndFolders'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().html(data.html);
-						var $detailContainer = $('.t3js-installer-environment-details');
-						var hasMessage = false;
-						if (Array.isArray(data.environmentStatusErrors)) {
-							data.environmentStatusErrors.forEach(function(element) {
-								hasMessage = true;
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$detailContainer.append(message);
-							});
-						}
-						if (Array.isArray(data.environmentStatusWarnings)) {
-							data.environmentStatusWarnings.forEach(function(element) {
-								hasMessage = true;
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$detailContainer.append(message);
-							});
-						}
-						if (Array.isArray(data.structureErrors)) {
-							data.structureErrors.forEach(function(element) {
-								hasMessage = true;
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$detailContainer.append(message);
-							});
-						}
-						if (hasMessage === true) {
-							$detailContainer.show();
-							$('.t3js-installer-environmentFolders-bad').show();
-						} else {
-							$('.t3js-installer-environmentFolders-good').show();
-						}
-					}
-				}
-			});
-		},
+    showEnvironmentAndFolders: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('showEnvironmentAndFolders'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().html(data.html);
+            var $detailContainer = $('.t3js-installer-environment-details');
+            var hasMessage = false;
+            if (Array.isArray(data.environmentStatusErrors)) {
+              data.environmentStatusErrors.forEach(function(element) {
+                hasMessage = true;
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $detailContainer.append(message);
+              });
+            }
+            if (Array.isArray(data.environmentStatusWarnings)) {
+              data.environmentStatusWarnings.forEach(function(element) {
+                hasMessage = true;
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $detailContainer.append(message);
+              });
+            }
+            if (Array.isArray(data.structureErrors)) {
+              data.structureErrors.forEach(function(element) {
+                hasMessage = true;
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $detailContainer.append(message);
+              });
+            }
+            if (hasMessage === true) {
+              $detailContainer.show();
+              $('.t3js-installer-environmentFolders-bad').show();
+            } else {
+              $('.t3js-installer-environmentFolders-good').show();
+            }
+          }
+        }
+      });
+    },
 
-		executeEnvironmentAndFolders: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeEnvironmentAndFolders'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkTrustedHostsPattern();
-					} else {
-						// @todo message output handling
-					}
-				}
-			});
-		},
+    executeEnvironmentAndFolders: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeEnvironmentAndFolders'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkTrustedHostsPattern();
+          } else {
+            // @todo message output handling
+          }
+        }
+      });
+    },
 
-		checkTrustedHostsPattern: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('checkTrustedHostsPattern'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.executeSilentConfigurationUpdate();
-					} else {
-						self.executeAdjustTrustedHostsPattern();
-					}
-				}
-			});
-		},
+    checkTrustedHostsPattern: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('checkTrustedHostsPattern'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.executeSilentConfigurationUpdate();
+          } else {
+            self.executeAdjustTrustedHostsPattern();
+          }
+        }
+      });
+    },
 
-		executeAdjustTrustedHostsPattern: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeAdjustTrustedHostsPattern'),
-				cache: false,
-				success: function(data) {
-					self.executeSilentConfigurationUpdate();
-				}
-			});
-		},
+    executeAdjustTrustedHostsPattern: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeAdjustTrustedHostsPattern'),
+        cache: false,
+        success: function(data) {
+          self.executeSilentConfigurationUpdate();
+        }
+      });
+    },
 
-		executeSilentConfigurationUpdate: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeSilentConfigurationUpdate'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkDatabaseConnect();
-					} else {
-						self.executeSilentConfigurationUpdate();
-					}
-				}
-			});
-		},
+    executeSilentConfigurationUpdate: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeSilentConfigurationUpdate'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkDatabaseConnect();
+          } else {
+            self.executeSilentConfigurationUpdate();
+          }
+        }
+      });
+    },
 
-		checkDatabaseConnect: function() {
-			this.setProgress(2);
-			var self = this;
-			$.ajax({
-				url: this.getUrl('checkDatabaseConnect'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkDatabaseSelect();
-					} else {
-						self.showDatabaseConnect();
-					}
-				}
-			});
-		},
+    checkDatabaseConnect: function() {
+      this.setProgress(2);
+      var self = this;
+      $.ajax({
+        url: this.getUrl('checkDatabaseConnect'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkDatabaseSelect();
+          } else {
+            self.showDatabaseConnect();
+          }
+        }
+      });
+    },
 
-		showDatabaseConnect: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('showDatabaseConnect'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().html(data.html);
-						$('#t3js-connect-database-driver').trigger('change');
-					}
-				}
-			});
-		},
+    showDatabaseConnect: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('showDatabaseConnect'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().html(data.html);
+            $('#t3js-connect-database-driver').trigger('change');
+          }
+        }
+      });
+    },
 
-		executeDatabaseConnect: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorDatabaseConnectOutput);
-			var postData = {
-				'install[action]': 'executeDatabaseConnect',
-				'install[token]': $(self.selectorExecuteDatabaseConnectToken).text()
-			};
-			$($(this.selectorBody + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			$.ajax({
-				url: this.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: postData,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkDatabaseSelect();
-					} else {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.empty().append(message);
-							});
-						}
-					}
-				}
-			});
-		},
+    executeDatabaseConnect: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorDatabaseConnectOutput);
+      var postData = {
+        'install[action]': 'executeDatabaseConnect',
+        'install[token]': $(self.selectorExecuteDatabaseConnectToken).text()
+      };
+      $($(this.selectorBody + ' form').serializeArray()).each(function() {
+        postData[this.name] = this.value;
+      });
+      $.ajax({
+        url: this.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: postData,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkDatabaseSelect();
+          } else {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.empty().append(message);
+              });
+            }
+          }
+        }
+      });
+    },
 
-		checkDatabaseSelect: function() {
-			var self = this;
-			this.setProgress(3);
-			$.ajax({
-				url: this.getUrl('checkDatabaseSelect'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkDatabaseData();
-					} else {
-						self.showDatabaseSelect();
-					}
-				}
-			});
-		},
+    checkDatabaseSelect: function() {
+      var self = this;
+      this.setProgress(3);
+      $.ajax({
+        url: this.getUrl('checkDatabaseSelect'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkDatabaseData();
+          } else {
+            self.showDatabaseSelect();
+          }
+        }
+      });
+    },
 
-		showDatabaseSelect: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('showDatabaseSelect'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().html(data.html);
-					}
-				}
-			});
-		},
+    showDatabaseSelect: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('showDatabaseSelect'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().html(data.html);
+          }
+        }
+      });
+    },
 
-		executeDatabaseSelect: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorDatabaseSelectOutput);
-			var postData = {
-				'install[action]': 'executeDatabaseSelect',
-				'install[token]': $(self.selectorExecuteDatabaseSelectToken).text()
-			};
-			$($(this.selectorBody + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			$.ajax({
-				url: this.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: postData,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkDatabaseData();
-					} else {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.empty().append(message);
-							});
-						}
-					}
-				}
-			});
-		},
+    executeDatabaseSelect: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorDatabaseSelectOutput);
+      var postData = {
+        'install[action]': 'executeDatabaseSelect',
+        'install[token]': $(self.selectorExecuteDatabaseSelectToken).text()
+      };
+      $($(this.selectorBody + ' form').serializeArray()).each(function() {
+        postData[this.name] = this.value;
+      });
+      $.ajax({
+        url: this.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: postData,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkDatabaseData();
+          } else {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.empty().append(message);
+              });
+            }
+          }
+        }
+      });
+    },
 
-		checkDatabaseData: function() {
-			var self = this;
-			this.setProgress(4);
-			$.ajax({
-				url: this.getUrl('checkDatabaseData'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.showDefaultConfiguration();
-					} else {
-						self.showDatabaseData();
-					}
-				}
-			});
-		},
+    checkDatabaseData: function() {
+      var self = this;
+      this.setProgress(4);
+      $.ajax({
+        url: this.getUrl('checkDatabaseData'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.showDefaultConfiguration();
+          } else {
+            self.showDatabaseData();
+          }
+        }
+      });
+    },
 
-		showDatabaseData: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('showDatabaseData'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().html(data.html);
-					}
-				}
-			});
-		},
+    showDatabaseData: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('showDatabaseData'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().html(data.html);
+          }
+        }
+      });
+    },
 
-		executeDatabaseData: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorDatabaseDataOutput);
-			var postData = {
-				'install[action]': 'executeDatabaseData',
-				'install[token]': $(self.selectorExecuteDatabaseDataToken).text()
-			};
-			$($(this.selectorBody + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: this.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: postData,
-				success: function(data) {
-					if (data.success === true) {
-						self.showDefaultConfiguration();
-					} else {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.empty().append(message);
-							});
-						}
-					}
-				}
-			});
-		},
+    executeDatabaseData: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorDatabaseDataOutput);
+      var postData = {
+        'install[action]': 'executeDatabaseData',
+        'install[token]': $(self.selectorExecuteDatabaseDataToken).text()
+      };
+      $($(this.selectorBody + ' form').serializeArray()).each(function() {
+        postData[this.name] = this.value;
+      });
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: this.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: postData,
+        success: function(data) {
+          if (data.success === true) {
+            self.showDefaultConfiguration();
+          } else {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.empty().append(message);
+              });
+            }
+          }
+        }
+      });
+    },
 
-		showDefaultConfiguration: function() {
-			var $outputContainer = $(this.selectorMainContent);
-			this.setProgress(5);
-			$.ajax({
-				url: this.getUrl('showDefaultConfiguration'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$outputContainer.empty().html(data.html);
-					}
-				}
-			});
-		},
+    showDefaultConfiguration: function() {
+      var $outputContainer = $(this.selectorMainContent);
+      this.setProgress(5);
+      $.ajax({
+        url: this.getUrl('showDefaultConfiguration'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.empty().html(data.html);
+          }
+        }
+      });
+    },
 
-		executeDefaultConfiguration: function() {
-			var self = this;
-			var postData = {
-				'install[action]': 'executeDefaultConfiguration',
-				'install[token]': $(self.selectorExecuteDefaultConfigurationToken).text()
-			};
-			$($(this.selectorBody + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			$.ajax({
-				url: this.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: postData,
-				success: function(data) {
-					top.location.href = data.redirect;
-				}
-			});
-		}
-	};
+    executeDefaultConfiguration: function() {
+      var self = this;
+      var postData = {
+        'install[action]': 'executeDefaultConfiguration',
+        'install[token]': $(self.selectorExecuteDefaultConfigurationToken).text()
+      };
+      $($(this.selectorBody + ' form').serializeArray()).each(function() {
+        postData[this.name] = this.value;
+      });
+      $.ajax({
+        url: this.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: postData,
+        success: function(data) {
+          top.location.href = data.redirect;
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js
index a1c7962b0ed9..0db7111917e5 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Cache.js
@@ -15,52 +15,52 @@
  * Module: TYPO3/CMS/Install/Cache
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorClearTrigger: '.t3js-clearAllCache-clear',
-		selectorOutputContainer: '.t3js-clearAllCache-output',
+  return {
+    selectorClearTrigger: '.t3js-clearAllCache-clear',
+    selectorOutputContainer: '.t3js-clearAllCache-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorClearTrigger, function(e) {
-				e.preventDefault();
-				self.clearAll();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorClearTrigger, function(e) {
+        e.preventDefault();
+        self.clearAll();
+      });
+    },
 
-		clearAll: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, '', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('cacheClearAll', 'maintenance'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							$outputContainer.empty();
-							data.status.forEach((function (element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							}));
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    clearAll: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, '', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('cacheClearAll', 'maintenance'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            if (data.status.length > 0) {
+              $outputContainer.empty();
+              data.status.forEach((function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              }));
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js
index c73d3085d711..b5287b80d2d9 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CardLayout.js
@@ -14,168 +14,168 @@
 /**
  * Module: TYPO3/CMS/Install/CardLayout
  */
-define(['jquery', 'bootstrap'], function ($) {
-	'use strict';
+define(['jquery', 'bootstrap'], function($) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{transitionInProgress: boolean}}
-	 */
-	var CardLayout = {
-		transitionInProgress: false
-	};
+  /**
+   *
+   * @type {{transitionInProgress: boolean}}
+   */
+  var CardLayout = {
+    transitionInProgress: false
+  };
 
-	/**
-	 * Initialize the CardLayout, bind events
-	 */
-	CardLayout.initialize = function() {
-		$(document).on('click', '.gridder-list', function(e) {
-			e.preventDefault();
-			var $element = $(this);
-			if (!$element.hasClass('selectedItem')) {
-				CardLayout.openCard($element);
-			} else {
-				CardLayout.closeCard($element);
-			}
-		});
+  /**
+   * Initialize the CardLayout, bind events
+   */
+  CardLayout.initialize = function() {
+    $(document).on('click', '.gridder-list', function(e) {
+      e.preventDefault();
+      var $element = $(this);
+      if (!$element.hasClass('selectedItem')) {
+        CardLayout.openCard($element);
+      } else {
+        CardLayout.closeCard($element);
+      }
+    });
 
-		// Close current and open previous card
-		$(document).on('click', '.gridder-nav-prev', function(e) {
-			e.preventDefault();
-			CardLayout.openPrevCard();
-		});
+    // Close current and open previous card
+    $(document).on('click', '.gridder-nav-prev', function(e) {
+      e.preventDefault();
+      CardLayout.openPrevCard();
+    });
 
-		// Close current and open next card
-		$(document).on('click', '.gridder-nav-next', function(e) {
-			e.preventDefault();
-			CardLayout.openNextCard();
-		});
+    // Close current and open next card
+    $(document).on('click', '.gridder-nav-next', function(e) {
+      e.preventDefault();
+      CardLayout.openNextCard();
+    });
 
-		// Close current open card
-		$(document).on('click', '.gridder-close', function(e) {
-			e.preventDefault();
-			CardLayout.closeCurrentCard();
-		});
+    // Close current open card
+    $(document).on('click', '.gridder-close', function(e) {
+      e.preventDefault();
+      CardLayout.closeCurrentCard();
+    });
 
-		CardLayout.checkNavigationButtons();
-	};
+    CardLayout.checkNavigationButtons();
+  };
 
-	/**
-	 * Find and return the current open card
-	 *
-	 * @returns {jQuery}
-	 */
-	CardLayout.getCurrentOpenCard = function() {
-		return $('.gridder-content.gridder-show').prev();
-	};
+  /**
+   * Find and return the current open card
+   *
+   * @returns {jQuery}
+   */
+  CardLayout.getCurrentOpenCard = function() {
+    return $('.gridder-content.gridder-show').prev();
+  };
 
-	/**
-	 * Find and close the current open card
-	 */
-	CardLayout.closeCurrentCard = function() {
-		CardLayout.closeCard(CardLayout.getCurrentOpenCard());
-		CardLayout.checkNavigationButtons();
-	};
+  /**
+   * Find and close the current open card
+   */
+  CardLayout.closeCurrentCard = function() {
+    CardLayout.closeCard(CardLayout.getCurrentOpenCard());
+    CardLayout.checkNavigationButtons();
+  };
 
-	/**
-	 * Open the given card and call the callback function
-	 *
-	 * @param {jQuery} $element
-	 * @param {function} callback
-	 * @returns {boolean}
-	 */
-	CardLayout.openCard = function($element, callback) {
-		if (CardLayout.transitionInProgress) {
-			return false;
-		}
-		CardLayout.transitionInProgress = true;
-		$('.gridder-list').removeClass('selectedItem');
-		$('.gridder-content.gridder-show').slideUp(function() {
-			$(this).removeClass('gridder-show');
-		});
-		$element.addClass('selectedItem');
-		$element.next().addClass('gridder-show').slideDown(function() {
-			CardLayout.transitionInProgress = false;
-			if (typeof callback === 'function') {
-				callback();
-			}
-			CardLayout.checkNavigationButtons();
-		});
-		$(document).trigger('cardlayout:card-opened', [$element]);
-	};
+  /**
+   * Open the given card and call the callback function
+   *
+   * @param {jQuery} $element
+   * @param {function} callback
+   * @returns {boolean}
+   */
+  CardLayout.openCard = function($element, callback) {
+    if (CardLayout.transitionInProgress) {
+      return false;
+    }
+    CardLayout.transitionInProgress = true;
+    $('.gridder-list').removeClass('selectedItem');
+    $('.gridder-content.gridder-show').slideUp(function() {
+      $(this).removeClass('gridder-show');
+    });
+    $element.addClass('selectedItem');
+    $element.next().addClass('gridder-show').slideDown(function() {
+      CardLayout.transitionInProgress = false;
+      if (typeof callback === 'function') {
+        callback();
+      }
+      CardLayout.checkNavigationButtons();
+    });
+    $(document).trigger('cardlayout:card-opened', [$element]);
+  };
 
-	/**
-	 * Close the given card and call the callback function
-	 *
-	 * @param {jQuery} $element
-	 * @param {function} callback
-	 * @returns {boolean}
-	 */
-	CardLayout.closeCard = function($element, callback) {
-		if (CardLayout.transitionInProgress) {
-			return false;
-		}
-		CardLayout.transitionInProgress = true;
-		var $contentContainer = $element.next();
-		$element.removeClass('selectedItem');
-		$contentContainer.slideUp(function() {
-			$contentContainer.removeClass('gridder-show');
-			CardLayout.transitionInProgress = false;
-			if (typeof callback === 'function') {
-				callback();
-			}
-			CardLayout.checkNavigationButtons();
-		});
-		$(document).trigger('cardlayout:card-closed', [$element]);
-	};
+  /**
+   * Close the given card and call the callback function
+   *
+   * @param {jQuery} $element
+   * @param {function} callback
+   * @returns {boolean}
+   */
+  CardLayout.closeCard = function($element, callback) {
+    if (CardLayout.transitionInProgress) {
+      return false;
+    }
+    CardLayout.transitionInProgress = true;
+    var $contentContainer = $element.next();
+    $element.removeClass('selectedItem');
+    $contentContainer.slideUp(function() {
+      $contentContainer.removeClass('gridder-show');
+      CardLayout.transitionInProgress = false;
+      if (typeof callback === 'function') {
+        callback();
+      }
+      CardLayout.checkNavigationButtons();
+    });
+    $(document).trigger('cardlayout:card-closed', [$element]);
+  };
 
-	/**
-	 * Find the next card and open it, if it exists
-	 */
-	CardLayout.openNextCard = function() {
-		var $currentOpenCard = CardLayout.getCurrentOpenCard();
-		var $nextCard = $currentOpenCard.next().next();
-		if ($nextCard.length) {
-			CardLayout.closeCard($currentOpenCard, function() {
-				CardLayout.openCard($nextCard);
-			});
-		}
-	};
+  /**
+   * Find the next card and open it, if it exists
+   */
+  CardLayout.openNextCard = function() {
+    var $currentOpenCard = CardLayout.getCurrentOpenCard();
+    var $nextCard = $currentOpenCard.next().next();
+    if ($nextCard.length) {
+      CardLayout.closeCard($currentOpenCard, function() {
+        CardLayout.openCard($nextCard);
+      });
+    }
+  };
 
-	/**
-	 * Find the previous card and open it, if it exists
-	 */
-	CardLayout.openPrevCard = function() {
-		var $currentOpenCard = CardLayout.getCurrentOpenCard();
-		var $nextCard = $currentOpenCard.prev().prev();
-		if ($nextCard.length) {
-			CardLayout.closeCard($currentOpenCard, function() {
-				CardLayout.openCard($nextCard);
-			});
-		}
-	};
+  /**
+   * Find the previous card and open it, if it exists
+   */
+  CardLayout.openPrevCard = function() {
+    var $currentOpenCard = CardLayout.getCurrentOpenCard();
+    var $nextCard = $currentOpenCard.prev().prev();
+    if ($nextCard.length) {
+      CardLayout.closeCard($currentOpenCard, function() {
+        CardLayout.openCard($nextCard);
+      });
+    }
+  };
 
-	/**
-	 * Check the navigation icons and enable/disable the buttons
-	 */
-	CardLayout.checkNavigationButtons = function() {
-		var $currentOpenCard = CardLayout.getCurrentOpenCard();
-		if ($currentOpenCard.length === 0) {
-			$('.gridder-close').addClass('disabled');
-		} else {
-			$('.gridder-close').removeClass('disabled');
-		}
-		if ($currentOpenCard.prev().prev().length === 0) {
-			$('.gridder-nav-prev').addClass('disabled');
-		} else {
-			$('.gridder-nav-prev').removeClass('disabled');
-		}
-		if ($currentOpenCard.next().next().length === 0) {
-			$('.gridder-nav-next').addClass('disabled');
-		} else {
-			$('.gridder-nav-next').removeClass('disabled');
-		}
-	};
+  /**
+   * Check the navigation icons and enable/disable the buttons
+   */
+  CardLayout.checkNavigationButtons = function() {
+    var $currentOpenCard = CardLayout.getCurrentOpenCard();
+    if ($currentOpenCard.length === 0) {
+      $('.gridder-close').addClass('disabled');
+    } else {
+      $('.gridder-close').removeClass('disabled');
+    }
+    if ($currentOpenCard.prev().prev().length === 0) {
+      $('.gridder-nav-prev').addClass('disabled');
+    } else {
+      $('.gridder-nav-prev').removeClass('disabled');
+    }
+    if ($currentOpenCard.next().next().length === 0) {
+      $('.gridder-nav-next').addClass('disabled');
+    } else {
+      $('.gridder-nav-next').removeClass('disabled');
+    }
+  };
 
-	return CardLayout;
+  return CardLayout;
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js
index 543ced85901b..52c542b3aa7a 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ChangeInstallToolPassword.js
@@ -15,64 +15,64 @@
  * Module: TYPO3/CMS/Install/CreateAdmin
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'TYPO3/CMS/Install/PasswordStrength'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'TYPO3/CMS/Install/PasswordStrength'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, PasswordStrength) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorChangeToken: '#t3js-changeInstallToolPassword-token',
-		selectorChangeTrigger: '.t3js-changeInstallToolPassword-change',
-		selectorOutputContainer: '.t3js-changeInstallToolPassword-output',
+  return {
+    selectorChangeToken: '#t3js-changeInstallToolPassword-token',
+    selectorChangeTrigger: '.t3js-changeInstallToolPassword-change',
+    selectorOutputContainer: '.t3js-changeInstallToolPassword-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorChangeTrigger, function(e) {
-				e.preventDefault();
-				self.change();
-			});
-			$(document).on('keyup', '.t3-install-form-password-strength', function() {
-				PasswordStrength.initialize('.t3-install-form-password-strength');
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorChangeTrigger, function(e) {
+        e.preventDefault();
+        self.change();
+      });
+      $(document).on('keyup', '.t3-install-form-password-strength', function() {
+        PasswordStrength.initialize('.t3-install-form-password-strength');
+      });
+    },
 
-		change: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'changeInstallToolPassword',
-						'token': $(this.selectorChangeToken).text(),
-						'password': $('.t3js-changeInstallToolPassword-password').val(),
-						'passwordCheck': $('.t3js-changeInstallToolPassword-password-check').val()
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.append(message);
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    change: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'changeInstallToolPassword',
+            'token': $(this.selectorChangeToken).text(),
+            'password': $('.t3js-changeInstallToolPassword-password').val(),
+            'passwordCheck': $('.t3js-changeInstallToolPassword-password-check').val()
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.append(message);
+            });
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
index 4119181609bd..faebe82a8b79 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTables.js
@@ -15,123 +15,123 @@
  * Module: TYPO3/CMS/Install/ClearTable
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-clearTables-open',
-		selectorClearToken: '#t3js-clearTables-clear-token',
-		selectorClearTrigger: '.t3js-clearTables-clear',
-		selectorStatsTrigger: '.t3js-clearTables-stats',
-		selectorOutputContainer: '.t3js-clearTables-output',
-		selectorStatContainer: 't3js-clearTables-stat-container',
-		selectorStatTemplate: '.t3js-clearTables-stat-template',
-		selectorStatDescription: '.t3js-clearTables-stat-description',
-		selectorStatRows: '.t3js-clearTables-stat-rows',
-		selectorStatName: '.t3js-clearTables-stat-name',
-		selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler',
+  return {
+    selectorGridderOpener: 't3js-clearTables-open',
+    selectorClearToken: '#t3js-clearTables-clear-token',
+    selectorClearTrigger: '.t3js-clearTables-clear',
+    selectorStatsTrigger: '.t3js-clearTables-stats',
+    selectorOutputContainer: '.t3js-clearTables-output',
+    selectorStatContainer: 't3js-clearTables-stat-container',
+    selectorStatTemplate: '.t3js-clearTables-stat-template',
+    selectorStatDescription: '.t3js-clearTables-stat-description',
+    selectorStatRows: '.t3js-clearTables-stat-rows',
+    selectorStatName: '.t3js-clearTables-stat-name',
+    selectorStatLastRuler: '.t3js-clearTables-stat-lastRuler',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Load stats on first open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
-					$card.data('isInitialized', true);
-					self.getStats();
-				}
-			});
+      // Load stats on first open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
+          $card.data('isInitialized', true);
+          self.getStats();
+        }
+      });
 
-			$(document).on('click', this.selectorStatsTrigger, function(e) {
-				e.preventDefault();
-				$(self.selectorOutputContainer).empty();
-				self.getStats();
-			});
+      $(document).on('click', this.selectorStatsTrigger, function(e) {
+        e.preventDefault();
+        $(self.selectorOutputContainer).empty();
+        self.getStats();
+      });
 
-			$(document).on('click', this.selectorClearTrigger, function(e) {
-				var table = $(e.target).closest(self.selectorClearTrigger).data('table');
-				e.preventDefault();
-				self.clear(table);
-			});
-		},
+      $(document).on('click', this.selectorClearTrigger, function(e) {
+        var table = $(e.target).closest(self.selectorClearTrigger).data('table');
+        e.preventDefault();
+        self.clear(table);
+      });
+    },
 
-		getStats: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var $statContainer = $('.' + this.selectorStatContainer);
-			$statContainer.empty();
-			var $statTemplate = $(this.selectorStatTemplate);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$.ajax({
-				url: Router.getUrl('clearTablesStats'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true) {
-						$outputContainer.find('.alert-loading').remove();
-						if (Array.isArray(data.stats) && data.stats.length > 0) {
-							data.stats.forEach(function(element) {
-								if (element.rowCount > 0) {
-									var $aStat = $statTemplate.clone();
-									$aStat.find(self.selectorStatDescription).text(element.description);
-									$aStat.find(self.selectorStatName).text(element.name);
-									$aStat.find(self.selectorStatRows).text(element.rowCount);
-									$aStat.find(self.selectorClearTrigger).data('table', element.name);
-									$statContainer.append($aStat);
-								}
-							});
-							$statContainer.find(self.selectorStatLastRuler + ':last').remove();
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getStats: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $statContainer = $('.' + this.selectorStatContainer);
+      $statContainer.empty();
+      var $statTemplate = $(this.selectorStatTemplate);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $.ajax({
+        url: Router.getUrl('clearTablesStats'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.find('.alert-loading').remove();
+            if (Array.isArray(data.stats) && data.stats.length > 0) {
+              data.stats.forEach(function(element) {
+                if (element.rowCount > 0) {
+                  var $aStat = $statTemplate.clone();
+                  $aStat.find(self.selectorStatDescription).text(element.description);
+                  $aStat.find(self.selectorStatName).text(element.name);
+                  $aStat.find(self.selectorStatRows).text(element.rowCount);
+                  $aStat.find(self.selectorClearTrigger).data('table', element.name);
+                  $statContainer.append($aStat);
+                }
+              });
+              $statContainer.find(self.selectorStatLastRuler + ':last').remove();
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		clear: function(table) {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().append(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				context: this,
-				data: {
-					'install': {
-						'action': 'clearTablesClear',
-						'token': $(this.selectorClearToken).text(),
-						'table': table
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.append(message);
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.append(message);
-					}
-					this.getStats();
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    clear: function(table) {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().append(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        context: this,
+        data: {
+          'install': {
+            'action': 'clearTablesClear',
+            'token': $(this.selectorClearToken).text(),
+            'table': table
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.append(message);
+            });
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.append(message);
+          }
+          this.getStats();
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js
index 93386c2b0e18..5a8a87b28228 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ClearTypo3tempFiles.js
@@ -15,119 +15,119 @@
  * Module: TYPO3/CMS/Install/ClearTypo3tempFiles
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-clearTypo3temp-open',
-		selectorDeleteToken: '#t3js-clearTypo3temp-delete-token',
-		selectorDeleteTrigger: '.t3js-clearTypo3temp-delete',
-		selectorOutputContainer: '.t3js-clearTypo3temp-output',
-		selectorStatContainer: 't3js-clearTypo3temp-stat-container',
-		selectorStatsTrigger: '.t3js-clearTypo3temp-stats',
-		selectorStatTemplate: '.t3js-clearTypo3temp-stat-template',
-		selectorStatDescription: '.t3js-clearTypo3temp-stat-description',
-		selectorStatNumberOfFiles: '.t3js-clearTypo3temp-stat-numberOfFiles',
-		selectorStatDirectory: '.t3js-clearTypo3temp-stat-directory',
-		selectorStatName: '.t3js-clearTypo3temp-stat-name',
-		selectorStatLastRuler: '.t3js-clearTypo3temp-stat-lastRuler',
+  return {
+    selectorGridderOpener: 't3js-clearTypo3temp-open',
+    selectorDeleteToken: '#t3js-clearTypo3temp-delete-token',
+    selectorDeleteTrigger: '.t3js-clearTypo3temp-delete',
+    selectorOutputContainer: '.t3js-clearTypo3temp-output',
+    selectorStatContainer: 't3js-clearTypo3temp-stat-container',
+    selectorStatsTrigger: '.t3js-clearTypo3temp-stats',
+    selectorStatTemplate: '.t3js-clearTypo3temp-stat-template',
+    selectorStatDescription: '.t3js-clearTypo3temp-stat-description',
+    selectorStatNumberOfFiles: '.t3js-clearTypo3temp-stat-numberOfFiles',
+    selectorStatDirectory: '.t3js-clearTypo3temp-stat-directory',
+    selectorStatName: '.t3js-clearTypo3temp-stat-name',
+    selectorStatLastRuler: '.t3js-clearTypo3temp-stat-lastRuler',
 
 
-		initialize: function() {
-			var self = this;
-			// Load stats on first open
-			$(document).on('cardlayout:card-opened', function () {
-				self.getStats();
-			});
+    initialize: function() {
+      var self = this;
+      // Load stats on first open
+      $(document).on('cardlayout:card-opened', function() {
+        self.getStats();
+      });
 
-			$(document).on('click', this.selectorStatsTrigger, function (e) {
-				e.preventDefault();
-				$(self.selectorOutputContainer).empty();
-				self.getStats();
-			});
-			$(document).on('click', this.selectorDeleteTrigger, function (e) {
-				var folder = $(e.target).data('folder');
-				e.preventDefault();
-				self.delete(folder);
-			});
-		},
+      $(document).on('click', this.selectorStatsTrigger, function(e) {
+        e.preventDefault();
+        $(self.selectorOutputContainer).empty();
+        self.getStats();
+      });
+      $(document).on('click', this.selectorDeleteTrigger, function(e) {
+        var folder = $(e.target).data('folder');
+        e.preventDefault();
+        self.delete(folder);
+      });
+    },
 
-		getStats: function () {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var $statContainer = $('.' + this.selectorStatContainer);
-			$statContainer.empty();
-			var $statTemplate = $(this.selectorStatTemplate);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$.ajax({
-				url: Router.getUrl('clearTypo3tempFilesStats'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true) {
-						$outputContainer.find('.alert-loading').remove();
-						if (Array.isArray(data.stats) && data.stats.length > 0) {
-							data.stats.forEach(function (element) {
-								if (element.numberOfFiles > 0) {
-									var $aStat = $statTemplate.clone();
-									$aStat.find(self.selectorStatNumberOfFiles).text(element.numberOfFiles);
-									$aStat.find(self.selectorStatDirectory).text(element.directory);
-									$aStat.find(self.selectorDeleteTrigger).data('folder', element.directory);
-									$statContainer.append($aStat);
-								}
-							});
-							$statContainer.find(self.selectorStatLastRuler + ':last').remove();
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.append(message);
-					}
-				},
-				error: function (xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getStats: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $statContainer = $('.' + this.selectorStatContainer);
+      $statContainer.empty();
+      var $statTemplate = $(this.selectorStatTemplate);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $.ajax({
+        url: Router.getUrl('clearTypo3tempFilesStats'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.find('.alert-loading').remove();
+            if (Array.isArray(data.stats) && data.stats.length > 0) {
+              data.stats.forEach(function(element) {
+                if (element.numberOfFiles > 0) {
+                  var $aStat = $statTemplate.clone();
+                  $aStat.find(self.selectorStatNumberOfFiles).text(element.numberOfFiles);
+                  $aStat.find(self.selectorStatDirectory).text(element.directory);
+                  $aStat.find(self.selectorDeleteTrigger).data('folder', element.directory);
+                  $statContainer.append($aStat);
+                }
+              });
+              $statContainer.find(self.selectorStatLastRuler + ':last').remove();
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		delete: function(folder) {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().append(message);
-			$.ajax({
-				method: 'POST',
-				url: Router.getUrl(),
-				context: this,
-				data: {
-					'install': {
-						'action': 'clearTypo3tempFiles',
-						'token': $(this.selectorDeleteToken).text(),
-						'folder': folder
-					}
-				},
-				cache: false,
-				success: function (data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function (element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.html(message);
-						});
-						this.getStats();
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    delete: function(folder) {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().append(message);
+      $.ajax({
+        method: 'POST',
+        url: Router.getUrl(),
+        context: this,
+        data: {
+          'install': {
+            'action': 'clearTypo3tempFiles',
+            'token': $(this.selectorDeleteToken).text(),
+            'folder': folder
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.html(message);
+            });
+            this.getStats();
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js
index d08bd43e1967..089245cd4cff 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CoreUpdate.js
@@ -15,250 +15,250 @@
  * Module: TYPO3/CMS/Install/CoreUpdate
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/Severity'
-], function ($, Router, FlashMessage, Severity) {
-	'use strict';
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/Severity'
+], function($, Router, FlashMessage, Severity) {
+  'use strict';
 
-	return {
-		/**
-		 * The action queue defines what actions are called in which order
-		 */
-		actionQueue: {
-			coreUpdateUpdateVersionMatrix: {
-				loadingMessage: 'Fetching list of released versions from typo3.org',
-				finishMessage: 'Fetched list of released versions',
-				nextActionName: 'coreUpdateIsUpdateAvailable'
-			},
-			coreUpdateIsUpdateAvailable: {
-				loadingMessage: 'Checking for possible regular or security update',
-				finishMessage: undefined,
-				nextActionName: undefined
-			},
-			coreUpdateCheckPreConditions: {
-				loadingMessage: 'Checking if update is possible',
-				finishMessage: 'System can be updated',
-				nextActionName: 'coreUpdateDownload'
-			},
-			coreUpdateDownload: {
-				loadingMessage: 'Downloading new core',
-				finishMessage: undefined,
-				nextActionName: 'coreUpdateVerifyChecksum'
-			},
-			coreUpdateVerifyChecksum: {
-				loadingMessage: 'Verifying checksum of downloaded core',
-				finishMessage: undefined,
-				nextActionName: 'coreUpdateUnpack'
-			},
-			coreUpdateUnpack: {
-				loadingMessage: 'Unpacking core',
-				finishMessage: undefined,
-				nextActionName: 'coreUpdateMove'
-			},
-			coreUpdateMove: {
-				loadingMessage: 'Moving core',
-				finishMessage: undefined,
-				nextActionName: 'coreUpdateClearAllCache'
-			},
-			clearAllCache: {
-				loadingMessage: 'Clearing caches',
-				finishMessage: 'Caches cleared',
-				nextActionName: 'coreUpdateActivate'
-			},
-			coreUpdateActivate: {
-				loadingMessage: 'Activating core',
-				finishMessage: 'Core updated - please reload your browser',
-				nextActionName: undefined
-			}
-		},
+  return {
+    /**
+     * The action queue defines what actions are called in which order
+     */
+    actionQueue: {
+      coreUpdateUpdateVersionMatrix: {
+        loadingMessage: 'Fetching list of released versions from typo3.org',
+        finishMessage: 'Fetched list of released versions',
+        nextActionName: 'coreUpdateIsUpdateAvailable'
+      },
+      coreUpdateIsUpdateAvailable: {
+        loadingMessage: 'Checking for possible regular or security update',
+        finishMessage: undefined,
+        nextActionName: undefined
+      },
+      coreUpdateCheckPreConditions: {
+        loadingMessage: 'Checking if update is possible',
+        finishMessage: 'System can be updated',
+        nextActionName: 'coreUpdateDownload'
+      },
+      coreUpdateDownload: {
+        loadingMessage: 'Downloading new core',
+        finishMessage: undefined,
+        nextActionName: 'coreUpdateVerifyChecksum'
+      },
+      coreUpdateVerifyChecksum: {
+        loadingMessage: 'Verifying checksum of downloaded core',
+        finishMessage: undefined,
+        nextActionName: 'coreUpdateUnpack'
+      },
+      coreUpdateUnpack: {
+        loadingMessage: 'Unpacking core',
+        finishMessage: undefined,
+        nextActionName: 'coreUpdateMove'
+      },
+      coreUpdateMove: {
+        loadingMessage: 'Moving core',
+        finishMessage: undefined,
+        nextActionName: 'coreUpdateClearAllCache'
+      },
+      clearAllCache: {
+        loadingMessage: 'Clearing caches',
+        finishMessage: 'Caches cleared',
+        nextActionName: 'coreUpdateActivate'
+      },
+      coreUpdateActivate: {
+        loadingMessage: 'Activating core',
+        finishMessage: 'Core updated - please reload your browser',
+        nextActionName: undefined
+      }
+    },
 
-		selectorOutput: '.t3js-coreUpdate-output',
-		selectorTemplate: '.t3js-coreUpdate-buttonTemplate',
+    selectorOutput: '.t3js-coreUpdate-output',
+    selectorTemplate: '.t3js-coreUpdate-buttonTemplate',
 
-		/**
-		 * Clone of a DOM object acts as button template
-		 */
-		buttonTemplate: null,
+    /**
+     * Clone of a DOM object acts as button template
+     */
+    buttonTemplate: null,
 
-		/**
-		 * Fetching the templates out of the DOM
-		 */
-		initialize: function () {
-			var self = this;
-			var buttonTemplateSection = $(self.selectorTemplate);
-			this.buttonTemplate = buttonTemplateSection.children().clone();
+    /**
+     * Fetching the templates out of the DOM
+     */
+    initialize: function() {
+      var self = this;
+      var buttonTemplateSection = $(self.selectorTemplate);
+      this.buttonTemplate = buttonTemplateSection.children().clone();
 
-			$(document).on('click', '.t3js-coreUpdate-init', function (e) {
-				e.preventDefault();
-				var action = $(e.target).data('action');
-				$(document).find(self.selectorOutput).empty();
-				self[action]();
-			});
-		},
+      $(document).on('click', '.t3js-coreUpdate-init', function(e) {
+        e.preventDefault();
+        var action = $(e.target).data('action');
+        $(document).find(self.selectorOutput).empty();
+        self[action]();
+      });
+    },
 
-		/**
-		 * Public method checkForUpdate
-		 */
-		checkForUpdate: function () {
-			this.callAction('coreUpdateUpdateVersionMatrix');
-		},
+    /**
+     * Public method checkForUpdate
+     */
+    checkForUpdate: function() {
+      this.callAction('coreUpdateUpdateVersionMatrix');
+    },
 
-		/**
-		 * Public method updateDevelopment
-		 */
-		updateDevelopment: function () {
-			this.update('development');
-		},
+    /**
+     * Public method updateDevelopment
+     */
+    updateDevelopment: function() {
+      this.update('development');
+    },
 
-		updateRegular: function () {
-			this.update('regular');
-		},
+    updateRegular: function() {
+      this.update('regular');
+    },
 
-		/**
-		 * Execute core update.
-		 *
-		 * @param type Either 'development' or 'regular'
-		 */
-		update: function (type) {
-			if (type !== "development") {
-				type = 'regular';
-			}
-			this.callAction('coreUpdateCheckPreConditions', type);
-		},
+    /**
+     * Execute core update.
+     *
+     * @param type Either 'development' or 'regular'
+     */
+    update: function(type) {
+      if (type !== "development") {
+        type = 'regular';
+      }
+      this.callAction('coreUpdateCheckPreConditions', type);
+    },
 
-		/**
-		 * Generic method to call actions from the queue
-		 *
-		 * @param actionName Name of the action to be called
-		 * @param type Update type (optional)
-		 */
-		callAction: function (actionName, type) {
-			var self = this;
-			var data = {
-				install: {
-					action: actionName
-				}
-			};
-			if (type !== undefined) {
-				data.install["type"] = type;
-			}
-			this.addLoadingMessage(this.actionQueue[actionName].loadingMessage);
-			$.ajax({
-				url: Router.getUrl(),
-				data: data,
-				cache: false,
-				success: function (result) {
-					var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage);
-					if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) {
-						self.callAction(self.actionQueue[actionName].nextActionName, type);
-					}
-				},
-				error: function (result) {
-					self.handleResult(result);
-				}
-			});
-		},
+    /**
+     * Generic method to call actions from the queue
+     *
+     * @param actionName Name of the action to be called
+     * @param type Update type (optional)
+     */
+    callAction: function(actionName, type) {
+      var self = this;
+      var data = {
+        install: {
+          action: actionName
+        }
+      };
+      if (type !== undefined) {
+        data.install["type"] = type;
+      }
+      this.addLoadingMessage(this.actionQueue[actionName].loadingMessage);
+      $.ajax({
+        url: Router.getUrl(),
+        data: data,
+        cache: false,
+        success: function(result) {
+          var canContinue = self.handleResult(result, self.actionQueue[actionName].finishMessage);
+          if (canContinue === true && (self.actionQueue[actionName].nextActionName !== undefined)) {
+            self.callAction(self.actionQueue[actionName].nextActionName, type);
+          }
+        },
+        error: function(result) {
+          self.handleResult(result);
+        }
+      });
+    },
 
-		/**
-		 * Handle ajax result of core update step.
-		 *
-		 * @param data
-		 * @param successMessage Optional success message
-		 */
-		handleResult: function (data, successMessage) {
-			var canContinue = false;
-			this.removeLoadingMessage();
-			if (data.success === true) {
-				canContinue = true;
-				if (data.status && typeof(data.status) === 'object') {
-					this.showStatusMessages(data.status);
-				}
-				if (data.action && typeof(data.action) === 'object') {
-					this.showActionButton(data.action);
-				}
-				if (successMessage) {
-					this.addMessage(Severity.ok, successMessage);
-				}
-			} else {
-				Router.handleAjaxError(xhr);
-			}
-			return canContinue;
-		},
+    /**
+     * Handle ajax result of core update step.
+     *
+     * @param data
+     * @param successMessage Optional success message
+     */
+    handleResult: function(data, successMessage) {
+      var canContinue = false;
+      this.removeLoadingMessage();
+      if (data.success === true) {
+        canContinue = true;
+        if (data.status && typeof(data.status) === 'object') {
+          this.showStatusMessages(data.status);
+        }
+        if (data.action && typeof(data.action) === 'object') {
+          this.showActionButton(data.action);
+        }
+        if (successMessage) {
+          this.addMessage(Severity.ok, successMessage);
+        }
+      } else {
+        Router.handleAjaxError(xhr);
+      }
+      return canContinue;
+    },
 
-		/**
-		 * Add a loading message with some text.
-		 *
-		 * @param messageTitle
-		 */
-		addLoadingMessage: function (messageTitle) {
-			var domMessage = FlashMessage.render(Severity.loading, messageTitle);
-			$(this.selectorOutput).append(domMessage);
-		},
+    /**
+     * Add a loading message with some text.
+     *
+     * @param messageTitle
+     */
+    addLoadingMessage: function(messageTitle) {
+      var domMessage = FlashMessage.render(Severity.loading, messageTitle);
+      $(this.selectorOutput).append(domMessage);
+    },
 
-		/**
-		 * Remove an enabled loading message
-		 */
-		removeLoadingMessage: function () {
-			$(this.selectorOutput).find('.alert-loading').remove();
-		},
+    /**
+     * Remove an enabled loading message
+     */
+    removeLoadingMessage: function() {
+      $(this.selectorOutput).find('.alert-loading').remove();
+    },
 
-		/**
-		 * Show a list of status messages
-		 *
-		 * @param messages
-		 */
-		showStatusMessages: function (messages) {
-			var self = this;
-			$.each(messages, function (index, element) {
-				var title = false;
-				var message = false;
-				var severity = element.severity;
-				if (element.title) {
-					title = element.title;
-				}
-				if (element.message) {
-					message = element.message;
-				}
-				self.addMessage(severity, title, message);
-			});
-		},
+    /**
+     * Show a list of status messages
+     *
+     * @param messages
+     */
+    showStatusMessages: function(messages) {
+      var self = this;
+      $.each(messages, function(index, element) {
+        var title = false;
+        var message = false;
+        var severity = element.severity;
+        if (element.title) {
+          title = element.title;
+        }
+        if (element.message) {
+          message = element.message;
+        }
+        self.addMessage(severity, title, message);
+      });
+    },
 
-		/**
-		 * Show an action button
-		 *
-		 * @param button
-		 */
-		showActionButton: function (button) {
-			var title = false;
-			var action = false;
-			if (button.title) {
-				title = button.title;
-			}
-			if (button.action) {
-				action = button.action;
-			}
-			var domButton = this.buttonTemplate;
-			if (action) {
-				domButton.find('button').data('action', action);
-			}
-			if (title) {
-				domButton.find('button').text(title);
-			}
-			$(this.selectorOutput).append(domButton);
-		},
+    /**
+     * Show an action button
+     *
+     * @param button
+     */
+    showActionButton: function(button) {
+      var title = false;
+      var action = false;
+      if (button.title) {
+        title = button.title;
+      }
+      if (button.action) {
+        action = button.action;
+      }
+      var domButton = this.buttonTemplate;
+      if (action) {
+        domButton.find('button').data('action', action);
+      }
+      if (title) {
+        domButton.find('button').text(title);
+      }
+      $(this.selectorOutput).append(domButton);
+    },
 
-		/**
-		 * Show a status message
-		 *
-		 * @param severity
-		 * @param title
-		 * @param message
-		 */
-		addMessage: function (severity, title, message) {
-			var domMessage = FlashMessage.render(severity, title, message);
-			$(this.selectorOutput).append(domMessage);
-		}
-	};
+    /**
+     * Show a status message
+     *
+     * @param severity
+     * @param title
+     * @param message
+     */
+    addMessage: function(severity, title, message) {
+      var domMessage = FlashMessage.render(severity, title, message);
+      $(this.selectorOutput).append(domMessage);
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js
index 311942bf3161..a745eb2227c1 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/CreateAdmin.js
@@ -15,68 +15,68 @@
  * Module: TYPO3/CMS/Install/CreateAdmin
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'TYPO3/CMS/Install/PasswordStrength',
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'TYPO3/CMS/Install/PasswordStrength'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, PasswordStrength) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorCreateForm: '#t3js-createAdmin-form',
-		selectorCreateToken: '#t3js-createAdmin-token',
-		selectorCreateTrigger: '.t3js-createAdmin-create',
-		selectorOutputContainer: '.t3js-createAdmin-output',
+  return {
+    selectorCreateForm: '#t3js-createAdmin-form',
+    selectorCreateToken: '#t3js-createAdmin-token',
+    selectorCreateTrigger: '.t3js-createAdmin-create',
+    selectorOutputContainer: '.t3js-createAdmin-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('submit', this.selectorCreateForm, function(e) {
-				e.preventDefault();
-				self.create();
-			});
-			$(document).on('keyup', '.t3-install-form-password-strength', function() {
-				PasswordStrength.initialize('.t3-install-form-password-strength');
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('submit', this.selectorCreateForm, function(e) {
+        e.preventDefault();
+        self.create();
+      });
+      $(document).on('keyup', '.t3-install-form-password-strength', function() {
+        PasswordStrength.initialize('.t3-install-form-password-strength');
+      });
+    },
 
-		create: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'createAdmin',
-						'token': $(self.selectorCreateToken).text(),
-						'userName': $('.t3js-createAdmin-user').val(),
-						'userPassword': $('.t3js-createAdmin-password').val(),
-						'userPasswordCheck': $('.t3js-createAdmin-password-check').val(),
-						'userSystemMaintainer': ($('.t3js-createAdmin-system-maintainer').is(':checked'))? 1 : 0
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.html(message);
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    create: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'createAdmin',
+            'token': $(self.selectorCreateToken).text(),
+            'userName': $('.t3js-createAdmin-user').val(),
+            'userPassword': $('.t3js-createAdmin-password').val(),
+            'userPasswordCheck': $('.t3js-createAdmin-password-check').val(),
+            'userSystemMaintainer': ($('.t3js-createAdmin-system-maintainer').is(':checked')) ? 1 : 0
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.html(message);
+            });
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js
index 9b8dd870bfe2..7daadb1a1c6c 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DatabaseAnalyzer.js
@@ -15,159 +15,159 @@
  * Module: TYPO3/CMS/Install/DatabaseAnalyzer
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-databaseAnalyzer-open',
-		selectorAnalyzeTrigger: '.t3js-databaseAnalyzer-analyze',
-		selectorExecuteTrigger: '.t3js-databaseAnalyzer-execute',
-		selectorOutputContainer: '.t3js-databaseAnalyzer-output',
-		selectorSuggestionBlock: '.t3js-databaseAnalyzer-suggestion-block',
-		selectorSuggestionLine: '.t3js-databaseAnalyzer-suggestion-line',
+  return {
+    selectorGridderOpener: 't3js-databaseAnalyzer-open',
+    selectorAnalyzeTrigger: '.t3js-databaseAnalyzer-analyze',
+    selectorExecuteTrigger: '.t3js-databaseAnalyzer-execute',
+    selectorOutputContainer: '.t3js-databaseAnalyzer-output',
+    selectorSuggestionBlock: '.t3js-databaseAnalyzer-suggestion-block',
+    selectorSuggestionLine: '.t3js-databaseAnalyzer-suggestion-line',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Load main content on first open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
-					$card.data('isInitialized', true);
-					self.analyze();
-				}
-			});
+      // Load main content on first open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
+          $card.data('isInitialized', true);
+          self.analyze();
+        }
+      });
 
-			// Select / deselect all checkboxes
-			$(document).on('click', '.t3js-databaseAnalyzer-suggestion-block-checkbox', function () {
-				$(this).closest('fieldset').find(':checkbox').prop('checked', this.checked);
-			});
-			$(document).on('click', this.selectorAnalyzeTrigger, function(e) {
-				e.preventDefault();
-				self.analyze();
-			});
-			$(document).on('click', this.selectorExecuteTrigger, function(e) {
-				e.preventDefault();
-				self.execute();
-			});
-		},
+      // Select / deselect all checkboxes
+      $(document).on('click', '.t3js-databaseAnalyzer-suggestion-block-checkbox', function() {
+        $(this).closest('fieldset').find(':checkbox').prop('checked', this.checked);
+      });
+      $(document).on('click', this.selectorAnalyzeTrigger, function(e) {
+        e.preventDefault();
+        self.analyze();
+      });
+      $(document).on('click', this.selectorExecuteTrigger, function(e) {
+        e.preventDefault();
+        self.execute();
+      });
+    },
 
-		analyze: function() {
-			$(this.selectorOutputContainer).empty();
-			this.analyzeAjax();
-		},
+    analyze: function() {
+      $(this.selectorOutputContainer).empty();
+      this.analyzeAjax();
+    },
 
-		analyzeAjax: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var blockTemplate = $(this.selectorSuggestionBlock).html();
-			var lineTemplate = $(this.selectorSuggestionLine).html();
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$(this.selectorExecuteTrigger).prop('disabled', true);
-			$(this.selectorAnalyzeTrigger).prop('disabled', true);
-			$.ajax({
-				url: Router.getUrl('databaseAnalyzerAnalyze'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true) {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.find('.alert-loading').remove();
-								$outputContainer.append(message);
-							});
-						}
-						if (Array.isArray(data.suggestions)) {
-							data.suggestions.forEach(function(element) {
-								var aBlock = $(blockTemplate).clone();
-								var key = element.key;
-								aBlock.find('.t3js-databaseAnalyzer-suggestion-block-legend').text(element.label);
-								aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('id', 't3-install-' + key + '-checkbox');
-								if (element.enabled) {
-									aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('checked', 'checked');
-								}
-								aBlock.find('.t3js-databaseAnalyzer-suggestion-block-label').attr('for', 't3-install-' + key + '-checkbox');
-								element.children.forEach(function(line) {
-									var aLine = $(lineTemplate).clone();
-									var hash = line.hash;
-									aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('id', 't3-install-db-' + hash);
-									aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').data('hash', hash);
-									if (element.enabled) {
-										aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('checked', 'checked');
-									}
-									aLine.find('.t3js-databaseAnalyzer-suggestion-line-label').attr('for', 't3-install-db-' + hash);
-									aLine.find('.t3js-databaseAnalyzer-suggestion-line-statement').text(line.statement);
-									if (line.current !== undefined) {
-										aLine.find('.t3js-databaseAnalyzer-suggestion-line-current-value').text(line.current);
-										aLine.find('.t3js-databaseAnalyzer-suggestion-line-current').show();
-									}
-									if (line.rowCount !== undefined) {
-										aLine.find('.t3js-databaseAnalyzer-suggestion-line-count-value').text(line.rowCount);
-										aLine.find('.t3js-databaseAnalyzer-suggestion-line-count').show();
-									}
-									aBlock.find('.t3js-databaseAnalyzer-suggestion-block-line').append(aLine);
-								});
-								$outputContainer.append(aBlock);
-							});
-							$(self.selectorExecuteTrigger).prop('disabled', false);
-							$(self.selectorAnalyzeTrigger).prop('disabled', false);
-						}
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    analyzeAjax: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var blockTemplate = $(this.selectorSuggestionBlock).html();
+      var lineTemplate = $(this.selectorSuggestionLine).html();
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $(this.selectorExecuteTrigger).prop('disabled', true);
+      $(this.selectorAnalyzeTrigger).prop('disabled', true);
+      $.ajax({
+        url: Router.getUrl('databaseAnalyzerAnalyze'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.find('.alert-loading').remove();
+                $outputContainer.append(message);
+              });
+            }
+            if (Array.isArray(data.suggestions)) {
+              data.suggestions.forEach(function(element) {
+                var aBlock = $(blockTemplate).clone();
+                var key = element.key;
+                aBlock.find('.t3js-databaseAnalyzer-suggestion-block-legend').text(element.label);
+                aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('id', 't3-install-' + key + '-checkbox');
+                if (element.enabled) {
+                  aBlock.find('.t3js-databaseAnalyzer-suggestion-block-checkbox').attr('checked', 'checked');
+                }
+                aBlock.find('.t3js-databaseAnalyzer-suggestion-block-label').attr('for', 't3-install-' + key + '-checkbox');
+                element.children.forEach(function(line) {
+                  var aLine = $(lineTemplate).clone();
+                  var hash = line.hash;
+                  aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('id', 't3-install-db-' + hash);
+                  aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').data('hash', hash);
+                  if (element.enabled) {
+                    aLine.find('.t3js-databaseAnalyzer-suggestion-line-checkbox').attr('checked', 'checked');
+                  }
+                  aLine.find('.t3js-databaseAnalyzer-suggestion-line-label').attr('for', 't3-install-db-' + hash);
+                  aLine.find('.t3js-databaseAnalyzer-suggestion-line-statement').text(line.statement);
+                  if (line.current !== undefined) {
+                    aLine.find('.t3js-databaseAnalyzer-suggestion-line-current-value').text(line.current);
+                    aLine.find('.t3js-databaseAnalyzer-suggestion-line-current').show();
+                  }
+                  if (line.rowCount !== undefined) {
+                    aLine.find('.t3js-databaseAnalyzer-suggestion-line-count-value').text(line.rowCount);
+                    aLine.find('.t3js-databaseAnalyzer-suggestion-line-count').show();
+                  }
+                  aBlock.find('.t3js-databaseAnalyzer-suggestion-block-line').append(aLine);
+                });
+                $outputContainer.append(aBlock);
+              });
+              $(self.selectorExecuteTrigger).prop('disabled', false);
+              $(self.selectorAnalyzeTrigger).prop('disabled', false);
+            }
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		execute: function() {
-			var self = this;
-			var executeToken = $('#t3js-databaseAnalyzer-execute-token').text();
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			var $outputContainer = $('.t3js-databaseAnalyzer-output');
-			var selectedHashes = [];
-			$('.gridder-show .t3js-databaseAnalyzer-output .t3js-databaseAnalyzer-suggestion-block-line input:checked').each(function () {
-				selectedHashes.push($(this).data('hash'));
-			});
-			$outputContainer.empty().html(message);
-			$(this.selectorExecuteTrigger).prop('disabled', true);
-			$(this.selectorAnalyzeTrigger).prop('disabled', true);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'databaseAnalyzerExecute',
-						'token': executeToken,
-						'hashes': selectedHashes
-					}
-				},
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.find('.alert-loading').remove();
-								$outputContainer.append(message);
-							});
-						}
-					}
-					self.analyzeAjax();
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    execute: function() {
+      var self = this;
+      var executeToken = $('#t3js-databaseAnalyzer-execute-token').text();
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      var $outputContainer = $('.t3js-databaseAnalyzer-output');
+      var selectedHashes = [];
+      $('.gridder-show .t3js-databaseAnalyzer-output .t3js-databaseAnalyzer-suggestion-block-line input:checked').each(function() {
+        selectedHashes.push($(this).data('hash'));
+      });
+      $outputContainer.empty().html(message);
+      $(this.selectorExecuteTrigger).prop('disabled', true);
+      $(this.selectorAnalyzeTrigger).prop('disabled', true);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'databaseAnalyzerExecute',
+            'token': executeToken,
+            'hashes': selectedHashes
+          }
+        },
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.find('.alert-loading').remove();
+                $outputContainer.append(message);
+              });
+            }
+          }
+          self.analyzeAjax();
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js
index 9db347316295..990f1c0fdc8c 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/DumpAutoload.js
@@ -15,52 +15,52 @@
  * Module: TYPO3/CMS/Install/DumpAutoload
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorDumpTrigger: '.t3js-dumpAutoload-dump',
-		selectorOutputContainer: '.t3js-dumpAutoload-output',
+  return {
+    selectorDumpTrigger: '.t3js-dumpAutoload-dump',
+    selectorOutputContainer: '.t3js-dumpAutoload-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorDumpTrigger, function(e) {
-				e.preventDefault();
-				self.dump();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorDumpTrigger, function(e) {
+        e.preventDefault();
+        self.dump();
+      });
+    },
 
-		dump: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('dumpAutoload'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							$outputContainer.empty();
-							data.status.forEach((function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							}));
-						}
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    dump: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('dumpAutoload'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            if (data.status.length > 0) {
+              $outputContainer.empty();
+              data.status.forEach((function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              }));
+            }
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js
index 81c8699aaf39..1d2d05706a85 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/EnvironmentCheck.js
@@ -15,75 +15,75 @@
  * Module: TYPO3/CMS/Install/EnvironmentCheck
  */
 define([
-    'jquery',
-    'TYPO3/CMS/Install/Router',
-    'TYPO3/CMS/Install/FlashMessage',
-    'TYPO3/CMS/Install/ProgressBar',
-    'TYPO3/CMS/Install/InfoBox',
-    'TYPO3/CMS/Install/Severity',
-    'bootstrap'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-    'use strict';
+  'use strict';
 
-    return {
-        selectorGridderBadge: '.t3js-environmentCheck-badge',
-        selectorExecuteTrigger: '.t3js-environmentCheck-execute',
-        selectorOutputContainer: '.t3js-environmentCheck-output',
+  return {
+    selectorGridderBadge: '.t3js-environmentCheck-badge',
+    selectorExecuteTrigger: '.t3js-environmentCheck-execute',
+    selectorOutputContainer: '.t3js-environmentCheck-output',
 
-        initialize: function() {
-            var self = this;
+    initialize: function() {
+      var self = this;
 
-            // Get status on initialize to have the badge and content ready
-            self.runTests();
+      // Get status on initialize to have the badge and content ready
+      self.runTests();
 
-            $(document).on('click', this.selectorExecuteTrigger, function(e) {
-                e.preventDefault();
-                self.runTests();
-            });
-        },
+      $(document).on('click', this.selectorExecuteTrigger, function(e) {
+        e.preventDefault();
+        self.runTests();
+      });
+    },
 
-        runTests: function() {
-            var $outputContainer = $(this.selectorOutputContainer);
-            var $errorBadge = $(this.selectorGridderBadge);
-            $errorBadge.text('').hide();
-            var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-            $outputContainer.empty().append(message);
-            $.ajax({
-                url: Router.getUrl('environmentCheckGetStatus'),
-                cache: false,
-                success: function(data) {
-                    $outputContainer.empty();
-                    var warningCount = 0;
-                    var errorCount = 0;
-                    if (data.success === true && typeof(data.status) === 'object') {
-                        $.each(data.status, function(i, element) {
-                            if (Array.isArray(element) && element.length > 0) {
-                                element.forEach(function(aStatus) {
-                                    if (aStatus.severity === 1) {
-                                        warningCount += 1;
-                                    }
-                                    if (aStatus.severity === 2) {
-                                        errorCount += 1;
-                                    }
-                                    var message = InfoBox.render(aStatus.severity, aStatus.title, aStatus.message);
-                                    $outputContainer.append(message);
-                                });
-                            }
-                        });
-                        if (errorCount > 0) {
-                            $errorBadge.removeClass('label-warning').addClass('label-danger').text(errorCount).show();
-                        } else if (warningCount > 0) {
-                            $errorBadge.removeClass('label-error').addClass('label-warning').text(warningCount).show();
-                        }
-                    } else {
-                      var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-                      $outputContainer.empty().append(message);
-                    }
-                },
-                error: function(xhr) {
-                    Router.handleAjaxError(xhr);
-                }
+    runTests: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $errorBadge = $(this.selectorGridderBadge);
+      $errorBadge.text('').hide();
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().append(message);
+      $.ajax({
+        url: Router.getUrl('environmentCheckGetStatus'),
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          var warningCount = 0;
+          var errorCount = 0;
+          if (data.success === true && typeof(data.status) === 'object') {
+            $.each(data.status, function(i, element) {
+              if (Array.isArray(element) && element.length > 0) {
+                element.forEach(function(aStatus) {
+                  if (aStatus.severity === 1) {
+                    warningCount += 1;
+                  }
+                  if (aStatus.severity === 2) {
+                    errorCount += 1;
+                  }
+                  var message = InfoBox.render(aStatus.severity, aStatus.title, aStatus.message);
+                  $outputContainer.append(message);
+                });
+              }
             });
+            if (errorCount > 0) {
+              $errorBadge.removeClass('label-warning').addClass('label-danger').text(errorCount).show();
+            } else if (warningCount > 0) {
+              $errorBadge.removeClass('label-error').addClass('label-warning').text(warningCount).show();
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
         }
-    };
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js
index f8daa7291e61..bf0ffcbd71df 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionCompatTester.js
@@ -15,185 +15,185 @@
  * Module: TYPO3/CMS/Install/ExtensionCompatTester
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'TYPO3/CMS/Install/Cache'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'TYPO3/CMS/Install/Cache'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity, Cache) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorLoadExtLocalconfToken: '#t3js-extensionCompatTester-loadExtLocalconf-token',
-		selectorLoadExtTablesToken: '#t3js-extensionCompatTester-loadExtTables-token',
-		selectorUninstallExtensionToken: '#t3js-extensionCompatTester-uninstallExtension-token',
-		selectorCheckTrigger: '.t3js-extensionCompatTester-check',
-		selectorUninstallTrigger: '.t3js-extensionCompatTester-uninstall',
-		selectorOutputContainer: '.t3js-extensionCompatTester-output',
+  return {
+    selectorLoadExtLocalconfToken: '#t3js-extensionCompatTester-loadExtLocalconf-token',
+    selectorLoadExtTablesToken: '#t3js-extensionCompatTester-loadExtTables-token',
+    selectorUninstallExtensionToken: '#t3js-extensionCompatTester-uninstallExtension-token',
+    selectorCheckTrigger: '.t3js-extensionCompatTester-check',
+    selectorUninstallTrigger: '.t3js-extensionCompatTester-uninstall',
+    selectorOutputContainer: '.t3js-extensionCompatTester-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorCheckTrigger, function(e) {
-				$(self.selectorUninstallTrigger).hide();
-				$(self.selectorOutputContainer).empty();
-				self.getLoadedExtensionList();
-			});
-			$(document).on('click', this.selectorUninstallTrigger, function(e) {
-				self.uninstallExtension($(e.target).data('extension'));
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorCheckTrigger, function(e) {
+        $(self.selectorUninstallTrigger).hide();
+        $(self.selectorOutputContainer).empty();
+        self.getLoadedExtensionList();
+      });
+      $(document).on('click', this.selectorUninstallTrigger, function(e) {
+        self.uninstallExtension($(e.target).data('extension'));
+      });
+    },
 
-		getLoadedExtensionList: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var $uninstallButton = $(this.selectorUninstallTrigger);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			var loadResult = false;
-			$.ajax({
-				url: Router.getUrl('extensionCompatTesterLoadedExtensionList'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && Array.isArray(data.extensions)) {
-						var extension;
-						try {
-							data.extensions.forEach(function(extension) {
-								loadResult = self.loadExtLocalconf(extension);
-								if (loadResult === false) {
-									throw extension;
-								}
-							});
-							message = InfoBox.render(Severity.OK, 'ext_localconf.php of all loaded extensions successfully loaded', '');
-							$outputContainer.find('.alert-loading').remove();
-							$outputContainer.append(message);
-							var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-							$outputContainer.append(message);
-							try {
-								data.extensions.forEach(function(extension) {
-									loadResult = self.loadExtTables(extension);
-									if (loadResult === false) {
-										throw extension;
-									}
-								});
-								message = InfoBox.render(Severity.OK, 'ext_tables.php of all loaded extensions successfully loaded', '');
-								$outputContainer.find('.alert-loading').remove();
-								$outputContainer.append(message);
-							} catch (extension) {
-								message = InfoBox.render(Severity.error, 'Loading ext_tables.php of extension "' + extension + '" failed');
-								$outputContainer.find('.alert-loading').remove();
-								$outputContainer.append(message);
-								$uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show();
-							}
-						} catch (extension) {
-							message = InfoBox.render(Severity.error, 'Loading ext_localconf.php of extension "' + extension + '" failed');
-							$outputContainer.find('.alert-loading').remove();
-							$outputContainer.append(message);
-							$uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show();
-						}
-					} else {
-						message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getLoadedExtensionList: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $uninstallButton = $(this.selectorUninstallTrigger);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      var loadResult = false;
+      $.ajax({
+        url: Router.getUrl('extensionCompatTesterLoadedExtensionList'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.extensions)) {
+            var extension;
+            try {
+              data.extensions.forEach(function(extension) {
+                loadResult = self.loadExtLocalconf(extension);
+                if (loadResult === false) {
+                  throw extension;
+                }
+              });
+              message = InfoBox.render(Severity.OK, 'ext_localconf.php of all loaded extensions successfully loaded', '');
+              $outputContainer.find('.alert-loading').remove();
+              $outputContainer.append(message);
+              var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+              $outputContainer.append(message);
+              try {
+                data.extensions.forEach(function(extension) {
+                  loadResult = self.loadExtTables(extension);
+                  if (loadResult === false) {
+                    throw extension;
+                  }
+                });
+                message = InfoBox.render(Severity.OK, 'ext_tables.php of all loaded extensions successfully loaded', '');
+                $outputContainer.find('.alert-loading').remove();
+                $outputContainer.append(message);
+              } catch (extension) {
+                message = InfoBox.render(Severity.error, 'Loading ext_tables.php of extension "' + extension + '" failed');
+                $outputContainer.find('.alert-loading').remove();
+                $outputContainer.append(message);
+                $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show();
+              }
+            } catch (extension) {
+              message = InfoBox.render(Severity.error, 'Loading ext_localconf.php of extension "' + extension + '" failed');
+              $outputContainer.find('.alert-loading').remove();
+              $outputContainer.append(message);
+              $uninstallButton.text('Unload extension "' + extension + '"').data('extension', extension).show();
+            }
+          } else {
+            message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		loadExtLocalconf: function(extension) {
-			var self = this;
-			var result = false;
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				cache: false,
-				async: false,
-				data: {
-					'install': {
-						'action': 'extensionCompatTesterLoadExtLocalconf',
-						'token': $(self.selectorLoadExtLocalconfToken).text(),
-						'extension': extension
-					}
-				},
-				success: function(data) {
-					result = data.success === true;
-				},
-				error: function(data) {
-					result = false;
-				}
-			});
-			return result;
-		},
+    loadExtLocalconf: function(extension) {
+      var self = this;
+      var result = false;
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        cache: false,
+        async: false,
+        data: {
+          'install': {
+            'action': 'extensionCompatTesterLoadExtLocalconf',
+            'token': $(self.selectorLoadExtLocalconfToken).text(),
+            'extension': extension
+          }
+        },
+        success: function(data) {
+          result = data.success === true;
+        },
+        error: function(data) {
+          result = false;
+        }
+      });
+      return result;
+    },
 
-		loadExtTables: function(extension) {
-			var self = this;
-			var result = false;
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				cache: false,
-				async: false,
-				data: {
-					'install': {
-						'action': 'extensionCompatTesterLoadExtTables',
-						'token': $(self.selectorLoadExtTablesToken).text(),
-						'extension': extension
-					}
-				},
-				success: function(data) {
-					result = data.success === true;
-				},
-				error: function(data) {
-					result = false;
-				}
-			});
-			return result;
-		},
+    loadExtTables: function(extension) {
+      var self = this;
+      var result = false;
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        cache: false,
+        async: false,
+        data: {
+          'install': {
+            'action': 'extensionCompatTesterLoadExtTables',
+            'token': $(self.selectorLoadExtTablesToken).text(),
+            'extension': extension
+          }
+        },
+        success: function(data) {
+          result = data.success === true;
+        },
+        error: function(data) {
+          result = false;
+        }
+      });
+      return result;
+    },
 
-		/**
-		 * Send an ajax request to uninstall an extension (or multiple extensions)
-		 *
-		 * @param extension string of extension(s) - may be comma separated
-		 */
-		uninstallExtension: function(extension) {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$.ajax({
-				url: Router.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'extensionCompatTesterUninstallExtension',
-						'token': $(self.selectorUninstallExtensionToken).text(),
-						'extension': extension
-					}
-				},
-				success: function(data) {
-					if (data.success) {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.empty().append(message);
-							});
-						}
-						$(self.selectorUninstallTrigger).hide();
-						Cache.clearAll();
-						self.getLoadedExtensionList();
-					} else {
-						message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    /**
+     * Send an ajax request to uninstall an extension (or multiple extensions)
+     *
+     * @param extension string of extension(s) - may be comma separated
+     */
+    uninstallExtension: function(extension) {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $.ajax({
+        url: Router.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'extensionCompatTesterUninstallExtension',
+            'token': $(self.selectorUninstallExtensionToken).text(),
+            'extension': extension
+          }
+        },
+        success: function(data) {
+          if (data.success) {
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.empty().append(message);
+              });
+            }
+            $(self.selectorUninstallTrigger).hide();
+            Cache.clearAll();
+            self.getLoadedExtensionList();
+          } else {
+            message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js
index 5db58ecb6c0a..13c9970e6e9c 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionConfiguration.js
@@ -15,214 +15,214 @@
  * Module: TYPO3/CMS/Install/ExtensionConfiguration
  */
 define([
-    'jquery',
-    'TYPO3/CMS/Install/Router',
-    'TYPO3/CMS/Install/FlashMessage',
-    'TYPO3/CMS/Install/ProgressBar',
-    'TYPO3/CMS/Install/InfoBox',
-    'TYPO3/CMS/Install/Severity',
-    'bootstrap'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-    'use strict';
-
-    return {
-        selectorGridderOpener: 't3js-extensionConfiguration-open',
-        selectorContentContainer: '.t3js-extensionConfiguration-content',
-        selectorFormListener: '.t3js-extensionConfiguration-form',
-        selectorWriteToken: '#t3js-extensionConfiguration-write-token',
-        selectorOutputContainer: '.t3js-extensionConfiguration-output',
-        selectorSearchInput: '.t3js-extensionConfiguration-search',
-
-        initialize: function() {
-            var self = this;
-
-            // Get extension configuration list on card open
-            $(document).on('cardlayout:card-opened', function(event, $card) {
-                if ($card.hasClass(self.selectorGridderOpener)) {
-                    self.getContent();
-                }
-            });
-
-            // Focus search field on certain user interactions
-            $(document).on('keydown', function(e) {
-                var $searchInput = $(self.selectorSearchInput);
-                if (e.ctrlKey || e.metaKey) {
-                    // Focus search field on ctrl-f
-                    switch (String.fromCharCode(e.which).toLowerCase()) {
-                        case 'f':
-                            e.preventDefault();
-                            $searchInput.focus();
-                            break;
-                    }
-                } else if (e.keyCode === 27) {
-                    // Clear search on ESC key
-                    e.preventDefault();
-                    $searchInput.val('').focus();
-                }
-            });
-
-            // Perform expand collapse on search matches
-            $(document).on('keyup', this.selectorSearchInput, function() {
-                var typedQuery = $(this).val();
-                var $searchInput = $(self.selectorSearchInput);
-                $('.search-item').each(function() {
-                    var $item = $(this);
-                    if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
-                        $item.removeClass('hidden').addClass('searchhit');
-                    } else {
-                        $item.removeClass('searchhit').addClass('hidden');
-                    }
-                });
-                $('.searchhit').collapse('show');
-                // Make search field clearable
-                require(['jquery.clearable'], function() {
-                    $searchInput.clearable().focus();
-                });
-            });
-
-            $(document).on('submit', this.selectorFormListener, function(e) {
-                e.preventDefault();
-                self.write($(this));
-            });
+  'use strict';
+
+  return {
+    selectorGridderOpener: 't3js-extensionConfiguration-open',
+    selectorContentContainer: '.t3js-extensionConfiguration-content',
+    selectorFormListener: '.t3js-extensionConfiguration-form',
+    selectorWriteToken: '#t3js-extensionConfiguration-write-token',
+    selectorOutputContainer: '.t3js-extensionConfiguration-output',
+    selectorSearchInput: '.t3js-extensionConfiguration-search',
+
+    initialize: function() {
+      var self = this;
+
+      // Get extension configuration list on card open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener)) {
+          self.getContent();
+        }
+      });
+
+      // Focus search field on certain user interactions
+      $(document).on('keydown', function(e) {
+        var $searchInput = $(self.selectorSearchInput);
+        if (e.ctrlKey || e.metaKey) {
+          // Focus search field on ctrl-f
+          switch (String.fromCharCode(e.which).toLowerCase()) {
+            case 'f':
+              e.preventDefault();
+              $searchInput.focus();
+              break;
+          }
+        } else if (e.keyCode === 27) {
+          // Clear search on ESC key
+          e.preventDefault();
+          $searchInput.val('').focus();
+        }
+      });
+
+      // Perform expand collapse on search matches
+      $(document).on('keyup', this.selectorSearchInput, function() {
+        var typedQuery = $(this).val();
+        var $searchInput = $(self.selectorSearchInput);
+        $('.search-item').each(function() {
+          var $item = $(this);
+          if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
+            $item.removeClass('hidden').addClass('searchhit');
+          } else {
+            $item.removeClass('searchhit').addClass('hidden');
+          }
+        });
+        $('.searchhit').collapse('show');
+        // Make search field clearable
+        require(['jquery.clearable'], function() {
+          $searchInput.clearable().focus();
+        });
+      });
+
+      $(document).on('submit', this.selectorFormListener, function(e) {
+        e.preventDefault();
+        self.write($(this));
+      });
+    },
+
+    getContent: function() {
+      var self = this;
+      var outputContainer = $(this.selectorContentContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('extensionConfigurationGetContent'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            outputContainer.empty().append(data.html);
+            self.initializeWrap();
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            outputContainer.empty().append(message);
+          }
         },
-
-        getContent: function() {
-            var self = this;
-            var outputContainer = $(this.selectorContentContainer);
-            var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-            outputContainer.empty().html(message);
-            $.ajax({
-                url: Router.getUrl('extensionConfigurationGetContent'),
-                cache: false,
-                success: function(data) {
-                    if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-                        outputContainer.empty().append(data.html);
-                        self.initializeWrap();
-                    } else {
-                        var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-                        outputContainer.empty().append(message);
-                    }
-                },
-                error: function(xhr) {
-                    Router.handleAjaxError(xhr);
-                }
-            });
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
+
+    /**
+     * Submit the form and show the result message
+     *
+     * @param {jQuery} $form The form of the current extension
+     */
+    write: function($form) {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      var extensionConfiguration = {};
+      $.each($form.serializeArray(), function() {
+        extensionConfiguration[this.name] = this.value;
+      });
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'token': $(this.selectorWriteToken).text(),
+            'action': 'extensionConfigurationWrite',
+            'extensionKey': $form.attr('data-extensionKey'),
+            'extensionConfiguration': extensionConfiguration
+          }
         },
-
-        /**
-         * Submit the form and show the result message
-         *
-         * @param {jQuery} $form The form of the current extension
-         */
-        write: function($form) {
-            var $outputContainer = $(this.selectorOutputContainer);
-            var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-            $outputContainer.append(message);
-            var extensionConfiguration = { };
-            $.each($form.serializeArray(), function() {
-              extensionConfiguration[this.name] = this.value;
-            });
-            $.ajax({
-                url: Router.getUrl(),
-                method: 'POST',
-                data: {
-                    'install': {
-                        'token': $(this.selectorWriteToken).text(),
-                        'action': 'extensionConfigurationWrite',
-                        'extensionKey': $form.attr('data-extensionKey'),
-                        'extensionConfiguration': extensionConfiguration
-                    }
-                },
-                success: function (data) {
-                    if (data.success === true && Array.isArray(data.status)) {
-                        data.status.forEach(function(element) {
-                            var message = InfoBox.render(element.severity, element.title, element.message);
-                            $outputContainer.empty().append(message);
-                        });
-                    } else {
-                        var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-                        $outputContainer.empty().html(message);
-                    }
-                },
-                error: function(xhr) {
-                    Router.handleAjaxError(xhr);
-                }
-            }).always(function() {
-                $outputContainer.find('.alert-loading').remove();
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.empty().append(message);
             });
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
         },
-
-        /**
-         * configuration properties
-         */
-        initializeWrap: function() {
-            $('.t3js-emconf-offset').each(function() {
-                var $me = $(this),
-                    $parent = $me.parent(),
-                    id = $me.attr('id'),
-                    val = $me.attr('value'),
-                    valArr = val.split(',');
-
-                $me.attr('data-offsetfield-x', '#' + id + '_offset_x')
-                    .attr('data-offsetfield-y', '#' + id + '_offset_y')
-                    .wrap('<div class="hidden"></div>');
-
-                var elementX = '' +
-                    '<div class="form-multigroup-item">' +
-                    '<div class="input-group">' +
-                    '<div class="input-group-addon">x</div>' +
-                    '<input id="' + id + '_offset_x" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
-                    '</div>' +
-                    '</div>';
-                var elementY = '' +
-                    '<div class="form-multigroup-item">' +
-                    '<div class="input-group">' +
-                    '<div class="input-group-addon">y</div>' +
-                    '<input id="' + id + '_offset_y" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
-                    '</div>' +
-                    '</div>';
-
-                var offsetGroup = '<div class="form-multigroup-wrap">' + elementX + elementY + '</div>';
-                $parent.append(offsetGroup);
-                $parent.find('.t3js-emconf-offset').keyup(function() {
-                    var $target = $($(this).data('target'));
-                    $target.attr(
-                        'value',
-                        $($target.data('offsetfield-x')).val() + ',' + $($target.data('offsetfield-y')).val()
-                    );
-                });
-            });
-
-            $('.t3js-emconf-wrap').each(function() {
-                var $me = $(this),
-                    $parent = $me.parent(),
-                    id = $me.attr('id'),
-                    val = $me.attr('value'),
-                    valArr = val.split('|');
-
-                $me.attr('data-wrapfield-start', '#' + id + '_wrap_start')
-                    .attr('data-wrapfield-end', '#' + id + '_wrap_end')
-                    .wrap('<div class="hidden"></div>');
-
-                var elementStart = '' +
-                    '<div class="form-multigroup-item">' +
-                    '<input id="' + id + '_wrap_start" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
-                    '</div>';
-                var elementEnd = '' +
-                    '<div class="form-multigroup-item">' +
-                    '<input id="' + id + '_wrap_end" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
-                    '</div>';
-
-                var wrapGroup = '<div class="form-multigroup-wrap">' + elementStart + elementEnd + '</div>';
-                $parent.append(wrapGroup);
-                $parent.find('.t3js-emconf-wrapfield').keyup(function() {
-                    var $target = $($(this).data('target'));
-                    $target.attr(
-                        'value',
-                        $($target.data('wrapfield-start')).val() + '|' + $($target.data('wrapfield-end')).val()
-                    );
-                });
-            });
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
         }
-    };
+      }).always(function() {
+        $outputContainer.find('.alert-loading').remove();
+      });
+    },
+
+    /**
+     * configuration properties
+     */
+    initializeWrap: function() {
+      $('.t3js-emconf-offset').each(function() {
+        var $me = $(this),
+          $parent = $me.parent(),
+          id = $me.attr('id'),
+          val = $me.attr('value'),
+          valArr = val.split(',');
+
+        $me.attr('data-offsetfield-x', '#' + id + '_offset_x')
+          .attr('data-offsetfield-y', '#' + id + '_offset_y')
+          .wrap('<div class="hidden"></div>');
+
+        var elementX = '' +
+          '<div class="form-multigroup-item">' +
+          '<div class="input-group">' +
+          '<div class="input-group-addon">x</div>' +
+          '<input id="' + id + '_offset_x" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
+          '</div>' +
+          '</div>';
+        var elementY = '' +
+          '<div class="form-multigroup-item">' +
+          '<div class="input-group">' +
+          '<div class="input-group-addon">y</div>' +
+          '<input id="' + id + '_offset_y" class="form-control t3js-emconf-offsetfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
+          '</div>' +
+          '</div>';
+
+        var offsetGroup = '<div class="form-multigroup-wrap">' + elementX + elementY + '</div>';
+        $parent.append(offsetGroup);
+        $parent.find('.t3js-emconf-offset').keyup(function() {
+          var $target = $($(this).data('target'));
+          $target.attr(
+            'value',
+            $($target.data('offsetfield-x')).val() + ',' + $($target.data('offsetfield-y')).val()
+          );
+        });
+      });
+
+      $('.t3js-emconf-wrap').each(function() {
+        var $me = $(this),
+          $parent = $me.parent(),
+          id = $me.attr('id'),
+          val = $me.attr('value'),
+          valArr = val.split('|');
+
+        $me.attr('data-wrapfield-start', '#' + id + '_wrap_start')
+          .attr('data-wrapfield-end', '#' + id + '_wrap_end')
+          .wrap('<div class="hidden"></div>');
+
+        var elementStart = '' +
+          '<div class="form-multigroup-item">' +
+          '<input id="' + id + '_wrap_start" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[0]) + '">' +
+          '</div>';
+        var elementEnd = '' +
+          '<div class="form-multigroup-item">' +
+          '<input id="' + id + '_wrap_end" class="form-control t3js-emconf-wrapfield" data-target="#' + id + '" value="' + $.trim(valArr[1]) + '">' +
+          '</div>';
+
+        var wrapGroup = '<div class="form-multigroup-wrap">' + elementStart + elementEnd + '</div>';
+        $parent.append(wrapGroup);
+        $parent.find('.t3js-emconf-wrapfield').keyup(function() {
+          var $target = $($(this).data('target'));
+          $target.attr(
+            'value',
+            $($target.data('wrapfield-start')).val() + '|' + $($target.data('wrapfield-end')).val()
+          );
+        });
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js
index 55d81c2a24cc..ad3a2dd1e122 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ExtensionScanner.js
@@ -15,294 +15,294 @@
  * Module: TYPO3/CMS/Install/ExtensionScanner
  */
 define(['jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Backend/Notification'
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Backend/Notification'
 ], function($, Router, Notification) {
-	'use strict';
+  'use strict';
 
-	return {
-		listOfAffectedRestFileHashes: [],
-		selectorFilesToken: '#t3js-extensionScanner-files-token',
-		selectorScanFileToken: '#t3js-extensionScanner-scan-file-token',
-		selectorMarkFullyScannedRestFilesToken: '#t3js-extensionScanner-mark-fully-scanned-rest-files-token',
-		selectorExtensionContainer: '.t3js-extensionScanner-extension',
-		selectorNumberOfFiles: '.t3js-extensionScanner-number-of-files',
-		selectorScanSingleTrigger: '.t3js-extensionScanner-scan-single',
+  return {
+    listOfAffectedRestFileHashes: [],
+    selectorFilesToken: '#t3js-extensionScanner-files-token',
+    selectorScanFileToken: '#t3js-extensionScanner-scan-file-token',
+    selectorMarkFullyScannedRestFilesToken: '#t3js-extensionScanner-mark-fully-scanned-rest-files-token',
+    selectorExtensionContainer: '.t3js-extensionScanner-extension',
+    selectorNumberOfFiles: '.t3js-extensionScanner-number-of-files',
+    selectorScanSingleTrigger: '.t3js-extensionScanner-scan-single',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorScanSingleTrigger, function(e) {
-				// Scan a single extension
-				var extension = $(e.target).data('extension');
-				e.preventDefault();
-				self.scanSingleExtension(extension);
-				return false;
-			});
-			$(document).on('show.bs.collapse', this.selectorExtensionContainer, function(e) {
-				// Trigger extension scan on opening a extension collapsible
-				if ($(e.target).closest(self.selectorExtensionContainer).data('hasRun') !== 'true') {
-					$(this).find(self.selectorScanSingleTrigger).click();
-				}
-			});
-			$(document).on('click', '.t3js-extensionScanner-scan-all', function(e) {
-				// Scann all button
-				e.preventDefault();
-				var $extensions = $(self.selectorExtensionContainer);
-				self.scanAll($extensions);
-				return false;
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorScanSingleTrigger, function(e) {
+        // Scan a single extension
+        var extension = $(e.target).data('extension');
+        e.preventDefault();
+        self.scanSingleExtension(extension);
+        return false;
+      });
+      $(document).on('show.bs.collapse', this.selectorExtensionContainer, function(e) {
+        // Trigger extension scan on opening a extension collapsible
+        if ($(e.target).closest(self.selectorExtensionContainer).data('hasRun') !== 'true') {
+          $(this).find(self.selectorScanSingleTrigger).click();
+        }
+      });
+      $(document).on('click', '.t3js-extensionScanner-scan-all', function(e) {
+        // Scann all button
+        e.preventDefault();
+        var $extensions = $(self.selectorExtensionContainer);
+        self.scanAll($extensions);
+        return false;
+      });
+    },
 
-		/**
-		 * @param {string} extension
-		 * @returns {string}
-		 */
-		getExtensionSelector: function(extension) {
-			return this.selectorExtensionContainer + '-' + extension;
-		},
+    /**
+     * @param {string} extension
+     * @returns {string}
+     */
+    getExtensionSelector: function(extension) {
+      return this.selectorExtensionContainer + '-' + extension;
+    },
 
-		/**
-		 * @param {JQuery} $extensions
-		 */
-		scanAll: function($extensions) {
-			var self = this;
-			$(this.selectorExtensionContainer)
-				.removeClass('panel-danger panel-warning panel-success')
-				.find('.panel-progress-bar')
-				.css('width', 0)
-				.attr('aria-valuenow', 0)
-				.find('span')
-				.text('0%');
-			self.setProgressForAll();
-			$extensions.each(function() {
-				var extension = $(this).data('extension');
-				self.scanSingleExtension(extension);
-			});
-		},
+    /**
+     * @param {JQuery} $extensions
+     */
+    scanAll: function($extensions) {
+      var self = this;
+      $(this.selectorExtensionContainer)
+        .removeClass('panel-danger panel-warning panel-success')
+        .find('.panel-progress-bar')
+        .css('width', 0)
+        .attr('aria-valuenow', 0)
+        .find('span')
+        .text('0%');
+      self.setProgressForAll();
+      $extensions.each(function() {
+        var extension = $(this).data('extension');
+        self.scanSingleExtension(extension);
+      });
+    },
 
-		/**
-		 * @param {string} extension
-		 * @param {number} doneFiles
-		 * @param {number} numberOfFiles
-		 */
-		setStatusMessageForScan: function(extension, doneFiles, numberOfFiles) {
-			$(this.getExtensionSelector(extension))
-				.find(this.selectorNumberOfFiles)
-				.text('Checked ' + doneFiles + ' of ' + numberOfFiles + ' files');
-		},
+    /**
+     * @param {string} extension
+     * @param {number} doneFiles
+     * @param {number} numberOfFiles
+     */
+    setStatusMessageForScan: function(extension, doneFiles, numberOfFiles) {
+      $(this.getExtensionSelector(extension))
+        .find(this.selectorNumberOfFiles)
+        .text('Checked ' + doneFiles + ' of ' + numberOfFiles + ' files');
+    },
 
-		/**
-		 * @param {string} extension
-		 * @param {number} doneFiles
-		 * @param {number} numberOfFiles
-		 */
-		setProgressForScan: function(extension, doneFiles, numberOfFiles) {
-			var percent = (doneFiles / numberOfFiles) * 100;
-			$(this.getExtensionSelector(extension))
-				.find('.panel-progress-bar')
-				.css('width', percent + '%')
-				.attr('aria-valuenow', percent)
-				.find('span')
-				.text(percent + '%');
-		},
+    /**
+     * @param {string} extension
+     * @param {number} doneFiles
+     * @param {number} numberOfFiles
+     */
+    setProgressForScan: function(extension, doneFiles, numberOfFiles) {
+      var percent = (doneFiles / numberOfFiles) * 100;
+      $(this.getExtensionSelector(extension))
+        .find('.panel-progress-bar')
+        .css('width', percent + '%')
+        .attr('aria-valuenow', percent)
+        .find('span')
+        .text(percent + '%');
+    },
 
-		/**
-		 * Update main progress bar
-		 */
-		setProgressForAll: function() {
-			var self = this;
-			var numberOfExtensions = $(this.selectorExtensionContainer).length;
-			var numberOfSuccess = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-success').length;
-			var numberOfWarning = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-warning').length;
-			var numberOfError = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-danger').length;
-			var numberOfScannedExtensions = numberOfSuccess + numberOfWarning + numberOfError;
-			var percent = (numberOfScannedExtensions / numberOfExtensions) * 100;
-			$('.t3js-extensionScanner-progress-all-extension .progress-bar')
-				.css('width', percent + '%')
-				.attr('aria-valuenow', percent)
-				.find('span')
-				.text(numberOfScannedExtensions + ' of ' + numberOfExtensions + ' scanned');
-			if (numberOfScannedExtensions === numberOfExtensions) {
-				Notification.success('Scan finished', 'All extensions have been scanned');
-				$.ajax({
-					url: Router.getUrl(),
-					method: 'POST',
-					data: {
-						'install': {
-							'action': 'extensionScannerMarkFullyScannedRestFiles',
-							'token': $(self.selectorMarkFullyScannedRestFilesToken).text(),
-							'hashes': self.uniqueArray(this.listOfAffectedRestFileHashes)
-						}
-					},
-					cache: false,
-					success: function(data) {
-						if (data.success === true) {
-							Notification.success('Marked not affected files', 'Marked ' + data.markedAsNotAffected + ' ReST files as not affected.');
-						}
-					},
-					error: function(xhr) {
-						Router.handleAjaxError(xhr);
-					}
-				});
-			}
-		},
+    /**
+     * Update main progress bar
+     */
+    setProgressForAll: function() {
+      var self = this;
+      var numberOfExtensions = $(this.selectorExtensionContainer).length;
+      var numberOfSuccess = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-success').length;
+      var numberOfWarning = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-warning').length;
+      var numberOfError = $(this.selectorExtensionContainer + '.t3js-extensionscan-finished.panel-danger').length;
+      var numberOfScannedExtensions = numberOfSuccess + numberOfWarning + numberOfError;
+      var percent = (numberOfScannedExtensions / numberOfExtensions) * 100;
+      $('.t3js-extensionScanner-progress-all-extension .progress-bar')
+        .css('width', percent + '%')
+        .attr('aria-valuenow', percent)
+        .find('span')
+        .text(numberOfScannedExtensions + ' of ' + numberOfExtensions + ' scanned');
+      if (numberOfScannedExtensions === numberOfExtensions) {
+        Notification.success('Scan finished', 'All extensions have been scanned');
+        $.ajax({
+          url: Router.getUrl(),
+          method: 'POST',
+          data: {
+            'install': {
+              'action': 'extensionScannerMarkFullyScannedRestFiles',
+              'token': $(self.selectorMarkFullyScannedRestFilesToken).text(),
+              'hashes': self.uniqueArray(this.listOfAffectedRestFileHashes)
+            }
+          },
+          cache: false,
+          success: function(data) {
+            if (data.success === true) {
+              Notification.success('Marked not affected files', 'Marked ' + data.markedAsNotAffected + ' ReST files as not affected.');
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      }
+    },
 
-		/**
-		 * Helper method removing duplicate entries from an array
-		 *
-		 * @param {Array} anArray
-		 * @returns {Array}
-		 */
-		uniqueArray: function(anArray) {
-			return anArray.filter(function(value, index, self) {
-				return self.indexOf(value) === index;
-			});
-		},
+    /**
+     * Helper method removing duplicate entries from an array
+     *
+     * @param {Array} anArray
+     * @returns {Array}
+     */
+    uniqueArray: function(anArray) {
+      return anArray.filter(function(value, index, self) {
+        return self.indexOf(value) === index;
+      });
+    },
 
-		/**
-		 * Handle a single extension scan
-		 *
-		 * @param {string} extension
-		 */
-		scanSingleExtension: function(extension) {
-			var self = this;
-			var $extensionContainer = $(this.getExtensionSelector(extension));
-			var hitTemplate = $('#t3js-extensionScanner-file-hit-template').html();
-			var restTemplate = $('#t3js-extensionScanner-file-hit-rest-template').html();
-			var hitFound = false;
-			$extensionContainer.removeClass('panel-danger panel-warning panel-success t3js-extensionscan-finished');
-			$extensionContainer.data('hasRun', 'true');
-			$extensionContainer.find('.t3js-extensionScanner-scan-single').text('Scanning...').attr('disabled', 'disabled');
-			$extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text('0');
-			$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text('0');
-			$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text('0');
-			this.setProgressForAll();
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'extensionScannerFiles',
-						'token': $(self.selectorFilesToken).text(),
-						'extension': extension
-					}
-				},
-				cache: false,
-				success: function(data) {
-					if (data.success === true && Array.isArray(data.files)) {
-						var numberOfFiles = data.files.length;
-						if (numberOfFiles > 0) {
-							self.setStatusMessageForScan(extension, 0, numberOfFiles);
-							$extensionContainer.find('.t3js-extensionScanner-extension-body').text('');
-							var doneFiles = 0;
-							data.files.forEach(function(file) {
-								$.ajax({
-									method: 'POST',
-									data: {
-										'install': {
-											'action': 'extensionScannerScanFile',
-											'token': $(self.selectorScanFileToken).text(),
-											'extension': extension,
-											'file': file
-										}
-									},
-									url: Router.getUrl(),
-									cache: false,
-									success: function(fileData) {
-										doneFiles = doneFiles + 1;
-										self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
-										self.setProgressForScan(extension, doneFiles, numberOfFiles);
-										if (fileData.success && $.isArray(fileData.matches)) {
-											$(fileData.matches).each(function() {
-												hitFound = true;
-												var match = this;
-												var aMatch = $(hitTemplate).clone();
-												aMatch.find('.t3js-extensionScanner-hit-file-panel-head').attr('href', '#collapse' + match.uniqueId);
-												aMatch.find('.t3js-extensionScanner-hit-file-panel-body').attr('id', 'collapse' + match.uniqueId);
-												aMatch.find('.t3js-extensionScanner-hit-filename').text(file);
-												aMatch.find('.t3js-extensionScanner-hit-message').text(match.message);
-												if (match.indicator === 'strong') {
-													aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
-														.append('<span class="badge" title="Reliable match, false positive unlikely">strong</span>');
-												} else {
-													aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
-														.append('<span class="badge" title="Probable match, but can be a false positive">weak</span>');
-												}
-												if (match.silenced === true) {
-													aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
-														.append('<span class="badge" title="Match has been annotated by extension author as false positive match">silenced</span>');
-												}
-												aMatch.find('.t3js-extensionScanner-hit-file-lineContent').empty().text(match.lineContent);
-												aMatch.find('.t3js-extensionScanner-hit-file-line').empty().text(match.line + ': ');
-												if ($.isArray(match.restFiles)) {
-													$(match.restFiles).each(function() {
-														var restFile = this;
-														var aRest = $(restTemplate).clone();
-														aRest.find('.t3js-extensionScanner-hit-rest-panel-head').attr('href', '#collapse' + restFile.uniqueId);
-														aRest.find('.t3js-extensionScanner-hit-rest-panel-head .badge').empty().text(restFile.version);
-														aRest.find('.t3js-extensionScanner-hit-rest-panel-body').attr('id', 'collapse' + restFile.uniqueId);
-														aRest.find('.t3js-extensionScanner-hit-rest-headline').text(restFile.headline);
-														aRest.find('.t3js-extensionScanner-hit-rest-body').text(restFile.content);
-														aRest.addClass('panel-' + restFile.class);
-														aMatch.find('.t3js-extensionScanner-hit-file-rest-container').append(aRest);
-														self.listOfAffectedRestFileHashes.push(restFile.file_hash);
-													});
-												}
-												var panelClass =
-													aMatch.find('.panel-breaking', '.t3js-extensionScanner-hit-file-rest-container').length > 0
-														? 'panel-danger'
-														: 'panel-warning';
-												aMatch.addClass(panelClass);
-												$extensionContainer.find('.t3js-extensionScanner-extension-body').removeClass('hide').append(aMatch);
-												if (panelClass === 'panel-danger') {
-													$extensionContainer.removeClass('panel-warning').addClass(panelClass);
-												}
-												if (panelClass === 'panel-warning' && !$extensionContainer.hasClass('panel-danger')) {
-													$extensionContainer.addClass(panelClass);
-												}
-											});
-										}
-										if (fileData.success) {
-											var currentLinesOfCode = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-loc').text());
-											$extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text(currentLinesOfCode + parseInt(fileData.effectiveCodeLines));
-											if (fileData.isFileIgnored) {
-												var currentIgnoredFiles = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').text());
-												$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text(currentIgnoredFiles + 1);
-											}
-											var currentIgnoredLines = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').text());
-											$extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text(currentIgnoredLines + parseInt(fileData.ignoredLines));
-										}
-										if (doneFiles === numberOfFiles) {
-											if (!hitFound) {
-												$extensionContainer.addClass('panel-success');
-											}
-											$extensionContainer.addClass('t3js-extensionscan-finished');
-											self.setProgressForAll();
-											$extensionContainer.find('.t3js-extensionScanner-scan-single').text('Rescan').attr('disabled', null);
-										}
-									},
-									error: function(data) {
-										doneFiles = doneFiles + 1;
-										self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
-										self.setProgressForScan(extension, doneFiles, numberOfFiles);
-										self.setProgressForAll();
-										Notification.error('Oops, an error occurred', 'Please look at the console output for details');
-										console.error(data);
-									}
-								});
-							});
-						} else {
-							Notification.warning('No files found', 'The extension EXT:' + extension + ' contains no files we can scan');
-						}
-					} else {
-						Notification.error('Oops, an error occurred', 'Please look at the console output for details');
-						console.error(data);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    /**
+     * Handle a single extension scan
+     *
+     * @param {string} extension
+     */
+    scanSingleExtension: function(extension) {
+      var self = this;
+      var $extensionContainer = $(this.getExtensionSelector(extension));
+      var hitTemplate = $('#t3js-extensionScanner-file-hit-template').html();
+      var restTemplate = $('#t3js-extensionScanner-file-hit-rest-template').html();
+      var hitFound = false;
+      $extensionContainer.removeClass('panel-danger panel-warning panel-success t3js-extensionscan-finished');
+      $extensionContainer.data('hasRun', 'true');
+      $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Scanning...').attr('disabled', 'disabled');
+      $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text('0');
+      $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text('0');
+      $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text('0');
+      this.setProgressForAll();
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'extensionScannerFiles',
+            'token': $(self.selectorFilesToken).text(),
+            'extension': extension
+          }
+        },
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.files)) {
+            var numberOfFiles = data.files.length;
+            if (numberOfFiles > 0) {
+              self.setStatusMessageForScan(extension, 0, numberOfFiles);
+              $extensionContainer.find('.t3js-extensionScanner-extension-body').text('');
+              var doneFiles = 0;
+              data.files.forEach(function(file) {
+                $.ajax({
+                  method: 'POST',
+                  data: {
+                    'install': {
+                      'action': 'extensionScannerScanFile',
+                      'token': $(self.selectorScanFileToken).text(),
+                      'extension': extension,
+                      'file': file
+                    }
+                  },
+                  url: Router.getUrl(),
+                  cache: false,
+                  success: function(fileData) {
+                    doneFiles = doneFiles + 1;
+                    self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
+                    self.setProgressForScan(extension, doneFiles, numberOfFiles);
+                    if (fileData.success && $.isArray(fileData.matches)) {
+                      $(fileData.matches).each(function() {
+                        hitFound = true;
+                        var match = this;
+                        var aMatch = $(hitTemplate).clone();
+                        aMatch.find('.t3js-extensionScanner-hit-file-panel-head').attr('href', '#collapse' + match.uniqueId);
+                        aMatch.find('.t3js-extensionScanner-hit-file-panel-body').attr('id', 'collapse' + match.uniqueId);
+                        aMatch.find('.t3js-extensionScanner-hit-filename').text(file);
+                        aMatch.find('.t3js-extensionScanner-hit-message').text(match.message);
+                        if (match.indicator === 'strong') {
+                          aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
+                            .append('<span class="badge" title="Reliable match, false positive unlikely">strong</span>');
+                        } else {
+                          aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
+                            .append('<span class="badge" title="Probable match, but can be a false positive">weak</span>');
+                        }
+                        if (match.silenced === true) {
+                          aMatch.find('.t3js-extensionScanner-hit-file-panel-head .badges')
+                            .append('<span class="badge" title="Match has been annotated by extension author as false positive match">silenced</span>');
+                        }
+                        aMatch.find('.t3js-extensionScanner-hit-file-lineContent').empty().text(match.lineContent);
+                        aMatch.find('.t3js-extensionScanner-hit-file-line').empty().text(match.line + ': ');
+                        if ($.isArray(match.restFiles)) {
+                          $(match.restFiles).each(function() {
+                            var restFile = this;
+                            var aRest = $(restTemplate).clone();
+                            aRest.find('.t3js-extensionScanner-hit-rest-panel-head').attr('href', '#collapse' + restFile.uniqueId);
+                            aRest.find('.t3js-extensionScanner-hit-rest-panel-head .badge').empty().text(restFile.version);
+                            aRest.find('.t3js-extensionScanner-hit-rest-panel-body').attr('id', 'collapse' + restFile.uniqueId);
+                            aRest.find('.t3js-extensionScanner-hit-rest-headline').text(restFile.headline);
+                            aRest.find('.t3js-extensionScanner-hit-rest-body').text(restFile.content);
+                            aRest.addClass('panel-' + restFile.class);
+                            aMatch.find('.t3js-extensionScanner-hit-file-rest-container').append(aRest);
+                            self.listOfAffectedRestFileHashes.push(restFile.file_hash);
+                          });
+                        }
+                        var panelClass =
+                          aMatch.find('.panel-breaking', '.t3js-extensionScanner-hit-file-rest-container').length > 0
+                            ? 'panel-danger'
+                            : 'panel-warning';
+                        aMatch.addClass(panelClass);
+                        $extensionContainer.find('.t3js-extensionScanner-extension-body').removeClass('hide').append(aMatch);
+                        if (panelClass === 'panel-danger') {
+                          $extensionContainer.removeClass('panel-warning').addClass(panelClass);
+                        }
+                        if (panelClass === 'panel-warning' && !$extensionContainer.hasClass('panel-danger')) {
+                          $extensionContainer.addClass(panelClass);
+                        }
+                      });
+                    }
+                    if (fileData.success) {
+                      var currentLinesOfCode = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-loc').text());
+                      $extensionContainer.find('.t3js-extensionScanner-extension-body-loc').empty().text(currentLinesOfCode + parseInt(fileData.effectiveCodeLines));
+                      if (fileData.isFileIgnored) {
+                        var currentIgnoredFiles = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').text());
+                        $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-files').empty().text(currentIgnoredFiles + 1);
+                      }
+                      var currentIgnoredLines = parseInt($extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').text());
+                      $extensionContainer.find('.t3js-extensionScanner-extension-body-ignored-lines').empty().text(currentIgnoredLines + parseInt(fileData.ignoredLines));
+                    }
+                    if (doneFiles === numberOfFiles) {
+                      if (!hitFound) {
+                        $extensionContainer.addClass('panel-success');
+                      }
+                      $extensionContainer.addClass('t3js-extensionscan-finished');
+                      self.setProgressForAll();
+                      $extensionContainer.find('.t3js-extensionScanner-scan-single').text('Rescan').attr('disabled', null);
+                    }
+                  },
+                  error: function(data) {
+                    doneFiles = doneFiles + 1;
+                    self.setStatusMessageForScan(extension, doneFiles, numberOfFiles);
+                    self.setProgressForScan(extension, doneFiles, numberOfFiles);
+                    self.setProgressForAll();
+                    Notification.error('Oops, an error occurred', 'Please look at the console output for details');
+                    console.error(data);
+                  }
+                });
+              });
+            } else {
+              Notification.warning('No files found', 'The extension EXT:' + extension + ' contains no files we can scan');
+            }
+          } else {
+            Notification.error('Oops, an error occurred', 'Please look at the console output for details');
+            console.error(data);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js
index 8554df58846c..372e277d6d22 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FlashMessage.js
@@ -14,36 +14,36 @@
 /**
  * Module: TYPO3/CMS/Install/FlashMessage
  */
-define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
+  'use strict';
 
-	/**
-	 * @type {{template: (*)}}
-	 */
-	var FlashMessage = {
-		template: $('<div class="t3js-message typo3-message alert"><h4></h4><p class="messageText"></p></div>')
-	};
+  /**
+   * @type {{template: (*)}}
+   */
+  var FlashMessage = {
+    template: $('<div class="t3js-message typo3-message alert"><h4></h4><p class="messageText"></p></div>')
+  };
 
-	/**
-	 * render a FlashMessage
-	 * @param {Number} severity
-	 * @param {String} title
-	 * @param {String} message
-	 * @returns {jQuery}
-	 */
-	FlashMessage.render = function (severity, title, message) {
-		var flashMessage = this.template.clone();
-		flashMessage.addClass('alert-' + Severity.getCssClass(severity));
-		if (title) {
-			flashMessage.find('h4').text(title);
-		}
-		if (message) {
-			flashMessage.find('.messageText').text(message);
-		} else {
-			flashMessage.find('.messageText').remove();
-		}
-		return flashMessage;
-	};
+  /**
+   * render a FlashMessage
+   * @param {Number} severity
+   * @param {String} title
+   * @param {String} message
+   * @returns {jQuery}
+   */
+  FlashMessage.render = function(severity, title, message) {
+    var flashMessage = this.template.clone();
+    flashMessage.addClass('alert-' + Severity.getCssClass(severity));
+    if (title) {
+      flashMessage.find('h4').text(title);
+    }
+    if (message) {
+      flashMessage.find('.messageText').text(message);
+    } else {
+      flashMessage.find('.messageText').remove();
+    }
+    return flashMessage;
+  };
 
-	return FlashMessage;
+  return FlashMessage;
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js
index 70790e828350..2cd3a0a9cab1 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/FolderStructure.js
@@ -15,129 +15,129 @@
  * Module: TYPO3/CMS/Install/FolderStructure
  */
 define(['jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap'
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderBadge: '.t3js-folderStructure-badge',
-		selectorFixTrigger: '.t3js-folderStructure-errors-fix',
-		selectorOutputContainer: '.t3js-folderStructure-output',
-		selectorErrorContainer: '.t3js-folderStructure-errors',
-		selectorErrorList: '.t3js-folderStructure-errors-list',
-		selectorErrorFixTrigger: '.t3js-folderStructure-errors-fix',
-		selectorOkContainer: '.t3js-folderStructure-ok',
-		selectorOkList: '.t3js-folderStructure-ok-list',
-		selectorPermissionContainer: '.t3js-folderStructure-permissions',
+  return {
+    selectorGridderBadge: '.t3js-folderStructure-badge',
+    selectorFixTrigger: '.t3js-folderStructure-errors-fix',
+    selectorOutputContainer: '.t3js-folderStructure-output',
+    selectorErrorContainer: '.t3js-folderStructure-errors',
+    selectorErrorList: '.t3js-folderStructure-errors-list',
+    selectorErrorFixTrigger: '.t3js-folderStructure-errors-fix',
+    selectorOkContainer: '.t3js-folderStructure-ok',
+    selectorOkList: '.t3js-folderStructure-ok-list',
+    selectorPermissionContainer: '.t3js-folderStructure-permissions',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Get status on initialize to have the badge and content ready
-			self.getStatus();
+      // Get status on initialize to have the badge and content ready
+      self.getStatus();
 
-			$(document).on('click', this.selectorErrorFixTrigger, function(e) {
-				e.preventDefault();
-				self.fix();
-			});
-		},
+      $(document).on('click', this.selectorErrorFixTrigger, function(e) {
+        e.preventDefault();
+        self.fix();
+      });
+    },
 
-		getStatus: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var $errorContainer = $(this.selectorErrorContainer);
-			var $errorBadge = $(this.selectorGridderBadge);
-			$errorBadge.text('').hide();
-			var $errorList = $(this.selectorErrorList);
-			var $okContainer = $(this.selectorOkContainer);
-			var $okList = $(this.selectorOkList);
-			var $permissionContainer = $(this.selectorPermissionContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$.ajax({
-				url: Router.getUrl('folderStructureGetStatus'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true && Array.isArray(data.errorStatus)) {
-						var errorCount = 0;
-						if (data.errorStatus.length > 0) {
-							$errorContainer.show();
-							$errorList.empty();
-							data.errorStatus.forEach((function(element) {
-								errorCount += 1;
-								$errorBadge.text(errorCount).show();
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$errorList.append(message);
-							}));
-						} else {
-							$errorContainer.hide();
-						}
-					}
-					if (data.success === true && Array.isArray(data.okStatus)) {
-						if (data.okStatus.length > 0) {
-							$okContainer.show();
-							$okList.empty();
-							data.okStatus.forEach((function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$okList.append(message);
-							}));
-						} else {
-							$okList.hide();
-						}
-					}
-					var element = data.folderStructureFilePermissionStatus;
-					message = InfoBox.render(element.severity, element.title, element.message);
-					$permissionContainer.empty().append(message);
-					element = data.folderStructureDirectoryPermissionStatus;
-					message = InfoBox.render(element.severity, element.title, element.message);
-					$permissionContainer.append(message);
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getStatus: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $errorContainer = $(this.selectorErrorContainer);
+      var $errorBadge = $(this.selectorGridderBadge);
+      $errorBadge.text('').hide();
+      var $errorList = $(this.selectorErrorList);
+      var $okContainer = $(this.selectorOkContainer);
+      var $okList = $(this.selectorOkList);
+      var $permissionContainer = $(this.selectorPermissionContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $.ajax({
+        url: Router.getUrl('folderStructureGetStatus'),
+        cache: false,
+        success: function(data) {
+          self.removeLoadingMessage($outputContainer);
+          if (data.success === true && Array.isArray(data.errorStatus)) {
+            var errorCount = 0;
+            if (data.errorStatus.length > 0) {
+              $errorContainer.show();
+              $errorList.empty();
+              data.errorStatus.forEach((function(element) {
+                errorCount += 1;
+                $errorBadge.text(errorCount).show();
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $errorList.append(message);
+              }));
+            } else {
+              $errorContainer.hide();
+            }
+          }
+          if (data.success === true && Array.isArray(data.okStatus)) {
+            if (data.okStatus.length > 0) {
+              $okContainer.show();
+              $okList.empty();
+              data.okStatus.forEach((function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $okList.append(message);
+              }));
+            } else {
+              $okList.hide();
+            }
+          }
+          var element = data.folderStructureFilePermissionStatus;
+          message = InfoBox.render(element.severity, element.title, element.message);
+          $permissionContainer.empty().append(message);
+          element = data.folderStructureDirectoryPermissionStatus;
+          message = InfoBox.render(element.severity, element.title, element.message);
+          $permissionContainer.append(message);
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		fix: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('folderStructureFix'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true && Array.isArray(data.fixedStatus)) {
-						if (data.fixedStatus.length > 0) {
-							data.fixedStatus.forEach(function(element) {
-								message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						} else {
-							message = InfoBox.render(Severity.warning, 'Nothing fixed', '');
-							$outputContainer.append(message);
-						}
-						self.getStatus();
-					} else {
-						message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    fix: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('folderStructureFix'),
+        cache: false,
+        success: function(data) {
+          self.removeLoadingMessage($outputContainer);
+          if (data.success === true && Array.isArray(data.fixedStatus)) {
+            if (data.fixedStatus.length > 0) {
+              data.fixedStatus.forEach(function(element) {
+                message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              });
+            } else {
+              message = InfoBox.render(Severity.warning, 'Nothing fixed', '');
+              $outputContainer.append(message);
+            }
+            self.getStatus();
+          } else {
+            message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		removeLoadingMessage: function($container) {
-			$container.find('.alert-loading').remove();
-		}
-	};
+    removeLoadingMessage: function($container) {
+      $container.find('.alert-loading').remove();
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js
index c4cddcafc10c..418bcccbd0c7 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ImageProcessing.js
@@ -15,87 +15,87 @@
  * Module: TYPO3/CMS/Install/ImageProcessing
  */
 define(['jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap'
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-    'use strict';
+  'use strict';
 
-    return {
-        selectorGridderOpener: 't3js-imageProcessing-open',
-        selectorExecuteTrigger: '.t3js-imageProcessing-execute',
-        selectorTestContainer: '.t3js-imageProcessing-twinContainer',
-        selectorTwinImageTemplate: '.t3js-imageProcessing-twinImage-template',
-        selectorCommandContainer: '.t3js-imageProcessing-command',
-        selectorCommandText: '.t3js-imageProcessing-command-text',
-        selectorTwinImages: '.t3js-imageProcessing-images',
+  return {
+    selectorGridderOpener: 't3js-imageProcessing-open',
+    selectorExecuteTrigger: '.t3js-imageProcessing-execute',
+    selectorTestContainer: '.t3js-imageProcessing-twinContainer',
+    selectorTwinImageTemplate: '.t3js-imageProcessing-twinImage-template',
+    selectorCommandContainer: '.t3js-imageProcessing-command',
+    selectorCommandText: '.t3js-imageProcessing-command-text',
+    selectorTwinImages: '.t3js-imageProcessing-images',
 
-        initialize: function() {
-            var self = this;
+    initialize: function() {
+      var self = this;
 
-            // Load main content on first open
-            $(document).on('cardlayout:card-opened', function(event, $card) {
-                if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
-                    $card.data('isInitialized', true);
-                    self.runTests();
-                }
-            });
+      // Load main content on first open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
+          $card.data('isInitialized', true);
+          self.runTests();
+        }
+      });
 
-            $(document).on('click', this.selectorExecuteTrigger, function(e) {
-                e.preventDefault();
-                self.runTests();
-            });
-        },
+      $(document).on('click', this.selectorExecuteTrigger, function(e) {
+        e.preventDefault();
+        self.runTests();
+      });
+    },
 
-        runTests: function() {
-            var self = this;
-            var $twinImageTemplate = $(this.selectorTwinImageTemplate);
-            $(this.selectorTestContainer).each(function() {
-                var $container = $(this);
-                var testType = $container.data('test');
-                var message = InfoBox.render(Severity.loading, 'Loading...', '');
-                $container.empty().html(message);
-                $.ajax({
-                    url: Router.getUrl(testType),
-                    cache: false,
-                    success: function(data) {
-                        if (data.success === true) {
-                            $container.empty();
-                            if (Array.isArray(data.status)) {
-                                data.status.forEach(function(element) {
-                                    var message = InfoBox.render(element.severity, element.title, element.message);
-                                    $container.append(message);
-                                });
-                            }
-                            var $aTwin = $twinImageTemplate.clone();
-                            $aTwin.removeClass('t3js-imageProcessing-twinImage-template');
-                            if (data.fileExists === true) {
-                                $aTwin.find('img.reference').attr('src', data.referenceFile);
-                                $aTwin.find('img.result').attr('src', data.outputFile);
-                                $aTwin.find(self.selectorTwinImages).show();
-                            }
-                            if (Array.isArray(data.command) && data.command.length > 0) {
-                                $aTwin.find(self.selectorCommandContainer).show();
-                                var commandText = [];
-                                data.command.forEach(function(element) {
-                                    commandText.push('<strong>Command:</strong>\n' + element[1]);
-                                    if (element.length === 3) {
-                                        commandText.push('<strong>Result:</strong>\n' + element[2]);
-                                    }
-                                });
-                                $aTwin.find(self.selectorCommandText).html(commandText.join('\n'));
-                            }
-                            $container.append($aTwin);
-                        }
-                    },
-                    error: function(xhr) {
-                        Router.handleAjaxError(xhr);
-                    }
+    runTests: function() {
+      var self = this;
+      var $twinImageTemplate = $(this.selectorTwinImageTemplate);
+      $(this.selectorTestContainer).each(function() {
+        var $container = $(this);
+        var testType = $container.data('test');
+        var message = InfoBox.render(Severity.loading, 'Loading...', '');
+        $container.empty().html(message);
+        $.ajax({
+          url: Router.getUrl(testType),
+          cache: false,
+          success: function(data) {
+            if (data.success === true) {
+              $container.empty();
+              if (Array.isArray(data.status)) {
+                data.status.forEach(function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $container.append(message);
                 });
-            });
-        }
-    };
+              }
+              var $aTwin = $twinImageTemplate.clone();
+              $aTwin.removeClass('t3js-imageProcessing-twinImage-template');
+              if (data.fileExists === true) {
+                $aTwin.find('img.reference').attr('src', data.referenceFile);
+                $aTwin.find('img.result').attr('src', data.outputFile);
+                $aTwin.find(self.selectorTwinImages).show();
+              }
+              if (Array.isArray(data.command) && data.command.length > 0) {
+                $aTwin.find(self.selectorCommandContainer).show();
+                var commandText = [];
+                data.command.forEach(function(element) {
+                  commandText.push('<strong>Command:</strong>\n' + element[1]);
+                  if (element.length === 3) {
+                    commandText.push('<strong>Result:</strong>\n' + element[2]);
+                  }
+                });
+                $aTwin.find(self.selectorCommandText).html(commandText.join('\n'));
+              }
+              $container.append($aTwin);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js
index 292781333519..10f44df0517e 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/InfoBox.js
@@ -14,36 +14,36 @@
 /**
  * Module: TYPO3/CMS/Install/InfoBox
  */
-define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
+  'use strict';
 
-	/**
-	 * @type {{template: (*)}}
-	 */
-	var InfoBox = {
-		template: $('<div class="t3js-infobox callout callout-sm"><h4 class="callout-title"></h4><div class="callout-body"></div></div>')
-	};
+  /**
+   * @type {{template: (*)}}
+   */
+  var InfoBox = {
+    template: $('<div class="t3js-infobox callout callout-sm"><h4 class="callout-title"></h4><div class="callout-body"></div></div>')
+  };
 
-	/**
-	 * render a InfoBox
-	 * @param {Number} severity
-	 * @param {String} title
-	 * @param {String} message
-	 * @returns {jQuery}
-	 */
-	InfoBox.render = function (severity, title, message) {
-		var infoBox = this.template.clone();
-		infoBox.addClass('callout-' + Severity.getCssClass(severity));
-		if (title) {
-			infoBox.find('h4').text(title);
-		}
-		if (message) {
-			infoBox.find('.callout-body').text(message);
-		} else {
-			infoBox.find('.callout-body').remove();
-		}
-		return infoBox;
-	};
+  /**
+   * render a InfoBox
+   * @param {Number} severity
+   * @param {String} title
+   * @param {String} message
+   * @returns {jQuery}
+   */
+  InfoBox.render = function(severity, title, message) {
+    var infoBox = this.template.clone();
+    infoBox.addClass('callout-' + Severity.getCssClass(severity));
+    if (title) {
+      infoBox.find('h4').text(title);
+    }
+    if (message) {
+      infoBox.find('.callout-body').text(message);
+    } else {
+      infoBox.find('.callout-body').remove();
+    }
+    return infoBox;
+  };
 
-	return InfoBox;
+  return InfoBox;
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js
index f96e18503448..dbf9dd494b97 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/LocalConfiguration.js
@@ -15,201 +15,201 @@
  * Module: TYPO3/CMS/Install/LocalConfiguration
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-localConfiguration-open',
-		selectorToggleAllTrigger: '.t3js-localConfiguration-toggleAll',
-		selectorWriteTrigger: '.t3js-localConfiguration-write',
-		selectorSearchTrigger: '.t3js-localConfiguration-search',
-		selectorWriteToken: '#t3js-localConfiguration-write-token',
-		selectorContentContainer: '.t3js-localConfiguration-content',
-		selectorOutputContainer: '.t3js-localConfiguration-output',
+  return {
+    selectorGridderOpener: 't3js-localConfiguration-open',
+    selectorToggleAllTrigger: '.t3js-localConfiguration-toggleAll',
+    selectorWriteTrigger: '.t3js-localConfiguration-write',
+    selectorSearchTrigger: '.t3js-localConfiguration-search',
+    selectorWriteToken: '#t3js-localConfiguration-write-token',
+    selectorContentContainer: '.t3js-localConfiguration-content',
+    selectorOutputContainer: '.t3js-localConfiguration-output',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Get configuration list on card open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener)) {
-					self.getContent();
-				}
-			});
+      // Get configuration list on card open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener)) {
+          self.getContent();
+        }
+      });
 
-			// Write out new settings
-			$(document).on('click', this.selectorWriteTrigger, function() {
-				self.write();
-			});
+      // Write out new settings
+      $(document).on('click', this.selectorWriteTrigger, function() {
+        self.write();
+      });
 
-			// Expand / collapse "Toggle all" button
-			$(document).on('click', this.selectorToggleAllTrigger, function() {
-				var $panels = $('.t3js-localConfiguration .panel-collapse');
-				var action = ($panels.eq(0).hasClass('in')) ? 'hide' : 'show';
-				$panels.collapse(action);
-			});
+      // Expand / collapse "Toggle all" button
+      $(document).on('click', this.selectorToggleAllTrigger, function() {
+        var $panels = $('.t3js-localConfiguration .panel-collapse');
+        var action = ($panels.eq(0).hasClass('in')) ? 'hide' : 'show';
+        $panels.collapse(action);
+      });
 
-			// Make jquerys "contains" work case-insensitive
-			jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
-				return function (elem) {
-					return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
-				};
-			});
+      // Make jquerys "contains" work case-insensitive
+      jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
+        return function(elem) {
+          return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
+        };
+      });
 
-			// Focus search field on certain user interactions
-			$(document).on('keydown', function(e) {
-				var $searchInput = $(self.selectorSearchTrigger);
-				if (e.ctrlKey || e.metaKey) {
-					// Focus search field on ctrl-f
-					switch (String.fromCharCode(e.which).toLowerCase()) {
-						case 'f':
-							e.preventDefault();
-							$searchInput.focus();
-							break;
-					}
-				} else if (e.keyCode === 27) {
-					// Clear search on ESC key
-					e.preventDefault();
-					$searchInput.val('').focus();
-				}
-			});
+      // Focus search field on certain user interactions
+      $(document).on('keydown', function(e) {
+        var $searchInput = $(self.selectorSearchTrigger);
+        if (e.ctrlKey || e.metaKey) {
+          // Focus search field on ctrl-f
+          switch (String.fromCharCode(e.which).toLowerCase()) {
+            case 'f':
+              e.preventDefault();
+              $searchInput.focus();
+              break;
+          }
+        } else if (e.keyCode === 27) {
+          // Clear search on ESC key
+          e.preventDefault();
+          $searchInput.val('').focus();
+        }
+      });
 
-			// Perform expand collapse on search matches
-			$(document).on('keyup', this.selectorSearchTrigger, function() {
-				var typedQuery = $(this).val();
-				var $searchInput = $(self.selectorSearchTrigger);
-				$('div.item').each(function() {
-					var $item = $(this);
-					if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
-						$item.removeClass('hidden').addClass('searchhit');
-					} else {
-						$item.removeClass('searchhit').addClass('hidden');
-					}
-				});
-				$('.searchhit').parent().collapse('show');
-				self.handleButtonScrolling();
-				// Make search field clearable
-				require(['jquery.clearable'], function() {
-					var searchResultShown = ('' !== $searchInput.first().val());
-					$searchInput.clearable().focus();
-				});
-			});
+      // Perform expand collapse on search matches
+      $(document).on('keyup', this.selectorSearchTrigger, function() {
+        var typedQuery = $(this).val();
+        var $searchInput = $(self.selectorSearchTrigger);
+        $('div.item').each(function() {
+          var $item = $(this);
+          if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
+            $item.removeClass('hidden').addClass('searchhit');
+          } else {
+            $item.removeClass('searchhit').addClass('hidden');
+          }
+        });
+        $('.searchhit').parent().collapse('show');
+        self.handleButtonScrolling();
+        // Make search field clearable
+        require(['jquery.clearable'], function() {
+          var searchResultShown = ('' !== $searchInput.first().val());
+          $searchInput.clearable().focus();
+        });
+      });
 
-			// Trigger fixed button calculation on collapse / expand
-			$(document).on('shown.bs.collapse', '.gridder-show .collapse', function() {
-				self.handleButtonScrolling();
-			});
-			$(document).on('hidden.bs.collapse', '.gridder-show .collapse', function() {
-				self.handleButtonScrolling();
-			});
-		},
+      // Trigger fixed button calculation on collapse / expand
+      $(document).on('shown.bs.collapse', '.gridder-show .collapse', function() {
+        self.handleButtonScrolling();
+      });
+      $(document).on('hidden.bs.collapse', '.gridder-show .collapse', function() {
+        self.handleButtonScrolling();
+      });
+    },
 
-		getContent: function() {
-			var outputContainer = $(this.selectorContentContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('localConfigurationGetContent'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-						outputContainer.empty().append(data.html);
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getContent: function() {
+      var outputContainer = $(this.selectorContentContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('localConfigurationGetContent'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            outputContainer.empty().append(data.html);
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		write: function() {
-			var configurationValues = {};
-			$('.gridder-show .t3js-localConfiguration-pathValue').each(function(i, element) {
-				var $element = $(element);
-				if ($element.attr('type') === 'checkbox') {
-					if (element.checked) {
-						configurationValues[$element.data('path')] = '1';
-					} else {
-						configurationValues[$element.data('path')] = '0';
-					}
-				} else {
-					configurationValues[$element.data('path')] = $element.val();
-				}
-			});
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'localConfigurationWrite',
-						'token': $(this.selectorWriteToken).text(),
-						'configurationValues': configurationValues
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.append(message);
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    write: function() {
+      var configurationValues = {};
+      $('.gridder-show .t3js-localConfiguration-pathValue').each(function(i, element) {
+        var $element = $(element);
+        if ($element.attr('type') === 'checkbox') {
+          if (element.checked) {
+            configurationValues[$element.data('path')] = '1';
+          } else {
+            configurationValues[$element.data('path')] = '0';
+          }
+        } else {
+          configurationValues[$element.data('path')] = $element.val();
+        }
+      });
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'localConfigurationWrite',
+            'token': $(this.selectorWriteToken).text(),
+            'configurationValues': configurationValues
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.append(message);
+            });
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		/**
-		 * Fix or unfix the "Write configuration" / "Toggle all" buttons at browser window
-		 * bottom if a scrollbar is shown
-		 */
-		handleButtonScrolling: function() {
-			var $fixedFooterHandler = $('#fixed-footer-handler');
-			if ($fixedFooterHandler.length > 0) {
-				var $fixedFooter = $('#fixed-footer');
-				if (!this.isScrolledIntoView($fixedFooterHandler)) {
-					$fixedFooter.addClass('fixed');
-					$fixedFooter.width($('.t3js-localConfiguration .panel-group').width());
-				} else {
-					$fixedFooter.removeClass('fixed');
-				}
-			}
-		},
+    /**
+     * Fix or unfix the "Write configuration" / "Toggle all" buttons at browser window
+     * bottom if a scrollbar is shown
+     */
+    handleButtonScrolling: function() {
+      var $fixedFooterHandler = $('#fixed-footer-handler');
+      if ($fixedFooterHandler.length > 0) {
+        var $fixedFooter = $('#fixed-footer');
+        if (!this.isScrolledIntoView($fixedFooterHandler)) {
+          $fixedFooter.addClass('fixed');
+          $fixedFooter.width($('.t3js-localConfiguration .panel-group').width());
+        } else {
+          $fixedFooter.removeClass('fixed');
+        }
+      }
+    },
 
-		/**
-		 * Helper of handleButtonScrolling()
-		 * See if an element is within current viewport.
-		 *
-		 * @param element
-		 * @returns {boolean}
-		 */
-		isScrolledIntoView: function(element) {
-			var $window = $(window);
-			var docViewTop = $window.scrollTop();
-			var docViewBottom = docViewTop + $window.height();
-			var $elem = $(element);
-			var elemTop = $elem.offset().top;
-			var elemBottom = elemTop + $elem.height();
-			return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
-		}
-	};
+    /**
+     * Helper of handleButtonScrolling()
+     * See if an element is within current viewport.
+     *
+     * @param element
+     * @returns {boolean}
+     */
+    isScrolledIntoView: function(element) {
+      var $window = $(window);
+      var docViewTop = $window.scrollTop();
+      var docViewBottom = docViewTop + $window.height();
+      var $elem = $(element);
+      var elemTop = $elem.offset().top;
+      var elemBottom = elemTop + $elem.height();
+      return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js
index dae54e295aae..3530e07687b4 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/MailTest.js
@@ -15,63 +15,63 @@
  * Module: TYPO3/CMS/Install/CreateAdmin
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorSendToken: '#t3js-mailTest-token',
-		selectorForm: '#t3js-mailTest-form',
-		selectorEmail: '.t3js-mailTest-email',
-		selectorOutputContainer: '.t3js-mailTest-output',
+  return {
+    selectorSendToken: '#t3js-mailTest-token',
+    selectorForm: '#t3js-mailTest-form',
+    selectorEmail: '.t3js-mailTest-email',
+    selectorOutputContainer: '.t3js-mailTest-output',
 
-		initialize: function() {
-			var self = this;
-			$(this.selectorForm).submit(function(e) {
-				e.preventDefault();
-				self.send();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(this.selectorForm).submit(function(e) {
+        e.preventDefault();
+        self.send();
+      });
+    },
 
-		send: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'mailTest',
-						'token': $(this.selectorSendToken).text(),
-						'email': $('.t3js-mailTest-email').val()
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.html(message);
-						});
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					// 500 can happen here if the mail configuration is broken
-					var message = InfoBox.render(Severity.error, 'Please check your mail settings', 'Sending test mail failed');
-					$outputContainer.empty().html(message);
-				}
-			});
-		}
-	};
+    send: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'mailTest',
+            'token': $(this.selectorSendToken).text(),
+            'email': $('.t3js-mailTest-email').val()
+          }
+        },
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.html(message);
+            });
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          // 500 can happen here if the mail configuration is broken
+          var message = InfoBox.render(Severity.error, 'Please check your mail settings', 'Sending test mail failed');
+          $outputContainer.empty().html(message);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js
index f9aff9a5d7fe..ffd696cc2ad2 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/PasswordStrength.js
@@ -15,31 +15,31 @@
  * Module: TYPO3/CMS/Install/Cache
  */
 define([
-	'jquery'
+  'jquery'
 ], function($) {
-	'use strict';
+  'use strict';
 
-	return {
-		initialize: function(field) {
-			// Simple password strength indicator
-			$(document).on('keyup', field, function() {
-				var value = $(this).val();
-				var strongRegex = new RegExp('^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g');
-				var mediumRegex = new RegExp('^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g');
-				var enoughRegex = new RegExp('(?=.{8,}).*', 'g');
+  return {
+    initialize: function(field) {
+      // Simple password strength indicator
+      $(document).on('keyup', field, function() {
+        var value = $(this).val();
+        var strongRegex = new RegExp('^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$', 'g');
+        var mediumRegex = new RegExp('^(?=.{8,})(((?=.*[A-Z])(?=.*[a-z]))|((?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[0-9]))).*$', 'g');
+        var enoughRegex = new RegExp('(?=.{8,}).*', 'g');
 
-				if (value.length === 0) {
-					$(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
-				} else if (!enoughRegex.test(value)) {
-					$(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
-				} else if (strongRegex.test(value)) {
-					$(this).attr('style', 'background-color:#CDEACA; border:1px solid #58B548');
-				} else if (mediumRegex.test(value)) {
-					$(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
-				} else {
-					$(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
-				}
-			});
-		}
-	};
+        if (value.length === 0) {
+          $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
+        } else if (!enoughRegex.test(value)) {
+          $(this).attr('style', 'background-color:#FBB19B; border:1px solid #DC4C42');
+        } else if (strongRegex.test(value)) {
+          $(this).attr('style', 'background-color:#CDEACA; border:1px solid #58B548');
+        } else if (mediumRegex.test(value)) {
+          $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
+        } else {
+          $(this).attr('style', 'background-color:#FBFFB3; border:1px solid #C4B70D');
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js
index 62dbf5922964..7b2536bdf6f4 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Presets.js
@@ -15,119 +15,119 @@
  * Module: TYPO3/CMS/Install/Presets
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGetContentToken: '#t3js-presets-getContent-token',
-		selectorActivateToken: '#t3js-presets-activate-token',
-		selectorGridderOpener: 't3js-presets-open',
-		selectorActivateTrigger: '.t3js-presets-activate',
-		selectorContentContainer: '.t3js-presets-content',
-		selectorOutputContainer: '.t3js-presets-output',
-		selectorImageExecutable: '.t3js-presets-image-executable',
-		selectorImageExecutableTrigger: '.t3js-presets-image-executable-trigger',
+  return {
+    selectorGetContentToken: '#t3js-presets-getContent-token',
+    selectorActivateToken: '#t3js-presets-activate-token',
+    selectorGridderOpener: 't3js-presets-open',
+    selectorActivateTrigger: '.t3js-presets-activate',
+    selectorContentContainer: '.t3js-presets-content',
+    selectorOutputContainer: '.t3js-presets-output',
+    selectorImageExecutable: '.t3js-presets-image-executable',
+    selectorImageExecutableTrigger: '.t3js-presets-image-executable-trigger',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Get current system maintainer list on card open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener)) {
-					self.getContent();
-				}
-			});
+      // Get current system maintainer list on card open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener)) {
+          self.getContent();
+        }
+      });
 
-			// Load content on click image executable path button
-			$(document).on('click', this.selectorImageExecutableTrigger, function(e) {
-				e.preventDefault();
-				self.getContent();
-			});
+      // Load content on click image executable path button
+      $(document).on('click', this.selectorImageExecutableTrigger, function(e) {
+        e.preventDefault();
+        self.getContent();
+      });
 
-			// Write out selected preset
-			$(document).on('click', this.selectorActivateTrigger, function(e) {
-				e.preventDefault();
-				self.activate();
-			});
+      // Write out selected preset
+      $(document).on('click', this.selectorActivateTrigger, function(e) {
+        e.preventDefault();
+        self.activate();
+      });
 
-			// Automatically select the custom preset if a value in one of its input fields is changed
-			$('.t3js-custom-preset').on('input', function() {
-				$('#' + $(this).data('radio')).prop('checked', true);
-			});
-		},
+      // Automatically select the custom preset if a value in one of its input fields is changed
+      $('.t3js-custom-preset').on('input', function() {
+        $('#' + $(this).data('radio')).prop('checked', true);
+      });
+    },
 
-		getContent: function() {
-			var self = this;
-			var outputContainer = $(this.selectorContentContainer);
-			var executablePath = $(self.selectorImageExecutable).val();
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'token': $(this.selectorGetContentToken).text(),
-						'action': 'presetsGetContent',
-						'values': {
-							'Image': {
-								'additionalSearchPath': executablePath
-							}
-						}
-					}
-				},
-				cache: false,
-				success: function(data) {
-					if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-						outputContainer.empty().append(data.html);
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getContent: function() {
+      var self = this;
+      var outputContainer = $(this.selectorContentContainer);
+      var executablePath = $(self.selectorImageExecutable).val();
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: {
+          'install': {
+            'token': $(this.selectorGetContentToken).text(),
+            'action': 'presetsGetContent',
+            'values': {
+              'Image': {
+                'additionalSearchPath': executablePath
+              }
+            }
+          }
+        },
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            outputContainer.empty().append(data.html);
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		activate: function() {
-			var postData = {};
-			$($(this.selectorContentContainer + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			postData['install[action]'] = 'presetsActivate';
-			postData['install[token]'] = $(this.selectorActivateToken).text();
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: postData,
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.append(message);
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    activate: function() {
+      var postData = {};
+      $($(this.selectorContentContainer + ' form').serializeArray()).each(function() {
+        postData[this.name] = this.value;
+      });
+      postData['install[action]'] = 'presetsActivate';
+      postData['install[token]'] = $(this.selectorActivateToken).text();
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl(),
+        method: 'POST',
+        data: postData,
+        cache: false,
+        success: function(data) {
+          $outputContainer.empty();
+          if (data.success === true && Array.isArray(data.status)) {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.append(message);
+            });
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js
index b44effa2ffe5..8b4f4e289c07 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ProgressBar.js
@@ -14,35 +14,35 @@
 /**
  * Module: TYPO3/CMS/Install/ProgressBar
  */
-define(['jquery', 'TYPO3/CMS/Install/Severity'], function ($, Severity) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Install/Severity'], function($, Severity) {
+  'use strict';
 
-	/**
-	 * @type {{template: (*)}}
-	 */
-	var ProgressBar = {
-		template: $('<div class="progress"><div class="t3js-progressbar progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <span class="sr-only"></span></div></div>')
-	};
+  /**
+   * @type {{template: (*)}}
+   */
+  var ProgressBar = {
+    template: $('<div class="progress"><div class="t3js-progressbar progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <span class="sr-only"></span></div></div>')
+  };
 
-	/**
-	 * render a ProgressBar
-	 * @param {Number} severity
-	 * @param {String} title
-	 * @param {Number} progress
-	 * @returns {jQuery}
-	 */
-	ProgressBar.render = function (severity, title, progress) {
-		var progressBar = this.template.clone();
-		progressBar.addClass('progress-bar-' + Severity.getCssClass(severity));
-		if (progress) {
-			progressBar.css('width', progress + '%');
-			progressBar.attr('aria-valuenow',progresss);
-		}
-		if (title) {
-			progressBar.find('.sr-only').text(title);
-		}
-		return progressBar;
-	};
+  /**
+   * render a ProgressBar
+   * @param {Number} severity
+   * @param {String} title
+   * @param {Number} progress
+   * @returns {jQuery}
+   */
+  ProgressBar.render = function(severity, title, progress) {
+    var progressBar = this.template.clone();
+    progressBar.addClass('progress-bar-' + Severity.getCssClass(severity));
+    if (progress) {
+      progressBar.css('width', progress + '%');
+      progressBar.attr('aria-valuenow', progresss);
+    }
+    if (title) {
+      progressBar.find('.sr-only').text(title);
+    }
+    return progressBar;
+  };
 
-	return ProgressBar;
+  return ProgressBar;
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js
index 591e692846f7..a0067abc7e55 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/ResetBackendUserUc.js
@@ -15,53 +15,53 @@
  * Module: TYPO3/CMS/Install/DumpAutoload
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorResetTrigger: '.t3js-resetBackendUserUc-reset',
-		selectorOutputContainer: '.t3js-resetBackendUserUc-output',
+  return {
+    selectorResetTrigger: '.t3js-resetBackendUserUc-reset',
+    selectorOutputContainer: '.t3js-resetBackendUserUc-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorResetTrigger, function(e) {
-				e.preventDefault();
-				self.reset();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorResetTrigger, function(e) {
+        e.preventDefault();
+        self.reset();
+      });
+    },
 
-		reset: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('resetBackendUserUc'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							$outputContainer.empty();
-							data.status.forEach(function (element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    reset: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('resetBackendUserUc'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            if (data.status.length > 0) {
+              $outputContainer.empty();
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              });
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js
index 1a43de4ad130..42afb21cac17 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Router.js
@@ -15,302 +15,302 @@
  * Module: TYPO3/CMS/Install/Router
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'TYPO3/CMS/Install/CardLayout',
-	'TYPO3/CMS/Install/ProgressBar'
+  'jquery',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'TYPO3/CMS/Install/CardLayout',
+  'TYPO3/CMS/Install/ProgressBar'
 ], function($, InfoBox, Severity, CardLayout, ProgressBar) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorBody: '.t3js-body',
-		selectorMainContent: '.t3js-module-body',
+  return {
+    selectorBody: '.t3js-body',
+    selectorMainContent: '.t3js-module-body',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			$(document).on('click', '.t3js-login-lockInstallTool', function(e) {
-				e.preventDefault();
-				self.logout();
-			});
-			$(document).on('click', '.t3js-login-login', function(e) {
-				e.preventDefault();
-				self.login();
-			});
-			$(document).on('keydown', '#t3-install-form-password', function(e) {
-				if (e.keyCode === 13) {
-					e.preventDefault();
-					$('.t3js-login-login').click();
-				}
-			});
+      $(document).on('click', '.t3js-login-lockInstallTool', function(e) {
+        e.preventDefault();
+        self.logout();
+      });
+      $(document).on('click', '.t3js-login-login', function(e) {
+        e.preventDefault();
+        self.login();
+      });
+      $(document).on('keydown', '#t3-install-form-password', function(e) {
+        if (e.keyCode === 13) {
+          e.preventDefault();
+          $('.t3js-login-login').click();
+        }
+      });
 
-			this.executeSilentConfigurationUpdate();
-		},
+      this.executeSilentConfigurationUpdate();
+    },
 
-		getUrl: function(action, controller) {
-			var url = location.href;
-			var context = $(this.selectorBody).data('context');
-			url = url.replace(location.search, '');
-			if (controller === undefined) {
-				controller = $(this.selectorBody).data('controller');
-			}
-			url = url + '?install[controller]=' + controller;
-			if (context !== undefined && context !== '') {
-				url = url + '&install[context]=' + context;
-			}
-			if (action !== undefined) {
-				url = url + '&install[action]=' + action;
-			}
-			return url;
-		},
+    getUrl: function(action, controller) {
+      var url = location.href;
+      var context = $(this.selectorBody).data('context');
+      url = url.replace(location.search, '');
+      if (controller === undefined) {
+        controller = $(this.selectorBody).data('controller');
+      }
+      url = url + '?install[controller]=' + controller;
+      if (context !== undefined && context !== '') {
+        url = url + '&install[context]=' + context;
+      }
+      if (action !== undefined) {
+        url = url + '&install[action]=' + action;
+      }
+      return url;
+    },
 
-		executeSilentConfigurationUpdate: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeSilentConfigurationUpdate', 'layout'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.executeSilentLegacyExtConfExtensionConfigurationUpdate();
-					} else {
-						self.executeSilentConfigurationUpdate();
-					}
-				},
-				error: function(xhr) {
-					self.handleAjaxError(xhr);
-				}
-			});
-		},
+    executeSilentConfigurationUpdate: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeSilentConfigurationUpdate', 'layout'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.executeSilentLegacyExtConfExtensionConfigurationUpdate();
+          } else {
+            self.executeSilentConfigurationUpdate();
+          }
+        },
+        error: function(xhr) {
+          self.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		/**
-		 * Legacy layer to upmerge LocalConfiguration EXT/extConf serialized array keys
-		 * to EXTENSIONS array in LocalConfiguration for initial update from v8 to v9.
-		 *
-		 * @deprecated since TYPO3 v9, will be removed with v10 - re-route executeSilentConfigurationUpdate()
-		 * to executeSilentExtensionConfigurationUpdate() on removal of this function.
-		 */
-		executeSilentLegacyExtConfExtensionConfigurationUpdate: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeSilentLegacyExtConfExtensionConfigurationUpdate', 'layout'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.executeSilentExtensionConfigurationSynchronization();
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					self.handleAjaxError(xhr);
-				}
-			});
-		},
+    /**
+     * Legacy layer to upmerge LocalConfiguration EXT/extConf serialized array keys
+     * to EXTENSIONS array in LocalConfiguration for initial update from v8 to v9.
+     *
+     * @deprecated since TYPO3 v9, will be removed with v10 - re-route executeSilentConfigurationUpdate()
+     * to executeSilentExtensionConfigurationUpdate() on removal of this function.
+     */
+    executeSilentLegacyExtConfExtensionConfigurationUpdate: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeSilentLegacyExtConfExtensionConfigurationUpdate', 'layout'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.executeSilentExtensionConfigurationSynchronization();
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          self.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		/**
-		 * Extensions which come with new default settings in ext_conf_template.txt extension
-		 * configuration files get their new defaults written to LocalConfiguration.
-		 */
-		executeSilentExtensionConfigurationSynchronization: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('executeSilentExtensionConfigurationSynchronization', 'layout'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.loadMainLayout();
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					self.handleAjaxError(xhr);
-				}
-			});
-		},
+    /**
+     * Extensions which come with new default settings in ext_conf_template.txt extension
+     * configuration files get their new defaults written to LocalConfiguration.
+     */
+    executeSilentExtensionConfigurationSynchronization: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('executeSilentExtensionConfigurationSynchronization', 'layout'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.loadMainLayout();
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          self.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		loadMainLayout: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorBody);
-			$.ajax({
-				url: this.getUrl('mainLayout', 'layout'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-						$outputContainer.empty().append(data.html);
-						// Mark main module as active in standalone
-						if ($(self.selectorBody).data('context') !== 'backend') {
-							var controller = $outputContainer.data('controller');
-							$outputContainer.find('.t3js-mainmodule[data-controller="' + controller + '"]').addClass('active');
-						}
-						self.loadCards();
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					self.handleAjaxError(xhr);
-				}
-			});
-		},
+    loadMainLayout: function() {
+      var self = this;
+      var $outputContainer = $(this.selectorBody);
+      $.ajax({
+        url: this.getUrl('mainLayout', 'layout'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            $outputContainer.empty().append(data.html);
+            // Mark main module as active in standalone
+            if ($(self.selectorBody).data('context') !== 'backend') {
+              var controller = $outputContainer.data('controller');
+              $outputContainer.find('.t3js-mainmodule[data-controller="' + controller + '"]').addClass('active');
+            }
+            self.loadCards();
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          self.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		handleAjaxError: function(xhr) {
-			var message = '';
-			if (xhr.status === 401) {
-				// Install tool session expired - depending on context render error message or login
-				var context = $(this.selectorBody).data('context');
-				if (context === 'backend') {
-					message = InfoBox.render(
-						Severity.error,
-						'The install tool session expired. Please reload the backend and try again.'
-					);
-					$(this.selectorBody).empty().append(message);
-				} else {
-					this.checkEnableInstallToolFile();
-				}
-			} else {
-				// @todo Recovery tests should be started here
-				var url = this.getUrl(undefined, 'upgrade');
-				message = '<div class="t3js-infobox callout callout-sm callout-danger"><div class="callout-body">'
-						+ 'Something went wrong. Please use <b><a href="' + url + '">Check for broken'
-						+ ' extensions</a></b> to see if a loaded extension breaks this part of the install tool'
-						+ ' and unload it.</div></div>';
-				$(this.selectorBody).empty().html(message);
-			}
-		},
+    handleAjaxError: function(xhr) {
+      var message = '';
+      if (xhr.status === 401) {
+        // Install tool session expired - depending on context render error message or login
+        var context = $(this.selectorBody).data('context');
+        if (context === 'backend') {
+          message = InfoBox.render(
+            Severity.error,
+            'The install tool session expired. Please reload the backend and try again.'
+          );
+          $(this.selectorBody).empty().append(message);
+        } else {
+          this.checkEnableInstallToolFile();
+        }
+      } else {
+        // @todo Recovery tests should be started here
+        var url = this.getUrl(undefined, 'upgrade');
+        message = '<div class="t3js-infobox callout callout-sm callout-danger"><div class="callout-body">'
+          + 'Something went wrong. Please use <b><a href="' + url + '">Check for broken'
+          + ' extensions</a></b> to see if a loaded extension breaks this part of the install tool'
+          + ' and unload it.</div></div>';
+        $(this.selectorBody).empty().html(message);
+      }
+    },
 
-		checkEnableInstallToolFile: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('checkEnableInstallToolFile'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.checkLogin();
-					} else {
-						self.showEnableInstallTool();
-					}
-				}
-			});
-		},
+    checkEnableInstallToolFile: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('checkEnableInstallToolFile'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.checkLogin();
+          } else {
+            self.showEnableInstallTool();
+          }
+        }
+      });
+    },
 
-		showEnableInstallTool: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('showEnableInstallToolFile'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$(self.selectorBody).empty().append(data.html);
-					}
-				}
-			});
-		},
+    showEnableInstallTool: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('showEnableInstallToolFile'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $(self.selectorBody).empty().append(data.html);
+          }
+        }
+      });
+    },
 
-		checkLogin: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('checkLogin'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.loadMainLayout();
-					} else {
-						self.showLogin();
-					}
-				}
-			});
-		},
+    checkLogin: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('checkLogin'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.loadMainLayout();
+          } else {
+            self.showLogin();
+          }
+        }
+      });
+    },
 
-		showLogin: function() {
-			var self = this;
-			$.ajax({
-				url: this.getUrl('showLogin'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						$(self.selectorBody).empty().append(data.html);
-					}
-				}
-			});
-		},
+    showLogin: function() {
+      var self = this;
+      $.ajax({
+        url: this.getUrl('showLogin'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $(self.selectorBody).empty().append(data.html);
+          }
+        }
+      });
+    },
 
-		login: function() {
-			var self = this;
-			var $outputContainer = $('.t3js-login-output');
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: self.getUrl(),
-				cache: false,
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'login',
-						'token': $('#t3js-login-token').text(),
-						'password': $('.t3-install-form-input-text').val()
-					}
-				},
-				success: function(data) {
-					if (data.success === true) {
-						self.loadMainLayout();
-					} else {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.empty().html(message);
-						});
-					}
-				}
-			});
-		},
+    login: function() {
+      var self = this;
+      var $outputContainer = $('.t3js-login-output');
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: self.getUrl(),
+        cache: false,
+        method: 'POST',
+        data: {
+          'install': {
+            'action': 'login',
+            'token': $('#t3js-login-token').text(),
+            'password': $('.t3-install-form-input-text').val()
+          }
+        },
+        success: function(data) {
+          if (data.success === true) {
+            self.loadMainLayout();
+          } else {
+            data.status.forEach(function(element) {
+              var message = InfoBox.render(element.severity, element.title, element.message);
+              $outputContainer.empty().html(message);
+            });
+          }
+        }
+      });
+    },
 
-		logout: function() {
-			var self = this;
-			$.ajax({
-				url: self.getUrl('logout'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true) {
-						self.showEnableInstallTool();
-					}
-				}
-			});
-		},
+    logout: function() {
+      var self = this;
+      $.ajax({
+        url: self.getUrl('logout'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            self.showEnableInstallTool();
+          }
+        }
+      });
+    },
 
-		loadCards: function() {
-			var self = this;
-			var outputContainer = $(this.selectorMainContent);
-			$.ajax({
-				url: this.getUrl('cards'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-						outputContainer.empty().append(data.html);
-						CardLayout.initialize();
-						// Each card head can have a t3js-require class and a data-require attribute
-						// with the name of a requireJS module. Those are loaded here and initialize()
-						// is executed if exists.
-						$('.t3js-require').each(function() {
-							var module = $(this).data('require');
-							require([module], function(aModule) {
-								if (typeof aModule.initialize !== 'undefined') {
-									aModule.initialize();
-								}
-							});
-						});
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					self.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    loadCards: function() {
+      var self = this;
+      var outputContainer = $(this.selectorMainContent);
+      $.ajax({
+        url: this.getUrl('cards'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            outputContainer.empty().append(data.html);
+            CardLayout.initialize();
+            // Each card head can have a t3js-require class and a data-require attribute
+            // with the name of a requireJS module. Those are loaded here and initialize()
+            // is executed if exists.
+            $('.t3js-require').each(function() {
+              var module = $(this).data('require');
+              require([module], function(aModule) {
+                if (typeof aModule.initialize !== 'undefined') {
+                  aModule.initialize();
+                }
+              });
+            });
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          self.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js
index 63d0faeca1b2..3906a75af7ee 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/Severity.js
@@ -14,42 +14,42 @@
 /**
  * Module: TYPO3/CMS/Install/Severity
  */
-define([], function () {
-	'use strict';
+define([], function() {
+  'use strict';
 
-	var Severity = {
-		loading: -3,
-		notice: -2,
-		info: -1,
-		ok: 0,
-		warning: 1,
-		error: 2
-	};
+  var Severity = {
+    loading: -3,
+    notice: -2,
+    info: -1,
+    ok: 0,
+    warning: 1,
+    error: 2
+  };
 
-	Severity.getCssClass = function (severity) {
-		var severityClass;
-		switch (severity) {
-			case Severity.loading:
-				severityClass = 'notice alert-loading';
-				break;
-			case Severity.notice:
-				severityClass = 'notice';
-				break;
-			case Severity.ok:
-				severityClass = 'success';
-				break;
-			case Severity.warning:
-				severityClass = 'warning';
-				break;
-			case Severity.error:
-				severityClass = 'danger';
-				break;
-			case Severity.info:
-			default:
-				severityClass = 'info';
-		}
-		return severityClass;
-	};
+  Severity.getCssClass = function(severity) {
+    var severityClass;
+    switch (severity) {
+      case Severity.loading:
+        severityClass = 'notice alert-loading';
+        break;
+      case Severity.notice:
+        severityClass = 'notice';
+        break;
+      case Severity.ok:
+        severityClass = 'success';
+        break;
+      case Severity.warning:
+        severityClass = 'warning';
+        break;
+      case Severity.error:
+        severityClass = 'danger';
+        break;
+      case Severity.info:
+      default:
+        severityClass = 'info';
+    }
+    return severityClass;
+  };
 
-	return Severity;
+  return Severity;
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js
index 0aacaae60f5d..2d3e4b02ce7c 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/SystemMaintainer.js
@@ -15,128 +15,128 @@
  * Module: TYPO3/CMS/Install/SystemMaintainer
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap',
-	'chosen'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap',
+  'chosen'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-systemMaintainer-open',
-		selectorWriteTrigger: '.t3js-systemMaintainer-write',
-		selectorWriteToken: '#t3js-systemMaintainer-write-token',
-		selectorOutputContainer: '.t3js-systemMaintainer-output',
-		selectorChosenContainer: '.t3js-systemMaintainer-chosen',
-		selectorChosenField: '.t3js-systemMaintainer-chosen-select',
+  return {
+    selectorGridderOpener: 't3js-systemMaintainer-open',
+    selectorWriteTrigger: '.t3js-systemMaintainer-write',
+    selectorWriteToken: '#t3js-systemMaintainer-write-token',
+    selectorOutputContainer: '.t3js-systemMaintainer-output',
+    selectorChosenContainer: '.t3js-systemMaintainer-chosen',
+    selectorChosenField: '.t3js-systemMaintainer-chosen-select',
 
-		initialize: function() {
-			var self = this;
+    initialize: function() {
+      var self = this;
 
-			// Get current system maintainer list on card open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener)) {
-					self.getList();
-				}
-			});
+      // Get current system maintainer list on card open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener)) {
+          self.getList();
+        }
+      });
 
-			$(document).on('click', this.selectorWriteTrigger, function(e) {
-				e.preventDefault();
-				self.write();
-			});
-		},
+      $(document).on('click', this.selectorWriteTrigger, function(e) {
+        e.preventDefault();
+        self.write();
+      });
+    },
 
-		getList: function() {
-			var self = this;
-			var $chosenContainer = $(this.selectorChosenContainer);
-			var $outputContainer = $(this.selectorOutputContainer);
-			var $chosenField = $(self.selectorChosenField);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().append(message);
-			$chosenContainer.hide();
-			$chosenField.empty();
-			$.ajax({
-				url: Router.getUrl('systemMaintainerGetList'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true) {
-						$outputContainer.find('.alert-loading').remove();
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-						if (Array.isArray(data.users)) {
-							data.users.forEach(function(element) {
-								var name = element.username;
-								if (element.disable) {
-									name = '[DISABLED] ' + name;
-								}
-								var selected = '';
-								if (element.isSystemMaintainer) {
-									selected = 'selected="selected"';
-								}
-								$chosenField.append(
-									'<option value="' + element.uid + '" ' + selected + '>' + name + '</option>'
-								);
-							});
-						}
-						var config = {
-							'.chosen-select': {width: "100%", placeholder_text_multiple: "users"},
-							'.chosen-select-deselect': {allow_single_deselect: true},
-							'.chosen-select-width': {width: "100%"}
-						};
-						for (var selector in config) {
-							$(selector).chosen(config[selector]);
-						}
-						$chosenContainer.show();
-						$chosenField.trigger('chosen:updated');
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+    getList: function() {
+      var self = this;
+      var $chosenContainer = $(this.selectorChosenContainer);
+      var $outputContainer = $(this.selectorOutputContainer);
+      var $chosenField = $(self.selectorChosenField);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().append(message);
+      $chosenContainer.hide();
+      $chosenField.empty();
+      $.ajax({
+        url: Router.getUrl('systemMaintainerGetList'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.find('.alert-loading').remove();
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              });
+            }
+            if (Array.isArray(data.users)) {
+              data.users.forEach(function(element) {
+                var name = element.username;
+                if (element.disable) {
+                  name = '[DISABLED] ' + name;
+                }
+                var selected = '';
+                if (element.isSystemMaintainer) {
+                  selected = 'selected="selected"';
+                }
+                $chosenField.append(
+                  '<option value="' + element.uid + '" ' + selected + '>' + name + '</option>'
+                );
+              });
+            }
+            var config = {
+              '.chosen-select': {width: "100%", placeholder_text_multiple: "users"},
+              '.chosen-select-deselect': {allow_single_deselect: true},
+              '.chosen-select-width': {width: "100%"}
+            };
+            for (var selector in config) {
+              $(selector).chosen(config[selector]);
+            }
+            $chosenContainer.show();
+            $chosenField.trigger('chosen:updated');
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
 
-		write: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var selectedUsers = $(this.selectorChosenField).val();
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.append(message);
-			$.ajax({
-				method: 'POST',
-				url: Router.getUrl(),
-				data: {
-					'install': {
-						'users': selectedUsers,
-						'token': $(this.selectorWriteToken).text(),
-						'action': 'systemMaintainerWrite'
-					}
-				},
-				success: function (data) {
-					if (data.success === true) {
-						$outputContainer.find('.alert-loading').remove();
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.empty().append(message);
-							});
-						}
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    write: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var selectedUsers = $(this.selectorChosenField).val();
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.append(message);
+      $.ajax({
+        method: 'POST',
+        url: Router.getUrl(),
+        data: {
+          'install': {
+            'users': selectedUsers,
+            'token': $(this.selectorWriteToken).text(),
+            'action': 'systemMaintainerWrite'
+          }
+        },
+        success: function(data) {
+          if (data.success === true) {
+            $outputContainer.find('.alert-loading').remove();
+            if (Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.empty().append(message);
+              });
+            }
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js
index 6586d7905a03..e29af284840f 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaExtTablesCheck.js
@@ -15,61 +15,61 @@
  * Module: TYPO3/CMS/Install/TcaExtTablesCheck
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorCheckTrigger: '.t3js-tcaExtTablesCheck-check',
-		selectorOutputContainer: '.t3js-tcaExtTablesCheck-output',
+  return {
+    selectorCheckTrigger: '.t3js-tcaExtTablesCheck-check',
+    selectorOutputContainer: '.t3js-tcaExtTablesCheck-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorCheckTrigger, function(e) {
-				e.preventDefault();
-				self.check();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorCheckTrigger, function(e) {
+        e.preventDefault();
+        self.check();
+      });
+    },
 
-		check: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('tcaExtTablesCheck'),
-				cache: false,
-				success: function (data) {
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							var message = InfoBox.render(
-								Severity.warning,
-								'Extensions change TCA in ext_tables.php',
-								'Check for ExtensionManagementUtility and $GLOBALS["TCA"]'
-							);
-							$outputContainer.empty();
-							$outputContainer.append(message);
-							data.status.forEach(function (element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						} else {
-							var message = InfoBox.render(Severity.ok, 'No TCA changes in ext_tables.php files. Good job!', '');
-							$outputContainer.empty().html(message);
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    check: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('tcaExtTablesCheck'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            if (data.status.length > 0) {
+              var message = InfoBox.render(
+                Severity.warning,
+                'Extensions change TCA in ext_tables.php',
+                'Check for ExtensionManagementUtility and $GLOBALS["TCA"]'
+              );
+              $outputContainer.empty();
+              $outputContainer.append(message);
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              });
+            } else {
+              var message = InfoBox.render(Severity.ok, 'No TCA changes in ext_tables.php files. Good job!', '');
+              $outputContainer.empty().html(message);
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js
index 0a03946c26de..b6e343421e6f 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/TcaMigrationsCheck.js
@@ -15,61 +15,61 @@
  * Module: TYPO3/CMS/Install/TcaIntegrityChecker
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/FlashMessage',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity'
 ], function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+  'use strict';
 
-	return {
-		selectorCheckTrigger: '.t3js-tcaMigrationsCheck-check',
-		selectorOutputContainer: '.t3js-tcaMigrationsCheck-output',
+  return {
+    selectorCheckTrigger: '.t3js-tcaMigrationsCheck-check',
+    selectorOutputContainer: '.t3js-tcaMigrationsCheck-output',
 
-		initialize: function() {
-			var self = this;
-			$(document).on('click', this.selectorCheckTrigger, function(e) {
-				e.preventDefault();
-				self.check();
-			});
-		},
+    initialize: function() {
+      var self = this;
+      $(document).on('click', this.selectorCheckTrigger, function(e) {
+        e.preventDefault();
+        self.check();
+      });
+    },
 
-		check: function() {
-			var $outputContainer = $(this.selectorOutputContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			$outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('tcaMigrationsCheck'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							var message = InfoBox.render(
-								Severity.warning,
-								'TCA migrations need to be applied',
-								'Check the following list and apply needed changes.'
-							);
-							$outputContainer.empty();
-							$outputContainer.append(message);
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						} else {
-							var message = InfoBox.render(Severity.ok, 'No TCA migrations need to be applied', 'Your TCA looks good.');
-							$outputContainer.empty().html(message);
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		}
-	};
+    check: function() {
+      var $outputContainer = $(this.selectorOutputContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      $outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('tcaMigrationsCheck'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && Array.isArray(data.status)) {
+            if (data.status.length > 0) {
+              var message = InfoBox.render(
+                Severity.warning,
+                'TCA migrations need to be applied',
+                'Check the following list and apply needed changes.'
+              );
+              $outputContainer.empty();
+              $outputContainer.append(message);
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+              });
+            } else {
+              var message = InfoBox.render(Severity.ok, 'No TCA migrations need to be applied', 'Your TCA looks good.');
+              $outputContainer.empty().html(message);
+            }
+          } else {
+            var message = FlashMessage.render(Severity.error, 'Something went wrong', 'Use "Check for broken extensions"');
+            $outputContainer.empty().html(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js
index 91f665af5291..cef55807e152 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeDocs.js
@@ -15,227 +15,227 @@
  * Module: TYPO3/CMS/Install/UpgradeDocs
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity',
-	'bootstrap',
-	'chosen'
-], function ($, Router, ProgressBar, InfoBox, Severity) {
-	'use strict';
-
-	return {
-		selectorGridderOpener: 't3js-upgradeDocs-open',
-		selectorContentContainer: '.t3js-upgradeDocs-content',
-		selectorMarkReadToken: '#t3js-upgradeDocs-markRead-token',
-		selectorUnmarkReadToken: '#t3js-upgradeDocs-unmarkRead-token',
-		selectorRestFileItem: '.upgrade_analysis_item_to_filter',
-		selectorFulltextSearch: '.gridder-show .t3js-upgradeDocs-fulltext-search',
-		selectorChosenField: '.gridder-show .t3js-upgradeDocs-chosen-select',
-
-		chosenField: null,
-		fulltextSearchField: null,
-
-		initialize: function() {
-			var self = this;
-
-			// Get content on card open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener)) {
-					self.getContent();
-				}
-			});
-
-			// Mark a file as read
-			$(document).on('click', '.t3js-upgradeDocs-markRead', function(event) {
-				self.markRead(event.target);
-			});
-			$(document).on('click', '.t3js-upgradeDocs-unmarkRead', function(event) {
-				self.unmarkRead(event.target);
-			});
-
-			// Make jquerys "contains" work case-insensitive
-			jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
-				return function (elem) {
-					return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
-				};
-			});
-		},
-
-		getContent: function() {
-			var self = this;
-			var outputContainer = $(this.selectorContentContainer);
-			var message = ProgressBar.render(Severity.loading, 'Loading...', '');
-			outputContainer.empty().html(message);
-			$.ajax({
-				url: Router.getUrl('upgradeDocsGetContent'),
-				cache: false,
-				success: function(data) {
-					if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
-						outputContainer.empty().append(data.html);
-						$('[data-toggle="tooltip"]').tooltip({container: 'body'});
-						self.chosenField = $(self.selectorChosenField);
-						self.fulltextSearchField = $(self.selectorFulltextSearch);
-						self.initializeChosenSelector();
-						self.chosenField.on('change', function() {
-							self.combinedFilterSearch();
-						});
-						self.fulltextSearchField.on('keyup', function() {
-							self.combinedFilterSearch();
-						});
-					} else {
-						var message = InfoBox.render(Severity.error, 'Something went wrong', '');
-						outputContainer.empty().append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
-
-		initializeChosenSelector: function() {
-			var self = this;
-			var tagString = '';
-			$(this.selectorRestFileItem).each(function() {
-				tagString += $(this).data('item-tags') + ',';
-			});
-			var tagArray = this.trimExplodeAndUnique(',', tagString);
-			$.each(tagArray, function(i, tag) {
-				self.chosenField.append('<option>' + tag + '</option>');
-			});
-			var config = {
-				'.chosen-select': {width: "100%", placeholder_text_multiple: "tags"},
-				'.chosen-select-deselect': {allow_single_deselect: true},
-				'.chosen-select-no-single': {disable_search_threshold: 10},
-				'.chosen-select-no-results': {no_results_text: 'Oops, nothing found!'},
-				'.chosen-select-width': {width: "100%"}
-			};
-			for (var selector in config) {
-				$(selector).chosen(config[selector]);
-			}
-			this.chosenField.trigger('chosen:updated');
-		},
-
-		combinedFilterSearch: function() {
-			var $items = $('div.item');
-			if (this.chosenField.val().length < 1 && this.fulltextSearchField.val().length < 1) {
-				$('.panel-version:not(:first) > .panel-collapse').collapse('hide');
-				$items.removeClass('hidden searchhit filterhit');
-				return false;
-			}
-			$items.addClass('hidden').removeClass('searchhit filterhit');
-
-			// apply tags
-			if (this.chosenField.val().length > 0) {
-				$items
-					.addClass('hidden')
-					.removeClass('filterhit');
-				var orTags = [];
-				var andTags = [];
-				$.each(this.chosenField.val(), function(index, item) {
-					var tagFilter = '[data-item-tags*="' + item + '"]';
-					if (item.indexOf(':') > 0) {
-						orTags.push(tagFilter);
-					} else {
-						andTags.push(tagFilter);
-					}
-				});
-				var andString = andTags.join('');
-				var tags = [];
-				if (orTags.length) {
-					for (var i = 0; i < orTags.length; i++) {
-						tags.push(andString + orTags[i]);
-					}
-				} else {
-					tags.push(andString);
-				}
-				var tagSelection = tags.join(',');
-				$(tagSelection)
-					.removeClass('hidden')
-					.addClass('searchhit filterhit');
-			} else {
-				$items
-					.addClass('filterhit')
-					.removeClass('hidden');
-			}
-			// apply fulltext search
-			var typedQuery = this.fulltextSearchField.val();
-			$('div.item.filterhit').each(function() {
-				var $item = $(this);
-				if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
-					$item.removeClass('hidden').addClass('searchhit');
-				} else {
-					$item.removeClass('searchhit').addClass('hidden');
-				}
-			});
-
-			$('.searchhit').closest('.panel-collapse').collapse('show');
-
-			//check for empty panels
-			$('.panel-version').each(function() {
-				if ($(this).find('.searchhit', '.filterhit').length < 1) {
-					$(this).find(' > .panel-collapse').collapse('hide');
-				}
-			});
-		},
-
-		markRead: function(element) {
-			var $button = $(element).closest('a');
-			$button.toggleClass('t3js-upgradeDocs-unmarkRead t3js-upgradeDocs-markRead');
-			$button.find('i').toggleClass('fa-check fa-ban');
-			$button.closest('.panel').appendTo('.panel-body-read');
-			$.ajax({
-				method: 'POST',
-				url: Router.getUrl(),
-				data: {
-					'install': {
-						'ignoreFile': $button.data('filepath'),
-						'token': $(this.selectorMarkReadToken).text(),
-						'action': 'upgradeDocsMarkRead'
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
-
-		unmarkRead: function(element) {
-			var $button = $(element).closest('a');
-			var version = $button.closest('.panel').data('item-version');
-			$button.toggleClass('t3js-upgradeDocs-markRead t3js-upgradeDocs-unmarkRead');
-			$button.find('i').toggleClass('fa-check fa-ban');
-			$button.closest('.panel').appendTo('*[data-group-version="' + version + '"] .panel-body');
-			$.ajax({
-				method: 'POST',
-				url: Router.getUrl(),
-				data: {
-					'install': {
-						'ignoreFile': $button.data('filepath'),
-						'token': $(this.selectorUnmarkReadToken).text(),
-						action: 'upgradeDocsUnmarkRead'
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
-
-		trimExplodeAndUnique: function(delimiter, string) {
-			var result = [];
-			var items = string.split(delimiter);
-			for (var i = 0; i < items.length; i++) {
-				var item = items[i].trim();
-				if (item.length > 0) {
-					if ($.inArray(item, result) === -1) {
-						result.push(item);
-					}
-				}
-			}
-			return result;
-		}
-	};
+  'jquery',
+  'TYPO3/CMS/Install/Router',
+  'TYPO3/CMS/Install/ProgressBar',
+  'TYPO3/CMS/Install/InfoBox',
+  'TYPO3/CMS/Install/Severity',
+  'bootstrap',
+  'chosen'
+], function($, Router, ProgressBar, InfoBox, Severity) {
+  'use strict';
+
+  return {
+    selectorGridderOpener: 't3js-upgradeDocs-open',
+    selectorContentContainer: '.t3js-upgradeDocs-content',
+    selectorMarkReadToken: '#t3js-upgradeDocs-markRead-token',
+    selectorUnmarkReadToken: '#t3js-upgradeDocs-unmarkRead-token',
+    selectorRestFileItem: '.upgrade_analysis_item_to_filter',
+    selectorFulltextSearch: '.gridder-show .t3js-upgradeDocs-fulltext-search',
+    selectorChosenField: '.gridder-show .t3js-upgradeDocs-chosen-select',
+
+    chosenField: null,
+    fulltextSearchField: null,
+
+    initialize: function() {
+      var self = this;
+
+      // Get content on card open
+      $(document).on('cardlayout:card-opened', function(event, $card) {
+        if ($card.hasClass(self.selectorGridderOpener)) {
+          self.getContent();
+        }
+      });
+
+      // Mark a file as read
+      $(document).on('click', '.t3js-upgradeDocs-markRead', function(event) {
+        self.markRead(event.target);
+      });
+      $(document).on('click', '.t3js-upgradeDocs-unmarkRead', function(event) {
+        self.unmarkRead(event.target);
+      });
+
+      // Make jquerys "contains" work case-insensitive
+      jQuery.expr[':'].contains = jQuery.expr.createPseudo(function(arg) {
+        return function(elem) {
+          return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
+        };
+      });
+    },
+
+    getContent: function() {
+      var self = this;
+      var outputContainer = $(this.selectorContentContainer);
+      var message = ProgressBar.render(Severity.loading, 'Loading...', '');
+      outputContainer.empty().html(message);
+      $.ajax({
+        url: Router.getUrl('upgradeDocsGetContent'),
+        cache: false,
+        success: function(data) {
+          if (data.success === true && data.html !== 'undefined' && data.html.length > 0) {
+            outputContainer.empty().append(data.html);
+            $('[data-toggle="tooltip"]').tooltip({container: 'body'});
+            self.chosenField = $(self.selectorChosenField);
+            self.fulltextSearchField = $(self.selectorFulltextSearch);
+            self.initializeChosenSelector();
+            self.chosenField.on('change', function() {
+              self.combinedFilterSearch();
+            });
+            self.fulltextSearchField.on('keyup', function() {
+              self.combinedFilterSearch();
+            });
+          } else {
+            var message = InfoBox.render(Severity.error, 'Something went wrong', '');
+            outputContainer.empty().append(message);
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
+
+    initializeChosenSelector: function() {
+      var self = this;
+      var tagString = '';
+      $(this.selectorRestFileItem).each(function() {
+        tagString += $(this).data('item-tags') + ',';
+      });
+      var tagArray = this.trimExplodeAndUnique(',', tagString);
+      $.each(tagArray, function(i, tag) {
+        self.chosenField.append('<option>' + tag + '</option>');
+      });
+      var config = {
+        '.chosen-select': {width: "100%", placeholder_text_multiple: "tags"},
+        '.chosen-select-deselect': {allow_single_deselect: true},
+        '.chosen-select-no-single': {disable_search_threshold: 10},
+        '.chosen-select-no-results': {no_results_text: 'Oops, nothing found!'},
+        '.chosen-select-width': {width: "100%"}
+      };
+      for (var selector in config) {
+        $(selector).chosen(config[selector]);
+      }
+      this.chosenField.trigger('chosen:updated');
+    },
+
+    combinedFilterSearch: function() {
+      var $items = $('div.item');
+      if (this.chosenField.val().length < 1 && this.fulltextSearchField.val().length < 1) {
+        $('.panel-version:not(:first) > .panel-collapse').collapse('hide');
+        $items.removeClass('hidden searchhit filterhit');
+        return false;
+      }
+      $items.addClass('hidden').removeClass('searchhit filterhit');
+
+      // apply tags
+      if (this.chosenField.val().length > 0) {
+        $items
+          .addClass('hidden')
+          .removeClass('filterhit');
+        var orTags = [];
+        var andTags = [];
+        $.each(this.chosenField.val(), function(index, item) {
+          var tagFilter = '[data-item-tags*="' + item + '"]';
+          if (item.indexOf(':') > 0) {
+            orTags.push(tagFilter);
+          } else {
+            andTags.push(tagFilter);
+          }
+        });
+        var andString = andTags.join('');
+        var tags = [];
+        if (orTags.length) {
+          for (var i = 0; i < orTags.length; i++) {
+            tags.push(andString + orTags[i]);
+          }
+        } else {
+          tags.push(andString);
+        }
+        var tagSelection = tags.join(',');
+        $(tagSelection)
+          .removeClass('hidden')
+          .addClass('searchhit filterhit');
+      } else {
+        $items
+          .addClass('filterhit')
+          .removeClass('hidden');
+      }
+      // apply fulltext search
+      var typedQuery = this.fulltextSearchField.val();
+      $('div.item.filterhit').each(function() {
+        var $item = $(this);
+        if ($(':contains(' + typedQuery + ')', $item).length > 0 || $('input[value*="' + typedQuery + '"]', $item).length > 0) {
+          $item.removeClass('hidden').addClass('searchhit');
+        } else {
+          $item.removeClass('searchhit').addClass('hidden');
+        }
+      });
+
+      $('.searchhit').closest('.panel-collapse').collapse('show');
+
+      //check for empty panels
+      $('.panel-version').each(function() {
+        if ($(this).find('.searchhit', '.filterhit').length < 1) {
+          $(this).find(' > .panel-collapse').collapse('hide');
+        }
+      });
+    },
+
+    markRead: function(element) {
+      var $button = $(element).closest('a');
+      $button.toggleClass('t3js-upgradeDocs-unmarkRead t3js-upgradeDocs-markRead');
+      $button.find('i').toggleClass('fa-check fa-ban');
+      $button.closest('.panel').appendTo('.panel-body-read');
+      $.ajax({
+        method: 'POST',
+        url: Router.getUrl(),
+        data: {
+          'install': {
+            'ignoreFile': $button.data('filepath'),
+            'token': $(this.selectorMarkReadToken).text(),
+            'action': 'upgradeDocsMarkRead'
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
+
+    unmarkRead: function(element) {
+      var $button = $(element).closest('a');
+      var version = $button.closest('.panel').data('item-version');
+      $button.toggleClass('t3js-upgradeDocs-markRead t3js-upgradeDocs-unmarkRead');
+      $button.find('i').toggleClass('fa-check fa-ban');
+      $button.closest('.panel').appendTo('*[data-group-version="' + version + '"] .panel-body');
+      $.ajax({
+        method: 'POST',
+        url: Router.getUrl(),
+        data: {
+          'install': {
+            'ignoreFile': $button.data('filepath'),
+            'token': $(this.selectorUnmarkReadToken).text(),
+            action: 'upgradeDocsUnmarkRead'
+          }
+        },
+        error: function(xhr) {
+          Router.handleAjaxError(xhr);
+        }
+      });
+    },
+
+    trimExplodeAndUnique: function(delimiter, string) {
+      var result = [];
+      var items = string.split(delimiter);
+      for (var i = 0; i < items.length; i++) {
+        var item = items[i].trim();
+        if (item.length > 0) {
+          if ($.inArray(item, result) === -1) {
+            result.push(item);
+          }
+        }
+      }
+      return result;
+    }
+  };
 });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js
index 73f19e12ff4e..dc80b69e1971 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/Modules/UpgradeWizards.js
@@ -15,466 +15,466 @@
  * Module: TYPO3/CMS/Install/UpgradeWizards
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Install/Router',
-	'TYPO3/CMS/Install/FlashMessage',
-	'TYPO3/CMS/Install/ProgressBar',
-	'TYPO3/CMS/Install/InfoBox',
-	'TYPO3/CMS/Install/Severity'
-],
-function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
-	'use strict';
+    'jquery',
+    'TYPO3/CMS/Install/Router',
+    'TYPO3/CMS/Install/FlashMessage',
+    'TYPO3/CMS/Install/ProgressBar',
+    'TYPO3/CMS/Install/InfoBox',
+    'TYPO3/CMS/Install/Severity'
+  ],
+  function($, Router, FlashMessage, ProgressBar, InfoBox, Severity) {
+    'use strict';
 
-	return {
-		selectorGridderOpener: 't3js-upgradeWizards-open',
-		selectorMarkUndoneToken: '#t3js-upgradeWizards-markUndone-token',
-		selectorOutputWizardsContainer: '.t3js-upgradeWizards-wizards-output',
-		selectorOutputDoneContainer: '.t3js-upgradeWizards-done-output',
-		selectorWizardsBlockingAddsTemplate: '.t3js-upgradeWizards-blocking-adds-template',
-		selectorWizardsBlockingAddsRows: '.t3js-upgradeWizards-blocking-adds-rows',
-		selectorWizardsBlockingAddsExecute: '.t3js-upgradeWizards-blocking-adds-execute',
-		selectorWizardsBlockingCharsetTemplate: '.t3js-upgradeWizards-blocking-charset-template',
-		selectorWizardsBlockingCharsetFix: '.t3js-upgradeWizards-blocking-charset-fix',
-		selectorWizardsDoneBodyTemplate: '.t3js-upgradeWizards-done-body-template',
-		selectorWizardsDoneRows: '.t3js-upgradeWizards-done-rows',
-		selectorWizardsDoneRowTemplate: '.t3js-upgradeWizards-done-row-template table tbody',
-		selectorWizardsDoneRowMarkUndone: '.t3js-upgradeWizards-done-markUndone',
-		selectorWizardsDoneRowTitle: '.t3js-upgradeWizards-done-title',
-		selectorWizardsListTemplate: '.gridder-show .t3js-upgradeWizards-list-template',
-		selectorWizardsListRows: '.t3js-upgradeWizards-list-rows',
-		selectorWizardsListRowTemplate: '.gridder-show .t3js-upgradeWizards-list-row-template',
-		selectorWizardsListRowTitle: '.t3js-upgradeWizards-list-row-title',
-		selectorWizardsListRowExplanation: '.t3js-upgradeWizards-list-row-explanation',
-		selectorWizardsListRowExecute: '.t3js-upgradeWizards-list-row-execute',
-		selectorWizardsInputToken: '#t3js-upgradeWizards-input-token',
-		selectorWizardsInputTemplate: '.gridder-show .t3js-upgradeWizards-input',
-		selectorWizardsInputTitle: '.t3js-upgradeWizards-input-title',
-		selectorWizardsInputHtml: '.t3js-upgradeWizards-input-html',
-		selectorWizardsInputPerform: '.t3js-upgradeWizards-input-perform',
-		selectorWizardsExecuteToken: '#t3js-upgradeWizards-execute-token',
+    return {
+      selectorGridderOpener: 't3js-upgradeWizards-open',
+      selectorMarkUndoneToken: '#t3js-upgradeWizards-markUndone-token',
+      selectorOutputWizardsContainer: '.t3js-upgradeWizards-wizards-output',
+      selectorOutputDoneContainer: '.t3js-upgradeWizards-done-output',
+      selectorWizardsBlockingAddsTemplate: '.t3js-upgradeWizards-blocking-adds-template',
+      selectorWizardsBlockingAddsRows: '.t3js-upgradeWizards-blocking-adds-rows',
+      selectorWizardsBlockingAddsExecute: '.t3js-upgradeWizards-blocking-adds-execute',
+      selectorWizardsBlockingCharsetTemplate: '.t3js-upgradeWizards-blocking-charset-template',
+      selectorWizardsBlockingCharsetFix: '.t3js-upgradeWizards-blocking-charset-fix',
+      selectorWizardsDoneBodyTemplate: '.t3js-upgradeWizards-done-body-template',
+      selectorWizardsDoneRows: '.t3js-upgradeWizards-done-rows',
+      selectorWizardsDoneRowTemplate: '.t3js-upgradeWizards-done-row-template table tbody',
+      selectorWizardsDoneRowMarkUndone: '.t3js-upgradeWizards-done-markUndone',
+      selectorWizardsDoneRowTitle: '.t3js-upgradeWizards-done-title',
+      selectorWizardsListTemplate: '.gridder-show .t3js-upgradeWizards-list-template',
+      selectorWizardsListRows: '.t3js-upgradeWizards-list-rows',
+      selectorWizardsListRowTemplate: '.gridder-show .t3js-upgradeWizards-list-row-template',
+      selectorWizardsListRowTitle: '.t3js-upgradeWizards-list-row-title',
+      selectorWizardsListRowExplanation: '.t3js-upgradeWizards-list-row-explanation',
+      selectorWizardsListRowExecute: '.t3js-upgradeWizards-list-row-execute',
+      selectorWizardsInputToken: '#t3js-upgradeWizards-input-token',
+      selectorWizardsInputTemplate: '.gridder-show .t3js-upgradeWizards-input',
+      selectorWizardsInputTitle: '.t3js-upgradeWizards-input-title',
+      selectorWizardsInputHtml: '.t3js-upgradeWizards-input-html',
+      selectorWizardsInputPerform: '.t3js-upgradeWizards-input-perform',
+      selectorWizardsExecuteToken: '#t3js-upgradeWizards-execute-token',
 
-		loadingMessage: ProgressBar.render(Severity.loading, 'Loading...', ''),
+      loadingMessage: ProgressBar.render(Severity.loading, 'Loading...', ''),
 
-		initialize: function() {
-			var self = this;
+      initialize: function() {
+        var self = this;
 
-			// Load main content on first open
-			$(document).on('cardlayout:card-opened', function(event, $card) {
-				if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
-					$card.data('isInitialized', true);
-					self.silentUpgrades();
-					self.doneUpgrades();
-				}
-			});
+        // Load main content on first open
+        $(document).on('cardlayout:card-opened', function(event, $card) {
+          if ($card.hasClass(self.selectorGridderOpener) && !$card.data('isInitialized')) {
+            $card.data('isInitialized', true);
+            self.silentUpgrades();
+            self.doneUpgrades();
+          }
+        });
 
-			// Mark a done wizard undone
-			$(document).on('click', this.selectorWizardsDoneRowMarkUndone, function(event) {
-				var identifier = $(event.target).data('identifier');
-				self.markUndone(identifier);
-			});
+        // Mark a done wizard undone
+        $(document).on('click', this.selectorWizardsDoneRowMarkUndone, function(event) {
+          var identifier = $(event.target).data('identifier');
+          self.markUndone(identifier);
+        });
 
-			// Execute "fix default mysql connection db charset" blocking wizard
-			$(document).on('click', this.selectorWizardsBlockingCharsetFix, function(event) {
-				self.blockingUpgradesDatabaseCharsetFix();
-			});
+        // Execute "fix default mysql connection db charset" blocking wizard
+        $(document).on('click', this.selectorWizardsBlockingCharsetFix, function(event) {
+          self.blockingUpgradesDatabaseCharsetFix();
+        });
 
-			// Execute "add required fields + tables" blocking wizard
-			$(document).on('click', this.selectorWizardsBlockingAddsExecute, function(event) {
-				self.blockingUpgradesDatabaseAddsExecute();
-			});
+        // Execute "add required fields + tables" blocking wizard
+        $(document).on('click', this.selectorWizardsBlockingAddsExecute, function(event) {
+          self.blockingUpgradesDatabaseAddsExecute();
+        });
 
-			// Get user input of a single upgrade wizard
-			$(document).on('click', this.selectorWizardsListRowExecute, function(event) {
-				var identifier = $(event.target).data('identifier');
-				self.wizardInput(identifier);
-			});
+        // Get user input of a single upgrade wizard
+        $(document).on('click', this.selectorWizardsListRowExecute, function(event) {
+          var identifier = $(event.target).data('identifier');
+          self.wizardInput(identifier);
+        });
 
-			// Execute one upgrade wizard
-			$(document).on('click', this.selectorWizardsInputPerform, function(event) {
-				var identifier = $(event.target).data('identifier');
-				self.wizardExecute(identifier);
-			});
-		},
+        // Execute one upgrade wizard
+        $(document).on('click', this.selectorWizardsInputPerform, function(event) {
+          var identifier = $(event.target).data('identifier');
+          self.wizardExecute(identifier);
+        });
+      },
 
-		silentUpgrades: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			$outputContainer.empty().html(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsSilentUpgrades'),
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						if (data.status.length > 0) {
-							data.status.forEach((function (element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							}));
-						}
-						self.blockingUpgradesDatabaseCharsetTest();
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      silentUpgrades: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        $outputContainer.empty().html(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsSilentUpgrades'),
+          cache: false,
+          success: function(data) {
+            $outputContainer.empty();
+            if (data.success === true && Array.isArray(data.status)) {
+              if (data.status.length > 0) {
+                data.status.forEach((function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                }));
+              }
+              self.blockingUpgradesDatabaseCharsetTest();
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              $outputContainer.empty().html(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		blockingUpgradesDatabaseCharsetTest: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			var charsetTemplate = $(this.selectorWizardsBlockingCharsetTemplate).html();
-			$outputContainer.append().html(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetTest'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true) {
-						if (data.needsUpdate === true) {
-							$outputContainer.append($(charsetTemplate).clone());
-						} else {
-							self.blockingUpgradesDatabaseAdds();
-						}
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      blockingUpgradesDatabaseCharsetTest: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        var charsetTemplate = $(this.selectorWizardsBlockingCharsetTemplate).html();
+        $outputContainer.append().html(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetTest'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            if (data.success === true) {
+              if (data.needsUpdate === true) {
+                $outputContainer.append($(charsetTemplate).clone());
+              } else {
+                self.blockingUpgradesDatabaseAdds();
+              }
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		blockingUpgradesDatabaseCharsetFix: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			$outputContainer.append().html(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetFix'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true) {
-						if (Array.isArray(data.status) && data.status.length > 0) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						self.removeLoadingMessage($outputContainer);
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      blockingUpgradesDatabaseCharsetFix: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        $outputContainer.append().html(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsBlockingDatabaseCharsetFix'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            if (data.success === true) {
+              if (Array.isArray(data.status) && data.status.length > 0) {
+                data.status.forEach(function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                });
+              }
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              self.removeLoadingMessage($outputContainer);
+              $outputContainer.append(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		blockingUpgradesDatabaseAdds: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			var breakingAddsTemplate = $(this.selectorWizardsBlockingAddsTemplate).html();
-			$outputContainer.append().html(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsBlockingDatabaseAdds'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true) {
-						if (data.needsUpdate === true) {
-							var adds = $(breakingAddsTemplate).clone();
-							if (typeof(data.adds.tables) === 'object') {
-								data.adds.tables.forEach(function(element) {
-									adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + '<br>');
-								});
-							}
-							if (typeof(data.adds.columns) === 'object') {
-								data.adds.columns.forEach(function(element) {
-									adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Field: ' + element.field + '<br>');
-								});
-							}
-							if (typeof(data.adds.indexes) === 'object') {
-								data.adds.indexes.forEach(function(element) {
-									adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Index: ' + element.index + '<br>');
-								});
-							}
-							$outputContainer.append(adds);
-						} else {
-							self.wizardsList();
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						self.removeLoadingMessage($outputContainer);
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      blockingUpgradesDatabaseAdds: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        var breakingAddsTemplate = $(this.selectorWizardsBlockingAddsTemplate).html();
+        $outputContainer.append().html(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsBlockingDatabaseAdds'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            if (data.success === true) {
+              if (data.needsUpdate === true) {
+                var adds = $(breakingAddsTemplate).clone();
+                if (typeof(data.adds.tables) === 'object') {
+                  data.adds.tables.forEach(function(element) {
+                    adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + '<br>');
+                  });
+                }
+                if (typeof(data.adds.columns) === 'object') {
+                  data.adds.columns.forEach(function(element) {
+                    adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Field: ' + element.field + '<br>');
+                  });
+                }
+                if (typeof(data.adds.indexes) === 'object') {
+                  data.adds.indexes.forEach(function(element) {
+                    adds.find(self.selectorWizardsBlockingAddsRows).append('Table: ' + element.table + ', Index: ' + element.index + '<br>');
+                  });
+                }
+                $outputContainer.append(adds);
+              } else {
+                self.wizardsList();
+              }
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              self.removeLoadingMessage($outputContainer);
+              $outputContainer.append(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		blockingUpgradesDatabaseAddsExecute: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			$outputContainer.empty().html(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsBlockingDatabaseExecute'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true) {
-						if (Array.isArray(data.status) && data.status.length > 0) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-							self.wizardsList();
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						self.removeLoadingMessage($outputContainer);
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      blockingUpgradesDatabaseAddsExecute: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        $outputContainer.empty().html(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsBlockingDatabaseExecute'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            if (data.success === true) {
+              if (Array.isArray(data.status) && data.status.length > 0) {
+                data.status.forEach(function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                });
+                self.wizardsList();
+              }
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              self.removeLoadingMessage($outputContainer);
+              $outputContainer.append(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		wizardsList: function() {
-			var self = this;
-			var listTemplate = $(this.selectorWizardsListTemplate);
-			var wizardTemplate = $(this.selectorWizardsListRowTemplate);
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			$outputContainer.append(self.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsList'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					var list = $(listTemplate).clone();
-					list.removeClass('t3js-upgradeWizards-list-template');
-					if (data.success === true) {
-						var numberOfWizardsTodo = 0;
-						var numberOfWizards = 0;
-						if (Array.isArray(data.wizards) && data.wizards.length > 0) {
-							numberOfWizards = data.wizards.length;
-							data.wizards.forEach(function(element) {
-								if (element.shouldRenderWizard === true) {
-									var aRow = $(wizardTemplate).clone();
-									numberOfWizardsTodo = numberOfWizardsTodo +1;
-									aRow.removeClass('t3js-upgradeWizards-list-row-template');
-									aRow.find(self.selectorWizardsListRowTitle).empty().text(element.title);
-									aRow.find(self.selectorWizardsListRowExplanation).empty().text(element.explanation);
-									aRow.find(self.selectorWizardsListRowExecute).data('identifier', element.identifier);
-									list.find(self.selectorWizardsListRows).append(aRow);
-								}
-							});
-							list.find(self.selectorWizardsListRows + ' hr:last').remove();
-						}
-						var percent = 100;
-						if (numberOfWizardsTodo > 0) {
-							percent = ((numberOfWizards - numberOfWizardsTodo) / data.wizards.length) * 100;
-						}
-						list.find('.progress-bar')
-							.css('width', percent + '%')
-							.attr('aria-valuenow', percent)
-							.find('span')
-							.text(parseInt(percent) + '%');
-						$outputContainer.append(list);
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						self.removeLoadingMessage($outputContainer);
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      wizardsList: function() {
+        var self = this;
+        var listTemplate = $(this.selectorWizardsListTemplate);
+        var wizardTemplate = $(this.selectorWizardsListRowTemplate);
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        $outputContainer.append(self.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsList'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            var list = $(listTemplate).clone();
+            list.removeClass('t3js-upgradeWizards-list-template');
+            if (data.success === true) {
+              var numberOfWizardsTodo = 0;
+              var numberOfWizards = 0;
+              if (Array.isArray(data.wizards) && data.wizards.length > 0) {
+                numberOfWizards = data.wizards.length;
+                data.wizards.forEach(function(element) {
+                  if (element.shouldRenderWizard === true) {
+                    var aRow = $(wizardTemplate).clone();
+                    numberOfWizardsTodo = numberOfWizardsTodo + 1;
+                    aRow.removeClass('t3js-upgradeWizards-list-row-template');
+                    aRow.find(self.selectorWizardsListRowTitle).empty().text(element.title);
+                    aRow.find(self.selectorWizardsListRowExplanation).empty().text(element.explanation);
+                    aRow.find(self.selectorWizardsListRowExecute).data('identifier', element.identifier);
+                    list.find(self.selectorWizardsListRows).append(aRow);
+                  }
+                });
+                list.find(self.selectorWizardsListRows + ' hr:last').remove();
+              }
+              var percent = 100;
+              if (numberOfWizardsTodo > 0) {
+                percent = ((numberOfWizards - numberOfWizardsTodo) / data.wizards.length) * 100;
+              }
+              list.find('.progress-bar')
+                .css('width', percent + '%')
+                .attr('aria-valuenow', percent)
+                .find('span')
+                .text(parseInt(percent) + '%');
+              $outputContainer.append(list);
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              self.removeLoadingMessage($outputContainer);
+              $outputContainer.append(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		wizardInput: function(identifier) {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			var inputTemplate = $(this.selectorWizardsInputTemplate);
-			$outputContainer.empty().html(this.loadingMessage);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'upgradeWizardsInput',
-						'token': $(this.selectorWizardsInputToken).text(),
-						'identifier': identifier
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					var input = $(inputTemplate).clone();
-					input.removeClass('t3js-upgradeWizards-input');
-					if (data.success === true) {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = FlashMessage.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-						if (data.userInput.wizardHtml.length > 0) {
-							input.find(self.selectorWizardsInputHtml).html(data.userInput.wizardHtml);
-						}
-						input.find(self.selectorWizardsInputTitle).text(data.userInput.title);
-						input.find(self.selectorWizardsInputPerform).data('identifier', data.userInput.identifier);
-					}
-					$outputContainer.append(input);
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      wizardInput: function(identifier) {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        var inputTemplate = $(this.selectorWizardsInputTemplate);
+        $outputContainer.empty().html(this.loadingMessage);
+        $.ajax({
+          url: Router.getUrl(),
+          method: 'POST',
+          data: {
+            'install': {
+              'action': 'upgradeWizardsInput',
+              'token': $(this.selectorWizardsInputToken).text(),
+              'identifier': identifier
+            }
+          },
+          cache: false,
+          success: function(data) {
+            $outputContainer.empty();
+            var input = $(inputTemplate).clone();
+            input.removeClass('t3js-upgradeWizards-input');
+            if (data.success === true) {
+              if (Array.isArray(data.status)) {
+                data.status.forEach(function(element) {
+                  var message = FlashMessage.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                });
+              }
+              if (data.userInput.wizardHtml.length > 0) {
+                input.find(self.selectorWizardsInputHtml).html(data.userInput.wizardHtml);
+              }
+              input.find(self.selectorWizardsInputTitle).text(data.userInput.title);
+              input.find(self.selectorWizardsInputPerform).data('identifier', data.userInput.identifier);
+            }
+            $outputContainer.append(input);
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		wizardExecute: function(identifier) {
-			var self = this;
-			var postData = {
-				'install[action]': 'upgradeWizardsExecute',
-				'install[token]': $(this.selectorWizardsExecuteToken).text(),
-				'install[identifier]': identifier
-			};
-			$($(this.selectorOutputWizardsContainer + ' form').serializeArray()).each(function() {
-				postData[this.name] = this.value;
-			});
-			var $outputContainer = $(this.selectorOutputWizardsContainer);
-			var $outputDoneContainer = $(this.selectorOutputDoneContainer);
-			$outputContainer.empty().html(this.loadingMessage);
-			$.ajax({
-				method: 'POST',
-				data: postData,
-				url: Router.getUrl(),
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true) {
-						if (Array.isArray(data.status)) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-						self.wizardsList();
-						$outputDoneContainer.empty();
-						self.doneUpgrades();
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      wizardExecute: function(identifier) {
+        var self = this;
+        var postData = {
+          'install[action]': 'upgradeWizardsExecute',
+          'install[token]': $(this.selectorWizardsExecuteToken).text(),
+          'install[identifier]': identifier
+        };
+        $($(this.selectorOutputWizardsContainer + ' form').serializeArray()).each(function() {
+          postData[this.name] = this.value;
+        });
+        var $outputContainer = $(this.selectorOutputWizardsContainer);
+        var $outputDoneContainer = $(this.selectorOutputDoneContainer);
+        $outputContainer.empty().html(this.loadingMessage);
+        $.ajax({
+          method: 'POST',
+          data: postData,
+          url: Router.getUrl(),
+          cache: false,
+          success: function(data) {
+            $outputContainer.empty();
+            if (data.success === true) {
+              if (Array.isArray(data.status)) {
+                data.status.forEach(function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                });
+              }
+              self.wizardsList();
+              $outputDoneContainer.empty();
+              self.doneUpgrades();
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              $outputContainer.empty().html(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		doneUpgrades: function() {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputDoneContainer);
-			var rowTemplate = $(this.selectorWizardsDoneRowTemplate).html();
-			var bodyTemplate = $(this.selectorWizardsDoneBodyTemplate).html();
-			$outputContainer.append(this.loadingMessage);
-			$.ajax({
-				url: Router.getUrl('upgradeWizardsDoneUpgrades'),
-				cache: false,
-				success: function(data) {
-					self.removeLoadingMessage($outputContainer);
-					if (data.success === true) {
-						if (Array.isArray(data.status) && data.status.length > 0) {
-							data.status.forEach(function(element) {
-								var message = InfoBox.render(element.severity, element.title, element.message);
-								$outputContainer.append(message);
-							});
-						}
-						var body = $(bodyTemplate).clone();
-						var hasBodyContent = false;
-						var $wizardsDoneContainer = body.find(self.selectorWizardsDoneRows);
-						if (Array.isArray(data.wizardsDone) && data.wizardsDone.length > 0) {
-							data.wizardsDone.forEach(function(element) {
-								hasBodyContent = true;
-								var aRow = $(rowTemplate).clone();
-								aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier);
-								aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
-								$wizardsDoneContainer.append(aRow);
-							});
-						}
-						if (Array.isArray(data.rowUpdatersDone) && data.rowUpdatersDone.length > 0) {
-							data.rowUpdatersDone.forEach(function(element) {
-								hasBodyContent = true;
-								var aRow = $(rowTemplate).clone();
-								aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier);
-								aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
-								$wizardsDoneContainer.append(aRow);
-							});
-						}
-						if (hasBodyContent === true) {
-							$outputContainer.append(body);
-						}
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						self.removeLoadingMessage($outputContainer);
-						$outputContainer.append(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      doneUpgrades: function() {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputDoneContainer);
+        var rowTemplate = $(this.selectorWizardsDoneRowTemplate).html();
+        var bodyTemplate = $(this.selectorWizardsDoneBodyTemplate).html();
+        $outputContainer.append(this.loadingMessage);
+        $.ajax({
+          url: Router.getUrl('upgradeWizardsDoneUpgrades'),
+          cache: false,
+          success: function(data) {
+            self.removeLoadingMessage($outputContainer);
+            if (data.success === true) {
+              if (Array.isArray(data.status) && data.status.length > 0) {
+                data.status.forEach(function(element) {
+                  var message = InfoBox.render(element.severity, element.title, element.message);
+                  $outputContainer.append(message);
+                });
+              }
+              var body = $(bodyTemplate).clone();
+              var hasBodyContent = false;
+              var $wizardsDoneContainer = body.find(self.selectorWizardsDoneRows);
+              if (Array.isArray(data.wizardsDone) && data.wizardsDone.length > 0) {
+                data.wizardsDone.forEach(function(element) {
+                  hasBodyContent = true;
+                  var aRow = $(rowTemplate).clone();
+                  aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier);
+                  aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
+                  $wizardsDoneContainer.append(aRow);
+                });
+              }
+              if (Array.isArray(data.rowUpdatersDone) && data.rowUpdatersDone.length > 0) {
+                data.rowUpdatersDone.forEach(function(element) {
+                  hasBodyContent = true;
+                  var aRow = $(rowTemplate).clone();
+                  aRow.find(self.selectorWizardsDoneRowMarkUndone).data('identifier', element.identifier);
+                  aRow.find(self.selectorWizardsDoneRowTitle).text(element.title);
+                  $wizardsDoneContainer.append(aRow);
+                });
+              }
+              if (hasBodyContent === true) {
+                $outputContainer.append(body);
+              }
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              self.removeLoadingMessage($outputContainer);
+              $outputContainer.append(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		markUndone: function(identifier) {
-			var self = this;
-			var $outputContainer = $(this.selectorOutputDoneContainer);
-			$outputContainer.empty().html(this.loadingMessage);
-			$.ajax({
-				url: Router.getUrl(),
-				method: 'POST',
-				data: {
-					'install': {
-						'action': 'upgradeWizardsMarkUndone',
-						'token': $(this.selectorMarkUndoneToken).text(),
-						'identifier': identifier
-					}
-				},
-				cache: false,
-				success: function(data) {
-					$outputContainer.empty();
-					if (data.success === true && Array.isArray(data.status)) {
-						data.status.forEach(function(element) {
-							var message = InfoBox.render(element.severity, element.title, element.message);
-							$outputContainer.append(message);
-							self.doneUpgrades();
-							self.blockingUpgradesDatabaseCharsetTest();
-						});
-					} else {
-						var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
-						$outputContainer.empty().html(message);
-					}
-				},
-				error: function(xhr) {
-					Router.handleAjaxError(xhr);
-				}
-			});
-		},
+      markUndone: function(identifier) {
+        var self = this;
+        var $outputContainer = $(this.selectorOutputDoneContainer);
+        $outputContainer.empty().html(this.loadingMessage);
+        $.ajax({
+          url: Router.getUrl(),
+          method: 'POST',
+          data: {
+            'install': {
+              'action': 'upgradeWizardsMarkUndone',
+              'token': $(this.selectorMarkUndoneToken).text(),
+              'identifier': identifier
+            }
+          },
+          cache: false,
+          success: function(data) {
+            $outputContainer.empty();
+            if (data.success === true && Array.isArray(data.status)) {
+              data.status.forEach(function(element) {
+                var message = InfoBox.render(element.severity, element.title, element.message);
+                $outputContainer.append(message);
+                self.doneUpgrades();
+                self.blockingUpgradesDatabaseCharsetTest();
+              });
+            } else {
+              var message = FlashMessage.render(Severity.error, 'Something went wrong', '');
+              $outputContainer.empty().html(message);
+            }
+          },
+          error: function(xhr) {
+            Router.handleAjaxError(xhr);
+          }
+        });
+      },
 
-		removeLoadingMessage: function($container) {
-			$container.find('.alert-loading').remove();
-		}
-	};
-});
+      removeLoadingMessage: function($container) {
+        $container.find('.alert-loading').remove();
+      }
+    };
+  });
diff --git a/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js b/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js
index 7aca611178aa..4cc7754e6c08 100644
--- a/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js
+++ b/typo3/sysext/install/Resources/Public/JavaScript/RequireJSConfig.js
@@ -1,21 +1,21 @@
 var require = {
-	baseUrl: '',
-	urlArgs: 'bust=' + (new Date()).getTime(),
-	paths: {
-		'TYPO3/CMS/Backend': 'sysext/backend/Resources/Public/JavaScript/',
-		'TYPO3/CMS/Install': 'sysext/install/Resources/Public/JavaScript/Modules/',
-		'jquery': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery/jquery-3.2.1.min',
-		'jquery.clearable': 'sysext/backend/Resources/Public/JavaScript/jquery.clearable',
-		'TYPO3/CMS/Core/Contrib/jquery.minicolors': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors',
-		'bootstrap': 'sysext/install/Resources/Public/JavaScript/bootstrap.min',
-		'chosen': 'sysext/install/Resources/Public/JavaScript/chosen.jquery.min'
-	},
-	shim: {
-		jQuery: {
-			exports: '$'
-		},
-		'bootstrap': {
-			'deps': ['jquery']
-		}
-	}
+  baseUrl: '',
+  urlArgs: 'bust=' + (new Date()).getTime(),
+  paths: {
+    'TYPO3/CMS/Backend': 'sysext/backend/Resources/Public/JavaScript/',
+    'TYPO3/CMS/Install': 'sysext/install/Resources/Public/JavaScript/Modules/',
+    'jquery': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery/jquery-3.2.1.min',
+    'jquery.clearable': 'sysext/backend/Resources/Public/JavaScript/jquery.clearable',
+    'TYPO3/CMS/Core/Contrib/jquery.minicolors': 'sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors',
+    'bootstrap': 'sysext/install/Resources/Public/JavaScript/bootstrap.min',
+    'chosen': 'sysext/install/Resources/Public/JavaScript/chosen.jquery.min'
+  },
+  shim: {
+    jQuery: {
+      exports: '$'
+    },
+    'bootstrap': {
+      'deps': ['jquery']
+    }
+  }
 };
diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js b/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js
index 360d91b905d0..0f13c0784322 100644
--- a/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js
+++ b/typo3/sysext/lang/Resources/Public/JavaScript/Lang.js
@@ -18,30 +18,30 @@
  * `TYPO3.lang.foo[0].target = 'blah'` becomes `TYPO3.lang['foo'] = 'blah'`
  */
 define(['jquery'], function($) {
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Lang/Lang
-	 */
-	var Lang = {};
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Lang/Lang
+   */
+  var Lang = {};
 
-	/**
-	 *
-	 */
-	Lang.convertToOneDimension = function() {
-		var originalLangObject = $.extend(true, {}, TYPO3.lang);
-		TYPO3.lang = [];
-		$.each(originalLangObject, function(index, value) {
-			if (typeof value === "object") {
-				TYPO3.lang[index] = value[0].target || value[0].source;
-			} else {
-				TYPO3.lang[index] = value;
-			}
-		});
+  /**
+   *
+   */
+  Lang.convertToOneDimension = function() {
+    var originalLangObject = $.extend(true, {}, TYPO3.lang);
+    TYPO3.lang = [];
+    $.each(originalLangObject, function(index, value) {
+      if (typeof value === "object") {
+        TYPO3.lang[index] = value[0].target || value[0].source;
+      } else {
+        TYPO3.lang[index] = value;
+      }
+    });
 
-		delete originalLangObject;
-	};
+    delete originalLangObject;
+  };
 
-	Lang.convertToOneDimension();
-	return TYPO3.lang;
+  Lang.convertToOneDimension();
+  return TYPO3.lang;
 });
diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js b/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js
index 0d8d2e9eb6cd..704dbe50e36c 100644
--- a/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js
+++ b/typo3/sysext/lang/Resources/Public/JavaScript/LanguageModule.js
@@ -16,748 +16,748 @@
  * Language module class
  */
 define(['jquery',
-		'moment',
-		'TYPO3/CMS/Backend/Icons',
-		'TYPO3/CMS/Backend/Notification',
-		'datatables',
-		'TYPO3/CMS/Backend/jquery.clearable'
-	   ], function($, moment, Icons, Notification) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{me: *, context: null, table: null, topMenu: null, currentRequest: null, settings: {}, icons: {}, labels: {}, identifiers: {searchField: string, topMenu: string, activateIcon: string, deactivateIcon: string, downloadIcon: string, loadingIcon: string, completeIcon: string, progressBar: string, progressBarText: string, progressBarInner: string, lastUpdate: string, languagePrefix: string, extensionPrefix: string}, classes: {enabled: string, disabled: string, processing: string, complete: string, extension: string, actions: string, progressBar: string, loading: string, lastUpdate: string}}}
-	 * @exports TYPO3/CMS/Lang/LanguageModule
-	 */
-	var LanguageModule = {
-		me: this,
-		context: null,
-		table: null,
-		topMenu: null,
-		currentRequest: null,
-		userAbortRequest: false,
-		settings: {},
-		icons: {},
-		labels: {},
-		buttons: {
-			update: null,
-			cancel: null
-		},
-		identifiers: {
-			searchField: '.t3js-language-searchfield',
-			topMenu: 'div.t3js-module-docheader',
-			activateIcon: 'span.activateIcon',
-			deactivateIcon: 'span.deactivateIcon',
-			downloadIcon: 'span.downloadIcon',
-			removeIcon: 'span.removeIcon',
-			loadingIcon: 'span.loadingIcon',
-			completeIcon: 'span.completeIcon',
-			progressBar: 'div.progressBar',
-			progressBarText: 'div.progress-text',
-			progressBarInner: 'div.progress-bar',
-			lastUpdate: 'td.lastUpdate',
-			languagePrefix: 'language-',
-			extensionPrefix: 'extension-'
-		},
-		classes: {
-			enabled: 'enabled',
-			disabled: 'disabled',
-			processing: 'processing',
-			complete: 'complete',
-			extension: 'extensionName',
-			actions: 'actions',
-			progressBar: 'progressBar',
-			loading: 'loading',
-			lastUpdate: 'lastUpdate'
-		}
-	};
-
-	/**
-	 * Initialize language table
-	 *
-	 * @param {HTMLElement} contextElement
-	 * @param {HTMLElement} tableElement
-	 */
-	LanguageModule.initializeLanguageTable = function(contextElement, tableElement) {
-		LanguageModule.context = $(contextElement);
-		LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu);
-		LanguageModule.settings = LanguageModule.context.data();
-		LanguageModule.icons = LanguageModule.buildIcons();
-		LanguageModule.labels = LanguageModule.buildLabels();
-		LanguageModule.table = LanguageModule.buildLanguageTable(tableElement);
-		LanguageModule.initializeSearchField();
-		LanguageModule.initializeEventHandler();
-		LanguageModule.initializeButtons();
-	};
-
-	/**
-	 * Initialize translation table
-	 *
-	 * @param {HTMLElement} contextElement
-	 * @param {HTMLElement} tableElement
-	 */
-	LanguageModule.initializeTranslationTable = function(contextElement, tableElement) {
-		LanguageModule.context = $(contextElement);
-		LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu);
-		LanguageModule.settings = LanguageModule.context.data();
-		LanguageModule.icons = LanguageModule.buildIcons();
-		LanguageModule.labels = LanguageModule.buildLabels();
-		LanguageModule.table = LanguageModule.buildTranslationTable(tableElement);
-		LanguageModule.initializeSearchField();
-		LanguageModule.initializeEventHandler();
-	};
-
-	/**
-	 * Activate a language
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.activateLanguageAction = function(triggerElement, parameters) {
-		var $row = $(triggerElement).closest('tr'),
-			locale = $row.data('locale');
-
-		if ($row.hasClass(LanguageModule.classes.processing)) {
-			LanguageModule.abortAjaxRequest();
-		}
-		LanguageModule.executeAjaxRequest(LanguageModule.settings.activateLanguageUri, {locale: locale}, function(response, status) {
-			if (status === 'success' && response.success) {
-				$row.removeClass(LanguageModule.classes.disabled).addClass(LanguageModule.classes.enabled);
-				LanguageModule.displaySuccess(LanguageModule.labels.languageActivated);
-			} else {
-				LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-			}
-		});
-	};
-
-	/**
-	 * Deactivate a language
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.deactivateLanguageAction = function(triggerElement, parameters) {
-		var $row = $(triggerElement).closest('tr'),
-			locale = $row.data('locale');
-
-		if ($row.hasClass(LanguageModule.classes.processing)) {
-			LanguageModule.abortAjaxRequest();
-		}
-		LanguageModule.executeAjaxRequest(LanguageModule.settings.deactivateLanguageUri, {locale: locale}, function(response, status) {
-			if (status === 'success' && response.success) {
-				$row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled);
-				LanguageModule.displaySuccess(LanguageModule.labels.languageDeactivated);
-			} else {
-				LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-			}
-		});
-	};
-
-	/**
-	 * Remove a language
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.removeLanguageAction = function(triggerElement, parameters) {
-		var $row = $(triggerElement).closest('tr'),
-			locale = $row.data('locale'),
-			$lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row);
-
-		if ($row.hasClass(LanguageModule.classes.processing)) {
-			LanguageModule.abortAjaxRequest();
-		}
-		LanguageModule.executeAjaxRequest(LanguageModule.settings.removeLanguageUri, {locale: locale}, function(response, status) {
-			if (status === 'success' && response.success) {
-				$row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled);
-				$lastUpdate.html('');
-				LanguageModule.displaySuccess(LanguageModule.labels.languageRemoved);
-			} else {
-				LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-			}
-		});
-	};
-
-	/**
-	 * Update a language
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.updateLanguageAction = function(triggerElement, parameters) {
-		var $row = $(triggerElement).closest('tr'),
-			locale = $row.data('locale'),
-			$progressBar = $(LanguageModule.identifiers.progressBar, $row),
-			$lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row);
-
-		$row.addClass(LanguageModule.classes.processing);
-		LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) {
-			if (status === 'success') {
-				LanguageModule.setProgress($progressBar, 100);
-				LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
-				$row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
-				$lastUpdate.html(LanguageModule.formatDate(response.timestamp));
-			} else if (status === 'progress') {
-				LanguageModule.setProgress($progressBar, parseFloat(response.progress));
-			} else if (status === 'error') {
-				LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-			}
-		});
-	};
-
-	/**
-	 * Update all active languages
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.updateActiveLanguagesAction = function(triggerElement, parameters) {
-		var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
-		if ($activeRows.length > 0) {
-			LanguageModule.updateButtonStatus('update');
-			LanguageModule.topMenu.addClass(LanguageModule.classes.processing);
-			$activeRows.addClass(LanguageModule.classes.processing);
-			LanguageModule.loadTranslationsByRows($activeRows, function(row, status, data, response) {
-				var $progressBar = $(LanguageModule.identifiers.progressBar, row),
-					$lastUpdate = $(LanguageModule.identifiers.lastUpdate, row);
-
-				if (status === 'success') {
-					LanguageModule.setProgress($progressBar, 100);
-					row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
-					$lastUpdate.html(LanguageModule.formatDate(response.timestamp));
-				} else if (status === 'progress') {
-					LanguageModule.setProgress($progressBar, parseFloat(response.progress));
-				} else if (status === 'error') {
-					LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-				} else if (status === 'finished') {
-					LanguageModule.updateButtonStatus('cancel');
-					LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
-					LanguageModule.topMenu.removeClass(LanguageModule.classes.processing);
-				}
-			});
-		} else {
-			LanguageModule.displayError(LanguageModule.labels.noLanguageActivated);
-		}
-	};
-
-	/**
-	 * Cancel language update
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.cancelLanguageUpdateAction = function(triggerElement, parameters) {
-		var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
-		LanguageModule.updateButtonStatus('cancel');
-		LanguageModule.topMenu.removeClass(LanguageModule.classes.processing);
-		$activeRows.removeClass(LanguageModule.classes.processing);
-		LanguageModule.abortAjaxRequest();
-	};
-
-	/**
-	 * Update an extension translation
-	 *
-	 * @param {HTMLElement} triggerElement
-	 * @param {Object} parameters
-	 */
-	LanguageModule.updateTranslationAction = function(triggerElement, parameters) {
-		var $row = $(triggerElement).closest('tr'),
-			$cell = $(triggerElement).closest('td'),
-			extension = $row.data('extension'),
-			locale = LanguageModule.table.cell($cell).data().locale;
-
-		$cell.addClass(LanguageModule.classes.processing);
-		LanguageModule.loadTranslationByExtensionAndLocale(extension, locale, function(status, data, response) {
-			if (status === 'success') {
-				LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
-				$cell.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
-			} else if (status === 'error') {
-				LanguageModule.displayError(LanguageModule.labels.errorOccurred);
-			}
-		});
-	};
-
-	/**
-	 * Build icons
-	 *
-	 * @returns {{activate: (*|jQuery), deactivate: (*|jQuery), download: (*|jQuery), loading: (*|jQuery), complete: (*|jQuery), progressBar: (*|jQuery)}}
-	 */
-	LanguageModule.buildIcons = function() {
-		return {
-			activate: $(LanguageModule.identifiers.activateIcon, LanguageModule.context).html(),
-			deactivate: $(LanguageModule.identifiers.deactivateIcon, LanguageModule.context).html(),
-			download: $(LanguageModule.identifiers.downloadIcon, LanguageModule.context).html(),
-			remove: $(LanguageModule.identifiers.removeIcon, LanguageModule.context).html(),
-			loading: $(LanguageModule.identifiers.loadingIcon, LanguageModule.context).html(),
-			complete: $(LanguageModule.identifiers.completeIcon, LanguageModule.context).html(),
-			progressBar: $(LanguageModule.identifiers.progressBar, LanguageModule.context).html()
-		}
-	};
-
-	/**
-	 * Build labels
-	 *
-	 * @returns {{processing: *, search: *, loadingRecords: *, zeroRecords: *, emptyTable: *, dateFormat: *, errorHeader: *, infoHeader: *, successHeader: *, languageActivated: *, errorOccurred: *, languageDeactivated: *, languageRemoved: *, updateComplete: *}}
-	 */
-	LanguageModule.buildLabels = function() {
-		return {
-			processing: TYPO3.lang['table.processing'],
-			search: TYPO3.lang['table.search'],
-			loadingRecords: TYPO3.lang['table.loadingRecords'],
-			zeroRecords: TYPO3.lang['table.zeroRecords'],
-			emptyTable: TYPO3.lang['table.emptyTable'],
-			dateFormat: TYPO3.lang['table.dateFormat'],
-			errorHeader: TYPO3.lang['flashmessage.error'],
-			infoHeader: TYPO3.lang['flashmessage.information'],
-			successHeader: TYPO3.lang['flashmessage.success'],
-			languageActivated: TYPO3.lang['flashmessage.languageActivated'],
-			errorOccurred: TYPO3.lang['flashmessage.errorOccurred'],
-			languageDeactivated: TYPO3.lang['flashmessage.languageDeactivated'],
-			languageRemoved: TYPO3.lang['flashmessage.languageRemoved'],
-			noLanguageActivated: TYPO3.lang['flashmessage.noLanguageActivated'],
-			updateComplete: TYPO3.lang['flashmessage.updateComplete'],
-			canceled: TYPO3.lang['flashmessage.canceled']
-		}
-	};
-
-	/**
-	 * Build language table
-	 *
-	 * @param {HTMLElement} tableElement
-	 * @returns {Object}
-	 */
-	LanguageModule.buildLanguageTable = function(tableElement) {
-		return $(tableElement).DataTable({
-			dom: 'lrtip',
-			serverSide: false,
-			stateSave: true,
-			paging: false,
-			info: false,
-			ordering: true,
-			columnDefs: [{targets: 4, orderable: false}],
-			language: LanguageModule.labels,
-			order: [[1, 'asc']]
-		});
-	};
-
-	/**
-	 * Initialize translation table
-	 *
-	 * @param {HTMLElement} tableElement
-	 * @returns {Object}
-	 */
-	LanguageModule.buildTranslationTable = function(tableElement) {
-		var languageCount = $(tableElement).data('languageCount'),
-			columns = [
-				{
-					render: function(data, type, row) {
-						return LanguageModule.buildImage(data.icon, data.title, data.title, data.width, data.height);
-					},
-					width: '20px',
-					orderable: false,
-					targets: 0
-				}, {
-					render: function(data, type, row) {
-						return data.title;
-					},
-					className: LanguageModule.classes.extension,
-					targets: 1
-				}
-			];
-
-		for (var i = 0; i < languageCount; i++) {
-			columns.push({
-				render: function(data, type, row) {
-					var links = [
-						LanguageModule.buildActionLink('updateTranslation', data, LanguageModule.icons.download),
-						LanguageModule.buildActionLink('removeTranslation', data, LanguageModule.icons.remove),
-						LanguageModule.buildLoadingIndicator(),
-						LanguageModule.buildCompleteIndicator()
-					];
-					return links.join('');
-				},
-				className: 'dt-center',
-				targets: (i + 2)
-			});
-		}
-
-		return $(tableElement).DataTable({
-			dom: 'lrtip',
-			serverSide: false,
-			stateSave: true,
-			paging: false,
-			info: false,
-			ordering: true,
-			language: LanguageModule.labels,
-			ajax: LanguageModule.settings.listTranslationsUri,
-			order: [[1, 'asc']],
-			columnDefs: columns,
-			createdRow: function (row, data, index) {
-				var $row = $(row);
-				$row.attr('id', LanguageModule.identifiers.extensionPrefix + data[1].key);
-				$row.attr('data-extension', data[1].key);
-			}
-		});
-	};
-
-	/**
-	 * Initialize search field
-	 */
-	LanguageModule.initializeSearchField = function() {
-		var getVars = LanguageModule.getUrlVars();
-		var currentSearch = (getVars['search'] ? getVars['search'] : LanguageModule.table.search());
-		$(LanguageModule.identifiers.searchField)
-			.val(currentSearch)
-			.on('input', function() {
-				LanguageModule.table.search($(this).val()).draw();
-			})
-			.clearable({
-				onClear: function() {
-					if (LanguageModule.table !== null) {
-						LanguageModule.table.search('').draw();
-					}
-				}
-			})
-			.parents('form').on('submit', function() {
-				return false;
-			});
-	};
-
-	/**
-	 * Initialize event handler, redirect clicks to controller actions
-	 */
-	LanguageModule.initializeEventHandler = function() {
-		$(document).on('click', function(event) {
-			var $element = $(event.target);
-			var $parent = $element.closest('[data-action]');
-
-			if ($element.data('action') !== undefined) {
-				LanguageModule.handleActionEvent($element, event);
-			} else if ($parent.data('action') !== undefined) {
-				LanguageModule.handleActionEvent($parent, event);
-			}
-		});
-	};
-
-	/**
-	 * Initialize buttons
-	 */
-	LanguageModule.initializeButtons = function() {
-		LanguageModule.buttons.update = LanguageModule.topMenu.find('.t3js-button-update');
-		LanguageModule.buttons.cancel = LanguageModule.topMenu.find('.t3js-button-cancel');
-	};
-
-	/**
-	 * Update buttons in top menu
-	 *
-	 * @param {String} action
-	 */
-	LanguageModule.updateButtonStatus = function(action) {
-		switch (action) {
-			case 'update':
-				LanguageModule.buttons.update.data('action', 'cancelLanguageUpdate');
-				LanguageModule.buttons.cancel.removeClass('disabled');
-				Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(spinner) {
-					LanguageModule.buttons.update.find('span.icon').replaceWith(spinner);
-				});
-				break;
-			case 'cancel':
-				LanguageModule.buttons.update.data('action', 'updateActiveLanguages');
-				LanguageModule.buttons.cancel.addClass('disabled');
-				Icons.getIcon('actions-system-extension-download', Icons.sizes.small).done(function(download) {
-					LanguageModule.buttons.update.find('span.icon').replaceWith(download);
-				});
-				break;
-		}
-	};
-
-	/**
-	 * Handler for "action" events
-	 *
-	 * @param {Object} element
-	 * @param {Event} event
-	 */
-	LanguageModule.handleActionEvent = function(element, event) {
-		event.preventDefault();
-		var data = element.data();
-		var actionName = data.action + 'Action';
-		if (actionName in LanguageModule) {
-			LanguageModule[actionName](element, data);
-		}
-	};
-
-	/**
-	 * Load translations for all extensions by given locale
-	 *
-	 * @param {String} locale
-	 * @param {function} callback
-	 * @param {Number} counter
-	 */
-	LanguageModule.loadTranslationsByLocale = function(locale, callback, counter) {
-		counter = counter || 0;
-		var data = {locale: locale, count: counter};
-		LanguageModule.executeAjaxRequest(LanguageModule.settings.updateLanguageUri, data, function(response, status) {
-			if (status === 'success' && response.success) {
-				if (parseFloat(response.progress) < 100) {
-					callback('progress', data, response);
-					counter++;
-					LanguageModule.loadTranslationsByLocale(locale, callback, counter);
-				} else {
-					callback('success', data, response);
-				}
-			} else {
-				callback('error', data, response);
-			}
-		});
-	};
-
-	/**
-	 * Load translations for all extensions by given rows
-	 *
-	 * @param {Object} rows
-	 * @param {function} callback
-	 */
-	LanguageModule.loadTranslationsByRows = function(rows, callback) {
-		if (rows) {
-			rows = $(rows).toArray();
-			var $row = $(rows.shift()),
-				locale = $row.data('locale');
-
-			LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) {
-				callback($row, status, data, response);
-				if (status === 'success') {
-					if (rows.length) {
-						LanguageModule.loadTranslationsByRows(rows, callback);
-					} else {
-						callback($row, 'finished', data, response);
-					}
-				}
-			});
-		}
-	};
-
-	/**
-	 * Load translation for one extension by given locale
-	 *
-	 * @param {String} extension
-	 * @param {String} locale
-	 * @param {function} callback
-	 */
-	LanguageModule.loadTranslationByExtensionAndLocale = function(extension, locale, callback) {
-		var data = {extension: extension, locale: locale};
-		LanguageModule.executeAjaxRequest(LanguageModule.settings.updateTranslationUri, data, function(response, status) {
-			if (status === 'success' && response.success) {
-				callback('success', data, response);
-			} else {
-				callback('error', data, response);
-			}
-		});
-	};
-
-	/**
-	 * Execute AJAX request
-	 *
-	 * @param {String} uri
-	 * @param {Object} data
-	 * @param {function} callback
-	 */
-	LanguageModule.executeAjaxRequest = function(uri, data, callback) {
-		var newData = {};
-		newData[LanguageModule.settings.prefix] = {
-			data: data
-		};
-		LanguageModule.currentRequest = $.ajax({
-			type: 'POST',
-			cache: false,
-			url: uri,
-			data: newData,
-			dataType: 'json',
-			success: function(response, status) {
-				if (typeof callback === 'function') {
-					callback(response, status, '');
-				}
-			},
-			error: function(response, status, error) {
-				if (typeof callback === 'function') {
-					callback(response, status, error);
-				}
-			}
-		});
-	};
-
-	/**
-	 * Abort current AJAX request
-	 */
-	LanguageModule.abortAjaxRequest = function() {
-		if (LanguageModule.currentRequest) {
-			LanguageModule.userAbortRequest = true;
-			LanguageModule.currentRequest.abort();
-		}
-	};
-
-	/**
-	 * Display error flash message
-	 *
-	 * @param {String} label
-	 */
-	LanguageModule.displayError = function(label) {
-		if (LanguageModule.userAbortRequest) {
-			LanguageModule.displaySuccess(LanguageModule.labels.canceled);
-		} else if (typeof label === 'string' && label !== '') {
-			Notification.error(LanguageModule.labels.errorHeader, label);
-		}
-	};
-
-	/**
-	 * Display information flash message
-	 *
-	 * @param {String} label
-	 */
-	LanguageModule.displayInformation = function(label) {
-		if (typeof label === 'string' && label !== '') {
-			Notification.info(LanguageModule.labels.infoHeader, label);
-		}
-	};
-
-	/**
-	 * Display success flash message
-	 *
-	 * @param {String} label
-	 */
-	LanguageModule.displaySuccess = function(label) {
-		if (typeof label === 'string' && label !== '') {
-			Notification.success(LanguageModule.labels.successHeader, label);
-		}
-	};
-
-	/**
-	 * Build action link
-	 *
-	 * @param {String} action
-	 * @param {Object} parameters
-	 * @param {String} content
-	 * @returns {Object}
-	 */
-	LanguageModule.buildActionLink = function(action, parameters, content) {
-		var $link = $('<a>');
-
-		$link.addClass(action + 'Link');
-		$link.attr('data-action', action);
-		for (var name in parameters) {
-			if (parameters.hasOwnProperty(name)) {
-				$link.attr('data-' + name, parameters[name]);
-			}
-		}
-		$link.html(content);
-		return $link.wrap('<span>').parent().html();
-	};
-
-	/**
-	 * Build progress bar
-	 *
-	 * @returns {Object}
-	 */
-	LanguageModule.buildProgressBar = function() {
-		var $span = $('<span>');
-		$span.addClass(LanguageModule.classes.progressBar);
-		$span.html(LanguageModule.icons.progressBar);
-		return $span.wrap('<span>').parent().html();
-	};
-
-	/**
-	 * Build loading indicator
-	 *
-	 * @returns {Object}
-	 */
-	LanguageModule.buildLoadingIndicator = function() {
-		var $span = $('<span>');
-		$span.addClass(LanguageModule.classes.loading);
-		$span.html(LanguageModule.icons.loading);
-		return $span.wrap('<span>').parent().html();
-	};
-
-	/**
-	 * Build complete state indicator
-	 *
-	 * @returns {Object}
-	 */
-	LanguageModule.buildCompleteIndicator = function() {
-		var $span = $('<span>');
-		$span.addClass(LanguageModule.classes.complete);
-		$span.html(LanguageModule.icons.complete);
-		return $span.wrap('<span>').parent().html();
-	};
-
-	/**
-	 * Build image
-	 *
-	 * @param {String} uri
-	 * @param {String} alt
-	 * @param {String} title
-	 * @param {Number} width
-	 * @param {Number} heigth
-	 * @returns {Object}
-	 */
-	LanguageModule.buildImage = function(uri, alt, title, width, heigth) {
-		var $image = $('<img>');
-		$image.attr('src', uri);
-		$image.attr('alt', alt ? alt : '');
-		$image.attr('title', title ? title : '');
-		$image.attr('style', 'width: ' + width + 'px; height: ' + heigth + 'px;');
-		var $span = $('<span>');
-		$span.addClass('typo3-app-icon');
-		$span.attr('style', 'background: none; text-align: center;');
-		$span.html($image);
-		return $span.wrap('<span>').parent().html();
-	};
-
-	/**
-	 * Format date
-	 *
-	 * @param {Number} timestamp
-	 * @returns {*}
-	 */
-	LanguageModule.formatDate = function(timestamp) {
-		return moment.unix(timestamp).format(LanguageModule.labels.dateFormat);
-	};
-
-	/**
-	 * Set progress bar progress
-	 *
-	 * @param {Object} progressBar
-	 * @param {String} progress
-	 */
-	LanguageModule.setProgress = function(progressBar, progress) {
-		var $inner = $(LanguageModule.identifiers.progressBarInner, progressBar),
-			$text = $(LanguageModule.identifiers.progressBarText, progressBar);
-		$inner.css({width: progress + '%'});
-		$inner.attr('aria-valuenow', progress);
-		$text.text(Math.round(progress) + '%');
-	};
-
-	/**
-	 * Utility method to retrieve query parameters
-	 *
-	 * @returns {Array}
-	 */
-	LanguageModule.getUrlVars = function getUrlVars() {
-		var vars = [], hash;
-		var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
-		for (var i = 0; i < hashes.length; i++) {
-			hash = hashes[i].split('=');
-			vars.push(hash[0]);
-			vars[hash[0]] = hash[1];
-		}
-		return vars;
-	};
-
-	$(function() {
-		if ($('#typo3-language-list').length) {
-			LanguageModule.initializeLanguageTable('div.typo3-module-lang', '#typo3-language-list');
-		} else if ($('#typo3-translation-list').length) {
-			LanguageModule.initializeTranslationTable('div.typo3-module-lang', '#typo3-translation-list');
-		}
-	});
-
-	return LanguageModule;
+  'moment',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Notification',
+  'datatables',
+  'TYPO3/CMS/Backend/jquery.clearable'
+], function($, moment, Icons, Notification) {
+  'use strict';
+
+  /**
+   *
+   * @type {{me: *, context: null, table: null, topMenu: null, currentRequest: null, settings: {}, icons: {}, labels: {}, identifiers: {searchField: string, topMenu: string, activateIcon: string, deactivateIcon: string, downloadIcon: string, loadingIcon: string, completeIcon: string, progressBar: string, progressBarText: string, progressBarInner: string, lastUpdate: string, languagePrefix: string, extensionPrefix: string}, classes: {enabled: string, disabled: string, processing: string, complete: string, extension: string, actions: string, progressBar: string, loading: string, lastUpdate: string}}}
+   * @exports TYPO3/CMS/Lang/LanguageModule
+   */
+  var LanguageModule = {
+    me: this,
+    context: null,
+    table: null,
+    topMenu: null,
+    currentRequest: null,
+    userAbortRequest: false,
+    settings: {},
+    icons: {},
+    labels: {},
+    buttons: {
+      update: null,
+      cancel: null
+    },
+    identifiers: {
+      searchField: '.t3js-language-searchfield',
+      topMenu: 'div.t3js-module-docheader',
+      activateIcon: 'span.activateIcon',
+      deactivateIcon: 'span.deactivateIcon',
+      downloadIcon: 'span.downloadIcon',
+      removeIcon: 'span.removeIcon',
+      loadingIcon: 'span.loadingIcon',
+      completeIcon: 'span.completeIcon',
+      progressBar: 'div.progressBar',
+      progressBarText: 'div.progress-text',
+      progressBarInner: 'div.progress-bar',
+      lastUpdate: 'td.lastUpdate',
+      languagePrefix: 'language-',
+      extensionPrefix: 'extension-'
+    },
+    classes: {
+      enabled: 'enabled',
+      disabled: 'disabled',
+      processing: 'processing',
+      complete: 'complete',
+      extension: 'extensionName',
+      actions: 'actions',
+      progressBar: 'progressBar',
+      loading: 'loading',
+      lastUpdate: 'lastUpdate'
+    }
+  };
+
+  /**
+   * Initialize language table
+   *
+   * @param {HTMLElement} contextElement
+   * @param {HTMLElement} tableElement
+   */
+  LanguageModule.initializeLanguageTable = function(contextElement, tableElement) {
+    LanguageModule.context = $(contextElement);
+    LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu);
+    LanguageModule.settings = LanguageModule.context.data();
+    LanguageModule.icons = LanguageModule.buildIcons();
+    LanguageModule.labels = LanguageModule.buildLabels();
+    LanguageModule.table = LanguageModule.buildLanguageTable(tableElement);
+    LanguageModule.initializeSearchField();
+    LanguageModule.initializeEventHandler();
+    LanguageModule.initializeButtons();
+  };
+
+  /**
+   * Initialize translation table
+   *
+   * @param {HTMLElement} contextElement
+   * @param {HTMLElement} tableElement
+   */
+  LanguageModule.initializeTranslationTable = function(contextElement, tableElement) {
+    LanguageModule.context = $(contextElement);
+    LanguageModule.topMenu = $(LanguageModule.identifiers.topMenu);
+    LanguageModule.settings = LanguageModule.context.data();
+    LanguageModule.icons = LanguageModule.buildIcons();
+    LanguageModule.labels = LanguageModule.buildLabels();
+    LanguageModule.table = LanguageModule.buildTranslationTable(tableElement);
+    LanguageModule.initializeSearchField();
+    LanguageModule.initializeEventHandler();
+  };
+
+  /**
+   * Activate a language
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.activateLanguageAction = function(triggerElement, parameters) {
+    var $row = $(triggerElement).closest('tr'),
+      locale = $row.data('locale');
+
+    if ($row.hasClass(LanguageModule.classes.processing)) {
+      LanguageModule.abortAjaxRequest();
+    }
+    LanguageModule.executeAjaxRequest(LanguageModule.settings.activateLanguageUri, {locale: locale}, function(response, status) {
+      if (status === 'success' && response.success) {
+        $row.removeClass(LanguageModule.classes.disabled).addClass(LanguageModule.classes.enabled);
+        LanguageModule.displaySuccess(LanguageModule.labels.languageActivated);
+      } else {
+        LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+      }
+    });
+  };
+
+  /**
+   * Deactivate a language
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.deactivateLanguageAction = function(triggerElement, parameters) {
+    var $row = $(triggerElement).closest('tr'),
+      locale = $row.data('locale');
+
+    if ($row.hasClass(LanguageModule.classes.processing)) {
+      LanguageModule.abortAjaxRequest();
+    }
+    LanguageModule.executeAjaxRequest(LanguageModule.settings.deactivateLanguageUri, {locale: locale}, function(response, status) {
+      if (status === 'success' && response.success) {
+        $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled);
+        LanguageModule.displaySuccess(LanguageModule.labels.languageDeactivated);
+      } else {
+        LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+      }
+    });
+  };
+
+  /**
+   * Remove a language
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.removeLanguageAction = function(triggerElement, parameters) {
+    var $row = $(triggerElement).closest('tr'),
+      locale = $row.data('locale'),
+      $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row);
+
+    if ($row.hasClass(LanguageModule.classes.processing)) {
+      LanguageModule.abortAjaxRequest();
+    }
+    LanguageModule.executeAjaxRequest(LanguageModule.settings.removeLanguageUri, {locale: locale}, function(response, status) {
+      if (status === 'success' && response.success) {
+        $row.removeClass(LanguageModule.classes.enabled).removeClass(LanguageModule.classes.complete).addClass(LanguageModule.classes.disabled);
+        $lastUpdate.html('');
+        LanguageModule.displaySuccess(LanguageModule.labels.languageRemoved);
+      } else {
+        LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+      }
+    });
+  };
+
+  /**
+   * Update a language
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.updateLanguageAction = function(triggerElement, parameters) {
+    var $row = $(triggerElement).closest('tr'),
+      locale = $row.data('locale'),
+      $progressBar = $(LanguageModule.identifiers.progressBar, $row),
+      $lastUpdate = $(LanguageModule.identifiers.lastUpdate, $row);
+
+    $row.addClass(LanguageModule.classes.processing);
+    LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) {
+      if (status === 'success') {
+        LanguageModule.setProgress($progressBar, 100);
+        LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
+        $row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
+        $lastUpdate.html(LanguageModule.formatDate(response.timestamp));
+      } else if (status === 'progress') {
+        LanguageModule.setProgress($progressBar, parseFloat(response.progress));
+      } else if (status === 'error') {
+        LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+      }
+    });
+  };
+
+  /**
+   * Update all active languages
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.updateActiveLanguagesAction = function(triggerElement, parameters) {
+    var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
+    if ($activeRows.length > 0) {
+      LanguageModule.updateButtonStatus('update');
+      LanguageModule.topMenu.addClass(LanguageModule.classes.processing);
+      $activeRows.addClass(LanguageModule.classes.processing);
+      LanguageModule.loadTranslationsByRows($activeRows, function(row, status, data, response) {
+        var $progressBar = $(LanguageModule.identifiers.progressBar, row),
+          $lastUpdate = $(LanguageModule.identifiers.lastUpdate, row);
+
+        if (status === 'success') {
+          LanguageModule.setProgress($progressBar, 100);
+          row.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
+          $lastUpdate.html(LanguageModule.formatDate(response.timestamp));
+        } else if (status === 'progress') {
+          LanguageModule.setProgress($progressBar, parseFloat(response.progress));
+        } else if (status === 'error') {
+          LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+        } else if (status === 'finished') {
+          LanguageModule.updateButtonStatus('cancel');
+          LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
+          LanguageModule.topMenu.removeClass(LanguageModule.classes.processing);
+        }
+      });
+    } else {
+      LanguageModule.displayError(LanguageModule.labels.noLanguageActivated);
+    }
+  };
+
+  /**
+   * Cancel language update
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.cancelLanguageUpdateAction = function(triggerElement, parameters) {
+    var $activeRows = $('tr.' + LanguageModule.classes.enabled, LanguageModule.table.table().container());
+    LanguageModule.updateButtonStatus('cancel');
+    LanguageModule.topMenu.removeClass(LanguageModule.classes.processing);
+    $activeRows.removeClass(LanguageModule.classes.processing);
+    LanguageModule.abortAjaxRequest();
+  };
+
+  /**
+   * Update an extension translation
+   *
+   * @param {HTMLElement} triggerElement
+   * @param {Object} parameters
+   */
+  LanguageModule.updateTranslationAction = function(triggerElement, parameters) {
+    var $row = $(triggerElement).closest('tr'),
+      $cell = $(triggerElement).closest('td'),
+      extension = $row.data('extension'),
+      locale = LanguageModule.table.cell($cell).data().locale;
+
+    $cell.addClass(LanguageModule.classes.processing);
+    LanguageModule.loadTranslationByExtensionAndLocale(extension, locale, function(status, data, response) {
+      if (status === 'success') {
+        LanguageModule.displaySuccess(LanguageModule.labels.updateComplete);
+        $cell.removeClass(LanguageModule.classes.processing).addClass(LanguageModule.classes.complete);
+      } else if (status === 'error') {
+        LanguageModule.displayError(LanguageModule.labels.errorOccurred);
+      }
+    });
+  };
+
+  /**
+   * Build icons
+   *
+   * @returns {{activate: (*|jQuery), deactivate: (*|jQuery), download: (*|jQuery), loading: (*|jQuery), complete: (*|jQuery), progressBar: (*|jQuery)}}
+   */
+  LanguageModule.buildIcons = function() {
+    return {
+      activate: $(LanguageModule.identifiers.activateIcon, LanguageModule.context).html(),
+      deactivate: $(LanguageModule.identifiers.deactivateIcon, LanguageModule.context).html(),
+      download: $(LanguageModule.identifiers.downloadIcon, LanguageModule.context).html(),
+      remove: $(LanguageModule.identifiers.removeIcon, LanguageModule.context).html(),
+      loading: $(LanguageModule.identifiers.loadingIcon, LanguageModule.context).html(),
+      complete: $(LanguageModule.identifiers.completeIcon, LanguageModule.context).html(),
+      progressBar: $(LanguageModule.identifiers.progressBar, LanguageModule.context).html()
+    }
+  };
+
+  /**
+   * Build labels
+   *
+   * @returns {{processing: *, search: *, loadingRecords: *, zeroRecords: *, emptyTable: *, dateFormat: *, errorHeader: *, infoHeader: *, successHeader: *, languageActivated: *, errorOccurred: *, languageDeactivated: *, languageRemoved: *, updateComplete: *}}
+   */
+  LanguageModule.buildLabels = function() {
+    return {
+      processing: TYPO3.lang['table.processing'],
+      search: TYPO3.lang['table.search'],
+      loadingRecords: TYPO3.lang['table.loadingRecords'],
+      zeroRecords: TYPO3.lang['table.zeroRecords'],
+      emptyTable: TYPO3.lang['table.emptyTable'],
+      dateFormat: TYPO3.lang['table.dateFormat'],
+      errorHeader: TYPO3.lang['flashmessage.error'],
+      infoHeader: TYPO3.lang['flashmessage.information'],
+      successHeader: TYPO3.lang['flashmessage.success'],
+      languageActivated: TYPO3.lang['flashmessage.languageActivated'],
+      errorOccurred: TYPO3.lang['flashmessage.errorOccurred'],
+      languageDeactivated: TYPO3.lang['flashmessage.languageDeactivated'],
+      languageRemoved: TYPO3.lang['flashmessage.languageRemoved'],
+      noLanguageActivated: TYPO3.lang['flashmessage.noLanguageActivated'],
+      updateComplete: TYPO3.lang['flashmessage.updateComplete'],
+      canceled: TYPO3.lang['flashmessage.canceled']
+    }
+  };
+
+  /**
+   * Build language table
+   *
+   * @param {HTMLElement} tableElement
+   * @returns {Object}
+   */
+  LanguageModule.buildLanguageTable = function(tableElement) {
+    return $(tableElement).DataTable({
+      dom: 'lrtip',
+      serverSide: false,
+      stateSave: true,
+      paging: false,
+      info: false,
+      ordering: true,
+      columnDefs: [{targets: 4, orderable: false}],
+      language: LanguageModule.labels,
+      order: [[1, 'asc']]
+    });
+  };
+
+  /**
+   * Initialize translation table
+   *
+   * @param {HTMLElement} tableElement
+   * @returns {Object}
+   */
+  LanguageModule.buildTranslationTable = function(tableElement) {
+    var languageCount = $(tableElement).data('languageCount'),
+      columns = [
+        {
+          render: function(data, type, row) {
+            return LanguageModule.buildImage(data.icon, data.title, data.title, data.width, data.height);
+          },
+          width: '20px',
+          orderable: false,
+          targets: 0
+        }, {
+          render: function(data, type, row) {
+            return data.title;
+          },
+          className: LanguageModule.classes.extension,
+          targets: 1
+        }
+      ];
+
+    for (var i = 0; i < languageCount; i++) {
+      columns.push({
+        render: function(data, type, row) {
+          var links = [
+            LanguageModule.buildActionLink('updateTranslation', data, LanguageModule.icons.download),
+            LanguageModule.buildActionLink('removeTranslation', data, LanguageModule.icons.remove),
+            LanguageModule.buildLoadingIndicator(),
+            LanguageModule.buildCompleteIndicator()
+          ];
+          return links.join('');
+        },
+        className: 'dt-center',
+        targets: (i + 2)
+      });
+    }
+
+    return $(tableElement).DataTable({
+      dom: 'lrtip',
+      serverSide: false,
+      stateSave: true,
+      paging: false,
+      info: false,
+      ordering: true,
+      language: LanguageModule.labels,
+      ajax: LanguageModule.settings.listTranslationsUri,
+      order: [[1, 'asc']],
+      columnDefs: columns,
+      createdRow: function(row, data, index) {
+        var $row = $(row);
+        $row.attr('id', LanguageModule.identifiers.extensionPrefix + data[1].key);
+        $row.attr('data-extension', data[1].key);
+      }
+    });
+  };
+
+  /**
+   * Initialize search field
+   */
+  LanguageModule.initializeSearchField = function() {
+    var getVars = LanguageModule.getUrlVars();
+    var currentSearch = (getVars['search'] ? getVars['search'] : LanguageModule.table.search());
+    $(LanguageModule.identifiers.searchField)
+      .val(currentSearch)
+      .on('input', function() {
+        LanguageModule.table.search($(this).val()).draw();
+      })
+      .clearable({
+        onClear: function() {
+          if (LanguageModule.table !== null) {
+            LanguageModule.table.search('').draw();
+          }
+        }
+      })
+      .parents('form').on('submit', function() {
+      return false;
+    });
+  };
+
+  /**
+   * Initialize event handler, redirect clicks to controller actions
+   */
+  LanguageModule.initializeEventHandler = function() {
+    $(document).on('click', function(event) {
+      var $element = $(event.target);
+      var $parent = $element.closest('[data-action]');
+
+      if ($element.data('action') !== undefined) {
+        LanguageModule.handleActionEvent($element, event);
+      } else if ($parent.data('action') !== undefined) {
+        LanguageModule.handleActionEvent($parent, event);
+      }
+    });
+  };
+
+  /**
+   * Initialize buttons
+   */
+  LanguageModule.initializeButtons = function() {
+    LanguageModule.buttons.update = LanguageModule.topMenu.find('.t3js-button-update');
+    LanguageModule.buttons.cancel = LanguageModule.topMenu.find('.t3js-button-cancel');
+  };
+
+  /**
+   * Update buttons in top menu
+   *
+   * @param {String} action
+   */
+  LanguageModule.updateButtonStatus = function(action) {
+    switch (action) {
+      case 'update':
+        LanguageModule.buttons.update.data('action', 'cancelLanguageUpdate');
+        LanguageModule.buttons.cancel.removeClass('disabled');
+        Icons.getIcon('spinner-circle-dark', Icons.sizes.small).done(function(spinner) {
+          LanguageModule.buttons.update.find('span.icon').replaceWith(spinner);
+        });
+        break;
+      case 'cancel':
+        LanguageModule.buttons.update.data('action', 'updateActiveLanguages');
+        LanguageModule.buttons.cancel.addClass('disabled');
+        Icons.getIcon('actions-system-extension-download', Icons.sizes.small).done(function(download) {
+          LanguageModule.buttons.update.find('span.icon').replaceWith(download);
+        });
+        break;
+    }
+  };
+
+  /**
+   * Handler for "action" events
+   *
+   * @param {Object} element
+   * @param {Event} event
+   */
+  LanguageModule.handleActionEvent = function(element, event) {
+    event.preventDefault();
+    var data = element.data();
+    var actionName = data.action + 'Action';
+    if (actionName in LanguageModule) {
+      LanguageModule[actionName](element, data);
+    }
+  };
+
+  /**
+   * Load translations for all extensions by given locale
+   *
+   * @param {String} locale
+   * @param {function} callback
+   * @param {Number} counter
+   */
+  LanguageModule.loadTranslationsByLocale = function(locale, callback, counter) {
+    counter = counter || 0;
+    var data = {locale: locale, count: counter};
+    LanguageModule.executeAjaxRequest(LanguageModule.settings.updateLanguageUri, data, function(response, status) {
+      if (status === 'success' && response.success) {
+        if (parseFloat(response.progress) < 100) {
+          callback('progress', data, response);
+          counter++;
+          LanguageModule.loadTranslationsByLocale(locale, callback, counter);
+        } else {
+          callback('success', data, response);
+        }
+      } else {
+        callback('error', data, response);
+      }
+    });
+  };
+
+  /**
+   * Load translations for all extensions by given rows
+   *
+   * @param {Object} rows
+   * @param {function} callback
+   */
+  LanguageModule.loadTranslationsByRows = function(rows, callback) {
+    if (rows) {
+      rows = $(rows).toArray();
+      var $row = $(rows.shift()),
+        locale = $row.data('locale');
+
+      LanguageModule.loadTranslationsByLocale(locale, function(status, data, response) {
+        callback($row, status, data, response);
+        if (status === 'success') {
+          if (rows.length) {
+            LanguageModule.loadTranslationsByRows(rows, callback);
+          } else {
+            callback($row, 'finished', data, response);
+          }
+        }
+      });
+    }
+  };
+
+  /**
+   * Load translation for one extension by given locale
+   *
+   * @param {String} extension
+   * @param {String} locale
+   * @param {function} callback
+   */
+  LanguageModule.loadTranslationByExtensionAndLocale = function(extension, locale, callback) {
+    var data = {extension: extension, locale: locale};
+    LanguageModule.executeAjaxRequest(LanguageModule.settings.updateTranslationUri, data, function(response, status) {
+      if (status === 'success' && response.success) {
+        callback('success', data, response);
+      } else {
+        callback('error', data, response);
+      }
+    });
+  };
+
+  /**
+   * Execute AJAX request
+   *
+   * @param {String} uri
+   * @param {Object} data
+   * @param {function} callback
+   */
+  LanguageModule.executeAjaxRequest = function(uri, data, callback) {
+    var newData = {};
+    newData[LanguageModule.settings.prefix] = {
+      data: data
+    };
+    LanguageModule.currentRequest = $.ajax({
+      type: 'POST',
+      cache: false,
+      url: uri,
+      data: newData,
+      dataType: 'json',
+      success: function(response, status) {
+        if (typeof callback === 'function') {
+          callback(response, status, '');
+        }
+      },
+      error: function(response, status, error) {
+        if (typeof callback === 'function') {
+          callback(response, status, error);
+        }
+      }
+    });
+  };
+
+  /**
+   * Abort current AJAX request
+   */
+  LanguageModule.abortAjaxRequest = function() {
+    if (LanguageModule.currentRequest) {
+      LanguageModule.userAbortRequest = true;
+      LanguageModule.currentRequest.abort();
+    }
+  };
+
+  /**
+   * Display error flash message
+   *
+   * @param {String} label
+   */
+  LanguageModule.displayError = function(label) {
+    if (LanguageModule.userAbortRequest) {
+      LanguageModule.displaySuccess(LanguageModule.labels.canceled);
+    } else if (typeof label === 'string' && label !== '') {
+      Notification.error(LanguageModule.labels.errorHeader, label);
+    }
+  };
+
+  /**
+   * Display information flash message
+   *
+   * @param {String} label
+   */
+  LanguageModule.displayInformation = function(label) {
+    if (typeof label === 'string' && label !== '') {
+      Notification.info(LanguageModule.labels.infoHeader, label);
+    }
+  };
+
+  /**
+   * Display success flash message
+   *
+   * @param {String} label
+   */
+  LanguageModule.displaySuccess = function(label) {
+    if (typeof label === 'string' && label !== '') {
+      Notification.success(LanguageModule.labels.successHeader, label);
+    }
+  };
+
+  /**
+   * Build action link
+   *
+   * @param {String} action
+   * @param {Object} parameters
+   * @param {String} content
+   * @returns {Object}
+   */
+  LanguageModule.buildActionLink = function(action, parameters, content) {
+    var $link = $('<a>');
+
+    $link.addClass(action + 'Link');
+    $link.attr('data-action', action);
+    for (var name in parameters) {
+      if (parameters.hasOwnProperty(name)) {
+        $link.attr('data-' + name, parameters[name]);
+      }
+    }
+    $link.html(content);
+    return $link.wrap('<span>').parent().html();
+  };
+
+  /**
+   * Build progress bar
+   *
+   * @returns {Object}
+   */
+  LanguageModule.buildProgressBar = function() {
+    var $span = $('<span>');
+    $span.addClass(LanguageModule.classes.progressBar);
+    $span.html(LanguageModule.icons.progressBar);
+    return $span.wrap('<span>').parent().html();
+  };
+
+  /**
+   * Build loading indicator
+   *
+   * @returns {Object}
+   */
+  LanguageModule.buildLoadingIndicator = function() {
+    var $span = $('<span>');
+    $span.addClass(LanguageModule.classes.loading);
+    $span.html(LanguageModule.icons.loading);
+    return $span.wrap('<span>').parent().html();
+  };
+
+  /**
+   * Build complete state indicator
+   *
+   * @returns {Object}
+   */
+  LanguageModule.buildCompleteIndicator = function() {
+    var $span = $('<span>');
+    $span.addClass(LanguageModule.classes.complete);
+    $span.html(LanguageModule.icons.complete);
+    return $span.wrap('<span>').parent().html();
+  };
+
+  /**
+   * Build image
+   *
+   * @param {String} uri
+   * @param {String} alt
+   * @param {String} title
+   * @param {Number} width
+   * @param {Number} heigth
+   * @returns {Object}
+   */
+  LanguageModule.buildImage = function(uri, alt, title, width, heigth) {
+    var $image = $('<img>');
+    $image.attr('src', uri);
+    $image.attr('alt', alt ? alt : '');
+    $image.attr('title', title ? title : '');
+    $image.attr('style', 'width: ' + width + 'px; height: ' + heigth + 'px;');
+    var $span = $('<span>');
+    $span.addClass('typo3-app-icon');
+    $span.attr('style', 'background: none; text-align: center;');
+    $span.html($image);
+    return $span.wrap('<span>').parent().html();
+  };
+
+  /**
+   * Format date
+   *
+   * @param {Number} timestamp
+   * @returns {*}
+   */
+  LanguageModule.formatDate = function(timestamp) {
+    return moment.unix(timestamp).format(LanguageModule.labels.dateFormat);
+  };
+
+  /**
+   * Set progress bar progress
+   *
+   * @param {Object} progressBar
+   * @param {String} progress
+   */
+  LanguageModule.setProgress = function(progressBar, progress) {
+    var $inner = $(LanguageModule.identifiers.progressBarInner, progressBar),
+      $text = $(LanguageModule.identifiers.progressBarText, progressBar);
+    $inner.css({width: progress + '%'});
+    $inner.attr('aria-valuenow', progress);
+    $text.text(Math.round(progress) + '%');
+  };
+
+  /**
+   * Utility method to retrieve query parameters
+   *
+   * @returns {Array}
+   */
+  LanguageModule.getUrlVars = function getUrlVars() {
+    var vars = [], hash;
+    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
+    for (var i = 0; i < hashes.length; i++) {
+      hash = hashes[i].split('=');
+      vars.push(hash[0]);
+      vars[hash[0]] = hash[1];
+    }
+    return vars;
+  };
+
+  $(function() {
+    if ($('#typo3-language-list').length) {
+      LanguageModule.initializeLanguageTable('div.typo3-module-lang', '#typo3-language-list');
+    } else if ($('#typo3-translation-list').length) {
+      LanguageModule.initializeTranslationTable('div.typo3-module-lang', '#typo3-translation-list');
+    }
+  });
+
+  return LanguageModule;
 });
diff --git a/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js b/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js
index 02dca0a6c852..9f130f451c7e 100644
--- a/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js
+++ b/typo3/sysext/lang/Resources/Public/JavaScript/Typo3Lang.js
@@ -15,57 +15,57 @@ Ext.ns('TYPO3.l10n');
 
 TYPO3.l10n = function() {
 
-	/**
-	 * Protected copy of translationUnits
-	 * @private
-	 */
-	var lang = [],
+  /**
+   * Protected copy of translationUnits
+   * @private
+   */
+  var lang = [],
 
-	sanitize = function() {
-		if (typeof TYPO3.lang !== 'undefined') {
-			for (key in TYPO3.lang) {
-				lang[key] = TYPO3.lang[key];
+    sanitize = function() {
+      if (typeof TYPO3.lang !== 'undefined') {
+        for (key in TYPO3.lang) {
+          lang[key] = TYPO3.lang[key];
 
-				if (!Ext.isString(TYPO3.lang[key])) {
-					TYPO3.lang[key] = TYPO3.lang[key][0].target;
-				}
-			}
-		}
-	};
+          if (!Ext.isString(TYPO3.lang[key])) {
+            TYPO3.lang[key] = TYPO3.lang[key][0].target;
+          }
+        }
+      }
+    };
 
-	return {
+  return {
 
-		initialize: function() {
-			sanitize();
-		},
+    initialize: function() {
+      sanitize();
+    },
 
-		localize: function(label, replace, plural) {
-			if (typeof lang === 'undefined' || typeof lang[label] === 'undefined') {
-				return false;
-			}
+    localize: function(label, replace, plural) {
+      if (typeof lang === 'undefined' || typeof lang[label] === 'undefined') {
+        return false;
+      }
 
-			var i = plural || 0,
-					translationUnit = lang[label],
-					label = null, regexp = null;
+      var i = plural || 0,
+        translationUnit = lang[label],
+        label = null, regexp = null;
 
-			// Get localized label
-			if (Ext.isString(translationUnit)) {
-				label = translationUnit;
-			} else {
-				label = translationUnit[i]['target'];
-			}
+      // Get localized label
+      if (Ext.isString(translationUnit)) {
+        label = translationUnit;
+      } else {
+        label = translationUnit[i]['target'];
+      }
 
-			// Replace
-			if (typeof replace !== 'undefined') {
-				for (key in replace) {
-					regexp = new RegExp('%' + key + '|%s');
-					label = label.replace(regexp, replace[key]);
-				}
-			}
+      // Replace
+      if (typeof replace !== 'undefined') {
+        for (key in replace) {
+          regexp = new RegExp('%' + key + '|%s');
+          label = label.replace(regexp, replace[key]);
+        }
+      }
 
-			return label;
-		}
-	};
+      return label;
+    }
+  };
 }();
 
-TYPO3.l10n.initialize();
\ No newline at end of file
+TYPO3.l10n.initialize();
diff --git a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js
index b4578bbe7c81..c166b4f06ea0 100644
--- a/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js
+++ b/typo3/sysext/linkvalidator/Resources/Public/JavaScript/Linkvalidator.js
@@ -15,58 +15,58 @@
  * Module: TYPO3/CMS/Linkvalidator/Linkvalidator
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Linkvalidator/Linkvalidator
-	 */
-	var Linkvalidator = {};
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Linkvalidator/Linkvalidator
+   */
+  var Linkvalidator = {};
 
-	/**
-	 *
-	 * @param {String} prefix
-	 */
-	Linkvalidator.toggleActionButton = function(prefix) {
-		var buttonDisable = true;
-		$('.' + prefix).each(function() {
-			if ($(this).prop('checked')) {
-				buttonDisable = false;
-			}
-		});
+  /**
+   *
+   * @param {String} prefix
+   */
+  Linkvalidator.toggleActionButton = function(prefix) {
+    var buttonDisable = true;
+    $('.' + prefix).each(function() {
+      if ($(this).prop('checked')) {
+        buttonDisable = false;
+      }
+    });
 
-		if (prefix === 'check') {
-			$('#updateLinkList').prop('disabled', buttonDisable);
-		} else {
-			$('#refreshLinkList').prop('disabled', buttonDisable);
-		}
-	};
+    if (prefix === 'check') {
+      $('#updateLinkList').prop('disabled', buttonDisable);
+    } else {
+      $('#refreshLinkList').prop('disabled', buttonDisable);
+    }
+  };
 
-	/**
-	 * Registers listeners
-	 */
-	Linkvalidator.initializeEvents = function() {
-		$('.refresh').on('click', function() {
-			Linkvalidator.toggleActionButton('refresh');
-		});
+  /**
+   * Registers listeners
+   */
+  Linkvalidator.initializeEvents = function() {
+    $('.refresh').on('click', function() {
+      Linkvalidator.toggleActionButton('refresh');
+    });
 
-		$('.check').on('click', function() {
-			Linkvalidator.toggleActionButton('check');
-		});
+    $('.check').on('click', function() {
+      Linkvalidator.toggleActionButton('check');
+    });
 
-		$('.t3js-update-button').on('click', function() {
-			var $element = $(this);
-			var name = $element.attr('name');
-			var message = 'Event triggered';
-			if (name === 'refreshLinkList' || name === 'updateLinkList') {
-				message = $element.data('notification-message');
-			}
-			top.TYPO3.Notification.success(message);
-		});
-	};
+    $('.t3js-update-button').on('click', function() {
+      var $element = $(this);
+      var name = $element.attr('name');
+      var message = 'Event triggered';
+      if (name === 'refreshLinkList' || name === 'updateLinkList') {
+        message = $element.data('notification-message');
+      }
+      top.TYPO3.Notification.success(message);
+    });
+  };
 
-	$(Linkvalidator.initializeEvents);
+  $(Linkvalidator.initializeEvents);
 
-	return Linkvalidator;
+  return Linkvalidator;
 });
diff --git a/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js b/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js
index 1adb83b180bb..7123e823f483 100644
--- a/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js
+++ b/typo3/sysext/lowlevel/Resources/Public/JavaScript/ConfigurationView.js
@@ -18,20 +18,20 @@
  */
 define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
 
-    var $searchFields = $('input[name="searchString"]');
-    var searchResultShown = ('' !== $searchFields.first().val());
+  var $searchFields = $('input[name="searchString"]');
+  var searchResultShown = ('' !== $searchFields.first().val());
 
-    // make search field clearable
-    $searchFields.clearable({
-        onClear: function() {
-            if (searchResultShown) {
-                $(this).closest('form').submit();
-            }
-        }
-    });
-
-    if (self.location.hash) {
-        // scroll page down, so the just opened subtree is visible after reload and not hidden by doc header
-        $("html, body").scrollTop((document.documentElement.scrollTop || document.body.scrollTop) - 80);
+  // make search field clearable
+  $searchFields.clearable({
+    onClear: function() {
+      if (searchResultShown) {
+        $(this).closest('form').submit();
+      }
     }
+  });
+
+  if (self.location.hash) {
+    // scroll page down, so the just opened subtree is visible after reload and not hidden by doc header
+    $("html, body").scrollTop((document.documentElement.scrollTop || document.body.scrollTop) - 80);
+  }
 });
diff --git a/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js b/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js
index 424a53fcfc96..47a00da8362f 100644
--- a/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js
+++ b/typo3/sysext/lowlevel/Resources/Public/JavaScript/QueryGenerator.js
@@ -15,78 +15,78 @@
  * Module: TYPO3/CMS/Lowlevel/QueryGenerator
  * This module handle the QueryGenerator forms.
  */
-define(['jquery', 'TYPO3/CMS/Backend/DateTimePicker', 'TYPO3/CMS/Backend/jquery.clearable'], function ($) {
+define(['jquery', 'TYPO3/CMS/Backend/DateTimePicker', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
 
-	/**
-	 * The QueryGenerator AMD module
-	 *
-	 * @type {{form: null, limitField: null}}
-	 * @exports TYPO3/CMS/Lowlevel/QueryGenerator
-	 */
-	var QueryGenerator = {
-		form: null,
-		limitField: null
-	};
+  /**
+   * The QueryGenerator AMD module
+   *
+   * @type {{form: null, limitField: null}}
+   * @exports TYPO3/CMS/Lowlevel/QueryGenerator
+   */
+  var QueryGenerator = {
+    form: null,
+    limitField: null
+  };
 
-	/**
-	 * Initialize the QueryGenerator object
-	 */
-	QueryGenerator.initialize = function() {
-		QueryGenerator.form = $('form[name="queryform"]');
-		QueryGenerator.limitField = $('#queryLimit');
-		QueryGenerator.form.on('click', '.t3js-submit-click', function(e) {
-			e.preventDefault();
-			QueryGenerator.doSubmit();
-		});
-		QueryGenerator.form.on('change', '.t3js-submit-change', function(e) {
-			e.preventDefault();
-			QueryGenerator.doSubmit();
-		});
-		QueryGenerator.form.on('click', '.t3js-limit-submit button', function(e) {
-			e.preventDefault();
-			QueryGenerator.setLimit($(this).data('value'));
-			QueryGenerator.doSubmit();
-		});
-		QueryGenerator.form.on('click', '.t3js-addfield', function(e) {
-			e.preventDefault();
-			QueryGenerator.addValueToField($(this).data('field'), $(this).val());
-		});
-		QueryGenerator.form.find('.t3js-clearable').clearable({
-			onClear: function() {
-				QueryGenerator.doSubmit();
-			}
-		});
-	};
+  /**
+   * Initialize the QueryGenerator object
+   */
+  QueryGenerator.initialize = function() {
+    QueryGenerator.form = $('form[name="queryform"]');
+    QueryGenerator.limitField = $('#queryLimit');
+    QueryGenerator.form.on('click', '.t3js-submit-click', function(e) {
+      e.preventDefault();
+      QueryGenerator.doSubmit();
+    });
+    QueryGenerator.form.on('change', '.t3js-submit-change', function(e) {
+      e.preventDefault();
+      QueryGenerator.doSubmit();
+    });
+    QueryGenerator.form.on('click', '.t3js-limit-submit button', function(e) {
+      e.preventDefault();
+      QueryGenerator.setLimit($(this).data('value'));
+      QueryGenerator.doSubmit();
+    });
+    QueryGenerator.form.on('click', '.t3js-addfield', function(e) {
+      e.preventDefault();
+      QueryGenerator.addValueToField($(this).data('field'), $(this).val());
+    });
+    QueryGenerator.form.find('.t3js-clearable').clearable({
+      onClear: function() {
+        QueryGenerator.doSubmit();
+      }
+    });
+  };
 
-	/**
-	 * Submit the form
-	 */
-	QueryGenerator.doSubmit = function() {
-		QueryGenerator.form.submit();
-	};
+  /**
+   * Submit the form
+   */
+  QueryGenerator.doSubmit = function() {
+    QueryGenerator.form.submit();
+  };
 
-	/**
-	 * Set query limit
-	 *
-	 * @param {String} value
-	 */
-	QueryGenerator.setLimit = function(value) {
-		QueryGenerator.limitField.val(value);
-	};
+  /**
+   * Set query limit
+   *
+   * @param {String} value
+   */
+  QueryGenerator.setLimit = function(value) {
+    QueryGenerator.limitField.val(value);
+  };
 
-	/**
-	 * Add value to text field
-	 *
-	 * @param {String} field the name of the field
-	 * @param {String} value the value to add
-	 */
-	QueryGenerator.addValueToField = function(field, value) {
-		var $target = QueryGenerator.form.find('[name="' + field + '"]');
-		var currentValue = $target.val();
-		$target.val(currentValue + ',' + value);
-	};
+  /**
+   * Add value to text field
+   *
+   * @param {String} field the name of the field
+   * @param {String} value the value to add
+   */
+  QueryGenerator.addValueToField = function(field, value) {
+    var $target = QueryGenerator.form.find('[name="' + field + '"]');
+    var currentValue = $target.val();
+    $target.val(currentValue + ',' + value);
+  };
 
-	// Initialize
-	QueryGenerator.initialize();
-	return QueryGenerator;
+  // Initialize
+  QueryGenerator.initialize();
+  return QueryGenerator;
 });
diff --git a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js
index a690a23bf46d..e294f55f64ba 100644
--- a/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js
+++ b/typo3/sysext/opendocs/Resources/Public/JavaScript/Toolbar/OpendocsMenu.js
@@ -18,112 +18,112 @@
  *  - updating the menu
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Icons',
-	'TYPO3/CMS/Backend/Viewport'
+  'jquery',
+  'TYPO3/CMS/Backend/Icons',
+  'TYPO3/CMS/Backend/Viewport'
 ], function($, Icons, Viewport) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{options: {containerSelector: string, hashDataAttributeName: string, closeSelector: string, menuContainerSelector: string, toolbarIconSelector: string, openDocumentsItemsSelector: string, counterSelector: string}}}
-	 * @exports TYPO3/CMS/Opendocs/OpendocsMenu
-	 */
-	var OpendocsMenu = {
-		options: {
-			containerSelector: '#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem',
-			hashDataAttributeName: 'opendocsidentifier',
-			closeSelector: '.t3js-topbar-opendocs-close',
-			menuContainerSelector: '.dropdown-menu',
-			toolbarIconSelector: '.toolbar-item-icon .t3js-icon',
-			openDocumentsItemsSelector: '.t3js-topbar-opendocs-item',
-			counterSelector: '#tx-opendocs-counter'
-		}
-	};
+  /**
+   *
+   * @type {{options: {containerSelector: string, hashDataAttributeName: string, closeSelector: string, menuContainerSelector: string, toolbarIconSelector: string, openDocumentsItemsSelector: string, counterSelector: string}}}
+   * @exports TYPO3/CMS/Opendocs/OpendocsMenu
+   */
+  var OpendocsMenu = {
+    options: {
+      containerSelector: '#typo3-cms-opendocs-backend-toolbaritems-opendocstoolbaritem',
+      hashDataAttributeName: 'opendocsidentifier',
+      closeSelector: '.t3js-topbar-opendocs-close',
+      menuContainerSelector: '.dropdown-menu',
+      toolbarIconSelector: '.toolbar-item-icon .t3js-icon',
+      openDocumentsItemsSelector: '.t3js-topbar-opendocs-item',
+      counterSelector: '#tx-opendocs-counter'
+    }
+  };
 
-	/**
-	 * register event handlers
-	 */
-	OpendocsMenu.initializeEvents = function() {
-		// send a request when removing an opendoc
-		$(OpendocsMenu.options.containerSelector).on('click', OpendocsMenu.options.closeSelector, function(evt) {
-			evt.preventDefault();
-			var md5 = $(this).data(OpendocsMenu.options.hashDataAttributeName);
-			if (md5) {
-				OpendocsMenu.closeDocument(md5);
-			}
-		});
-	};
+  /**
+   * register event handlers
+   */
+  OpendocsMenu.initializeEvents = function() {
+    // send a request when removing an opendoc
+    $(OpendocsMenu.options.containerSelector).on('click', OpendocsMenu.options.closeSelector, function(evt) {
+      evt.preventDefault();
+      var md5 = $(this).data(OpendocsMenu.options.hashDataAttributeName);
+      if (md5) {
+        OpendocsMenu.closeDocument(md5);
+      }
+    });
+  };
 
-	/**
-	 * Displays the menu and does the AJAX call to the TYPO3 backend
-	 */
-	OpendocsMenu.updateMenu = function() {
-		var $toolbarItemIcon = $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector),
-			$existingIcon = $toolbarItemIcon.clone();
+  /**
+   * Displays the menu and does the AJAX call to the TYPO3 backend
+   */
+  OpendocsMenu.updateMenu = function() {
+    var $toolbarItemIcon = $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector),
+      $existingIcon = $toolbarItemIcon.clone();
 
-		Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
-			$toolbarItemIcon.replaceWith(spinner);
-		});
+    Icons.getIcon('spinner-circle-light', Icons.sizes.small).done(function(spinner) {
+      $toolbarItemIcon.replaceWith(spinner);
+    });
 
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['opendocs_menu'],
-			type: 'post',
-			cache: false,
-			success: function(data) {
-				$(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.menuContainerSelector).html(data);
-				OpendocsMenu.updateNumberOfDocs();
-				$(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector).replaceWith($existingIcon);
-			}
-		});
-	};
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['opendocs_menu'],
+      type: 'post',
+      cache: false,
+      success: function(data) {
+        $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.menuContainerSelector).html(data);
+        OpendocsMenu.updateNumberOfDocs();
+        $(OpendocsMenu.options.toolbarIconSelector, OpendocsMenu.options.containerSelector).replaceWith($existingIcon);
+      }
+    });
+  };
 
-	/**
-	 * Updates the number of open documents in the toolbar according to the
-	 * number of items in the menu bar.
-	 */
-	OpendocsMenu.updateNumberOfDocs = function() {
-		var num = $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.openDocumentsItemsSelector).length;
-		$(OpendocsMenu.options.counterSelector).text(num).toggle(num > 0);
-	};
+  /**
+   * Updates the number of open documents in the toolbar according to the
+   * number of items in the menu bar.
+   */
+  OpendocsMenu.updateNumberOfDocs = function() {
+    var num = $(OpendocsMenu.options.containerSelector).find(OpendocsMenu.options.openDocumentsItemsSelector).length;
+    $(OpendocsMenu.options.counterSelector).text(num).toggle(num > 0);
+  };
 
-	/**
-	 * Closes an open document
-	 *
-	 * @param {String} md5sum
-	 */
-	OpendocsMenu.closeDocument = function(md5sum) {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['opendocs_closedoc'],
-			type: 'post',
-			cache: false,
-			data: {
-				md5sum: md5sum
-			},
-			success: function(data) {
-				$(OpendocsMenu.options.menuContainerSelector, OpendocsMenu.options.containerSelector).html(data);
-				OpendocsMenu.updateNumberOfDocs();
-				// Re-open the menu after closing a document
-				$(OpendocsMenu.options.containerSelector).toggleClass('open');
-			}
-		});
-	};
+  /**
+   * Closes an open document
+   *
+   * @param {String} md5sum
+   */
+  OpendocsMenu.closeDocument = function(md5sum) {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['opendocs_closedoc'],
+      type: 'post',
+      cache: false,
+      data: {
+        md5sum: md5sum
+      },
+      success: function(data) {
+        $(OpendocsMenu.options.menuContainerSelector, OpendocsMenu.options.containerSelector).html(data);
+        OpendocsMenu.updateNumberOfDocs();
+        // Re-open the menu after closing a document
+        $(OpendocsMenu.options.containerSelector).toggleClass('open');
+      }
+    });
+  };
 
-	/**
-	 * closes the menu (e.g. when clicked on an item)
-	 */
-	OpendocsMenu.toggleMenu = function() {
-		$('.scaffold').removeClass('scaffold-toolbar-expanded');
-		$(OpendocsMenu.options.containerSelector).toggleClass('open');
-	};
+  /**
+   * closes the menu (e.g. when clicked on an item)
+   */
+  OpendocsMenu.toggleMenu = function() {
+    $('.scaffold').removeClass('scaffold-toolbar-expanded');
+    $(OpendocsMenu.options.containerSelector).toggleClass('open');
+  };
 
-	Viewport.Topbar.Toolbar.registerEvent(function() {
-		OpendocsMenu.initializeEvents();
-		OpendocsMenu.updateMenu();
-	});
+  Viewport.Topbar.Toolbar.registerEvent(function() {
+    OpendocsMenu.initializeEvents();
+    OpendocsMenu.updateMenu();
+  });
 
-	// expose to global
-	TYPO3.OpendocsMenu = OpendocsMenu;
+  // expose to global
+  TYPO3.OpendocsMenu = OpendocsMenu;
 
-	return OpendocsMenu;
+  return OpendocsMenu;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js
index faf54e68f3b6..2ab2f5ebdc5e 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseDatabase.js
@@ -17,30 +17,30 @@
  * @exports TYPO3/CMS/Recordlist/BrowseDatabase
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser'], function($, ElementBrowser) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		$('[data-close]').on('click', function(event) {
-			event.preventDefault();
-			var data = $(this).parents('span').data();
+  $(function() {
+    $('[data-close]').on('click', function(event) {
+      event.preventDefault();
+      var data = $(this).parents('span').data();
 
-			ElementBrowser.insertElement(
-				data.table,
-				data.uid,
-				'db',
-				data.title,
-				'',
-				'',
-				data.icon,
-				'',
-				$(this).data('close')
-			);
-		});
+      ElementBrowser.insertElement(
+        data.table,
+        data.uid,
+        'db',
+        data.title,
+        '',
+        '',
+        data.icon,
+        '',
+        $(this).data('close')
+      );
+    });
 
-		// adjust searchbox layout
-		var searchbox = document.getElementById('db_list-searchbox-toolbar');
-		searchbox.style.display = 'block';
-		searchbox.style.position = 'relative';
-	});
+    // adjust searchbox layout
+    var searchbox = document.getElementById('db_list-searchbox-toolbar');
+    searchbox.style.display = 'block';
+    searchbox.style.position = 'relative';
+  });
 
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js
index e3da67d73bbd..1c1df55b59ca 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFiles.js
@@ -16,96 +16,96 @@
  * File selection
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/LegacyTree'], function($, ElementBrowser, Tree) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{elements: {}}}
-	 * @exports TYPO3/CMS/Recordlist/BrowseFiles
-	 */
-	var BrowseFiles = {
-		elements: {}
-	};
+  /**
+   *
+   * @type {{elements: {}}}
+   * @exports TYPO3/CMS/Recordlist/BrowseFiles
+   */
+  var BrowseFiles = {
+    elements: {}
+  };
 
-	/**
-	 * when selecting one or multiple files, this action is called
-	 *
-	 * @type {{insertElement: Function, insertElementMultiple: Function}}
-	 */
-	BrowseFiles.File = {
-		insertElement: function(index, close) {
-			var result = false;
-			if (typeof BrowseFiles.elements[index] !== 'undefined') {
-				var element = BrowseFiles.elements[index];
-				result = ElementBrowser.insertElement(element.table, element.uid, element.type, element.fileName, element.filePath, element.fileExt, element.fileIcon, '', close);
-			}
-			return result;
-		},
-		insertElementMultiple: function(list) {
-			var uidList = [];
-			for (var i = 0, n = list.length; i < n; i++) {
-				if (typeof BrowseFiles.elements[list[i]] !== 'undefined') {
-					var element = BrowseFiles.elements[list[i]];
-					uidList.push(element.uid);
-				}
-			}
-			ElementBrowser.insertMultiple('sys_file', uidList);
-		}
-	};
+  /**
+   * when selecting one or multiple files, this action is called
+   *
+   * @type {{insertElement: Function, insertElementMultiple: Function}}
+   */
+  BrowseFiles.File = {
+    insertElement: function(index, close) {
+      var result = false;
+      if (typeof BrowseFiles.elements[index] !== 'undefined') {
+        var element = BrowseFiles.elements[index];
+        result = ElementBrowser.insertElement(element.table, element.uid, element.type, element.fileName, element.filePath, element.fileExt, element.fileIcon, '', close);
+      }
+      return result;
+    },
+    insertElementMultiple: function(list) {
+      var uidList = [];
+      for (var i = 0, n = list.length; i < n; i++) {
+        if (typeof BrowseFiles.elements[list[i]] !== 'undefined') {
+          var element = BrowseFiles.elements[list[i]];
+          uidList.push(element.uid);
+        }
+      }
+      ElementBrowser.insertMultiple('sys_file', uidList);
+    }
+  };
 
-	/**
-	 * Selector when using "Import selection" and "Toggle selection"
-	 */
-	BrowseFiles.Selector = {
-		// Toggle selection button is pressed
-		toggle: function(e) {
-			e.preventDefault();
-			var items = BrowseFiles.Selector.getItems();
-			if (items.length) {
-				items.each(function(position, item) {
-					item.checked = (item.checked ? null : 'checked');
-				});
-			}
-		},
-		// Import selection button is pressed
-		handle: function(e) {
-			e.preventDefault();
-			var items = BrowseFiles.Selector.getItems();
-			var selectedItems = [];
-			if (items.length) {
-				items.each(function(position, item) {
-					if (item.checked && item.name) {
-						selectedItems.push(item.name);
-					}
-				});
-				if (selectedItems.length > 0) {
-					if (ElementBrowser.hasActionMultipleCode) {
-						BrowseFiles.File.insertElementMultiple(selectedItems);
-					} else {
-						for (var i = 0; i < selectedItems.length; i++) {
-							BrowseFiles.File.insertElement(selectedItems[i]);
-						}
-					}
-				}
-				ElementBrowser.focusOpenerAndClose(true);
-			}
-		},
-		getItems: function() {
-			return $('#typo3-filelist').find('.typo3-bulk-item');
-		}
-	};
+  /**
+   * Selector when using "Import selection" and "Toggle selection"
+   */
+  BrowseFiles.Selector = {
+    // Toggle selection button is pressed
+    toggle: function(e) {
+      e.preventDefault();
+      var items = BrowseFiles.Selector.getItems();
+      if (items.length) {
+        items.each(function(position, item) {
+          item.checked = (item.checked ? null : 'checked');
+        });
+      }
+    },
+    // Import selection button is pressed
+    handle: function(e) {
+      e.preventDefault();
+      var items = BrowseFiles.Selector.getItems();
+      var selectedItems = [];
+      if (items.length) {
+        items.each(function(position, item) {
+          if (item.checked && item.name) {
+            selectedItems.push(item.name);
+          }
+        });
+        if (selectedItems.length > 0) {
+          if (ElementBrowser.hasActionMultipleCode) {
+            BrowseFiles.File.insertElementMultiple(selectedItems);
+          } else {
+            for (var i = 0; i < selectedItems.length; i++) {
+              BrowseFiles.File.insertElement(selectedItems[i]);
+            }
+          }
+        }
+        ElementBrowser.focusOpenerAndClose(true);
+      }
+    },
+    getItems: function() {
+      return $('#typo3-filelist').find('.typo3-bulk-item');
+    }
+  };
 
-	$(function() {
-		$.extend(BrowseFiles.elements, $('body').data('elements'));
+  $(function() {
+    $.extend(BrowseFiles.elements, $('body').data('elements'));
 
-		$('[data-close]').on('click', function (e) {
-			e.preventDefault();
-			BrowseFiles.File.insertElement('file_' + $(this).data('fileIndex'), $(this).data('close'));
-		});
+    $('[data-close]').on('click', function(e) {
+      e.preventDefault();
+      BrowseFiles.File.insertElement('file_' + $(this).data('fileIndex'), $(this).data('close'));
+    });
 
-		$('#t3js-importSelection').on('click', BrowseFiles.Selector.handle);
-		$('#t3js-toggleSelection').on('click', BrowseFiles.Selector.toggle);
-	});
+    $('#t3js-importSelection').on('click', BrowseFiles.Selector.handle);
+    $('#t3js-toggleSelection').on('click', BrowseFiles.Selector.toggle);
+  });
 
-	return BrowseFiles;
+  return BrowseFiles;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js
index e149e294ec88..1b73340a7b4a 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/BrowseFolders.js
@@ -16,21 +16,21 @@
  * Folder selection
  * @exports TYPO3/CMS/Recordlist/BrowseFolders
  */
-define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function ($, ElementBrowser, Modal, Severity) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Recordlist/ElementBrowser', 'TYPO3/CMS/Backend/Modal', 'TYPO3/CMS/Backend/Severity'], function($, ElementBrowser, Modal, Severity) {
+  'use strict';
 
-	$(function() {
-		$('[data-folder-id]').on('click', function (event) {
-			event.preventDefault();
-			var folderId = $(this).data('folderId');
-			var close = $(this).data('close');
-			ElementBrowser.insertElement('', folderId, 'folder', folderId, folderId, '', '', '', close);
-		});
+  $(function() {
+    $('[data-folder-id]').on('click', function(event) {
+      event.preventDefault();
+      var folderId = $(this).data('folderId');
+      var close = $(this).data('close');
+      ElementBrowser.insertElement('', folderId, 'folder', folderId, folderId, '', '', '', close);
+    });
 
-		$('.t3js-folderIdError').on('click', function (event) {
-			event.preventDefault();
-			Modal.confirm('', $(this).data('message'), Severity.error, [], []);
-		});
-	});
+    $('.t3js-folderIdError').on('click', function(event) {
+      event.preventDefault();
+      Modal.confirm('', $(this).data('message'), Severity.error, [], []);
+    });
+  });
 
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js
index 114f4c8f5976..2f4cd6c2a65c 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/ElementBrowser.js
@@ -16,263 +16,263 @@
  * ElementBrowser communication with parent windows
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Modal'
+  'jquery',
+  'TYPO3/CMS/Backend/Modal'
 ], function($, Modal) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{thisScriptUrl: string, mode: string, formFieldName: string, hasActionMultipleCode: boolean, fieldReference: string, fieldReferenceSlashed: string, rte: {parameters: string, configuration: string}, irre: {objectId: number, checkUniqueAction: string, addAction: string, insertAction: string}}}
-	 * @exports TYPO3/CMS/Recordlist/ElementBrowser
-	 */
-	var ElementBrowser = {
-		thisScriptUrl: '',
-		mode: '',
-		formFieldName: '',
-		hasActionMultipleCode: false,
-		fieldReference: '',
-		fieldReferenceSlashed: '',
-		rte: {
-			parameters: '',
-			configuration: ''
-		},
-		irre: {
-			objectId: 0,
-			checkUniqueAction: '',
-			addAction: '',
-			insertAction: ''
-		}
-	};
+  /**
+   *
+   * @type {{thisScriptUrl: string, mode: string, formFieldName: string, hasActionMultipleCode: boolean, fieldReference: string, fieldReferenceSlashed: string, rte: {parameters: string, configuration: string}, irre: {objectId: number, checkUniqueAction: string, addAction: string, insertAction: string}}}
+   * @exports TYPO3/CMS/Recordlist/ElementBrowser
+   */
+  var ElementBrowser = {
+    thisScriptUrl: '',
+    mode: '',
+    formFieldName: '',
+    hasActionMultipleCode: false,
+    fieldReference: '',
+    fieldReferenceSlashed: '',
+    rte: {
+      parameters: '',
+      configuration: ''
+    },
+    irre: {
+      objectId: 0,
+      checkUniqueAction: '',
+      addAction: '',
+      insertAction: ''
+    }
+  };
 
-	/**
-	 *
-	 * @returns {Boolean}
-	 */
-	ElementBrowser.setReferences = function() {
-		if (
-			ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform
-			&& ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName]
-		) {
-			ElementBrowser.targetDoc = ElementBrowser.getParent().content.document;
-			ElementBrowser.elRef = ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName];
-			return true;
-		} else {
-			return false;
-		}
-	};
+  /**
+   *
+   * @returns {Boolean}
+   */
+  ElementBrowser.setReferences = function() {
+    if (
+      ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform
+      && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName]
+    ) {
+      ElementBrowser.targetDoc = ElementBrowser.getParent().content.document;
+      ElementBrowser.elRef = ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName];
+      return true;
+    } else {
+      return false;
+    }
+  };
 
-	/**
-	 * Dynamically calls a function on a given context object.
-	 *
-	 * @param {String} functionName e.g. "inline.somefunc"
-	 * @param {Object} context e.g. window
-	 * @returns {*}
-	 */
-	ElementBrowser.executeFunctionByName = function(functionName, context /*, args */) {
-		var args = Array.prototype.slice.call(arguments, 2);
-		var namespaces = functionName.split(".");
-		var func = namespaces.pop();
-		for (var i = 0; i < namespaces.length; i++) {
-			context = context[namespaces[i]];
-		}
-		return context[func].apply(context, args);
-	};
+  /**
+   * Dynamically calls a function on a given context object.
+   *
+   * @param {String} functionName e.g. "inline.somefunc"
+   * @param {Object} context e.g. window
+   * @returns {*}
+   */
+  ElementBrowser.executeFunctionByName = function(functionName, context /*, args */) {
+    var args = Array.prototype.slice.call(arguments, 2);
+    var namespaces = functionName.split(".");
+    var func = namespaces.pop();
+    for (var i = 0; i < namespaces.length; i++) {
+      context = context[namespaces[i]];
+    }
+    return context[func].apply(context, args);
+  };
 
-	/**
-	 * Returns the parent document object
-	 */
-	ElementBrowser.getParent = function() {
-		var opener = null;
-		if (
-			typeof window.parent !== 'undefined' &&
-			typeof window.parent.document.list_frame !== 'undefined' &&
-			window.parent.document.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null
-		) {
-			opener = window.parent.document.list_frame;
-		} else if (
-			typeof window.parent !== 'undefined' &&
-			typeof window.parent.frames.list_frame !== 'undefined' &&
-			window.parent.frames.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null
-		) {
-			opener = window.parent.frames.list_frame;
-		} else if (
-			typeof window.frames !== 'undefined' &&
-			typeof window.frames.frameElement !== 'undefined' &&
-			window.frames.frameElement !== null &&
-			window.frames.frameElement.classList.contains('t3js-modal-iframe')
-		) {
-			opener = window.frames.frameElement.contentWindow.parent;
-		} else if (window.opener) {
-			opener = window.opener;
-		}
-		return opener;
-	};
+  /**
+   * Returns the parent document object
+   */
+  ElementBrowser.getParent = function() {
+    var opener = null;
+    if (
+      typeof window.parent !== 'undefined' &&
+      typeof window.parent.document.list_frame !== 'undefined' &&
+      window.parent.document.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null
+    ) {
+      opener = window.parent.document.list_frame;
+    } else if (
+      typeof window.parent !== 'undefined' &&
+      typeof window.parent.frames.list_frame !== 'undefined' &&
+      window.parent.frames.list_frame.parent.document.querySelector('.t3js-modal-iframe') !== null
+    ) {
+      opener = window.parent.frames.list_frame;
+    } else if (
+      typeof window.frames !== 'undefined' &&
+      typeof window.frames.frameElement !== 'undefined' &&
+      window.frames.frameElement !== null &&
+      window.frames.frameElement.classList.contains('t3js-modal-iframe')
+    ) {
+      opener = window.frames.frameElement.contentWindow.parent;
+    } else if (window.opener) {
+      opener = window.opener;
+    }
+    return opener;
+  };
 
-	/**
-	 *
-	 * @param {String} table
-	 * @param {Number} uid
-	 * @param {String} type
-	 * @param {String} filename
-	 * @param {String} fp
-	 * @param {String} filetype
-	 * @param {String} imagefile
-	 * @param {String} action
-	 * @param {String} close
-	 * @returns {Boolean}
-	 */
-	ElementBrowser.insertElement = function(table, uid, type, filename, fp, filetype, imagefile, action, close) {
-		var performAction = true;
+  /**
+   *
+   * @param {String} table
+   * @param {Number} uid
+   * @param {String} type
+   * @param {String} filename
+   * @param {String} fp
+   * @param {String} filetype
+   * @param {String} imagefile
+   * @param {String} action
+   * @param {String} close
+   * @returns {Boolean}
+   */
+  ElementBrowser.insertElement = function(table, uid, type, filename, fp, filetype, imagefile, action, close) {
+    var performAction = true;
 
-		// Call a check function in the opener window (e.g. for uniqueness handling):
-		if (ElementBrowser.irre.objectId && ElementBrowser.irre.checkUniqueAction) {
-			if (ElementBrowser.getParent()) {
-				var res = ElementBrowser.executeFunctionByName(ElementBrowser.irre.checkUniqueAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type);
-				if (!res.passed) {
-					if (res.message) {
-						alert(res.message);
-					}
-					performAction = false;
-				}
-			} else {
-				alert("Error - reference to main window is not set properly!");
-				ElementBrowser.focusOpenerAndClose();
-			}
-		}
-		// Call performing function and finish this action:
-		if (performAction) {
-			// Call helper function to manage data in the opener window:
-			if (ElementBrowser.irre.objectId && ElementBrowser.irre.addAction) {
-				if (ElementBrowser.getParent()) {
-					ElementBrowser.executeFunctionByName(ElementBrowser.irre.addAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type, ElementBrowser.fieldReferenceSlashed);
-				} else {
-					alert("Error - reference to main window is not set properly!");
-					ElementBrowser.focusOpenerAndClose();
-				}
-			}
-			if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) {
-				if (ElementBrowser.getParent()) {
-					ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type);
-					if (close) {
-						ElementBrowser.focusOpenerAndClose();
-					}
-				} else {
-					alert("Error - reference to main window is not set properly!");
-					if (close) {
-						ElementBrowser.focusOpenerAndClose();
-					}
-				}
-			} else if (ElementBrowser.fieldReference && !ElementBrowser.rte.parameters && !ElementBrowser.rte.configuration) {
-				ElementBrowser.addElement(filename, table + "_" + uid, fp, close);
-			} else {
-				if (
-					ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform
-					&& ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName]
-				) {
-					ElementBrowser.getParent().group_change(
-						"add",
-						ElementBrowser.fieldReference,
-						ElementBrowser.rte.parameters,
-						ElementBrowser.rte.configuration,
-						ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName],
-						ElementBrowser.getParent().content.document
-					);
-				} else {
-					alert("Error - reference to main window is not set properly!");
-				}
-				if (close) {
-					ElementBrowser.focusOpenerAndClose();
-				}
-			}
-		}
-		return false;
-	};
+    // Call a check function in the opener window (e.g. for uniqueness handling):
+    if (ElementBrowser.irre.objectId && ElementBrowser.irre.checkUniqueAction) {
+      if (ElementBrowser.getParent()) {
+        var res = ElementBrowser.executeFunctionByName(ElementBrowser.irre.checkUniqueAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type);
+        if (!res.passed) {
+          if (res.message) {
+            alert(res.message);
+          }
+          performAction = false;
+        }
+      } else {
+        alert("Error - reference to main window is not set properly!");
+        ElementBrowser.focusOpenerAndClose();
+      }
+    }
+    // Call performing function and finish this action:
+    if (performAction) {
+      // Call helper function to manage data in the opener window:
+      if (ElementBrowser.irre.objectId && ElementBrowser.irre.addAction) {
+        if (ElementBrowser.getParent()) {
+          ElementBrowser.executeFunctionByName(ElementBrowser.irre.addAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type, ElementBrowser.fieldReferenceSlashed);
+        } else {
+          alert("Error - reference to main window is not set properly!");
+          ElementBrowser.focusOpenerAndClose();
+        }
+      }
+      if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) {
+        if (ElementBrowser.getParent()) {
+          ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction, ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type);
+          if (close) {
+            ElementBrowser.focusOpenerAndClose();
+          }
+        } else {
+          alert("Error - reference to main window is not set properly!");
+          if (close) {
+            ElementBrowser.focusOpenerAndClose();
+          }
+        }
+      } else if (ElementBrowser.fieldReference && !ElementBrowser.rte.parameters && !ElementBrowser.rte.configuration) {
+        ElementBrowser.addElement(filename, table + "_" + uid, fp, close);
+      } else {
+        if (
+          ElementBrowser.getParent() && ElementBrowser.getParent().content && ElementBrowser.getParent().content.document.editform
+          && ElementBrowser.getParent().content.document.editform[ElementBrowser.formFieldName]
+        ) {
+          ElementBrowser.getParent().group_change(
+            "add",
+            ElementBrowser.fieldReference,
+            ElementBrowser.rte.parameters,
+            ElementBrowser.rte.configuration,
+            ElementBrowser.targetDoc.editform[ElementBrowser.formFieldName],
+            ElementBrowser.getParent().content.document
+          );
+        } else {
+          alert("Error - reference to main window is not set properly!");
+        }
+        if (close) {
+          ElementBrowser.focusOpenerAndClose();
+        }
+      }
+    }
+    return false;
+  };
 
-	/**
-	 *
-	 * @param {String} table
-	 * @param {Number} uid
-	 * @returns {Boolean}
-	 */
-	ElementBrowser.insertMultiple = function(table, uid) {
-		var type = "";
-		if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) {
-			// Call helper function to manage data in the opener window:
-			if (ElementBrowser.getParent()) {
-				ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction + 'Multiple', ElementBrowser.getParent(), ElementBrowser.irre.objectId, table ,uid, type, ElementBrowser.fieldReference);
-			} else {
-				alert("Error - reference to main window is not set properly!");
-				ElementBrowser.focusOpenerAndClose();
-			}
-		}
-		return false;
-	};
+  /**
+   *
+   * @param {String} table
+   * @param {Number} uid
+   * @returns {Boolean}
+   */
+  ElementBrowser.insertMultiple = function(table, uid) {
+    var type = "";
+    if (ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction) {
+      // Call helper function to manage data in the opener window:
+      if (ElementBrowser.getParent()) {
+        ElementBrowser.executeFunctionByName(ElementBrowser.irre.insertAction + 'Multiple', ElementBrowser.getParent(), ElementBrowser.irre.objectId, table, uid, type, ElementBrowser.fieldReference);
+      } else {
+        alert("Error - reference to main window is not set properly!");
+        ElementBrowser.focusOpenerAndClose();
+      }
+    }
+    return false;
+  };
 
-	/**
-	 *
-	 * @param {String} elName
-	 * @param {String} elValue
-	 * @param {String} altElValue
-	 * @param {String} close
-	 */
-	ElementBrowser.addElement = function(elName, elValue, altElValue, close) {
-		if (ElementBrowser.getParent() && ElementBrowser.getParent().setFormValueFromBrowseWin) {
-			ElementBrowser.getParent().setFormValueFromBrowseWin(ElementBrowser.fieldReference, altElValue ? altElValue : elValue, elName);
-			if (close) {
-				ElementBrowser.focusOpenerAndClose();
-			}
-		} else {
-			alert("Error - reference to main window is not set properly!");
-			ElementBrowser.focusOpenerAndClose();
-		}
-	};
+  /**
+   *
+   * @param {String} elName
+   * @param {String} elValue
+   * @param {String} altElValue
+   * @param {String} close
+   */
+  ElementBrowser.addElement = function(elName, elValue, altElValue, close) {
+    if (ElementBrowser.getParent() && ElementBrowser.getParent().setFormValueFromBrowseWin) {
+      ElementBrowser.getParent().setFormValueFromBrowseWin(ElementBrowser.fieldReference, altElValue ? altElValue : elValue, elName);
+      if (close) {
+        ElementBrowser.focusOpenerAndClose();
+      }
+    } else {
+      alert("Error - reference to main window is not set properly!");
+      ElementBrowser.focusOpenerAndClose();
+    }
+  };
 
-	/**
-	 *
-	 */
-	ElementBrowser.focusOpenerAndClose = function() {
-		if (ElementBrowser.getParent()) {
-			ElementBrowser.getParent().focus();
-		}
-		Modal.dismiss();
-		close();
-	};
+  /**
+   *
+   */
+  ElementBrowser.focusOpenerAndClose = function() {
+    if (ElementBrowser.getParent()) {
+      ElementBrowser.getParent().focus();
+    }
+    Modal.dismiss();
+    close();
+  };
 
-	$(function() {
-		var data = $('body').data();
+  $(function() {
+    var data = $('body').data();
 
-		ElementBrowser.thisScriptUrl = data.thisScriptUrl;
-		ElementBrowser.mode = data.mode;
-		ElementBrowser.formFieldName = data.formFieldName;
-		ElementBrowser.fieldReference = data.fieldReference;
-		ElementBrowser.fieldReferenceSlashed = data.fieldReferenceSlashed;
-		ElementBrowser.rte.parameters = data.rteParameters;
-		ElementBrowser.rte.configuration = data.rteConfiguration;
-		ElementBrowser.irre.checkUniqueAction = data.irreCheckUniqueAction;
-		ElementBrowser.irre.addAction = data.irreAddAction;
-		ElementBrowser.irre.insertAction = data.irreInsertAction;
-		ElementBrowser.irre.objectId = data.irreObjectId;
-		ElementBrowser.hasActionMultipleCode = ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction;
-	});
+    ElementBrowser.thisScriptUrl = data.thisScriptUrl;
+    ElementBrowser.mode = data.mode;
+    ElementBrowser.formFieldName = data.formFieldName;
+    ElementBrowser.fieldReference = data.fieldReference;
+    ElementBrowser.fieldReferenceSlashed = data.fieldReferenceSlashed;
+    ElementBrowser.rte.parameters = data.rteParameters;
+    ElementBrowser.rte.configuration = data.rteConfiguration;
+    ElementBrowser.irre.checkUniqueAction = data.irreCheckUniqueAction;
+    ElementBrowser.irre.addAction = data.irreAddAction;
+    ElementBrowser.irre.insertAction = data.irreInsertAction;
+    ElementBrowser.irre.objectId = data.irreObjectId;
+    ElementBrowser.hasActionMultipleCode = ElementBrowser.irre.objectId && ElementBrowser.irre.insertAction;
+  });
 
-	/**
-	 * Global jumpTo function
-	 *
-	 * Used by tree implementation
-	 *
-	 * @param {String} URL
-	 * @param {String} anchor
-	 * @returns {Boolean}
-	 */
-	window.jumpToUrl = function(URL, anchor) {
-		if (URL.charAt(0) === '?') {
-			URL = ElementBrowser.thisScriptUrl + URL.substring(1);
-		}
-		var add_mode = URL.indexOf("mode=") === -1 ? '&mode=' + encodeURIComponent(ElementBrowser.mode) : "";
-		window.location.href = URL + add_mode + (typeof(anchor) === "string" ? anchor : '');
-		return false;
-	};
+  /**
+   * Global jumpTo function
+   *
+   * Used by tree implementation
+   *
+   * @param {String} URL
+   * @param {String} anchor
+   * @returns {Boolean}
+   */
+  window.jumpToUrl = function(URL, anchor) {
+    if (URL.charAt(0) === '?') {
+      URL = ElementBrowser.thisScriptUrl + URL.substring(1);
+    }
+    var add_mode = URL.indexOf("mode=") === -1 ? '&mode=' + encodeURIComponent(ElementBrowser.mode) : "";
+    window.location.href = URL + add_mode + (typeof(anchor) === "string" ? anchor : '');
+    return false;
+  };
 
-	return ElementBrowser;
+  return ElementBrowser;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js
index fef5bf6a6c08..3d2b2b96c2a6 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js
@@ -17,18 +17,18 @@
  * @exports TYPO3/CMS/Recordlist/FieldSelectBox
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		$('.fieldSelectBox .checkAll').change(function() {
-			var checked = $(this).prop('checked');
-			var $checkboxes = $('.fieldSelectBox tbody').find(':checkbox');
-			$checkboxes.each(function() {
-				if (!$(this).prop('disabled')) {
-					$(this).prop('checked', checked);
-				}
-			});
-		});
-	});
+  $(function() {
+    $('.fieldSelectBox .checkAll').change(function() {
+      var checked = $(this).prop('checked');
+      var $checkboxes = $('.fieldSelectBox tbody').find(':checkbox');
+      $checkboxes.each(function() {
+        if (!$(this).prop('disabled')) {
+          $(this).prop('checked', checked);
+        }
+      });
+    });
+  });
 
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js
index ae444a70e381..3a64c0645f87 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/FileLinkHandler.js
@@ -16,40 +16,40 @@
  * File link interaction
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/LegacyTree'], function($, LinkBrowser, Tree) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{currentLink: string}}
-	 * @exports TYPO3/CMS/Recordlist/FileLinkHandler
-	 */
-	var FileLinkHandler = {
-		currentLink: ''
-	};
+  /**
+   *
+   * @type {{currentLink: string}}
+   * @exports TYPO3/CMS/Recordlist/FileLinkHandler
+   */
+  var FileLinkHandler = {
+    currentLink: ''
+  };
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	FileLinkHandler.linkFile = function(event) {
-		event.preventDefault();
-		LinkBrowser.finalizeFunction($(this).attr('href'));
-	};
+  /**
+   *
+   * @param {Event} event
+   */
+  FileLinkHandler.linkFile = function(event) {
+    event.preventDefault();
+    LinkBrowser.finalizeFunction($(this).attr('href'));
+  };
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	FileLinkHandler.linkCurrent = function(event) {
-		event.preventDefault();
-		LinkBrowser.finalizeFunction(FileLinkHandler.currentLink);
-	};
+  /**
+   *
+   * @param {Event} event
+   */
+  FileLinkHandler.linkCurrent = function(event) {
+    event.preventDefault();
+    LinkBrowser.finalizeFunction(FileLinkHandler.currentLink);
+  };
 
-	$(function() {
-		FileLinkHandler.currentLink = $('body').data('currentLink');
-		$('a.t3js-fileLink').on('click', FileLinkHandler.linkFile);
-		$('input.t3js-linkCurrent').on('click', FileLinkHandler.linkCurrent);
-	});
+  $(function() {
+    FileLinkHandler.currentLink = $('body').data('currentLink');
+    $('a.t3js-fileLink').on('click', FileLinkHandler.linkFile);
+    $('input.t3js-linkCurrent').on('click', FileLinkHandler.linkCurrent);
+  });
 
-	return FileLinkHandler;
+  return FileLinkHandler;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js
index 93e1f6adddc7..a75b9c113f15 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/LinkBrowser.js
@@ -16,128 +16,130 @@
  * LinkBrowser communication with parent window
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, additionalLinkAttributes: {}, finalizeFunction: null}}
-	 * @exports TYPO3/CMS/Recordlist/LinkBrowser
-	 */
-	var LinkBrowser = {
-		thisScriptUrl: '',
-		urlParameters: {},
-		parameters: {},
-		addOnParams: '',
-		linkAttributeFields: [],
-		additionalLinkAttributes: {},
-		finalizeFunction: null
-	};
+  /**
+   *
+   * @type {{thisScriptUrl: string, urlParameters: {}, parameters: {}, addOnParams: string, linkAttributeFields: Array, additionalLinkAttributes: {}, finalizeFunction: null}}
+   * @exports TYPO3/CMS/Recordlist/LinkBrowser
+   */
+  var LinkBrowser = {
+    thisScriptUrl: '',
+    urlParameters: {},
+    parameters: {},
+    addOnParams: '',
+    linkAttributeFields: [],
+    additionalLinkAttributes: {},
+    finalizeFunction: null
+  };
 
-	/**
-	 * Collect the link attributes values as object
-	 *
-	 * @returns {Object}
-	 */
-	LinkBrowser.getLinkAttributeValues = function() {
-		var attributeValues = {};
-		$.each(LinkBrowser.linkAttributeFields, function(index, fieldName) {
-			var val = $('[name="l' + fieldName + '"]').val();
-			if (val) {
-				attributeValues[fieldName] = val;
-			}
-		});
-		$.extend(attributeValues, LinkBrowser.additionalLinkAttributes);
-		return attributeValues;
-	};
+  /**
+   * Collect the link attributes values as object
+   *
+   * @returns {Object}
+   */
+  LinkBrowser.getLinkAttributeValues = function() {
+    var attributeValues = {};
+    $.each(LinkBrowser.linkAttributeFields, function(index, fieldName) {
+      var val = $('[name="l' + fieldName + '"]').val();
+      if (val) {
+        attributeValues[fieldName] = val;
+      }
+    });
+    $.extend(attributeValues, LinkBrowser.additionalLinkAttributes);
+    return attributeValues;
+  };
 
-	/**
-	 *
-	 */
-	LinkBrowser.loadTarget = function() {
-		$('.t3js-linkTarget').val($(this).val());
-		this.selectedIndex = 0;
-	};
+  /**
+   *
+   */
+  LinkBrowser.loadTarget = function() {
+    $('.t3js-linkTarget').val($(this).val());
+    this.selectedIndex = 0;
+  };
 
-	/**
-	 * Encode objects to GET parameter arrays in PHP notation
-	 *
-	 * @param {Object} obj
-	 * @param {String} prefix
-	 * @param {String} url
-	 * @returns {String}
-	 */
-	LinkBrowser.encodeGetParameters = function(obj, prefix, url) {
-		var str = [];
-		for(var p in obj) {
-			if (obj.hasOwnProperty(p)) {
-				var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
-				if (url.indexOf(k + "=") === -1) {
-					str.push(
-						typeof v === "object"
-							? LinkBrowser.encodeGetParameters(v, k, url)
-							: encodeURIComponent(k) + "=" + encodeURIComponent(v)
-					);
-				}
-			}
-		}
-		return '&' + str.join("&");
-	};
+  /**
+   * Encode objects to GET parameter arrays in PHP notation
+   *
+   * @param {Object} obj
+   * @param {String} prefix
+   * @param {String} url
+   * @returns {String}
+   */
+  LinkBrowser.encodeGetParameters = function(obj, prefix, url) {
+    var str = [];
+    for (var p in obj) {
+      if (obj.hasOwnProperty(p)) {
+        var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
+        if (url.indexOf(k + "=") === -1) {
+          str.push(
+            typeof v === "object"
+              ? LinkBrowser.encodeGetParameters(v, k, url)
+              : encodeURIComponent(k) + "=" + encodeURIComponent(v)
+          );
+        }
+      }
+    }
+    return '&' + str.join("&");
+  };
 
-	/**
-	 * Set an additional attribute for the link
-	 *
-	 * @param {String} name
-	 * @param value
-	 */
-	LinkBrowser.setAdditionalLinkAttribute = function(name, value) {
-		LinkBrowser.additionalLinkAttributes[name] = value;
-	};
+  /**
+   * Set an additional attribute for the link
+   *
+   * @param {String} name
+   * @param value
+   */
+  LinkBrowser.setAdditionalLinkAttribute = function(name, value) {
+    LinkBrowser.additionalLinkAttributes[name] = value;
+  };
 
-	/**
-	 * Stores the final link
-	 *
-	 * This method MUST be overridden in the actual implementation of the link browser.
-	 * The function is responsible for encoding the link (and possible link attributes) and
-	 * returning it to the caller (e.g. FormEngine, RTE, etc)
-	 *
-	 * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>")
-	 */
-	LinkBrowser.finalizeFunction = function(link) {
-		throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
-	};
+  /**
+   * Stores the final link
+   *
+   * This method MUST be overridden in the actual implementation of the link browser.
+   * The function is responsible for encoding the link (and possible link attributes) and
+   * returning it to the caller (e.g. FormEngine, RTE, etc)
+   *
+   * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>")
+   */
+  LinkBrowser.finalizeFunction = function(link) {
+    throw 'The link browser requires the finalizeFunction to be set. Seems like you discovered a major bug.';
+  };
 
-	$(function() {
-		var data = $('body').data();
+  $(function() {
+    var data = $('body').data();
 
-		LinkBrowser.thisScriptUrl = data.thisScriptUrl;
-		LinkBrowser.urlParameters = data.urlParameters;
-		LinkBrowser.parameters = data.parameters;
-		LinkBrowser.addOnParams = data.addOnParams;
-		LinkBrowser.linkAttributeFields = data.linkAttributeFields;
+    LinkBrowser.thisScriptUrl = data.thisScriptUrl;
+    LinkBrowser.urlParameters = data.urlParameters;
+    LinkBrowser.parameters = data.parameters;
+    LinkBrowser.addOnParams = data.addOnParams;
+    LinkBrowser.linkAttributeFields = data.linkAttributeFields;
 
-		$('.t3js-targetPreselect').on('change', LinkBrowser.loadTarget);
-		$('form.t3js-dummyform').on('submit', function(evt) { evt.preventDefault(); });
-	});
+    $('.t3js-targetPreselect').on('change', LinkBrowser.loadTarget);
+    $('form.t3js-dummyform').on('submit', function(evt) {
+      evt.preventDefault();
+    });
+  });
 
-	/**
-	 * Global jumpTo function
-	 *
-	 * Used by tree implementation
-	 *
-	 * @param {String} URL
-	 * @param {String} anchor
-	 * @returns {Boolean}
-	 */
-	window.jumpToUrl = function(URL, anchor) {
-		if (URL.charAt(0) === '?') {
-			URL = LinkBrowser.thisScriptUrl + URL.substring(1);
-		}
-		var urlParameters = LinkBrowser.encodeGetParameters(LinkBrowser.urlParameters, '', URL);
-		var parameters = LinkBrowser.encodeGetParameters(LinkBrowser.getLinkAttributeValues(), 'linkAttributes', '');
+  /**
+   * Global jumpTo function
+   *
+   * Used by tree implementation
+   *
+   * @param {String} URL
+   * @param {String} anchor
+   * @returns {Boolean}
+   */
+  window.jumpToUrl = function(URL, anchor) {
+    if (URL.charAt(0) === '?') {
+      URL = LinkBrowser.thisScriptUrl + URL.substring(1);
+    }
+    var urlParameters = LinkBrowser.encodeGetParameters(LinkBrowser.urlParameters, '', URL);
+    var parameters = LinkBrowser.encodeGetParameters(LinkBrowser.getLinkAttributeValues(), 'linkAttributes', '');
 
-		window.location.href = URL + urlParameters + parameters + LinkBrowser.addOnParams + (typeof(anchor) === "string" ? anchor : '');
-		return false;
-	};
+    window.location.href = URL + urlParameters + parameters + LinkBrowser.addOnParams + (typeof(anchor) === "string" ? anchor : '');
+    return false;
+  };
 
-	return LinkBrowser;
+  return LinkBrowser;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js
index f4d733d1bdad..8dfff9377c3e 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/MailLinkHandler.js
@@ -16,31 +16,31 @@
  * Mail link interaction
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Recordlist/MailLinkHandler
-	 */
-	var MailLinkHandler = {};
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Recordlist/MailLinkHandler
+   */
+  var MailLinkHandler = {};
 
-	$(function() {
-		$('#lmailform').on('submit', function(event) {
-			event.preventDefault();
+  $(function() {
+    $('#lmailform').on('submit', function(event) {
+      event.preventDefault();
 
-			var value = $(this).find('[name="lemail"]').val();
-			if (value === 'mailto:') {
-				return;
-			}
+      var value = $(this).find('[name="lemail"]').val();
+      if (value === 'mailto:') {
+        return;
+      }
 
-			while (value.substr(0, 7) === 'mailto:') {
-				value = value.substr(7);
-			}
+      while (value.substr(0, 7) === 'mailto:') {
+        value = value.substr(7);
+      }
 
-			LinkBrowser.finalizeFunction('mailto:' + value);
-		});
-	});
+      LinkBrowser.finalizeFunction('mailto:' + value);
+    });
+  });
 
-	return MailLinkHandler;
+  return MailLinkHandler;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js
index 6e07cb056c2f..f7488ccfde89 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/PageLinkHandler.js
@@ -16,57 +16,57 @@
  * Page link interaction
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{currentLink: string}}
-	 * @exports TYPO3/CMS/Recordlist/PageLinkHandler
-	 */
-	var PageLinkHandler = {
-		currentLink: ''
-	};
+  /**
+   *
+   * @type {{currentLink: string}}
+   * @exports TYPO3/CMS/Recordlist/PageLinkHandler
+   */
+  var PageLinkHandler = {
+    currentLink: ''
+  };
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	PageLinkHandler.linkPage = function(event) {
-		event.preventDefault();
-		LinkBrowser.finalizeFunction($(this).attr('href'));
-	};
+  /**
+   *
+   * @param {Event} event
+   */
+  PageLinkHandler.linkPage = function(event) {
+    event.preventDefault();
+    LinkBrowser.finalizeFunction($(this).attr('href'));
+  };
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	PageLinkHandler.linkPageByTextfield = function(event) {
-		event.preventDefault();
+  /**
+   *
+   * @param {Event} event
+   */
+  PageLinkHandler.linkPageByTextfield = function(event) {
+    event.preventDefault();
 
-		var value = $('#luid').val();
-		if (!value) {
-			return;
-		}
+    var value = $('#luid').val();
+    if (!value) {
+      return;
+    }
 
-		LinkBrowser.finalizeFunction(value);
-	};
+    LinkBrowser.finalizeFunction(value);
+  };
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	PageLinkHandler.linkCurrent = function(event) {
-		event.preventDefault();
-		LinkBrowser.finalizeFunction(PageLinkHandler.currentLink);
-	};
+  /**
+   *
+   * @param {Event} event
+   */
+  PageLinkHandler.linkCurrent = function(event) {
+    event.preventDefault();
+    LinkBrowser.finalizeFunction(PageLinkHandler.currentLink);
+  };
 
-	$(function() {
-		PageLinkHandler.currentLink = $('body').data('currentLink');
+  $(function() {
+    PageLinkHandler.currentLink = $('body').data('currentLink');
 
-		$('a.t3js-pageLink').on('click', PageLinkHandler.linkPage);
-		$('input.t3js-linkCurrent').on('click', PageLinkHandler.linkCurrent);
-		$('input.t3js-pageLink').on('click', PageLinkHandler.linkPageByTextfield);
-	});
+    $('a.t3js-pageLink').on('click', PageLinkHandler.linkPage);
+    $('input.t3js-linkCurrent').on('click', PageLinkHandler.linkCurrent);
+    $('input.t3js-pageLink').on('click', PageLinkHandler.linkPageByTextfield);
+  });
 
-	return PageLinkHandler;
+  return PageLinkHandler;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js
index 16a2fa67d0e0..f7a904e868f3 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/RecordLinkHandler.js
@@ -15,49 +15,49 @@
  * Module: TYPO3/CMS/Recordlist/RecordLinkHandler
  * record link interaction
  */
-define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function ($, LinkBrowser) {
-	'use strict';
-
-	/**
-	 * @type {{currentLink: string, identifier: string, linkRecord: function, linkCurrent: function}}
-	 */
-	var RecordLinkHandler = {
-		currentLink: '',
-		identifier: '',
-
-		/**
-		 * @param {Event} event
-		 */
-		linkRecord: function (event) {
-			event.preventDefault();
-
-			var data = $(this).parents('span').data();
-			LinkBrowser.finalizeFunction(RecordLinkHandler.identifier + data.uid);
-		},
-
-		/**
-		 * @param {Event} event
-		 */
-		linkCurrent: function (event) {
-			event.preventDefault();
-
-			LinkBrowser.finalizeFunction(RecordLinkHandler.currentLink);
-		}
-	};
-
-	$(function () {
-		var body = $('body');
-		RecordLinkHandler.currentLink = body.data('currentLink');
-		RecordLinkHandler.identifier = body.data('identifier');
-
-		// adjust searchbox layout
-		var searchbox = document.getElementById('db_list-searchbox-toolbar');
-		searchbox.style.display = 'block';
-		searchbox.style.position = 'relative';
-
-		$('[data-close]').on('click', RecordLinkHandler.linkRecord);
-		$('input.t3js-linkCurrent').on('click', RecordLinkHandler.linkCurrent);
-	});
-
-	return RecordLinkHandler;
+define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
+  'use strict';
+
+  /**
+   * @type {{currentLink: string, identifier: string, linkRecord: function, linkCurrent: function}}
+   */
+  var RecordLinkHandler = {
+    currentLink: '',
+    identifier: '',
+
+    /**
+     * @param {Event} event
+     */
+    linkRecord: function(event) {
+      event.preventDefault();
+
+      var data = $(this).parents('span').data();
+      LinkBrowser.finalizeFunction(RecordLinkHandler.identifier + data.uid);
+    },
+
+    /**
+     * @param {Event} event
+     */
+    linkCurrent: function(event) {
+      event.preventDefault();
+
+      LinkBrowser.finalizeFunction(RecordLinkHandler.currentLink);
+    }
+  };
+
+  $(function() {
+    var body = $('body');
+    RecordLinkHandler.currentLink = body.data('currentLink');
+    RecordLinkHandler.identifier = body.data('identifier');
+
+    // adjust searchbox layout
+    var searchbox = document.getElementById('db_list-searchbox-toolbar');
+    searchbox.style.display = 'block';
+    searchbox.style.position = 'relative';
+
+    $('[data-close]').on('click', RecordLinkHandler.linkRecord);
+    $('input.t3js-linkCurrent').on('click', RecordLinkHandler.linkCurrent);
+  });
+
+  return RecordLinkHandler;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js
index a6be684f96f2..86f9c5fe436f 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/Recordlist.js
@@ -16,112 +16,114 @@
  * Usability improvements for the record list
  */
 define(['jquery', 'TYPO3/CMS/Backend/Storage/Persistent', 'TYPO3/CMS/Backend/Icons'], function($, PersistentStorage, Icons) {
-	'use strict';
-
-	/**
-	 * @type {Object}
-	 * @exports TYPO3/CMS/Recordlist/Recordlist
-	 */
-	var Recordlist = {
-		identifier: {
-			entity: '.t3js-entity',
-			toggle: '.t3js-toggle-recordlist',
-			icons: {
-				collapse: 'actions-view-list-collapse',
-				expand: 'actions-view-list-expand',
-				editMultiple: '.t3js-record-edit-multiple'
-			}
-		}
-	};
-
-	/**
-	 * @param {MouseEvent} e
-	 */
-	Recordlist.toggleClick = function(e) {
-		e.preventDefault();
-
-		var $me = $(this),
-			table = $me.data('table'),
-			$target = $($me.data('target')),
-			isExpanded = $target.data('state') === 'expanded',
-			$collapseIcon = $me.find('.collapseIcon'),
-			toggleIcon = isExpanded ? Recordlist.identifier.icons.expand : Recordlist.identifier.icons.collapse;
-
-		Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(toggleIcon) {
-			$collapseIcon.html(toggleIcon);
-		});
-
-		// Store collapse state in UC
-		var storedModuleDataList = {};
-
-		if (PersistentStorage.isset('moduleData.list')) {
-			storedModuleDataList = PersistentStorage.get('moduleData.list');
-		}
-
-		var collapseConfig = {};
-		collapseConfig[table] = isExpanded ? 1 : 0;
-
-		$.extend(true, storedModuleDataList, collapseConfig);
-		PersistentStorage.set('moduleData.list', storedModuleDataList).done(function() {
-			$target.data('state', isExpanded ? 'collapsed' : 'expanded');
-		});
-	};
-
-	/**
-	 * Handles editing multiple records.
-	 *
-	 * @param {MouseEvent} event
-	 */
-	Recordlist.onEditMultiple = function(event) {
-		event.preventDefault();
-
-		var $tableContainer, tableName, entityIdentifiers, uri, patterns;
-
-		$tableContainer = $(this).closest('[data-table]');
-		if ($tableContainer.length === 0) {
-			return;
-		}
-
-		uri = $(this).data('uri');
-		tableName = $tableContainer.data('table');
-		entityIdentifiers = $tableContainer
-			.find(Recordlist.identifier.entity + '[data-uid][data-table="' + tableName + '"]')
-			.map(function(index, entity) { return $(entity).data('uid'); })
-			.toArray()
-			.join(',');
-
-		patterns = uri.match(/{[^}]+}/g);
-		$.each(patterns, function(patternIndex, pattern) {
-			var expression = pattern.substr(1, pattern.length - 2);
-			var pipes = expression.split(':');
-			var name = pipes.shift();
-			var value;
-
-			switch (name) {
-				case 'entityIdentifiers':
-					value = entityIdentifiers;
-					break;
-				case 'T3_THIS_LOCATION':
-					value = T3_THIS_LOCATION;
-					break;
-				default:
-					return;
-			}
-
-			$.each(pipes, function(pipeIndex, pipe) {
-				if (pipe === 'editList') {
-					value = editList(tableName, value);
-				}
-			});
-
-			uri = uri.replace(pattern, value);
-		});
-
-		window.location.href = uri;
-	};
-
-	$(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick);
-	$(document).on('click', Recordlist.identifier.icons.editMultiple, Recordlist.onEditMultiple);
-
-	return Recordlist;
+  'use strict';
+
+  /**
+   * @type {Object}
+   * @exports TYPO3/CMS/Recordlist/Recordlist
+   */
+  var Recordlist = {
+    identifier: {
+      entity: '.t3js-entity',
+      toggle: '.t3js-toggle-recordlist',
+      icons: {
+        collapse: 'actions-view-list-collapse',
+        expand: 'actions-view-list-expand',
+        editMultiple: '.t3js-record-edit-multiple'
+      }
+    }
+  };
+
+  /**
+   * @param {MouseEvent} e
+   */
+  Recordlist.toggleClick = function(e) {
+    e.preventDefault();
+
+    var $me = $(this),
+      table = $me.data('table'),
+      $target = $($me.data('target')),
+      isExpanded = $target.data('state') === 'expanded',
+      $collapseIcon = $me.find('.collapseIcon'),
+      toggleIcon = isExpanded ? Recordlist.identifier.icons.expand : Recordlist.identifier.icons.collapse;
+
+    Icons.getIcon(toggleIcon, Icons.sizes.small).done(function(toggleIcon) {
+      $collapseIcon.html(toggleIcon);
+    });
+
+    // Store collapse state in UC
+    var storedModuleDataList = {};
+
+    if (PersistentStorage.isset('moduleData.list')) {
+      storedModuleDataList = PersistentStorage.get('moduleData.list');
+    }
+
+    var collapseConfig = {};
+    collapseConfig[table] = isExpanded ? 1 : 0;
+
+    $.extend(true, storedModuleDataList, collapseConfig);
+    PersistentStorage.set('moduleData.list', storedModuleDataList).done(function() {
+      $target.data('state', isExpanded ? 'collapsed' : 'expanded');
+    });
+  };
+
+  /**
+   * Handles editing multiple records.
+   *
+   * @param {MouseEvent} event
+   */
+  Recordlist.onEditMultiple = function(event) {
+    event.preventDefault();
+
+    var $tableContainer, tableName, entityIdentifiers, uri, patterns;
+
+    $tableContainer = $(this).closest('[data-table]');
+    if ($tableContainer.length === 0) {
+      return;
+    }
+
+    uri = $(this).data('uri');
+    tableName = $tableContainer.data('table');
+    entityIdentifiers = $tableContainer
+      .find(Recordlist.identifier.entity + '[data-uid][data-table="' + tableName + '"]')
+      .map(function(index, entity) {
+        return $(entity).data('uid');
+      })
+      .toArray()
+      .join(',');
+
+    patterns = uri.match(/{[^}]+}/g);
+    $.each(patterns, function(patternIndex, pattern) {
+      var expression = pattern.substr(1, pattern.length - 2);
+      var pipes = expression.split(':');
+      var name = pipes.shift();
+      var value;
+
+      switch (name) {
+        case 'entityIdentifiers':
+          value = entityIdentifiers;
+          break;
+        case 'T3_THIS_LOCATION':
+          value = T3_THIS_LOCATION;
+          break;
+        default:
+          return;
+      }
+
+      $.each(pipes, function(pipeIndex, pipe) {
+        if (pipe === 'editList') {
+          value = editList(tableName, value);
+        }
+      });
+
+      uri = uri.replace(pattern, value);
+    });
+
+    window.location.href = uri;
+  };
+
+  $(document).on('click', Recordlist.identifier.toggle, Recordlist.toggleClick);
+  $(document).on('click', Recordlist.identifier.icons.editMultiple, Recordlist.onEditMultiple);
+
+  return Recordlist;
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js
index 4651b8847cf0..e7887c3d5f9b 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/Tooltip.js
@@ -17,17 +17,17 @@
  * @exports TYPO3/CMS/Recordlist/Tooltip
  */
 define(['jquery', 'TYPO3/CMS/Backend/Tooltip'], function($, Tooltip) {
-	'use strict';
+  'use strict';
 
-	$(function() {
-		Tooltip.initialize('.table-fit a[title]', {
-			delay: {
-				show: 500,
-				hide: 100
-			},
-			trigger: 'hover',
-			container: 'body'
-		});
-	});
+  $(function() {
+    Tooltip.initialize('.table-fit a[title]', {
+      delay: {
+        show: 500,
+        hide: 100
+      },
+      trigger: 'hover',
+      container: 'body'
+    });
+  });
 
 });
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js
index 7e08ef67acda..e82e0ac9184c 100644
--- a/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js
+++ b/typo3/sysext/recordlist/Resources/Public/JavaScript/UrlLinkHandler.js
@@ -16,33 +16,33 @@
  * URL link interaction
  */
 define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser'], function($, LinkBrowser) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Recordlist/UrlLinkHandler
-	 */
-	var UrlLinkHandler = {};
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Recordlist/UrlLinkHandler
+   */
+  var UrlLinkHandler = {};
 
-	/**
-	 *
-	 * @param {Event} event
-	 */
-	UrlLinkHandler.link = function(event) {
-		event.preventDefault();
+  /**
+   *
+   * @param {Event} event
+   */
+  UrlLinkHandler.link = function(event) {
+    event.preventDefault();
 
-		var value = $(this).find('[name="lurl"]').val();
-		if (value === "http://") {
-			return;
-		}
+    var value = $(this).find('[name="lurl"]').val();
+    if (value === "http://") {
+      return;
+    }
 
-		LinkBrowser.finalizeFunction(value);
-	};
+    LinkBrowser.finalizeFunction(value);
+  };
 
-	$(function() {
-		$('#lurlform').on('submit', UrlLinkHandler.link);
-	});
+  $(function() {
+    $('#lurlform').on('submit', UrlLinkHandler.link);
+  });
 
-	return UrlLinkHandler;
+  return UrlLinkHandler;
 });
diff --git a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js
index 7d3336a96d5f..1128c58e5562 100644
--- a/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js
+++ b/typo3/sysext/recycler/Resources/Public/JavaScript/Recycler.js
@@ -16,587 +16,590 @@
  * RequireJS module for Recycler
  */
 define(['jquery',
-		'nprogress',
-		'TYPO3/CMS/Backend/Modal',
-		'TYPO3/CMS/Backend/Notification',
-		'TYPO3/CMS/Backend/Severity',
-		'TYPO3/CMS/Backend/jquery.clearable'
-	   ], function($, NProgress, Modal, Notification, Severity) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{identifiers: {searchForm: string, searchText: string, searchSubmitBtn: string, depthSelector: string, tableSelector: string, recyclerTable: string, paginator: string, reloadAction: string, massUndo: string, massDelete: string, toggleAll: string}, elements: {}, paging: {currentPage: number, totalPages: number, totalItems: number, itemsPerPage: number}, markedRecordsForMassAction: Array, allToggled: boolean}}
-	 * @exports TYPO3/CMS/Recycler/Recycler
-	 */
-	var Recycler = {
-		identifiers: {
-			searchForm: '#recycler-form',
-			searchText: '#recycler-form [name=search-text]',
-			searchSubmitBtn: '#recycler-form button[type=submit]',
-			depthSelector: '#recycler-form [name=depth]',
-			tableSelector: '#recycler-form [name=pages]',
-			recyclerTable: '#itemsInRecycler',
-			paginator: '#recycler-index nav',
-			reloadAction: 'a[data-action=reload]',
-			massUndo: 'button[data-action=massundo]',
-			massDelete: 'button[data-action=massdelete]',
-			toggleAll: '.t3js-toggle-all'
-		},
-		elements: {}, // filled in getElements()
-		paging: {
-			currentPage: 1,
-			totalPages: 1,
-			totalItems: 0,
-			itemsPerPage: TYPO3.settings.Recycler.pagingSize
-		},
-		markedRecordsForMassAction: [],
-		allToggled: false
-	};
-
-	/**
-	 * Gets required elements
-	 */
-	Recycler.getElements = function() {
-		Recycler.elements = {
-			$searchForm: $(Recycler.identifiers.searchForm),
-			$searchTextField: $(Recycler.identifiers.searchText),
-			$searchSubmitBtn: $(Recycler.identifiers.searchSubmitBtn),
-			$depthSelector: $(Recycler.identifiers.depthSelector),
-			$tableSelector: $(Recycler.identifiers.tableSelector),
-			$recyclerTable: $(Recycler.identifiers.recyclerTable),
-			$tableBody: $(Recycler.identifiers.recyclerTable).find('tbody'),
-			$paginator: $(Recycler.identifiers.paginator),
-			$reloadAction: $(Recycler.identifiers.reloadAction),
-			$massUndo: $(Recycler.identifiers.massUndo),
-			$massDelete: $(Recycler.identifiers.massDelete),
-			$toggleAll: $(Recycler.identifiers.toggleAll)
-		};
-	};
-
-	/**
-	 * Register events
-	 */
-	Recycler.registerEvents = function() {
-		// submitting the form
-		Recycler.elements.$searchForm.on('submit', function(e) {
-			e.preventDefault();
-			if (Recycler.elements.$searchTextField.val() !== '') {
-				Recycler.loadDeletedElements();
-			}
-		});
-
-		// changing the search field
-		Recycler.elements.$searchTextField.on('keyup', function() {
-			var $me = $(this);
-
-			if ($me.val() !== '') {
-				Recycler.elements.$searchSubmitBtn.removeClass('disabled');
-			} else {
-				Recycler.elements.$searchSubmitBtn.addClass('disabled');
-				Recycler.loadDeletedElements();
-			}
-		}).clearable(
-			{
-				onClear: function() {
-					Recycler.elements.$searchSubmitBtn.addClass('disabled');
-					Recycler.loadDeletedElements();
-				}
-			}
-		);
-
-		// changing "depth"
-		Recycler.elements.$depthSelector.on('change', function() {
-			$.when(Recycler.loadAvailableTables()).done(function() {
-				Recycler.loadDeletedElements();
-			});
-		});
-
-		// changing "table"
-		Recycler.elements.$tableSelector.on('change', function() {
-			Recycler.paging.currentPage = 1;
-			Recycler.loadDeletedElements();
-		});
-
-		// clicking "recover" in single row
-		Recycler.elements.$recyclerTable.on('click', '[data-action=undo]', Recycler.undoRecord);
-
-		// clicking "delete" in single row
-		Recycler.elements.$recyclerTable.on('click', '[data-action=delete]', Recycler.deleteRecord);
-
-		Recycler.elements.$reloadAction.on('click', function(e) {
-			e.preventDefault();
-			$.when(Recycler.loadAvailableTables()).done(function() {
-				Recycler.loadDeletedElements();
-			});
-		});
-
-		// clicking an action in the paginator
-		Recycler.elements.$paginator.on('click', 'a[data-action]', function(e) {
-			e.preventDefault();
-
-			var $el = $(this),
-				reload = false;
-
-			switch ($el.data('action')) {
-				case 'previous':
-					if (Recycler.paging.currentPage > 1) {
-						Recycler.paging.currentPage--;
-						reload = true;
-					}
-					break;
-				case 'next':
-					if (Recycler.paging.currentPage < Recycler.paging.totalPages) {
-						Recycler.paging.currentPage++;
-						reload = true;
-					}
-					break;
-				case 'page':
-					Recycler.paging.currentPage = parseInt($el.find('span').text());
-					reload = true;
-					break;
-			}
-
-			if (reload) {
-				Recycler.loadDeletedElements();
-			}
-		});
-
-		if (!TYPO3.settings.Recycler.deleteDisable) {
-			Recycler.elements.$massDelete.show();
-		} else {
-			Recycler.elements.$massDelete.remove();
-		}
-
-		Recycler.elements.$recyclerTable.on('show.bs.collapse hide.bs.collapse', 'tr.collapse', function(e) {
-			var $trigger = $(e.currentTarget).prev('tr').find('[data-action=expand]'),
-				$iconEl = $trigger.find('.t3-icon'),
-				removeClass,
-				addClass;
-
-			switch (e.type) {
-				case 'show':
-					removeClass = 't3-icon-pagetree-collapse';
-					addClass = 't3-icon-pagetree-expand';
-					break;
-				case 'hide':
-					removeClass = 't3-icon-pagetree-expand';
-					addClass = 't3-icon-pagetree-collapse';
-					break;
-			}
-
-			$iconEl.removeClass(removeClass).addClass(addClass);
-		});
-
-		// checkboxes in the table
-		Recycler.elements.$toggleAll.on('click', function() {
-			Recycler.allToggled = !Recycler.allToggled;
-			$('input[type="checkbox"]').prop('checked', Recycler.allToggled).trigger('change');
-		});
-		Recycler.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', Recycler.handleCheckboxSelects);
-
-		Recycler.elements.$massUndo.on('click', Recycler.undoRecord);
-		Recycler.elements.$massDelete.on('click', Recycler.deleteRecord);
-	};
-
-	/**
-	 * Initialize the recycler module
-	 */
-	Recycler.initialize = function() {
-		NProgress.configure({parent: '.module-loading-indicator', showSpinner: false});
-
-		Recycler.getElements();
-		Recycler.registerEvents();
-
-		if (TYPO3.settings.Recycler.depthSelection > 0) {
-			Recycler.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger('change');
-		} else {
-			$.when(Recycler.loadAvailableTables()).done(function() {
-				Recycler.loadDeletedElements();
-			});
-		}
-	};
-
-	/**
-	 * Handles the clicks on checkboxes in the records table
-	 */
-	Recycler.handleCheckboxSelects = function() {
-		var $checkbox = $(this),
-			$tr = $checkbox.parents('tr'),
-			table = $tr.data('table'),
-			uid = $tr.data('uid'),
-			record = table + ':' + uid;
-
-		if ($checkbox.prop('checked')) {
-			Recycler.markedRecordsForMassAction.push(record);
-			$tr.addClass('warning');
-		} else {
-			var index = Recycler.markedRecordsForMassAction.indexOf(record);
-			if (index > -1) {
-				Recycler.markedRecordsForMassAction.splice(index, 1);
-			}
-			$tr.removeClass('warning');
-		}
-
-		if (Recycler.markedRecordsForMassAction.length > 0) {
-			if (Recycler.elements.$massUndo.hasClass('disabled')) {
-				Recycler.elements.$massUndo.removeClass('disabled');
-			}
-			if (Recycler.elements.$massDelete.hasClass('disabled')) {
-				Recycler.elements.$massDelete.removeClass('disabled');
-			}
-
-			var btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [Recycler.markedRecordsForMassAction.length]),
-				btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [Recycler.markedRecordsForMassAction.length]);
-
-			Recycler.elements.$massUndo.find('span.text').text(btnTextUndo);
-			Recycler.elements.$massDelete.find('span.text').text(btnTextDelete);
-
-		} else {
-			Recycler.resetMassActionButtons();
-		}
-	};
-
-	/**
-	 * Resets the mass action state
-	 */
-	Recycler.resetMassActionButtons = function() {
-		Recycler.markedRecordsForMassAction = [];
-		Recycler.elements.$massUndo.addClass('disabled');
-		Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']);
-		Recycler.elements.$massDelete.addClass('disabled');
-		Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']);
-	};
-
-	/**
-	 * Loads all tables which contain deleted records.
-	 *
-	 * @returns {Promise}
-	 */
-	Recycler.loadAvailableTables = function() {
-		return $.ajax({
-			url: TYPO3.settings.ajaxUrls['recycler'],
-			dataType: 'json',
-			data: {
-				action: 'getTables',
-				startUid: TYPO3.settings.Recycler.startUid,
-				depth: Recycler.elements.$depthSelector.find('option:selected').val()
-			},
-			beforeSend: function() {
-				NProgress.start();
-				Recycler.elements.$tableSelector.val('');
-				Recycler.paging.currentPage = 1;
-			},
-			success: function(data) {
-				var tables = [];
-				Recycler.elements.$tableSelector.children().remove();
-				$.each(data, function(_, value) {
-					var tableName = value[0],
-						deletedRecords = value[1],
-						tableDescription = value[2];
-
-					if (tableDescription === '') {
-						tableDescription = TYPO3.lang['label_allrecordtypes'];
-					}
-					var optionText = tableDescription + ' (' + deletedRecords + ')';
-					tables.push($('<option />').val(tableName).text(optionText))
-				});
-
-				if (tables.length > 0) {
-					Recycler.elements.$tableSelector.append(tables);
-					if (TYPO3.settings.Recycler.tableSelection !== '') {
-						Recycler.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection);
-					}
-				}
-			},
-			complete: function() {
-				NProgress.done();
-			}
-		});
-	};
-
-	/**
-	 * Loads the deleted elements, based on the filters
-	 *
-	 * @returns {Promise}
-	 */
-	Recycler.loadDeletedElements = function() {
-		return $.ajax({
-			url: TYPO3.settings.ajaxUrls['recycler'],
-			dataType: 'json',
-			data: {
-				action: 'getDeletedRecords',
-				depth: Recycler.elements.$depthSelector.find('option:selected').val(),
-				startUid: TYPO3.settings.Recycler.startUid,
-				table: Recycler.elements.$tableSelector.find('option:selected').val(),
-				filterTxt: Recycler.elements.$searchTextField.val(),
-				start: (Recycler.paging.currentPage -1) * Recycler.paging.itemsPerPage,
-				limit: Recycler.paging.itemsPerPage
-			},
-			beforeSend: function() {
-				NProgress.start();
-				Recycler.resetMassActionButtons();
-			},
-			success: function(data) {
-				Recycler.elements.$tableBody.html(data.rows);
-				Recycler.buildPaginator(data.totalItems);
-			},
-			complete: function() {
-				NProgress.done();
-			}
-		});
-	};
-
-	/**
-	 *
-	 */
-	Recycler.deleteRecord = function() {
-		if (TYPO3.settings.Recycler.deleteDisable) {
-			return;
-		}
-
-		var $tr = $(this).parents('tr'),
-			isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button
-
-		var records, message;
-		if (isMassDelete) {
-			records = Recycler.markedRecordsForMassAction;
-			message = TYPO3.lang['modal.massdelete.text'];
-		} else {
-			var uid = $tr.data('uid'),
-				table = $tr.data('table'),
-				recordTitle = $tr.data('recordtitle');
-			records = table + ':' + uid;
-			message = table === 'pages' ? TYPO3.lang['modal.deletepage.text'] : TYPO3.lang['modal.deletecontent.text'];
-			message = Recycler.createMessage(message, [recordTitle, '[' + records + ']']);
-		}
-
-		Modal.confirm(TYPO3.lang['modal.delete.header'], message, Severity.error, [
-			{
-				text: TYPO3.lang['button.cancel'],
-				btnClass: 'btn-default',
-				trigger: function() {
-					Modal.dismiss();
-				}
-			}, {
-				text: TYPO3.lang['button.delete'],
-				btnClass: 'btn-danger',
-				trigger: function() {
-					Recycler.callAjaxAction('delete', typeof records === 'object' ? records : [records], isMassDelete);
-				}
-			}
-		]);
-	};
-
-	/**
-	 *
-	 */
-	Recycler.undoRecord = function() {
-		var $tr = $(this).parents('tr'),
-			isMassUndo = $tr.parent().prop('tagName') !== 'TBODY'; // undoRecord() was invoked by the mass delete button
-
-		var records, messageText, recoverPages;
-		if (isMassUndo) {
-			records = Recycler.markedRecordsForMassAction;
-			messageText = TYPO3.lang['modal.massundo.text'];
-			recoverPages = true;
-		} else {
-			var uid = $tr.data('uid'),
-				table = $tr.data('table'),
-				recordTitle = $tr.data('recordtitle');
-
-			records = table + ':' + uid;
-			recoverPages = table === 'pages';
-			messageText = recoverPages ? TYPO3.lang['modal.undopage.text'] : TYPO3.lang['modal.undocontent.text'];
-			messageText = Recycler.createMessage(messageText, [recordTitle, '[' + records + ']']);
-
-			if (recoverPages && $tr.data('parentDeleted')) {
-				messageText += TYPO3.lang['modal.undo.parentpages'];
-			}
-		}
-
-		var $message = null;
-		if (recoverPages) {
-			$message = $('<div />').append(
-				$('<p />').text(messageText),
-				$('<div />', {class: 'checkbox'}).append(
-					$('<label />').append(TYPO3.lang['modal.undo.recursive']).prepend($('<input />', {id: 'undo-recursive', type: 'checkbox'}))
-				)
-			);
-		} else {
-			$message = messageText;
-		}
-
-		Modal.confirm(TYPO3.lang['modal.undo.header'], $message, Severity.ok, [
-			{
-				text: TYPO3.lang['button.cancel'],
-				btnClass: 'btn-default',
-				trigger: function() {
-					Modal.dismiss();
-				}
-			}, {
-				text: TYPO3.lang['button.undo'],
-				btnClass: 'btn-success',
-				trigger: function() {
-					Recycler.callAjaxAction('undo', typeof records === 'object' ? records : [records], isMassUndo, $message.find('#undo-recursive').prop('checked') ? 1 : 0);
-				}
-			}
-		]);
-	};
-
-	/**
-	 *
-	 * @param {String} action
-	 * @param {Object} records
-	 * @param {Boolean} isMassAction
-	 * @param {Boolean} recursive
-	 */
-	Recycler.callAjaxAction = function(action, records, isMassAction, recursive) {
-		var data = {
-				records: records,
-				action: ''
-			},
-			reloadPageTree = false;
-		if (action === 'undo') {
-			data.action = 'undoRecords';
-			data.recursive = recursive ? 1 : 0;
-			reloadPageTree = true;
-		} else if (action === 'delete') {
-			data.action = 'deleteRecords';
-		} else {
-			return;
-		}
-
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['recycler'],
-			dataType: 'json',
-			data: data,
-			beforeSend: function() {
-				NProgress.start();
-			},
-			success: function(data) {
-				if (data.success) {
-					Notification.success('', data.message);
-				} else {
-					Notification.error('', data.message);
-				}
-
-				// reload recycler data
-				Recycler.paging.currentPage = 1;
-
-				$.when(Recycler.loadAvailableTables()).done(function() {
-					Recycler.loadDeletedElements();
-					if (isMassAction) {
-						Recycler.resetMassActionButtons();
-					}
-
-					if (reloadPageTree) {
-						Recycler.refreshPageTree();
-					}
-
-					// Reset toggle state
-					Recycler.allToggled = false;
-				});
-			},
-			complete: function() {
-				Modal.dismiss();
-				NProgress.done();
-			}
-		});
-	};
-
-	/**
-	 * Replaces the placeholders with actual values
-	 *
-	 * @param {String} message
-	 * @param {Array} placeholders
-	 * @returns {*}
-	 */
-	Recycler.createMessage = function(message, placeholders) {
-		if (typeof message === 'undefined') {
-			return '';
-		}
-
-		return message.replace(
-			/\{([0-9]+)\}/g,
-			function(_, index) {
-				return placeholders[index];
-			}
-		);
-	};
-
-	/**
-	 * Reloads the page tree
-	 */
-	Recycler.refreshPageTree = function() {
-		if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
-			top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-		}
-	};
-
-	/**
-	 * Build the paginator
-	 *
-	 * @param {Number} totalItems
-	 */
-	Recycler.buildPaginator = function(totalItems) {
-		if (totalItems === 0) {
-			Recycler.elements.$paginator.contents().remove();
-			return;
-		}
-
-		Recycler.paging.totalItems = totalItems;
-		Recycler.paging.totalPages = Math.ceil(totalItems / Recycler.paging.itemsPerPage);
-
-		if (Recycler.paging.totalPages === 1) {
-			// early abort if only one page is available
-			Recycler.elements.$paginator.contents().remove();
-			return;
-		}
-
-		var $ul = $('<ul />', {class: 'pagination pagination-block'}),
-			liElements = [],
-			$controlFirstPage = $('<li />').append(
-				$('<a />', {'data-action': 'previous'}).append(
-					$('<span />', {class: 't3-icon fa fa-arrow-left'})
-				)
-			),
-			$controlLastPage = $('<li />').append(
-				$('<a />', {'data-action': 'next'}).append(
-					$('<span />', {class: 't3-icon fa fa-arrow-right'})
-				)
-			);
-
-		if (Recycler.paging.currentPage === 1) {
-			$controlFirstPage.disablePagingAction();
-		}
-
-		if (Recycler.paging.currentPage === Recycler.paging.totalPages) {
-			$controlLastPage.disablePagingAction();
-		}
-
-		for (var i = 1; i <= Recycler.paging.totalPages; i++) {
-			var $li = $('<li />', {class: Recycler.paging.currentPage === i ? 'active' : ''});
-			$li.append(
-				$('<a />', {'data-action': 'page'}).append(
-					$('<span />').text(i)
-				)
-			);
-			liElements.push($li);
-		}
-
-		$ul.append($controlFirstPage, liElements, $controlLastPage);
-		Recycler.elements.$paginator.html($ul);
-	};
-
-	/**
-	 * Changes the markup of a pagination action being disabled
-	 */
-	$.fn.disablePagingAction = function() {
-		$(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />'));
-	};
-
-	$(Recycler.initialize);
-
-	return Recycler;
+  'nprogress',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Notification',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/jquery.clearable'
+], function($, NProgress, Modal, Notification, Severity) {
+  'use strict';
+
+  /**
+   *
+   * @type {{identifiers: {searchForm: string, searchText: string, searchSubmitBtn: string, depthSelector: string, tableSelector: string, recyclerTable: string, paginator: string, reloadAction: string, massUndo: string, massDelete: string, toggleAll: string}, elements: {}, paging: {currentPage: number, totalPages: number, totalItems: number, itemsPerPage: number}, markedRecordsForMassAction: Array, allToggled: boolean}}
+   * @exports TYPO3/CMS/Recycler/Recycler
+   */
+  var Recycler = {
+    identifiers: {
+      searchForm: '#recycler-form',
+      searchText: '#recycler-form [name=search-text]',
+      searchSubmitBtn: '#recycler-form button[type=submit]',
+      depthSelector: '#recycler-form [name=depth]',
+      tableSelector: '#recycler-form [name=pages]',
+      recyclerTable: '#itemsInRecycler',
+      paginator: '#recycler-index nav',
+      reloadAction: 'a[data-action=reload]',
+      massUndo: 'button[data-action=massundo]',
+      massDelete: 'button[data-action=massdelete]',
+      toggleAll: '.t3js-toggle-all'
+    },
+    elements: {}, // filled in getElements()
+    paging: {
+      currentPage: 1,
+      totalPages: 1,
+      totalItems: 0,
+      itemsPerPage: TYPO3.settings.Recycler.pagingSize
+    },
+    markedRecordsForMassAction: [],
+    allToggled: false
+  };
+
+  /**
+   * Gets required elements
+   */
+  Recycler.getElements = function() {
+    Recycler.elements = {
+      $searchForm: $(Recycler.identifiers.searchForm),
+      $searchTextField: $(Recycler.identifiers.searchText),
+      $searchSubmitBtn: $(Recycler.identifiers.searchSubmitBtn),
+      $depthSelector: $(Recycler.identifiers.depthSelector),
+      $tableSelector: $(Recycler.identifiers.tableSelector),
+      $recyclerTable: $(Recycler.identifiers.recyclerTable),
+      $tableBody: $(Recycler.identifiers.recyclerTable).find('tbody'),
+      $paginator: $(Recycler.identifiers.paginator),
+      $reloadAction: $(Recycler.identifiers.reloadAction),
+      $massUndo: $(Recycler.identifiers.massUndo),
+      $massDelete: $(Recycler.identifiers.massDelete),
+      $toggleAll: $(Recycler.identifiers.toggleAll)
+    };
+  };
+
+  /**
+   * Register events
+   */
+  Recycler.registerEvents = function() {
+    // submitting the form
+    Recycler.elements.$searchForm.on('submit', function(e) {
+      e.preventDefault();
+      if (Recycler.elements.$searchTextField.val() !== '') {
+        Recycler.loadDeletedElements();
+      }
+    });
+
+    // changing the search field
+    Recycler.elements.$searchTextField.on('keyup', function() {
+      var $me = $(this);
+
+      if ($me.val() !== '') {
+        Recycler.elements.$searchSubmitBtn.removeClass('disabled');
+      } else {
+        Recycler.elements.$searchSubmitBtn.addClass('disabled');
+        Recycler.loadDeletedElements();
+      }
+    }).clearable(
+      {
+        onClear: function() {
+          Recycler.elements.$searchSubmitBtn.addClass('disabled');
+          Recycler.loadDeletedElements();
+        }
+      }
+    );
+
+    // changing "depth"
+    Recycler.elements.$depthSelector.on('change', function() {
+      $.when(Recycler.loadAvailableTables()).done(function() {
+        Recycler.loadDeletedElements();
+      });
+    });
+
+    // changing "table"
+    Recycler.elements.$tableSelector.on('change', function() {
+      Recycler.paging.currentPage = 1;
+      Recycler.loadDeletedElements();
+    });
+
+    // clicking "recover" in single row
+    Recycler.elements.$recyclerTable.on('click', '[data-action=undo]', Recycler.undoRecord);
+
+    // clicking "delete" in single row
+    Recycler.elements.$recyclerTable.on('click', '[data-action=delete]', Recycler.deleteRecord);
+
+    Recycler.elements.$reloadAction.on('click', function(e) {
+      e.preventDefault();
+      $.when(Recycler.loadAvailableTables()).done(function() {
+        Recycler.loadDeletedElements();
+      });
+    });
+
+    // clicking an action in the paginator
+    Recycler.elements.$paginator.on('click', 'a[data-action]', function(e) {
+      e.preventDefault();
+
+      var $el = $(this),
+        reload = false;
+
+      switch ($el.data('action')) {
+        case 'previous':
+          if (Recycler.paging.currentPage > 1) {
+            Recycler.paging.currentPage--;
+            reload = true;
+          }
+          break;
+        case 'next':
+          if (Recycler.paging.currentPage < Recycler.paging.totalPages) {
+            Recycler.paging.currentPage++;
+            reload = true;
+          }
+          break;
+        case 'page':
+          Recycler.paging.currentPage = parseInt($el.find('span').text());
+          reload = true;
+          break;
+      }
+
+      if (reload) {
+        Recycler.loadDeletedElements();
+      }
+    });
+
+    if (!TYPO3.settings.Recycler.deleteDisable) {
+      Recycler.elements.$massDelete.show();
+    } else {
+      Recycler.elements.$massDelete.remove();
+    }
+
+    Recycler.elements.$recyclerTable.on('show.bs.collapse hide.bs.collapse', 'tr.collapse', function(e) {
+      var $trigger = $(e.currentTarget).prev('tr').find('[data-action=expand]'),
+        $iconEl = $trigger.find('.t3-icon'),
+        removeClass,
+        addClass;
+
+      switch (e.type) {
+        case 'show':
+          removeClass = 't3-icon-pagetree-collapse';
+          addClass = 't3-icon-pagetree-expand';
+          break;
+        case 'hide':
+          removeClass = 't3-icon-pagetree-expand';
+          addClass = 't3-icon-pagetree-collapse';
+          break;
+      }
+
+      $iconEl.removeClass(removeClass).addClass(addClass);
+    });
+
+    // checkboxes in the table
+    Recycler.elements.$toggleAll.on('click', function() {
+      Recycler.allToggled = !Recycler.allToggled;
+      $('input[type="checkbox"]').prop('checked', Recycler.allToggled).trigger('change');
+    });
+    Recycler.elements.$recyclerTable.on('change', 'tr input[type=checkbox]', Recycler.handleCheckboxSelects);
+
+    Recycler.elements.$massUndo.on('click', Recycler.undoRecord);
+    Recycler.elements.$massDelete.on('click', Recycler.deleteRecord);
+  };
+
+  /**
+   * Initialize the recycler module
+   */
+  Recycler.initialize = function() {
+    NProgress.configure({parent: '.module-loading-indicator', showSpinner: false});
+
+    Recycler.getElements();
+    Recycler.registerEvents();
+
+    if (TYPO3.settings.Recycler.depthSelection > 0) {
+      Recycler.elements.$depthSelector.val(TYPO3.settings.Recycler.depthSelection).trigger('change');
+    } else {
+      $.when(Recycler.loadAvailableTables()).done(function() {
+        Recycler.loadDeletedElements();
+      });
+    }
+  };
+
+  /**
+   * Handles the clicks on checkboxes in the records table
+   */
+  Recycler.handleCheckboxSelects = function() {
+    var $checkbox = $(this),
+      $tr = $checkbox.parents('tr'),
+      table = $tr.data('table'),
+      uid = $tr.data('uid'),
+      record = table + ':' + uid;
+
+    if ($checkbox.prop('checked')) {
+      Recycler.markedRecordsForMassAction.push(record);
+      $tr.addClass('warning');
+    } else {
+      var index = Recycler.markedRecordsForMassAction.indexOf(record);
+      if (index > -1) {
+        Recycler.markedRecordsForMassAction.splice(index, 1);
+      }
+      $tr.removeClass('warning');
+    }
+
+    if (Recycler.markedRecordsForMassAction.length > 0) {
+      if (Recycler.elements.$massUndo.hasClass('disabled')) {
+        Recycler.elements.$massUndo.removeClass('disabled');
+      }
+      if (Recycler.elements.$massDelete.hasClass('disabled')) {
+        Recycler.elements.$massDelete.removeClass('disabled');
+      }
+
+      var btnTextUndo = Recycler.createMessage(TYPO3.lang['button.undoselected'], [Recycler.markedRecordsForMassAction.length]),
+        btnTextDelete = Recycler.createMessage(TYPO3.lang['button.deleteselected'], [Recycler.markedRecordsForMassAction.length]);
+
+      Recycler.elements.$massUndo.find('span.text').text(btnTextUndo);
+      Recycler.elements.$massDelete.find('span.text').text(btnTextDelete);
+
+    } else {
+      Recycler.resetMassActionButtons();
+    }
+  };
+
+  /**
+   * Resets the mass action state
+   */
+  Recycler.resetMassActionButtons = function() {
+    Recycler.markedRecordsForMassAction = [];
+    Recycler.elements.$massUndo.addClass('disabled');
+    Recycler.elements.$massUndo.find('span.text').text(TYPO3.lang['button.undo']);
+    Recycler.elements.$massDelete.addClass('disabled');
+    Recycler.elements.$massDelete.find('span.text').text(TYPO3.lang['button.delete']);
+  };
+
+  /**
+   * Loads all tables which contain deleted records.
+   *
+   * @returns {Promise}
+   */
+  Recycler.loadAvailableTables = function() {
+    return $.ajax({
+      url: TYPO3.settings.ajaxUrls['recycler'],
+      dataType: 'json',
+      data: {
+        action: 'getTables',
+        startUid: TYPO3.settings.Recycler.startUid,
+        depth: Recycler.elements.$depthSelector.find('option:selected').val()
+      },
+      beforeSend: function() {
+        NProgress.start();
+        Recycler.elements.$tableSelector.val('');
+        Recycler.paging.currentPage = 1;
+      },
+      success: function(data) {
+        var tables = [];
+        Recycler.elements.$tableSelector.children().remove();
+        $.each(data, function(_, value) {
+          var tableName = value[0],
+            deletedRecords = value[1],
+            tableDescription = value[2];
+
+          if (tableDescription === '') {
+            tableDescription = TYPO3.lang['label_allrecordtypes'];
+          }
+          var optionText = tableDescription + ' (' + deletedRecords + ')';
+          tables.push($('<option />').val(tableName).text(optionText))
+        });
+
+        if (tables.length > 0) {
+          Recycler.elements.$tableSelector.append(tables);
+          if (TYPO3.settings.Recycler.tableSelection !== '') {
+            Recycler.elements.$tableSelector.val(TYPO3.settings.Recycler.tableSelection);
+          }
+        }
+      },
+      complete: function() {
+        NProgress.done();
+      }
+    });
+  };
+
+  /**
+   * Loads the deleted elements, based on the filters
+   *
+   * @returns {Promise}
+   */
+  Recycler.loadDeletedElements = function() {
+    return $.ajax({
+      url: TYPO3.settings.ajaxUrls['recycler'],
+      dataType: 'json',
+      data: {
+        action: 'getDeletedRecords',
+        depth: Recycler.elements.$depthSelector.find('option:selected').val(),
+        startUid: TYPO3.settings.Recycler.startUid,
+        table: Recycler.elements.$tableSelector.find('option:selected').val(),
+        filterTxt: Recycler.elements.$searchTextField.val(),
+        start: (Recycler.paging.currentPage - 1) * Recycler.paging.itemsPerPage,
+        limit: Recycler.paging.itemsPerPage
+      },
+      beforeSend: function() {
+        NProgress.start();
+        Recycler.resetMassActionButtons();
+      },
+      success: function(data) {
+        Recycler.elements.$tableBody.html(data.rows);
+        Recycler.buildPaginator(data.totalItems);
+      },
+      complete: function() {
+        NProgress.done();
+      }
+    });
+  };
+
+  /**
+   *
+   */
+  Recycler.deleteRecord = function() {
+    if (TYPO3.settings.Recycler.deleteDisable) {
+      return;
+    }
+
+    var $tr = $(this).parents('tr'),
+      isMassDelete = $tr.parent().prop('tagName') !== 'TBODY'; // deleteRecord() was invoked by the mass delete button
+
+    var records, message;
+    if (isMassDelete) {
+      records = Recycler.markedRecordsForMassAction;
+      message = TYPO3.lang['modal.massdelete.text'];
+    } else {
+      var uid = $tr.data('uid'),
+        table = $tr.data('table'),
+        recordTitle = $tr.data('recordtitle');
+      records = table + ':' + uid;
+      message = table === 'pages' ? TYPO3.lang['modal.deletepage.text'] : TYPO3.lang['modal.deletecontent.text'];
+      message = Recycler.createMessage(message, [recordTitle, '[' + records + ']']);
+    }
+
+    Modal.confirm(TYPO3.lang['modal.delete.header'], message, Severity.error, [
+      {
+        text: TYPO3.lang['button.cancel'],
+        btnClass: 'btn-default',
+        trigger: function() {
+          Modal.dismiss();
+        }
+      }, {
+        text: TYPO3.lang['button.delete'],
+        btnClass: 'btn-danger',
+        trigger: function() {
+          Recycler.callAjaxAction('delete', typeof records === 'object' ? records : [records], isMassDelete);
+        }
+      }
+    ]);
+  };
+
+  /**
+   *
+   */
+  Recycler.undoRecord = function() {
+    var $tr = $(this).parents('tr'),
+      isMassUndo = $tr.parent().prop('tagName') !== 'TBODY'; // undoRecord() was invoked by the mass delete button
+
+    var records, messageText, recoverPages;
+    if (isMassUndo) {
+      records = Recycler.markedRecordsForMassAction;
+      messageText = TYPO3.lang['modal.massundo.text'];
+      recoverPages = true;
+    } else {
+      var uid = $tr.data('uid'),
+        table = $tr.data('table'),
+        recordTitle = $tr.data('recordtitle');
+
+      records = table + ':' + uid;
+      recoverPages = table === 'pages';
+      messageText = recoverPages ? TYPO3.lang['modal.undopage.text'] : TYPO3.lang['modal.undocontent.text'];
+      messageText = Recycler.createMessage(messageText, [recordTitle, '[' + records + ']']);
+
+      if (recoverPages && $tr.data('parentDeleted')) {
+        messageText += TYPO3.lang['modal.undo.parentpages'];
+      }
+    }
+
+    var $message = null;
+    if (recoverPages) {
+      $message = $('<div />').append(
+        $('<p />').text(messageText),
+        $('<div />', {class: 'checkbox'}).append(
+          $('<label />').append(TYPO3.lang['modal.undo.recursive']).prepend($('<input />', {
+            id: 'undo-recursive',
+            type: 'checkbox'
+          }))
+        )
+      );
+    } else {
+      $message = messageText;
+    }
+
+    Modal.confirm(TYPO3.lang['modal.undo.header'], $message, Severity.ok, [
+      {
+        text: TYPO3.lang['button.cancel'],
+        btnClass: 'btn-default',
+        trigger: function() {
+          Modal.dismiss();
+        }
+      }, {
+        text: TYPO3.lang['button.undo'],
+        btnClass: 'btn-success',
+        trigger: function() {
+          Recycler.callAjaxAction('undo', typeof records === 'object' ? records : [records], isMassUndo, $message.find('#undo-recursive').prop('checked') ? 1 : 0);
+        }
+      }
+    ]);
+  };
+
+  /**
+   *
+   * @param {String} action
+   * @param {Object} records
+   * @param {Boolean} isMassAction
+   * @param {Boolean} recursive
+   */
+  Recycler.callAjaxAction = function(action, records, isMassAction, recursive) {
+    var data = {
+        records: records,
+        action: ''
+      },
+      reloadPageTree = false;
+    if (action === 'undo') {
+      data.action = 'undoRecords';
+      data.recursive = recursive ? 1 : 0;
+      reloadPageTree = true;
+    } else if (action === 'delete') {
+      data.action = 'deleteRecords';
+    } else {
+      return;
+    }
+
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['recycler'],
+      dataType: 'json',
+      data: data,
+      beforeSend: function() {
+        NProgress.start();
+      },
+      success: function(data) {
+        if (data.success) {
+          Notification.success('', data.message);
+        } else {
+          Notification.error('', data.message);
+        }
+
+        // reload recycler data
+        Recycler.paging.currentPage = 1;
+
+        $.when(Recycler.loadAvailableTables()).done(function() {
+          Recycler.loadDeletedElements();
+          if (isMassAction) {
+            Recycler.resetMassActionButtons();
+          }
+
+          if (reloadPageTree) {
+            Recycler.refreshPageTree();
+          }
+
+          // Reset toggle state
+          Recycler.allToggled = false;
+        });
+      },
+      complete: function() {
+        Modal.dismiss();
+        NProgress.done();
+      }
+    });
+  };
+
+  /**
+   * Replaces the placeholders with actual values
+   *
+   * @param {String} message
+   * @param {Array} placeholders
+   * @returns {*}
+   */
+  Recycler.createMessage = function(message, placeholders) {
+    if (typeof message === 'undefined') {
+      return '';
+    }
+
+    return message.replace(
+      /\{([0-9]+)\}/g,
+      function(_, index) {
+        return placeholders[index];
+      }
+    );
+  };
+
+  /**
+   * Reloads the page tree
+   */
+  Recycler.refreshPageTree = function() {
+    if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
+      top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+    }
+  };
+
+  /**
+   * Build the paginator
+   *
+   * @param {Number} totalItems
+   */
+  Recycler.buildPaginator = function(totalItems) {
+    if (totalItems === 0) {
+      Recycler.elements.$paginator.contents().remove();
+      return;
+    }
+
+    Recycler.paging.totalItems = totalItems;
+    Recycler.paging.totalPages = Math.ceil(totalItems / Recycler.paging.itemsPerPage);
+
+    if (Recycler.paging.totalPages === 1) {
+      // early abort if only one page is available
+      Recycler.elements.$paginator.contents().remove();
+      return;
+    }
+
+    var $ul = $('<ul />', {class: 'pagination pagination-block'}),
+      liElements = [],
+      $controlFirstPage = $('<li />').append(
+        $('<a />', {'data-action': 'previous'}).append(
+          $('<span />', {class: 't3-icon fa fa-arrow-left'})
+        )
+      ),
+      $controlLastPage = $('<li />').append(
+        $('<a />', {'data-action': 'next'}).append(
+          $('<span />', {class: 't3-icon fa fa-arrow-right'})
+        )
+      );
+
+    if (Recycler.paging.currentPage === 1) {
+      $controlFirstPage.disablePagingAction();
+    }
+
+    if (Recycler.paging.currentPage === Recycler.paging.totalPages) {
+      $controlLastPage.disablePagingAction();
+    }
+
+    for (var i = 1; i <= Recycler.paging.totalPages; i++) {
+      var $li = $('<li />', {class: Recycler.paging.currentPage === i ? 'active' : ''});
+      $li.append(
+        $('<a />', {'data-action': 'page'}).append(
+          $('<span />').text(i)
+        )
+      );
+      liElements.push($li);
+    }
+
+    $ul.append($controlFirstPage, liElements, $controlLastPage);
+    Recycler.elements.$paginator.html($ul);
+  };
+
+  /**
+   * Changes the markup of a pagination action being disabled
+   */
+  $.fn.disablePagingAction = function() {
+    $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />'));
+  };
+
+  $(Recycler.initialize);
+
+  return Recycler;
 });
diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js
index 05024e8ce64d..ab660653269a 100644
--- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js
+++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryption.js
@@ -1,181 +1,181 @@
 (function() {
-	'use strict';
-
-	/**
-	 * Prevent calling the function multiple times
-	 */
-	var documentReadyFunctionCalled = false;
-
-	var rsaEncryption = function(form) {
-
-		/**
-		 * Submitted form element
-		 */
-		this.form = form;
-
-		/**
-		 * Store found fields in an array
-		 */
-		this.fields = [];
-
-		/**
-		 * XMLHttpRequest
-		 */
-		this.xhr = null;
-
-		/**
-		 * Remember if we fetched the RSA key already
-		 */
-		this.fetchedRsaKey = false;
-
-		/**
-		 * Fetches a new public key by Ajax and encrypts the password for transmission
-		 */
-		this.handleFormSubmitRequest = function(event) {
-			if (event.cancelBubble) {
-				return;
-			}
-
-			var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption;
-			if (!rsaEncryption) {
-				return;
-			}
-			if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) {
-				rsaEncryption.fetchedRsaKey = true;
-				rsaEncryption.ajaxCall(
-					TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP
-					rsaEncryption,
-					function(response) {
-						rsaEncryption.handlePublicKeyResponse(response, rsaEncryption);
-					}
-				);
-
-				if (event.preventDefault) {
-					event.preventDefault();
-				} else if (window.event) {
-					window.event.returnValue = false;
-				}
-			}
-		};
-
-		this.ajaxCall = function(url, rsaEncryption, callback) {
-			// Abort previous request, only last request/generated key pair can be used
-			if (rsaEncryption.xhr) {
-				rsaEncryption.xhr.abort();
-			}
-
-			if (typeof XMLHttpRequest !== 'undefined') {
-				rsaEncryption.xhr = new XMLHttpRequest();
-			} else {
-				var versions = [
-					'MSXML2.XmlHttp.5.0',
-					'MSXML2.XmlHttp.4.0',
-					'MSXML2.XmlHttp.3.0',
-					'MSXML2.XmlHttp.2.0',
-					'Microsoft.XmlHttp'
-				];
-				for (var i = 0, count = versions.length; i < count; i++) {
-					try {
-						rsaEncryption.xhr = new ActiveXObject(versions[i]);
-						break;
-					} catch (e) {
-					}
-				}
-			}
-
-			rsaEncryption.xhr.onreadystatechange = function() {
-				// Only process requests that are ready and have a status (not aborted)
-				if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) {
-					callback(rsaEncryption.xhr);
-				}
-			};
-
-			rsaEncryption.xhr.open('GET', url, true);
-			rsaEncryption.xhr.send('');
-		};
-
-		this.handlePublicKeyResponse = function(response, rsaEncryption) {
-			var publicKey = response.responseText.split(':');
-			if (!publicKey[0] || !publicKey[1]) {
-				alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
-				return false;
-			}
-
-			var rsa = new RSAKey();
-			rsa.setPublic(publicKey[0], publicKey[1]);
-			for (var i = rsaEncryption.fields.length; i--;) {
-				var field = rsaEncryption.fields[i];
-				var encryptedValue = rsa.encrypt(field.value);
-				// Replace value with encrypted value
-				field.value = 'rsa:' + hex2b64(encryptedValue);
-			}
-
-			// Submit the form again but now with encrypted values
-			var form = document.createElement('form');
-			if (form.submit.call) {
-				form.submit.call(rsaEncryption.form);
-			} else {
-				for (var j = rsaEncryption.form.elements.length; j--;) {
-					var submitField = rsaEncryption.form.elements[j];
-					if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") {
-						submitField.click();
-					}
-				}
-			}
-		};
-	};
-
-	/**
-	 * Bind submit handler to all forms with input:data-rsa-encryption fields
-	 */
-	function ready() {
-		if (documentReadyFunctionCalled) {
-			return;
-		}
-
-		documentReadyFunctionCalled = true;
-		rng_seed_time();
-		for (var i = document.forms.length; i--;) {
-			var form = document.forms[i];
-			for (var j = form.elements.length; j--;) {
-				var field = form.elements[j];
-				if (field.nodeName.toLowerCase() === 'input') {
-					var dataAttribute = field.getAttribute('data-rsa-encryption');
-					if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) {
-						if (!form.rsaEncryption) {
-							form.rsaEncryption = new rsaEncryption(form);
-							if (form.addEventListener) {
-								form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false);
-							} else if (form.attachEvent) {
-								form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest);
-							}
-						}
-						form.rsaEncryption.fields.push(field);
-					}
-				}
-			}
-		}
-	}
-
-	// If the document is ready, callback function can be called
-	if (document.readyState === 'complete') {
-		setTimeout(ready, 1);
-	} else {
-		// Install event handlers for older browsers
-		if (document.addEventListener) {
-			// First register DOMContentLoaded event
-			document.addEventListener('DOMContentLoaded', ready, false);
-			// Register backup on windows object
-			window.addEventListener('load', ready, false);
-		} else {
-			// Fallback for Internet Explorer
-			document.attachEvent('onreadystatechange', function() {
-				if (document.readyState === 'complete') {
-					ready();
-				}
-			});
-			window.attachEvent('onload', ready);
-		}
-	}
+  'use strict';
+
+  /**
+   * Prevent calling the function multiple times
+   */
+  var documentReadyFunctionCalled = false;
+
+  var rsaEncryption = function(form) {
+
+    /**
+     * Submitted form element
+     */
+    this.form = form;
+
+    /**
+     * Store found fields in an array
+     */
+    this.fields = [];
+
+    /**
+     * XMLHttpRequest
+     */
+    this.xhr = null;
+
+    /**
+     * Remember if we fetched the RSA key already
+     */
+    this.fetchedRsaKey = false;
+
+    /**
+     * Fetches a new public key by Ajax and encrypts the password for transmission
+     */
+    this.handleFormSubmitRequest = function(event) {
+      if (event.cancelBubble) {
+        return;
+      }
+
+      var rsaEncryption = this.rsaEncryption || event.srcElement.rsaEncryption;
+      if (!rsaEncryption) {
+        return;
+      }
+      if (rsaEncryption.fields.length && !rsaEncryption.fetchedRsaKey) {
+        rsaEncryption.fetchedRsaKey = true;
+        rsaEncryption.ajaxCall(
+          TYPO3RsaEncryptionPublicKeyUrl, // defined in PHP
+          rsaEncryption,
+          function(response) {
+            rsaEncryption.handlePublicKeyResponse(response, rsaEncryption);
+          }
+        );
+
+        if (event.preventDefault) {
+          event.preventDefault();
+        } else if (window.event) {
+          window.event.returnValue = false;
+        }
+      }
+    };
+
+    this.ajaxCall = function(url, rsaEncryption, callback) {
+      // Abort previous request, only last request/generated key pair can be used
+      if (rsaEncryption.xhr) {
+        rsaEncryption.xhr.abort();
+      }
+
+      if (typeof XMLHttpRequest !== 'undefined') {
+        rsaEncryption.xhr = new XMLHttpRequest();
+      } else {
+        var versions = [
+          'MSXML2.XmlHttp.5.0',
+          'MSXML2.XmlHttp.4.0',
+          'MSXML2.XmlHttp.3.0',
+          'MSXML2.XmlHttp.2.0',
+          'Microsoft.XmlHttp'
+        ];
+        for (var i = 0, count = versions.length; i < count; i++) {
+          try {
+            rsaEncryption.xhr = new ActiveXObject(versions[i]);
+            break;
+          } catch (e) {
+          }
+        }
+      }
+
+      rsaEncryption.xhr.onreadystatechange = function() {
+        // Only process requests that are ready and have a status (not aborted)
+        if (rsaEncryption.xhr.readyState === 4 && rsaEncryption.xhr.status > 0) {
+          callback(rsaEncryption.xhr);
+        }
+      };
+
+      rsaEncryption.xhr.open('GET', url, true);
+      rsaEncryption.xhr.send('');
+    };
+
+    this.handlePublicKeyResponse = function(response, rsaEncryption) {
+      var publicKey = response.responseText.split(':');
+      if (!publicKey[0] || !publicKey[1]) {
+        alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
+        return false;
+      }
+
+      var rsa = new RSAKey();
+      rsa.setPublic(publicKey[0], publicKey[1]);
+      for (var i = rsaEncryption.fields.length; i--;) {
+        var field = rsaEncryption.fields[i];
+        var encryptedValue = rsa.encrypt(field.value);
+        // Replace value with encrypted value
+        field.value = 'rsa:' + hex2b64(encryptedValue);
+      }
+
+      // Submit the form again but now with encrypted values
+      var form = document.createElement('form');
+      if (form.submit.call) {
+        form.submit.call(rsaEncryption.form);
+      } else {
+        for (var j = rsaEncryption.form.elements.length; j--;) {
+          var submitField = rsaEncryption.form.elements[j];
+          if (submitField.nodeName.toLowerCase() === 'input' && submitField.type === "submit") {
+            submitField.click();
+          }
+        }
+      }
+    };
+  };
+
+  /**
+   * Bind submit handler to all forms with input:data-rsa-encryption fields
+   */
+  function ready() {
+    if (documentReadyFunctionCalled) {
+      return;
+    }
+
+    documentReadyFunctionCalled = true;
+    rng_seed_time();
+    for (var i = document.forms.length; i--;) {
+      var form = document.forms[i];
+      for (var j = form.elements.length; j--;) {
+        var field = form.elements[j];
+        if (field.nodeName.toLowerCase() === 'input') {
+          var dataAttribute = field.getAttribute('data-rsa-encryption');
+          if (dataAttribute || dataAttribute === '' && field.outerHTML.match(/ data-rsa-encryption=""/)) {
+            if (!form.rsaEncryption) {
+              form.rsaEncryption = new rsaEncryption(form);
+              if (form.addEventListener) {
+                form.addEventListener('submit', form.rsaEncryption.handleFormSubmitRequest, false);
+              } else if (form.attachEvent) {
+                form.attachEvent('onsubmit', form.rsaEncryption.handleFormSubmitRequest);
+              }
+            }
+            form.rsaEncryption.fields.push(field);
+          }
+        }
+      }
+    }
+  }
+
+  // If the document is ready, callback function can be called
+  if (document.readyState === 'complete') {
+    setTimeout(ready, 1);
+  } else {
+    // Install event handlers for older browsers
+    if (document.addEventListener) {
+      // First register DOMContentLoaded event
+      document.addEventListener('DOMContentLoaded', ready, false);
+      // Register backup on windows object
+      window.addEventListener('load', ready, false);
+    } else {
+      // Fallback for Internet Explorer
+      document.attachEvent('onreadystatechange', function() {
+        if (document.readyState === 'complete') {
+          ready();
+        }
+      });
+      window.attachEvent('onload', ready);
+    }
+  }
 
 })();
diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js
index 6ae8daf5c232..68ac12e40bfd 100644
--- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js
+++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaEncryptionModule.js
@@ -16,138 +16,138 @@
  * Object that handles RSA encryption and submission of the form
  */
 define(['jquery', './RsaLibrary'], function($) {
-	'use strict';
-
-	/**
-	 * @type {{$currentForm: null, fetchedRsaKey: boolean, initialize: Function, registerForm: Function, handleFormSubmitRequest: Function, handlePublicKeyResponse: Function}}
-	 * @exports TYPO3/CMS/Rsaauth/RsaEncryptionModule
-	 */
-	var RsaEncryption = {
-
-		/**
-		 * Remember the form which was submitted
-		 */
-		$currentForm: null,
-
-		/**
-		 * Remember if we fetched the RSA key already
-		 */
-		fetchedRsaKey: false,
-
-		/**
-		 * Replace event handler of submit button for given form
-		 *
-		 * @param {Form} form Form DOM object
-		 */
-		registerForm: function(form) {
-			var $form = $(form);
-
-			if ($form.data('rsaRegistered')) {
-				// Do not register form twice
-				return;
-			}
-			// Mark form as registered
-			$form.data('rsaRegistered', true);
-
-			// Store the original submit handler that is executed later
-			$form.data('original-onsubmit', $form.attr('onsubmit'));
-
-			// Remove the original submit handler and register RsaEncryption.handleFormSubmitRequest instead
-			$form.removeAttr('onsubmit').on('submit', RsaEncryption.handleFormSubmitRequest);
-
-			// Bind submit event first (this is a dirty hack with jquery internals, but there is no way around that)
-			var handlers = $._data(form, 'events').submit;
-			var handler = handlers.pop();
-			handlers.unshift(handler);
-		},
-
-		/**
-		 * Fetches a new public key by Ajax and encrypts the password for transmission
-		 *
-		 * @param {Event} event
-		 */
-		handleFormSubmitRequest: function(event) {
-			if (!RsaEncryption.fetchedRsaKey) {
-				event.stopImmediatePropagation();
-
-				RsaEncryption.fetchedRsaKey = true;
-				RsaEncryption.$currentForm = $(this);
-
-				$.ajax({
-					url: TYPO3.settings.ajaxUrls['rsa_publickey'],
-					success: RsaEncryption.handlePublicKeyResponse
-				});
-
-				return false;
-			} else {
-				// we come here again when the submit is triggered below
-				// reset the variable to fetch a new key for next attempt
-				RsaEncryption.fetchedRsaKey = false;
-			}
-		},
-
-		/**
-		 * Parses the Json response and triggers submission of the form
-		 *
-		 * @param {Object} response Ajax response object
-		 */
-		handlePublicKeyResponse: function(response) {
-			var publicKey = response.split(':');
-			if (!publicKey[0] || !publicKey[1]) {
-				alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
-				return;
-			}
-
-			var rsa = new RSAKey();
-			rsa.setPublic(publicKey[0], publicKey[1]);
-			RsaEncryption.$currentForm.find(':input[data-rsa-encryption]').each(function() {
-				var $this = $(this);
-				var encryptedValue = rsa.encrypt($this.val());
-				var dataAttribute = $this.data('rsa-encryption');
-				var rsaValue = 'rsa:' + hex2b64(encryptedValue);
-
-				if (!dataAttribute) {
-					$this.val(rsaValue);
-				} else {
-					var $typo3Field = $('#' + dataAttribute);
-					$typo3Field.val(rsaValue);
-					// Reset user password field to prevent it from being submitted
-					$this.val('');
-				}
-			});
-
-			// Try to fetch the field which submitted the form
-			var $currentField = RsaEncryption.$currentForm.find('input[type=submit]:focus,input[type=image]:focus');
-			if ($currentField.length === 1) {
-				$currentField.trigger('click');
-			} else {
-				// Create a hidden input field to fake pressing the submit button
-				RsaEncryption.$currentForm.append('<input type="hidden" name="commandLI" value="Submit">');
-
-				// Restore the original submit handler
-				var originalOnSubmit = RsaEncryption.$currentForm.data('original-onsubmit');
-				if (typeof originalOnSubmit === 'string' && originalOnSubmit.length > 0) {
-					RsaEncryption.$currentForm.attr('onsubmit', originalOnSubmit);
-					RsaEncryption.$currentForm.removeData('original-onsubmit');
-				}
-
-				// Submit the form
-				RsaEncryption.$currentForm.trigger('submit');
-			}
-		}
-	};
-
-	/**
-	 * Search for forms and add event handler
-	 */
-	RsaEncryption.initialize = function() {
-		$(':input[data-rsa-encryption]').closest('form').each(function() {
-			RsaEncryption.registerForm(this);
-		});
-		rng_seed_time();
-	};
-
-	$(RsaEncryption.initialize);
-
-	return RsaEncryption;
+  'use strict';
+
+  /**
+   * @type {{$currentForm: null, fetchedRsaKey: boolean, initialize: Function, registerForm: Function, handleFormSubmitRequest: Function, handlePublicKeyResponse: Function}}
+   * @exports TYPO3/CMS/Rsaauth/RsaEncryptionModule
+   */
+  var RsaEncryption = {
+
+    /**
+     * Remember the form which was submitted
+     */
+    $currentForm: null,
+
+    /**
+     * Remember if we fetched the RSA key already
+     */
+    fetchedRsaKey: false,
+
+    /**
+     * Replace event handler of submit button for given form
+     *
+     * @param {Form} form Form DOM object
+     */
+    registerForm: function(form) {
+      var $form = $(form);
+
+      if ($form.data('rsaRegistered')) {
+        // Do not register form twice
+        return;
+      }
+      // Mark form as registered
+      $form.data('rsaRegistered', true);
+
+      // Store the original submit handler that is executed later
+      $form.data('original-onsubmit', $form.attr('onsubmit'));
+
+      // Remove the original submit handler and register RsaEncryption.handleFormSubmitRequest instead
+      $form.removeAttr('onsubmit').on('submit', RsaEncryption.handleFormSubmitRequest);
+
+      // Bind submit event first (this is a dirty hack with jquery internals, but there is no way around that)
+      var handlers = $._data(form, 'events').submit;
+      var handler = handlers.pop();
+      handlers.unshift(handler);
+    },
+
+    /**
+     * Fetches a new public key by Ajax and encrypts the password for transmission
+     *
+     * @param {Event} event
+     */
+    handleFormSubmitRequest: function(event) {
+      if (!RsaEncryption.fetchedRsaKey) {
+        event.stopImmediatePropagation();
+
+        RsaEncryption.fetchedRsaKey = true;
+        RsaEncryption.$currentForm = $(this);
+
+        $.ajax({
+          url: TYPO3.settings.ajaxUrls['rsa_publickey'],
+          success: RsaEncryption.handlePublicKeyResponse
+        });
+
+        return false;
+      } else {
+        // we come here again when the submit is triggered below
+        // reset the variable to fetch a new key for next attempt
+        RsaEncryption.fetchedRsaKey = false;
+      }
+    },
+
+    /**
+     * Parses the Json response and triggers submission of the form
+     *
+     * @param {Object} response Ajax response object
+     */
+    handlePublicKeyResponse: function(response) {
+      var publicKey = response.split(':');
+      if (!publicKey[0] || !publicKey[1]) {
+        alert('No public key could be generated. Please inform your TYPO3 administrator to check the OpenSSL settings.');
+        return;
+      }
+
+      var rsa = new RSAKey();
+      rsa.setPublic(publicKey[0], publicKey[1]);
+      RsaEncryption.$currentForm.find(':input[data-rsa-encryption]').each(function() {
+        var $this = $(this);
+        var encryptedValue = rsa.encrypt($this.val());
+        var dataAttribute = $this.data('rsa-encryption');
+        var rsaValue = 'rsa:' + hex2b64(encryptedValue);
+
+        if (!dataAttribute) {
+          $this.val(rsaValue);
+        } else {
+          var $typo3Field = $('#' + dataAttribute);
+          $typo3Field.val(rsaValue);
+          // Reset user password field to prevent it from being submitted
+          $this.val('');
+        }
+      });
+
+      // Try to fetch the field which submitted the form
+      var $currentField = RsaEncryption.$currentForm.find('input[type=submit]:focus,input[type=image]:focus');
+      if ($currentField.length === 1) {
+        $currentField.trigger('click');
+      } else {
+        // Create a hidden input field to fake pressing the submit button
+        RsaEncryption.$currentForm.append('<input type="hidden" name="commandLI" value="Submit">');
+
+        // Restore the original submit handler
+        var originalOnSubmit = RsaEncryption.$currentForm.data('original-onsubmit');
+        if (typeof originalOnSubmit === 'string' && originalOnSubmit.length > 0) {
+          RsaEncryption.$currentForm.attr('onsubmit', originalOnSubmit);
+          RsaEncryption.$currentForm.removeData('original-onsubmit');
+        }
+
+        // Submit the form
+        RsaEncryption.$currentForm.trigger('submit');
+      }
+    }
+  };
+
+  /**
+   * Search for forms and add event handler
+   */
+  RsaEncryption.initialize = function() {
+    $(':input[data-rsa-encryption]').closest('form').each(function() {
+      RsaEncryption.registerForm(this);
+    });
+    rng_seed_time();
+  };
+
+  $(RsaEncryption.initialize);
+
+  return RsaEncryption;
 });
diff --git a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js
index 96244d0412cc..9a0a2050fc6b 100644
--- a/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js
+++ b/typo3/sysext/rsaauth/Resources/Public/JavaScript/RsaLibrary.js
@@ -1,76 +1,76 @@
 //
 // base64.js
 //
-var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-var b64padchar="=";
+var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var b64padchar = "=";
 
 function hex2b64(h) {
-	var i;
-	var c;
-	var ret = "";
-	for(i = 0; i+3 <= h.length; i+=3) {
-		c = parseInt(h.substring(i,i+3),16);
-		ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
-	}
-	if(i+1 == h.length) {
-		c = parseInt(h.substring(i,i+1),16);
-		ret += b64map.charAt(c << 2);
-	}
-	else if(i+2 == h.length) {
-		c = parseInt(h.substring(i,i+2),16);
-		ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
-	}
-	while((ret.length & 3) > 0) ret += b64padchar;
-	return ret;
+  var i;
+  var c;
+  var ret = "";
+  for (i = 0; i + 3 <= h.length; i += 3) {
+    c = parseInt(h.substring(i, i + 3), 16);
+    ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
+  }
+  if (i + 1 == h.length) {
+    c = parseInt(h.substring(i, i + 1), 16);
+    ret += b64map.charAt(c << 2);
+  }
+  else if (i + 2 == h.length) {
+    c = parseInt(h.substring(i, i + 2), 16);
+    ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
+  }
+  while ((ret.length & 3) > 0) ret += b64padchar;
+  return ret;
 }
 
 // convert a base64 string to hex
 function b64tohex(s) {
-	var ret = "";
-	var i;
-	var k = 0; // b64 state, 0-3
-	var slop;
-	for(i = 0; i < s.length; ++i) {
-		if(s.charAt(i) == b64padchar) break;
-		v = b64map.indexOf(s.charAt(i));
-		if(v < 0) continue;
-		if(k == 0) {
-			ret += int2char(v >> 2);
-			slop = v & 3;
-			k = 1;
-		}
-		else if(k == 1) {
-			ret += int2char((slop << 2) | (v >> 4));
-			slop = v & 0xf;
-			k = 2;
-		}
-		else if(k == 2) {
-			ret += int2char(slop);
-			ret += int2char(v >> 2);
-			slop = v & 3;
-			k = 3;
-		}
-		else {
-			ret += int2char((slop << 2) | (v >> 4));
-			ret += int2char(v & 0xf);
-			k = 0;
-		}
-	}
-	if(k == 1)
-		ret += int2char(slop << 2);
-	return ret;
+  var ret = "";
+  var i;
+  var k = 0; // b64 state, 0-3
+  var slop;
+  for (i = 0; i < s.length; ++i) {
+    if (s.charAt(i) == b64padchar) break;
+    v = b64map.indexOf(s.charAt(i));
+    if (v < 0) continue;
+    if (k == 0) {
+      ret += int2char(v >> 2);
+      slop = v & 3;
+      k = 1;
+    }
+    else if (k == 1) {
+      ret += int2char((slop << 2) | (v >> 4));
+      slop = v & 0xf;
+      k = 2;
+    }
+    else if (k == 2) {
+      ret += int2char(slop);
+      ret += int2char(v >> 2);
+      slop = v & 3;
+      k = 3;
+    }
+    else {
+      ret += int2char((slop << 2) | (v >> 4));
+      ret += int2char(v & 0xf);
+      k = 0;
+    }
+  }
+  if (k == 1)
+    ret += int2char(slop << 2);
+  return ret;
 }
 
 // convert a base64 string to a byte/number array
 function b64toBA(s) {
-	//piggyback on b64tohex for now, optimize later
-	var h = b64tohex(s);
-	var i;
-	var a = new Array();
-	for(i = 0; 2*i < h.length; ++i) {
-		a[i] = parseInt(h.substring(2*i,2*i+2),16);
-	}
-	return a;
+  //piggyback on b64tohex for now, optimize later
+  var h = b64tohex(s);
+  var i;
+  var a = new Array();
+  for (i = 0; 2 * i < h.length; ++i) {
+    a[i] = parseInt(h.substring(2 * i, 2 * i + 2), 16);
+  }
+  return a;
 }
 
 //
@@ -88,18 +88,20 @@ var dbits;
 
 // JavaScript engine analysis
 var canary = 0xdeadbeefcafe;
-var j_lm = ((canary&0xffffff)==0xefcafe);
+var j_lm = ((canary & 0xffffff) == 0xefcafe);
 
 // (public) Constructor
-function BigInteger(a,b,c) {
-	if(a != null)
-		if("number" == typeof a) this.fromNumber(a,b,c);
-		else if(b == null && "string" != typeof a) this.fromString(a,256);
-		else this.fromString(a,b);
+function BigInteger(a, b, c) {
+  if (a != null)
+    if ("number" == typeof a) this.fromNumber(a, b, c);
+    else if (b == null && "string" != typeof a) this.fromString(a, 256);
+    else this.fromString(a, b);
 }
 
 // return new, unset BigInteger
-function nbi() { return new BigInteger(null); }
+function nbi() {
+  return new BigInteger(null);
+}
 
 // am: Compute w_j += (x*this_i), propagate carries,
 // c is initial carry, returns final carry.
@@ -109,391 +111,457 @@ function nbi() { return new BigInteger(null); }
 // am1: use a single mult and divide to get the high bits,
 // max digit bits should be 26 because
 // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
-function am1(i,x,w,j,c,n) {
-	while(--n >= 0) {
-		var v = x*this[i++]+w[j]+c;
-		c = Math.floor(v/0x4000000);
-		w[j++] = v&0x3ffffff;
-	}
-	return c;
+function am1(i, x, w, j, c, n) {
+  while (--n >= 0) {
+    var v = x * this[i++] + w[j] + c;
+    c = Math.floor(v / 0x4000000);
+    w[j++] = v & 0x3ffffff;
+  }
+  return c;
 }
+
 // am2 avoids a big mult-and-extract completely.
 // Max digit bits should be <= 30 because we do bitwise ops
 // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
-function am2(i,x,w,j,c,n) {
-	var xl = x&0x7fff, xh = x>>15;
-	while(--n >= 0) {
-		var l = this[i]&0x7fff;
-		var h = this[i++]>>15;
-		var m = xh*l+h*xl;
-		l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
-		c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
-		w[j++] = l&0x3fffffff;
-	}
-	return c;
+function am2(i, x, w, j, c, n) {
+  var xl = x & 0x7fff, xh = x >> 15;
+  while (--n >= 0) {
+    var l = this[i] & 0x7fff;
+    var h = this[i++] >> 15;
+    var m = xh * l + h * xl;
+    l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff);
+    c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30);
+    w[j++] = l & 0x3fffffff;
+  }
+  return c;
 }
+
 // Alternately, set max digit bits to 28 since some
 // browsers slow down when dealing with 32-bit numbers.
-function am3(i,x,w,j,c,n) {
-	var xl = x&0x3fff, xh = x>>14;
-	while(--n >= 0) {
-		var l = this[i]&0x3fff;
-		var h = this[i++]>>14;
-		var m = xh*l+h*xl;
-		l = xl*l+((m&0x3fff)<<14)+w[j]+c;
-		c = (l>>28)+(m>>14)+xh*h;
-		w[j++] = l&0xfffffff;
-	}
-	return c;
-}
-if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
-	BigInteger.prototype.am = am2;
-	dbits = 30;
-}
-else if(j_lm && (navigator.appName != "Netscape")) {
-	BigInteger.prototype.am = am1;
-	dbits = 26;
+function am3(i, x, w, j, c, n) {
+  var xl = x & 0x3fff, xh = x >> 14;
+  while (--n >= 0) {
+    var l = this[i] & 0x3fff;
+    var h = this[i++] >> 14;
+    var m = xh * l + h * xl;
+    l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
+    c = (l >> 28) + (m >> 14) + xh * h;
+    w[j++] = l & 0xfffffff;
+  }
+  return c;
+}
+
+if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
+  BigInteger.prototype.am = am2;
+  dbits = 30;
+}
+else if (j_lm && (navigator.appName != "Netscape")) {
+  BigInteger.prototype.am = am1;
+  dbits = 26;
 }
 else { // Mozilla/Netscape seems to prefer am3
-	BigInteger.prototype.am = am3;
-	dbits = 28;
+  BigInteger.prototype.am = am3;
+  dbits = 28;
 }
 
 BigInteger.prototype.DB = dbits;
-BigInteger.prototype.DM = ((1<<dbits)-1);
-BigInteger.prototype.DV = (1<<dbits);
+BigInteger.prototype.DM = ((1 << dbits) - 1);
+BigInteger.prototype.DV = (1 << dbits);
 
 var BI_FP = 52;
-BigInteger.prototype.FV = Math.pow(2,BI_FP);
-BigInteger.prototype.F1 = BI_FP-dbits;
-BigInteger.prototype.F2 = 2*dbits-BI_FP;
+BigInteger.prototype.FV = Math.pow(2, BI_FP);
+BigInteger.prototype.F1 = BI_FP - dbits;
+BigInteger.prototype.F2 = 2 * dbits - BI_FP;
 
 // Digit conversions
 var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
 var BI_RC = new Array();
-var rr,vv;
+var rr, vv;
 rr = "0".charCodeAt(0);
-for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
+for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
 rr = "a".charCodeAt(0);
-for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
 rr = "A".charCodeAt(0);
-for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
+for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
 
-function int2char(n) { return BI_RM.charAt(n); }
-function intAt(s,i) {
-	var c = BI_RC[s.charCodeAt(i)];
-	return (c==null)?-1:c;
+function int2char(n) {
+  return BI_RM.charAt(n);
+}
+
+function intAt(s, i) {
+  var c = BI_RC[s.charCodeAt(i)];
+  return (c == null) ? -1 : c;
 }
 
 // (protected) copy this to r
 function bnpCopyTo(r) {
-	for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
-	r.t = this.t;
-	r.s = this.s;
+  for (var i = this.t - 1; i >= 0; --i) r[i] = this[i];
+  r.t = this.t;
+  r.s = this.s;
 }
 
 // (protected) set from integer value x, -DV <= x < DV
 function bnpFromInt(x) {
-	this.t = 1;
-	this.s = (x<0)?-1:0;
-	if(x > 0) this[0] = x;
-	else if(x < -1) this[0] = x+this.DV;
-	else this.t = 0;
+  this.t = 1;
+  this.s = (x < 0) ? -1 : 0;
+  if (x > 0) this[0] = x;
+  else if (x < -1) this[0] = x + this.DV;
+  else this.t = 0;
 }
 
 // return bigint initialized to value
-function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
+function nbv(i) {
+  var r = nbi();
+  r.fromInt(i);
+  return r;
+}
 
 // (protected) set from string and radix
-function bnpFromString(s,b) {
-	var k;
-	if(b == 16) k = 4;
-	else if(b == 8) k = 3;
-	else if(b == 256) k = 8; // byte array
-	else if(b == 2) k = 1;
-	else if(b == 32) k = 5;
-	else if(b == 4) k = 2;
-	else { this.fromRadix(s,b); return; }
-	this.t = 0;
-	this.s = 0;
-	var i = s.length, mi = false, sh = 0;
-	while(--i >= 0) {
-		var x = (k==8)?s[i]&0xff:intAt(s,i);
-		if(x < 0) {
-			if(s.charAt(i) == "-") mi = true;
-			continue;
-		}
-		mi = false;
-		if(sh == 0)
-			this[this.t++] = x;
-		else if(sh+k > this.DB) {
-			this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
-			this[this.t++] = (x>>(this.DB-sh));
-		}
-		else
-			this[this.t-1] |= x<<sh;
-		sh += k;
-		if(sh >= this.DB) sh -= this.DB;
-	}
-	if(k == 8 && (s[0]&0x80) != 0) {
-		this.s = -1;
-		if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
-	}
-	this.clamp();
-	if(mi) BigInteger.ZERO.subTo(this,this);
+function bnpFromString(s, b) {
+  var k;
+  if (b == 16) k = 4;
+  else if (b == 8) k = 3;
+  else if (b == 256) k = 8; // byte array
+  else if (b == 2) k = 1;
+  else if (b == 32) k = 5;
+  else if (b == 4) k = 2;
+  else {
+    this.fromRadix(s, b);
+    return;
+  }
+  this.t = 0;
+  this.s = 0;
+  var i = s.length, mi = false, sh = 0;
+  while (--i >= 0) {
+    var x = (k == 8) ? s[i] & 0xff : intAt(s, i);
+    if (x < 0) {
+      if (s.charAt(i) == "-") mi = true;
+      continue;
+    }
+    mi = false;
+    if (sh == 0)
+      this[this.t++] = x;
+    else if (sh + k > this.DB) {
+      this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh;
+      this[this.t++] = (x >> (this.DB - sh));
+    }
+    else
+      this[this.t - 1] |= x << sh;
+    sh += k;
+    if (sh >= this.DB) sh -= this.DB;
+  }
+  if (k == 8 && (s[0] & 0x80) != 0) {
+    this.s = -1;
+    if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh;
+  }
+  this.clamp();
+  if (mi) BigInteger.ZERO.subTo(this, this);
 }
 
 // (protected) clamp off excess high words
 function bnpClamp() {
-	var c = this.s&this.DM;
-	while(this.t > 0 && this[this.t-1] == c) --this.t;
+  var c = this.s & this.DM;
+  while (this.t > 0 && this[this.t - 1] == c) --this.t;
 }
 
 // (public) return string representation in given radix
 function bnToString(b) {
-	if(this.s < 0) return "-"+this.negate().toString(b);
-	var k;
-	if(b == 16) k = 4;
-	else if(b == 8) k = 3;
-	else if(b == 2) k = 1;
-	else if(b == 32) k = 5;
-	else if(b == 4) k = 2;
-	else return this.toRadix(b);
-	var km = (1<<k)-1, d, m = false, r = "", i = this.t;
-	var p = this.DB-(i*this.DB)%k;
-	if(i-- > 0) {
-		if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
-		while(i >= 0) {
-			if(p < k) {
-				d = (this[i]&((1<<p)-1))<<(k-p);
-				d |= this[--i]>>(p+=this.DB-k);
-			}
-			else {
-				d = (this[i]>>(p-=k))&km;
-				if(p <= 0) { p += this.DB; --i; }
-			}
-			if(d > 0) m = true;
-			if(m) r += int2char(d);
-		}
-	}
-	return m?r:"0";
+  if (this.s < 0) return "-" + this.negate().toString(b);
+  var k;
+  if (b == 16) k = 4;
+  else if (b == 8) k = 3;
+  else if (b == 2) k = 1;
+  else if (b == 32) k = 5;
+  else if (b == 4) k = 2;
+  else return this.toRadix(b);
+  var km = (1 << k) - 1, d, m = false, r = "", i = this.t;
+  var p = this.DB - (i * this.DB) % k;
+  if (i-- > 0) {
+    if (p < this.DB && (d = this[i] >> p) > 0) {
+      m = true;
+      r = int2char(d);
+    }
+    while (i >= 0) {
+      if (p < k) {
+        d = (this[i] & ((1 << p) - 1)) << (k - p);
+        d |= this[--i] >> (p += this.DB - k);
+      }
+      else {
+        d = (this[i] >> (p -= k)) & km;
+        if (p <= 0) {
+          p += this.DB;
+          --i;
+        }
+      }
+      if (d > 0) m = true;
+      if (m) r += int2char(d);
+    }
+  }
+  return m ? r : "0";
 }
 
 // (public) -this
-function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
+function bnNegate() {
+  var r = nbi();
+  BigInteger.ZERO.subTo(this, r);
+  return r;
+}
 
 // (public) |this|
-function bnAbs() { return (this.s<0)?this.negate():this; }
+function bnAbs() {
+  return (this.s < 0) ? this.negate() : this;
+}
 
 // (public) return + if this > a, - if this < a, 0 if equal
 function bnCompareTo(a) {
-	var r = this.s-a.s;
-	if(r != 0) return r;
-	var i = this.t;
-	r = i-a.t;
-	if(r != 0) return (this.s<0)?-r:r;
-	while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
-	return 0;
+  var r = this.s - a.s;
+  if (r != 0) return r;
+  var i = this.t;
+  r = i - a.t;
+  if (r != 0) return (this.s < 0) ? -r : r;
+  while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r;
+  return 0;
 }
 
 // returns bit length of the integer x
 function nbits(x) {
-	var r = 1, t;
-	if((t=x>>>16) != 0) { x = t; r += 16; }
-	if((t=x>>8) != 0) { x = t; r += 8; }
-	if((t=x>>4) != 0) { x = t; r += 4; }
-	if((t=x>>2) != 0) { x = t; r += 2; }
-	if((t=x>>1) != 0) { x = t; r += 1; }
-	return r;
+  var r = 1, t;
+  if ((t = x >>> 16) != 0) {
+    x = t;
+    r += 16;
+  }
+  if ((t = x >> 8) != 0) {
+    x = t;
+    r += 8;
+  }
+  if ((t = x >> 4) != 0) {
+    x = t;
+    r += 4;
+  }
+  if ((t = x >> 2) != 0) {
+    x = t;
+    r += 2;
+  }
+  if ((t = x >> 1) != 0) {
+    x = t;
+    r += 1;
+  }
+  return r;
 }
 
 // (public) return the number of bits in "this"
 function bnBitLength() {
-	if(this.t <= 0) return 0;
-	return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
+  if (this.t <= 0) return 0;
+  return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM));
 }
 
 // (protected) r = this << n*DB
-function bnpDLShiftTo(n,r) {
-	var i;
-	for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
-	for(i = n-1; i >= 0; --i) r[i] = 0;
-	r.t = this.t+n;
-	r.s = this.s;
+function bnpDLShiftTo(n, r) {
+  var i;
+  for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i];
+  for (i = n - 1; i >= 0; --i) r[i] = 0;
+  r.t = this.t + n;
+  r.s = this.s;
 }
 
 // (protected) r = this >> n*DB
-function bnpDRShiftTo(n,r) {
-	for(var i = n; i < this.t; ++i) r[i-n] = this[i];
-	r.t = Math.max(this.t-n,0);
-	r.s = this.s;
+function bnpDRShiftTo(n, r) {
+  for (var i = n; i < this.t; ++i) r[i - n] = this[i];
+  r.t = Math.max(this.t - n, 0);
+  r.s = this.s;
 }
 
 // (protected) r = this << n
-function bnpLShiftTo(n,r) {
-	var bs = n%this.DB;
-	var cbs = this.DB-bs;
-	var bm = (1<<cbs)-1;
-	var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
-	for(i = this.t-1; i >= 0; --i) {
-		r[i+ds+1] = (this[i]>>cbs)|c;
-		c = (this[i]&bm)<<bs;
-	}
-	for(i = ds-1; i >= 0; --i) r[i] = 0;
-	r[ds] = c;
-	r.t = this.t+ds+1;
-	r.s = this.s;
-	r.clamp();
+function bnpLShiftTo(n, r) {
+  var bs = n % this.DB;
+  var cbs = this.DB - bs;
+  var bm = (1 << cbs) - 1;
+  var ds = Math.floor(n / this.DB), c = (this.s << bs) & this.DM, i;
+  for (i = this.t - 1; i >= 0; --i) {
+    r[i + ds + 1] = (this[i] >> cbs) | c;
+    c = (this[i] & bm) << bs;
+  }
+  for (i = ds - 1; i >= 0; --i) r[i] = 0;
+  r[ds] = c;
+  r.t = this.t + ds + 1;
+  r.s = this.s;
+  r.clamp();
 }
 
 // (protected) r = this >> n
-function bnpRShiftTo(n,r) {
-	r.s = this.s;
-	var ds = Math.floor(n/this.DB);
-	if(ds >= this.t) { r.t = 0; return; }
-	var bs = n%this.DB;
-	var cbs = this.DB-bs;
-	var bm = (1<<bs)-1;
-	r[0] = this[ds]>>bs;
-	for(var i = ds+1; i < this.t; ++i) {
-		r[i-ds-1] |= (this[i]&bm)<<cbs;
-		r[i-ds] = this[i]>>bs;
-	}
-	if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
-	r.t = this.t-ds;
-	r.clamp();
+function bnpRShiftTo(n, r) {
+  r.s = this.s;
+  var ds = Math.floor(n / this.DB);
+  if (ds >= this.t) {
+    r.t = 0;
+    return;
+  }
+  var bs = n % this.DB;
+  var cbs = this.DB - bs;
+  var bm = (1 << bs) - 1;
+  r[0] = this[ds] >> bs;
+  for (var i = ds + 1; i < this.t; ++i) {
+    r[i - ds - 1] |= (this[i] & bm) << cbs;
+    r[i - ds] = this[i] >> bs;
+  }
+  if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs;
+  r.t = this.t - ds;
+  r.clamp();
 }
 
 // (protected) r = this - a
-function bnpSubTo(a,r) {
-	var i = 0, c = 0, m = Math.min(a.t,this.t);
-	while(i < m) {
-		c += this[i]-a[i];
-		r[i++] = c&this.DM;
-		c >>= this.DB;
-	}
-	if(a.t < this.t) {
-		c -= a.s;
-		while(i < this.t) {
-			c += this[i];
-			r[i++] = c&this.DM;
-			c >>= this.DB;
-		}
-		c += this.s;
-	}
-	else {
-		c += this.s;
-		while(i < a.t) {
-			c -= a[i];
-			r[i++] = c&this.DM;
-			c >>= this.DB;
-		}
-		c -= a.s;
-	}
-	r.s = (c<0)?-1:0;
-	if(c < -1) r[i++] = this.DV+c;
-	else if(c > 0) r[i++] = c;
-	r.t = i;
-	r.clamp();
+function bnpSubTo(a, r) {
+  var i = 0, c = 0, m = Math.min(a.t, this.t);
+  while (i < m) {
+    c += this[i] - a[i];
+    r[i++] = c & this.DM;
+    c >>= this.DB;
+  }
+  if (a.t < this.t) {
+    c -= a.s;
+    while (i < this.t) {
+      c += this[i];
+      r[i++] = c & this.DM;
+      c >>= this.DB;
+    }
+    c += this.s;
+  }
+  else {
+    c += this.s;
+    while (i < a.t) {
+      c -= a[i];
+      r[i++] = c & this.DM;
+      c >>= this.DB;
+    }
+    c -= a.s;
+  }
+  r.s = (c < 0) ? -1 : 0;
+  if (c < -1) r[i++] = this.DV + c;
+  else if (c > 0) r[i++] = c;
+  r.t = i;
+  r.clamp();
 }
 
 // (protected) r = this * a, r != this,a (HAC 14.12)
 // "this" should be the larger one if appropriate.
-function bnpMultiplyTo(a,r) {
-	var x = this.abs(), y = a.abs();
-	var i = x.t;
-	r.t = i+y.t;
-	while(--i >= 0) r[i] = 0;
-	for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
-	r.s = 0;
-	r.clamp();
-	if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
+function bnpMultiplyTo(a, r) {
+  var x = this.abs(), y = a.abs();
+  var i = x.t;
+  r.t = i + y.t;
+  while (--i >= 0) r[i] = 0;
+  for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t);
+  r.s = 0;
+  r.clamp();
+  if (this.s != a.s) BigInteger.ZERO.subTo(r, r);
 }
 
 // (protected) r = this^2, r != this (HAC 14.16)
 function bnpSquareTo(r) {
-	var x = this.abs();
-	var i = r.t = 2*x.t;
-	while(--i >= 0) r[i] = 0;
-	for(i = 0; i < x.t-1; ++i) {
-		var c = x.am(i,x[i],r,2*i,0,1);
-		if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
-			r[i+x.t] -= x.DV;
-			r[i+x.t+1] = 1;
-		}
-	}
-	if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
-	r.s = 0;
-	r.clamp();
+  var x = this.abs();
+  var i = r.t = 2 * x.t;
+  while (--i >= 0) r[i] = 0;
+  for (i = 0; i < x.t - 1; ++i) {
+    var c = x.am(i, x[i], r, 2 * i, 0, 1);
+    if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) {
+      r[i + x.t] -= x.DV;
+      r[i + x.t + 1] = 1;
+    }
+  }
+  if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1);
+  r.s = 0;
+  r.clamp();
 }
 
 // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
 // r != q, this != m.  q or r may be null.
-function bnpDivRemTo(m,q,r) {
-	var pm = m.abs();
-	if(pm.t <= 0) return;
-	var pt = this.abs();
-	if(pt.t < pm.t) {
-		if(q != null) q.fromInt(0);
-		if(r != null) this.copyTo(r);
-		return;
-	}
-	if(r == null) r = nbi();
-	var y = nbi(), ts = this.s, ms = m.s;
-	var nsh = this.DB-nbits(pm[pm.t-1]);	// normalize modulus
-	if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
-	else { pm.copyTo(y); pt.copyTo(r); }
-	var ys = y.t;
-	var y0 = y[ys-1];
-	if(y0 == 0) return;
-	var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
-	var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
-	var i = r.t, j = i-ys, t = (q==null)?nbi():q;
-	y.dlShiftTo(j,t);
-	if(r.compareTo(t) >= 0) {
-		r[r.t++] = 1;
-		r.subTo(t,r);
-	}
-	BigInteger.ONE.dlShiftTo(ys,t);
-	t.subTo(y,y);	// "negative" y so we can replace sub with am later
-	while(y.t < ys) y[y.t++] = 0;
-	while(--j >= 0) {
-		// Estimate quotient digit
-		var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
-		if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
-			y.dlShiftTo(j,t);
-			r.subTo(t,r);
-			while(r[i] < --qd) r.subTo(t,r);
-		}
-	}
-	if(q != null) {
-		r.drShiftTo(ys,q);
-		if(ts != ms) BigInteger.ZERO.subTo(q,q);
-	}
-	r.t = ys;
-	r.clamp();
-	if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
-	if(ts < 0) BigInteger.ZERO.subTo(r,r);
+function bnpDivRemTo(m, q, r) {
+  var pm = m.abs();
+  if (pm.t <= 0) return;
+  var pt = this.abs();
+  if (pt.t < pm.t) {
+    if (q != null) q.fromInt(0);
+    if (r != null) this.copyTo(r);
+    return;
+  }
+  if (r == null) r = nbi();
+  var y = nbi(), ts = this.s, ms = m.s;
+  var nsh = this.DB - nbits(pm[pm.t - 1]);	// normalize modulus
+  if (nsh > 0) {
+    pm.lShiftTo(nsh, y);
+    pt.lShiftTo(nsh, r);
+  }
+  else {
+    pm.copyTo(y);
+    pt.copyTo(r);
+  }
+  var ys = y.t;
+  var y0 = y[ys - 1];
+  if (y0 == 0) return;
+  var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0);
+  var d1 = this.FV / yt, d2 = (1 << this.F1) / yt, e = 1 << this.F2;
+  var i = r.t, j = i - ys, t = (q == null) ? nbi() : q;
+  y.dlShiftTo(j, t);
+  if (r.compareTo(t) >= 0) {
+    r[r.t++] = 1;
+    r.subTo(t, r);
+  }
+  BigInteger.ONE.dlShiftTo(ys, t);
+  t.subTo(y, y);	// "negative" y so we can replace sub with am later
+  while (y.t < ys) y[y.t++] = 0;
+  while (--j >= 0) {
+    // Estimate quotient digit
+    var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
+    if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) {	// Try it out
+      y.dlShiftTo(j, t);
+      r.subTo(t, r);
+      while (r[i] < --qd) r.subTo(t, r);
+    }
+  }
+  if (q != null) {
+    r.drShiftTo(ys, q);
+    if (ts != ms) BigInteger.ZERO.subTo(q, q);
+  }
+  r.t = ys;
+  r.clamp();
+  if (nsh > 0) r.rShiftTo(nsh, r);	// Denormalize remainder
+  if (ts < 0) BigInteger.ZERO.subTo(r, r);
 }
 
 // (public) this mod a
 function bnMod(a) {
-	var r = nbi();
-	this.abs().divRemTo(a,null,r);
-	if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
-	return r;
+  var r = nbi();
+  this.abs().divRemTo(a, null, r);
+  if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r);
+  return r;
 }
 
 // Modular reduction using "classic" algorithm
-function Classic(m) { this.m = m; }
+function Classic(m) {
+  this.m = m;
+}
+
 function cConvert(x) {
-	if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
-	else return x;
+  if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
+  else return x;
+}
+
+function cRevert(x) {
+  return x;
+}
+
+function cReduce(x) {
+  x.divRemTo(this.m, null, x);
+}
+
+function cMulTo(x, y, r) {
+  x.multiplyTo(y, r);
+  this.reduce(r);
+}
+
+function cSqrTo(x, r) {
+  x.squareTo(r);
+  this.reduce(r);
 }
-function cRevert(x) { return x; }
-function cReduce(x) { x.divRemTo(this.m,null,x); }
-function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
-function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
 
 Classic.prototype.convert = cConvert;
 Classic.prototype.revert = cRevert;
@@ -512,71 +580,80 @@ Classic.prototype.sqrTo = cSqrTo;
 // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
 // JS multiply "overflows" differently from C/C++, so care is needed here.
 function bnpInvDigit() {
-	if(this.t < 1) return 0;
-	var x = this[0];
-	if((x&1) == 0) return 0;
-	var y = x&3;		// y == 1/x mod 2^2
-	y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
-	y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
-	y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
-	// last step - calculate inverse mod DV directly;
-	// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
-	y = (y*(2-x*y%this.DV))%this.DV;		// y == 1/x mod 2^dbits
-	// we really want the negative inverse, and -DV < y < DV
-	return (y>0)?this.DV-y:-y;
+  if (this.t < 1) return 0;
+  var x = this[0];
+  if ((x & 1) == 0) return 0;
+  var y = x & 3;		// y == 1/x mod 2^2
+  y = (y * (2 - (x & 0xf) * y)) & 0xf;	// y == 1/x mod 2^4
+  y = (y * (2 - (x & 0xff) * y)) & 0xff;	// y == 1/x mod 2^8
+  y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff;	// y == 1/x mod 2^16
+  // last step - calculate inverse mod DV directly;
+  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
+  y = (y * (2 - x * y % this.DV)) % this.DV;		// y == 1/x mod 2^dbits
+  // we really want the negative inverse, and -DV < y < DV
+  return (y > 0) ? this.DV - y : -y;
 }
 
 // Montgomery reduction
 function Montgomery(m) {
-	this.m = m;
-	this.mp = m.invDigit();
-	this.mpl = this.mp&0x7fff;
-	this.mph = this.mp>>15;
-	this.um = (1<<(m.DB-15))-1;
-	this.mt2 = 2*m.t;
+  this.m = m;
+  this.mp = m.invDigit();
+  this.mpl = this.mp & 0x7fff;
+  this.mph = this.mp >> 15;
+  this.um = (1 << (m.DB - 15)) - 1;
+  this.mt2 = 2 * m.t;
 }
 
 // xR mod m
 function montConvert(x) {
-	var r = nbi();
-	x.abs().dlShiftTo(this.m.t,r);
-	r.divRemTo(this.m,null,r);
-	if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
-	return r;
+  var r = nbi();
+  x.abs().dlShiftTo(this.m.t, r);
+  r.divRemTo(this.m, null, r);
+  if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r);
+  return r;
 }
 
 // x/R mod m
 function montRevert(x) {
-	var r = nbi();
-	x.copyTo(r);
-	this.reduce(r);
-	return r;
+  var r = nbi();
+  x.copyTo(r);
+  this.reduce(r);
+  return r;
 }
 
 // x = x/R mod m (HAC 14.32)
 function montReduce(x) {
-	while(x.t <= this.mt2)	// pad x so am has enough room later
-		x[x.t++] = 0;
-	for(var i = 0; i < this.m.t; ++i) {
-		// faster way of calculating u0 = x[i]*mp mod DV
-		var j = x[i]&0x7fff;
-		var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
-		// use am to combine the multiply-shift-add into one call
-		j = i+this.m.t;
-		x[j] += this.m.am(0,u0,x,i,0,this.m.t);
-		// propagate carry
-		while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
-	}
-	x.clamp();
-	x.drShiftTo(this.m.t,x);
-	if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
+  while (x.t <= this.mt2)	// pad x so am has enough room later
+    x[x.t++] = 0;
+  for (var i = 0; i < this.m.t; ++i) {
+    // faster way of calculating u0 = x[i]*mp mod DV
+    var j = x[i] & 0x7fff;
+    var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM;
+    // use am to combine the multiply-shift-add into one call
+    j = i + this.m.t;
+    x[j] += this.m.am(0, u0, x, i, 0, this.m.t);
+    // propagate carry
+    while (x[j] >= x.DV) {
+      x[j] -= x.DV;
+      x[++j]++;
+    }
+  }
+  x.clamp();
+  x.drShiftTo(this.m.t, x);
+  if (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
 }
 
 // r = "x^2/R mod m"; x != r
-function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
+function montSqrTo(x, r) {
+  x.squareTo(r);
+  this.reduce(r);
+}
 
 // r = "xy/R mod m"; x,y != r
-function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
+function montMulTo(x, y, r) {
+  x.multiplyTo(y, r);
+  this.reduce(r);
+}
 
 Montgomery.prototype.convert = montConvert;
 Montgomery.prototype.revert = montRevert;
@@ -585,26 +662,32 @@ Montgomery.prototype.mulTo = montMulTo;
 Montgomery.prototype.sqrTo = montSqrTo;
 
 // (protected) true iff this is even
-function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
+function bnpIsEven() {
+  return ((this.t > 0) ? (this[0] & 1) : this.s) == 0;
+}
 
 // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
-function bnpExp(e,z) {
-	if(e > 0xffffffff || e < 1) return BigInteger.ONE;
-	var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
-	g.copyTo(r);
-	while(--i >= 0) {
-		z.sqrTo(r,r2);
-		if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
-		else { var t = r; r = r2; r2 = t; }
-	}
-	return z.revert(r);
+function bnpExp(e, z) {
+  if (e > 0xffffffff || e < 1) return BigInteger.ONE;
+  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e) - 1;
+  g.copyTo(r);
+  while (--i >= 0) {
+    z.sqrTo(r, r2);
+    if ((e & (1 << i)) > 0) z.mulTo(r2, g, r);
+    else {
+      var t = r;
+      r = r2;
+      r2 = t;
+    }
+  }
+  return z.revert(r);
 }
 
 // (public) this^e % m, 0 <= e < 2^32
-function bnModPowInt(e,m) {
-	var z;
-	if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
-	return this.exp(e,z);
+function bnModPowInt(e, m) {
+  var z;
+  if (e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
+  return this.exp(e, z);
 }
 
 // protected
@@ -642,35 +725,35 @@ BigInteger.ONE = nbv(1);
 //
 
 function Arcfour() {
-	this.i = 0;
-	this.j = 0;
-	this.S = new Array();
+  this.i = 0;
+  this.j = 0;
+  this.S = new Array();
 }
 
 // Initialize arcfour context from key, an array of ints, each from [0..255]
 function ARC4init(key) {
-	var i, j, t;
-	for(i = 0; i < 256; ++i)
-		this.S[i] = i;
-	j = 0;
-	for(i = 0; i < 256; ++i) {
-		j = (j + this.S[i] + key[i % key.length]) & 255;
-		t = this.S[i];
-		this.S[i] = this.S[j];
-		this.S[j] = t;
-	}
-	this.i = 0;
-	this.j = 0;
+  var i, j, t;
+  for (i = 0; i < 256; ++i)
+    this.S[i] = i;
+  j = 0;
+  for (i = 0; i < 256; ++i) {
+    j = (j + this.S[i] + key[i % key.length]) & 255;
+    t = this.S[i];
+    this.S[i] = this.S[j];
+    this.S[j] = t;
+  }
+  this.i = 0;
+  this.j = 0;
 }
 
 function ARC4next() {
-	var t;
-	this.i = (this.i + 1) & 255;
-	this.j = (this.j + this.S[this.i]) & 255;
-	t = this.S[this.i];
-	this.S[this.i] = this.S[this.j];
-	this.S[this.j] = t;
-	return this.S[(t + this.S[this.i]) & 255];
+  var t;
+  this.i = (this.i + 1) & 255;
+  this.j = (this.j + this.S[this.i]) & 255;
+  t = this.S[this.i];
+  this.S[this.i] = this.S[this.j];
+  this.S[this.j] = t;
+  return this.S[(t + this.S[this.i]) & 255];
 }
 
 Arcfour.prototype.init = ARC4init;
@@ -678,7 +761,7 @@ Arcfour.prototype.next = ARC4next;
 
 // Plug in your RNG constructor here
 function prng_newstate() {
-	return new Arcfour();
+  return new Arcfour();
 }
 
 // Pool size must be a multiple of 4 and greater than 32.
@@ -702,67 +785,68 @@ var rng_pptr;
 
 // Mix in a 32-bit integer into the pool
 function rng_seed_int(x) {
-	rng_pool[rng_pptr++] ^= x & 255;
-	rng_pool[rng_pptr++] ^= (x >> 8) & 255;
-	rng_pool[rng_pptr++] ^= (x >> 16) & 255;
-	rng_pool[rng_pptr++] ^= (x >> 24) & 255;
-	if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
+  rng_pool[rng_pptr++] ^= x & 255;
+  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
+  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
+  if (rng_pptr >= rng_psize) rng_pptr -= rng_psize;
 }
 
 // Mix in the current time (w/milliseconds) into the pool
 function rng_seed_time() {
-	rng_seed_int(new Date().getTime());
+  rng_seed_int(new Date().getTime());
 }
 
 // Initialize the pool with junk if needed.
-if(rng_pool == null) {
-	rng_pool = new Array();
-	rng_pptr = 0;
-	var t;
-	if(window.crypto && window.crypto.getRandomValues) {
-		// Use webcrypto if available
-		var ua = new Uint8Array(32);
-		window.crypto.getRandomValues(ua);
-		for(t = 0; t < 32; ++t)
-			rng_pool[rng_pptr++] = ua[t];
-	}
-	if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
-		// Extract entropy (256 bits) from NS4 RNG if available
-		var z = window.crypto.random(32);
-		for(t = 0; t < z.length; ++t)
-			rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
-	}
-	while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
-		t = Math.floor(65536 * Math.random());
-		rng_pool[rng_pptr++] = t >>> 8;
-		rng_pool[rng_pptr++] = t & 255;
-	}
-	rng_pptr = 0;
-	rng_seed_time();
-	//rng_seed_int(window.screenX);
-	//rng_seed_int(window.screenY);
+if (rng_pool == null) {
+  rng_pool = new Array();
+  rng_pptr = 0;
+  var t;
+  if (window.crypto && window.crypto.getRandomValues) {
+    // Use webcrypto if available
+    var ua = new Uint8Array(32);
+    window.crypto.getRandomValues(ua);
+    for (t = 0; t < 32; ++t)
+      rng_pool[rng_pptr++] = ua[t];
+  }
+  if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
+    // Extract entropy (256 bits) from NS4 RNG if available
+    var z = window.crypto.random(32);
+    for (t = 0; t < z.length; ++t)
+      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
+  }
+  while (rng_pptr < rng_psize) {  // extract some randomness from Math.random()
+    t = Math.floor(65536 * Math.random());
+    rng_pool[rng_pptr++] = t >>> 8;
+    rng_pool[rng_pptr++] = t & 255;
+  }
+  rng_pptr = 0;
+  rng_seed_time();
+  //rng_seed_int(window.screenX);
+  //rng_seed_int(window.screenY);
 }
 
 function rng_get_byte() {
-	if(rng_state == null) {
-		rng_seed_time();
-		rng_state = prng_newstate();
-		rng_state.init(rng_pool);
-		for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
-			rng_pool[rng_pptr] = 0;
-		rng_pptr = 0;
-		//rng_pool = null;
-	}
-	// TODO: allow reseeding after first request
-	return rng_state.next();
+  if (rng_state == null) {
+    rng_seed_time();
+    rng_state = prng_newstate();
+    rng_state.init(rng_pool);
+    for (rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
+      rng_pool[rng_pptr] = 0;
+    rng_pptr = 0;
+    //rng_pool = null;
+  }
+  // TODO: allow reseeding after first request
+  return rng_state.next();
 }
 
 function rng_get_bytes(ba) {
-	var i;
-	for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
+  var i;
+  for (i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
 }
 
-function SecureRandom() {}
+function SecureRandom() {
+}
 
 SecureRandom.prototype.nextBytes = rng_get_bytes;
 
@@ -775,98 +859,98 @@ SecureRandom.prototype.nextBytes = rng_get_bytes;
 // Version 1.1: support utf-8 encoding in pkcs1pad2
 
 // convert a (hex) string to a bignum object
-function parseBigInt(str,r) {
-	return new BigInteger(str,r);
+function parseBigInt(str, r) {
+  return new BigInteger(str, r);
 }
 
-function linebrk(s,n) {
-	var ret = "";
-	var i = 0;
-	while(i + n < s.length) {
-		ret += s.substring(i,i+n) + "\n";
-		i += n;
-	}
-	return ret + s.substring(i,s.length);
+function linebrk(s, n) {
+  var ret = "";
+  var i = 0;
+  while (i + n < s.length) {
+    ret += s.substring(i, i + n) + "\n";
+    i += n;
+  }
+  return ret + s.substring(i, s.length);
 }
 
 function byte2Hex(b) {
-	if(b < 0x10)
-		return "0" + b.toString(16);
-	else
-		return b.toString(16);
+  if (b < 0x10)
+    return "0" + b.toString(16);
+  else
+    return b.toString(16);
 }
 
 // PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
-function pkcs1pad2(s,n) {
-	if(n < s.length + 11) { // TODO: fix for utf-8
-		alert("Message too long for RSA");
-		return null;
-	}
-	var ba = new Array();
-	var i = s.length - 1;
-	while(i >= 0 && n > 0) {
-		var c = s.charCodeAt(i--);
-		if(c < 128) { // encode using utf-8
-			ba[--n] = c;
-		}
-		else if((c > 127) && (c < 2048)) {
-			ba[--n] = (c & 63) | 128;
-			ba[--n] = (c >> 6) | 192;
-		}
-		else {
-			ba[--n] = (c & 63) | 128;
-			ba[--n] = ((c >> 6) & 63) | 128;
-			ba[--n] = (c >> 12) | 224;
-		}
-	}
-	ba[--n] = 0;
-	var rng = new SecureRandom();
-	var x = new Array();
-	while(n > 2) { // random non-zero pad
-		x[0] = 0;
-		while(x[0] == 0) rng.nextBytes(x);
-		ba[--n] = x[0];
-	}
-	ba[--n] = 2;
-	ba[--n] = 0;
-	return new BigInteger(ba);
+function pkcs1pad2(s, n) {
+  if (n < s.length + 11) { // TODO: fix for utf-8
+    alert("Message too long for RSA");
+    return null;
+  }
+  var ba = new Array();
+  var i = s.length - 1;
+  while (i >= 0 && n > 0) {
+    var c = s.charCodeAt(i--);
+    if (c < 128) { // encode using utf-8
+      ba[--n] = c;
+    }
+    else if ((c > 127) && (c < 2048)) {
+      ba[--n] = (c & 63) | 128;
+      ba[--n] = (c >> 6) | 192;
+    }
+    else {
+      ba[--n] = (c & 63) | 128;
+      ba[--n] = ((c >> 6) & 63) | 128;
+      ba[--n] = (c >> 12) | 224;
+    }
+  }
+  ba[--n] = 0;
+  var rng = new SecureRandom();
+  var x = new Array();
+  while (n > 2) { // random non-zero pad
+    x[0] = 0;
+    while (x[0] == 0) rng.nextBytes(x);
+    ba[--n] = x[0];
+  }
+  ba[--n] = 2;
+  ba[--n] = 0;
+  return new BigInteger(ba);
 }
 
 // "empty" RSA key constructor
 function RSAKey() {
-	this.n = null;
-	this.e = 0;
-	this.d = null;
-	this.p = null;
-	this.q = null;
-	this.dmp1 = null;
-	this.dmq1 = null;
-	this.coeff = null;
+  this.n = null;
+  this.e = 0;
+  this.d = null;
+  this.p = null;
+  this.q = null;
+  this.dmp1 = null;
+  this.dmq1 = null;
+  this.coeff = null;
 }
 
 // Set the public key fields N and e from hex strings
-function RSASetPublic(N,E) {
-	if(N != null && E != null && N.length > 0 && E.length > 0) {
-		this.n = parseBigInt(N,16);
-		this.e = parseInt(E,16);
-	}
-	else
-		alert("Invalid RSA public key");
+function RSASetPublic(N, E) {
+  if (N != null && E != null && N.length > 0 && E.length > 0) {
+    this.n = parseBigInt(N, 16);
+    this.e = parseInt(E, 16);
+  }
+  else
+    alert("Invalid RSA public key");
 }
 
 // Perform raw public operation on "x": return x^e (mod n)
 function RSADoPublic(x) {
-	return x.modPowInt(this.e, this.n);
+  return x.modPowInt(this.e, this.n);
 }
 
 // Return the PKCS#1 RSA encryption of "text" as an even-length hex string
 function RSAEncrypt(text) {
-	var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
-	if(m == null) return null;
-	var c = this.doPublic(m);
-	if(c == null) return null;
-	var h = c.toString(16);
-	if((h.length & 1) == 0) return h; else return "0" + h;
+  var m = pkcs1pad2(text, (this.n.bitLength() + 7) >> 3);
+  if (m == null) return null;
+  var c = this.doPublic(m);
+  if (c == null) return null;
+  var h = c.toString(16);
+  if ((h.length & 1) == 0) return h; else return "0" + h;
 }
 
 // Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js
index 409bc9c41492..43a97a54b14f 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/autolinking.js
@@ -5,126 +5,126 @@
  * Inspired by https://github.com/Gnodiah/ckeditor-autolink
  */
 CKEDITOR.plugins.add('autolinking', {
-	init: function(editor) {
-		var spaceChar = 32, enterChar = 13, tabChar = 9, fillChar = ' ';
-		var isFillChar = function (node, isInStart) {
-			return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '' ) + ' '), '').length;
-		};
-		var isBodyTag = function (node) {
-			return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body';
-		};
-		var isAnchorTag = function (node) {
-			return node && node.nodeType == 1 && node.tagName.toLowerCase() === 'a';
-		};
-		var html = function (str) {
-			return str ? str.replace(/&((g|l|quo)t|amp|#39);/g, function (m) {
-				return {
-					'&lt;':'<',
-					'&amp;':'&',
-					'&quot;':'"',
-					'&gt;':'>',
-					'&#39;':"'"
-				}[m]
-			}) : '';
-		};
+  init: function(editor) {
+    var spaceChar = 32, enterChar = 13, tabChar = 9, fillChar = ' ';
+    var isFillChar = function(node, isInStart) {
+      return node.nodeType == 3 && !node.nodeValue.replace(new RegExp((isInStart ? '^' : '') + ' '), '').length;
+    };
+    var isBodyTag = function(node) {
+      return node && node.nodeType == 1 && node.tagName.toLowerCase() == 'body';
+    };
+    var isAnchorTag = function(node) {
+      return node && node.nodeType == 1 && node.tagName.toLowerCase() === 'a';
+    };
+    var html = function(str) {
+      return str ? str.replace(/&((g|l|quo)t|amp|#39);/g, function(m) {
+        return {
+          '&lt;': '<',
+          '&amp;': '&',
+          '&quot;': '"',
+          '&gt;': '>',
+          '&#39;': "'"
+        }[m]
+      }) : '';
+    };
 
-		var hasParentAnchorTag = function (node) {
-			if (node && !isBodyTag(node)) {
-				while (node) {
-					if (isBodyTag(node)) {
-						return false;
-					} else if (isAnchorTag(node)) {
-						return true;
-					}
-					node = node.parentNode;
-				}
-			}
-			return false;
-		};
+    var hasParentAnchorTag = function(node) {
+      if (node && !isBodyTag(node)) {
+        while (node) {
+          if (isBodyTag(node)) {
+            return false;
+          } else if (isAnchorTag(node)) {
+            return true;
+          }
+          node = node.parentNode;
+        }
+      }
+      return false;
+    };
 
-		editor.on('instanceReady', function() {
-			editor.autolinking = function(evt) {
-				var sel = editor.getSelection().getNative(),
-					range = sel.getRangeAt(0).cloneRange(),
-					offset,
-					charCode;
+    editor.on('instanceReady', function() {
+      editor.autolinking = function(evt) {
+        var sel = editor.getSelection().getNative(),
+          range = sel.getRangeAt(0).cloneRange(),
+          offset,
+          charCode;
 
-				var start = range.startContainer;
-				while (start.nodeType == 1 && range.startOffset > 0) {
-					start = range.startContainer.childNodes[range.startOffset - 1];
-					if (!start) break;
+        var start = range.startContainer;
+        while (start.nodeType == 1 && range.startOffset > 0) {
+          start = range.startContainer.childNodes[range.startOffset - 1];
+          if (!start) break;
 
-					range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
-					range.collapse(true);
-					start = range.startContainer;
-				}
+          range.setStart(start, start.nodeType == 1 ? start.childNodes.length : start.nodeValue.length);
+          range.collapse(true);
+          start = range.startContainer;
+        }
 
-				do {
-					if (range.startOffset == 0) {
-						start = range.startContainer.previousSibling;
+        do {
+          if (range.startOffset == 0) {
+            start = range.startContainer.previousSibling;
 
-						while (start && start.nodeType == 1) {
-							if (CKEDITOR.env.gecko && start.firstChild)
-								start = start.firstChild;
-							else
-								start = start.lastChild;
-						}
-						if (!start || isFillChar(start)) break;
-						offset = start.nodeValue.length;
-					} else {
-						start = range.startContainer;
-						offset = range.startOffset;
-					}
-					range.setStart(start, offset - 1);
-					charCode = range.toString().charCodeAt(0);
-				} while (charCode != 160 && charCode != spaceChar);
+            while (start && start.nodeType == 1) {
+              if (CKEDITOR.env.gecko && start.firstChild)
+                start = start.firstChild;
+              else
+                start = start.lastChild;
+            }
+            if (!start || isFillChar(start)) break;
+            offset = start.nodeValue.length;
+          } else {
+            start = range.startContainer;
+            offset = range.startOffset;
+          }
+          range.setStart(start, offset - 1);
+          charCode = range.toString().charCodeAt(0);
+        } while (charCode != 160 && charCode != spaceChar);
 
-				if (range.toString().replace(new RegExp(fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
-					while (range.toString().length) {
-						if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) break;
+        if (range.toString().replace(new RegExp(fillChar, 'g'), '').match(/(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i)) {
+          while (range.toString().length) {
+            if (/^(?:https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)/i.test(range.toString())) break;
 
-						try {
-							range.setStart(range.startContainer, range.startOffset+1);
-						} catch (e) {
-							var startChar = range.startContainer;
-							while (!(next = startChar.nextSibling)) {
-								if (isBodyTag(startChar)) {
-									return;
-								}
-								startChar = startChar.parentNode;
-							}
-							range.setStart(next, 0);
-						}
-					}
+            try {
+              range.setStart(range.startContainer, range.startOffset + 1);
+            } catch (e) {
+              var startChar = range.startContainer;
+              while (!(next = startChar.nextSibling)) {
+                if (isBodyTag(startChar)) {
+                  return;
+                }
+                startChar = startChar.parentNode;
+              }
+              range.setStart(next, 0);
+            }
+          }
 
-					if (hasParentAnchorTag(range.startContainer)) {
-						return;
-					}
+          if (hasParentAnchorTag(range.startContainer)) {
+            return;
+          }
 
-					var a = document.createElement('a'),
-						href;
+          var a = document.createElement('a'),
+            href;
 
-					editor.undoManger && editor.undoManger.save();
-					a.appendChild(range.extractContents());
-					a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, '');
-					href = a.getAttribute('href').replace(new RegExp(fillChar,'g'), '');
-					href = /^(?:https?:\/\/)/ig.test(href) ? href : 'http://' + href;
-					a.href = html(href);
+          editor.undoManger && editor.undoManger.save();
+          a.appendChild(range.extractContents());
+          a.href = a.innerHTML = a.innerHTML.replace(/<[^>]+>/g, '');
+          href = a.getAttribute('href').replace(new RegExp(fillChar, 'g'), '');
+          href = /^(?:https?:\/\/)/ig.test(href) ? href : 'http://' + href;
+          a.href = html(href);
 
-					range.insertNode(a);
-					range.setStart(a.nextSibling, 0);
-					range.collapse(true);
-					sel.removeAllRanges();
-					sel.addRange(range);
-					editor.undoManger && editor.undoManger.save();
-				}
-			};
+          range.insertNode(a);
+          range.setStart(a.nextSibling, 0);
+          range.collapse(true);
+          sel.removeAllRanges();
+          sel.addRange(range);
+          editor.undoManger && editor.undoManger.save();
+        }
+      };
 
-			editor.on('key', function(evt) {
-				if (evt.data.keyCode === spaceChar || evt.data.keyCode === tabChar || evt.data.keyCode === enterChar) {
-					editor.autolinking(evt);
-				}
-			});
-		});
-	}
+      editor.on('key', function(evt) {
+        if (evt.data.keyCode === spaceChar || evt.data.keyCode === tabChar || evt.data.keyCode === enterChar) {
+          editor.autolinking(evt);
+        }
+      });
+    });
+  }
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js
index c09547a75b19..b62ca196efed 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/af.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'af', {
-	more: 'Meer...'
-});
\ No newline at end of file
+CKEDITOR.plugins.setLang('quicktable', 'af', {
+  more: 'Meer...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js
index dd31fb8d512d..15d7ea9a0ca0 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ar.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ar', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ar', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js
index 8a571d874529..db3491537817 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bg.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'bg', {
-	more: 'Още...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'bg', {
+  more: 'Още...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js
index 7ad52caac3e3..1f38df622c5b 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bn.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'bn', {
-	more: 'আরও...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'bn', {
+  more: 'আরও...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js
index 2254758c3f61..c1c1d7b462e9 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/bs.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'bs', {
-	more: 'Više...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'bs', {
+  more: 'Više...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js
index 535f8c383ad2..32b03e164e53 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ca.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ca', {
-	more: 'Més...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ca', {
+  more: 'Més...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js
index 39a11fab0d30..6b111cb93351 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cs.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'cs', {
-	more: 'Více...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'cs', {
+  more: 'Více...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js
index 337bfa1bea57..2b5e968fe56b 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/cy.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'cy', {
-	more: 'Mwy...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'cy', {
+  more: 'Mwy...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js
index d10c3ce308c1..46979974f336 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/da.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'da', {
-	more: 'Flere...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'da', {
+  more: 'Flere...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js
index 0bfba045f026..4fa1cb34afa6 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/de.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'de', {
-	more: 'Mehr...'
-});
\ No newline at end of file
+CKEDITOR.plugins.setLang('quicktable', 'de', {
+  more: 'Mehr...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js
index be6eef1a0148..d63aadd94b98 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/el.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'el', {
-	more: 'Περισσότερα...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'el', {
+  more: 'Περισσότερα...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js
index df0052571b99..ffa8eebf8534 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-au.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'en-au', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'en-au', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js
index e796c5952860..09d3a3303f0d 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-ca.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'en-ca', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'en-ca', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js
index e6aa66b669a3..2b5d97511cab 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en-gb.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'en-gb', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'en-gb', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js
index 8ffbf411b6c5..f7fc9e78aeff 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/en.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'en', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'en', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js
index 618bc2ba6b43..436aa36c6d56 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eo.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'eo', {
-	more: 'Pli...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'eo', {
+  more: 'Pli...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js
index d3771d453ce2..87f00d36c415 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/es.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'es', {
-	more: 'Más...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'es', {
+  more: 'Más...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js
index 6dc2712bc4f9..9eeaac53e4c5 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/et.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'et', {
-	more: 'Rohkem...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'et', {
+  more: 'Rohkem...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js
index b99b2fc01182..637cd59a50a1 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/eu.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'eu', {
-	more: 'Gehiago...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'eu', {
+  more: 'Gehiago...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js
index b4bf3696ea7a..335bee6a71c3 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fa.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'fa', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'fa', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js
index 36cc0bef6a02..78ebe8045304 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fi.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'fi', {
-	more: 'Lisää...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'fi', {
+  more: 'Lisää...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js
index 7ce2604056ac..7d95e5a9f109 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fo.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'fo', {
-	more: 'Fleiri...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'fo', {
+  more: 'Fleiri...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js
index 6f5f44bc8319..042c8317e523 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr-ca.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'fr-ca', {
-	more: 'Plus...'
+CKEDITOR.plugins.setLang('quicktable', 'fr-ca', {
+  more: 'Plus...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js
index b5c4dff0ddf6..293e065a6611 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/fr.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'fr', {
-	more: 'Plus...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'fr', {
+  more: 'Plus...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js
index 7f53d09a7e49..bc6192527057 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gl.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'gl', {
-	more: 'Máis...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'gl', {
+  more: 'Máis...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js
index 9fe93d49ead9..5cdc776e91ec 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/gu.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'gu', {
-	more: 'ઔર...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'gu', {
+  more: 'ઔર...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js
index 9027aaecc000..54820070712e 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/he.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'he', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'he', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js
index 7f2284bcee8f..730e41b10505 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hi.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'hi', {
-	more: 'और...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'hi', {
+  more: 'और...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js
index 020820207260..c7cad9c1c0d0 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hr.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'hr', {
-	more: 'Više...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'hr', {
+  more: 'Više...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js
index 4113694c44d2..053530ecd729 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/hu.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'hu', {
-	more: 'További...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'hu', {
+  more: 'További...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js
index 25c9dcc845e2..af225faed2d6 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/id.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'id', {
-	more: 'More...' // MISSING
-} );
+CKEDITOR.plugins.setLang('quicktable', 'id', {
+  more: 'More...' // MISSING
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js
index a68b85c229fa..3b74e768c40e 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/is.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'is', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'is', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js
index 2c971d6a1ce5..0fb0976ed936 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/it.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'it', {
-	more: 'Altri...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'it', {
+  more: 'Altri...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js
index 180129ecd642..b25abc6db948 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ja.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ja', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ja', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js
index 506c2d7e117a..3906577914d0 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ka.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ka', {
-	more: 'მეტი...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ka', {
+  more: 'მეტი...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js
index d959ec17baba..0086fae67603 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/km.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'km', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'km', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js
index b8f284e0255e..f20bf6a213c4 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ko.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ko', {
-	more: 'More...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ko', {
+  more: 'More...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js
index c5c058e1a0e0..48cb3ef6f522 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ku.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ku', {
-	more: 'بیشتر...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ku', {
+  more: 'بیشتر...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js
index 7378735621aa..aeb8fbe90fa1 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lt.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'lt', {
-	more: 'Daugiau...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'lt', {
+  more: 'Daugiau...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js
index 1476f656aa0b..fcd4de8da18c 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/lv.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'lv', {
-	more: 'Plašāka...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'lv', {
+  more: 'Plašāka...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js
index e3b6727d650f..bafb9fe616ba 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mk.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'mk', {
-	more: 'More...' // MISSING
+CKEDITOR.plugins.setLang('quicktable', 'mk', {
+  more: 'More...' // MISSING
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js
index 8a8563834f97..1ebd42c20e89 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/mn.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'mn', {
-	more: 'Нэмэлт...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'mn', {
+  more: 'Нэмэлт...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js
index 4e5ef758f16f..fd2c933acc4f 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ms.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ms', {
-	more: 'Lebih...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ms', {
+  more: 'Lebih...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js
index 3bccbab4810d..911f52f8cb73 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nb.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'nb', {
-	more: 'Flere...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'nb', {
+  more: 'Flere...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js
index ba2d6ffc0b0b..b6a2e7a6ea21 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/nl.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'nl', {
-	more: 'Meer...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'nl', {
+  more: 'Meer...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js
index eb4de1f7be51..5cf4c77fa275 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/no.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'no', {
-	more: 'Flere...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'no', {
+  more: 'Flere...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js
index b92d7fb68b85..f3b9fb71ff78 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pl.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'pl', {
-	more: 'Więcej...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'pl', {
+  more: 'Więcej...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js
index d12595b4691e..8475c5b13e06 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt-br.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'pt-br', {
-	more: 'Mais...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'pt-br', {
+  more: 'Mais...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js
index 9d301095ded6..aaaa44a3ff72 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/pt.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'pt', {
-	more: 'Mais...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'pt', {
+  more: 'Mais...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js
index 4219d3ac3be7..380f326d0ae0 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ro.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ro', {
-	more: 'Mai multe...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ro', {
+  more: 'Mai multe...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js
index 87200067a27e..e7bfceee2494 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ru.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ru', {
-	more: 'Ещё...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ru', {
+  more: 'Ещё...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js
index b03f7bf37762..de1d5ccc0d41 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/si.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'si', {
-	more: 'More...' // MISSING
+CKEDITOR.plugins.setLang('quicktable', 'si', {
+  more: 'More...' // MISSING
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js
index 52912fccbc54..5283fcc9a9d4 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sk.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sk', {
-	more: 'Viac...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'sk', {
+  more: 'Viac...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js
index 14166c6fb0ed..0e68bd1e894a 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sl.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sl', {
-	more: 'Več...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'sl', {
+  more: 'Več...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js
index 4d1eb3bedfb5..dd67d79ee66c 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sq.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sq', {
-	more: 'Më Shumë...'
+CKEDITOR.plugins.setLang('quicktable', 'sq', {
+  more: 'Më Shumë...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js
index 8731c80033a2..6f37510503c9 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr-latn.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sr-latn', {
-	more: 'Više...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'sr-latn', {
+  more: 'Više...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js
index facee051958b..b958a3472008 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sr.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sr', {
-	more: 'Више...'
+CKEDITOR.plugins.setLang('quicktable', 'sr', {
+  more: 'Више...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js
index 644ac96b9536..40751f4aefef 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/sv.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'sv', {
-	more: 'Fler...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'sv', {
+  more: 'Fler...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js
index 32443498bd2f..b4acbc339c93 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/th.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'th', {
-	more: ' เลือกอื่นๆ...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'th', {
+  more: ' เลือกอื่นๆ...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js
index 9f8d0041bb4f..5efb5c520fcf 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tr.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'tr', {
-	more: 'DiÄŸer...'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'tr', {
+  more: 'DiÄŸer...'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js
index 5a7e888e3f31..8574d45dd6b2 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/tt.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'tt', {
-	more: 'Башка'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'tt', {
+  more: 'Башка'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js
index 9ea2ef710e4f..945fb7e89056 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/ug.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'ug', {
-	more: 'ا رەڭ'
-} );
+CKEDITOR.plugins.setLang('quicktable', 'ug', {
+  more: 'ا رەڭ'
+});
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js
index e487676a866e..57b29963a87c 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/uk.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'uk', {
-	more: 'більш...'
+CKEDITOR.plugins.setLang('quicktable', 'uk', {
+  more: 'більш...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js
index f2e6fc88e69f..36d1db5927cb 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/vi.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'vi', {
-	more: 'Màu...'
+CKEDITOR.plugins.setLang('quicktable', 'vi', {
+  more: 'Màu...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js
index 6167d556d20b..4b8f7d5d79e4 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh-cn.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'zh-cn', {
-	more: '其它...'
+CKEDITOR.plugins.setLang('quicktable', 'zh-cn', {
+  more: '其它...'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js
index a986d5ebbb8b..ca117e22d25d 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/lang/zh.js
@@ -2,6 +2,6 @@
 Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
 For licensing, see LICENSE.md or http://ckeditor.com/license
 */
-CKEDITOR.plugins.setLang( 'quicktable', 'zh', {
-	more: '更多'
+CKEDITOR.plugins.setLang('quicktable', 'zh', {
+  more: '更多'
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js
index 4c4944c84cbc..1918b204b7dc 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/quicktable/plugin.js
@@ -6,190 +6,191 @@
  * Removed the "more" button
  * Removed styling / border options that would be set etc.
  */
-CKEDITOR.plugins.add( 'quicktable', {
-	requires: 'table,panelbutton,floatpanel',
-	lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
-	afterInit: function( editor ) {
-		var conf = editor.config,
-			quickRows = conf.qtRows || 4,
-			quickColumns = conf.qtColumns || 6,
-			quickClass = conf.qtClass || '',
-			quickPreviewSize = conf.qtPreviewSize || '14px',
-			quickPreviewBorder = conf.qtPreviewBorder || '1px solid #aaa',
-			quickPreviewBackground = conf.qtPreviewBackground || '#e5e5e5';
-			
-		function makeElement( name ) {
-			return new CKEDITOR.dom.element( name, editor.document );
-		}
-
-		function insertTable( rowCount, columnCount ) {
-			var table = makeElement( 'table' );
-			var tbody = table.append( makeElement( 'tbody' ) );
-
-			for ( var i = 0; i < rowCount; i++ ) {
-				var row = tbody.append( makeElement( 'tr' ) );
-				for ( var j = 0; j < columnCount; j++ ) {
-					var cell = row.append( makeElement( 'td' ) );
-					cell.appendBogus();
-				}
-			}
-
-			table.setAttribute( 'class', quickClass );
-			editor.insertElement( table );
-			
-			// Fire event for showborders plugin (so hidden borders are visible)
-			editor.fire('removeFormatCleanup', table);
-		}
-
-		function renderQuickTable(panel) {
-			var output = [];
-
-			var clickFn = CKEDITOR.tools.addFunction( function( i, j ) {
-				insertTable( parseInt( i, 10 ) + 1, parseInt( j, 10 ) + 1 );
-				panel.hide();
-			} );
-
-			output.push( '<a style="display:block" _cke_focus=1 hidefocus=true href="javascript:void(1)">' +
-				'<table role="presentation" cellspacing=1 cellpadding=1 style="width: 100%; margin: 0 auto 3px;table-layout:fixed;">' );
-
-			for ( var i = 0; i < quickRows; i++ ) {
-				output.push( '<tr>' );
-				for ( var j = 0; j < quickColumns; j++ ) {
-					output.push( '<td style="border: ' + quickPreviewBorder + ';width:'+quickPreviewSize+';height:'+quickPreviewSize+';" data-i="' + i + '" data-j="' + j + '"' +
-						' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', i, '\',\'', j, '\'); return false;"' +
-					'></td>' );
-				}
-				output.push('</tr>');
-			}
-
-			output.push( '</table></a>' );
-
-			return output.join( '' );
-		}
-
-		var selection = {row: -1, column: -1};
-		function select( label, table, rowCount, columnCount ) {
-			var rows = table.$.tBodies[0].rows;
-			for ( var i = 0; i < rows.length; i++ ) {
-				var cells = rows[i].cells;
-				for ( var j = 0; j < cells.length; j++ ) {
-					var cell = cells[j];
-					if ( i < rowCount && j < columnCount ) {
-						cell.style.background = quickPreviewBackground;
-					} else {
-						cell.style.background = '';
-					}
-				}
-			}
-			selection.row = rowCount - 1;
-			selection.column = columnCount - 1;
-			label.setText( rowCount + ' × ' + columnCount + ' ' + editor.lang.table.toolbar );
-		}
-		
-		editor.ui.add( 'Table', CKEDITOR.UI_PANELBUTTON, {
-			label: editor.lang.table.toolbar,
-			command: 'table',
-			modes: { wysiwyg: 1 },
-			editorFocus: 0,
-			toolbar: 'insert,30',
-
-			caption: null,
-			table: null,
-
-			panel: {
-				css: CKEDITOR.skin.getPath( 'editor' ),
-				attributes: { role: 'listbox', 'aria-label': editor.lang.table.toolbar }
-			},
-
-			onBlock: function( panel, block ) {
-				block.autoSize = true;
-				block.element.addClass( 'cke_colorblock' );
-
-				var caption = new CKEDITOR.dom.element( 'div' );
-				caption.setStyles( { 'text-align': 'center', 'margin': '3px 0' } );
-				block.element.append( caption );
-				this.caption = caption;
-
-				var tableWrapper = CKEDITOR.dom.element.createFromHtml( renderQuickTable(panel) );
-				this.table = this.addEvents(tableWrapper);
-				block.element.append( tableWrapper );
-
-				CKEDITOR.ui.fire( 'ready', this );
-				
-				block.keys = this.assignKeys(block.keys);
-			},
-			
-			assignKeys: function(keys){
-				var rtl = editor.lang.dir == 'rtl';
-				keys[ rtl ? 37 : 39 ] = 'next'; // ARROW-RIGHT
-				keys[ 40 ] = 'next'; // ARROW-DOWN
-				keys[ 9 ] = 'next'; // TAB
-				keys[ rtl ? 39 : 37 ] = 'prev'; // ARROW-LEFT
-				keys[ 38 ] = 'prev'; // ARROW-UP
-				keys[ CKEDITOR.SHIFT + 9 ] = 'prev'; // SHIFT + TAB
-				keys[ 32 ] = 'click'; // SPACE
-				return keys;
-			},
-			
-			addEvents: function(tableWrapper){
-				var table = this.table = tableWrapper.getFirst();
-				var caption = this.caption;
-				table.on( 'mouseleave', function( evt ) {
-					select( caption, table, 1, 1 );
-				} );
-				table.on( 'mousemove', function( evt ) {
-					var target = evt.data.getTarget();
-					if ( target.getName() == 'td' ) {
-						var i = parseInt( target.getAttribute( 'data-i' ), 10 );
-						var j = parseInt( target.getAttribute( 'data-j' ), 10 );
-						select( caption, table, i + 1, j + 1 );
-					}
-				} );
-				tableWrapper.on( 'keydown', function( evt ) {
-					var keystroke = evt.data.getKeystroke(),
-						row = selection.row,
-						column = selection.column;
-
-					switch ( keystroke ) {
-						case 37: // ARROW-LEFT
-							column--;
-							break;
-						case 39: // ARROW-RIGHT
-							column++;
-							break;
-						case 40: // ARROW-DOWN
-							row++;
-							break;
-						case 38: // ARROW-UP
-							row--;
-							break;
-						case 13: // ENTER
-						case 32: // SPACE
-							insertTable( row + 1, column + 1 );
-							return;
-						default:
-							return;
-					}
-
-					if ( row < 0 || column < 0 ) {
-						this.panel.hide();
-						return;
-					}
-
-					if ( row > quickRows - 1 || column > quickColumns - 1 ) {
-						editor.execCommand( 'table' );
-					}
-					select( caption, table, row + 1, column + 1 );
-					evt.data.preventDefault();
-					evt.data.stopPropagation();
-				});
-				
-				return table;
-			},
-			
-			onOpen: function() {
-				select( this.caption, this.table, 1, 1 );
-			}
-		} );
-	}
+CKEDITOR.plugins.add('quicktable', {
+  requires: 'table,panelbutton,floatpanel',
+  lang: 'af,ar,bg,bn,bs,ca,cs,cy,da,de,el,en,en-au,en-ca,en-gb,eo,es,et,eu,fa,fi,fo,fr,fr-ca,gl,gu,he,hi,hr,hu,id,is,it,ja,ka,km,ko,ku,lt,lv,mk,mn,ms,nb,nl,no,pl,pt,pt-br,ro,ru,si,sk,sl,sq,sr,sr-latn,sv,th,tr,ug,uk,vi,zh,zh-cn', // %REMOVE_LINE_CORE%
+  afterInit: function(editor) {
+    var conf = editor.config,
+      quickRows = conf.qtRows || 4,
+      quickColumns = conf.qtColumns || 6,
+      quickClass = conf.qtClass || '',
+      quickPreviewSize = conf.qtPreviewSize || '14px',
+      quickPreviewBorder = conf.qtPreviewBorder || '1px solid #aaa',
+      quickPreviewBackground = conf.qtPreviewBackground || '#e5e5e5';
+
+    function makeElement(name) {
+      return new CKEDITOR.dom.element(name, editor.document);
+    }
+
+    function insertTable(rowCount, columnCount) {
+      var table = makeElement('table');
+      var tbody = table.append(makeElement('tbody'));
+
+      for (var i = 0; i < rowCount; i++) {
+        var row = tbody.append(makeElement('tr'));
+        for (var j = 0; j < columnCount; j++) {
+          var cell = row.append(makeElement('td'));
+          cell.appendBogus();
+        }
+      }
+
+      table.setAttribute('class', quickClass);
+      editor.insertElement(table);
+
+      // Fire event for showborders plugin (so hidden borders are visible)
+      editor.fire('removeFormatCleanup', table);
+    }
+
+    function renderQuickTable(panel) {
+      var output = [];
+
+      var clickFn = CKEDITOR.tools.addFunction(function(i, j) {
+        insertTable(parseInt(i, 10) + 1, parseInt(j, 10) + 1);
+        panel.hide();
+      });
+
+      output.push('<a style="display:block" _cke_focus=1 hidefocus=true href="javascript:void(1)">' +
+        '<table role="presentation" cellspacing=1 cellpadding=1 style="width: 100%; margin: 0 auto 3px;table-layout:fixed;">');
+
+      for (var i = 0; i < quickRows; i++) {
+        output.push('<tr>');
+        for (var j = 0; j < quickColumns; j++) {
+          output.push('<td style="border: ' + quickPreviewBorder + ';width:' + quickPreviewSize + ';height:' + quickPreviewSize + ';" data-i="' + i + '" data-j="' + j + '"' +
+            ' onclick="CKEDITOR.tools.callFunction(', clickFn, ',\'', i, '\',\'', j, '\'); return false;"' +
+            '></td>');
+        }
+        output.push('</tr>');
+      }
+
+      output.push('</table></a>');
+
+      return output.join('');
+    }
+
+    var selection = {row: -1, column: -1};
+
+    function select(label, table, rowCount, columnCount) {
+      var rows = table.$.tBodies[0].rows;
+      for (var i = 0; i < rows.length; i++) {
+        var cells = rows[i].cells;
+        for (var j = 0; j < cells.length; j++) {
+          var cell = cells[j];
+          if (i < rowCount && j < columnCount) {
+            cell.style.background = quickPreviewBackground;
+          } else {
+            cell.style.background = '';
+          }
+        }
+      }
+      selection.row = rowCount - 1;
+      selection.column = columnCount - 1;
+      label.setText(rowCount + ' × ' + columnCount + ' ' + editor.lang.table.toolbar);
+    }
+
+    editor.ui.add('Table', CKEDITOR.UI_PANELBUTTON, {
+      label: editor.lang.table.toolbar,
+      command: 'table',
+      modes: {wysiwyg: 1},
+      editorFocus: 0,
+      toolbar: 'insert,30',
+
+      caption: null,
+      table: null,
+
+      panel: {
+        css: CKEDITOR.skin.getPath('editor'),
+        attributes: {role: 'listbox', 'aria-label': editor.lang.table.toolbar}
+      },
+
+      onBlock: function(panel, block) {
+        block.autoSize = true;
+        block.element.addClass('cke_colorblock');
+
+        var caption = new CKEDITOR.dom.element('div');
+        caption.setStyles({'text-align': 'center', 'margin': '3px 0'});
+        block.element.append(caption);
+        this.caption = caption;
+
+        var tableWrapper = CKEDITOR.dom.element.createFromHtml(renderQuickTable(panel));
+        this.table = this.addEvents(tableWrapper);
+        block.element.append(tableWrapper);
+
+        CKEDITOR.ui.fire('ready', this);
+
+        block.keys = this.assignKeys(block.keys);
+      },
+
+      assignKeys: function(keys) {
+        var rtl = editor.lang.dir == 'rtl';
+        keys[rtl ? 37 : 39] = 'next'; // ARROW-RIGHT
+        keys[40] = 'next'; // ARROW-DOWN
+        keys[9] = 'next'; // TAB
+        keys[rtl ? 39 : 37] = 'prev'; // ARROW-LEFT
+        keys[38] = 'prev'; // ARROW-UP
+        keys[CKEDITOR.SHIFT + 9] = 'prev'; // SHIFT + TAB
+        keys[32] = 'click'; // SPACE
+        return keys;
+      },
+
+      addEvents: function(tableWrapper) {
+        var table = this.table = tableWrapper.getFirst();
+        var caption = this.caption;
+        table.on('mouseleave', function(evt) {
+          select(caption, table, 1, 1);
+        });
+        table.on('mousemove', function(evt) {
+          var target = evt.data.getTarget();
+          if (target.getName() == 'td') {
+            var i = parseInt(target.getAttribute('data-i'), 10);
+            var j = parseInt(target.getAttribute('data-j'), 10);
+            select(caption, table, i + 1, j + 1);
+          }
+        });
+        tableWrapper.on('keydown', function(evt) {
+          var keystroke = evt.data.getKeystroke(),
+            row = selection.row,
+            column = selection.column;
+
+          switch (keystroke) {
+            case 37: // ARROW-LEFT
+              column--;
+              break;
+            case 39: // ARROW-RIGHT
+              column++;
+              break;
+            case 40: // ARROW-DOWN
+              row++;
+              break;
+            case 38: // ARROW-UP
+              row--;
+              break;
+            case 13: // ENTER
+            case 32: // SPACE
+              insertTable(row + 1, column + 1);
+              return;
+            default:
+              return;
+          }
+
+          if (row < 0 || column < 0) {
+            this.panel.hide();
+            return;
+          }
+
+          if (row > quickRows - 1 || column > quickColumns - 1) {
+            editor.execCommand('table');
+          }
+          select(caption, table, row + 1, column + 1);
+          evt.data.preventDefault();
+          evt.data.stopPropagation();
+        });
+
+        return table;
+      },
+
+      onOpen: function() {
+        select(this.caption, this.table, 1, 1);
+      }
+    });
+  }
 });
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js
index 0c338bbd1b6d..5cfa2e494641 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/Plugins/typo3link.js
@@ -13,141 +13,141 @@
 
 'use strict';
 
-(function () {
-
-	CKEDITOR.plugins.add('typo3link', {
-		elementBrowser: null,
-		init: function (editor) {
-			var allowedAttributes = ['!href', 'title', 'class', 'target', 'rel'],
-				required = 'a[href]';
-
-			var additionalAttributes = getAdditionalAttributes(editor);
-			if (additionalAttributes.length) {
-				allowedAttributes.push.apply(allowedAttributes, additionalAttributes);
-			}
-
-			// Override link command
-			editor.addCommand('link', {
-				exec: openLinkBrowser,
-				allowedContent: 'a[' + allowedAttributes.join(',') + ']',
-				requiredContent: required
-			});
-
-			// Override doubleclick opening default link dialog
-			editor.on('doubleclick', function (evt) {
-				var element = CKEDITOR.plugins.link.getSelectedLink(editor) || evt.data.element;
-				if (!element.isReadOnly() && element.is('a') && element.getAttribute('href')) {
-					evt.stop();
-					openLinkBrowser(editor, element);
-				}
-			}, null, null, 30);
-
-		}
-	});
-
-	/**
-	 * Open link browser
-	 *
-	 * @param {Object} editor CKEditor object
-	 * @param {Object} element Selected link element
-	 */
-	function openLinkBrowser(editor, element) {
-		var additionalParameters = '';
-
-		if ($.isEmptyObject(element)) {
-			element = CKEDITOR.plugins.link.getSelectedLink(editor);
-		}
-		if (element) {
-			additionalParameters = '&curUrl[url]=' + encodeURIComponent(element.getAttribute('href'));
-			var i = 0,
-				attributeNames = ["target", "class", "title", "rel"];
-			for (i = 0; i < attributeNames.length; ++i) {
-				if (element.getAttribute(attributeNames[i])) {
-					additionalParameters += '&curUrl[' + attributeNames[i] + ']=';
-					additionalParameters += encodeURIComponent(element.getAttribute(attributeNames[i]));
-				}
-			}
-
-			var additionalAttributes = getAdditionalAttributes(editor);
-			for (i = additionalAttributes.length; --i >= 0;) {
-				if (element.hasAttribute(additionalAttributes[i])) {
-					additionalParameters += '&curUrl[' + additionalAttributes[i] + ']=';
-					additionalParameters += encodeURIComponent(element.getAttribute(additionalAttributes[i]));
-				}
-			}
-		}
-
-		openElementBrowser(
-			editor,
-			editor.lang.link.toolbar,
-			TYPO3.settings.Textarea.RTEPopupWindow.height,
-			makeUrlFromModulePath(
-				editor,
-				editor.config.typo3link.routeUrl,
-				additionalParameters
-			));
-	}
-
-	/**
-	 * Make url from url
-	 *
-	 * @param {Object} editor CKEditor object
-	 * @param {String} routeUrl URL
-	 * @param {String} parameters Additional parameters
-	 *
-	 * @return {String} The url
-	 */
-	function makeUrlFromModulePath(editor, routeUrl, parameters) {
-
-		return routeUrl
-			+ (routeUrl.indexOf('?') === -1 ? '?' : '&')
-			+ '&contentsLanguage=' + editor.config.contentsLanguage
-			+ '&editorId=' + editor.id
-			+ (parameters ? parameters : '');
-	}
-
-	/**
-	 * Open a window with container iframe
-	 *
-	 * @param {Object} editor The CKEditor instance
-	 * @param {String} title The window title (will be localized here)
-	 * @param {Integer} height The height of the containing iframe
-	 * @param {String} url The url to load ino the iframe
-	 */
-	function openElementBrowser(editor, title, height, url) {
-		require([
-			'jquery',
-			'TYPO3/CMS/Backend/Modal'
-			], function ($, Modal) {
-
-			Modal.advanced({
-				type: Modal.types.iframe,
-				title: title,
-				content: url,
-				size: Modal.sizes.large,
-				callback: function(currentModal) {
-					// Add the instance to the iframe itself
-					currentModal.data('ckeditor', editor);
-					currentModal.find('.t3js-modal-body')
-						.addClass('rte-ckeditor-window')
-						.attr('id', editor.id);
-				}
-			});
-		});
-	}
-
-	/**
-	 * Fetch attributes for the <a> tag which are allowed additionally
-	 * @param {Object} editor The CKEditor instance
-	 *
-	 * @return {Array} registered attributes available for the link
-	 */
-	function getAdditionalAttributes(editor) {
-		if (editor.config.typo3link.additionalAttributes && editor.config.typo3link.additionalAttributes.length) {
-			return editor.config.typo3link.additionalAttributes;
-		} else {
-			return [];
-		}
-	}
+(function() {
+
+  CKEDITOR.plugins.add('typo3link', {
+    elementBrowser: null,
+    init: function(editor) {
+      var allowedAttributes = ['!href', 'title', 'class', 'target', 'rel'],
+        required = 'a[href]';
+
+      var additionalAttributes = getAdditionalAttributes(editor);
+      if (additionalAttributes.length) {
+        allowedAttributes.push.apply(allowedAttributes, additionalAttributes);
+      }
+
+      // Override link command
+      editor.addCommand('link', {
+        exec: openLinkBrowser,
+        allowedContent: 'a[' + allowedAttributes.join(',') + ']',
+        requiredContent: required
+      });
+
+      // Override doubleclick opening default link dialog
+      editor.on('doubleclick', function(evt) {
+        var element = CKEDITOR.plugins.link.getSelectedLink(editor) || evt.data.element;
+        if (!element.isReadOnly() && element.is('a') && element.getAttribute('href')) {
+          evt.stop();
+          openLinkBrowser(editor, element);
+        }
+      }, null, null, 30);
+
+    }
+  });
+
+  /**
+   * Open link browser
+   *
+   * @param {Object} editor CKEditor object
+   * @param {Object} element Selected link element
+   */
+  function openLinkBrowser(editor, element) {
+    var additionalParameters = '';
+
+    if ($.isEmptyObject(element)) {
+      element = CKEDITOR.plugins.link.getSelectedLink(editor);
+    }
+    if (element) {
+      additionalParameters = '&curUrl[url]=' + encodeURIComponent(element.getAttribute('href'));
+      var i = 0,
+        attributeNames = ["target", "class", "title", "rel"];
+      for (i = 0; i < attributeNames.length; ++i) {
+        if (element.getAttribute(attributeNames[i])) {
+          additionalParameters += '&curUrl[' + attributeNames[i] + ']=';
+          additionalParameters += encodeURIComponent(element.getAttribute(attributeNames[i]));
+        }
+      }
+
+      var additionalAttributes = getAdditionalAttributes(editor);
+      for (i = additionalAttributes.length; --i >= 0;) {
+        if (element.hasAttribute(additionalAttributes[i])) {
+          additionalParameters += '&curUrl[' + additionalAttributes[i] + ']=';
+          additionalParameters += encodeURIComponent(element.getAttribute(additionalAttributes[i]));
+        }
+      }
+    }
+
+    openElementBrowser(
+      editor,
+      editor.lang.link.toolbar,
+      TYPO3.settings.Textarea.RTEPopupWindow.height,
+      makeUrlFromModulePath(
+        editor,
+        editor.config.typo3link.routeUrl,
+        additionalParameters
+      ));
+  }
+
+  /**
+   * Make url from url
+   *
+   * @param {Object} editor CKEditor object
+   * @param {String} routeUrl URL
+   * @param {String} parameters Additional parameters
+   *
+   * @return {String} The url
+   */
+  function makeUrlFromModulePath(editor, routeUrl, parameters) {
+
+    return routeUrl
+      + (routeUrl.indexOf('?') === -1 ? '?' : '&')
+      + '&contentsLanguage=' + editor.config.contentsLanguage
+      + '&editorId=' + editor.id
+      + (parameters ? parameters : '');
+  }
+
+  /**
+   * Open a window with container iframe
+   *
+   * @param {Object} editor The CKEditor instance
+   * @param {String} title The window title (will be localized here)
+   * @param {Integer} height The height of the containing iframe
+   * @param {String} url The url to load ino the iframe
+   */
+  function openElementBrowser(editor, title, height, url) {
+    require([
+      'jquery',
+      'TYPO3/CMS/Backend/Modal'
+    ], function($, Modal) {
+
+      Modal.advanced({
+        type: Modal.types.iframe,
+        title: title,
+        content: url,
+        size: Modal.sizes.large,
+        callback: function(currentModal) {
+          // Add the instance to the iframe itself
+          currentModal.data('ckeditor', editor);
+          currentModal.find('.t3js-modal-body')
+            .addClass('rte-ckeditor-window')
+            .attr('id', editor.id);
+        }
+      });
+    });
+  }
+
+  /**
+   * Fetch attributes for the <a> tag which are allowed additionally
+   * @param {Object} editor The CKEditor instance
+   *
+   * @return {Array} registered attributes available for the link
+   */
+  function getAdditionalAttributes(editor) {
+    if (editor.config.typo3link.additionalAttributes && editor.config.typo3link.additionalAttributes.length) {
+      return editor.config.typo3link.additionalAttributes;
+    } else {
+      return [];
+    }
+  }
 
 })();
diff --git a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js
index d7eb3f8fd84b..ff22f335c0bc 100644
--- a/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js
+++ b/typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/RteLinkBrowser.js
@@ -15,102 +15,102 @@
  * Module: TYPO3/CMS/RteCkeditor/RteLinkBrowser
  * LinkBrowser communication with parent window
  */
-define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/Modal'], function ($, LinkBrowser, Modal) {
-	'use strict';
+define(['jquery', 'TYPO3/CMS/Recordlist/LinkBrowser', 'TYPO3/CMS/Backend/Modal'], function($, LinkBrowser, Modal) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{plugin: null, CKEditor: null, siteUrl: string}}
-	 * @exports TYPO3/CMS/RteCkeditor/RteLinkBrowser
-	 */
-	var RteLinkBrowser = {
-		plugin: null,
-		CKEditor: null,
-		siteUrl: ''
-	};
+  /**
+   *
+   * @type {{plugin: null, CKEditor: null, siteUrl: string}}
+   * @exports TYPO3/CMS/RteCkeditor/RteLinkBrowser
+   */
+  var RteLinkBrowser = {
+    plugin: null,
+    CKEditor: null,
+    siteUrl: ''
+  };
 
-	/**
-	 * @param {String} editorId Id of CKEditor
-	 */
-	RteLinkBrowser.initialize = function (editorId) {
-		var editor = Modal.currentModal.data('ckeditor');
-		if (typeof editor !== 'undefined') {
-			RteLinkBrowser.CKEditor = editor;
-		} else {
-			var callerWindow;
-			if (typeof top.TYPO3.Backend !== 'undefined' && typeof top.TYPO3.Backend.ContentContainer.get() !== 'undefined') {
-				callerWindow = top.TYPO3.Backend.ContentContainer.get();
-			} else {
-				callerWindow = window.parent;
-			}
+  /**
+   * @param {String} editorId Id of CKEditor
+   */
+  RteLinkBrowser.initialize = function(editorId) {
+    var editor = Modal.currentModal.data('ckeditor');
+    if (typeof editor !== 'undefined') {
+      RteLinkBrowser.CKEditor = editor;
+    } else {
+      var callerWindow;
+      if (typeof top.TYPO3.Backend !== 'undefined' && typeof top.TYPO3.Backend.ContentContainer.get() !== 'undefined') {
+        callerWindow = top.TYPO3.Backend.ContentContainer.get();
+      } else {
+        callerWindow = window.parent;
+      }
 
-			$.each(callerWindow.CKEDITOR.instances, function (name, editor) {
-				if (editor.id === editorId) {
-					RteLinkBrowser.CKEditor = editor;
-				}
-			});
-		}
+      $.each(callerWindow.CKEDITOR.instances, function(name, editor) {
+        if (editor.id === editorId) {
+          RteLinkBrowser.CKEditor = editor;
+        }
+      });
+    }
 
-		// siteUrl etc are added as data attributes to the body tag
-		$.extend(RteLinkBrowser, $('body').data());
+    // siteUrl etc are added as data attributes to the body tag
+    $.extend(RteLinkBrowser, $('body').data());
 
-		$('.t3js-class-selector').on('change', function () {
-			if ($('option:selected', this).data('linkTitle')) {
-				$('.t3js-linkTitle').val($('option:selected', this).data('linkTitle'));
-			}
-		});
+    $('.t3js-class-selector').on('change', function() {
+      if ($('option:selected', this).data('linkTitle')) {
+        $('.t3js-linkTitle').val($('option:selected', this).data('linkTitle'));
+      }
+    });
 
-		$('.t3js-removeCurrentLink').on('click', function (event) {
-			event.preventDefault();
-			RteLinkBrowser.CKEditor.execCommand('unlink');
-			Modal.dismiss();
-		});
-	};
+    $('.t3js-removeCurrentLink').on('click', function(event) {
+      event.preventDefault();
+      RteLinkBrowser.CKEditor.execCommand('unlink');
+      Modal.dismiss();
+    });
+  };
 
-	/**
-	 * Store the final link
-	 *
-	 * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>")
-	 */
-	LinkBrowser.finalizeFunction = function (link) {
+  /**
+   * Store the final link
+   *
+   * @param {String} link The select element or anything else which identifies the link (e.g. "page:<pageUid>" or "file:<uid>")
+   */
+  LinkBrowser.finalizeFunction = function(link) {
 
-		var linkElement = RteLinkBrowser.CKEditor.document.createElement('a');
-		var attributes = LinkBrowser.getLinkAttributeValues();
-		var params = attributes.params ? attributes.params : '';
+    var linkElement = RteLinkBrowser.CKEditor.document.createElement('a');
+    var attributes = LinkBrowser.getLinkAttributeValues();
+    var params = attributes.params ? attributes.params : '';
 
-		if (attributes.target) {
-			linkElement.setAttribute('target', attributes.target);
-		}
-		if (attributes.class) {
-			linkElement.setAttribute('class', attributes.class);
-		}
-		if (attributes.title) {
-			linkElement.setAttribute('title', attributes.title);
-		}
-		delete attributes.title;
-		delete attributes.class;
-		delete attributes.target;
-		delete attributes.params;
+    if (attributes.target) {
+      linkElement.setAttribute('target', attributes.target);
+    }
+    if (attributes.class) {
+      linkElement.setAttribute('class', attributes.class);
+    }
+    if (attributes.title) {
+      linkElement.setAttribute('title', attributes.title);
+    }
+    delete attributes.title;
+    delete attributes.class;
+    delete attributes.target;
+    delete attributes.params;
 
-		$.each(attributes, function (attrName, attrValue) {
-			linkElement.setAttribute(attrName, attrValue);
-		});
+    $.each(attributes, function(attrName, attrValue) {
+      linkElement.setAttribute(attrName, attrValue);
+    });
 
-		linkElement.setAttribute('href', link + params);
+    linkElement.setAttribute('href', link + params);
 
-		var selection = RteLinkBrowser.CKEditor.getSelection();
-		if (selection && selection.getSelectedText() === '') {
-			selection.selectElement(selection.getStartElement());
-		}
-		if (selection && selection.getSelectedText()) {
-			linkElement.setText(selection.getSelectedText());
-		} else {
-			linkElement.setText(linkElement.getAttribute('href'));
-		}
-		RteLinkBrowser.CKEditor.insertElement(linkElement);
+    var selection = RteLinkBrowser.CKEditor.getSelection();
+    if (selection && selection.getSelectedText() === '') {
+      selection.selectElement(selection.getStartElement());
+    }
+    if (selection && selection.getSelectedText()) {
+      linkElement.setText(selection.getSelectedText());
+    } else {
+      linkElement.setText(linkElement.getAttribute('href'));
+    }
+    RteLinkBrowser.CKEditor.insertElement(linkElement);
 
-		Modal.dismiss();
-	};
+    Modal.dismiss();
+  };
 
-	return RteLinkBrowser;
+  return RteLinkBrowser;
 });
diff --git a/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js b/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js
index 018f7a39acfd..e89f52d06457 100644
--- a/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js
+++ b/typo3/sysext/scheduler/Resources/Public/JavaScript/PageBrowser.js
@@ -16,15 +16,15 @@
  * Javascript for adding links for calling the page browser pop up
  */
 define(['jquery'], function($) {
-    'use strict';
+  'use strict';
 
-    $(document).on('click', '.t3js-pageBrowser', function() {
-        var $this = $(this),
-            browserWin = "",
-            pageUrl = $this.data('url');
+  $(document).on('click', '.t3js-pageBrowser', function() {
+    var $this = $(this),
+      browserWin = "",
+      pageUrl = $this.data('url');
 
-        browserWin = window.open(pageUrl,"Typo3WinBrowser","height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1");
-        browserWin.focus();
-    });
+    browserWin = window.open(pageUrl, "Typo3WinBrowser", "height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1");
+    browserWin.focus();
+  });
 
 });
diff --git a/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js b/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js
index 3af13bbab617..ed6ccfa47e8d 100644
--- a/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js
+++ b/typo3/sysext/scheduler/Resources/Public/JavaScript/Scheduler.js
@@ -15,179 +15,178 @@
  * Module: TYPO3/CMS/Scheduler/Scheduler
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/SplitButtons',
-		'datatables'
-		], function($, SplitButtons) {
-
-	/**
-	 *
-	 * @type {{}}
-	 * @exports TYPO3/CMS/Scheduler/Scheduler
-	 */
-	var Scheduler = {
-	};
-
-	var allCheckedStatus = false;
-
-	/**
-	 * This method reacts on changes to the task class
-	 * It switches on or off the relevant extra fields
-	 *
-	 * @param {Object} theSelector
-	 */
-	Scheduler.actOnChangedTaskClass = function(theSelector) {
-		var taskClass = theSelector.val();
-		taskClass = taskClass.toLowerCase().replace(/\\/g, '-');
-
-		// Hide all extra fields
-		$('.extraFields').hide();
-		// Show only relevant extra fields
-		$('.extra_fields_' + taskClass).show();
-	};
-
-	/**
-	 * This method reacts on changes to the type of a task, i.e. single or recurring
-	 */
-	Scheduler.actOnChangedTaskType = function() {
-		Scheduler.toggleFieldsByTaskType($(this).val());
-	};
-
-	/**
-	 * This method reacts on field changes of all table field for table garbage collection task
-	 *
-	 * @param {Object} theCheckbox
-	 */
-	Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables = function(theCheckbox) {
-		var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays');
-		var $taskTableGarbageCollectionTable = $('#task_tableGarbageCollection_table');
-		if (theCheckbox.prop('checked')) {
-			$taskTableGarbageCollectionTable.prop('disabled', true);
-			$numberOfDays.prop('disabled', true);
-		} else {
-			// Get number of days for selected table
-			var numberOfDays = parseInt($numberOfDays.val());
-			if (numberOfDays < 1) {
-				var selectedTable = $taskTableGarbageCollectionTable.val();
-				if (typeof(defaultNumberOfDays[selectedTable]) !== 'undefined') {
-					numberOfDays = defaultNumberOfDays[selectedTable];
-				}
-			}
-
-			$taskTableGarbageCollectionTable.prop('disabled', false);
-			if (numberOfDays > 0) {
-				$numberOfDays.prop('disabled', false);
-			}
-		}
-	};
-
-	/**
-	 * This methods set the 'number of days' field to the default expire period
-	 * of the selected table
-	 *
-	 * @param {Object} theSelector
-	 */
-	Scheduler.actOnChangeSchedulerTableGarbageCollectionTable = function(theSelector) {
-		var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays');
-		if (defaultNumberOfDays[theSelector.val()] > 0) {
-			$numberOfDays.prop('disabled', false);
-			$numberOfDays.val(defaultNumberOfDays[theSelector.val()]);
-		} else {
-			$numberOfDays.prop('disabled', true);
-			$numberOfDays.val(0);
-		}
-	};
-
-	/**
-	 * Check or uncheck all checkboxes
-	 *
-	 * @param {Object} theSelector
-	 * @returns {Boolean}
-	 */
-	Scheduler.checkOrUncheckAllCheckboxes = function(theSelector) {
-		theSelector.parents('.tx_scheduler_mod1_table').find(':checkbox').prop('checked', !allCheckedStatus);
-		allCheckedStatus = !allCheckedStatus;
-		return false;
-	};
-
-	/**
-	 * Toggle the relevant form fields by task type
-	 *
-	 * @param {Integer} taskType
-	 */
-	Scheduler.toggleFieldsByTaskType = function(taskType) {
-		// Single task option = 1, Recurring task option = 2
-		taskType = parseInt(taskType);
-		$('#task_end_col').toggle(taskType === 2);
-		$('#task_frequency_row').toggle(taskType === 2);
-	};
-
-	/**
-	 * Toggle the visibility of task groups
-	 *
-	 * @param {Object} theSelector
-	 */
-	Scheduler.toggleTaskGroups = function(theSelector) {
-		var taskGroup = theSelector.data('task-group-id');
-		var taskGroupClass= '.taskGroup_' + taskGroup;
-		$(taskGroupClass).toggleClass('taskGroup--close');
-	};
-
-    /**
-	 * Registers listeners
-	 */
-	Scheduler.initializeEvents = function() {
-		$('.checkall').on('click', function() {
-			Scheduler.checkOrUncheckAllCheckboxes($(this));
-		});
-
-		$('#task_class').change(function() {
-			Scheduler.actOnChangedTaskClass($(this));
-		});
-
-		$('#task_type').change(Scheduler.actOnChangedTaskType);
-
-		$('#task_tableGarbageCollection_allTables').change(function() {
-			Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables($(this));
-		});
-
-		$('#task_tableGarbageCollection_table').change(function() {
-			Scheduler.actOnChangeSchedulerTableGarbageCollectionTable($(this));
-		});
-
-		$('.taskGroup').on('click', function() {
-			Scheduler.toggleTaskGroups($(this));
-		});
-
-		$('table.display').DataTable( {
-			"paging":   false,
-			"searching": false
-		} );
-	};
-
-	/**
-	 * Initialize default states
-	 */
-	Scheduler.initializeDefaultStates = function() {
-		var $taskType = $('#task_type');
-		if ($taskType.length) {
-			Scheduler.toggleFieldsByTaskType($taskType.val());
-		}
-		var $taskClass = $('#task_class');
-        if ($taskClass.length) {
-			Scheduler.actOnChangedTaskClass($taskClass);
+  'TYPO3/CMS/Backend/SplitButtons',
+  'datatables'
+], function($, SplitButtons) {
+
+  /**
+   *
+   * @type {{}}
+   * @exports TYPO3/CMS/Scheduler/Scheduler
+   */
+  var Scheduler = {};
+
+  var allCheckedStatus = false;
+
+  /**
+   * This method reacts on changes to the task class
+   * It switches on or off the relevant extra fields
+   *
+   * @param {Object} theSelector
+   */
+  Scheduler.actOnChangedTaskClass = function(theSelector) {
+    var taskClass = theSelector.val();
+    taskClass = taskClass.toLowerCase().replace(/\\/g, '-');
+
+    // Hide all extra fields
+    $('.extraFields').hide();
+    // Show only relevant extra fields
+    $('.extra_fields_' + taskClass).show();
+  };
+
+  /**
+   * This method reacts on changes to the type of a task, i.e. single or recurring
+   */
+  Scheduler.actOnChangedTaskType = function() {
+    Scheduler.toggleFieldsByTaskType($(this).val());
+  };
+
+  /**
+   * This method reacts on field changes of all table field for table garbage collection task
+   *
+   * @param {Object} theCheckbox
+   */
+  Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables = function(theCheckbox) {
+    var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays');
+    var $taskTableGarbageCollectionTable = $('#task_tableGarbageCollection_table');
+    if (theCheckbox.prop('checked')) {
+      $taskTableGarbageCollectionTable.prop('disabled', true);
+      $numberOfDays.prop('disabled', true);
+    } else {
+      // Get number of days for selected table
+      var numberOfDays = parseInt($numberOfDays.val());
+      if (numberOfDays < 1) {
+        var selectedTable = $taskTableGarbageCollectionTable.val();
+        if (typeof(defaultNumberOfDays[selectedTable]) !== 'undefined') {
+          numberOfDays = defaultNumberOfDays[selectedTable];
         }
-	};
-
-	$(Scheduler.initializeEvents);
-	$(Scheduler.initializeDefaultStates);
-
-	SplitButtons.addPreSubmitCallback(function() {
-		var taskClass = $('#task_class').val();
-		taskClass = taskClass.toLowerCase().replace(/\\/g, '-');
-
-		$('.extraFields').appendTo($('#extraFieldsHidden'));
-		$('.extra_fields_' + taskClass).appendTo($('#extraFieldsSection'));
-	});
-
-	return Scheduler;
+      }
+
+      $taskTableGarbageCollectionTable.prop('disabled', false);
+      if (numberOfDays > 0) {
+        $numberOfDays.prop('disabled', false);
+      }
+    }
+  };
+
+  /**
+   * This methods set the 'number of days' field to the default expire period
+   * of the selected table
+   *
+   * @param {Object} theSelector
+   */
+  Scheduler.actOnChangeSchedulerTableGarbageCollectionTable = function(theSelector) {
+    var $numberOfDays = $('#task_tableGarbageCollection_numberOfDays');
+    if (defaultNumberOfDays[theSelector.val()] > 0) {
+      $numberOfDays.prop('disabled', false);
+      $numberOfDays.val(defaultNumberOfDays[theSelector.val()]);
+    } else {
+      $numberOfDays.prop('disabled', true);
+      $numberOfDays.val(0);
+    }
+  };
+
+  /**
+   * Check or uncheck all checkboxes
+   *
+   * @param {Object} theSelector
+   * @returns {Boolean}
+   */
+  Scheduler.checkOrUncheckAllCheckboxes = function(theSelector) {
+    theSelector.parents('.tx_scheduler_mod1_table').find(':checkbox').prop('checked', !allCheckedStatus);
+    allCheckedStatus = !allCheckedStatus;
+    return false;
+  };
+
+  /**
+   * Toggle the relevant form fields by task type
+   *
+   * @param {Integer} taskType
+   */
+  Scheduler.toggleFieldsByTaskType = function(taskType) {
+    // Single task option = 1, Recurring task option = 2
+    taskType = parseInt(taskType);
+    $('#task_end_col').toggle(taskType === 2);
+    $('#task_frequency_row').toggle(taskType === 2);
+  };
+
+  /**
+   * Toggle the visibility of task groups
+   *
+   * @param {Object} theSelector
+   */
+  Scheduler.toggleTaskGroups = function(theSelector) {
+    var taskGroup = theSelector.data('task-group-id');
+    var taskGroupClass = '.taskGroup_' + taskGroup;
+    $(taskGroupClass).toggleClass('taskGroup--close');
+  };
+
+  /**
+   * Registers listeners
+   */
+  Scheduler.initializeEvents = function() {
+    $('.checkall').on('click', function() {
+      Scheduler.checkOrUncheckAllCheckboxes($(this));
+    });
+
+    $('#task_class').change(function() {
+      Scheduler.actOnChangedTaskClass($(this));
+    });
+
+    $('#task_type').change(Scheduler.actOnChangedTaskType);
+
+    $('#task_tableGarbageCollection_allTables').change(function() {
+      Scheduler.actOnChangeSchedulerTableGarbageCollectionAllTables($(this));
+    });
+
+    $('#task_tableGarbageCollection_table').change(function() {
+      Scheduler.actOnChangeSchedulerTableGarbageCollectionTable($(this));
+    });
+
+    $('.taskGroup').on('click', function() {
+      Scheduler.toggleTaskGroups($(this));
+    });
+
+    $('table.display').DataTable({
+      "paging": false,
+      "searching": false
+    });
+  };
+
+  /**
+   * Initialize default states
+   */
+  Scheduler.initializeDefaultStates = function() {
+    var $taskType = $('#task_type');
+    if ($taskType.length) {
+      Scheduler.toggleFieldsByTaskType($taskType.val());
+    }
+    var $taskClass = $('#task_class');
+    if ($taskClass.length) {
+      Scheduler.actOnChangedTaskClass($taskClass);
+    }
+  };
+
+  $(Scheduler.initializeEvents);
+  $(Scheduler.initializeDefaultStates);
+
+  SplitButtons.addPreSubmitCallback(function() {
+    var taskClass = $('#task_class').val();
+    taskClass = taskClass.toLowerCase().replace(/\\/g, '-');
+
+    $('.extraFields').appendTo($('#extraFieldsHidden'));
+    $('.extra_fields_' + taskClass).appendTo($('#extraFieldsSection'));
+  });
+
+  return Scheduler;
 });
diff --git a/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js b/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js
index a679c578ae52..eb7598348a07 100644
--- a/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js
+++ b/typo3/sysext/sys_action/Resources/Public/JavaScript/ActionTask.js
@@ -16,20 +16,20 @@
  * JavaScript to handle confirm windows in the task center module
  * @exports TYPO3/CMS/SysAction/ActionTask
  */
-define(['jquery', 'TYPO3/CMS/Backend/Modal'], function ($, Modal) {
-	$(function() {
-		$(document).on('click', '.t3js-confirm-trigger', function(e) {
-			e.preventDefault();
-			var $link = $(this);
-			Modal.confirm($link.data('title'), $link.data('message'))
-				.on('confirm.button.ok', function() {
-					self.location.href = $link.attr('href');
-					Modal.currentModal.trigger('modal-dismiss');
-				})
-				.on('confirm.button.cancel', function() {
-					Modal.currentModal.trigger('modal-dismiss');
-				});
-			return false;
-		});
-	});
+define(['jquery', 'TYPO3/CMS/Backend/Modal'], function($, Modal) {
+  $(function() {
+    $(document).on('click', '.t3js-confirm-trigger', function(e) {
+      e.preventDefault();
+      var $link = $(this);
+      Modal.confirm($link.data('title'), $link.data('message'))
+        .on('confirm.button.ok', function() {
+          self.location.href = $link.attr('href');
+          Modal.currentModal.trigger('modal-dismiss');
+        })
+        .on('confirm.button.cancel', function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        });
+      return false;
+    });
+  });
 });
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js
index d3a550c098da..f9b34f88ae38 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/CompletionResult.js
@@ -15,106 +15,106 @@
  * Module: TYPO3/CMS/T3editor/Addon/Hint/CompletionResult
  * Contains the CompletionResult class
  */
-define(['jquery'], function ($) {
-	/**
-	 *
-	 * @type {{tsRef: null, tsTreeNode: null}}
-	 * @exports TYPO3/CMS/T3editor/Addon/Hint/CompletionResult
-	 */
-	var CompletionResult = {
-		tsRef: null,
-		tsTreeNode: null
-	};
+define(['jquery'], function($) {
+  /**
+   *
+   * @type {{tsRef: null, tsTreeNode: null}}
+   * @exports TYPO3/CMS/T3editor/Addon/Hint/CompletionResult
+   */
+  var CompletionResult = {
+    tsRef: null,
+    tsTreeNode: null
+  };
 
-	/**
-	 *
-	 * @param {Object} config
-	 * @returns {{tsRef: null, tsTreeNode: null}}
-	 */
-	CompletionResult.init = function(config) {
-		CompletionResult.tsRef = config.tsRef;
-		CompletionResult.tsTreeNode = config.tsTreeNode;
+  /**
+   *
+   * @param {Object} config
+   * @returns {{tsRef: null, tsTreeNode: null}}
+   */
+  CompletionResult.init = function(config) {
+    CompletionResult.tsRef = config.tsRef;
+    CompletionResult.tsTreeNode = config.tsTreeNode;
 
-		return CompletionResult;
-	};
+    return CompletionResult;
+  };
 
-	/**
-	 * returns the type of the currentTsTreeNode
-	 *
-	 * @returns {*}
-	 */
-	CompletionResult.getType = function() {
-		var val = CompletionResult.tsTreeNode.getValue();
-		if (CompletionResult.tsRef.isType(val)) {
-			return CompletionResult.tsRef.getType(val);
-		}
-		return null;
-	};
+  /**
+   * returns the type of the currentTsTreeNode
+   *
+   * @returns {*}
+   */
+  CompletionResult.getType = function() {
+    var val = CompletionResult.tsTreeNode.getValue();
+    if (CompletionResult.tsRef.isType(val)) {
+      return CompletionResult.tsRef.getType(val);
+    }
+    return null;
+  };
 
-	/**
-	 * returns a list of possible path completions (proposals), which is:
-	 * a list of the children of the current TsTreeNode (= userdefined properties)
-	 * and a list of properties allowed for the current object in the TsRef
-	 * remove all words from list that don't start with the string in filter
-	 *
-	 * @param {String} filter beginning of the words contained in the proposal list
-	 * @return {Array} an Array of Proposals
-	 */
-	CompletionResult.getFilteredProposals = function(filter) {
-		var defined = [],
-			propArr = [],
-			childNodes = CompletionResult.tsTreeNode.getChildNodes(),
-			value = CompletionResult.tsTreeNode.getValue();
+  /**
+   * returns a list of possible path completions (proposals), which is:
+   * a list of the children of the current TsTreeNode (= userdefined properties)
+   * and a list of properties allowed for the current object in the TsRef
+   * remove all words from list that don't start with the string in filter
+   *
+   * @param {String} filter beginning of the words contained in the proposal list
+   * @return {Array} an Array of Proposals
+   */
+  CompletionResult.getFilteredProposals = function(filter) {
+    var defined = [],
+      propArr = [],
+      childNodes = CompletionResult.tsTreeNode.getChildNodes(),
+      value = CompletionResult.tsTreeNode.getValue();
 
-		// first get the childNodes of the Node (=properties defined by the user)
-		for (var key in childNodes) {
-			if (typeof childNodes[key].value !== 'undefined' && childNodes[key].value !== null) {
-				var propObj = {};
-				propObj.word = key;
-				if (CompletionResult.tsRef.typeHasProperty(value, childNodes[key].name)) {
-					CompletionResult.tsRef.cssClass = 'definedTSREFProperty';
-					propObj.type = childNodes[key].value;
-				} else {
-					propObj.cssClass = 'userProperty';
-					if (CompletionResult.tsRef.isType(childNodes[key].value)) {
-						propObj.type = childNodes[key].value;
-					} else {
-						propObj.type = '';
-					}
-				}
-				propArr.push(propObj);
-				defined[key] = true;
-			}
-		}
+    // first get the childNodes of the Node (=properties defined by the user)
+    for (var key in childNodes) {
+      if (typeof childNodes[key].value !== 'undefined' && childNodes[key].value !== null) {
+        var propObj = {};
+        propObj.word = key;
+        if (CompletionResult.tsRef.typeHasProperty(value, childNodes[key].name)) {
+          CompletionResult.tsRef.cssClass = 'definedTSREFProperty';
+          propObj.type = childNodes[key].value;
+        } else {
+          propObj.cssClass = 'userProperty';
+          if (CompletionResult.tsRef.isType(childNodes[key].value)) {
+            propObj.type = childNodes[key].value;
+          } else {
+            propObj.type = '';
+          }
+        }
+        propArr.push(propObj);
+        defined[key] = true;
+      }
+    }
 
-		// then get the tsref properties
-		var props = CompletionResult.tsRef.getPropertiesFromTypeId(CompletionResult.tsTreeNode.getValue());
-		for (var key in props) {
-			// show just the TSREF properties - no properties of the array-prototype and no properties which have been defined by the user
-			if (typeof props[key].value !== 'undefined' && defined[key] !== true) {
-				var propObj = {};
-				propObj.word = key;
-				propObj.cssClass = 'undefinedTSREFProperty';
-				propObj.type = props[key].value;
-				propArr.push(propObj);
-			}
-		}
+    // then get the tsref properties
+    var props = CompletionResult.tsRef.getPropertiesFromTypeId(CompletionResult.tsTreeNode.getValue());
+    for (var key in props) {
+      // show just the TSREF properties - no properties of the array-prototype and no properties which have been defined by the user
+      if (typeof props[key].value !== 'undefined' && defined[key] !== true) {
+        var propObj = {};
+        propObj.word = key;
+        propObj.cssClass = 'undefinedTSREFProperty';
+        propObj.type = props[key].value;
+        propArr.push(propObj);
+      }
+    }
 
-		var result = [],
-			wordBeginning = '';
+    var result = [],
+      wordBeginning = '';
 
-		for (var i = 0; i < propArr.length; i++) {
-			if (filter.length === 0) {
-				result.push(propArr[i]);
-				continue;
-			}
-			wordBeginning = propArr[i].word.substring(0, filter.length);
-			if (wordBeginning.toLowerCase() === filter.toLowerCase()) {
-				result.push(propArr[i]);
-			}
-		}
-		return result;
-	};
+    for (var i = 0; i < propArr.length; i++) {
+      if (filter.length === 0) {
+        result.push(propArr[i]);
+        continue;
+      }
+      wordBeginning = propArr[i].word.substring(0, filter.length);
+      if (wordBeginning.toLowerCase() === filter.toLowerCase()) {
+        result.push(propArr[i]);
+      }
+    }
+    return result;
+  };
 
-	return CompletionResult;
-});
\ No newline at end of file
+  return CompletionResult;
+});
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js
index be5a31488a27..c6c3a2595fd2 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsCodeCompletion.js
@@ -16,157 +16,157 @@
  * Contains the TsCodeCompletion class
  */
 define([
-	'jquery',
-	'TYPO3/CMS/T3editor/Addon/Hint/TsRef',
-	'TYPO3/CMS/T3editor/Addon/Hint/TsParser',
-	'TYPO3/CMS/T3editor/Addon/Hint/CompletionResult'
-], function ($, TsRef, TsParser, CompletionResult) {
-	/**
-	 *
-	 * @type {{tsRef: *, proposals: null, compResult: null, currentCursorPosition: null, extTsObjTree: {}, codemirror: null, parser: null, plugins: string[]}}
-	 * @exports TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion
-	 */
-	var TsCodeCompletion = {
-		tsRef: TsRef,
-		proposals: null,
-		compResult: null,
-		currentCursorPosition: null,
-		extTsObjTree: {},
-		codemirror: null,
-		parser: null
-	};
-
-	/**
-	 * All external templates along the rootline have to be loaded,
-	 * this function retrieves the JSON code by committing a AJAX request
-	 *
-	 * @param {number} id
-	 */
-	TsCodeCompletion.loadExtTemplatesAsync = function(id) {
-		// Ensure id is an integer
-		id *= 1;
-		if (isNaN(id) || id === 0) {
-			return null;
-		}
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['t3editor_codecompletion_loadtemplates'],
-			data: {
-				pageId: id
-			},
-			dataType: 'json',
-			success: function(response) {
-				TsCodeCompletion.extTsObjTree.c = response;
-				TsCodeCompletion.resolveExtReferencesRec(TsCodeCompletion.extTsObjTree.c);
-			}
-		});
-	};
-
-	/**
-	 * Since the references are not resolved server side we have to do it client-side
-	 * Benefit: less loading time due to less data which has to be transmitted
-	 *
-	 * @param {Array} childNodes
-	 */
-	TsCodeCompletion.resolveExtReferencesRec = function(childNodes) {
-		for (var key in childNodes) {
-			var childNode;
-			// if the childnode has a value and there is a part of a reference operator ('<')
-			// and it does not look like a html tag ('>')
-			if (childNodes[key].v && childNodes[key].v[0] === '<' && childNodes[key].v.indexOf('>') === -1 ) {
-				var path = $.trim(childNodes[key].v.replace(/</, ''));
-				// if there are still whitespaces it's no path
-				if (path.indexOf(' ') === -1) {
-					childNode = TsCodeCompletion.getExtChildNode(path);
-					// if the node was found - reference it
-					if (childNode !== null) {
-						childNodes[key] = childNode;
-					}
-				}
-			}
-			// if there was no reference-resolving then we go deeper into the tree
-			if (!childNode && childNodes[key].c) {
-				TsCodeCompletion.resolveExtReferencesRec(childNodes[key].c);
-			}
-		}
-	};
-
-	/**
-	 * Get the child node of given path
-	 *
-	 * @param {String} path
-	 * @returns {Object}
-	 */
-	TsCodeCompletion.getExtChildNode = function(path) {
-		var extTree = TsCodeCompletion.extTsObjTree,
-			path = path.split('.'),
-			pathSeg;
-
-		for (var i = 0; i < path.length; i++) {
-			pathSeg = path[i];
-			if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
-				return null;
-			}
-			extTree = extTree.c[pathSeg];
-		}
-		return extTree;
-	};
-
-	/**
-	 *
-	 * @returns {String}
-	 */
-	TsCodeCompletion.getFilter = function() {
-		var currentLine = TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string;
-		if (currentLine) {
-			var filter = currentLine.replace('.', '');
-			return filter.replace(/\s/g, '');
-		}
-		return '';
-	};
-
-	/**
-	 * Refreshes the code completion list based on the cursor's position
-	 */
-	TsCodeCompletion.refreshCodeCompletion = function(codemirror) {
-		TsCodeCompletion.codemirror = codemirror;
-
-		// retrieves the node right to the cursor
-		TsCodeCompletion.currentCursorPosition = TsCodeCompletion.codemirror.doc.getCursor();
-
-		// the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active
-		var filter = TsCodeCompletion.getFilter();
-
-		if (TsCodeCompletion.compResult === null || TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string === '.') {
-			// TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults())
-			var currentTsTreeNode = TsCodeCompletion.parser.buildTsObjTree(TsCodeCompletion.codemirror);
-			TsCodeCompletion.compResult = CompletionResult.init({
-				tsRef: TsRef,
-				tsTreeNode: currentTsTreeNode
-			});
-		}
-
-		TsCodeCompletion.proposals = TsCodeCompletion.compResult.getFilteredProposals(filter);
-
-		var proposals = [];
-		for (var i = 0; i < TsCodeCompletion.proposals.length; i++) {
-			proposals[i] = TsCodeCompletion.proposals[i].word;
-		}
-
-		return proposals;
-	};
-
-	/**
-	 * Resets the completion list
-	 */
-	TsCodeCompletion.resetCompList = function() {
-		TsCodeCompletion.compResult = null;
-	};
-
-	$(function() {
-		TsCodeCompletion.parser = TsParser.init(TsCodeCompletion.tsRef, TsCodeCompletion.extTsObjTree);
-		TsCodeCompletion.tsRef.loadTsrefAsync();
-		TsCodeCompletion.loadExtTemplatesAsync($('input[name="effectivePid"]').first().val());
-	});
-
-	return TsCodeCompletion;
+  'jquery',
+  'TYPO3/CMS/T3editor/Addon/Hint/TsRef',
+  'TYPO3/CMS/T3editor/Addon/Hint/TsParser',
+  'TYPO3/CMS/T3editor/Addon/Hint/CompletionResult'
+], function($, TsRef, TsParser, CompletionResult) {
+  /**
+   *
+   * @type {{tsRef: *, proposals: null, compResult: null, currentCursorPosition: null, extTsObjTree: {}, codemirror: null, parser: null, plugins: string[]}}
+   * @exports TYPO3/CMS/T3editor/CodeCompletion/TsCodeCompletion
+   */
+  var TsCodeCompletion = {
+    tsRef: TsRef,
+    proposals: null,
+    compResult: null,
+    currentCursorPosition: null,
+    extTsObjTree: {},
+    codemirror: null,
+    parser: null
+  };
+
+  /**
+   * All external templates along the rootline have to be loaded,
+   * this function retrieves the JSON code by committing a AJAX request
+   *
+   * @param {number} id
+   */
+  TsCodeCompletion.loadExtTemplatesAsync = function(id) {
+    // Ensure id is an integer
+    id *= 1;
+    if (isNaN(id) || id === 0) {
+      return null;
+    }
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['t3editor_codecompletion_loadtemplates'],
+      data: {
+        pageId: id
+      },
+      dataType: 'json',
+      success: function(response) {
+        TsCodeCompletion.extTsObjTree.c = response;
+        TsCodeCompletion.resolveExtReferencesRec(TsCodeCompletion.extTsObjTree.c);
+      }
+    });
+  };
+
+  /**
+   * Since the references are not resolved server side we have to do it client-side
+   * Benefit: less loading time due to less data which has to be transmitted
+   *
+   * @param {Array} childNodes
+   */
+  TsCodeCompletion.resolveExtReferencesRec = function(childNodes) {
+    for (var key in childNodes) {
+      var childNode;
+      // if the childnode has a value and there is a part of a reference operator ('<')
+      // and it does not look like a html tag ('>')
+      if (childNodes[key].v && childNodes[key].v[0] === '<' && childNodes[key].v.indexOf('>') === -1) {
+        var path = $.trim(childNodes[key].v.replace(/</, ''));
+        // if there are still whitespaces it's no path
+        if (path.indexOf(' ') === -1) {
+          childNode = TsCodeCompletion.getExtChildNode(path);
+          // if the node was found - reference it
+          if (childNode !== null) {
+            childNodes[key] = childNode;
+          }
+        }
+      }
+      // if there was no reference-resolving then we go deeper into the tree
+      if (!childNode && childNodes[key].c) {
+        TsCodeCompletion.resolveExtReferencesRec(childNodes[key].c);
+      }
+    }
+  };
+
+  /**
+   * Get the child node of given path
+   *
+   * @param {String} path
+   * @returns {Object}
+   */
+  TsCodeCompletion.getExtChildNode = function(path) {
+    var extTree = TsCodeCompletion.extTsObjTree,
+      path = path.split('.'),
+      pathSeg;
+
+    for (var i = 0; i < path.length; i++) {
+      pathSeg = path[i];
+      if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
+        return null;
+      }
+      extTree = extTree.c[pathSeg];
+    }
+    return extTree;
+  };
+
+  /**
+   *
+   * @returns {String}
+   */
+  TsCodeCompletion.getFilter = function() {
+    var currentLine = TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string;
+    if (currentLine) {
+      var filter = currentLine.replace('.', '');
+      return filter.replace(/\s/g, '');
+    }
+    return '';
+  };
+
+  /**
+   * Refreshes the code completion list based on the cursor's position
+   */
+  TsCodeCompletion.refreshCodeCompletion = function(codemirror) {
+    TsCodeCompletion.codemirror = codemirror;
+
+    // retrieves the node right to the cursor
+    TsCodeCompletion.currentCursorPosition = TsCodeCompletion.codemirror.doc.getCursor();
+
+    // the cursornode has to be stored cause inserted breaks have to be deleted after pressing enter if the codecompletion is active
+    var filter = TsCodeCompletion.getFilter();
+
+    if (TsCodeCompletion.compResult === null || TsCodeCompletion.codemirror.getTokenAt(TsCodeCompletion.currentCursorPosition).string === '.') {
+      // TODO: implement cases: operatorCompletion reference/copy path completion (formerly found in getCompletionResults())
+      var currentTsTreeNode = TsCodeCompletion.parser.buildTsObjTree(TsCodeCompletion.codemirror);
+      TsCodeCompletion.compResult = CompletionResult.init({
+        tsRef: TsRef,
+        tsTreeNode: currentTsTreeNode
+      });
+    }
+
+    TsCodeCompletion.proposals = TsCodeCompletion.compResult.getFilteredProposals(filter);
+
+    var proposals = [];
+    for (var i = 0; i < TsCodeCompletion.proposals.length; i++) {
+      proposals[i] = TsCodeCompletion.proposals[i].word;
+    }
+
+    return proposals;
+  };
+
+  /**
+   * Resets the completion list
+   */
+  TsCodeCompletion.resetCompList = function() {
+    TsCodeCompletion.compResult = null;
+  };
+
+  $(function() {
+    TsCodeCompletion.parser = TsParser.init(TsCodeCompletion.tsRef, TsCodeCompletion.extTsObjTree);
+    TsCodeCompletion.tsRef.loadTsrefAsync();
+    TsCodeCompletion.loadExtTemplatesAsync($('input[name="effectivePid"]').first().val());
+  });
+
+  return TsCodeCompletion;
 });
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js
index 1ba5181ab1d4..44876480ef30 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsParser.js
@@ -16,502 +16,503 @@
  * Contains the TsCodeCompletion class
  */
 define([
-	'jquery', 'TYPO3/CMS/T3editor/Addon/Hint/TsRef'
-], function ($) {
-	/**
-	 *
-	 * @type {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}}
-	 * @exports TYPO3/CMS/T3editor/Addon/Hint/TsParser
-	 */
-	var TsParser = {
-		typeId: null,
-		properties: null,
-		typeTree: [],
-		doc: null,
-		tsRef: null,
-		extTsObjTree: [],
-		tsTree: null
-	};
-
-	/**
-	 *
-	 * @param {Object} tsRef
-	 * @param {Object} extTsObjTree
-	 * @returns {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}}
-	 */
-	TsParser.init = function(tsRef, extTsObjTree) {
-		TsParser.tsRef = tsRef;
-		TsParser.extTsObjTree = extTsObjTree;
-		TsParser.tsTree = new TsParser.treeNode('_L_');
-
-		return TsParser;
-	};
-
-	/**
-	 *
-	 * @param {String} nodeName
-	 */
-	TsParser.treeNode = function(nodeName) {
-		this.name = nodeName;
-		this.childNodes = [];
-		this.extPath = '';
-		this.value = '';
-		this.isExternal = false;
-
-		/**
-		 * Returns local properties and the properties of the external templates
-		 *
-		 * @return {Array}
-		 */
-		this.getChildNodes = function() {
-			var node = this.getExtNode();
-			if (node !== null && typeof node.c === 'object') {
-				for (key in node.c) {
-					var tn = new TsParser.treeNode(key, this.tsObjTree);
-					tn.global = true;
-					tn.value = (node.c[key].v)? node.c[key].v : "";
-					tn.isExternal = true;
-					this.childNodes[key] = tn;
-				}
-			}
-			return this.childNodes;
-		};
-
-		/**
-		 * Returns the value of a node
-		 *
-		 * @returns {String}
-		 */
-		this.getValue = function() {
-			if (this.value) {
-				return this.value;
-			}
-			var node = this.getExtNode();
-			if (node && node.v) {
-				return node.v;
-			}
-
-			var type = this.getNodeTypeFromTsref();
-			if (type) {
-				return type;
-			}
-			return '';
-		};
-
-		/**
-		 * This method will try to resolve the properties recursively from right
-		 * to left. If the node's value property is not set, it will look for the
-		 * value of its parent node, and if there is a matching childProperty
-		 * (according to the TSREF) it will return the childProperties value.
-		 * If there is no value in the parent node it will go one step further
-		 * and look into the parent node of the parent node,...
-		 *
-		 * @return {String}
-		 */
-		this.getNodeTypeFromTsref = function() {
-			var path = this.extPath.split('.'),
-				lastSeg = path.pop();
-
-			// attention: there will be recursive calls if necessary
-			var parentValue = this.parent.getValue();
-			if (parentValue) {
-				if (TsParser.tsRef.typeHasProperty(parentValue, lastSeg)) {
-					var type = TsParser.tsRef.getType(parentValue);
-					return type.properties[lastSeg].value;
-				}
-			}
-			return '';
-		};
-
-		/**
-		 * Will look in the external ts-tree (static templates, templates on other pages)
-		 * if there is a value or childproperties assigned to the current node.
-		 * The method uses the extPath of the current node to navigate to the corresponding
-		 * node in the external tree
-		 *
-		 * @return {Object}
-		 */
-		this.getExtNode = function() {
-			var extTree = TsParser.extTsObjTree,
-				path,
-				pathSeg;
-
-			if (this.extPath === '') {
-				return extTree;
-			}
-			path = this.extPath.split('.');
-
-			for (var i = 0; i < path.length; i++) {
-				pathSeg = path[i];
-				if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
-					return null;
-				}
-				extTree = extTree.c[pathSeg];
-			}
-			return extTree;
-		};
-	};
-
-	/**
-	 * Check if there is an operator in the line and return it
-	 * if there is none, return -1
-	 *
-	 * @return {(String|Number)}
-	 */
-	TsParser.getOperator = function(line) {
-		var operators = [':=', '=<', '<', '>', '='];
-		for (var i = 0; i < operators.length; i++) {
-			var op = operators[i];
-			if (line.indexOf(op) !== -1) {
-				// check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML)
-				// we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder"
-				if ((op === '=<' || op === '<') && line.indexOf('>') > -1) {
-					// if there is a ">" in the line suppose there's some HTML
-					return '=';
-				}
-				return op;
-			}
-		}
-		return -1;
-	};
-
-	/**
-	 * Build the TypoScript object tree
-	 */
-	TsParser.buildTsObjTree = function(codemirror) {
-		TsParser.tsTree = new TsParser.treeNode('');
-		TsParser.tsTree.value = 'TLO';
-
-		function Stack() {
-		}
-		Stack.prototype = [];
-		Stack.prototype.lastElementEquals = function(str) {
-			return this.length > 0 && this[this.length-1] === str;
-		};
-
-		Stack.prototype.popIfLastElementEquals = function(str) {
-			if (this.lastElementEquals(str)) {
-				this.pop();
-				return true;
-			}
-			return false;
-		};
-
-		var currentLine = 0,
-			cursorPosition = codemirror.getCursor(),
-			line = '',
-			stack = new Stack(),
-			prefixes = [],
-			ignoreLine = false,
-			insideCondition = false;
-
-		while (currentLine <= cursorPosition.line) {
-			line = '';
-			var tokens = codemirror.getLineTokens(currentLine);
-			for (var i = 0; i <= tokens.length; ++i) {
-				if (i < tokens.length && tokens[i].string.length > 0) {
-					var tokenValue = tokens[i].string;
-
-					if (tokenValue[0] === '#') {
-						stack.push('#');
-					} else if (tokenValue === '(') {
-						stack.push('(');
-					} else if (tokenValue[0] === '/' && tokenValue[1] === '*') {
-						stack.push('/*');
-					} else if (tokenValue === '{') {
-						// TODO: ignore whole block if wrong whitespaces in this line
-						if (TsParser.getOperator(line) === -1) {
-							stack.push('{');
-							prefixes.push($.trim(line));
-							ignoreLine = true;
-						}
-					}
-					// TODO: conditions
-					// if condition starts -> ignore everything until end of condition
-					if (tokenValue.search(/^\s*\[.*\]/) !== -1
-						&& line.search(/\S/) === -1
-						&& tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) === -1
-						&& !stack.lastElementEquals('#')
-						&& !stack.lastElementEquals('/*')
-						&& !stack.lastElementEquals('{')
-						&& !stack.lastElementEquals('(')
-					) {
-						insideCondition = true;
-						ignoreLine = true;
-					}
-
-					// if end of condition reached
-					if (line.search(/\S/) === -1
-						&& !stack.lastElementEquals('#')
-						&& !stack.lastElementEquals('/*')
-						&& !stack.lastElementEquals('(')
-						&& (
-							(tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) !== -1
-							&& !stack.lastElementEquals('{'))
-							|| (tokenValue.search(/^\s*\[(global|GLOBAL)\]/) !== -1)
-						)
-					) {
-						insideCondition = false;
-						ignoreLine = true;
-					}
-
-					if (tokenValue === ')') {
-						stack.popIfLastElementEquals('(');
-					}
-					if (tokenValue[0] === '*' && tokenValue[1] === '/') {
-						stack.popIfLastElementEquals('/*');
-						ignoreLine = true;
-					}
-					if (tokenValue === '}') {
-						//no characters except whitespace allowed before closing bracket
-						var trimmedLine = line.replace(/\s/g, '');
-						if (trimmedLine === '') {
-							stack.popIfLastElementEquals('{');
-							if (prefixes.length > 0) {
-								prefixes.pop();
-							}
-							ignoreLine = true;
-						}
-					}
-					if (!stack.lastElementEquals('#')) {
-						line += tokenValue;
-					}
-				} else {
-					// ignore comments, ...
-					if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) {
-						line = $.trim(line);
-						// check if there is any operator in this line
-						var op = TsParser.getOperator(line);
-						if (op !== -1) {
-							// figure out the position of the operator
-							var pos = line.indexOf(op);
-							// the target objectpath should be left to the operator
-							var path = line.substring(0, pos);
-							// if we are in between curly brackets: add prefixes to object path
-							if (prefixes.length > 0) {
-								path = prefixes.join('.') + '.' + path;
-							}
-							// the type or value should be right to the operator
-							var str = line.substring(pos + op.length, line.length);
-							path = $.trim(path);
-							str = $.trim(str);
-							switch (op) { // set a value or create a new object
-								case '=':
-									//ignore if path is empty or contains whitespace
-									if (path.search(/\s/g) === -1 && path.length > 0) {
-										TsParser.setTreeNodeValue(path, str);
-									}
-									break;
-								case '=<': // reference to another object in the tree
-									// resolve relative path
-									if (prefixes.length > 0 && str.substr(0, 1) === '.') {
-										str = prefixes.join('.') + str;
-									}
-									//ignore if either path or str is empty or contains whitespace
-									if (path.search(/\s/g) === -1
-										&& path.length > 0
-										&& str.search(/\s/g) === -1
-										&& str.length > 0
-									) {
-										TsParser.setReference(path, str);
-									}
-									break;
-								case '<': // copy from another object in the tree
-									// resolve relative path
-									if (prefixes.length > 0 && str.substr(0, 1) === '.') {
-										str = prefixes.join('.') + str;
-									}
-									//ignore if either path or str is empty or contains whitespace
-									if (path.search(/\s/g) === -1
-										&& path.length > 0
-										&& str.search(/\s/g) === -1
-										&& str.length > 0
-									) {
-										TsParser.setCopy(path, str);
-									}
-									break;
-								case '>': // delete object value and properties
-									TsParser.deleteTreeNodeValue(path);
-									break;
-								case ':=': // function operator
-									// TODO: function-operator
-									break;
-							}
-						}
-					}
-					stack.popIfLastElementEquals('#');
-					ignoreLine = false;
-				}
-			}
-			currentLine++;
-		}
-		// when node at cursorPos is reached:
-		// save currentLine, currentTsTreeNode and filter if necessary
-		// if there is a reference or copy operator ('<' or '=<')
-		// return the treeNode of the path right to the operator,
-		// else try to build a path from the whole line
-		if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) {
-			var i = line.indexOf('<');
-
-			if (i !== -1) {
-				var path = line.substring(i+1, line.length);
-				path = $.trim(path);
-				if (prefixes.length > 0 && path.substr(0, 1) === '.') {
-					path = prefixes.join('.') + path;
-				}
-			} else {
-				var path = line;
-				if (prefixes.length > 0) {
-					path = prefixes.join('.') + '.' + path;
-					path = path.replace(/\s/g, '');
-				}
-			}
-			var lastDot = path.lastIndexOf('.');
-			path = path.substring(0, lastDot);
-		}
-		return TsParser.getTreeNode(path);
-	};
-
-	/**
-	 * Iterates through the object tree, and creates treenodes
-	 * along the path, if necessary
-	 *
-	 * @param {String} path
-	 * @returns {Object}
-	 */
-	TsParser.getTreeNode = function(path) {
-		path = $.trim(path);
-		if (path.length === 0) {
-			return TsParser.tsTree;
-		}
-		var aPath = path.split('.');
-
-		var subTree = TsParser.tsTree.childNodes,
-			pathSeg,
-			parent = TsParser.tsTree;
-
-		// step through the path from left to right
-		for (var i = 0; i < aPath.length; i++) {
-			pathSeg = aPath[i];
-
-			// if there isn't already a treenode
-			if (typeof subTree[pathSeg] === 'undefined' || typeof subTree[pathSeg].childNodes === 'undefined') { // if this subpath is not defined in the code
-				// create a new treenode
-				subTree[pathSeg] = new TsParser.treeNode(pathSeg);
-				subTree[pathSeg].parent = parent;
-				// the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates
-				var extPath = parent.extPath;
-				if (extPath) {
-					extPath += '.';
-				}
-				extPath += pathSeg;
-				subTree[pathSeg].extPath = extPath;
-			}
-			if (i === aPath.length - 1) {
-				return subTree[pathSeg];
-			}
-			parent = subTree[pathSeg];
-			subTree = subTree[pathSeg].childNodes;
-		}
-	};
-
-	/**
-	 * Navigates to the respecting treenode,
-	 * create nodes in the path, if necessary, and sets the value
-	 *
-	 * @param {String} path
-	 * @param {String} value
-	 */
-	TsParser.setTreeNodeValue = function(path, value) {
-		var treeNode = TsParser.getTreeNode(path);
-		// if we are inside a GIFBUILDER Object
-		if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "TEXT") {
-			value = 'GB_TEXT';
-		}
-		if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "IMAGE") {
-			value = 'GB_IMAGE';
-		}
-
-		// just override if it is a real objecttype
-		if (TsParser.tsRef.isType(value)) {
-			treeNode.value = value;
-		}
-	};
-
-	/**
-	 * Navigates to the respecting treenode,
-	 * creates nodes if necessary, empties the value and childNodes-Array
-	 *
-	 * @param {String} path
-	 */
-	TsParser.deleteTreeNodeValue = function(path) {
-		var treeNode = TsParser.getTreeNode(path);
-		// currently the node is not deleted really, it's just not displayed cause value == null
-		// deleting it would be a cleaner solution
-		treeNode.value = null;
-		treeNode.childNodes = {};
-	};
-
-	/**
-	 * Copies a reference of the treeNode specified by path2
-	 * to the location specified by path1
-	 *
-	 * @param {String} path1
-	 * @param {String} path2
-	 */
-	TsParser.setReference = function(path1, path2) {
-		var path1arr = path1.split('.'),
-			lastNodeName = path1arr[path1arr.length - 1],
-			treeNode1 = TsParser.getTreeNode(path1),
-			treeNode2 = TsParser.getTreeNode(path2);
-
-		if (treeNode1.parent !== null) {
-			treeNode1.parent.childNodes[lastNodeName] = treeNode2;
-		} else {
-			TsParser.tsTree.childNodes[lastNodeName] = treeNode2;
-		}
-	};
-
-	/**
-	 * copies a treeNode specified by path2
-	 * to the location specified by path1
-	 *
-	 * @param {String} path1
-	 * @param {String} path2
-	 */
-	TsParser.setCopy = function(path1, path2) {
-		this.clone = function(myObj) {
-			if (typeof myObj !== 'object') {
-				return myObj;
-			}
-
-			var myNewObj = {};
-			for (var i in myObj) {
-				// disable recursive cloning for parent object -> copy by reference
-				if (i !== 'parent') {
-					if (typeof myObj[i] === 'object') {
-						myNewObj[i] = this.clone(myObj[i]);
-					} else {
-						myNewObj[i] = myObj[i];
-					}
-				} else {
-					myNewObj.parent = myObj.parent;
-				}
-			}
-			return myNewObj;
-		};
-
-		var path1arr = path1.split('.'),
-			lastNodeName = path1arr[path1arr.length - 1],
-			treeNode1 = TsParser.getTreeNode(path1),
-			treeNode2 = TsParser.getTreeNode(path2);
-
-		if (treeNode1.parent !== null) {
-			treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2);
-		} else {
-			TsParser.tsTree.childNodes[lastNodeName] = this.clone(treeNode2);
-		}
-	};
-
-	return TsParser;
-});
\ No newline at end of file
+  'jquery', 'TYPO3/CMS/T3editor/Addon/Hint/TsRef'
+], function($) {
+  /**
+   *
+   * @type {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}}
+   * @exports TYPO3/CMS/T3editor/Addon/Hint/TsParser
+   */
+  var TsParser = {
+    typeId: null,
+    properties: null,
+    typeTree: [],
+    doc: null,
+    tsRef: null,
+    extTsObjTree: [],
+    tsTree: null
+  };
+
+  /**
+   *
+   * @param {Object} tsRef
+   * @param {Object} extTsObjTree
+   * @returns {{typeId: null, properties: null, typeTree: Array, doc: null, tsRef: null, extTsObjTree: Array, tsTree: null}}
+   */
+  TsParser.init = function(tsRef, extTsObjTree) {
+    TsParser.tsRef = tsRef;
+    TsParser.extTsObjTree = extTsObjTree;
+    TsParser.tsTree = new TsParser.treeNode('_L_');
+
+    return TsParser;
+  };
+
+  /**
+   *
+   * @param {String} nodeName
+   */
+  TsParser.treeNode = function(nodeName) {
+    this.name = nodeName;
+    this.childNodes = [];
+    this.extPath = '';
+    this.value = '';
+    this.isExternal = false;
+
+    /**
+     * Returns local properties and the properties of the external templates
+     *
+     * @return {Array}
+     */
+    this.getChildNodes = function() {
+      var node = this.getExtNode();
+      if (node !== null && typeof node.c === 'object') {
+        for (key in node.c) {
+          var tn = new TsParser.treeNode(key, this.tsObjTree);
+          tn.global = true;
+          tn.value = (node.c[key].v) ? node.c[key].v : "";
+          tn.isExternal = true;
+          this.childNodes[key] = tn;
+        }
+      }
+      return this.childNodes;
+    };
+
+    /**
+     * Returns the value of a node
+     *
+     * @returns {String}
+     */
+    this.getValue = function() {
+      if (this.value) {
+        return this.value;
+      }
+      var node = this.getExtNode();
+      if (node && node.v) {
+        return node.v;
+      }
+
+      var type = this.getNodeTypeFromTsref();
+      if (type) {
+        return type;
+      }
+      return '';
+    };
+
+    /**
+     * This method will try to resolve the properties recursively from right
+     * to left. If the node's value property is not set, it will look for the
+     * value of its parent node, and if there is a matching childProperty
+     * (according to the TSREF) it will return the childProperties value.
+     * If there is no value in the parent node it will go one step further
+     * and look into the parent node of the parent node,...
+     *
+     * @return {String}
+     */
+    this.getNodeTypeFromTsref = function() {
+      var path = this.extPath.split('.'),
+        lastSeg = path.pop();
+
+      // attention: there will be recursive calls if necessary
+      var parentValue = this.parent.getValue();
+      if (parentValue) {
+        if (TsParser.tsRef.typeHasProperty(parentValue, lastSeg)) {
+          var type = TsParser.tsRef.getType(parentValue);
+          return type.properties[lastSeg].value;
+        }
+      }
+      return '';
+    };
+
+    /**
+     * Will look in the external ts-tree (static templates, templates on other pages)
+     * if there is a value or childproperties assigned to the current node.
+     * The method uses the extPath of the current node to navigate to the corresponding
+     * node in the external tree
+     *
+     * @return {Object}
+     */
+    this.getExtNode = function() {
+      var extTree = TsParser.extTsObjTree,
+        path,
+        pathSeg;
+
+      if (this.extPath === '') {
+        return extTree;
+      }
+      path = this.extPath.split('.');
+
+      for (var i = 0; i < path.length; i++) {
+        pathSeg = path[i];
+        if (typeof extTree.c === 'undefined' || typeof extTree.c[pathSeg] === 'undefined') {
+          return null;
+        }
+        extTree = extTree.c[pathSeg];
+      }
+      return extTree;
+    };
+  };
+
+  /**
+   * Check if there is an operator in the line and return it
+   * if there is none, return -1
+   *
+   * @return {(String|Number)}
+   */
+  TsParser.getOperator = function(line) {
+    var operators = [':=', '=<', '<', '>', '='];
+    for (var i = 0; i < operators.length; i++) {
+      var op = operators[i];
+      if (line.indexOf(op) !== -1) {
+        // check if there is some HTML in this line (simple check, however it's the only difference between a reference operator and HTML)
+        // we do this check only in case of the two operators "=<" and "<" since the delete operator would trigger our "HTML-finder"
+        if ((op === '=<' || op === '<') && line.indexOf('>') > -1) {
+          // if there is a ">" in the line suppose there's some HTML
+          return '=';
+        }
+        return op;
+      }
+    }
+    return -1;
+  };
+
+  /**
+   * Build the TypoScript object tree
+   */
+  TsParser.buildTsObjTree = function(codemirror) {
+    TsParser.tsTree = new TsParser.treeNode('');
+    TsParser.tsTree.value = 'TLO';
+
+    function Stack() {
+    }
+
+    Stack.prototype = [];
+    Stack.prototype.lastElementEquals = function(str) {
+      return this.length > 0 && this[this.length - 1] === str;
+    };
+
+    Stack.prototype.popIfLastElementEquals = function(str) {
+      if (this.lastElementEquals(str)) {
+        this.pop();
+        return true;
+      }
+      return false;
+    };
+
+    var currentLine = 0,
+      cursorPosition = codemirror.getCursor(),
+      line = '',
+      stack = new Stack(),
+      prefixes = [],
+      ignoreLine = false,
+      insideCondition = false;
+
+    while (currentLine <= cursorPosition.line) {
+      line = '';
+      var tokens = codemirror.getLineTokens(currentLine);
+      for (var i = 0; i <= tokens.length; ++i) {
+        if (i < tokens.length && tokens[i].string.length > 0) {
+          var tokenValue = tokens[i].string;
+
+          if (tokenValue[0] === '#') {
+            stack.push('#');
+          } else if (tokenValue === '(') {
+            stack.push('(');
+          } else if (tokenValue[0] === '/' && tokenValue[1] === '*') {
+            stack.push('/*');
+          } else if (tokenValue === '{') {
+            // TODO: ignore whole block if wrong whitespaces in this line
+            if (TsParser.getOperator(line) === -1) {
+              stack.push('{');
+              prefixes.push($.trim(line));
+              ignoreLine = true;
+            }
+          }
+          // TODO: conditions
+          // if condition starts -> ignore everything until end of condition
+          if (tokenValue.search(/^\s*\[.*\]/) !== -1
+            && line.search(/\S/) === -1
+            && tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) === -1
+            && !stack.lastElementEquals('#')
+            && !stack.lastElementEquals('/*')
+            && !stack.lastElementEquals('{')
+            && !stack.lastElementEquals('(')
+          ) {
+            insideCondition = true;
+            ignoreLine = true;
+          }
+
+          // if end of condition reached
+          if (line.search(/\S/) === -1
+            && !stack.lastElementEquals('#')
+            && !stack.lastElementEquals('/*')
+            && !stack.lastElementEquals('(')
+            && (
+              (tokenValue.search(/^\s*\[(global|end|GLOBAL|END)\]/) !== -1
+                && !stack.lastElementEquals('{'))
+              || (tokenValue.search(/^\s*\[(global|GLOBAL)\]/) !== -1)
+            )
+          ) {
+            insideCondition = false;
+            ignoreLine = true;
+          }
+
+          if (tokenValue === ')') {
+            stack.popIfLastElementEquals('(');
+          }
+          if (tokenValue[0] === '*' && tokenValue[1] === '/') {
+            stack.popIfLastElementEquals('/*');
+            ignoreLine = true;
+          }
+          if (tokenValue === '}') {
+            //no characters except whitespace allowed before closing bracket
+            var trimmedLine = line.replace(/\s/g, '');
+            if (trimmedLine === '') {
+              stack.popIfLastElementEquals('{');
+              if (prefixes.length > 0) {
+                prefixes.pop();
+              }
+              ignoreLine = true;
+            }
+          }
+          if (!stack.lastElementEquals('#')) {
+            line += tokenValue;
+          }
+        } else {
+          // ignore comments, ...
+          if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine && !insideCondition) {
+            line = $.trim(line);
+            // check if there is any operator in this line
+            var op = TsParser.getOperator(line);
+            if (op !== -1) {
+              // figure out the position of the operator
+              var pos = line.indexOf(op);
+              // the target objectpath should be left to the operator
+              var path = line.substring(0, pos);
+              // if we are in between curly brackets: add prefixes to object path
+              if (prefixes.length > 0) {
+                path = prefixes.join('.') + '.' + path;
+              }
+              // the type or value should be right to the operator
+              var str = line.substring(pos + op.length, line.length);
+              path = $.trim(path);
+              str = $.trim(str);
+              switch (op) { // set a value or create a new object
+                case '=':
+                  //ignore if path is empty or contains whitespace
+                  if (path.search(/\s/g) === -1 && path.length > 0) {
+                    TsParser.setTreeNodeValue(path, str);
+                  }
+                  break;
+                case '=<': // reference to another object in the tree
+                  // resolve relative path
+                  if (prefixes.length > 0 && str.substr(0, 1) === '.') {
+                    str = prefixes.join('.') + str;
+                  }
+                  //ignore if either path or str is empty or contains whitespace
+                  if (path.search(/\s/g) === -1
+                    && path.length > 0
+                    && str.search(/\s/g) === -1
+                    && str.length > 0
+                  ) {
+                    TsParser.setReference(path, str);
+                  }
+                  break;
+                case '<': // copy from another object in the tree
+                  // resolve relative path
+                  if (prefixes.length > 0 && str.substr(0, 1) === '.') {
+                    str = prefixes.join('.') + str;
+                  }
+                  //ignore if either path or str is empty or contains whitespace
+                  if (path.search(/\s/g) === -1
+                    && path.length > 0
+                    && str.search(/\s/g) === -1
+                    && str.length > 0
+                  ) {
+                    TsParser.setCopy(path, str);
+                  }
+                  break;
+                case '>': // delete object value and properties
+                  TsParser.deleteTreeNodeValue(path);
+                  break;
+                case ':=': // function operator
+                  // TODO: function-operator
+                  break;
+              }
+            }
+          }
+          stack.popIfLastElementEquals('#');
+          ignoreLine = false;
+        }
+      }
+      currentLine++;
+    }
+    // when node at cursorPos is reached:
+    // save currentLine, currentTsTreeNode and filter if necessary
+    // if there is a reference or copy operator ('<' or '=<')
+    // return the treeNode of the path right to the operator,
+    // else try to build a path from the whole line
+    if (!stack.lastElementEquals('/*') && !stack.lastElementEquals('(') && !ignoreLine) {
+      var i = line.indexOf('<');
+
+      if (i !== -1) {
+        var path = line.substring(i + 1, line.length);
+        path = $.trim(path);
+        if (prefixes.length > 0 && path.substr(0, 1) === '.') {
+          path = prefixes.join('.') + path;
+        }
+      } else {
+        var path = line;
+        if (prefixes.length > 0) {
+          path = prefixes.join('.') + '.' + path;
+          path = path.replace(/\s/g, '');
+        }
+      }
+      var lastDot = path.lastIndexOf('.');
+      path = path.substring(0, lastDot);
+    }
+    return TsParser.getTreeNode(path);
+  };
+
+  /**
+   * Iterates through the object tree, and creates treenodes
+   * along the path, if necessary
+   *
+   * @param {String} path
+   * @returns {Object}
+   */
+  TsParser.getTreeNode = function(path) {
+    path = $.trim(path);
+    if (path.length === 0) {
+      return TsParser.tsTree;
+    }
+    var aPath = path.split('.');
+
+    var subTree = TsParser.tsTree.childNodes,
+      pathSeg,
+      parent = TsParser.tsTree;
+
+    // step through the path from left to right
+    for (var i = 0; i < aPath.length; i++) {
+      pathSeg = aPath[i];
+
+      // if there isn't already a treenode
+      if (typeof subTree[pathSeg] === 'undefined' || typeof subTree[pathSeg].childNodes === 'undefined') { // if this subpath is not defined in the code
+        // create a new treenode
+        subTree[pathSeg] = new TsParser.treeNode(pathSeg);
+        subTree[pathSeg].parent = parent;
+        // the extPath has to be set, so the TreeNode can retrieve the respecting node in the external templates
+        var extPath = parent.extPath;
+        if (extPath) {
+          extPath += '.';
+        }
+        extPath += pathSeg;
+        subTree[pathSeg].extPath = extPath;
+      }
+      if (i === aPath.length - 1) {
+        return subTree[pathSeg];
+      }
+      parent = subTree[pathSeg];
+      subTree = subTree[pathSeg].childNodes;
+    }
+  };
+
+  /**
+   * Navigates to the respecting treenode,
+   * create nodes in the path, if necessary, and sets the value
+   *
+   * @param {String} path
+   * @param {String} value
+   */
+  TsParser.setTreeNodeValue = function(path, value) {
+    var treeNode = TsParser.getTreeNode(path);
+    // if we are inside a GIFBUILDER Object
+    if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "TEXT") {
+      value = 'GB_TEXT';
+    }
+    if (treeNode.parent !== null && (treeNode.parent.value === "GIFBUILDER" || treeNode.parent.getValue() === "GMENU_itemState") && value === "IMAGE") {
+      value = 'GB_IMAGE';
+    }
+
+    // just override if it is a real objecttype
+    if (TsParser.tsRef.isType(value)) {
+      treeNode.value = value;
+    }
+  };
+
+  /**
+   * Navigates to the respecting treenode,
+   * creates nodes if necessary, empties the value and childNodes-Array
+   *
+   * @param {String} path
+   */
+  TsParser.deleteTreeNodeValue = function(path) {
+    var treeNode = TsParser.getTreeNode(path);
+    // currently the node is not deleted really, it's just not displayed cause value == null
+    // deleting it would be a cleaner solution
+    treeNode.value = null;
+    treeNode.childNodes = {};
+  };
+
+  /**
+   * Copies a reference of the treeNode specified by path2
+   * to the location specified by path1
+   *
+   * @param {String} path1
+   * @param {String} path2
+   */
+  TsParser.setReference = function(path1, path2) {
+    var path1arr = path1.split('.'),
+      lastNodeName = path1arr[path1arr.length - 1],
+      treeNode1 = TsParser.getTreeNode(path1),
+      treeNode2 = TsParser.getTreeNode(path2);
+
+    if (treeNode1.parent !== null) {
+      treeNode1.parent.childNodes[lastNodeName] = treeNode2;
+    } else {
+      TsParser.tsTree.childNodes[lastNodeName] = treeNode2;
+    }
+  };
+
+  /**
+   * copies a treeNode specified by path2
+   * to the location specified by path1
+   *
+   * @param {String} path1
+   * @param {String} path2
+   */
+  TsParser.setCopy = function(path1, path2) {
+    this.clone = function(myObj) {
+      if (typeof myObj !== 'object') {
+        return myObj;
+      }
+
+      var myNewObj = {};
+      for (var i in myObj) {
+        // disable recursive cloning for parent object -> copy by reference
+        if (i !== 'parent') {
+          if (typeof myObj[i] === 'object') {
+            myNewObj[i] = this.clone(myObj[i]);
+          } else {
+            myNewObj[i] = myObj[i];
+          }
+        } else {
+          myNewObj.parent = myObj.parent;
+        }
+      }
+      return myNewObj;
+    };
+
+    var path1arr = path1.split('.'),
+      lastNodeName = path1arr[path1arr.length - 1],
+      treeNode1 = TsParser.getTreeNode(path1),
+      treeNode2 = TsParser.getTreeNode(path2);
+
+    if (treeNode1.parent !== null) {
+      treeNode1.parent.childNodes[lastNodeName] = this.clone(treeNode2);
+    } else {
+      TsParser.tsTree.childNodes[lastNodeName] = this.clone(treeNode2);
+    }
+  };
+
+  return TsParser;
+});
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js
index 7a0343b8782d..37c2392161e0 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TsRef.js
@@ -15,162 +15,162 @@
  * Module: TYPO3/CMS/T3editor/CodeCompletion/TsRef
  * Contains the TsCodeCompletion class
  */
-define(['jquery'], function ($) {
-	/**
-	 *
-	 * @type {{typeId: null, properties: null, typeTree: Array, doc: null}}
-	 * @exports TYPO3/CMS/T3editor/CodeCompletion/TsRef
-	 */
-	var TsRef = {
-		typeId: null,
-		properties: null,
-		typeTree: [],
-		doc: null
-	};
+define(['jquery'], function($) {
+  /**
+   *
+   * @type {{typeId: null, properties: null, typeTree: Array, doc: null}}
+   * @exports TYPO3/CMS/T3editor/CodeCompletion/TsRef
+   */
+  var TsRef = {
+    typeId: null,
+    properties: null,
+    typeTree: [],
+    doc: null
+  };
 
-	/**
-	 * Prototypes a TS reference type object
-	 *
-	 * @param {String} typeId
-	 */
-	TsRef.TsRefType = function(typeId) {
-		this.typeId = typeId;
-		this.properties = [];
-	};
+  /**
+   * Prototypes a TS reference type object
+   *
+   * @param {String} typeId
+   */
+  TsRef.TsRefType = function(typeId) {
+    this.typeId = typeId;
+    this.properties = [];
+  };
 
-	/**
-	 * Prototypes a TS reference property object
-	 *
-	 * @param {String} parentType
-	 * @param {String} name
-	 * @param {String} value
-	 * @constructor
-	 */
-	TsRef.TsRefProperty = function(parentType, name, value) {
-		this.parentType = parentType;
-		this.name = name;
-		this.value = value;
-	};
+  /**
+   * Prototypes a TS reference property object
+   *
+   * @param {String} parentType
+   * @param {String} name
+   * @param {String} value
+   * @constructor
+   */
+  TsRef.TsRefProperty = function(parentType, name, value) {
+    this.parentType = parentType;
+    this.name = name;
+    this.value = value;
+  };
 
-	/**
-	 * Load available TypoScript reference
-	 */
-	TsRef.loadTsrefAsync = function() {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['t3editor_tsref'],
-			success: function(response) {
-				TsRef.doc = response;
-				TsRef.buildTree();
-			}
-		});
-	};
+  /**
+   * Load available TypoScript reference
+   */
+  TsRef.loadTsrefAsync = function() {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['t3editor_tsref'],
+      success: function(response) {
+        TsRef.doc = response;
+        TsRef.buildTree();
+      }
+    });
+  };
 
-	/**
-	 * Build the TypoScript reference tree
-	 */
-	TsRef.buildTree = function() {
-		for (var typeId in TsRef.doc) {
-			var arr = TsRef.doc[typeId];
-			TsRef.typeTree[typeId] = new TsRef.TsRefType(typeId);
+  /**
+   * Build the TypoScript reference tree
+   */
+  TsRef.buildTree = function() {
+    for (var typeId in TsRef.doc) {
+      var arr = TsRef.doc[typeId];
+      TsRef.typeTree[typeId] = new TsRef.TsRefType(typeId);
 
-			if (typeof arr['extends'] !== 'undefined') {
-				TsRef.typeTree[typeId]['extends'] = arr['extends'];
-			}
-			for (var propName in arr.properties) {
-				var propType = arr.properties[propName].type;
-				TsRef.typeTree[typeId].properties[propName] = new TsRef.TsRefProperty(typeId, propName, propType);
-			}
-		}
-		for (var typeId in TsRef.typeTree) {
-			if (typeof TsRef.typeTree[typeId]['extends'] !== 'undefined') {
-				TsRef.addPropertiesToType(TsRef.typeTree[typeId], TsRef.typeTree[typeId]['extends'], 100);
-			}
-		}
-	};
+      if (typeof arr['extends'] !== 'undefined') {
+        TsRef.typeTree[typeId]['extends'] = arr['extends'];
+      }
+      for (var propName in arr.properties) {
+        var propType = arr.properties[propName].type;
+        TsRef.typeTree[typeId].properties[propName] = new TsRef.TsRefProperty(typeId, propName, propType);
+      }
+    }
+    for (var typeId in TsRef.typeTree) {
+      if (typeof TsRef.typeTree[typeId]['extends'] !== 'undefined') {
+        TsRef.addPropertiesToType(TsRef.typeTree[typeId], TsRef.typeTree[typeId]['extends'], 100);
+      }
+    }
+  };
 
-	/**
-	 * Adds properties to TypoScript types
-	 *
-	 * @param {String} addToType
-	 * @param {String} addFromTypeNames
-	 * @param {Number} maxRecDepth
-	 */
-	TsRef.addPropertiesToType = function(addToType, addFromTypeNames, maxRecDepth) {
-		if (maxRecDepth < 0) {
-			throw "Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!";
-			return;
-		}
-		var exts = addFromTypeNames.split(','),
-			i;
-		for (i = 0; i < exts.length; i++) {
-			// "Type 'array' which is used to extend 'undefined', was not found in the TSREF!"
-			if (typeof TsRef.typeTree[exts[i]] !== 'undefined') {
-				if (typeof TsRef.typeTree[exts[i]]['extends'] !== 'undefined') {
-					TsRef.addPropertiesToType(TsRef.typeTree[exts[i]], TsRef.typeTree[exts[i]]['extends'], maxRecDepth-1);
-				}
-				var properties = TsRef.typeTree[exts[i]].properties;
-				for (var propName in properties) {
-					// only add this property if it was not already added by a supertype (subtypes override supertypes)
-					if (typeof addToType.properties[propName] === 'undefined') {
-						addToType.properties[propName] = properties[propName];
-					}
-				}
-			}
-		}
-	};
+  /**
+   * Adds properties to TypoScript types
+   *
+   * @param {String} addToType
+   * @param {String} addFromTypeNames
+   * @param {Number} maxRecDepth
+   */
+  TsRef.addPropertiesToType = function(addToType, addFromTypeNames, maxRecDepth) {
+    if (maxRecDepth < 0) {
+      throw "Maximum recursion depth exceeded while trying to resolve the extends in the TSREF!";
+      return;
+    }
+    var exts = addFromTypeNames.split(','),
+      i;
+    for (i = 0; i < exts.length; i++) {
+      // "Type 'array' which is used to extend 'undefined', was not found in the TSREF!"
+      if (typeof TsRef.typeTree[exts[i]] !== 'undefined') {
+        if (typeof TsRef.typeTree[exts[i]]['extends'] !== 'undefined') {
+          TsRef.addPropertiesToType(TsRef.typeTree[exts[i]], TsRef.typeTree[exts[i]]['extends'], maxRecDepth - 1);
+        }
+        var properties = TsRef.typeTree[exts[i]].properties;
+        for (var propName in properties) {
+          // only add this property if it was not already added by a supertype (subtypes override supertypes)
+          if (typeof addToType.properties[propName] === 'undefined') {
+            addToType.properties[propName] = properties[propName];
+          }
+        }
+      }
+    }
+  };
 
-	/**
-	 * Get properties from given TypoScript type id
-	 *
-	 * @param {String} tId
-	 * @return {Array}
-	 */
-	TsRef.getPropertiesFromTypeId = function(tId) {
-		if (typeof TsRef.typeTree[tId] !== 'undefined') {
-			// clone is needed to assure that nothing of the tsref is overwritten by user setup
-			TsRef.typeTree[tId].properties.clone = function() {
-				var result = [];
-				for (key in this) {
-					result[key] = new TsRef.TsRefProperty(this[key].parentType, this[key].name, this[key].value);
-				}
-				return result;
-			}
-			return TsRef.typeTree[tId].properties;
-		}
-		return [];
-	};
+  /**
+   * Get properties from given TypoScript type id
+   *
+   * @param {String} tId
+   * @return {Array}
+   */
+  TsRef.getPropertiesFromTypeId = function(tId) {
+    if (typeof TsRef.typeTree[tId] !== 'undefined') {
+      // clone is needed to assure that nothing of the tsref is overwritten by user setup
+      TsRef.typeTree[tId].properties.clone = function() {
+        var result = [];
+        for (key in this) {
+          result[key] = new TsRef.TsRefProperty(this[key].parentType, this[key].name, this[key].value);
+        }
+        return result;
+      }
+      return TsRef.typeTree[tId].properties;
+    }
+    return [];
+  };
 
-	/**
-	 * Check if a property of a type exists
-	 *
-	 * @param {String} typeId
-	 * @param {String} propertyName
-	 * @return {Boolean}
-	 */
-	TsRef.typeHasProperty = function(typeId, propertyName) {
-		return typeof TsRef.typeTree[typeId] !== 'undefined'
-			&& typeof TsRef.typeTree[typeId].properties[propertyName] !== 'undefined';
-	};
+  /**
+   * Check if a property of a type exists
+   *
+   * @param {String} typeId
+   * @param {String} propertyName
+   * @return {Boolean}
+   */
+  TsRef.typeHasProperty = function(typeId, propertyName) {
+    return typeof TsRef.typeTree[typeId] !== 'undefined'
+      && typeof TsRef.typeTree[typeId].properties[propertyName] !== 'undefined';
+  };
 
-	/**
-	 * Get the type
-	 *
-	 * @param {String} typeId
-	 * @return {Object}
-	 */
-	TsRef.getType = function(typeId) {
-		return TsRef.typeTree[typeId];
-	};
+  /**
+   * Get the type
+   *
+   * @param {String} typeId
+   * @return {Object}
+   */
+  TsRef.getType = function(typeId) {
+    return TsRef.typeTree[typeId];
+  };
 
-	/**
-	 * Check if type exists in the type tree
-	 *
-	 * @param {String} typeId
-	 * @return {Boolean}
-	 */
-	TsRef.isType = function(typeId) {
-		return typeof TsRef.typeTree[typeId] !== 'undefined';
-	};
+  /**
+   * Check if type exists in the type tree
+   *
+   * @param {String} typeId
+   * @return {Boolean}
+   */
+  TsRef.isType = function(typeId) {
+    return typeof TsRef.typeTree[typeId] !== 'undefined';
+  };
 
-	return TsRef;
-});
\ No newline at end of file
+  return TsRef;
+});
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js
index 29019c4137ea..9085650bcac5 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Addon/Hint/TypoScriptHint.js
@@ -1,105 +1,105 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: http://codemirror.net/LICENSE
 
-(function (mod) {
-	if (typeof exports === 'object' && typeof module === 'object') // CommonJS
-		mod(require('cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'));
-	else if (typeof define === 'function' && define.amd) // AMD
-		define(['cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'], mod);
-	else // Plain browser env
-		mod(CodeMirror);
-})(function (CodeMirror, TsCodeCompletion) {
-	var Pos = CodeMirror.Pos;
-
-	CodeMirror.registerHelper('hint', 'typoscript', function (editor, options) {
-		return typoScriptHint(editor, function (e, cur) {
-			return e.getTokenAt(cur);
-		}, options);
-	});
-
-	function arrayContains(arr, item) {
-		if (!Array.prototype.indexOf) {
-			var i = arr.length;
-			while (i--) {
-				if (arr[i] === item) {
-					return true;
-				}
-			}
-			return false;
-		}
-		return arr.indexOf(item) !== -1;
-	}
-
-	function typoScriptHint(editor, getToken) {
-		var keywords = TsCodeCompletion.refreshCodeCompletion(editor);
-
-		// Find the token at the cursor
-		var cur = editor.getCursor(),
-			token = getToken(editor, cur);
-
-		if (/\b(?:string|comment)\b/.test(token.type) && tokenIsSubStringOfKeywords(token, keywords)) {
-			return;
-		}
-		token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
-
-		// If it's not a 'word-style' token, ignore the token.
-		if (!/^[\w$_]*$/.test(token.string)) {
-			token = {
-				start: cur.ch, end: cur.ch, string: '', state: token.state,
-				type: token.string === '.' ? 'property' : null
-			};
-		} else if (token.end > cur.ch) {
-			token.end = cur.ch;
-			token.string = token.string.slice(0, cur.ch - token.start);
-		}
-
-		var completions = {
-			list: getCompletions(token, keywords),
-			from: Pos(cur.line, token.start),
-			to: Pos(cur.line, token.end)
-		};
-
-		CodeMirror.on(completions, 'pick', function() {
-			TsCodeCompletion.resetCompList();
-		});
-
-		return completions;
-	}
-
-	function tokenIsSubStringOfKeywords(token, keywords) {
-		var tokenLength = token.string.length;
-		for (var i = 0; i < keywords.length; ++i) {
-			if (token.string === keywords[i].substr(tokenLength)) {
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	function getCompletions(token, keywords) {
-		var found = [],
-			start = token.string;
-
-		function maybeAdd(str) {
-			if (str.lastIndexOf(start, 0) === 0 && !arrayContains(found, str)) {
-				found.push(str);
-			}
-		}
-
-		// If not, just look in the global object and any local scope
-		// (reading into JS mode internals to get at the local and global variables)
-		for (var v = token.state.localVars; v; v = v.next) {
-			maybeAdd(v.name);
-		}
-		for (var v = token.state.globalVars; v; v = v.next) {
-			maybeAdd(v.name);
-		}
-		for (var i = 0, e = keywords.length; i < e; ++i) {
-			maybeAdd(keywords[i]);
-		}
-		found.sort();
-
-		return found;
-	}
+(function(mod) {
+  if (typeof exports === 'object' && typeof module === 'object') // CommonJS
+    mod(require('cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'));
+  else if (typeof define === 'function' && define.amd) // AMD
+    define(['cm/lib/codemirror', 'TYPO3/CMS/T3editor/Addon/Hint/TsCodeCompletion'], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror, TsCodeCompletion) {
+  var Pos = CodeMirror.Pos;
+
+  CodeMirror.registerHelper('hint', 'typoscript', function(editor, options) {
+    return typoScriptHint(editor, function(e, cur) {
+      return e.getTokenAt(cur);
+    }, options);
+  });
+
+  function arrayContains(arr, item) {
+    if (!Array.prototype.indexOf) {
+      var i = arr.length;
+      while (i--) {
+        if (arr[i] === item) {
+          return true;
+        }
+      }
+      return false;
+    }
+    return arr.indexOf(item) !== -1;
+  }
+
+  function typoScriptHint(editor, getToken) {
+    var keywords = TsCodeCompletion.refreshCodeCompletion(editor);
+
+    // Find the token at the cursor
+    var cur = editor.getCursor(),
+      token = getToken(editor, cur);
+
+    if (/\b(?:string|comment)\b/.test(token.type) && tokenIsSubStringOfKeywords(token, keywords)) {
+      return;
+    }
+    token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
+
+    // If it's not a 'word-style' token, ignore the token.
+    if (!/^[\w$_]*$/.test(token.string)) {
+      token = {
+        start: cur.ch, end: cur.ch, string: '', state: token.state,
+        type: token.string === '.' ? 'property' : null
+      };
+    } else if (token.end > cur.ch) {
+      token.end = cur.ch;
+      token.string = token.string.slice(0, cur.ch - token.start);
+    }
+
+    var completions = {
+      list: getCompletions(token, keywords),
+      from: Pos(cur.line, token.start),
+      to: Pos(cur.line, token.end)
+    };
+
+    CodeMirror.on(completions, 'pick', function() {
+      TsCodeCompletion.resetCompList();
+    });
+
+    return completions;
+  }
+
+  function tokenIsSubStringOfKeywords(token, keywords) {
+    var tokenLength = token.string.length;
+    for (var i = 0; i < keywords.length; ++i) {
+      if (token.string === keywords[i].substr(tokenLength)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  function getCompletions(token, keywords) {
+    var found = [],
+      start = token.string;
+
+    function maybeAdd(str) {
+      if (str.lastIndexOf(start, 0) === 0 && !arrayContains(found, str)) {
+        found.push(str);
+      }
+    }
+
+    // If not, just look in the global object and any local scope
+    // (reading into JS mode internals to get at the local and global variables)
+    for (var v = token.state.localVars; v; v = v.next) {
+      maybeAdd(v.name);
+    }
+    for (var v = token.state.globalVars; v; v = v.next) {
+      maybeAdd(v.name);
+    }
+    for (var i = 0, e = keywords.length; i < e; ++i) {
+      maybeAdd(keywords[i]);
+    }
+    found.sort();
+
+    return found;
+  }
 });
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js
index 261b1247c8bc..15f0c72e8fb9 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/Mode/typoscript/typoscript.js
@@ -1,1825 +1,1825 @@
-(function (mod) {
-	if (typeof exports === "object" && typeof module === "object") // CommonJS
-		mod(require("cm/lib/codemirror"));
-	else if (typeof define === "function" && define.amd) // AMD
-		define(["cm/lib/codemirror"], mod);
-	else // Plain browser env
-		mod(CodeMirror);
-})(function (CodeMirror) {
-	"use strict";
-
-	function expressionAllowed(stream, state, backUp) {
-		return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
-			(state.lastType === "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
-	}
-
-	CodeMirror.defineMode("typoscript", function (config, parserConfig) {
-		var indentUnit = config.indentUnit;
-		var statementIndent = parserConfig.statementIndent;
-		var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
-
-		// Tokenizer
-
-		var keywords = function () {
-			function kw(type) {
-				return {type: type, style: "keyword"};
-			}
-
-			var A = kw("keyword a"), B = kw("keyword b");
-
-			return {
-				'_CSS_DEFAULT_STYLE': kw('_CSS_DEFAULT_STYLE'),
-				'_DEFAULT_PI_VARS': kw('_DEFAULT_PI_VARS'),
-				'_GIFBUILDER': kw('_GIFBUILDER'),
-				'_LOCAL_LANG': kw('_LOCAL_LANG'),
-				'_offset': kw('_offset'),
-				'absRefPrefix': kw('absRefPrefix'),
-				'accessibility': kw('accessibility'),
-				'accessKey': kw('accessKey'),
-				'ACT': B,
-				'ACTIFSUB': B,
-				'ACTIFSUBRO': kw('ACTIFSUBRO'),
-				'ACTRO': B,
-				'addAttributes': kw('addAttributes'),
-				'addExtUrlsAndShortCuts': kw('addExtUrlsAndShortCuts'),
-				'addItems': kw('addItems'),
-				'additionalHeaders': kw('additionalHeaders'),
-				'additionalParams': kw('additionalParams'),
-				'addParams': kw('addParams'),
-				'addQueryString': kw('addQueryString'),
-				'adjustItemsH': kw('adjustItemsH'),
-				'adjustSubItemsH': kw('adjustSubItemsH'),
-				'admPanel': A,
-				'after': kw('after'),
-				'afterImg': kw('afterImg'),
-				'afterImgLink': kw('afterImgLink'),
-				'afterImgTagParams': kw('afterImgTagParams'),
-				'afterROImg': kw('afterROImg'),
-				'afterWrap': kw('afterWrap'),
-				'age': kw('age'),
-				'alertPopups': kw('alertPopups'),
-				'align': kw('align'),
-				'all': B,
-				'allow': kw('allow'),
-				'allowCaching': kw('allowCaching'),
-				'allowedAttribs': kw('allowedAttribs'),
-				'allowedClasses': kw('allowedClasses'),
-				'allowedCols': kw('allowedCols'),
-				'allowedNewTables': kw('allowedNewTables'),
-				'allowTags': kw('allowTags'),
-				'allStdWrap': kw('allStdWrap'),
-				'allWrap': kw('allWrap'),
-				'alt_print': A,
-				'alternativeSortingField': kw('alternativeSortingField'),
-				'alternativeTempPath': kw('alternativeTempPath'),
-				'altIcons': kw('altIcons'),
-				'altImgResource': kw('altImgResource'),
-				'altLabels': kw('altLabels'),
-				'altTarget': kw('altTarget'),
-				'altText': kw('altText'),
-				'altUrl': kw('altUrl'),
-				'altUrl_noDefaultParams': kw('altUrl_noDefaultParams'),
-				'altWrap': kw('altWrap'),
-				'always': kw('always'),
-				'alwaysActivePIDlist': kw('alwaysActivePIDlist'),
-				'alwaysLink': kw('alwaysLink'),
-				'andWhere': kw('andWhere'),
-				'angle': kw('angle'),
-				'antiAlias': kw('antiAlias'),
-				'append': kw('append'),
-				'applyTotalH': kw('applyTotalH'),
-				'applyTotalW': kw('applyTotalW'),
-				'archive': kw('archive'),
-				'ascii': B,
-				'ATagAfterWrap': kw('ATagAfterWrap'),
-				'ATagBeforeWrap': kw('ATagBeforeWrap'),
-				'ATagParams': kw('ATagParams'),
-				'ATagTitle': kw('ATagTitle'),
-				'atLeast': B,
-				'atMost': B,
-				'attribute': kw('attribute'),
-				'auth': A,
-				'autoLevels': kw('autoLevels'),
-				'autonumber': kw('autonumber'),
-				'backColor': kw('backColor'),
-				'background': kw('background'),
-				'baseURL': kw('baseURL'),
-				'BE': B,
-				'be_groups': B,
-				'be_users': B,
-				'before': kw('before'),
-				'beforeImg': kw('beforeImg'),
-				'beforeImgLink': kw('beforeImgLink'),
-				'beforeImgTagParams': kw('beforeImgTagParams'),
-				'beforeROImg': kw('beforeROImg'),
-				'beforeWrap': kw('beforeWrap'),
-				'begin': kw('begin'),
-				'bgCol': kw('bgCol'),
-				'bgImg': kw('bgImg'),
-				'blur': kw('blur'),
-				'bm': kw('bm'),
-				'bodyTag': kw('bodyTag'),
-				'bodyTagAdd': kw('bodyTagAdd'),
-				'bodyTagCObject': kw('bodyTagCObject'),
-				'bodytext': kw('bodytext'),
-				'border': kw('border'),
-				'borderCol': kw('borderCol'),
-				'borderThick': kw('borderThick'),
-				'bottomBackColor': kw('bottomBackColor'),
-				'bottomContent': kw('bottomContent'),
-				'bottomHeight': kw('bottomHeight'),
-				'bottomImg': kw('bottomImg'),
-				'bottomImg_mask': kw('bottomImg_mask'),
-				'BOX': B,
-				'br': kw('br'),
-				'browse': B,
-				'browser': A,
-				'brTag': kw('brTag'),
-				'bullet': kw('bullet'),
-				'bulletlist': kw('bulletlist'),
-				'bullets': B,
-				'bytes': kw('bytes'),
-				'cache': A,
-				'cache_clearAtMidnight': kw('cache_clearAtMidnight'),
-				'cache_period': kw('cache_period'),
-				'caption': kw('caption'),
-				'caption_stdWrap': kw('caption_stdWrap'),
-				'captionHeader': kw('captionHeader'),
-				'captionSplit': kw('captionSplit'),
-				'CARRAY': kw('CARRAY'),
-				'CASE': kw('CASE'),
-				'case': kw('case'),
-				'casesensitiveComp': kw('casesensitiveComp'),
-				'cellpadding': kw('cellpadding'),
-				'cellspacing': kw('cellspacing'),
-				'char': kw('char'),
-				'charcoal': kw('charcoal'),
-				'charMapConfig': kw('charMapConfig'),
-				'CHECK': A,
-				'check': kw('check'),
-				'class': kw('class'),
-				'classesAnchor': kw('classesAnchor'),
-				'classesCharacter': kw('classesCharacter'),
-				'classesImage': kw('classesImage'),
-				'classesParagraph': kw('classesParagraph'),
-				'clear': kw('clear'),
-				'clearCache': kw('clearCache'),
-				'clearCache_disable': kw('clearCache_disable'),
-				'clearCache_pageGrandParent': kw('clearCache_pageGrandParent'),
-				'clearCache_pageSiblingChildren': kw('clearCache_pageSiblingChildren'),
-				'clearCacheCmd': kw('clearCacheCmd'),
-				'clearCacheLevels': kw('clearCacheLevels'),
-				'clearCacheOfPages': kw('clearCacheOfPages'),
-				'clickTitleMode': kw('clickTitleMode'),
-				'clipboardNumberPads': kw('clipboardNumberPads'),
-				'cMargins': kw('cMargins'),
-				'COA': kw('COA'),
-				'COA_INT': kw('COA_INT'),
-				'cObj': A,
-				'COBJ_ARRAY': kw('COBJ_ARRAY'),
-				'cObject': A,
-				'cObjNum': kw('cObjNum'),
-				'collapse': kw('collapse'),
-				'collections': kw('collections'),
-				'color': kw('color'),
-				'color1': kw('color1'),
-				'color2': kw('color2'),
-				'color3': kw('color3'),
-				'color4': kw('color4'),
-				'colors': kw('colors'),
-				'colour': kw('colour'),
-				'colPos_list': kw('colPos_list'),
-				'colRelations': kw('colRelations'),
-				'cols': kw('cols'),
-				'colSpace': kw('colSpace'),
-				'COMMENT': A,
-				'comment_auto': kw('comment_auto'),
-				'commentWrap': kw('commentWrap'),
-				'compX': kw('compX'),
-				'compY': kw('compY'),
-				'conf': kw('conf'),
-				'CONFIG': kw('CONFIG'),
-				'config': A,
-				'CONSTANTS': kw('CONSTANTS'),
-				'constants': kw('constants'),
-				'CONTENT': kw('CONTENT'),
-				'content': A,
-				'content_from_pid_allowOutsideDomain': kw('content_from_pid_allowOutsideDomain'),
-				'contextMenu': kw('contextMenu'),
-				'copy': A,
-				'copyLevels': kw('copyLevels'),
-				'count_HMENU_MENUOBJ': kw('count_HMENU_MENUOBJ'),
-				'count_menuItems': kw('count_menuItems'),
-				'count_MENUOBJ': kw('count_MENUOBJ'),
-				'create': kw('create'),
-				'createFoldersInEB': kw('createFoldersInEB'),
-				'crop': kw('crop'),
-				'csConv': kw('csConv'),
-				'CSS_inlineStyle': A,
-				'CType': kw('CType'),
-				'CUR': B,
-				'CURIFSUB': B,
-				'CURIFSUBRO': B,
-				'current': kw('current'),
-				'CURRO': B,
-				'curUid': kw('curUid'),
-				'cut': A,
-				'cWidth': kw('cWidth'),
-				'data': kw('data'),
-				'dataArray': A,
-				'dataWrap': kw('dataWrap'),
-				'date': kw('date'),
-				'date_stdWrap': kw('date_stdWrap'),
-				'datePrefix': kw('datePrefix'),
-				'dayofmonth': A,
-				'dayofweek': A,
-				'DB': kw('DB'),
-				'db_list': A,
-				'debug': kw('debug'),
-				'debugData': kw('debugData'),
-				'debugFunc': kw('debugFunc'),
-				'debugItemConf': kw('debugItemConf'),
-				'debugRenumberedObject': kw('debugRenumberedObject'),
-				'default': B,
-				'defaultAlign': kw('defaultAlign'),
-				'defaultCmd': kw('defaultCmd'),
-				'defaultFileUploads': kw('defaultFileUploads'),
-				'defaultHeaderType': kw('defaultHeaderType'),
-				'defaultOutput': kw('defaultOutput'),
-				'defaults': kw('defaults'),
-				'defaultType': kw('defaultType'),
-				'delete': kw('delete'),
-				'denyTags': kw('denyTags'),
-				'depth': kw('depth'),
-				'DESC': kw('DESC'),
-				'description': B,
-				'dimensions': kw('dimensions'),
-				'direction': kw('direction'),
-				'directory': B,
-				'directReturn': B,
-				'disableAdvanced': kw('disableAdvanced'),
-				'disableAllHeaderCode': kw('disableAllHeaderCode'),
-				'disableAltText': kw('disableAltText'),
-				'disableBodyTag': kw('disableBodyTag'),
-				'disableCacheSelector': kw('disableCacheSelector'),
-				'disableCharsetHeader': kw('disableCharsetHeader'),
-				'disabled': kw('disabled'),
-				'disableDelete': kw('disableDelete'),
-				'disableDocSelector': kw('disableDocSelector'),
-				'disableHideAtCopy': kw('disableHideAtCopy'),
-				'disableItems': kw('disableItems'),
-				'disableNewContentElementWizard': kw('disableNewContentElementWizard'),
-				'disableNoMatchingValueElement': kw('disableNoMatchingValueElement'),
-				'disablePageExternalUrl': kw('disablePageExternalUrl'),
-				'disablePrefixComment': kw('disablePrefixComment'),
-				'disablePrependAtCopy': kw('disablePrependAtCopy'),
-				'disableSearchBox': kw('disableSearchBox'),
-				'disableSingleTableView': kw('disableSingleTableView'),
-				'displayContent': kw('displayContent'),
-				'displayFieldIcons': kw('displayFieldIcons'),
-				'displayIcons': kw('displayIcons'),
-				'displayMessages': kw('displayMessages'),
-				'displayRecord': kw('displayRecord'),
-				'displayTimes': kw('displayTimes'),
-				'distributeX': kw('distributeX'),
-				'distributeY': kw('distributeY'),
-				'div': B,
-				'DIV': kw('DIV'),
-				'doctype': kw('doctype'),
-				'doctypeSwitch': kw('doctypeSwitch'),
-				'DOCUMENT_BODY': kw('DOCUMENT_BODY'),
-				'doktype': kw('doktype'),
-				'doNotLinkIt': kw('doNotLinkIt'),
-				'doNotShowLink': kw('doNotShowLink'),
-				'doNotStripHTML': kw('doNotStripHTML'),
-				'dontCheckPid': kw('dontCheckPid'),
-				'dontLinkIfSubmenu': kw('dontLinkIfSubmenu'),
-				'dontWrapInTable': kw('dontWrapInTable'),
-				'doubleBrTag': kw('doubleBrTag'),
-				'dWorkArea': kw('dWorkArea'),
-				'dynCSS': A,
-				'edge': kw('edge'),
-				'edit': A,
-				'edit_access': A,
-				'edit_docModuleUpload': kw('edit_docModuleUpload'),
-				'edit_pageheader': A,
-				'edit_RTE': kw('edit_RTE'),
-				'editFieldsAtATime': kw('editFieldsAtATime'),
-				'editFormsOnPage': kw('editFormsOnPage'),
-				'editIcons': kw('editIcons'),
-				'editNoPopup': kw('editNoPopup'),
-				'EDITPANEL': kw('EDITPANEL'),
-				'editPanel': kw('editPanel'),
-				'EFFECT': kw('EFFECT'),
-				'elements': kw('elements'),
-				'else': B,
-				'email': B,
-				'emailMeAtLogin': kw('emailMeAtLogin'),
-				'emailMess': kw('emailMess'),
-				'emboss': kw('emboss'),
-				'enable': kw('enable'),
-				'encapsLines': kw('encapsLines'),
-				'encapsLinesStdWrap': kw('encapsLinesStdWrap'),
-				'encapsTagList': kw('encapsTagList'),
-				'end': B,
-				'entryLevel': kw('entryLevel'),
-				'equalH': kw('equalH'),
-				'equals': B,
-				'everybody': kw('everybody'),
-				'excludeDoktypes': kw('excludeDoktypes'),
-				'excludeUidList': kw('excludeUidList'),
-				'expAll': kw('expAll'),
-				'expand': kw('expand'),
-				'explode': kw('explode'),
-				'ext': kw('ext'),
-				'external': B,
-				'externalBlocks': kw('externalBlocks'),
-				'extTarget': kw('extTarget'),
-				'face': kw('face'),
-				'false': B,
-				'FE': B,
-				'fe_adminLib': kw('fe_adminLib'),
-				'fe_groups': B,
-				'fe_users': B,
-				'feadmin': B,
-				'field': kw('field'),
-				'fieldName': kw('fieldName'),
-				'fieldOrder': kw('fieldOrder'),
-				'fieldRequired': kw('fieldRequired'),
-				'fields': kw('fields'),
-				'fieldWrap': kw('fieldWrap'),
-				'FILE': kw('FILE'),
-				'file': kw('file'),
-				'file1': kw('file1'),
-				'file2': kw('file2'),
-				'file3': kw('file3'),
-				'file4': kw('file4'),
-				'file5': kw('file5'),
-				'filelink': kw('filelink'),
-				'filelist': kw('filelist'),
-				'FILES': kw('FILES'),
-				'files': kw('files'),
-				'firstLabel': kw('firstLabel'),
-				'firstLabelGeneral': kw('firstLabelGeneral'),
-				'fixAttrib': kw('fixAttrib'),
-				'flip': kw('flip'),
-				'flop': kw('flop'),
-				'FLUIDTEMPLATE': kw('FLUIDTEMPLATE'),
-				'folder': A,
-				'folders': kw('folders'),
-				'folderTree': A,
-				'foldoutMenu': A,
-				'fontColor': kw('fontColor'),
-				'fontFile': kw('fontFile'),
-				'fontOffset': kw('fontOffset'),
-				'fontSize': kw('fontSize'),
-				'fontSizeMultiplicator': kw('fontSizeMultiplicator'),
-				'forceDisplayFieldIcons': kw('forceDisplayFieldIcons'),
-				'forceDisplayIcons': kw('forceDisplayIcons'),
-				'forceTemplateParsing': kw('forceTemplateParsing'),
-				'forceTypeValue': kw('forceTypeValue'),
-				'FORM': kw('FORM'),
-				'format': kw('format'),
-				'ftu': kw('ftu'),
-				'function': kw('function'),
-				'Functions': A,
-				'gamma': kw('gamma'),
-				'gapBgCol': kw('gapBgCol'),
-				'gapLineCol': kw('gapLineCol'),
-				'gapLineThickness': kw('gapLineThickness'),
-				'gapWidth': kw('gapWidth'),
-				'get': kw('get'),
-				'getBorder': kw('getBorder'),
-				'getLeft': kw('getLeft'),
-				'getRight': kw('getRight'),
-				'GIFBUILDER': kw('GIFBUILDER'),
-				'global': kw('global'),
-				'globalNesting': kw('globalNesting'),
-				'globalString': kw('globalString'),
-				'globalVar': kw('globalVar'),
-				'GMENU': kw('GMENU'),
-				'GP': kw('GP'),
-				'gray': kw('gray'),
-				'group': kw('group'),
-				'groupBy': kw('groupBy'),
-				'groupid': kw('groupid'),
-				'header': B,
-				'header_layout': kw('header_layout'),
-				'headerComment': kw('headerComment'),
-				'headerData': kw('headerData'),
-				'headerSpace': kw('headerSpace'),
-				'headTag': kw('headTag'),
-				'height': kw('height'),
-				'helpText': kw('helpText'),
-				'hidden': kw('hidden'),
-				'hiddenFields': kw('hiddenFields'),
-				'hide': kw('hide'),
-				'hideButCreateMap': kw('hideButCreateMap'),
-				'hidePStyleItems': kw('hidePStyleItems'),
-				'hideRecords': kw('hideRecords'),
-				'highColor': kw('highColor'),
-				'history': kw('history'),
-				'HMENU': kw('HMENU'),
-				'hostname': A,
-				'hour': A,
-				'HTML': kw('HTML'),
-				'html': B,
-				'HTMLparser': kw('HTMLparser'),
-				'HTMLparser_tags': kw('HTMLparser_tags'),
-				'htmlSpecialChars': kw('htmlSpecialChars'),
-				'htmlTag_dir': kw('htmlTag_dir'),
-				'htmlTag_langKey': kw('htmlTag_langKey'),
-				'htmlTag_setParams': kw('htmlTag_setParams'),
-				'http': kw('http'),
-				'icon': kw('icon'),
-				'icon_image_ext_list': kw('icon_image_ext_list'),
-				'icon_link': kw('icon_link'),
-				'iconCObject': kw('iconCObject'),
-				'id': B,
-				'IENV': kw('IENV'),
-				'if': B,
-				'ifEmpty': B,
-				'IFSUB': B,
-				'IFSUBRO': B,
-				'IMAGE': kw('IMAGE'),
-				'image': B,
-				'image_frames': kw('image_frames'),
-				'imageLinkWrap': kw('imageLinkWrap'),
-				'imagePath': kw('imagePath'),
-				'images': kw('images'),
-				'imageWrapIfAny': kw('imageWrapIfAny'),
-				'IMG_RESOURCE': kw('IMG_RESOURCE'),
-				'imgList': A,
-				'imgMap': kw('imgMap'),
-				'imgMapExtras': kw('imgMapExtras'),
-				'imgMax': kw('imgMax'),
-				'IMGMENU': kw('IMGMENU'),
-				'IMGMENUITEM': kw('IMGMENUITEM'),
-				'imgNameNotRandom': kw('imgNameNotRandom'),
-				'imgNamePrefix': kw('imgNamePrefix'),
-				'imgObjNum': kw('imgObjNum'),
-				'imgParams': kw('imgParams'),
-				'imgPath': kw('imgPath'),
-				'imgResource': A,
-				'imgStart': kw('imgStart'),
-				'IMGTEXT': kw('IMGTEXT'),
-				'imgText': A,
-				'import': kw('import'),
-				'inBranch': B,
-				'inc': kw('inc'),
-				'INCLUDE_TYPOSCRIPT': kw('INCLUDE_TYPOSCRIPT'),
-				'includeCSS': kw('includeCSS'),
-				'includeLibrary': kw('includeLibrary'),
-				'includeNotInMenu': kw('includeNotInMenu'),
-				'index': kw('index'),
-				'index_descrLgd': kw('index_descrLgd'),
-				'index_enable': kw('index_enable'),
-				'index_externals': kw('index_externals'),
-				'info': A,
-				'inlineStyle2TempFile': kw('inlineStyle2TempFile'),
-				'innerStdWrap': kw('innerStdWrap'),
-				'innerStdWrap_all': kw('innerStdWrap_all'),
-				'innerWrap': kw('innerWrap'),
-				'innerWrap2': kw('innerWrap2'),
-				'input': kw('input'),
-				'inputLevels': kw('inputLevels'),
-				'insertData': kw('insertData'),
-				'intensity': kw('intensity'),
-				'intTarget': kw('intTarget'),
-				'intval': kw('intval'),
-				'invert': kw('invert'),
-				'IP': A,
-				'IProcFunc': kw('IProcFunc'),
-				'isFalse': B,
-				'isGreaterThan': B,
-				'isInList': B,
-				'isLessThan': B,
-				'isPositive': B,
-				'isTrue': B,
-				'itemArrayProcFunc': kw('itemArrayProcFunc'),
-				'itemH': kw('itemH'),
-				'items': kw('items'),
-				'itemsProcFunc': kw('itemsProcFunc'),
-				'iterations': kw('iterations'),
-				'join': kw('join'),
-				'JSwindow': A,
-				'JSWindow': kw('JSWindow'),
-				'JSwindow_params': kw('JSwindow_params'),
-				'keep': kw('keep'),
-				'keepEntries': kw('keepEntries'),
-				'keepNonMatchedTags': kw('keepNonMatchedTags'),
-				'key': kw('key'),
-				'keyword3': B,
-				'LABEL': A,
-				'label': kw('label'),
-				'labelStdWrap': kw('labelStdWrap'),
-				'labelWrap': kw('labelWrap'),
-				'lang': kw('lang'),
-				'language': B,
-				'language_alt': kw('language_alt'),
-				'languageField': kw('languageField'),
-				'layout': A,
-				'left': kw('left'),
-				'leftjoin': kw('leftjoin'),
-				'levels': kw('levels'),
-				'leveltitle': B,
-				'leveluid': kw('leveluid'),
-				'lib': A,
-				'limit': kw('limit'),
-				'line': kw('line'),
-				'lineColor': kw('lineColor'),
-				'lineThickness': kw('lineThickness'),
-				'linkPrefix': kw('linkPrefix'),
-				'linkTitleToSelf': kw('linkTitleToSelf'),
-				'linkVars': kw('linkVars'),
-				'linkWrap': kw('linkWrap'),
-				'list': B,
-				'listNum': kw('listNum'),
-				'listOnlyInSingleTableView': kw('listOnlyInSingleTableView'),
-				'LIT': kw('LIT'),
-				'lm': kw('lm'),
-				'LOAD_REGISTER': kw('LOAD_REGISTER'),
-				'locale_all': kw('locale_all'),
-				'localNesting': kw('localNesting'),
-				'locationData': kw('locationData'),
-				'lockToIP': kw('lockToIP'),
-				'login': B,
-				'loginUser': A,
-				'longdescURL': kw('longdescURL'),
-				'lowColor': kw('lowColor'),
-				'lower': kw('lower'),
-				'LR': kw('LR'),
-				'mailform': B,
-				'mailto': kw('mailto'),
-				'main': kw('main'),
-				'makelinks': kw('makelinks'),
-				'markerWrap': kw('markerWrap'),
-				'marks': A,
-				'mask': kw('mask'),
-				'max': kw('max'),
-				'maxAge': kw('maxAge'),
-				'maxChars': kw('maxChars'),
-				'maxH': kw('maxH'),
-				'maxHeight': kw('maxHeight'),
-				'maxItems': kw('maxItems'),
-				'maxW': kw('maxW'),
-				'maxWidth': kw('maxWidth'),
-				'maxWInText': kw('maxWInText'),
-				'media': B,
-				'menu': B,
-				'menu_type': kw('menu_type'),
-				'menuHeight': kw('menuHeight'),
-				'menuName': kw('menuName'),
-				'menuOffset': kw('menuOffset'),
-				'menuWidth': kw('menuWidth'),
-				'message_page_is_being_generated': kw('message_page_is_being_generated'),
-				'message_preview': kw('message_preview'),
-				'META': kw('META'),
-				'meta': kw('meta'),
-				'metaCharset': kw('metaCharset'),
-				'method': kw('method'),
-				'min': kw('min'),
-				'minH': kw('minH'),
-				'minItems': kw('minItems'),
-				'minute': A,
-				'minW': kw('minW'),
-				'mod': B,
-				'mode': kw('mode'),
-				'module': A,
-				'month': A,
-				'move_wizard': A,
-				'MP_defaults': kw('MP_defaults'),
-				'MP_disableTypolinkClosestMPvalue': kw('MP_disableTypolinkClosestMPvalue'),
-				'MP_mapRootPoints': kw('MP_mapRootPoints'),
-				'MULTIMEDIA': kw('MULTIMEDIA'),
-				'multimedia': B,
-				'name': kw('name'),
-				'negate': B,
-				'nesting': kw('nesting'),
-				'neverHideAtCopy': kw('neverHideAtCopy'),
-				'new': A,
-				'NEW': B,
-				'new_wizard': A,
-				'newPageWiz': kw('newPageWiz'),
-				'newRecordFromTable': kw('newRecordFromTable'),
-				'newWindow': kw('newWindow'),
-				'newWizards': kw('newWizards'),
-				'next': kw('next'),
-				'niceText': kw('niceText'),
-				'nicetext': kw('nicetext'),
-				'NO': B,
-				'no_cache': kw('no_cache'),
-				'no_search': kw('no_search'),
-				'noAttrib': kw('noAttrib'),
-				'noCache': kw('noCache'),
-				'noCreateRecordsLink': kw('noCreateRecordsLink'),
-				'noLink': kw('noLink'),
-				'noMatchingValue_label': kw('noMatchingValue_label'),
-				'nonCachedSubst': kw('nonCachedSubst'),
-				'none': B,
-				'nonTypoTagStdWrap': kw('nonTypoTagStdWrap'),
-				'nonTypoTagUserFunc': kw('nonTypoTagUserFunc'),
-				'nonWrappedTag': kw('nonWrappedTag'),
-				'noOrderBy': kw('noOrderBy'),
-				'noPageTitle': kw('noPageTitle'),
-				'noResultObj': A,
-				'noThumbsInEB': kw('noThumbsInEB'),
-				'noThumbsInRTEimageSelect': kw('noThumbsInRTEimageSelect'),
-				'noTrimWrap': kw('noTrimWrap'),
-				'noValueInsert': kw('noValueInsert'),
-				'numRows': A,
-				'obj': kw('obj'),
-				'offset': kw('offset'),
-				'onlineWorkspaceInfo': kw('onlineWorkspaceInfo'),
-				'onlyCurrentPid': kw('onlyCurrentPid'),
-				'opacity': kw('opacity'),
-				'options': A,
-				'orderBy': kw('orderBy'),
-				'outerWrap': kw('outerWrap'),
-				'outline': kw('outline'),
-				'outputLevels': kw('outputLevels'),
-				'override': kw('override'),
-				'overrideAttribs': kw('overrideAttribs'),
-				'overrideId': kw('overrideId'),
-				'overridePageModule': kw('overridePageModule'),
-				'overrideWithExtension': kw('overrideWithExtension'),
-				'PAGE': kw('PAGE'),
-				'page': A,
-				'PAGE_TARGET': kw('PAGE_TARGET'),
-				'PAGE_TSCONFIG_ID': kw('PAGE_TSCONFIG_ID'),
-				'PAGE_TSCONFIG_IDLIST': kw('PAGE_TSCONFIG_IDLIST'),
-				'PAGE_TSCONFIG_STR': kw('PAGE_TSCONFIG_STR'),
-				'pageFrameObj': kw('pageFrameObj'),
-				'pages': B,
-				'pages_language_overlay': B,
-				'pageTitleFirst': kw('pageTitleFirst'),
-				'pageTree': A,
-				'parameter': kw('parameter'),
-				'params': kw('params'),
-				'parseFunc': kw('parseFunc'),
-				'parseFunc_RTE': B,
-				'parser': kw('parser'),
-				'password': kw('password'),
-				'paste': A,
-				'path': kw('path'),
-				'permissions': kw('permissions'),
-				'perms': A,
-				'pid': B,
-				'pid_list': kw('pid_list'),
-				'pidInList': kw('pidInList'),
-				'PIDinRootline': A,
-				'PIDupinRootline': A,
-				'pixelSpaceFontSizeRef': kw('pixelSpaceFontSizeRef'),
-				'plaintextLib': kw('plaintextLib'),
-				'plainTextStdWrap': kw('plainTextStdWrap'),
-				'plugin': A,
-				'postCObject': kw('postCObject'),
-				'postLineBlanks': kw('postLineBlanks'),
-				'postLineChar': kw('postLineChar'),
-				'postLineLen': kw('postLineLen'),
-				'postUserFunc': kw('postUserFunc'),
-				'postUserFuncInt': kw('postUserFuncInt'),
-				'preBlanks': kw('preBlanks'),
-				'preCObject': kw('preCObject'),
-				'prefix': kw('prefix'),
-				'prefixComment': kw('prefixComment'),
-				'prefixLocalAnchors': kw('prefixLocalAnchors'),
-				'prefixRelPathWith': kw('prefixRelPathWith'),
-				'preIfEmptyListNum': kw('preIfEmptyListNum'),
-				'preLineBlanks': kw('preLineBlanks'),
-				'preLineChar': kw('preLineChar'),
-				'preLineLen': kw('preLineLen'),
-				'prepend': kw('prepend'),
-				'preserveEntities': kw('preserveEntities'),
-				'preUserFunc': kw('preUserFunc'),
-				'prev': kw('prev'),
-				'preview': A,
-				'previewBorder': kw('previewBorder'),
-				'prevnextToSection': kw('prevnextToSection'),
-				'prioriCalc': kw('prioriCalc'),
-				'proc': kw('proc'),
-				'processor_allowUpscaling': kw('processor_allowUpscaling'),
-				'properties': kw('properties'),
-				'protect': kw('protect'),
-				'protectLvar': kw('protectLvar'),
-				'publish': A,
-				'publish_levels': kw('publish_levels'),
-				'QEisDefault': kw('QEisDefault'),
-				'quality': kw('quality'),
-				'RADIO': A,
-				'radio': kw('radio'),
-				'radioWrap': kw('radioWrap'),
-				'range': kw('range'),
-				'rawUrlEncode': kw('rawUrlEncode'),
-				'recipient': kw('recipient'),
-				'RECORDS': kw('RECORDS'),
-				'recursive': kw('recursive'),
-				'recursiveDelete': kw('recursiveDelete'),
-				'redirect': kw('redirect'),
-				'redirectToURL': kw('redirectToURL'),
-				'reduceColors': kw('reduceColors'),
-				'references': kw('references'),
-				'register': kw('register'),
-				'relPathPrefix': kw('relPathPrefix'),
-				'remap': kw('remap'),
-				'remapTag': kw('remapTag'),
-				'REMOTE_ADDR': kw('REMOTE_ADDR'),
-				'removeDefaultJS': kw('removeDefaultJS'),
-				'removeIfEquals': kw('removeIfEquals'),
-				'removeIfFalse': kw('removeIfFalse'),
-				'removeItems': kw('removeItems'),
-				'removeObjectsOfDummy': kw('removeObjectsOfDummy'),
-				'removePrependedNumbers': kw('removePrependedNumbers'),
-				'removeTags': kw('removeTags'),
-				'removeWrapping': kw('removeWrapping'),
-				'renderObj': A,
-				'renderWrap': kw('renderWrap'),
-				'REQ': A,
-				'required': B,
-				'reset': kw('reset'),
-				'resources': kw('resources'),
-				'RESTORE_REGISTER': kw('RESTORE_REGISTER'),
-				'resultObj': kw('resultObj'),
-				'returnLast': kw('returnLast'),
-				'returnUrl': kw('returnUrl'),
-				'rightjoin': kw('rightjoin'),
-				'rm': kw('rm'),
-				'rmTagIfNoAttrib': kw('rmTagIfNoAttrib'),
-				'RO': B,
-				'rootline': B,
-				'rotate': kw('rotate'),
-				'rows': kw('rows'),
-				'rowSpace': kw('rowSpace'),
-				'RTE': A,
-				'RTE_compliant': A,
-				'RTEfullScreenWidth': kw('RTEfullScreenWidth'),
-				'rules': kw('rules'),
-				'sample': kw('sample'),
-				'saveClipboard': kw('saveClipboard'),
-				'saveDocNew': kw('saveDocNew'),
-				'script': B,
-				'search': B,
-				'SEARCHRESULT': kw('SEARCHRESULT'),
-				'secondRow': kw('secondRow'),
-				'section': kw('section'),
-				'sectionIndex': kw('sectionIndex'),
-				'select': A,
-				'selectFields': kw('selectFields'),
-				'separator': kw('separator'),
-				'set': kw('set'),
-				'setContentToCurrent': kw('setContentToCurrent'),
-				'setCurrent': kw('setCurrent'),
-				'setfixed': kw('setfixed'),
-				'setOnly': kw('setOnly'),
-				'setup': A,
-				'shadow': kw('shadow'),
-				'SHARED': kw('SHARED'),
-				'sharpen': kw('sharpen'),
-				'shear': kw('shear'),
-				'short': kw('short'),
-				'shortcut': B,
-				'shortcutFrame': kw('shortcutFrame'),
-				'shortcutIcon': kw('shortcutIcon'),
-				'show': kw('show'),
-				'showAccessRestrictedPages': kw('showAccessRestrictedPages'),
-				'showActive': kw('showActive'),
-				'showClipControlPanelsDespiteOfCMlayers': kw('showClipControlPanelsDespiteOfCMlayers'),
-				'showFirst': kw('showFirst'),
-				'showHiddenPages': kw('showHiddenPages'),
-				'showHiddenRecords': kw('showHiddenRecords'),
-				'showHistory': kw('showHistory'),
-				'showPageIdWithTitle': kw('showPageIdWithTitle'),
-				'showTagFreeClasses': kw('showTagFreeClasses'),
-				'simulateDate': kw('simulateDate'),
-				'simulateUserGroup': kw('simulateUserGroup'),
-				'singlePid': kw('singlePid'),
-				'site_author': kw('site_author'),
-				'site_reserved': kw('site_reserved'),
-				'sitemap': B,
-				'sitetitle': kw('sitetitle'),
-				'siteUrl': kw('siteUrl'),
-				'size': kw('size'),
-				'solarize': kw('solarize'),
-				'sorting': kw('sorting'),
-				'source': kw('source'),
-				'space': kw('space'),
-				'spaceAfter': kw('spaceAfter'),
-				'spaceBefore': kw('spaceBefore'),
-				'spaceBelowAbove': kw('spaceBelowAbove'),
-				'spaceLeft': kw('spaceLeft'),
-				'spaceRight': kw('spaceRight'),
-				'spacing': kw('spacing'),
-				'spamProtectEmailAddresses': kw('spamProtectEmailAddresses'),
-				'spamProtectEmailAddresses_atSubst': kw('spamProtectEmailAddresses_atSubst'),
-				'spamProtectEmailAddresses_lastDotSubst': kw('spamProtectEmailAddresses_lastDotSubst'),
-				'SPC': B,
-				'special': kw('special'),
-				'split': A,
-				'splitChar': kw('splitChar'),
-				'splitRendering': kw('splitRendering'),
-				'src': kw('src'),
-				'stdheader': kw('stdheader'),
-				'stdWrap': A,
-				'stdWrap2': kw('stdWrap2'),
-				'strftime': kw('strftime'),
-				'stripHtml': kw('stripHtml'),
-				'styles': kw('styles'),
-				'submenuObjSuffixes': kw('submenuObjSuffixes'),
-				'subMenuOffset': kw('subMenuOffset'),
-				'submit': kw('submit'),
-				'subparts': A,
-				'subst_elementUid': kw('subst_elementUid'),
-				'substMarksSeparately': kw('substMarksSeparately'),
-				'substring': kw('substring'),
-				'swirl': kw('swirl'),
-				'sword': kw('sword'),
-				'sword_noMixedCase': kw('sword_noMixedCase'),
-				'SWORD_PARAMS': kw('SWORD_PARAMS'),
-				'sword_standAlone': kw('sword_standAlone'),
-				'sys_dmail': B,
-				'sys_domain': B,
-				'sys_filemounts': B,
-				'sys_language_mode': kw('sys_language_mode'),
-				'sys_language_overlay': kw('sys_language_overlay'),
-				'sys_language_uid': kw('sys_language_uid'),
-				'sys_note': B,
-				'sys_template': B,
-				'system': A,
-				'table': B,
-				'tableCellColor': kw('tableCellColor'),
-				'tableParams': kw('tableParams'),
-				'tables': kw('tables'),
-				'tableStdWrap': kw('tableStdWrap'),
-				'tableWidth': kw('tableWidth'),
-				'tags': kw('tags'),
-				'target': kw('target'),
-				'TCAdefaults': kw('TCAdefaults'),
-				'TCEFORM': kw('TCEFORM'),
-				'TCEMAIN': kw('TCEMAIN'),
-				'TDparams': kw('TDparams'),
-				'temp': A,
-				'TEMPLATE': kw('TEMPLATE'),
-				'template': A,
-				'templateContent': kw('templateContent'),
-				'templateFile': kw('templateFile'),
-				'TEXT': kw('TEXT'),
-				'text': B,
-				'textarea': kw('textarea'),
-				'textMargin': kw('textMargin'),
-				'textMargin_outOfText': kw('textMargin_outOfText'),
-				'textMaxLength': kw('textMaxLength'),
-				'textObjNum': kw('textObjNum'),
-				'textpic': B,
-				'textPos': kw('textPos'),
-				'thickness': kw('thickness'),
-				'this': B,
-				'thumbnailsByDefault': kw('thumbnailsByDefault'),
-				'tile': kw('tile'),
-				'time_stdWrap': kw('time_stdWrap'),
-				'tipafriendLib': kw('tipafriendLib'),
-				'title': kw('title'),
-				'titleLen': kw('titleLen'),
-				'titleTagFunction': kw('titleTagFunction'),
-				'titleText': kw('titleText'),
-				'tm': kw('tm'),
-				'TMENU': kw('TMENU'),
-				'TMENUITEM': kw('TMENUITEM'),
-				'token': kw('token'),
-				'top': B,
-				'totalWidth': kw('totalWidth'),
-				'transparentBackground': kw('transparentBackground'),
-				'transparentColor': kw('transparentColor'),
-				'treeLevel': A,
-				'trim': kw('trim'),
-				'true': B,
-				'tsdebug': A,
-				'tsdebug_tree': kw('tsdebug_tree'),
-				'TSFE': kw('TSFE'),
-				'type': kw('type'),
-				'typeNum': kw('typeNum'),
-				'types': kw('types'),
-				'typolink': A,
-				'uid': B,
-				'uidInList': kw('uidInList'),
-				'uniqueGlobal': B,
-				'uniqueLocal': B,
-				'unset': kw('unset'),
-				'unsetEmpty': B,
-				'updated': B,
-				'uploadFieldsInTopOfEB': kw('uploadFieldsInTopOfEB'),
-				'uploads': B,
-				'upper': kw('upper'),
-				'url': A,
-				'us': B,
-				'useCacheHash': kw('useCacheHash'),
-				'useLargestItemX': kw('useLargestItemX'),
-				'useLargestItemY': kw('useLargestItemY'),
-				'USER': kw('USER'),
-				'user': kw('user'),
-				'USER_INT': kw('USER_INT'),
-				'user_task': B,
-				'useragent': A,
-				'USERDEF1': B,
-				'USERDEF1RO': B,
-				'USERDEF2': B,
-				'USERDEF2RO': B,
-				'userdefined': kw('userdefined'),
-				'userFunc': A,
-				'userfunction': kw('userfunction'),
-				'usergroup': B,
-				'userid': kw('userid'),
-				'USERNAME_substToken': kw('USERNAME_substToken'),
-				'userProc': kw('userProc'),
-				'USR': B,
-				'USRRO': B,
-				'value': kw('value'),
-				'valueArray': kw('valueArray'),
-				'version': A,
-				'view': A,
-				'wave': kw('wave'),
-				'web_func': B,
-				'web_info': B,
-				'web_layout': B,
-				'web_list': B,
-				'web_ts': kw('web_ts'),
-				'where': kw('where'),
-				'width': kw('width'),
-				'wiz': kw('wiz'),
-				'wordSpacing': kw('wordSpacing'),
-				'workArea': kw('workArea'),
-				'workOnSubpart': A,
-				'wrap': kw('wrap'),
-				'wrap1': kw('wrap1'),
-				'wrap2': kw('wrap2'),
-				'wrap3': kw('wrap3'),
-				'wrapAfterTags': kw('wrapAfterTags'),
-				'wrapAlign': kw('wrapAlign'),
-				'wrapFieldName': kw('wrapFieldName'),
-				'wrapItemAndSub': kw('wrapItemAndSub'),
-				'wrapNonWrappedLines': kw('wrapNonWrappedLines'),
-				'wraps': kw('wraps'),
-				'xhtml_cleaning': kw('xhtml_cleaning'),
-				'xhtml_strict': B,
-				'xhtml_trans': B,
-				'xmlprologue': kw('xmlprologue'),
-				'XY': B
-			};
-		}();
-
-		var isOperatorChar = /[\+\-\*\&\%\/=<>!\?]/;
-		var inValue = false;
-
-		function readRegexp(stream) {
-			var escaped = false, next, inSet = false;
-			while ((next = stream.next()) != null) {
-				if (!escaped) {
-					if (next === "/" && !inSet) return;
-					if (next === "[") inSet = true;
-					else if (inSet && next === "]") inSet = false;
-				}
-				escaped = !escaped && next === "\\";
-			}
-		}
-
-		// Used as scratch variables to communicate multiple values without
-		// consing up tons of objects.
-		var type, content;
-
-		function ret(tp, style, cont) {
-			type = tp;
-			content = cont;
-			return style;
-		}
-
-		function tokenBase(stream, state) {
-			var ch = stream.next();
-			if (ch === "\n") {
-				inValue = false;
-			}
-
-			if (ch === "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
-				return ret("number", "number");
-			}
-			if (ch === "." && stream.match("..")) {
-				return ret("spread", "meta");
-			}
-			if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
-				return ret(ch);
-			}
-			if ((ch === '<' || ch === '>' || ch === '.' || (ch === '=' && stream.peek() !== '<'))) {
-				inValue = true;
-				return ret(ch, 'operator')
-			}
-			if (!inValue && /[\[\]\(\),;\:\.\<\>\=]/.test(ch)) {
-				return ret(ch, 'operator')
-			}
-			if (ch === "0" && stream.eat(/x/i)) {
-				stream.eatWhile(/[\da-f]/i);
-				return ret("number", "number");
-			}
-			if (ch === "0" && stream.eat(/o/i)) {
-				stream.eatWhile(/[0-7]/i);
-				return ret("number", "number");
-			}
-			if (ch === "0" && stream.eat(/b/i)) {
-				stream.eatWhile(/[01]/i);
-				return ret("number", "number");
-			}
-			if (/\d/.test(ch)) {
-				stream.match(/^\d*(?:\.\d+)?(?:[eE][+\-]?\d+)?/);
-				return ret("number", "number");
-			}
-			if (ch === "/") {
-				if (stream.eat("*")) {
-					state.tokenize = tokenComment;
-					return tokenComment(stream, state);
-				}
-				if (stream.eat("/")) {
-					stream.skipToEnd();
-					return ret("comment", "comment");
-				}
-				if (expressionAllowed(stream, state, 1)) {
-					readRegexp(stream);
-					stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
-					return ret("regexp", "string-2");
-				}
-
-				stream.eatWhile(isOperatorChar);
-				return ret("operator", "operator", stream.current());
-			}
-			if (ch === "`") {
-				state.tokenize = tokenQuasi;
-				return tokenQuasi(stream, state);
-			}
-			if (ch === "#") {
-				stream.skipToEnd();
-				return ret("comment", "comment");
-			}
-			if (isOperatorChar.test(ch)) {
-				if (ch !== ">" || !state.lexical || state.lexical.type !== ">") {
-					stream.eatWhile(isOperatorChar);
-				}
-				return ret("operator", "operator", stream.current());
-			}
-			if (wordRE.test(ch)) {
-				stream.eatWhile(wordRE);
-				var word = stream.current();
-				if (keywords.propertyIsEnumerable(word)) {
-					var kw = keywords[word];
-					return ret(kw.type, kw.style, word);
-				}
-				if (word === "async" && stream.match(/^\s*[\(\w]/, false)) {
-					return ret("async", "keyword", word);
-				}
-				if (inValue) {
-					return ret('string', 'string', word);
-				}
-				return ret("variable", "other", word);
-			}
-		}
-
-		function tokenString(quote) {
-			return function (stream, state) {
-				var escaped = false, next;
-				while ((next = stream.next()) != null) {
-					if (next == quote && !escaped) break;
-					escaped = !escaped && next === "\\";
-				}
-				if (!escaped) state.tokenize = tokenBase;
-				return ret("string", "string");
-			};
-		}
-
-		function tokenComment(stream, state) {
-			var maybeEnd = false, ch;
-			while (ch = stream.next()) {
-				if (ch === "/" && maybeEnd) {
-					state.tokenize = tokenBase;
-					break;
-				}
-				maybeEnd = (ch === "*");
-			}
-			return ret("comment", "comment");
-		}
-
-		function tokenQuasi(stream, state) {
-			var escaped = false, next;
-			while ((next = stream.next()) != null) {
-				if (!escaped && (next === "`" || next === "$" && stream.eat("{"))) {
-					state.tokenize = tokenBase;
-					break;
-				}
-				escaped = !escaped && next === "\\";
-			}
-			return ret("quasi", "string-2", stream.current());
-		}
-
-		var brackets = "([{}])";
-		// This is a crude lookahead trick to try and notice that we're
-		// parsing the argument patterns for a fat-arrow function before we
-		// actually hit the arrow token. It only works if the arrow is on
-		// the same line as the arguments and there's no strange noise
-		// (comments) in between. Fallback is to only notice when we hit the
-		// arrow, and not declare the arguments as locals for the arrow
-		// body.
-		function findFatArrow(stream, state) {
-			if (state.fatArrowAt) state.fatArrowAt = null;
-			var arrow = stream.string.indexOf("=>", stream.start);
-			if (arrow < 0) return;
-
-			var depth = 0, sawSomething = false;
-			for (var pos = arrow - 1; pos >= 0; --pos) {
-				var ch = stream.string.charAt(pos);
-				var bracket = brackets.indexOf(ch);
-				if (bracket >= 0 && bracket < 3) {
-					if (!depth) {
-						++pos;
-						break;
-					}
-					if (--depth == 0) {
-						if (ch === "(") sawSomething = true;
-						break;
-					}
-				} else if (bracket >= 3 && bracket < 6) {
-					++depth;
-				} else if (wordRE.test(ch)) {
-					sawSomething = true;
-				} else if (/["'\/]/.test(ch)) {
-					return;
-				} else if (sawSomething && !depth) {
-					++pos;
-					break;
-				}
-			}
-			if (sawSomething && !depth) state.fatArrowAt = pos;
-		}
-
-		// Parser
-
-		var atomicTypes = {
-			"atom": true,
-			"number": true,
-			"variable": true,
-			"string": true,
-			"regexp": true
-		};
-
-		function TSLexical(indented, column, type, align, prev, info) {
-			this.indented = indented;
-			this.column = column;
-			this.type = type;
-			this.prev = prev;
-			this.info = info;
-			if (align != null) this.align = align;
-		}
-
-		function inScope(state, varname) {
-			for (var v = state.localVars; v; v = v.next)
-				if (v.name == varname) return true;
-			for (var cx = state.context; cx; cx = cx.prev) {
-				for (var v = cx.vars; v; v = v.next)
-					if (v.name == varname) return true;
-			}
-		}
-
-		function parseTS(state, style, type, content, stream) {
-			var cc = state.cc;
-			// Communicate our context to the combinators.
-			// (Less wasteful than consing up a hundred closures on every call.)
-			cx.state = state;
-			cx.stream = stream;
-			cx.marked = null, cx.cc = cc;
-			cx.style = style;
-
-			if (!state.lexical.hasOwnProperty("align"))
-				state.lexical.align = true;
-
-			while (true) {
-				var combinator = cc.length ? cc.pop() : statement;
-				if (combinator(type, content)) {
-					while (cc.length && cc[cc.length - 1].lex)
-						cc.pop()();
-					if (cx.marked) return cx.marked;
-					if (type === "variable" && inScope(state, content)) return "variable-2";
-					return style;
-				}
-			}
-		}
-
-		// Combinator utils
-
-		var cx = {state: null, column: null, marked: null, cc: null};
-
-		function pass() {
-			for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
-		}
-
-		function cont() {
-			pass.apply(null, arguments);
-			return true;
-		}
-
-		function register(varname) {
-			function inList(list) {
-				for (var v = list; v; v = v.next)
-					if (v.name == varname) return true;
-				return false;
-			}
-
-			var state = cx.state;
-			cx.marked = "def";
-			if (state.context) {
-				if (inList(state.localVars)) return;
-				state.localVars = {name: varname, next: state.localVars};
-			} else {
-				if (inList(state.globalVars)) return;
-				if (parserConfig.globalVars)
-					state.globalVars = {name: varname, next: state.globalVars};
-			}
-		}
-
-		// Combinators
-
-		var defaultVars = {name: "this", next: {name: "arguments"}};
-
-		function pushcontext() {
-			cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
-			cx.state.localVars = defaultVars;
-		}
-
-		function popcontext() {
-			cx.state.localVars = cx.state.context.vars;
-			cx.state.context = cx.state.context.prev;
-		}
-
-		function pushlex(type, info) {
-			var result = function () {
-				var state = cx.state, indent = state.indented;
-				if (state.lexical.type === "stat") indent = state.lexical.indented;
-				else for (var outer = state.lexical; outer && outer.type === ")" && outer.align; outer = outer.prev)
-					indent = outer.indented;
-				state.lexical = new TSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
-			};
-			result.lex = true;
-			return result;
-		}
-
-		function poplex() {
-			var state = cx.state;
-			if (state.lexical.prev) {
-				if (state.lexical.type === ")")
-					state.indented = state.lexical.indented;
-				state.lexical = state.lexical.prev;
-			}
-		}
-
-		poplex.lex = true;
-
-		function expect(wanted) {
-			function exp(type) {
-				if (type == wanted) return cont();
-				else if (wanted === ";") return pass();
-				else return cont(exp);
-			};
-			return exp;
-		}
-
-		function statement(type, value) {
-			if (type === "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
-			if (type === "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
-			if (type === "keyword b") return cont(pushlex("form"), statement, poplex);
-			if (type === "{") return cont(pushlex("}"), block, poplex);
-			if (type === ";") return cont();
-			if (type === "if") {
-				if (cx.state.lexical.info === "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) {
-					cx.state.cc.pop()();
-				}
-				return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
-			}
-			if (type === "function") return cont(functiondef);
-			if (type === "for") return cont(pushlex("form"), forspec, statement, poplex);
-			if (type === "variable") {
-				return cont(pushlex("stat"), maybelabel);
-			}
-			if (type === "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"),
-				block, poplex, poplex);
-			if (type === "case") return cont(expression, expect(":"));
-			if (type === "default") return cont(expect(":"));
-			if (type === "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
-				statement, poplex, popcontext);
-			if (type === "class") return cont(pushlex("form"), className, poplex);
-			if (type === "export") return cont(pushlex("stat"), afterExport, poplex);
-			if (type === "import") return cont(pushlex("stat"), afterImport, poplex);
-			if (type === "module") return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
-			if (type === "async") return cont(statement)
-			if (value === "@") return cont(expression, statement)
-			return pass(pushlex("stat"), expression, expect(";"), poplex);
-		}
-
-		function expression(type) {
-			return expressionInner(type, false);
-		}
-
-		function expressionNoComma(type) {
-			return expressionInner(type, true);
-		}
-
-		function parenExpr(type) {
-			if (type !== "(") return pass()
-			return cont(pushlex(")"), expression, expect(")"), poplex)
-		}
-
-		function expressionInner(type, noComma) {
-			var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
-			if (atomicTypes.hasOwnProperty(type)) {
-				return cont(maybeop);
-			}
-			if (type === "keyword c") {
-				return cont(noComma ? maybeexpressionNoComma : maybeexpression);
-			}
-			if (type === "(") {
-				return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
-			}
-			if (type === "operator" || type === "spread") {
-				return cont(noComma ? expressionNoComma : expression);
-			}
-			if (type === "[") {
-				return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
-			}
-			if (type === "{") {
-				return contCommasep(objprop, "}", null, maybeop);
-			}
-			return cont();
-		}
-
-		function maybeexpression(type) {
-			if (type.match(/[;\}\)\],]/)) return pass();
-			return pass(expression);
-		}
-
-		function maybeexpressionNoComma(type) {
-			if (type.match(/[;\}\)\],]/)) return pass();
-			return pass(expressionNoComma);
-		}
-
-		function maybeoperatorComma(type, value) {
-			if (type === ",") return cont(expression);
-			return maybeoperatorNoComma(type, value, false);
-		}
-
-		function maybeoperatorNoComma(type, value, noComma) {
-			var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
-			var expr = noComma == false ? expression : expressionNoComma;
-			if (type === "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
-			if (type === "operator") {
-				if (/\+\+|--/.test(value)) return cont(me);
-				if (value === "?") return cont(expression, expect(":"), expr);
-				return cont(expr);
-			}
-			if (type === "quasi") {
-				return pass(quasi, me);
-			}
-			if (type === ";") return;
-			if (type === "(") return contCommasep(expressionNoComma, ")", "call", me);
-			if (type === ".") return cont(property, me);
-			if (type === "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
-		}
-
-		function quasi(type, value) {
-			if (type !== "quasi") return pass();
-			if (value.slice(value.length - 2) !== "${") return cont(quasi);
-			return cont(expression, continueQuasi);
-		}
-
-		function continueQuasi(type) {
-			if (type === "}") {
-				cx.marked = "string-2";
-				cx.state.tokenize = tokenQuasi;
-				return cont(quasi);
-			}
-		}
-
-		function arrowBody(type) {
-			findFatArrow(cx.stream, cx.state);
-			return pass(type === "{" ? statement : expression);
-		}
-
-		function arrowBodyNoComma(type) {
-			findFatArrow(cx.stream, cx.state);
-			return pass(type === "{" ? statement : expressionNoComma);
-		}
-
-		function maybeTarget(noComma) {
-			return function (type) {
-				if (type === ".") return cont(noComma ? targetNoComma : target);
-				else return pass(noComma ? expressionNoComma : expression);
-			};
-		}
-
-		function target(_, value) {
-			if (value === "target") {
-				cx.marked = "keyword";
-				return cont(maybeoperatorComma);
-			}
-		}
-
-		function targetNoComma(_, value) {
-			if (value === "target") {
-				cx.marked = "keyword";
-				return cont(maybeoperatorNoComma);
-			}
-		}
-
-		function maybelabel(type) {
-			if (type === ":") return cont(poplex, statement);
-			return pass(maybeoperatorComma, expect(";"), poplex);
-		}
-
-		function property(type) {
-			if (type === "variable") {
-				cx.marked = "property";
-				return cont();
-			}
-		}
-
-		function objprop(type, value) {
-			if (type === "async") {
-				cx.marked = "property";
-				return cont(objprop);
-			} else if (type === "variable" || cx.style === "keyword") {
-				cx.marked = "property";
-				if (value === "get" || value === "set") return cont(getterSetter);
-				return cont(afterprop);
-			} else if (type === "number" || type === "string") {
-				cx.marked = cx.style + " property";
-				return cont(afterprop);
-			} else if (type === "jsonld-keyword") {
-				return cont(afterprop);
-			} else if (type === "modifier") {
-				return cont(objprop)
-			} else if (type === "[") {
-				return cont(expression, expect("]"), afterprop);
-			} else if (type === "spread") {
-				return cont(expression, afterprop);
-			} else if (type === ":") {
-				return pass(afterprop)
-			}
-		}
-
-		function getterSetter(type) {
-			if (type !== "variable") return pass(afterprop);
-			cx.marked = "property";
-			return cont(functiondef);
-		}
-
-		function afterprop(type) {
-			if (type === ":") return cont(expressionNoComma);
-			if (type === "(") return pass(functiondef);
-		}
-
-		function commasep(what, end, sep) {
-			function proceed(type, value) {
-				if (sep ? sep.indexOf(type) > -1 : type === ",") {
-					var lex = cx.state.lexical;
-					if (lex.info === "call") lex.pos = (lex.pos || 0) + 1;
-					return cont(function (type, value) {
-						if (type == end || value == end) return pass()
-						return pass(what)
-					}, proceed);
-				}
-				if (type == end || value == end) return cont();
-				return cont(expect(end));
-			}
-
-			return function (type, value) {
-				if (type == end || value == end) return cont();
-				return pass(what, proceed);
-			};
-		}
-
-		function contCommasep(what, end, info) {
-			for (var i = 3; i < arguments.length; i++)
-				cx.cc.push(arguments[i]);
-			return cont(pushlex(end, info), commasep(what, end), poplex);
-		}
-
-		function block(type) {
-			if (type === "}") return cont();
-			return pass(statement, block);
-		}
-
-		function typeexpr(type) {
-			if (type === "variable") {
-				cx.marked = "type";
-				return cont(afterType);
-			}
-			if (type === "string" || type === "number" || type === "atom") return cont(afterType);
-			if (type === "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
-			if (type === "(") return cont(commasep(typearg, ")"), maybeReturnType)
-		}
-
-		function maybeReturnType(type) {
-			if (type === "=>") return cont(typeexpr)
-		}
-
-		function typeprop(type, value) {
-			if (type === "variable" || cx.style === "keyword") {
-				cx.marked = "property"
-				return cont(typeprop)
-			} else if (value === "?") {
-				return cont(typeprop)
-			} else if (type === ":") {
-				return cont(typeexpr)
-			} else if (type === "[") {
-				return cont(expression, null, expect("]"), typeprop)
-			}
-		}
-
-		function typearg(type) {
-			if (type === "variable") return cont(typearg)
-			else if (type === ":") return cont(typeexpr)
-		}
-
-		function afterType(type, value) {
-			if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
-			if (value === "|" || type === ".") return cont(typeexpr)
-			if (type === "[") return cont(expect("]"), afterType)
-			if (value === "extends") return cont(typeexpr)
-		}
-
-		function vardef() {
-			return pass(pattern, null, maybeAssign, vardefCont);
-		}
-
-		function pattern(type, value) {
-			if (type === "modifier") return cont(pattern)
-			if (type === "variable") {
-				register(value);
-				return cont();
-			}
-			if (type === "spread") return cont(pattern);
-			if (type === "[") return contCommasep(pattern, "]");
-			if (type === "{") return contCommasep(proppattern, "}");
-		}
-
-		function proppattern(type, value) {
-			if (type === "variable" && !cx.stream.match(/^\s*:/, false)) {
-				register(value);
-				return cont(maybeAssign);
-			}
-			if (type === "variable") cx.marked = "property";
-			if (type === "spread") return cont(pattern);
-			if (type === "}") return pass();
-			return cont(expect(":"), pattern, maybeAssign);
-		}
-
-		function maybeAssign(_type, value) {
-			if (value === "=") return cont(expressionNoComma);
-		}
-
-		function vardefCont(type) {
-			if (type === ",") return cont(vardef);
-		}
-
-		function maybeelse(type, value) {
-			if (type === "keyword b" && value === "else") return cont(pushlex("form", "else"), statement, poplex);
-		}
-
-		function forspec(type) {
-			if (type === "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
-		}
-
-		function forspec1(type) {
-			if (type === "var") return cont(vardef, expect(";"), forspec2);
-			if (type === ";") return cont(forspec2);
-			if (type === "variable") return cont(formaybeinof);
-			return pass(expression, expect(";"), forspec2);
-		}
-
-		function formaybeinof(_type, value) {
-			if (value === "in" || value === "of") {
-				cx.marked = "keyword";
-				return cont(expression);
-			}
-			return cont(maybeoperatorComma, forspec2);
-		}
-
-		function forspec2(type, value) {
-			if (type === ";") return cont(forspec3);
-			if (value === "in" || value === "of") {
-				cx.marked = "keyword";
-				return cont(expression);
-			}
-			return pass(expression, expect(";"), forspec3);
-		}
-
-		function forspec3(type) {
-			if (type !== ")") cont(expression);
-		}
-
-		function functiondef(type, value) {
-			if (value === "*") {
-				cx.marked = "keyword";
-				return cont(functiondef);
-			}
-			if (type === "variable") {
-				register(value);
-				return cont(functiondef);
-			}
-			if (type === "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, null, statement, popcontext);
-		}
-
-		function funarg(type) {
-			if (type === "spread") return cont(funarg);
-			return pass(pattern, null, maybeAssign);
-		}
-
-		function classExpression(type, value) {
-			// Class expressions may have an optional name.
-			if (type === "variable") return className(type, value);
-			return classNameAfter(type, value);
-		}
-
-		function className(type, value) {
-			if (type === "variable") {
-				register(value);
-				return cont(classNameAfter);
-			}
-		}
-
-		function classNameAfter(type, value) {
-			if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, classNameAfter)
-			if (value === "extends" || value === "implements")
-				return cont(expression, classNameAfter);
-			if (type === "{") return cont(pushlex("}"), classBody, poplex);
-		}
-
-		function classBody(type, value) {
-			if (type === "variable" || cx.style === "keyword") {
-				if ((value === "async" || value === "static" || value === "get" || value === "set") &&
-					cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
-					cx.marked = "keyword";
-					return cont(classBody);
-				}
-				cx.marked = "property";
-				return cont(functiondef, classBody);
-			}
-			if (type === "[")
-				return cont(expression, expect("]"), functiondef, classBody)
-			if (value === "*") {
-				cx.marked = "keyword";
-				return cont(classBody);
-			}
-			if (type === ";") return cont(classBody);
-			if (type === "}") return cont();
-			if (value === "@") return cont(expression, classBody)
-		}
-
-		function classfield(type, value) {
-			if (value === "?") return cont(classfield)
-			if (type === ":") return cont(typeexpr, maybeAssign)
-			if (value === "=") return cont(expressionNoComma)
-			return pass(functiondef)
-		}
-
-		function afterExport(type, value) {
-			if (value === "*") {
-				cx.marked = "keyword";
-				return cont(maybeFrom, expect(";"));
-			}
-			if (value === "default") {
-				cx.marked = "keyword";
-				return cont(expression, expect(";"));
-			}
-			if (type === "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
-			return pass(statement);
-		}
-
-		function exportField(type, value) {
-			if (value === "as") {
-				cx.marked = "keyword";
-				return cont(expect("variable"));
-			}
-			if (type === "variable") return pass(expressionNoComma, exportField);
-		}
-
-		function afterImport(type) {
-			if (type === "string") return cont();
-			return pass(importSpec, maybeMoreImports, maybeFrom);
-		}
-
-		function importSpec(type, value) {
-			if (type === "{") return contCommasep(importSpec, "}");
-			if (type === "variable") register(value);
-			if (value === "*") cx.marked = "keyword";
-			return cont(maybeAs);
-		}
-
-		function maybeMoreImports(type) {
-			if (type === ",") return cont(importSpec, maybeMoreImports)
-		}
-
-		function maybeAs(_type, value) {
-			if (value === "as") {
-				cx.marked = "keyword";
-				return cont(importSpec);
-			}
-		}
-
-		function maybeFrom(_type, value) {
-			if (value === "from") {
-				cx.marked = "keyword";
-				return cont(expression);
-			}
-		}
-
-		function arrayLiteral(type) {
-			if (type === "]") return cont();
-			return pass(commasep(expressionNoComma, "]"));
-		}
-
-		function isContinuedStatement(state, textAfter) {
-			return state.lastType === "operator" || state.lastType === "," ||
-				isOperatorChar.test(textAfter.charAt(0)) ||
-				/[,.]/.test(textAfter.charAt(0));
-		}
-
-		// Interface
-
-		return {
-			startState: function (basecolumn) {
-				var state = {
-					tokenize: tokenBase,
-					lastType: "sof",
-					cc: [],
-					lexical: new TSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
-					localVars: parserConfig.localVars,
-					context: parserConfig.localVars && {vars: parserConfig.localVars},
-					indented: basecolumn || 0
-				};
-				if (parserConfig.globalVars && typeof parserConfig.globalVars === "object")
-					state.globalVars = parserConfig.globalVars;
-				return state;
-			},
-
-			token: function (stream, state) {
-				if (stream.sol()) {
-					if (!state.lexical.hasOwnProperty("align"))
-						state.lexical.align = false;
-					state.indented = stream.indentation();
-					findFatArrow(stream, state);
-				}
-				if (state.tokenize != tokenComment && stream.eatSpace()) return null;
-				var style = state.tokenize(stream, state);
-				if (type === "comment") return style;
-				state.lastType = type === "operator" && (content === "++" || content === "--") ? "incdec" : type;
-				return parseTS(state, style, type, content, stream);
-			},
-
-			indent: function (state, textAfter) {
-				if (state.tokenize == tokenComment) return CodeMirror.Pass;
-				if (state.tokenize != tokenBase) return 0;
-				var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
-				// Kludge to prevent 'maybelse' from blocking lexical scope pops
-				if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
-					var c = state.cc[i];
-					if (c == poplex) lexical = lexical.prev;
-					else if (c != maybeelse) break;
-				}
-				while ((lexical.type === "stat" || lexical.type === "form") &&
-				(firstChar === "}" || ((top = state.cc[state.cc.length - 1]) &&
-				(top == maybeoperatorComma || top == maybeoperatorNoComma) &&
-				!/^[,\.=+\-*:?[\(]/.test(textAfter))))
-					lexical = lexical.prev;
-				if (statementIndent && lexical.type === ")" && lexical.prev.type === "stat")
-					lexical = lexical.prev;
-				var type = lexical.type, closing = firstChar == type;
-
-				if (type === "vardef") return lexical.indented + (state.lastType === "operator" || state.lastType === "," ? lexical.info + 1 : 0);
-				else if (type === "form" && firstChar === "{") return lexical.indented;
-				else if (type === "form") return lexical.indented + indentUnit;
-				else if (type === "stat")
-					return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
-				else if (lexical.info === "switch" && !closing && parserConfig.doubleIndentSwitch != false)
-					return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
-				else if (lexical.align) return lexical.column + (closing ? 0 : 1);
-				else return lexical.indented + (closing ? 0 : indentUnit);
-			},
-
-			electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
-			blockCommentStart: "/*",
-			blockCommentEnd: "*/",
-			lineComment: "#",
-			fold: "brace",
-			closeBrackets: "()[]{}''\"\"``",
-
-			helperType: "typoscript",
-
-			expressionAllowed: expressionAllowed,
-			skipExpression: function (state) {
-				var top = state.cc[state.cc.length - 1];
-				if (top == expression || top == expressionNoComma) state.cc.pop()
-			}
-		};
-	});
+(function(mod) {
+  if (typeof exports === "object" && typeof module === "object") // CommonJS
+    mod(require("cm/lib/codemirror"));
+  else if (typeof define === "function" && define.amd) // AMD
+    define(["cm/lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
+  function expressionAllowed(stream, state, backUp) {
+    return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
+      (state.lastType === "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
+  }
+
+  CodeMirror.defineMode("typoscript", function(config, parserConfig) {
+    var indentUnit = config.indentUnit;
+    var statementIndent = parserConfig.statementIndent;
+    var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
+
+    // Tokenizer
+
+    var keywords = function() {
+      function kw(type) {
+        return {type: type, style: "keyword"};
+      }
+
+      var A = kw("keyword a"), B = kw("keyword b");
+
+      return {
+        '_CSS_DEFAULT_STYLE': kw('_CSS_DEFAULT_STYLE'),
+        '_DEFAULT_PI_VARS': kw('_DEFAULT_PI_VARS'),
+        '_GIFBUILDER': kw('_GIFBUILDER'),
+        '_LOCAL_LANG': kw('_LOCAL_LANG'),
+        '_offset': kw('_offset'),
+        'absRefPrefix': kw('absRefPrefix'),
+        'accessibility': kw('accessibility'),
+        'accessKey': kw('accessKey'),
+        'ACT': B,
+        'ACTIFSUB': B,
+        'ACTIFSUBRO': kw('ACTIFSUBRO'),
+        'ACTRO': B,
+        'addAttributes': kw('addAttributes'),
+        'addExtUrlsAndShortCuts': kw('addExtUrlsAndShortCuts'),
+        'addItems': kw('addItems'),
+        'additionalHeaders': kw('additionalHeaders'),
+        'additionalParams': kw('additionalParams'),
+        'addParams': kw('addParams'),
+        'addQueryString': kw('addQueryString'),
+        'adjustItemsH': kw('adjustItemsH'),
+        'adjustSubItemsH': kw('adjustSubItemsH'),
+        'admPanel': A,
+        'after': kw('after'),
+        'afterImg': kw('afterImg'),
+        'afterImgLink': kw('afterImgLink'),
+        'afterImgTagParams': kw('afterImgTagParams'),
+        'afterROImg': kw('afterROImg'),
+        'afterWrap': kw('afterWrap'),
+        'age': kw('age'),
+        'alertPopups': kw('alertPopups'),
+        'align': kw('align'),
+        'all': B,
+        'allow': kw('allow'),
+        'allowCaching': kw('allowCaching'),
+        'allowedAttribs': kw('allowedAttribs'),
+        'allowedClasses': kw('allowedClasses'),
+        'allowedCols': kw('allowedCols'),
+        'allowedNewTables': kw('allowedNewTables'),
+        'allowTags': kw('allowTags'),
+        'allStdWrap': kw('allStdWrap'),
+        'allWrap': kw('allWrap'),
+        'alt_print': A,
+        'alternativeSortingField': kw('alternativeSortingField'),
+        'alternativeTempPath': kw('alternativeTempPath'),
+        'altIcons': kw('altIcons'),
+        'altImgResource': kw('altImgResource'),
+        'altLabels': kw('altLabels'),
+        'altTarget': kw('altTarget'),
+        'altText': kw('altText'),
+        'altUrl': kw('altUrl'),
+        'altUrl_noDefaultParams': kw('altUrl_noDefaultParams'),
+        'altWrap': kw('altWrap'),
+        'always': kw('always'),
+        'alwaysActivePIDlist': kw('alwaysActivePIDlist'),
+        'alwaysLink': kw('alwaysLink'),
+        'andWhere': kw('andWhere'),
+        'angle': kw('angle'),
+        'antiAlias': kw('antiAlias'),
+        'append': kw('append'),
+        'applyTotalH': kw('applyTotalH'),
+        'applyTotalW': kw('applyTotalW'),
+        'archive': kw('archive'),
+        'ascii': B,
+        'ATagAfterWrap': kw('ATagAfterWrap'),
+        'ATagBeforeWrap': kw('ATagBeforeWrap'),
+        'ATagParams': kw('ATagParams'),
+        'ATagTitle': kw('ATagTitle'),
+        'atLeast': B,
+        'atMost': B,
+        'attribute': kw('attribute'),
+        'auth': A,
+        'autoLevels': kw('autoLevels'),
+        'autonumber': kw('autonumber'),
+        'backColor': kw('backColor'),
+        'background': kw('background'),
+        'baseURL': kw('baseURL'),
+        'BE': B,
+        'be_groups': B,
+        'be_users': B,
+        'before': kw('before'),
+        'beforeImg': kw('beforeImg'),
+        'beforeImgLink': kw('beforeImgLink'),
+        'beforeImgTagParams': kw('beforeImgTagParams'),
+        'beforeROImg': kw('beforeROImg'),
+        'beforeWrap': kw('beforeWrap'),
+        'begin': kw('begin'),
+        'bgCol': kw('bgCol'),
+        'bgImg': kw('bgImg'),
+        'blur': kw('blur'),
+        'bm': kw('bm'),
+        'bodyTag': kw('bodyTag'),
+        'bodyTagAdd': kw('bodyTagAdd'),
+        'bodyTagCObject': kw('bodyTagCObject'),
+        'bodytext': kw('bodytext'),
+        'border': kw('border'),
+        'borderCol': kw('borderCol'),
+        'borderThick': kw('borderThick'),
+        'bottomBackColor': kw('bottomBackColor'),
+        'bottomContent': kw('bottomContent'),
+        'bottomHeight': kw('bottomHeight'),
+        'bottomImg': kw('bottomImg'),
+        'bottomImg_mask': kw('bottomImg_mask'),
+        'BOX': B,
+        'br': kw('br'),
+        'browse': B,
+        'browser': A,
+        'brTag': kw('brTag'),
+        'bullet': kw('bullet'),
+        'bulletlist': kw('bulletlist'),
+        'bullets': B,
+        'bytes': kw('bytes'),
+        'cache': A,
+        'cache_clearAtMidnight': kw('cache_clearAtMidnight'),
+        'cache_period': kw('cache_period'),
+        'caption': kw('caption'),
+        'caption_stdWrap': kw('caption_stdWrap'),
+        'captionHeader': kw('captionHeader'),
+        'captionSplit': kw('captionSplit'),
+        'CARRAY': kw('CARRAY'),
+        'CASE': kw('CASE'),
+        'case': kw('case'),
+        'casesensitiveComp': kw('casesensitiveComp'),
+        'cellpadding': kw('cellpadding'),
+        'cellspacing': kw('cellspacing'),
+        'char': kw('char'),
+        'charcoal': kw('charcoal'),
+        'charMapConfig': kw('charMapConfig'),
+        'CHECK': A,
+        'check': kw('check'),
+        'class': kw('class'),
+        'classesAnchor': kw('classesAnchor'),
+        'classesCharacter': kw('classesCharacter'),
+        'classesImage': kw('classesImage'),
+        'classesParagraph': kw('classesParagraph'),
+        'clear': kw('clear'),
+        'clearCache': kw('clearCache'),
+        'clearCache_disable': kw('clearCache_disable'),
+        'clearCache_pageGrandParent': kw('clearCache_pageGrandParent'),
+        'clearCache_pageSiblingChildren': kw('clearCache_pageSiblingChildren'),
+        'clearCacheCmd': kw('clearCacheCmd'),
+        'clearCacheLevels': kw('clearCacheLevels'),
+        'clearCacheOfPages': kw('clearCacheOfPages'),
+        'clickTitleMode': kw('clickTitleMode'),
+        'clipboardNumberPads': kw('clipboardNumberPads'),
+        'cMargins': kw('cMargins'),
+        'COA': kw('COA'),
+        'COA_INT': kw('COA_INT'),
+        'cObj': A,
+        'COBJ_ARRAY': kw('COBJ_ARRAY'),
+        'cObject': A,
+        'cObjNum': kw('cObjNum'),
+        'collapse': kw('collapse'),
+        'collections': kw('collections'),
+        'color': kw('color'),
+        'color1': kw('color1'),
+        'color2': kw('color2'),
+        'color3': kw('color3'),
+        'color4': kw('color4'),
+        'colors': kw('colors'),
+        'colour': kw('colour'),
+        'colPos_list': kw('colPos_list'),
+        'colRelations': kw('colRelations'),
+        'cols': kw('cols'),
+        'colSpace': kw('colSpace'),
+        'COMMENT': A,
+        'comment_auto': kw('comment_auto'),
+        'commentWrap': kw('commentWrap'),
+        'compX': kw('compX'),
+        'compY': kw('compY'),
+        'conf': kw('conf'),
+        'CONFIG': kw('CONFIG'),
+        'config': A,
+        'CONSTANTS': kw('CONSTANTS'),
+        'constants': kw('constants'),
+        'CONTENT': kw('CONTENT'),
+        'content': A,
+        'content_from_pid_allowOutsideDomain': kw('content_from_pid_allowOutsideDomain'),
+        'contextMenu': kw('contextMenu'),
+        'copy': A,
+        'copyLevels': kw('copyLevels'),
+        'count_HMENU_MENUOBJ': kw('count_HMENU_MENUOBJ'),
+        'count_menuItems': kw('count_menuItems'),
+        'count_MENUOBJ': kw('count_MENUOBJ'),
+        'create': kw('create'),
+        'createFoldersInEB': kw('createFoldersInEB'),
+        'crop': kw('crop'),
+        'csConv': kw('csConv'),
+        'CSS_inlineStyle': A,
+        'CType': kw('CType'),
+        'CUR': B,
+        'CURIFSUB': B,
+        'CURIFSUBRO': B,
+        'current': kw('current'),
+        'CURRO': B,
+        'curUid': kw('curUid'),
+        'cut': A,
+        'cWidth': kw('cWidth'),
+        'data': kw('data'),
+        'dataArray': A,
+        'dataWrap': kw('dataWrap'),
+        'date': kw('date'),
+        'date_stdWrap': kw('date_stdWrap'),
+        'datePrefix': kw('datePrefix'),
+        'dayofmonth': A,
+        'dayofweek': A,
+        'DB': kw('DB'),
+        'db_list': A,
+        'debug': kw('debug'),
+        'debugData': kw('debugData'),
+        'debugFunc': kw('debugFunc'),
+        'debugItemConf': kw('debugItemConf'),
+        'debugRenumberedObject': kw('debugRenumberedObject'),
+        'default': B,
+        'defaultAlign': kw('defaultAlign'),
+        'defaultCmd': kw('defaultCmd'),
+        'defaultFileUploads': kw('defaultFileUploads'),
+        'defaultHeaderType': kw('defaultHeaderType'),
+        'defaultOutput': kw('defaultOutput'),
+        'defaults': kw('defaults'),
+        'defaultType': kw('defaultType'),
+        'delete': kw('delete'),
+        'denyTags': kw('denyTags'),
+        'depth': kw('depth'),
+        'DESC': kw('DESC'),
+        'description': B,
+        'dimensions': kw('dimensions'),
+        'direction': kw('direction'),
+        'directory': B,
+        'directReturn': B,
+        'disableAdvanced': kw('disableAdvanced'),
+        'disableAllHeaderCode': kw('disableAllHeaderCode'),
+        'disableAltText': kw('disableAltText'),
+        'disableBodyTag': kw('disableBodyTag'),
+        'disableCacheSelector': kw('disableCacheSelector'),
+        'disableCharsetHeader': kw('disableCharsetHeader'),
+        'disabled': kw('disabled'),
+        'disableDelete': kw('disableDelete'),
+        'disableDocSelector': kw('disableDocSelector'),
+        'disableHideAtCopy': kw('disableHideAtCopy'),
+        'disableItems': kw('disableItems'),
+        'disableNewContentElementWizard': kw('disableNewContentElementWizard'),
+        'disableNoMatchingValueElement': kw('disableNoMatchingValueElement'),
+        'disablePageExternalUrl': kw('disablePageExternalUrl'),
+        'disablePrefixComment': kw('disablePrefixComment'),
+        'disablePrependAtCopy': kw('disablePrependAtCopy'),
+        'disableSearchBox': kw('disableSearchBox'),
+        'disableSingleTableView': kw('disableSingleTableView'),
+        'displayContent': kw('displayContent'),
+        'displayFieldIcons': kw('displayFieldIcons'),
+        'displayIcons': kw('displayIcons'),
+        'displayMessages': kw('displayMessages'),
+        'displayRecord': kw('displayRecord'),
+        'displayTimes': kw('displayTimes'),
+        'distributeX': kw('distributeX'),
+        'distributeY': kw('distributeY'),
+        'div': B,
+        'DIV': kw('DIV'),
+        'doctype': kw('doctype'),
+        'doctypeSwitch': kw('doctypeSwitch'),
+        'DOCUMENT_BODY': kw('DOCUMENT_BODY'),
+        'doktype': kw('doktype'),
+        'doNotLinkIt': kw('doNotLinkIt'),
+        'doNotShowLink': kw('doNotShowLink'),
+        'doNotStripHTML': kw('doNotStripHTML'),
+        'dontCheckPid': kw('dontCheckPid'),
+        'dontLinkIfSubmenu': kw('dontLinkIfSubmenu'),
+        'dontWrapInTable': kw('dontWrapInTable'),
+        'doubleBrTag': kw('doubleBrTag'),
+        'dWorkArea': kw('dWorkArea'),
+        'dynCSS': A,
+        'edge': kw('edge'),
+        'edit': A,
+        'edit_access': A,
+        'edit_docModuleUpload': kw('edit_docModuleUpload'),
+        'edit_pageheader': A,
+        'edit_RTE': kw('edit_RTE'),
+        'editFieldsAtATime': kw('editFieldsAtATime'),
+        'editFormsOnPage': kw('editFormsOnPage'),
+        'editIcons': kw('editIcons'),
+        'editNoPopup': kw('editNoPopup'),
+        'EDITPANEL': kw('EDITPANEL'),
+        'editPanel': kw('editPanel'),
+        'EFFECT': kw('EFFECT'),
+        'elements': kw('elements'),
+        'else': B,
+        'email': B,
+        'emailMeAtLogin': kw('emailMeAtLogin'),
+        'emailMess': kw('emailMess'),
+        'emboss': kw('emboss'),
+        'enable': kw('enable'),
+        'encapsLines': kw('encapsLines'),
+        'encapsLinesStdWrap': kw('encapsLinesStdWrap'),
+        'encapsTagList': kw('encapsTagList'),
+        'end': B,
+        'entryLevel': kw('entryLevel'),
+        'equalH': kw('equalH'),
+        'equals': B,
+        'everybody': kw('everybody'),
+        'excludeDoktypes': kw('excludeDoktypes'),
+        'excludeUidList': kw('excludeUidList'),
+        'expAll': kw('expAll'),
+        'expand': kw('expand'),
+        'explode': kw('explode'),
+        'ext': kw('ext'),
+        'external': B,
+        'externalBlocks': kw('externalBlocks'),
+        'extTarget': kw('extTarget'),
+        'face': kw('face'),
+        'false': B,
+        'FE': B,
+        'fe_adminLib': kw('fe_adminLib'),
+        'fe_groups': B,
+        'fe_users': B,
+        'feadmin': B,
+        'field': kw('field'),
+        'fieldName': kw('fieldName'),
+        'fieldOrder': kw('fieldOrder'),
+        'fieldRequired': kw('fieldRequired'),
+        'fields': kw('fields'),
+        'fieldWrap': kw('fieldWrap'),
+        'FILE': kw('FILE'),
+        'file': kw('file'),
+        'file1': kw('file1'),
+        'file2': kw('file2'),
+        'file3': kw('file3'),
+        'file4': kw('file4'),
+        'file5': kw('file5'),
+        'filelink': kw('filelink'),
+        'filelist': kw('filelist'),
+        'FILES': kw('FILES'),
+        'files': kw('files'),
+        'firstLabel': kw('firstLabel'),
+        'firstLabelGeneral': kw('firstLabelGeneral'),
+        'fixAttrib': kw('fixAttrib'),
+        'flip': kw('flip'),
+        'flop': kw('flop'),
+        'FLUIDTEMPLATE': kw('FLUIDTEMPLATE'),
+        'folder': A,
+        'folders': kw('folders'),
+        'folderTree': A,
+        'foldoutMenu': A,
+        'fontColor': kw('fontColor'),
+        'fontFile': kw('fontFile'),
+        'fontOffset': kw('fontOffset'),
+        'fontSize': kw('fontSize'),
+        'fontSizeMultiplicator': kw('fontSizeMultiplicator'),
+        'forceDisplayFieldIcons': kw('forceDisplayFieldIcons'),
+        'forceDisplayIcons': kw('forceDisplayIcons'),
+        'forceTemplateParsing': kw('forceTemplateParsing'),
+        'forceTypeValue': kw('forceTypeValue'),
+        'FORM': kw('FORM'),
+        'format': kw('format'),
+        'ftu': kw('ftu'),
+        'function': kw('function'),
+        'Functions': A,
+        'gamma': kw('gamma'),
+        'gapBgCol': kw('gapBgCol'),
+        'gapLineCol': kw('gapLineCol'),
+        'gapLineThickness': kw('gapLineThickness'),
+        'gapWidth': kw('gapWidth'),
+        'get': kw('get'),
+        'getBorder': kw('getBorder'),
+        'getLeft': kw('getLeft'),
+        'getRight': kw('getRight'),
+        'GIFBUILDER': kw('GIFBUILDER'),
+        'global': kw('global'),
+        'globalNesting': kw('globalNesting'),
+        'globalString': kw('globalString'),
+        'globalVar': kw('globalVar'),
+        'GMENU': kw('GMENU'),
+        'GP': kw('GP'),
+        'gray': kw('gray'),
+        'group': kw('group'),
+        'groupBy': kw('groupBy'),
+        'groupid': kw('groupid'),
+        'header': B,
+        'header_layout': kw('header_layout'),
+        'headerComment': kw('headerComment'),
+        'headerData': kw('headerData'),
+        'headerSpace': kw('headerSpace'),
+        'headTag': kw('headTag'),
+        'height': kw('height'),
+        'helpText': kw('helpText'),
+        'hidden': kw('hidden'),
+        'hiddenFields': kw('hiddenFields'),
+        'hide': kw('hide'),
+        'hideButCreateMap': kw('hideButCreateMap'),
+        'hidePStyleItems': kw('hidePStyleItems'),
+        'hideRecords': kw('hideRecords'),
+        'highColor': kw('highColor'),
+        'history': kw('history'),
+        'HMENU': kw('HMENU'),
+        'hostname': A,
+        'hour': A,
+        'HTML': kw('HTML'),
+        'html': B,
+        'HTMLparser': kw('HTMLparser'),
+        'HTMLparser_tags': kw('HTMLparser_tags'),
+        'htmlSpecialChars': kw('htmlSpecialChars'),
+        'htmlTag_dir': kw('htmlTag_dir'),
+        'htmlTag_langKey': kw('htmlTag_langKey'),
+        'htmlTag_setParams': kw('htmlTag_setParams'),
+        'http': kw('http'),
+        'icon': kw('icon'),
+        'icon_image_ext_list': kw('icon_image_ext_list'),
+        'icon_link': kw('icon_link'),
+        'iconCObject': kw('iconCObject'),
+        'id': B,
+        'IENV': kw('IENV'),
+        'if': B,
+        'ifEmpty': B,
+        'IFSUB': B,
+        'IFSUBRO': B,
+        'IMAGE': kw('IMAGE'),
+        'image': B,
+        'image_frames': kw('image_frames'),
+        'imageLinkWrap': kw('imageLinkWrap'),
+        'imagePath': kw('imagePath'),
+        'images': kw('images'),
+        'imageWrapIfAny': kw('imageWrapIfAny'),
+        'IMG_RESOURCE': kw('IMG_RESOURCE'),
+        'imgList': A,
+        'imgMap': kw('imgMap'),
+        'imgMapExtras': kw('imgMapExtras'),
+        'imgMax': kw('imgMax'),
+        'IMGMENU': kw('IMGMENU'),
+        'IMGMENUITEM': kw('IMGMENUITEM'),
+        'imgNameNotRandom': kw('imgNameNotRandom'),
+        'imgNamePrefix': kw('imgNamePrefix'),
+        'imgObjNum': kw('imgObjNum'),
+        'imgParams': kw('imgParams'),
+        'imgPath': kw('imgPath'),
+        'imgResource': A,
+        'imgStart': kw('imgStart'),
+        'IMGTEXT': kw('IMGTEXT'),
+        'imgText': A,
+        'import': kw('import'),
+        'inBranch': B,
+        'inc': kw('inc'),
+        'INCLUDE_TYPOSCRIPT': kw('INCLUDE_TYPOSCRIPT'),
+        'includeCSS': kw('includeCSS'),
+        'includeLibrary': kw('includeLibrary'),
+        'includeNotInMenu': kw('includeNotInMenu'),
+        'index': kw('index'),
+        'index_descrLgd': kw('index_descrLgd'),
+        'index_enable': kw('index_enable'),
+        'index_externals': kw('index_externals'),
+        'info': A,
+        'inlineStyle2TempFile': kw('inlineStyle2TempFile'),
+        'innerStdWrap': kw('innerStdWrap'),
+        'innerStdWrap_all': kw('innerStdWrap_all'),
+        'innerWrap': kw('innerWrap'),
+        'innerWrap2': kw('innerWrap2'),
+        'input': kw('input'),
+        'inputLevels': kw('inputLevels'),
+        'insertData': kw('insertData'),
+        'intensity': kw('intensity'),
+        'intTarget': kw('intTarget'),
+        'intval': kw('intval'),
+        'invert': kw('invert'),
+        'IP': A,
+        'IProcFunc': kw('IProcFunc'),
+        'isFalse': B,
+        'isGreaterThan': B,
+        'isInList': B,
+        'isLessThan': B,
+        'isPositive': B,
+        'isTrue': B,
+        'itemArrayProcFunc': kw('itemArrayProcFunc'),
+        'itemH': kw('itemH'),
+        'items': kw('items'),
+        'itemsProcFunc': kw('itemsProcFunc'),
+        'iterations': kw('iterations'),
+        'join': kw('join'),
+        'JSwindow': A,
+        'JSWindow': kw('JSWindow'),
+        'JSwindow_params': kw('JSwindow_params'),
+        'keep': kw('keep'),
+        'keepEntries': kw('keepEntries'),
+        'keepNonMatchedTags': kw('keepNonMatchedTags'),
+        'key': kw('key'),
+        'keyword3': B,
+        'LABEL': A,
+        'label': kw('label'),
+        'labelStdWrap': kw('labelStdWrap'),
+        'labelWrap': kw('labelWrap'),
+        'lang': kw('lang'),
+        'language': B,
+        'language_alt': kw('language_alt'),
+        'languageField': kw('languageField'),
+        'layout': A,
+        'left': kw('left'),
+        'leftjoin': kw('leftjoin'),
+        'levels': kw('levels'),
+        'leveltitle': B,
+        'leveluid': kw('leveluid'),
+        'lib': A,
+        'limit': kw('limit'),
+        'line': kw('line'),
+        'lineColor': kw('lineColor'),
+        'lineThickness': kw('lineThickness'),
+        'linkPrefix': kw('linkPrefix'),
+        'linkTitleToSelf': kw('linkTitleToSelf'),
+        'linkVars': kw('linkVars'),
+        'linkWrap': kw('linkWrap'),
+        'list': B,
+        'listNum': kw('listNum'),
+        'listOnlyInSingleTableView': kw('listOnlyInSingleTableView'),
+        'LIT': kw('LIT'),
+        'lm': kw('lm'),
+        'LOAD_REGISTER': kw('LOAD_REGISTER'),
+        'locale_all': kw('locale_all'),
+        'localNesting': kw('localNesting'),
+        'locationData': kw('locationData'),
+        'lockToIP': kw('lockToIP'),
+        'login': B,
+        'loginUser': A,
+        'longdescURL': kw('longdescURL'),
+        'lowColor': kw('lowColor'),
+        'lower': kw('lower'),
+        'LR': kw('LR'),
+        'mailform': B,
+        'mailto': kw('mailto'),
+        'main': kw('main'),
+        'makelinks': kw('makelinks'),
+        'markerWrap': kw('markerWrap'),
+        'marks': A,
+        'mask': kw('mask'),
+        'max': kw('max'),
+        'maxAge': kw('maxAge'),
+        'maxChars': kw('maxChars'),
+        'maxH': kw('maxH'),
+        'maxHeight': kw('maxHeight'),
+        'maxItems': kw('maxItems'),
+        'maxW': kw('maxW'),
+        'maxWidth': kw('maxWidth'),
+        'maxWInText': kw('maxWInText'),
+        'media': B,
+        'menu': B,
+        'menu_type': kw('menu_type'),
+        'menuHeight': kw('menuHeight'),
+        'menuName': kw('menuName'),
+        'menuOffset': kw('menuOffset'),
+        'menuWidth': kw('menuWidth'),
+        'message_page_is_being_generated': kw('message_page_is_being_generated'),
+        'message_preview': kw('message_preview'),
+        'META': kw('META'),
+        'meta': kw('meta'),
+        'metaCharset': kw('metaCharset'),
+        'method': kw('method'),
+        'min': kw('min'),
+        'minH': kw('minH'),
+        'minItems': kw('minItems'),
+        'minute': A,
+        'minW': kw('minW'),
+        'mod': B,
+        'mode': kw('mode'),
+        'module': A,
+        'month': A,
+        'move_wizard': A,
+        'MP_defaults': kw('MP_defaults'),
+        'MP_disableTypolinkClosestMPvalue': kw('MP_disableTypolinkClosestMPvalue'),
+        'MP_mapRootPoints': kw('MP_mapRootPoints'),
+        'MULTIMEDIA': kw('MULTIMEDIA'),
+        'multimedia': B,
+        'name': kw('name'),
+        'negate': B,
+        'nesting': kw('nesting'),
+        'neverHideAtCopy': kw('neverHideAtCopy'),
+        'new': A,
+        'NEW': B,
+        'new_wizard': A,
+        'newPageWiz': kw('newPageWiz'),
+        'newRecordFromTable': kw('newRecordFromTable'),
+        'newWindow': kw('newWindow'),
+        'newWizards': kw('newWizards'),
+        'next': kw('next'),
+        'niceText': kw('niceText'),
+        'nicetext': kw('nicetext'),
+        'NO': B,
+        'no_cache': kw('no_cache'),
+        'no_search': kw('no_search'),
+        'noAttrib': kw('noAttrib'),
+        'noCache': kw('noCache'),
+        'noCreateRecordsLink': kw('noCreateRecordsLink'),
+        'noLink': kw('noLink'),
+        'noMatchingValue_label': kw('noMatchingValue_label'),
+        'nonCachedSubst': kw('nonCachedSubst'),
+        'none': B,
+        'nonTypoTagStdWrap': kw('nonTypoTagStdWrap'),
+        'nonTypoTagUserFunc': kw('nonTypoTagUserFunc'),
+        'nonWrappedTag': kw('nonWrappedTag'),
+        'noOrderBy': kw('noOrderBy'),
+        'noPageTitle': kw('noPageTitle'),
+        'noResultObj': A,
+        'noThumbsInEB': kw('noThumbsInEB'),
+        'noThumbsInRTEimageSelect': kw('noThumbsInRTEimageSelect'),
+        'noTrimWrap': kw('noTrimWrap'),
+        'noValueInsert': kw('noValueInsert'),
+        'numRows': A,
+        'obj': kw('obj'),
+        'offset': kw('offset'),
+        'onlineWorkspaceInfo': kw('onlineWorkspaceInfo'),
+        'onlyCurrentPid': kw('onlyCurrentPid'),
+        'opacity': kw('opacity'),
+        'options': A,
+        'orderBy': kw('orderBy'),
+        'outerWrap': kw('outerWrap'),
+        'outline': kw('outline'),
+        'outputLevels': kw('outputLevels'),
+        'override': kw('override'),
+        'overrideAttribs': kw('overrideAttribs'),
+        'overrideId': kw('overrideId'),
+        'overridePageModule': kw('overridePageModule'),
+        'overrideWithExtension': kw('overrideWithExtension'),
+        'PAGE': kw('PAGE'),
+        'page': A,
+        'PAGE_TARGET': kw('PAGE_TARGET'),
+        'PAGE_TSCONFIG_ID': kw('PAGE_TSCONFIG_ID'),
+        'PAGE_TSCONFIG_IDLIST': kw('PAGE_TSCONFIG_IDLIST'),
+        'PAGE_TSCONFIG_STR': kw('PAGE_TSCONFIG_STR'),
+        'pageFrameObj': kw('pageFrameObj'),
+        'pages': B,
+        'pages_language_overlay': B,
+        'pageTitleFirst': kw('pageTitleFirst'),
+        'pageTree': A,
+        'parameter': kw('parameter'),
+        'params': kw('params'),
+        'parseFunc': kw('parseFunc'),
+        'parseFunc_RTE': B,
+        'parser': kw('parser'),
+        'password': kw('password'),
+        'paste': A,
+        'path': kw('path'),
+        'permissions': kw('permissions'),
+        'perms': A,
+        'pid': B,
+        'pid_list': kw('pid_list'),
+        'pidInList': kw('pidInList'),
+        'PIDinRootline': A,
+        'PIDupinRootline': A,
+        'pixelSpaceFontSizeRef': kw('pixelSpaceFontSizeRef'),
+        'plaintextLib': kw('plaintextLib'),
+        'plainTextStdWrap': kw('plainTextStdWrap'),
+        'plugin': A,
+        'postCObject': kw('postCObject'),
+        'postLineBlanks': kw('postLineBlanks'),
+        'postLineChar': kw('postLineChar'),
+        'postLineLen': kw('postLineLen'),
+        'postUserFunc': kw('postUserFunc'),
+        'postUserFuncInt': kw('postUserFuncInt'),
+        'preBlanks': kw('preBlanks'),
+        'preCObject': kw('preCObject'),
+        'prefix': kw('prefix'),
+        'prefixComment': kw('prefixComment'),
+        'prefixLocalAnchors': kw('prefixLocalAnchors'),
+        'prefixRelPathWith': kw('prefixRelPathWith'),
+        'preIfEmptyListNum': kw('preIfEmptyListNum'),
+        'preLineBlanks': kw('preLineBlanks'),
+        'preLineChar': kw('preLineChar'),
+        'preLineLen': kw('preLineLen'),
+        'prepend': kw('prepend'),
+        'preserveEntities': kw('preserveEntities'),
+        'preUserFunc': kw('preUserFunc'),
+        'prev': kw('prev'),
+        'preview': A,
+        'previewBorder': kw('previewBorder'),
+        'prevnextToSection': kw('prevnextToSection'),
+        'prioriCalc': kw('prioriCalc'),
+        'proc': kw('proc'),
+        'processor_allowUpscaling': kw('processor_allowUpscaling'),
+        'properties': kw('properties'),
+        'protect': kw('protect'),
+        'protectLvar': kw('protectLvar'),
+        'publish': A,
+        'publish_levels': kw('publish_levels'),
+        'QEisDefault': kw('QEisDefault'),
+        'quality': kw('quality'),
+        'RADIO': A,
+        'radio': kw('radio'),
+        'radioWrap': kw('radioWrap'),
+        'range': kw('range'),
+        'rawUrlEncode': kw('rawUrlEncode'),
+        'recipient': kw('recipient'),
+        'RECORDS': kw('RECORDS'),
+        'recursive': kw('recursive'),
+        'recursiveDelete': kw('recursiveDelete'),
+        'redirect': kw('redirect'),
+        'redirectToURL': kw('redirectToURL'),
+        'reduceColors': kw('reduceColors'),
+        'references': kw('references'),
+        'register': kw('register'),
+        'relPathPrefix': kw('relPathPrefix'),
+        'remap': kw('remap'),
+        'remapTag': kw('remapTag'),
+        'REMOTE_ADDR': kw('REMOTE_ADDR'),
+        'removeDefaultJS': kw('removeDefaultJS'),
+        'removeIfEquals': kw('removeIfEquals'),
+        'removeIfFalse': kw('removeIfFalse'),
+        'removeItems': kw('removeItems'),
+        'removeObjectsOfDummy': kw('removeObjectsOfDummy'),
+        'removePrependedNumbers': kw('removePrependedNumbers'),
+        'removeTags': kw('removeTags'),
+        'removeWrapping': kw('removeWrapping'),
+        'renderObj': A,
+        'renderWrap': kw('renderWrap'),
+        'REQ': A,
+        'required': B,
+        'reset': kw('reset'),
+        'resources': kw('resources'),
+        'RESTORE_REGISTER': kw('RESTORE_REGISTER'),
+        'resultObj': kw('resultObj'),
+        'returnLast': kw('returnLast'),
+        'returnUrl': kw('returnUrl'),
+        'rightjoin': kw('rightjoin'),
+        'rm': kw('rm'),
+        'rmTagIfNoAttrib': kw('rmTagIfNoAttrib'),
+        'RO': B,
+        'rootline': B,
+        'rotate': kw('rotate'),
+        'rows': kw('rows'),
+        'rowSpace': kw('rowSpace'),
+        'RTE': A,
+        'RTE_compliant': A,
+        'RTEfullScreenWidth': kw('RTEfullScreenWidth'),
+        'rules': kw('rules'),
+        'sample': kw('sample'),
+        'saveClipboard': kw('saveClipboard'),
+        'saveDocNew': kw('saveDocNew'),
+        'script': B,
+        'search': B,
+        'SEARCHRESULT': kw('SEARCHRESULT'),
+        'secondRow': kw('secondRow'),
+        'section': kw('section'),
+        'sectionIndex': kw('sectionIndex'),
+        'select': A,
+        'selectFields': kw('selectFields'),
+        'separator': kw('separator'),
+        'set': kw('set'),
+        'setContentToCurrent': kw('setContentToCurrent'),
+        'setCurrent': kw('setCurrent'),
+        'setfixed': kw('setfixed'),
+        'setOnly': kw('setOnly'),
+        'setup': A,
+        'shadow': kw('shadow'),
+        'SHARED': kw('SHARED'),
+        'sharpen': kw('sharpen'),
+        'shear': kw('shear'),
+        'short': kw('short'),
+        'shortcut': B,
+        'shortcutFrame': kw('shortcutFrame'),
+        'shortcutIcon': kw('shortcutIcon'),
+        'show': kw('show'),
+        'showAccessRestrictedPages': kw('showAccessRestrictedPages'),
+        'showActive': kw('showActive'),
+        'showClipControlPanelsDespiteOfCMlayers': kw('showClipControlPanelsDespiteOfCMlayers'),
+        'showFirst': kw('showFirst'),
+        'showHiddenPages': kw('showHiddenPages'),
+        'showHiddenRecords': kw('showHiddenRecords'),
+        'showHistory': kw('showHistory'),
+        'showPageIdWithTitle': kw('showPageIdWithTitle'),
+        'showTagFreeClasses': kw('showTagFreeClasses'),
+        'simulateDate': kw('simulateDate'),
+        'simulateUserGroup': kw('simulateUserGroup'),
+        'singlePid': kw('singlePid'),
+        'site_author': kw('site_author'),
+        'site_reserved': kw('site_reserved'),
+        'sitemap': B,
+        'sitetitle': kw('sitetitle'),
+        'siteUrl': kw('siteUrl'),
+        'size': kw('size'),
+        'solarize': kw('solarize'),
+        'sorting': kw('sorting'),
+        'source': kw('source'),
+        'space': kw('space'),
+        'spaceAfter': kw('spaceAfter'),
+        'spaceBefore': kw('spaceBefore'),
+        'spaceBelowAbove': kw('spaceBelowAbove'),
+        'spaceLeft': kw('spaceLeft'),
+        'spaceRight': kw('spaceRight'),
+        'spacing': kw('spacing'),
+        'spamProtectEmailAddresses': kw('spamProtectEmailAddresses'),
+        'spamProtectEmailAddresses_atSubst': kw('spamProtectEmailAddresses_atSubst'),
+        'spamProtectEmailAddresses_lastDotSubst': kw('spamProtectEmailAddresses_lastDotSubst'),
+        'SPC': B,
+        'special': kw('special'),
+        'split': A,
+        'splitChar': kw('splitChar'),
+        'splitRendering': kw('splitRendering'),
+        'src': kw('src'),
+        'stdheader': kw('stdheader'),
+        'stdWrap': A,
+        'stdWrap2': kw('stdWrap2'),
+        'strftime': kw('strftime'),
+        'stripHtml': kw('stripHtml'),
+        'styles': kw('styles'),
+        'submenuObjSuffixes': kw('submenuObjSuffixes'),
+        'subMenuOffset': kw('subMenuOffset'),
+        'submit': kw('submit'),
+        'subparts': A,
+        'subst_elementUid': kw('subst_elementUid'),
+        'substMarksSeparately': kw('substMarksSeparately'),
+        'substring': kw('substring'),
+        'swirl': kw('swirl'),
+        'sword': kw('sword'),
+        'sword_noMixedCase': kw('sword_noMixedCase'),
+        'SWORD_PARAMS': kw('SWORD_PARAMS'),
+        'sword_standAlone': kw('sword_standAlone'),
+        'sys_dmail': B,
+        'sys_domain': B,
+        'sys_filemounts': B,
+        'sys_language_mode': kw('sys_language_mode'),
+        'sys_language_overlay': kw('sys_language_overlay'),
+        'sys_language_uid': kw('sys_language_uid'),
+        'sys_note': B,
+        'sys_template': B,
+        'system': A,
+        'table': B,
+        'tableCellColor': kw('tableCellColor'),
+        'tableParams': kw('tableParams'),
+        'tables': kw('tables'),
+        'tableStdWrap': kw('tableStdWrap'),
+        'tableWidth': kw('tableWidth'),
+        'tags': kw('tags'),
+        'target': kw('target'),
+        'TCAdefaults': kw('TCAdefaults'),
+        'TCEFORM': kw('TCEFORM'),
+        'TCEMAIN': kw('TCEMAIN'),
+        'TDparams': kw('TDparams'),
+        'temp': A,
+        'TEMPLATE': kw('TEMPLATE'),
+        'template': A,
+        'templateContent': kw('templateContent'),
+        'templateFile': kw('templateFile'),
+        'TEXT': kw('TEXT'),
+        'text': B,
+        'textarea': kw('textarea'),
+        'textMargin': kw('textMargin'),
+        'textMargin_outOfText': kw('textMargin_outOfText'),
+        'textMaxLength': kw('textMaxLength'),
+        'textObjNum': kw('textObjNum'),
+        'textpic': B,
+        'textPos': kw('textPos'),
+        'thickness': kw('thickness'),
+        'this': B,
+        'thumbnailsByDefault': kw('thumbnailsByDefault'),
+        'tile': kw('tile'),
+        'time_stdWrap': kw('time_stdWrap'),
+        'tipafriendLib': kw('tipafriendLib'),
+        'title': kw('title'),
+        'titleLen': kw('titleLen'),
+        'titleTagFunction': kw('titleTagFunction'),
+        'titleText': kw('titleText'),
+        'tm': kw('tm'),
+        'TMENU': kw('TMENU'),
+        'TMENUITEM': kw('TMENUITEM'),
+        'token': kw('token'),
+        'top': B,
+        'totalWidth': kw('totalWidth'),
+        'transparentBackground': kw('transparentBackground'),
+        'transparentColor': kw('transparentColor'),
+        'treeLevel': A,
+        'trim': kw('trim'),
+        'true': B,
+        'tsdebug': A,
+        'tsdebug_tree': kw('tsdebug_tree'),
+        'TSFE': kw('TSFE'),
+        'type': kw('type'),
+        'typeNum': kw('typeNum'),
+        'types': kw('types'),
+        'typolink': A,
+        'uid': B,
+        'uidInList': kw('uidInList'),
+        'uniqueGlobal': B,
+        'uniqueLocal': B,
+        'unset': kw('unset'),
+        'unsetEmpty': B,
+        'updated': B,
+        'uploadFieldsInTopOfEB': kw('uploadFieldsInTopOfEB'),
+        'uploads': B,
+        'upper': kw('upper'),
+        'url': A,
+        'us': B,
+        'useCacheHash': kw('useCacheHash'),
+        'useLargestItemX': kw('useLargestItemX'),
+        'useLargestItemY': kw('useLargestItemY'),
+        'USER': kw('USER'),
+        'user': kw('user'),
+        'USER_INT': kw('USER_INT'),
+        'user_task': B,
+        'useragent': A,
+        'USERDEF1': B,
+        'USERDEF1RO': B,
+        'USERDEF2': B,
+        'USERDEF2RO': B,
+        'userdefined': kw('userdefined'),
+        'userFunc': A,
+        'userfunction': kw('userfunction'),
+        'usergroup': B,
+        'userid': kw('userid'),
+        'USERNAME_substToken': kw('USERNAME_substToken'),
+        'userProc': kw('userProc'),
+        'USR': B,
+        'USRRO': B,
+        'value': kw('value'),
+        'valueArray': kw('valueArray'),
+        'version': A,
+        'view': A,
+        'wave': kw('wave'),
+        'web_func': B,
+        'web_info': B,
+        'web_layout': B,
+        'web_list': B,
+        'web_ts': kw('web_ts'),
+        'where': kw('where'),
+        'width': kw('width'),
+        'wiz': kw('wiz'),
+        'wordSpacing': kw('wordSpacing'),
+        'workArea': kw('workArea'),
+        'workOnSubpart': A,
+        'wrap': kw('wrap'),
+        'wrap1': kw('wrap1'),
+        'wrap2': kw('wrap2'),
+        'wrap3': kw('wrap3'),
+        'wrapAfterTags': kw('wrapAfterTags'),
+        'wrapAlign': kw('wrapAlign'),
+        'wrapFieldName': kw('wrapFieldName'),
+        'wrapItemAndSub': kw('wrapItemAndSub'),
+        'wrapNonWrappedLines': kw('wrapNonWrappedLines'),
+        'wraps': kw('wraps'),
+        'xhtml_cleaning': kw('xhtml_cleaning'),
+        'xhtml_strict': B,
+        'xhtml_trans': B,
+        'xmlprologue': kw('xmlprologue'),
+        'XY': B
+      };
+    }();
+
+    var isOperatorChar = /[\+\-\*\&\%\/=<>!\?]/;
+    var inValue = false;
+
+    function readRegexp(stream) {
+      var escaped = false, next, inSet = false;
+      while ((next = stream.next()) != null) {
+        if (!escaped) {
+          if (next === "/" && !inSet) return;
+          if (next === "[") inSet = true;
+          else if (inSet && next === "]") inSet = false;
+        }
+        escaped = !escaped && next === "\\";
+      }
+    }
+
+    // Used as scratch variables to communicate multiple values without
+    // consing up tons of objects.
+    var type, content;
+
+    function ret(tp, style, cont) {
+      type = tp;
+      content = cont;
+      return style;
+    }
+
+    function tokenBase(stream, state) {
+      var ch = stream.next();
+      if (ch === "\n") {
+        inValue = false;
+      }
+
+      if (ch === "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
+        return ret("number", "number");
+      }
+      if (ch === "." && stream.match("..")) {
+        return ret("spread", "meta");
+      }
+      if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+        return ret(ch);
+      }
+      if ((ch === '<' || ch === '>' || ch === '.' || (ch === '=' && stream.peek() !== '<'))) {
+        inValue = true;
+        return ret(ch, 'operator')
+      }
+      if (!inValue && /[\[\]\(\),;\:\.\<\>\=]/.test(ch)) {
+        return ret(ch, 'operator')
+      }
+      if (ch === "0" && stream.eat(/x/i)) {
+        stream.eatWhile(/[\da-f]/i);
+        return ret("number", "number");
+      }
+      if (ch === "0" && stream.eat(/o/i)) {
+        stream.eatWhile(/[0-7]/i);
+        return ret("number", "number");
+      }
+      if (ch === "0" && stream.eat(/b/i)) {
+        stream.eatWhile(/[01]/i);
+        return ret("number", "number");
+      }
+      if (/\d/.test(ch)) {
+        stream.match(/^\d*(?:\.\d+)?(?:[eE][+\-]?\d+)?/);
+        return ret("number", "number");
+      }
+      if (ch === "/") {
+        if (stream.eat("*")) {
+          state.tokenize = tokenComment;
+          return tokenComment(stream, state);
+        }
+        if (stream.eat("/")) {
+          stream.skipToEnd();
+          return ret("comment", "comment");
+        }
+        if (expressionAllowed(stream, state, 1)) {
+          readRegexp(stream);
+          stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
+          return ret("regexp", "string-2");
+        }
+
+        stream.eatWhile(isOperatorChar);
+        return ret("operator", "operator", stream.current());
+      }
+      if (ch === "`") {
+        state.tokenize = tokenQuasi;
+        return tokenQuasi(stream, state);
+      }
+      if (ch === "#") {
+        stream.skipToEnd();
+        return ret("comment", "comment");
+      }
+      if (isOperatorChar.test(ch)) {
+        if (ch !== ">" || !state.lexical || state.lexical.type !== ">") {
+          stream.eatWhile(isOperatorChar);
+        }
+        return ret("operator", "operator", stream.current());
+      }
+      if (wordRE.test(ch)) {
+        stream.eatWhile(wordRE);
+        var word = stream.current();
+        if (keywords.propertyIsEnumerable(word)) {
+          var kw = keywords[word];
+          return ret(kw.type, kw.style, word);
+        }
+        if (word === "async" && stream.match(/^\s*[\(\w]/, false)) {
+          return ret("async", "keyword", word);
+        }
+        if (inValue) {
+          return ret('string', 'string', word);
+        }
+        return ret("variable", "other", word);
+      }
+    }
+
+    function tokenString(quote) {
+      return function(stream, state) {
+        var escaped = false, next;
+        while ((next = stream.next()) != null) {
+          if (next == quote && !escaped) break;
+          escaped = !escaped && next === "\\";
+        }
+        if (!escaped) state.tokenize = tokenBase;
+        return ret("string", "string");
+      };
+    }
+
+    function tokenComment(stream, state) {
+      var maybeEnd = false, ch;
+      while (ch = stream.next()) {
+        if (ch === "/" && maybeEnd) {
+          state.tokenize = tokenBase;
+          break;
+        }
+        maybeEnd = (ch === "*");
+      }
+      return ret("comment", "comment");
+    }
+
+    function tokenQuasi(stream, state) {
+      var escaped = false, next;
+      while ((next = stream.next()) != null) {
+        if (!escaped && (next === "`" || next === "$" && stream.eat("{"))) {
+          state.tokenize = tokenBase;
+          break;
+        }
+        escaped = !escaped && next === "\\";
+      }
+      return ret("quasi", "string-2", stream.current());
+    }
+
+    var brackets = "([{}])";
+    // This is a crude lookahead trick to try and notice that we're
+    // parsing the argument patterns for a fat-arrow function before we
+    // actually hit the arrow token. It only works if the arrow is on
+    // the same line as the arguments and there's no strange noise
+    // (comments) in between. Fallback is to only notice when we hit the
+    // arrow, and not declare the arguments as locals for the arrow
+    // body.
+    function findFatArrow(stream, state) {
+      if (state.fatArrowAt) state.fatArrowAt = null;
+      var arrow = stream.string.indexOf("=>", stream.start);
+      if (arrow < 0) return;
+
+      var depth = 0, sawSomething = false;
+      for (var pos = arrow - 1; pos >= 0; --pos) {
+        var ch = stream.string.charAt(pos);
+        var bracket = brackets.indexOf(ch);
+        if (bracket >= 0 && bracket < 3) {
+          if (!depth) {
+            ++pos;
+            break;
+          }
+          if (--depth == 0) {
+            if (ch === "(") sawSomething = true;
+            break;
+          }
+        } else if (bracket >= 3 && bracket < 6) {
+          ++depth;
+        } else if (wordRE.test(ch)) {
+          sawSomething = true;
+        } else if (/["'\/]/.test(ch)) {
+          return;
+        } else if (sawSomething && !depth) {
+          ++pos;
+          break;
+        }
+      }
+      if (sawSomething && !depth) state.fatArrowAt = pos;
+    }
+
+    // Parser
+
+    var atomicTypes = {
+      "atom": true,
+      "number": true,
+      "variable": true,
+      "string": true,
+      "regexp": true
+    };
+
+    function TSLexical(indented, column, type, align, prev, info) {
+      this.indented = indented;
+      this.column = column;
+      this.type = type;
+      this.prev = prev;
+      this.info = info;
+      if (align != null) this.align = align;
+    }
+
+    function inScope(state, varname) {
+      for (var v = state.localVars; v; v = v.next)
+        if (v.name == varname) return true;
+      for (var cx = state.context; cx; cx = cx.prev) {
+        for (var v = cx.vars; v; v = v.next)
+          if (v.name == varname) return true;
+      }
+    }
+
+    function parseTS(state, style, type, content, stream) {
+      var cc = state.cc;
+      // Communicate our context to the combinators.
+      // (Less wasteful than consing up a hundred closures on every call.)
+      cx.state = state;
+      cx.stream = stream;
+      cx.marked = null, cx.cc = cc;
+      cx.style = style;
+
+      if (!state.lexical.hasOwnProperty("align"))
+        state.lexical.align = true;
+
+      while (true) {
+        var combinator = cc.length ? cc.pop() : statement;
+        if (combinator(type, content)) {
+          while (cc.length && cc[cc.length - 1].lex)
+            cc.pop()();
+          if (cx.marked) return cx.marked;
+          if (type === "variable" && inScope(state, content)) return "variable-2";
+          return style;
+        }
+      }
+    }
+
+    // Combinator utils
+
+    var cx = {state: null, column: null, marked: null, cc: null};
+
+    function pass() {
+      for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
+    }
+
+    function cont() {
+      pass.apply(null, arguments);
+      return true;
+    }
+
+    function register(varname) {
+      function inList(list) {
+        for (var v = list; v; v = v.next)
+          if (v.name == varname) return true;
+        return false;
+      }
+
+      var state = cx.state;
+      cx.marked = "def";
+      if (state.context) {
+        if (inList(state.localVars)) return;
+        state.localVars = {name: varname, next: state.localVars};
+      } else {
+        if (inList(state.globalVars)) return;
+        if (parserConfig.globalVars)
+          state.globalVars = {name: varname, next: state.globalVars};
+      }
+    }
+
+    // Combinators
+
+    var defaultVars = {name: "this", next: {name: "arguments"}};
+
+    function pushcontext() {
+      cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
+      cx.state.localVars = defaultVars;
+    }
+
+    function popcontext() {
+      cx.state.localVars = cx.state.context.vars;
+      cx.state.context = cx.state.context.prev;
+    }
+
+    function pushlex(type, info) {
+      var result = function() {
+        var state = cx.state, indent = state.indented;
+        if (state.lexical.type === "stat") indent = state.lexical.indented;
+        else for (var outer = state.lexical; outer && outer.type === ")" && outer.align; outer = outer.prev)
+          indent = outer.indented;
+        state.lexical = new TSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
+      };
+      result.lex = true;
+      return result;
+    }
+
+    function poplex() {
+      var state = cx.state;
+      if (state.lexical.prev) {
+        if (state.lexical.type === ")")
+          state.indented = state.lexical.indented;
+        state.lexical = state.lexical.prev;
+      }
+    }
+
+    poplex.lex = true;
+
+    function expect(wanted) {
+      function exp(type) {
+        if (type == wanted) return cont();
+        else if (wanted === ";") return pass();
+        else return cont(exp);
+      };
+      return exp;
+    }
+
+    function statement(type, value) {
+      if (type === "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
+      if (type === "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
+      if (type === "keyword b") return cont(pushlex("form"), statement, poplex);
+      if (type === "{") return cont(pushlex("}"), block, poplex);
+      if (type === ";") return cont();
+      if (type === "if") {
+        if (cx.state.lexical.info === "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) {
+          cx.state.cc.pop()();
+        }
+        return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
+      }
+      if (type === "function") return cont(functiondef);
+      if (type === "for") return cont(pushlex("form"), forspec, statement, poplex);
+      if (type === "variable") {
+        return cont(pushlex("stat"), maybelabel);
+      }
+      if (type === "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"),
+        block, poplex, poplex);
+      if (type === "case") return cont(expression, expect(":"));
+      if (type === "default") return cont(expect(":"));
+      if (type === "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
+        statement, poplex, popcontext);
+      if (type === "class") return cont(pushlex("form"), className, poplex);
+      if (type === "export") return cont(pushlex("stat"), afterExport, poplex);
+      if (type === "import") return cont(pushlex("stat"), afterImport, poplex);
+      if (type === "module") return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
+      if (type === "async") return cont(statement)
+      if (value === "@") return cont(expression, statement)
+      return pass(pushlex("stat"), expression, expect(";"), poplex);
+    }
+
+    function expression(type) {
+      return expressionInner(type, false);
+    }
+
+    function expressionNoComma(type) {
+      return expressionInner(type, true);
+    }
+
+    function parenExpr(type) {
+      if (type !== "(") return pass()
+      return cont(pushlex(")"), expression, expect(")"), poplex)
+    }
+
+    function expressionInner(type, noComma) {
+      var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
+      if (atomicTypes.hasOwnProperty(type)) {
+        return cont(maybeop);
+      }
+      if (type === "keyword c") {
+        return cont(noComma ? maybeexpressionNoComma : maybeexpression);
+      }
+      if (type === "(") {
+        return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
+      }
+      if (type === "operator" || type === "spread") {
+        return cont(noComma ? expressionNoComma : expression);
+      }
+      if (type === "[") {
+        return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
+      }
+      if (type === "{") {
+        return contCommasep(objprop, "}", null, maybeop);
+      }
+      return cont();
+    }
+
+    function maybeexpression(type) {
+      if (type.match(/[;\}\)\],]/)) return pass();
+      return pass(expression);
+    }
+
+    function maybeexpressionNoComma(type) {
+      if (type.match(/[;\}\)\],]/)) return pass();
+      return pass(expressionNoComma);
+    }
+
+    function maybeoperatorComma(type, value) {
+      if (type === ",") return cont(expression);
+      return maybeoperatorNoComma(type, value, false);
+    }
+
+    function maybeoperatorNoComma(type, value, noComma) {
+      var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
+      var expr = noComma == false ? expression : expressionNoComma;
+      if (type === "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
+      if (type === "operator") {
+        if (/\+\+|--/.test(value)) return cont(me);
+        if (value === "?") return cont(expression, expect(":"), expr);
+        return cont(expr);
+      }
+      if (type === "quasi") {
+        return pass(quasi, me);
+      }
+      if (type === ";") return;
+      if (type === "(") return contCommasep(expressionNoComma, ")", "call", me);
+      if (type === ".") return cont(property, me);
+      if (type === "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
+    }
+
+    function quasi(type, value) {
+      if (type !== "quasi") return pass();
+      if (value.slice(value.length - 2) !== "${") return cont(quasi);
+      return cont(expression, continueQuasi);
+    }
+
+    function continueQuasi(type) {
+      if (type === "}") {
+        cx.marked = "string-2";
+        cx.state.tokenize = tokenQuasi;
+        return cont(quasi);
+      }
+    }
+
+    function arrowBody(type) {
+      findFatArrow(cx.stream, cx.state);
+      return pass(type === "{" ? statement : expression);
+    }
+
+    function arrowBodyNoComma(type) {
+      findFatArrow(cx.stream, cx.state);
+      return pass(type === "{" ? statement : expressionNoComma);
+    }
+
+    function maybeTarget(noComma) {
+      return function(type) {
+        if (type === ".") return cont(noComma ? targetNoComma : target);
+        else return pass(noComma ? expressionNoComma : expression);
+      };
+    }
+
+    function target(_, value) {
+      if (value === "target") {
+        cx.marked = "keyword";
+        return cont(maybeoperatorComma);
+      }
+    }
+
+    function targetNoComma(_, value) {
+      if (value === "target") {
+        cx.marked = "keyword";
+        return cont(maybeoperatorNoComma);
+      }
+    }
+
+    function maybelabel(type) {
+      if (type === ":") return cont(poplex, statement);
+      return pass(maybeoperatorComma, expect(";"), poplex);
+    }
+
+    function property(type) {
+      if (type === "variable") {
+        cx.marked = "property";
+        return cont();
+      }
+    }
+
+    function objprop(type, value) {
+      if (type === "async") {
+        cx.marked = "property";
+        return cont(objprop);
+      } else if (type === "variable" || cx.style === "keyword") {
+        cx.marked = "property";
+        if (value === "get" || value === "set") return cont(getterSetter);
+        return cont(afterprop);
+      } else if (type === "number" || type === "string") {
+        cx.marked = cx.style + " property";
+        return cont(afterprop);
+      } else if (type === "jsonld-keyword") {
+        return cont(afterprop);
+      } else if (type === "modifier") {
+        return cont(objprop)
+      } else if (type === "[") {
+        return cont(expression, expect("]"), afterprop);
+      } else if (type === "spread") {
+        return cont(expression, afterprop);
+      } else if (type === ":") {
+        return pass(afterprop)
+      }
+    }
+
+    function getterSetter(type) {
+      if (type !== "variable") return pass(afterprop);
+      cx.marked = "property";
+      return cont(functiondef);
+    }
+
+    function afterprop(type) {
+      if (type === ":") return cont(expressionNoComma);
+      if (type === "(") return pass(functiondef);
+    }
+
+    function commasep(what, end, sep) {
+      function proceed(type, value) {
+        if (sep ? sep.indexOf(type) > -1 : type === ",") {
+          var lex = cx.state.lexical;
+          if (lex.info === "call") lex.pos = (lex.pos || 0) + 1;
+          return cont(function(type, value) {
+            if (type == end || value == end) return pass()
+            return pass(what)
+          }, proceed);
+        }
+        if (type == end || value == end) return cont();
+        return cont(expect(end));
+      }
+
+      return function(type, value) {
+        if (type == end || value == end) return cont();
+        return pass(what, proceed);
+      };
+    }
+
+    function contCommasep(what, end, info) {
+      for (var i = 3; i < arguments.length; i++)
+        cx.cc.push(arguments[i]);
+      return cont(pushlex(end, info), commasep(what, end), poplex);
+    }
+
+    function block(type) {
+      if (type === "}") return cont();
+      return pass(statement, block);
+    }
+
+    function typeexpr(type) {
+      if (type === "variable") {
+        cx.marked = "type";
+        return cont(afterType);
+      }
+      if (type === "string" || type === "number" || type === "atom") return cont(afterType);
+      if (type === "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
+      if (type === "(") return cont(commasep(typearg, ")"), maybeReturnType)
+    }
+
+    function maybeReturnType(type) {
+      if (type === "=>") return cont(typeexpr)
+    }
+
+    function typeprop(type, value) {
+      if (type === "variable" || cx.style === "keyword") {
+        cx.marked = "property"
+        return cont(typeprop)
+      } else if (value === "?") {
+        return cont(typeprop)
+      } else if (type === ":") {
+        return cont(typeexpr)
+      } else if (type === "[") {
+        return cont(expression, null, expect("]"), typeprop)
+      }
+    }
+
+    function typearg(type) {
+      if (type === "variable") return cont(typearg)
+      else if (type === ":") return cont(typeexpr)
+    }
+
+    function afterType(type, value) {
+      if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
+      if (value === "|" || type === ".") return cont(typeexpr)
+      if (type === "[") return cont(expect("]"), afterType)
+      if (value === "extends") return cont(typeexpr)
+    }
+
+    function vardef() {
+      return pass(pattern, null, maybeAssign, vardefCont);
+    }
+
+    function pattern(type, value) {
+      if (type === "modifier") return cont(pattern)
+      if (type === "variable") {
+        register(value);
+        return cont();
+      }
+      if (type === "spread") return cont(pattern);
+      if (type === "[") return contCommasep(pattern, "]");
+      if (type === "{") return contCommasep(proppattern, "}");
+    }
+
+    function proppattern(type, value) {
+      if (type === "variable" && !cx.stream.match(/^\s*:/, false)) {
+        register(value);
+        return cont(maybeAssign);
+      }
+      if (type === "variable") cx.marked = "property";
+      if (type === "spread") return cont(pattern);
+      if (type === "}") return pass();
+      return cont(expect(":"), pattern, maybeAssign);
+    }
+
+    function maybeAssign(_type, value) {
+      if (value === "=") return cont(expressionNoComma);
+    }
+
+    function vardefCont(type) {
+      if (type === ",") return cont(vardef);
+    }
+
+    function maybeelse(type, value) {
+      if (type === "keyword b" && value === "else") return cont(pushlex("form", "else"), statement, poplex);
+    }
+
+    function forspec(type) {
+      if (type === "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
+    }
+
+    function forspec1(type) {
+      if (type === "var") return cont(vardef, expect(";"), forspec2);
+      if (type === ";") return cont(forspec2);
+      if (type === "variable") return cont(formaybeinof);
+      return pass(expression, expect(";"), forspec2);
+    }
+
+    function formaybeinof(_type, value) {
+      if (value === "in" || value === "of") {
+        cx.marked = "keyword";
+        return cont(expression);
+      }
+      return cont(maybeoperatorComma, forspec2);
+    }
+
+    function forspec2(type, value) {
+      if (type === ";") return cont(forspec3);
+      if (value === "in" || value === "of") {
+        cx.marked = "keyword";
+        return cont(expression);
+      }
+      return pass(expression, expect(";"), forspec3);
+    }
+
+    function forspec3(type) {
+      if (type !== ")") cont(expression);
+    }
+
+    function functiondef(type, value) {
+      if (value === "*") {
+        cx.marked = "keyword";
+        return cont(functiondef);
+      }
+      if (type === "variable") {
+        register(value);
+        return cont(functiondef);
+      }
+      if (type === "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, null, statement, popcontext);
+    }
+
+    function funarg(type) {
+      if (type === "spread") return cont(funarg);
+      return pass(pattern, null, maybeAssign);
+    }
+
+    function classExpression(type, value) {
+      // Class expressions may have an optional name.
+      if (type === "variable") return className(type, value);
+      return classNameAfter(type, value);
+    }
+
+    function className(type, value) {
+      if (type === "variable") {
+        register(value);
+        return cont(classNameAfter);
+      }
+    }
+
+    function classNameAfter(type, value) {
+      if (value === "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, classNameAfter)
+      if (value === "extends" || value === "implements")
+        return cont(expression, classNameAfter);
+      if (type === "{") return cont(pushlex("}"), classBody, poplex);
+    }
+
+    function classBody(type, value) {
+      if (type === "variable" || cx.style === "keyword") {
+        if ((value === "async" || value === "static" || value === "get" || value === "set") &&
+          cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
+          cx.marked = "keyword";
+          return cont(classBody);
+        }
+        cx.marked = "property";
+        return cont(functiondef, classBody);
+      }
+      if (type === "[")
+        return cont(expression, expect("]"), functiondef, classBody)
+      if (value === "*") {
+        cx.marked = "keyword";
+        return cont(classBody);
+      }
+      if (type === ";") return cont(classBody);
+      if (type === "}") return cont();
+      if (value === "@") return cont(expression, classBody)
+    }
+
+    function classfield(type, value) {
+      if (value === "?") return cont(classfield)
+      if (type === ":") return cont(typeexpr, maybeAssign)
+      if (value === "=") return cont(expressionNoComma)
+      return pass(functiondef)
+    }
+
+    function afterExport(type, value) {
+      if (value === "*") {
+        cx.marked = "keyword";
+        return cont(maybeFrom, expect(";"));
+      }
+      if (value === "default") {
+        cx.marked = "keyword";
+        return cont(expression, expect(";"));
+      }
+      if (type === "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
+      return pass(statement);
+    }
+
+    function exportField(type, value) {
+      if (value === "as") {
+        cx.marked = "keyword";
+        return cont(expect("variable"));
+      }
+      if (type === "variable") return pass(expressionNoComma, exportField);
+    }
+
+    function afterImport(type) {
+      if (type === "string") return cont();
+      return pass(importSpec, maybeMoreImports, maybeFrom);
+    }
+
+    function importSpec(type, value) {
+      if (type === "{") return contCommasep(importSpec, "}");
+      if (type === "variable") register(value);
+      if (value === "*") cx.marked = "keyword";
+      return cont(maybeAs);
+    }
+
+    function maybeMoreImports(type) {
+      if (type === ",") return cont(importSpec, maybeMoreImports)
+    }
+
+    function maybeAs(_type, value) {
+      if (value === "as") {
+        cx.marked = "keyword";
+        return cont(importSpec);
+      }
+    }
+
+    function maybeFrom(_type, value) {
+      if (value === "from") {
+        cx.marked = "keyword";
+        return cont(expression);
+      }
+    }
+
+    function arrayLiteral(type) {
+      if (type === "]") return cont();
+      return pass(commasep(expressionNoComma, "]"));
+    }
+
+    function isContinuedStatement(state, textAfter) {
+      return state.lastType === "operator" || state.lastType === "," ||
+        isOperatorChar.test(textAfter.charAt(0)) ||
+        /[,.]/.test(textAfter.charAt(0));
+    }
+
+    // Interface
+
+    return {
+      startState: function(basecolumn) {
+        var state = {
+          tokenize: tokenBase,
+          lastType: "sof",
+          cc: [],
+          lexical: new TSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
+          localVars: parserConfig.localVars,
+          context: parserConfig.localVars && {vars: parserConfig.localVars},
+          indented: basecolumn || 0
+        };
+        if (parserConfig.globalVars && typeof parserConfig.globalVars === "object")
+          state.globalVars = parserConfig.globalVars;
+        return state;
+      },
+
+      token: function(stream, state) {
+        if (stream.sol()) {
+          if (!state.lexical.hasOwnProperty("align"))
+            state.lexical.align = false;
+          state.indented = stream.indentation();
+          findFatArrow(stream, state);
+        }
+        if (state.tokenize != tokenComment && stream.eatSpace()) return null;
+        var style = state.tokenize(stream, state);
+        if (type === "comment") return style;
+        state.lastType = type === "operator" && (content === "++" || content === "--") ? "incdec" : type;
+        return parseTS(state, style, type, content, stream);
+      },
+
+      indent: function(state, textAfter) {
+        if (state.tokenize == tokenComment) return CodeMirror.Pass;
+        if (state.tokenize != tokenBase) return 0;
+        var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
+        // Kludge to prevent 'maybelse' from blocking lexical scope pops
+        if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
+          var c = state.cc[i];
+          if (c == poplex) lexical = lexical.prev;
+          else if (c != maybeelse) break;
+        }
+        while ((lexical.type === "stat" || lexical.type === "form") &&
+        (firstChar === "}" || ((top = state.cc[state.cc.length - 1]) &&
+          (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
+          !/^[,\.=+\-*:?[\(]/.test(textAfter))))
+          lexical = lexical.prev;
+        if (statementIndent && lexical.type === ")" && lexical.prev.type === "stat")
+          lexical = lexical.prev;
+        var type = lexical.type, closing = firstChar == type;
+
+        if (type === "vardef") return lexical.indented + (state.lastType === "operator" || state.lastType === "," ? lexical.info + 1 : 0);
+        else if (type === "form" && firstChar === "{") return lexical.indented;
+        else if (type === "form") return lexical.indented + indentUnit;
+        else if (type === "stat")
+          return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
+        else if (lexical.info === "switch" && !closing && parserConfig.doubleIndentSwitch != false)
+          return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
+        else if (lexical.align) return lexical.column + (closing ? 0 : 1);
+        else return lexical.indented + (closing ? 0 : indentUnit);
+      },
+
+      electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
+      blockCommentStart: "/*",
+      blockCommentEnd: "*/",
+      lineComment: "#",
+      fold: "brace",
+      closeBrackets: "()[]{}''\"\"``",
+
+      helperType: "typoscript",
+
+      expressionAllowed: expressionAllowed,
+      skipExpression: function(state) {
+        var top = state.cc[state.cc.length - 1];
+        if (top == expression || top == expressionNoComma) state.cc.pop()
+      }
+    };
+  });
 });
diff --git a/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js b/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js
index 0f074f718395..9012e9cdf549 100644
--- a/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js
+++ b/typo3/sysext/taskcenter/Resources/Public/JavaScript/Taskcenter.js
@@ -15,85 +15,85 @@
  * Module: TYPO3/CMS/Taskcenter/Taskcenter
  */
 define(['jquery',
-		'TYPO3/CMS/Backend/Icons',
-		'jquery-ui/sortable'
-		], function($, Icons) {
-	'use strict';
+  'TYPO3/CMS/Backend/Icons',
+  'jquery-ui/sortable'
+], function($, Icons) {
+  'use strict';
 
-	/**
-	 *
-	 * @type {{}}
-	 * @exports  TYPO3/CMS/Taskcenter/Taskcenter
-	 */
-	var Taskcenter = {};
+  /**
+   *
+   * @type {{}}
+   * @exports  TYPO3/CMS/Taskcenter/Taskcenter
+   */
+  var Taskcenter = {};
 
-	/**
-	 *
-	 * @param {Object} element
-	 * @param {Boolean} isCollapsed
-	 */
-	Taskcenter.collapse = function(element, isCollapsed) {
-		var $item = $(element);
-		var $parent = $item.parent();
-		var $icon = $parent.find('.t3js-taskcenter-header-collapse .t3js-icon');
-		var isCollapsed = isCollapsed;
-		var iconName;
+  /**
+   *
+   * @param {Object} element
+   * @param {Boolean} isCollapsed
+   */
+  Taskcenter.collapse = function(element, isCollapsed) {
+    var $item = $(element);
+    var $parent = $item.parent();
+    var $icon = $parent.find('.t3js-taskcenter-header-collapse .t3js-icon');
+    var isCollapsed = isCollapsed;
+    var iconName;
 
-		if(isCollapsed) {
-			iconName = 'actions-view-list-expand';
-		} else {
-			iconName = 'actions-view-list-collapse';
-		}
-		Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) {
-			$icon.replaceWith(icon);
-		});
+    if (isCollapsed) {
+      iconName = 'actions-view-list-expand';
+    } else {
+      iconName = 'actions-view-list-collapse';
+    }
+    Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function(icon) {
+      $icon.replaceWith(icon);
+    });
 
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['taskcenter_collapse'],
-			type: 'post',
-			cache: false,
-			data: {
-				'item': $parent.data('taskcenterId'),
-				'state': isCollapsed
-			}
-		});
-	};
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['taskcenter_collapse'],
+      type: 'post',
+      cache: false,
+      data: {
+        'item': $parent.data('taskcenterId'),
+        'state': isCollapsed
+      }
+    });
+  };
 
-	/**
-	 *
-	 */
-	Taskcenter.initializeSorting = function() {
-		$('#task-list').sortable({
-			update: function(event, ui) {
-				$.ajax({
-					url: TYPO3.settings.ajaxUrls['taskcenter_sort'],
-					type: 'post',
-					cache: false,
-					data: {
-						'data': $(this).sortable('serialize', {
-							key: 'task-list[]',
-							expression: /[=_](.+)/
-						})
-					}
-				});
-			}
-		});
-	};
+  /**
+   *
+   */
+  Taskcenter.initializeSorting = function() {
+    $('#task-list').sortable({
+      update: function(event, ui) {
+        $.ajax({
+          url: TYPO3.settings.ajaxUrls['taskcenter_sort'],
+          type: 'post',
+          cache: false,
+          data: {
+            'data': $(this).sortable('serialize', {
+              key: 'task-list[]',
+              expression: /[=_](.+)/
+            })
+          }
+        });
+      }
+    });
+  };
 
-	/**
-	 * Register listeners
-	 */
-	Taskcenter.initializeEvents = function() {
-		$('.t3js-taskcenter-collapse').on('show.bs.collapse', function() {
-			Taskcenter.collapse($(this), 0);
-		});
-		$('.t3js-taskcenter-collapse').on('hide.bs.collapse', function() {
-			Taskcenter.collapse($(this), 1);
-		});
-		Taskcenter.initializeSorting();
-	};
+  /**
+   * Register listeners
+   */
+  Taskcenter.initializeEvents = function() {
+    $('.t3js-taskcenter-collapse').on('show.bs.collapse', function() {
+      Taskcenter.collapse($(this), 0);
+    });
+    $('.t3js-taskcenter-collapse').on('hide.bs.collapse', function() {
+      Taskcenter.collapse($(this), 1);
+    });
+    Taskcenter.initializeSorting();
+  };
 
-	$(Taskcenter.initializeEvents);
+  $(Taskcenter.initializeEvents);
 
-	return Taskcenter;
+  return Taskcenter;
 });
diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js
index 07ffc30f46a4..bde86915c945 100644
--- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js
+++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/ConstantEditor.js
@@ -17,88 +17,88 @@
  * e.g. updating the field and working with colors
  */
 define(['jquery'], function($) {
-	'use strict';
+  'use strict';
 
-	/**
-	 *
-	 * @type {{options: {editIconSelector: string, colorSelectSelector: string, colorInputSelector: string}}}
-	 * @exports TYPO3/CMS/Tstemplate/ConstantEditor
-	 */
-	var ConstantEditor = {
-		options: {
-			editIconSelector: '.t3js-toggle',
-			colorSelectSelector: '.t3js-color-select',
-			colorInputSelector: '.t3js-color-input'
-		}
-	};
+  /**
+   *
+   * @type {{options: {editIconSelector: string, colorSelectSelector: string, colorInputSelector: string}}}
+   * @exports TYPO3/CMS/Tstemplate/ConstantEditor
+   */
+  var ConstantEditor = {
+    options: {
+      editIconSelector: '.t3js-toggle',
+      colorSelectSelector: '.t3js-color-select',
+      colorInputSelector: '.t3js-color-input'
+    }
+  };
 
-	/**
-	 * initially register event listeners
-	 *
-	 * @param {Object} $editIcon
-	 */
-	ConstantEditor.changeProperty = function($editIcon) {
-		var constantName = $editIcon.attr('rel');
-		var $defaultDiv = $('#defaultTS-' + constantName);
-		var $userDiv = $('#userTS-' + constantName);
-		var $checkBox = $('#check-' + constantName);
-		var toggleState = $editIcon.data('toggle');
+  /**
+   * initially register event listeners
+   *
+   * @param {Object} $editIcon
+   */
+  ConstantEditor.changeProperty = function($editIcon) {
+    var constantName = $editIcon.attr('rel');
+    var $defaultDiv = $('#defaultTS-' + constantName);
+    var $userDiv = $('#userTS-' + constantName);
+    var $checkBox = $('#check-' + constantName);
+    var toggleState = $editIcon.data('toggle');
 
-		if (toggleState === 'edit') {
-			$defaultDiv.hide();
-			$userDiv.show();
-			$userDiv.find('input').css({background: '#fdf8bd'});
-			$checkBox.attr('disabled', false).attr('checked', true);
-		} else if (toggleState === 'undo') {
-			$userDiv.hide();
-			$defaultDiv.show();
-			$checkBox.val('').attr('disabled', true);
-		}
-	};
+    if (toggleState === 'edit') {
+      $defaultDiv.hide();
+      $userDiv.show();
+      $userDiv.find('input').css({background: '#fdf8bd'});
+      $checkBox.attr('disabled', false).attr('checked', true);
+    } else if (toggleState === 'undo') {
+      $userDiv.hide();
+      $defaultDiv.show();
+      $checkBox.val('').attr('disabled', true);
+    }
+  };
 
-	/**
-	 * updates the color from a dropdown
-	 *
-	 * @param {Object} $colorSelect
-	 */
-	ConstantEditor.updateColorFromSelect = function($colorSelect) {
-		var constantName = $colorSelect.attr('rel');
-		var colorValue = $colorSelect.val();
+  /**
+   * updates the color from a dropdown
+   *
+   * @param {Object} $colorSelect
+   */
+  ConstantEditor.updateColorFromSelect = function($colorSelect) {
+    var constantName = $colorSelect.attr('rel');
+    var colorValue = $colorSelect.val();
 
-		$('#input-' + constantName).val(colorValue);
-		$('#colorbox-' + constantName).css({background: colorValue});
-	};
+    $('#input-' + constantName).val(colorValue);
+    $('#colorbox-' + constantName).css({background: colorValue});
+  };
 
-	/**
-	 * updates the color from an input field
-	 *
-	 * @param {Object} $colorInput
-	 */
-	ConstantEditor.updateColorFromInput = function($colorInput) {
-		var constantName = $colorInput.attr('rel');
-		var colorValue = $colorInput.val();
+  /**
+   * updates the color from an input field
+   *
+   * @param {Object} $colorInput
+   */
+  ConstantEditor.updateColorFromInput = function($colorInput) {
+    var constantName = $colorInput.attr('rel');
+    var colorValue = $colorInput.val();
 
-		$('#colorbox-' + constantName).css({background: colorValue});
-		$('#select-' + constantName).children().each(function(option) {
-			option.selected = (option.value === colorValue);
-		});
-	};
+    $('#colorbox-' + constantName).css({background: colorValue});
+    $('#select-' + constantName).children().each(function(option) {
+      option.selected = (option.value === colorValue);
+    });
+  };
 
-	/**
-	 * Registers listeners
-	 */
-	ConstantEditor.initializeEvents = function() {
-		// no DOMready needed since only events for document are registered
-		$(document).on('click', ConstantEditor.options.editIconSelector, function() {
-			ConstantEditor.changeProperty($(this));
-		}).on('change', ConstantEditor.options.colorSelectSelector, function() {
-			ConstantEditor.updateColorFromSelect($(this));
-		}).on('blur', ConstantEditor.options.colorInputSelector, function() {
-			ConstantEditor.updateColorFromInput($(this));
-		});
-	};
+  /**
+   * Registers listeners
+   */
+  ConstantEditor.initializeEvents = function() {
+    // no DOMready needed since only events for document are registered
+    $(document).on('click', ConstantEditor.options.editIconSelector, function() {
+      ConstantEditor.changeProperty($(this));
+    }).on('change', ConstantEditor.options.colorSelectSelector, function() {
+      ConstantEditor.updateColorFromSelect($(this));
+    }).on('blur', ConstantEditor.options.colorInputSelector, function() {
+      ConstantEditor.updateColorFromInput($(this));
+    });
+  };
 
-	ConstantEditor.initializeEvents();
+  ConstantEditor.initializeEvents();
 
-	return ConstantEditor;
+  return ConstantEditor;
 });
diff --git a/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js b/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js
index 6891c3c00beb..0850afe2c8bf 100644
--- a/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js
+++ b/typo3/sysext/tstemplate/Resources/Public/JavaScript/TypoScriptObjectBrowser.js
@@ -18,19 +18,19 @@
  */
 define(['jquery', 'TYPO3/CMS/Backend/jquery.clearable'], function($) {
 
-	var $searchFields = $('input[name="search_field"]');
-	var searchResultShown = ('' !== $searchFields.first().val());
+  var $searchFields = $('input[name="search_field"]');
+  var searchResultShown = ('' !== $searchFields.first().val());
 
-	// make search field clearable
-	$searchFields.clearable({
-		onClear: function() {
-			if (searchResultShown) {
-				$(this).closest('form').submit();
-			}
-		}
-	});
+  // make search field clearable
+  $searchFields.clearable({
+    onClear: function() {
+      if (searchResultShown) {
+        $(this).closest('form').submit();
+      }
+    }
+  });
 
-	if (self.location.hash) {
-		window.scrollTo(window.pageXOffset, window.pageYOffset - 40);
-	}
+  if (self.location.hash) {
+    window.scrollTo(window.pageXOffset, window.pageYOffset - 40);
+  }
 });
diff --git a/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js b/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js
index e66ed546c1f3..590259ab1526 100644
--- a/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js
+++ b/typo3/sysext/viewpage/Resources/Public/JavaScript/Main.js
@@ -15,255 +15,255 @@
  * Main logic for resizing the view of the frame
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Storage/Persistent',
-	'jquery-ui/resizable'
+  'jquery',
+  'TYPO3/CMS/Backend/Storage/Persistent',
+  'jquery-ui/resizable'
 ], function($, PersistentStorage) {
-	'use strict';
-
-	/**
-	 * @type {{<resizableContainerIdentifier: string, sizeIdentifier: string, moduleBodySelector: string, storagePrefix: string, $iframe: null, $resizableContainer: null, $sizeSelector: null}}
-	 * @exports TYPO3/CMS/Viewpage/Main
-	 */
-	var ViewPage = {
-
-		resizableContainerIdentifier: '.t3js-viewpage-resizeable',
-		sizeIdentifier: ' .t3js-viewpage-size',
-		moduleBodySelector: '.t3js-module-body',
-
-		defaultLabel: $('.t3js-preset-custom-label').html().trim(),
-		minimalHeight: 300,
-		minimalWidth: 300,
-
-		storagePrefix: 'moduleData.web_view.States.',
-		$iframe: null,
-		$resizableContainer: null,
-		$sizeSelector: null,
-
-		customSelector: '.t3js-preset-custom',
-		customWidthSelector: '.t3js-preset-custom-width',
-		customHeightSelector: '.t3js-preset-custom-height',
-
-		changeOrientationSelector: '.t3js-change-orientation',
-		changePresetSelector: '.t3js-change-preset',
-
-		inputWidthSelector: '.t3js-viewpage-input-width',
-		inputHeightSelector: '.t3js-viewpage-input-height',
-
-		currentLabelSelector: '.t3js-viewpage-current-label',
-		topbarContainerSelector: '.t3js-viewpage-topbar',
-
-		queue: [],
-		queueIsRunning: false,
-		queueDelayTimer: null
-
-	};
-
-	ViewPage.persistQueue = function() {
-		if (ViewPage.queueIsRunning === false && ViewPage.queue.length >= 1) {
-			ViewPage.queueIsRunning = true;
-			var item = ViewPage.queue.shift();
-			PersistentStorage.set(item.storageIdentifier, item.data).done(function() {
-				ViewPage.queueIsRunning = false;
-				ViewPage.persistQueue();
-			});
-		}
-	}
-
-	ViewPage.addToQueue = function(storageIdentifier, data) {
-		var item = {
-			'storageIdentifier': storageIdentifier,
-			'data': data
-		};
-		ViewPage.queue.push(item);
-		if (ViewPage.queue.length >= 1) {
-			ViewPage.persistQueue();
-		}
-	}
-
-	ViewPage.setSize = function(width, height) {
-		if (isNaN(height)) {
-			height = ViewPage.calculateContainerMaxHeight();
-		}
-		if (height < ViewPage.minimalHeight) {
-			height = ViewPage.minimalHeight;
-		}
-		if (isNaN(width)) {
-			width = ViewPage.calculateContainerMaxWidth();
-		}
-		if (width < ViewPage.minimalWidth) {
-			width = ViewPage.minimalWidth;
-		}
-
-		$(ViewPage.inputWidthSelector).val(width);
-		$(ViewPage.inputHeightSelector).val(height);
-
-		ViewPage.$resizableContainer.css({
-			width: width,
-			height: height,
-			left: 0
-		});
-	}
-
-	ViewPage.getCurrentWidth = function() {
-		return $(ViewPage.inputWidthSelector).val();
-	}
-
-	ViewPage.getCurrentHeight = function() {
-		return $(ViewPage.inputHeightSelector).val();
-	}
-
-	ViewPage.setLabel = function(label) {
-		$(ViewPage.currentLabelSelector).html(label);
-	}
-
-	ViewPage.getCurrentLabel = function() {
-		return $(ViewPage.currentLabelSelector).html().trim();
-	}
-
-	ViewPage.persistCurrentPreset = function() {
-		var data = {
-			width: ViewPage.getCurrentWidth(),
-			height: ViewPage.getCurrentHeight(),
-			label: ViewPage.getCurrentLabel()
-		}
-		ViewPage.addToQueue(ViewPage.storagePrefix + 'current', data);
-	}
-
-	ViewPage.persistCustomPreset = function() {
-		var data = {
-			width: ViewPage.getCurrentWidth(),
-			height: ViewPage.getCurrentHeight()
-		}
-		$(ViewPage.customSelector).data("width", data.width);
-		$(ViewPage.customSelector).data("height", data.height);
-		$(ViewPage.customWidthSelector).html(data.width);
-		$(ViewPage.customHeightSelector).html(data.height);
-		ViewPage.addToQueue(ViewPage.storagePrefix + 'custom', data);
-	}
-
-	ViewPage.persistCustomPresetAfterChange = function() {
-		clearTimeout(ViewPage.queueDelayTimer);
-		ViewPage.queueDelayTimer = setTimeout(function() {
-			ViewPage.persistCustomPreset();
-		}, 1000);
-	};
-
-	/**
-	 * Initialize
-	 */
-	ViewPage.initialize = function() {
-
-		ViewPage.$iframe = $('#tx_viewpage_iframe');
-		ViewPage.$resizableContainer = $(ViewPage.resizableContainerIdentifier);
-		ViewPage.$sizeSelector = $(ViewPage.sizeIdentifier);
-
-		// Change orientation
-		$(document).on('click', ViewPage.changeOrientationSelector, function() {
-			var width = $(ViewPage.inputHeightSelector).val();
-			var height = $(ViewPage.inputWidthSelector).val();
-			ViewPage.setSize(width, height);
-			ViewPage.persistCurrentPreset();
-		});
-
-		// On change
-		$(document).on('change', ViewPage.inputWidthSelector, function() {
-			var width = $(ViewPage.inputWidthSelector).val();
-			var height = $(ViewPage.inputHeightSelector).val();
-			ViewPage.setSize(width, height);
-			ViewPage.setLabel(ViewPage.defaultLabel);
-			ViewPage.persistCustomPresetAfterChange();
-		});
-		$(document).on('change', ViewPage.inputHeightSelector, function() {
-			var width = $(ViewPage.inputWidthSelector).val();
-			var height = $(ViewPage.inputHeightSelector).val();
-			ViewPage.setSize(width, height);
-			ViewPage.setLabel(ViewPage.defaultLabel);
-			ViewPage.persistCustomPresetAfterChange();
-		});
-
-		// Add event to width selector so the container is resized
-		$(document).on('click', ViewPage.changePresetSelector, function() {
-			var data = $(this).data();
-			ViewPage.setSize(parseInt(data.width), parseInt(data.height));
-			ViewPage.setLabel(data.label);
-			ViewPage.persistCurrentPreset();
-		});
-
-		// Initialize the jQuery UI Resizable plugin
-		ViewPage.$resizableContainer.resizable({
-			handles: 'w, sw, s, se, e'
-		});
-
-		ViewPage.$resizableContainer.on('resizestart', function() {
-			// Add iframe overlay to prevent losing the mouse focus to the iframe while resizing fast
-			$(this).append('<div id="viewpage-iframe-cover" style="z-index:99;position:absolute;width:100%;top:0;left:0;height:100%;"></div>');
-		});
-
-		ViewPage.$resizableContainer.on('resize', function(evt, ui) {
-			ui.size.width = ui.originalSize.width + ((ui.size.width - ui.originalSize.width) * 2);
-			if (ui.size.height < ViewPage.minimalHeight) {
-				ui.size.height = ViewPage.minimalHeight;
-			}
-			if (ui.size.width < ViewPage.minimalWidth) {
-				ui.size.width = ViewPage.minimalWidth;
-			}
-			$(ViewPage.inputWidthSelector).val(ui.size.width);
-			$(ViewPage.inputHeightSelector).val(ui.size.height);
-			ViewPage.$resizableContainer.css({
-				left: 0
-			});
-			ViewPage.setLabel(ViewPage.defaultLabel);
-		});
-
-		ViewPage.$resizableContainer.on('resizestop', function() {
-			$('#viewpage-iframe-cover').remove();
-			ViewPage.persistCurrentPreset();
-			ViewPage.persistCustomPreset();
-		});
-	};
-
-	/**
-	 * @returns {Number}
-	 */
-	ViewPage.calculateContainerMaxHeight = function() {
-		ViewPage.$resizableContainer.hide();
-		var $moduleBody = $(ViewPage.moduleBodySelector);
-		var padding = $moduleBody.outerHeight() - $moduleBody.height(),
-			documentHeight = $(document).height(),
-			topbarHeight = $(ViewPage.topbarContainerSelector).outerHeight();
-		ViewPage.$resizableContainer.show();
-		return documentHeight - padding - topbarHeight - 8;
-	};
-
-	/**
-	 * @returns {Number}
-	 */
-	ViewPage.calculateContainerMaxWidth = function() {
-		ViewPage.$resizableContainer.hide();
-		var $moduleBody = $(ViewPage.moduleBodySelector);
-		var padding = $moduleBody.outerWidth() - $moduleBody.width(),
-			documentWidth = $(document).width();
-		ViewPage.$resizableContainer.show();
-		return parseInt(documentWidth - padding);
-	};
-
-	/**
-	 * @param {String} url
-	 * @returns {{}}
-	 */
-	ViewPage.getUrlVars = function(url) {
-		var vars = {};
-		var hash;
-		var hashes = url.slice(url.indexOf('?') + 1).split('&');
-		for (var i = 0; i < hashes.length; i ++) {
-			hash = hashes[i].split('=');
-			vars[hash[0]] = hash[1];
-		}
-		return vars;
-	};
-
-	$(ViewPage.initialize);
-
-	return ViewPage;
+  'use strict';
+
+  /**
+   * @type {{<resizableContainerIdentifier: string, sizeIdentifier: string, moduleBodySelector: string, storagePrefix: string, $iframe: null, $resizableContainer: null, $sizeSelector: null}}
+   * @exports TYPO3/CMS/Viewpage/Main
+   */
+  var ViewPage = {
+
+    resizableContainerIdentifier: '.t3js-viewpage-resizeable',
+    sizeIdentifier: ' .t3js-viewpage-size',
+    moduleBodySelector: '.t3js-module-body',
+
+    defaultLabel: $('.t3js-preset-custom-label').html().trim(),
+    minimalHeight: 300,
+    minimalWidth: 300,
+
+    storagePrefix: 'moduleData.web_view.States.',
+    $iframe: null,
+    $resizableContainer: null,
+    $sizeSelector: null,
+
+    customSelector: '.t3js-preset-custom',
+    customWidthSelector: '.t3js-preset-custom-width',
+    customHeightSelector: '.t3js-preset-custom-height',
+
+    changeOrientationSelector: '.t3js-change-orientation',
+    changePresetSelector: '.t3js-change-preset',
+
+    inputWidthSelector: '.t3js-viewpage-input-width',
+    inputHeightSelector: '.t3js-viewpage-input-height',
+
+    currentLabelSelector: '.t3js-viewpage-current-label',
+    topbarContainerSelector: '.t3js-viewpage-topbar',
+
+    queue: [],
+    queueIsRunning: false,
+    queueDelayTimer: null
+
+  };
+
+  ViewPage.persistQueue = function() {
+    if (ViewPage.queueIsRunning === false && ViewPage.queue.length >= 1) {
+      ViewPage.queueIsRunning = true;
+      var item = ViewPage.queue.shift();
+      PersistentStorage.set(item.storageIdentifier, item.data).done(function() {
+        ViewPage.queueIsRunning = false;
+        ViewPage.persistQueue();
+      });
+    }
+  }
+
+  ViewPage.addToQueue = function(storageIdentifier, data) {
+    var item = {
+      'storageIdentifier': storageIdentifier,
+      'data': data
+    };
+    ViewPage.queue.push(item);
+    if (ViewPage.queue.length >= 1) {
+      ViewPage.persistQueue();
+    }
+  }
+
+  ViewPage.setSize = function(width, height) {
+    if (isNaN(height)) {
+      height = ViewPage.calculateContainerMaxHeight();
+    }
+    if (height < ViewPage.minimalHeight) {
+      height = ViewPage.minimalHeight;
+    }
+    if (isNaN(width)) {
+      width = ViewPage.calculateContainerMaxWidth();
+    }
+    if (width < ViewPage.minimalWidth) {
+      width = ViewPage.minimalWidth;
+    }
+
+    $(ViewPage.inputWidthSelector).val(width);
+    $(ViewPage.inputHeightSelector).val(height);
+
+    ViewPage.$resizableContainer.css({
+      width: width,
+      height: height,
+      left: 0
+    });
+  }
+
+  ViewPage.getCurrentWidth = function() {
+    return $(ViewPage.inputWidthSelector).val();
+  }
+
+  ViewPage.getCurrentHeight = function() {
+    return $(ViewPage.inputHeightSelector).val();
+  }
+
+  ViewPage.setLabel = function(label) {
+    $(ViewPage.currentLabelSelector).html(label);
+  }
+
+  ViewPage.getCurrentLabel = function() {
+    return $(ViewPage.currentLabelSelector).html().trim();
+  }
+
+  ViewPage.persistCurrentPreset = function() {
+    var data = {
+      width: ViewPage.getCurrentWidth(),
+      height: ViewPage.getCurrentHeight(),
+      label: ViewPage.getCurrentLabel()
+    }
+    ViewPage.addToQueue(ViewPage.storagePrefix + 'current', data);
+  }
+
+  ViewPage.persistCustomPreset = function() {
+    var data = {
+      width: ViewPage.getCurrentWidth(),
+      height: ViewPage.getCurrentHeight()
+    }
+    $(ViewPage.customSelector).data("width", data.width);
+    $(ViewPage.customSelector).data("height", data.height);
+    $(ViewPage.customWidthSelector).html(data.width);
+    $(ViewPage.customHeightSelector).html(data.height);
+    ViewPage.addToQueue(ViewPage.storagePrefix + 'custom', data);
+  }
+
+  ViewPage.persistCustomPresetAfterChange = function() {
+    clearTimeout(ViewPage.queueDelayTimer);
+    ViewPage.queueDelayTimer = setTimeout(function() {
+      ViewPage.persistCustomPreset();
+    }, 1000);
+  };
+
+  /**
+   * Initialize
+   */
+  ViewPage.initialize = function() {
+
+    ViewPage.$iframe = $('#tx_viewpage_iframe');
+    ViewPage.$resizableContainer = $(ViewPage.resizableContainerIdentifier);
+    ViewPage.$sizeSelector = $(ViewPage.sizeIdentifier);
+
+    // Change orientation
+    $(document).on('click', ViewPage.changeOrientationSelector, function() {
+      var width = $(ViewPage.inputHeightSelector).val();
+      var height = $(ViewPage.inputWidthSelector).val();
+      ViewPage.setSize(width, height);
+      ViewPage.persistCurrentPreset();
+    });
+
+    // On change
+    $(document).on('change', ViewPage.inputWidthSelector, function() {
+      var width = $(ViewPage.inputWidthSelector).val();
+      var height = $(ViewPage.inputHeightSelector).val();
+      ViewPage.setSize(width, height);
+      ViewPage.setLabel(ViewPage.defaultLabel);
+      ViewPage.persistCustomPresetAfterChange();
+    });
+    $(document).on('change', ViewPage.inputHeightSelector, function() {
+      var width = $(ViewPage.inputWidthSelector).val();
+      var height = $(ViewPage.inputHeightSelector).val();
+      ViewPage.setSize(width, height);
+      ViewPage.setLabel(ViewPage.defaultLabel);
+      ViewPage.persistCustomPresetAfterChange();
+    });
+
+    // Add event to width selector so the container is resized
+    $(document).on('click', ViewPage.changePresetSelector, function() {
+      var data = $(this).data();
+      ViewPage.setSize(parseInt(data.width), parseInt(data.height));
+      ViewPage.setLabel(data.label);
+      ViewPage.persistCurrentPreset();
+    });
+
+    // Initialize the jQuery UI Resizable plugin
+    ViewPage.$resizableContainer.resizable({
+      handles: 'w, sw, s, se, e'
+    });
+
+    ViewPage.$resizableContainer.on('resizestart', function() {
+      // Add iframe overlay to prevent losing the mouse focus to the iframe while resizing fast
+      $(this).append('<div id="viewpage-iframe-cover" style="z-index:99;position:absolute;width:100%;top:0;left:0;height:100%;"></div>');
+    });
+
+    ViewPage.$resizableContainer.on('resize', function(evt, ui) {
+      ui.size.width = ui.originalSize.width + ((ui.size.width - ui.originalSize.width) * 2);
+      if (ui.size.height < ViewPage.minimalHeight) {
+        ui.size.height = ViewPage.minimalHeight;
+      }
+      if (ui.size.width < ViewPage.minimalWidth) {
+        ui.size.width = ViewPage.minimalWidth;
+      }
+      $(ViewPage.inputWidthSelector).val(ui.size.width);
+      $(ViewPage.inputHeightSelector).val(ui.size.height);
+      ViewPage.$resizableContainer.css({
+        left: 0
+      });
+      ViewPage.setLabel(ViewPage.defaultLabel);
+    });
+
+    ViewPage.$resizableContainer.on('resizestop', function() {
+      $('#viewpage-iframe-cover').remove();
+      ViewPage.persistCurrentPreset();
+      ViewPage.persistCustomPreset();
+    });
+  };
+
+  /**
+   * @returns {Number}
+   */
+  ViewPage.calculateContainerMaxHeight = function() {
+    ViewPage.$resizableContainer.hide();
+    var $moduleBody = $(ViewPage.moduleBodySelector);
+    var padding = $moduleBody.outerHeight() - $moduleBody.height(),
+      documentHeight = $(document).height(),
+      topbarHeight = $(ViewPage.topbarContainerSelector).outerHeight();
+    ViewPage.$resizableContainer.show();
+    return documentHeight - padding - topbarHeight - 8;
+  };
+
+  /**
+   * @returns {Number}
+   */
+  ViewPage.calculateContainerMaxWidth = function() {
+    ViewPage.$resizableContainer.hide();
+    var $moduleBody = $(ViewPage.moduleBodySelector);
+    var padding = $moduleBody.outerWidth() - $moduleBody.width(),
+      documentWidth = $(document).width();
+    ViewPage.$resizableContainer.show();
+    return parseInt(documentWidth - padding);
+  };
+
+  /**
+   * @param {String} url
+   * @returns {{}}
+   */
+  ViewPage.getUrlVars = function(url) {
+    var vars = {};
+    var hash;
+    var hashes = url.slice(url.indexOf('?') + 1).split('&');
+    for (var i = 0; i < hashes.length; i++) {
+      hash = hashes[i].split('=');
+      vars[hash[0]] = hash[1];
+    }
+    return vars;
+  };
+
+  $(ViewPage.initialize);
+
+  return ViewPage;
 });
diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js
index bd3dfd542747..b5f344f540c0 100644
--- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js
+++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Backend.js
@@ -16,1176 +16,1213 @@
  * RequireJS module for the workspace backend module
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Workspaces/Workspaces',
-	'TYPO3/CMS/Backend/Tooltip',
-	'TYPO3/CMS/Backend/Severity',
-	'TYPO3/CMS/Backend/Modal',
-	'TYPO3/CMS/Backend/Wizard',
-	'nprogress',
-	'TYPO3/CMS/Backend/jquery.clearable'
+  'jquery',
+  'TYPO3/CMS/Workspaces/Workspaces',
+  'TYPO3/CMS/Backend/Tooltip',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Modal',
+  'TYPO3/CMS/Backend/Wizard',
+  'nprogress',
+  'TYPO3/CMS/Backend/jquery.clearable'
 ], function($, Workspaces, Tooltip, Severity, Modal, Wizard, NProgress) {
-	'use strict';
-
-	var Backend = {
-		workspaceTitle: '',
-		identifiers: {
-			searchForm: '#workspace-settings-form',
-			searchTextField: '#workspace-settings-form input[name="search-text"]',
-			searchSubmitBtn: '#workspace-settings-form button[type="submit"]',
-			depthSelector: '#workspace-settings-form [name="depth"]',
-			languageSelector: '#workspace-settings-form select[name="languages"]',
-			actionForm: '#workspace-actions-form',
-			chooseStageAction: '#workspace-actions-form [name="stage-action"]',
-			chooseSelectionAction: '#workspace-actions-form [name="selection-action"]',
-			chooseMassAction: '#workspace-actions-form [name="mass-action"]',
-			container: '#workspace-panel',
-			actionIcons: '#workspace-action-icons',
-			toggleAll: '.t3js-toggle-all',
-			previewLinksButton: '.t3js-preview-link',
-			pagination: '#workspace-pagination'
-		},
-		settings: {
-			depth: TYPO3.settings.Workspaces.depth,
-			dir: 'ASC',
-			id: TYPO3.settings.Workspaces.id,
-			language: TYPO3.settings.Workspaces.language,
-			limit: 30,
-			query: '',
-			sort: 'label_Live',
-			start: 0,
-			filterTxt: ''
-		},
-		paging: {
-			currentPage: 1,
-			totalPages: 1,
-			totalItems: 0
-		},
-		allToggled: false,
-		elements: {}, // filled in Backend.getElements()
-		latestPath: '',
-		markedRecordsForMassAction: [],
-		indentationPadding: 26
-	};
-
-	Backend.initialize = function() {
-		Backend.getElements();
-		Backend.registerEvents();
-
-		if (TYPO3.settings.Workspaces.depth > 0) {
-			Backend.elements.$depthSelector.val(TYPO3.settings.Workspaces.depth);
-		}
-
-		Backend.loadWorkspaceComponents();
-	};
-
-	Backend.getElements = function() {
-		Backend.elements.$searchForm = $(Backend.identifiers.searchForm);
-		Backend.elements.$searchTextField = $(Backend.identifiers.searchTextField);
-		Backend.elements.$searchSubmitBtn = $(Backend.identifiers.searchSubmitBtn);
-		Backend.elements.$depthSelector = $(Backend.identifiers.depthSelector);
-		Backend.elements.$languageSelector = $(Backend.identifiers.languageSelector);
-		Backend.elements.$container = $(Backend.identifiers.container);
-		Backend.elements.$tableBody = Backend.elements.$container.find('tbody');
-		Backend.elements.$actionIcons = $(Backend.identifiers.actionIcons);
-		Backend.elements.$toggleAll =  $(Backend.identifiers.toggleAll);
-		Backend.elements.$chooseStageAction = $(Backend.identifiers.chooseStageAction);
-		Backend.elements.$chooseSelectionAction = $(Backend.identifiers.chooseSelectionAction);
-		Backend.elements.$chooseMassAction = $(Backend.identifiers.chooseMassAction);
-		Backend.elements.$previewLinksButton = $(Backend.identifiers.previewLinksButton);
-		Backend.elements.$pagination = $(Backend.identifiers.pagination);
-	};
-
-	Backend.registerEvents = function() {
-		$(document).on('click', '[data-action="swap"]', function(e) {
-			var $tr = $(e.target).closest('tr');
-			Workspaces.checkIntegrity(
-				{
-					selection: [
-						{
-							liveId: $tr.data('uid'),
-							versionId: $tr.data('t3ver_oid'),
-							table: $tr.data('table')
-						}
-					],
-					type: 'selection'
-				}
-			).done(function(response) {
-				if (response[0].result.result === 'warning') {
-					Backend.addIntegrityCheckWarningToWizard();
-				}
-
-				Wizard.setup.forceSelection = false;
-				Wizard.addSlide(
-					'swap-confirm',
-					'Swap',
-					TYPO3.lang['window.swap.message'],
-					Severity.info
-				);
-				Wizard.addFinalProcessingSlide(function() {
-					// We passed this slide, swap the record now
-					Workspaces.sendRemoteRequest(
-						Workspaces.generateRemoteActionsPayload('swapSingleRecord', [
-							$tr.data('table'),
-							$tr.data('t3ver_oid'),
-							$tr.data('uid')
-						])
-					).done(function() {
-						Wizard.dismiss();
-						Backend.getWorkspaceInfos();
-						Backend.refreshPageTree();
-					});
-				}).done(function() {
-					Wizard.show();
-				});
-			});
-		}).on('click', '[data-action="prevstage"]', function(e) {
-			Backend.sendToStage($(e.target).closest('tr'), 'prev');
-		}).on('click', '[data-action="nextstage"]', function(e) {
-			Backend.sendToStage($(e.target).closest('tr'), 'next');
-		}).on('click', '[data-action="changes"]', Backend.viewChanges
-		).on('click', '[data-action="preview"]', Backend.openPreview
-		).on('click', '[data-action="open"]', function(e) {
-			var $tr = $(e.target).closest('tr'),
-				newUrl = TYPO3.settings.FormEngine.moduleUrl + '&returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + $tr.data('table') + '][' + $tr.data('uid') + ']=edit';
-
-			// Append workspace of record in all-workspaces view
-			if (TYPO3.settings.Workspaces.allView) {
-				newUrl += '&workspace=' + $tr.data('t3ver_wsid');
-			}
-			window.location.href = newUrl;
-		}).on('click', '[data-action="version"]', function(e) {
-			var $tr = $(e.target).closest('tr');
-			if ($tr.data('table') === 'pages') {
-				top.loadEditId($tr.data('t3ver_oid'));
-			} else {
-				top.loadEditId($tr.data('pid'));
-			}
-		}).on('click', '[data-action="remove"]', Backend.confirmDeleteRecordFromWorkspace
-		).on('click', '[data-action="expand"]', function(e) {
-			var $me = $(this),
-				$target = Backend.elements.$tableBody.find($me.data('target')),
-				iconIdentifier;
-
-			if ($target.first().attr('aria-expanded') === 'true') {
-				iconIdentifier = 'apps-pagetree-expand';
-			} else {
-				iconIdentifier = 'apps-pagetree-collapse';
-			}
-
-			$me.html(Backend.getPreRenderedIcon(iconIdentifier));
-		});
-
-		Backend.elements.$searchForm.on('submit', function(e) {
-			e.preventDefault();
-			Backend.settings.filterTxt = Backend.elements.$searchTextField.val();
-			Backend.getWorkspaceInfos();
-		});
-
-		Backend.elements.$searchTextField.on('keyup', function() {
-			var $me = $(this);
-
-			if ($me.val() !== '') {
-				Backend.elements.$searchSubmitBtn.removeClass('disabled');
-			} else {
-				Backend.elements.$searchSubmitBtn.addClass('disabled');
-				Backend.getWorkspaceInfos();
-			}
-		}).clearable(
-			{
-				onClear: function() {
-					Backend.elements.$searchSubmitBtn.addClass('disabled');
-					Backend.settings.filterTxt = '';
-					Backend.getWorkspaceInfos();
-				}
-			}
-		);
-
-		// checkboxes in the table
-		Backend.elements.$toggleAll.on('click', function() {
-			Backend.allToggled = !Backend.allToggled;
-			Backend.elements.$tableBody.find('input[type="checkbox"]').prop('checked', Backend.allToggled).trigger('change');
-		});
-		Backend.elements.$tableBody.on('change', 'tr input[type=checkbox]', Backend.handleCheckboxChange);
-
-		// Listen for depth changes
-		Backend.elements.$depthSelector.on('change', function(e) {
-			var $me = $(this);
-			Backend.settings.depth = $me.val();
-
-			Backend.getWorkspaceInfos();
-		});
-
-		// Generate preview links
-		Backend.elements.$previewLinksButton.on('click', Backend.generatePreviewLinks);
-
-		// Listen for language changes
-		Backend.elements.$languageSelector.on('change', function(e) {
-			var $me = $(this);
-			Backend.settings.language = $me.val();
-
-			Workspaces.sendRemoteRequest([
-				Workspaces.generateRemoteActionsPayload('saveLanguageSelection', [$me.val()]),
-				Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
-			]).done(function(response) {
-				Backend.elements.$languageSelector.prev().html($me.find(':selected').data('icon'));
-				Backend.renderWorkspaceInfos(response[1].result);
-			});
-		});
-
-		// Listen for actions
-		Backend.elements.$chooseStageAction.on('change', Backend.sendToSpecificStageAction);
-		Backend.elements.$chooseSelectionAction.on('change', Backend.runSelectionAction);
-		Backend.elements.$chooseMassAction.on('change', Backend.runMassAction);
-
-		// clicking an action in the paginator
-		Backend.elements.$pagination.on('click', 'a[data-action]', function(e) {
-			e.preventDefault();
-
-			var $el = $(this),
-				reload = false;
-
-			switch ($el.data('action')) {
-				case 'previous':
-					if (Backend.paging.currentPage > 1) {
-						Backend.paging.currentPage--;
-						reload = true;
-					}
-					break;
-				case 'next':
-					if (Backend.paging.currentPage < Backend.paging.totalPages) {
-						Backend.paging.currentPage++;
-						reload = true;
-					}
-					break;
-				case 'page':
-					Backend.paging.currentPage = parseInt($el.data('page'));
-					reload = true;
-					break;
-			}
-
-			if (reload) {
-				// Adjust settings
-				Backend.settings.start = Backend.settings.limit * (Backend.paging.currentPage - 1);
-				Backend.getWorkspaceInfos();
-			}
-		});
-	};
-
-	Backend.handleCheckboxChange = function(e) {
-		var $checkbox = $(this),
-			$tr = $checkbox.parents('tr'),
-			table = $tr.data('table'),
-			uid = $tr.data('uid'),
-			t3ver_oid = $tr.data('t3ver_oid'),
-			record = table + ':' + uid + ':' + t3ver_oid;
-
-		if ($checkbox.prop('checked')) {
-			Backend.markedRecordsForMassAction.push(record);
-			$tr.addClass('warning');
-		} else {
-			var index = Backend.markedRecordsForMassAction.indexOf(record);
-			if (index > -1) {
-				Backend.markedRecordsForMassAction.splice(index, 1);
-			}
-			$tr.removeClass('warning');
-		}
-
-		Backend.elements.$chooseStageAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0);
-		Backend.elements.$chooseSelectionAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0);
-		Backend.elements.$chooseMassAction.prop('disabled', Backend.markedRecordsForMassAction.length > 0);
-	};
-
-	/**
-	 * Generates the diff view of a record
-	 *
-	 * @param {Object} diff
-	 * @return {$}
-	 */
-	Backend.generateDiffView = function(diff) {
-		var $diff = $('<div />', {class: 'diff'});
-
-		for (var i = 0; i < diff.length; ++i) {
-			$diff.append(
-				$('<div />', {class: 'diff-item'}).append(
-					$('<div />', {class: 'diff-item-title'}).text(diff[i].label),
-					$('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(diff[i].content)
-				)
-			);
-		}
-		return $diff;
-	};
-
-	/**
-	 * Generates the comments view of a record
-	 *
-	 * @param {Object} comments
-	 * @return {$}
-	 */
-	Backend.generateCommentView = function(comments) {
-		var $comments = $('<div />');
-
-		for (var i = 0; i < comments.length; ++i) {
-			var $panel = $('<div />', {class: 'panel panel-default'});
-
-			if (comments[i].user_comment.length > 0) {
-				$panel.append(
-					$('<div />', {class: 'panel-body'}).html(comments[i].user_comment)
-				);
-			}
-
-			$panel.append(
-				$('<div />', {class: 'panel-footer'}).append(
-					$('<span />', {class: 'label label-success'}).text(comments[i].stage_title),
-					$('<span />', {class: 'label label-info'}).text(comments[i].tstamp)
-				)
-			);
-
-			$comments.append(
-				$('<div />', {class: 'media'}).append(
-					$('<div />', {class: 'media-left text-center'}).text(comments[i].user_username).prepend(
-						$('<div />').html(comments[i].user_avatar)
-					),
-					$('<div />', {class: 'media-body'}).append($panel)
-				)
-			);
-		}
-
-		return $comments;
-	};
-
-	/**
-	 * Sends a record to a stage
-	 *
-	 * @param {Object} $row
-	 * @param {String} direction
-	 */
-	Backend.sendToStage = function($row, direction) {
-		var nextStage,
-			stageWindowAction,
-			stageExecuteAction;
-
-		if (direction === 'next') {
-			nextStage = $row.data('nextStage');
-			stageWindowAction = 'sendToNextStageWindow';
-			stageExecuteAction = 'sendToNextStageExecute';
-		} else if (direction === 'prev') {
-			nextStage = $row.data('prevStage');
-			stageWindowAction = 'sendToPrevStageWindow';
-			stageExecuteAction = 'sendToPrevStageExecute';
-		} else {
-			throw 'Invalid direction given.';
-		}
-
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemoteActionsPayload(stageWindowAction, [
-				$row.data('uid'), $row.data('table'), $row.data('t3ver_oid')
-			])
-		).done(function(response) {
-			var $modal = Workspaces.renderSendToStageWindow(response);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'ok') {
-					var $form = $(e.currentTarget).find('form'),
-						serializedForm = $form.serializeObject();
-
-					serializedForm.affects = {
-						table: $row.data('table'),
-						nextStage: nextStage,
-						t3ver_oid: $row.data('t3ver_oid'),
-						uid: $row.data('uid'),
-						elements: []
-					};
-
-					Workspaces.sendRemoteRequest([
-						Workspaces.generateRemoteActionsPayload(stageExecuteAction, [serializedForm]),
-						Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
-					]).done(function(response) {
-						$modal.modal('hide');
-						Backend.renderWorkspaceInfos(response[1].result);
-						Backend.refreshPageTree();
-					});
-				}
-			});
-		});
-	};
-
-	/**
-	 * Loads the workspace components, like available stage actions and items of the workspace
-	 */
-	Backend.loadWorkspaceComponents = function() {
-		Workspaces.sendRemoteRequest([
-			Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings),
-			Workspaces.generateRemotePayload('getStageActions', {}),
-			Workspaces.generateRemoteMassActionsPayload('getMassStageActions', {}),
-			Workspaces.generateRemotePayload('getSystemLanguages', {})
-		]).done(function(response) {
-			Backend.elements.$depthSelector.prop('disabled', false);
-
-			// Records
-			Backend.renderWorkspaceInfos(response[0].result);
-
-			// Stage actions
-			var stageActions = response[1].result.data,
-				i;
-			for (i = 0; i < stageActions.length; ++i) {
-				Backend.elements.$chooseStageAction.append(
-					$('<option />').val(stageActions[i].uid).text(stageActions[i].title)
-				);
-			}
-
-			// Mass actions
-			var massActions = response[2].result.data;
-			for (i = 0; i < massActions.length; ++i) {
-				Backend.elements.$chooseSelectionAction.append(
-					$('<option />').val(massActions[i].action).text(massActions[i].title)
-				);
-
-				Backend.elements.$chooseMassAction.append(
-					$('<option />').val(massActions[i].action).text(massActions[i].title)
-				);
-			}
-
-			// Languages
-			var languages = response[3].result.data;
-			for (i = 0; i < languages.length; ++i) {
-				var $option = $('<option />').val(languages[i].uid).text(languages[i].title).data('icon', languages[i].icon);
-				if (String(languages[i].uid) === String(TYPO3.settings.Workspaces.language)) {
-					$option.prop('selected', true);
-					Backend.elements.$languageSelector.prev().html(languages[i].icon);
-				}
-				Backend.elements.$languageSelector.append($option);
-			}
-			Backend.elements.$languageSelector.prop('disabled', false);
-		});
-	};
-
-	/**
-	 * Gets the workspace infos
-	 *
-	 * @return {Promise}
-	 * @protected
-	 */
-	Backend.getWorkspaceInfos = function() {
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
-		).done(function(response) {
-			Backend.renderWorkspaceInfos(response[0].result);
-		});
-	};
-
-	/**
-	 * Renders fetched workspace informations
-	 *
-	 * @param {Object} result
-	 */
-	Backend.renderWorkspaceInfos = function(result) {
-		Backend.elements.$tableBody.children().remove();
-		Backend.allToggled = false;
-		Backend.elements.$chooseStageAction.prop('disabled', true);
-		Backend.elements.$chooseSelectionAction.prop('disabled', true);
-		Backend.elements.$chooseMassAction.prop('disabled', result.data.length === 0);
-
-		Backend.buildPagination(result.total);
-
-		for (var i = 0; i < result.data.length; ++i) {
-			var item = result.data[i],
-				$actions = $('<div />', {class: 'btn-group'}),
-				$integrityIcon = '';
-			$actions.append(
-				Backend.getAction(item.Workspaces_CollectionChildren > 0 && item.Workspaces_CollectionCurrent !== '', 'expand', 'apps-pagetree-collapse').attr('title', TYPO3.lang['tooltip.expand']).attr('data-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]').attr('data-toggle', 'collapse'),
-				$('<button />', {class: 'btn btn-default', 'data-action': 'changes', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.showChanges']}).append(Backend.getPreRenderedIcon('actions-document-info')),
-				Backend.getAction(item.allowedAction_swap && item.Workspaces_CollectionParent === '', 'swap', 'actions-version-swap-version').attr('title', TYPO3.lang['tooltip.swap']),
-				Backend.getAction(item.allowedAction_view, 'preview', 'actions-version-workspace-preview').attr('title', TYPO3.lang['tooltip.viewElementAction']),
-				$('<button />', {class: 'btn btn-default', 'data-action': 'open', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.editElementAction']}).append(Backend.getPreRenderedIcon('actions-open')),
-				$('<button />', {class: 'btn btn-default', 'data-action': 'version', 'data-toggle': 'tooltip', title: TYPO3.lang['tooltip.openPage']}).append(Backend.getPreRenderedIcon('actions-version-page-open')),
-				Backend.getAction(item.allowedAction_delete, 'remove', 'actions-version-document-remove').attr('title', TYPO3.lang['tooltip.discardVersion']),
-				$('<label />', {class: 'btn btn-default btn-checkbox'}).append(
-					$('<input />', {type: 'checkbox'}),
-					$('<span />', {class: 't3-icon fa'})
-				)
-			);
-
-			if (item.integrity.messages !== '') {
-				$integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]);
-				$integrityIcon
-					.attr('data-toggle', 'tooltip')
-					.attr('data-placement', 'top')
-					.attr('data-html', true)
-					.attr('title', item.integrity.messages);
-			}
-
-			if (Backend.latestPath !== item.path_Workspace) {
-				Backend.latestPath = item.path_Workspace;
-				Backend.elements.$tableBody.append(
-					$('<tr />').append(
-						$('<th />', {colspan: 6}).text(Backend.latestPath)
-					)
-				);
-			}
-
-			var rowConfiguration = {
-				'data-uid': item.uid,
-				'data-pid': item.livepid,
-				'data-t3ver_oid': item.t3ver_oid,
-				'data-t3ver_wsid': item.t3ver_wsid,
-				'data-table': item.table,
-				'data-next-stage': item.value_nextStage,
-				'data-prev-stage': item.value_prevStage,
-				'data-stage': item.stage
-			};
-
-			if (item.Workspaces_CollectionParent !== '') {
-				rowConfiguration['data-collection'] = item.Workspaces_CollectionParent;
-				rowConfiguration['class'] = 'collapse';
-			}
-
-			Backend.elements.$tableBody.append(
-				$('<tr />', rowConfiguration).append(
-					$('<td />', {class: 't3js-title-workspace', style: item.Workspaces_CollectionLevel > 0 ? 'padding-left: ' + Backend.indentationPadding * item.Workspaces_CollectionLevel + 'px' : ''}).html(item.icon_Workspace + '&nbsp;' + '<a href="#" data-action="changes"><span class="item-state-' + item.state_Workspace + '">' + item.label_Workspace + '</span></a>'),
-					$('<td />', {class: 't3js-title-live'}).html(item.icon_Live + '&nbsp;' + item.label_Live),
-					$('<td />').text(item.label_Stage),
-					$('<td />').html($integrityIcon),
-					$('<td />').html(item.language.icon),
-					$('<td />', {class: 'text-right nowrap'}).append($actions)
-				)
-			);
-
-			Tooltip.initialize('[data-toggle="tooltip"]', {
-				delay: {
-					show: 500,
-					hide: 100
-				},
-				trigger: 'hover',
-				container: 'body'
-			});
-		}
-	};
-
-	/**
-	 * Renders the pagination
-	 *
-	 * @param {Number} totalItems
-	 */
-	Backend.buildPagination = function(totalItems) {
-		if (totalItems === 0) {
-			Backend.elements.$pagination.contents().remove();
-			return;
-		}
-
-		Backend.paging.totalItems = totalItems;
-		Backend.paging.totalPages = Math.ceil(totalItems / Backend.settings.limit);
-
-		if (Backend.paging.totalPages === 1) {
-			// early abort if only one page is available
-			Backend.elements.$pagination.contents().remove();
-			return;
-		}
-
-		var $ul = $('<ul />', {class: 'pagination pagination-block'}),
-			liElements = [],
-			$controlFirstPage = $('<li />').append(
-				$('<a />', {'data-action': 'previous'}).append(
-					$('<span />', {class: 't3-icon fa fa-arrow-left'})
-				)
-			),
-			$controlLastPage = $('<li />').append(
-				$('<a />', {'data-action': 'next'}).append(
-					$('<span />', {class: 't3-icon fa fa-arrow-right'})
-				)
-			);
-
-		if (Backend.paging.currentPage === 1) {
-			$controlFirstPage.disablePagingAction();
-		}
-
-		if (Backend.paging.currentPage === Backend.paging.totalPages) {
-			$controlLastPage.disablePagingAction();
-		}
-
-		for (var i = 1; i <= Backend.paging.totalPages; i++) {
-			var $li = $('<li />', {class: Backend.paging.currentPage === i ? 'active' : ''});
-			$li.append(
-				$('<a />', {'data-action': 'page', 'data-page': i}).append(
-					$('<span />').text(i)
-				)
-			);
-			liElements.push($li);
-		}
-
-		$ul.append($controlFirstPage, liElements, $controlLastPage);
-		Backend.elements.$pagination.html($ul);
-	};
-
-	/**
-	 * View changes of a record
-	 *
-	 * @param {Event} e
-	 */
-	Backend.viewChanges = function(e) {
-		e.preventDefault();
-
-		var $tr = $(e.target).closest('tr');
-
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemotePayload('getRowDetails', {
-				stage: $tr.data('stage'),
-				t3ver_oid: $tr.data('t3ver_oid'),
-				table: $tr.data('table'),
-				uid: $tr.data('uid')
-			})
-		).done(function(response) {
-			var item = response[0].result.data[0],
-				$content = $('<div />'),
-				$tabsNav = $('<ul />', {class: 'nav nav-tabs', role: 'tablist'}),
-				$tabsContent = $('<div />', {class: 'tab-content'}),
-				modalButtons = [];
-
-			$content.append(
-				$('<p />').html(TYPO3.lang['path'].replace('{0}', item.path_Live)),
-				$('<p />').html(TYPO3.lang['current_step'].replace('{0}', item.label_Stage).replace('{1}', item.stage_position).replace('{2}', item.stage_count))
-			);
-
-			if (item.diff.length > 0) {
-				$tabsNav.append(
-					$('<li />', {role: 'presentation'}).append(
-						$('<a />', {href: '#workspace-changes', 'aria-controls': 'workspace-changes', role: 'tab', 'data-toggle': 'tab'}).text(TYPO3.lang['window.recordChanges.tabs.changeSummary'])
-					)
-				);
-				$tabsContent.append(
-					$('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-changes'}).append(
-						$('<div />', {class: 'form-section'}).append(
-							Backend.generateDiffView(item.diff)
-						)
-					)
-				);
-			}
-
-			if (item.comments.length > 0) {
-				$tabsNav.append(
-					$('<li />', {role: 'presentation'}).append(
-						$('<a />', {href: '#workspace-comments', 'aria-controls': 'workspace-comments', role: 'tab', 'data-toggle': 'tab'}).html(TYPO3.lang['window.recordChanges.tabs.comments'] + '&nbsp;').append(
-							$('<span />', {class: 'badge'}).text(item.comments.length)
-						)
-					)
-				);
-				$tabsContent.append(
-					$('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-comments'}).append(
-						$('<div />', {class: 'form-section'}).append(
-							Backend.generateCommentView(item.comments)
-						)
-					)
-				);
-			}
-
-			if (item.history.total > 0) {
-				$tabsNav.append(
-					$('<li />', {role: 'presentation'}).append(
-						$('<a />', {href: '#workspace-history', 'aria-controls': 'workspace-history', role: 'tab', 'data-toggle': 'tab'}).text(TYPO3.lang['window.recordChanges.tabs.history'])
-					)
-				);
-
-				$tabsContent.append(
-					$('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-history'}).append(
-						$('<div />', {class: 'form-section'}).append(
-							Backend.generateHistoryView(item.history.data)
-						)
-					)
-				);
-			}
-
-			// Mark the first tab and pane as active
-			$tabsNav.find('li').first().addClass('active');
-			$tabsContent.find('.tab-pane').first().addClass('active');
-
-			// Attach tabs
-			$content.append(
-				$('<div />').append(
-					$tabsNav,
-					$tabsContent
-				)
-			);
-
-			if ($tr.data('stage') !== $tr.data('prevStage')) {
-				modalButtons.push({
-					text: item.label_PrevStage.title,
-					active: true,
-					btnClass: 'btn-default',
-					name: 'prevstage',
-					trigger: function () {
-						Modal.currentModal.trigger('modal-dismiss');
-						Backend.sendToStage($(e.target).closest('tr'), 'prev');
-					}
-				});
-			}
-
-			modalButtons.push({
-				text: item.label_NextStage.title,
-				active: true,
-				btnClass: 'btn-default',
-				name: 'nextstage',
-				trigger: function () {
-					Modal.currentModal.trigger('modal-dismiss');
-					Backend.sendToStage($(e.target).closest('tr'), 'next');
-				}
-			});
-			modalButtons.push({
-				text: TYPO3.lang['close'],
-				active: true,
-				btnClass: 'btn-info',
-				name: 'cancel',
-				trigger: function () {
-					Modal.currentModal.trigger('modal-dismiss');
-				}
-			});
-
-			Modal.show(
-				TYPO3.lang['window.recordInformation'].replace('{0}', $.trim($tr.find('.t3js-title-live').text())),
-				$content,
-				Severity.info,
-				modalButtons
-			);
-		});
-	};
-
-	/**
-	 * Opens a record in a preview window
-	 *
-	 * @param {Event} e
-	 */
-	Backend.openPreview = function(e) {
-		var $tr = $(e.target).closest('tr');
-
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemoteActionsPayload('viewSingleRecord', [
-				$tr.data('table'), $tr.data('uid')
-			])
-		).done(function(response) {
-			eval(response[0].result);
-		});
-	};
-
-	/**
-	 * Renders the record's history
-	 *
-	 * @param {Object} data
-	 */
-	Backend.generateHistoryView = function(data) {
-		var $history = $('<div />');
-
-		for (var i = 0; i < data.length; ++i) {
-			var $panel = $('<div />', {class: 'panel panel-default'}),
-				$diff;
-
-			if (typeof data[i].differences === 'object') {
-				if (data[i].differences.length === 0) {
-					// Somehow here are no differences. What a pity, skip that record
-					continue;
-				}
-				$diff = $('<div />', {class: 'diff'});
-
-				for (var j = 0; j < data[i].differences.length; ++j) {
-					$diff.append(
-						$('<div />', {class: 'diff-item'}).append(
-							$('<div />', {class: 'diff-item-title'}).text(data[i].differences[j].label),
-							$('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(data[i].differences[j].html)
-						)
-					);
-				}
-
-				$panel.append(
-					$('<div />').append($diff)
-				);
-			} else {
-				$panel.append(
-					$('<div />', {class: 'panel-body'}).text(data[i].differences)
-				);
-			}
-			$panel.append(
-				$('<div />', {class: 'panel-footer'}).append(
-					$('<span />', {class: 'label label-info'}).text(data[i].datetime)
-				)
-			);
-
-			$history.append(
-				$('<div />', {class: 'media'}).append(
-					$('<div />', {class: 'media-left text-center'}).text(data[i].user).prepend(
-						$('<div />').html(data[i].user_avatar)
-					),
-					$('<div />', {class: 'media-body'}).append($panel)
-				)
-			);
-		}
-
-		return $history;
-	};
-
-	/**
-	 * Shows a confirmation modal and deletes the selected record from workspace.
-	 *
-	 * @param {Event} e
-	 */
-	Backend.confirmDeleteRecordFromWorkspace = function(e) {
-		var $tr = $(e.target).closest('tr');
-		var $modal = Modal.confirm(
-			TYPO3.lang['window.discard.title'],
-			TYPO3.lang['window.discard.message'],
-			Severity.warning,
-			[
-				{
-					text: TYPO3.lang['cancel'],
-					active: true,
-					btnClass: 'btn-default',
-					name: 'cancel',
-					trigger: function() {
-						$modal.modal('hide');
-					}
-				}, {
-					text: TYPO3.lang['ok'],
-					btnClass: 'btn-warning',
-					name: 'ok'
-				}
-			]
-		);
-		$modal.on('button.clicked', function(e) {
-			if (e.target.name === 'ok') {
-				Workspaces.sendRemoteRequest([
-					Workspaces.generateRemoteActionsPayload('deleteSingleRecord', [
-						$tr.data('table'),
-						$tr.data('uid')
-					])
-				]).done(function() {
-					$modal.modal('hide');
-					Backend.getWorkspaceInfos();
-					Backend.refreshPageTree();
-				});
-			}
-		});
-	};
-
-	/**
-	 * Runs a mass action
-	 */
-	Backend.runSelectionAction = function() {
-		var selectedAction = Backend.elements.$chooseSelectionAction.val(),
-			integrityCheckRequired = selectedAction !== 'discard';
-
-		if (selectedAction.length === 0) {
-			// Don't do anything if that value is empty
-			return;
-		}
-
-		var affectedRecords = [];
-		for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) {
-			var affected = Backend.markedRecordsForMassAction[i].split(':');
-			affectedRecords.push({
-				table: affected[0],
-				liveId: affected[2],
-				versionId: affected[1]
-			});
-		}
-
-		if (!integrityCheckRequired) {
-			Wizard.setup.forceSelection = false;
-			Backend.renderSelectionActionWizard(selectedAction, affectedRecords);
-		} else {
-			Workspaces.checkIntegrity(
-				{
-					selection: affectedRecords,
-					type: 'selection'
-				}
-			).done(function(response) {
-				Wizard.setup.forceSelection = false;
-				if (response[0].result.result === 'warning') {
-					Backend.addIntegrityCheckWarningToWizard();
-				}
-				Backend.renderSelectionActionWizard(selectedAction, affectedRecords);
-			});
-		}
-	};
-
-	/**
-	 * Adds a slide to the wizard concerning an integrity check warning.
-	 */
-	Backend.addIntegrityCheckWarningToWizard = function() {
-		Wizard.addSlide(
-			'integrity-warning',
-			'Warning',
-			TYPO3.lang['integrity.hasIssuesDescription'] + '<br>' + TYPO3.lang['integrity.hasIssuesQuestion'],
-			Severity.warning
-		);
-	};
-
-	/**
-	 * Renders the wizard for selection actions
-	 *
-	 * @param {String} selectedAction
-	 * @param {Object} affectedRecords
-	 */
-	Backend.renderSelectionActionWizard = function(selectedAction, affectedRecords) {
-		Wizard.addSlide(
-			'mass-action-confirmation',
-			TYPO3.lang['window.selectionAction.title'],
-			$('<p />').text(TYPO3.lang['tooltip.' + selectedAction + 'Selected']),
-			Severity.warning
-		);
-		Wizard.addFinalProcessingSlide(function() {
-			Workspaces.sendRemoteRequest(
-				Workspaces.generateRemoteActionsPayload('executeSelectionAction', {
-					action: selectedAction,
-					selection: affectedRecords
-				})
-			).done(function() {
-				Backend.getWorkspaceInfos();
-				Wizard.dismiss();
-				Backend.refreshPageTree();
-			});
-		}).done(function() {
-			Wizard.show();
-
-			Wizard.getComponent().on('wizard-dismissed', function() {
-				Backend.elements.$chooseSelectionAction.val('');
-			});
-		});
-	};
-
-	/**
-	 * Runs a mass action
-	 */
-	Backend.runMassAction = function() {
-		var selectedAction = Backend.elements.$chooseMassAction.val(),
-			integrityCheckRequired = selectedAction !== 'discard';
-
-		if (selectedAction.length === 0) {
-			// Don't do anything if that value is empty
-			return;
-		}
-
-		if (!integrityCheckRequired) {
-			Wizard.setup.forceSelection = false;
-			Backend.renderMassActionWizard(selectedAction);
-		} else {
-			Workspaces.checkIntegrity(
-				{
-					language: Backend.settings.language,
-					type: selectedAction
-				}
-			).done(function(response) {
-				Wizard.setup.forceSelection = false;
-				if (response[0].result.result === 'warning') {
-					Backend.addIntegrityCheckWarningToWizard();
-				}
-				Backend.renderMassActionWizard(selectedAction);
-			});
-		}
-	};
-
-	/**
-	 * Renders the wizard for mass actions
-	 *
-	 * @param {String} selectedAction
-	 */
-	Backend.renderMassActionWizard = function(selectedAction) {
-		var massAction,
-			doSwap = false;
-
-		switch (selectedAction) {
-			case 'publish':
-				massAction = 'publishWorkspace';
-				break;
-			case 'swap':
-				massAction = 'publishWorkspace';
-				doSwap = true;
-				break;
-			case 'discard':
-				massAction = 'flushWorkspace';
-				break;
-		}
-
-		if (massAction === null) {
-			throw 'Invalid mass action ' + selectedAction + ' called.';
-		}
-
-		Wizard.setup.forceSelection = false;
-		Wizard.addSlide(
-			'mass-action-confirmation',
-			TYPO3.lang['window.massAction.title'],
-			$('<p />').html(TYPO3.lang['tooltip.' + selectedAction + 'All'] + '<br><br>' + TYPO3.lang['tooltip.affectWholeWorkspace']),
-			Severity.warning
-		);
-		Wizard.addFinalProcessingSlide(function() {
-			Workspaces.sendRemoteRequest(
-				Workspaces.generateRemoteMassActionsPayload(massAction, {
-					init: true,
-					total: 0,
-					processed: 0,
-					language: Backend.settings.language,
-					swap: doSwap
-				})
-			).done(function(response) {
-				var payload = response[0].result;
-				Workspaces.sendRemoteRequest(
-					Workspaces.generateRemoteMassActionsPayload(massAction, payload)
-				).done(function() {
-					Backend.getWorkspaceInfos();
-					Wizard.dismiss();
-				});
-			});
-		}).done(function() {
-			Wizard.show();
-
-			Wizard.getComponent().on('wizard-dismissed', function() {
-				Backend.elements.$chooseMassAction.val('');
-			});
-		});
-	};
-
-	/**
-	 * Sends marked records to a stage
-	 *
-	 * @param {Event} e
-	 */
-	Backend.sendToSpecificStageAction = function(e) {
-		var affectedRecords = [],
-			stage = $(e.currentTarget).val();
-		for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) {
-			var affected = Backend.markedRecordsForMassAction[i].split(':');
-			affectedRecords.push({
-				table: affected[0],
-				uid: affected[1],
-				t3ver_oid: affected[2]
-			});
-		}
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemoteActionsPayload('sendToSpecificStageWindow', [
-				stage, affectedRecords
-			])
-		).done(function(response) {
-			var $modal = Workspaces.renderSendToStageWindow(response);
-			$modal.on('button.clicked', function(e) {
-				if (e.target.name === 'ok') {
-					var $form = $(e.currentTarget).find('form'),
-						serializedForm = $form.serializeObject();
-
-					serializedForm.affects = {
-						elements: affectedRecords,
-						nextStage: stage
-					};
-
-					Workspaces.sendRemoteRequest([
-						Workspaces.generateRemoteActionsPayload('sendToSpecificStageExecute', [serializedForm]),
-						Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
-					]).done(function(response) {
-						$modal.modal('hide');
-						Backend.renderWorkspaceInfos(response[1].result);
-						Backend.refreshPageTree();
-					});
-				}
-			}).on('modal-destroyed', function() {
-				Backend.elements.$chooseStageAction.val('');
-			});
-		});
-	};
-
-	/**
-	 * Reloads the page tree
-	 */
-	Backend.refreshPageTree = function() {
-		if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
-			top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-		}
-	};
-
-	/**
-	 * Renders the action button based on the user's permission.
-	 *
-	 * @returns {$}
-	 * @private
-	 */
-	Backend.getAction = function(condition, action, iconIdentifier) {
-		if (condition) {
-			return $('<button />', {class: 'btn btn-default', 'data-action': action, 'data-toggle': 'tooltip'}).append(Backend.getPreRenderedIcon(iconIdentifier))
-		}
-		return $('<span />', {class: 'btn btn-default disabled'}).append(Backend.getPreRenderedIcon('empty-empty'));
-	};
-
-	/**
-	 * Fetches and renders available preview links
-	 */
-	Backend.generatePreviewLinks = function() {
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemoteActionsPayload('generateWorkspacePreviewLinksForAllLanguages', [
-				Backend.settings.id
-			])
-		).done(function(response) {
-			var result = response[0].result,
-			$list = $('<dl />');
-
-			$.each(result, function(language, url) {
-				$list.append(
-					$('<dt />').text(language),
-					$('<dd />').append(
-						$('<a />', {href: url, target: '_blank'}).text(url)
-					)
-				);
-			});
-
-			Modal.show(
-				TYPO3.lang['previewLink'],
-				$list,
-				Severity.info,
-				[{
-					text: TYPO3.lang['ok'],
-					active: true,
-					btnClass: 'btn-info',
-					name: 'ok',
-					trigger: function() {
-						Modal.currentModal.trigger('modal-dismiss');
-					}
-				}],
-				['modal-inner-scroll']
-			);
-		});
-	};
-
-	/**
-	 * Gets the pre-rendered icon
-	 * This method is intended to be dropped once we use Fluid's StandaloneView.
-	 *
-	 * @param {String} identifier
-	 * @returns {$}
-	 */
-	Backend.getPreRenderedIcon = function(identifier) {
-		return Backend.elements.$actionIcons.find('[data-identifier="' + identifier + '"]').clone();
-	};
-
-	/**
-	 * Serialize a form to a JavaScript object
-	 *
-	 * @see http://stackoverflow.com/a/1186309/4828813
-	 * @return {Object}
-	 */
-	$.fn.serializeObject = function() {
-		var o = {};
-		var a = this.serializeArray();
-		$.each(a, function() {
-			if (typeof o[this.name] !== 'undefined') {
-				if (!o[this.name].push) {
-					o[this.name] = [o[this.name]];
-				}
-				o[this.name].push(this.value || '');
-			} else {
-				o[this.name] = this.value || '';
-			}
-		});
-		return o;
-	};
-
-	/**
-	 * Changes the markup of a pagination action being disabled
-	 */
-	$.fn.disablePagingAction = function() {
-		$(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />'));
-	};
-
-	$(Backend.initialize);
+  'use strict';
+
+  var Backend = {
+    workspaceTitle: '',
+    identifiers: {
+      searchForm: '#workspace-settings-form',
+      searchTextField: '#workspace-settings-form input[name="search-text"]',
+      searchSubmitBtn: '#workspace-settings-form button[type="submit"]',
+      depthSelector: '#workspace-settings-form [name="depth"]',
+      languageSelector: '#workspace-settings-form select[name="languages"]',
+      actionForm: '#workspace-actions-form',
+      chooseStageAction: '#workspace-actions-form [name="stage-action"]',
+      chooseSelectionAction: '#workspace-actions-form [name="selection-action"]',
+      chooseMassAction: '#workspace-actions-form [name="mass-action"]',
+      container: '#workspace-panel',
+      actionIcons: '#workspace-action-icons',
+      toggleAll: '.t3js-toggle-all',
+      previewLinksButton: '.t3js-preview-link',
+      pagination: '#workspace-pagination'
+    },
+    settings: {
+      depth: TYPO3.settings.Workspaces.depth,
+      dir: 'ASC',
+      id: TYPO3.settings.Workspaces.id,
+      language: TYPO3.settings.Workspaces.language,
+      limit: 30,
+      query: '',
+      sort: 'label_Live',
+      start: 0,
+      filterTxt: ''
+    },
+    paging: {
+      currentPage: 1,
+      totalPages: 1,
+      totalItems: 0
+    },
+    allToggled: false,
+    elements: {}, // filled in Backend.getElements()
+    latestPath: '',
+    markedRecordsForMassAction: [],
+    indentationPadding: 26
+  };
+
+  Backend.initialize = function() {
+    Backend.getElements();
+    Backend.registerEvents();
+
+    if (TYPO3.settings.Workspaces.depth > 0) {
+      Backend.elements.$depthSelector.val(TYPO3.settings.Workspaces.depth);
+    }
+
+    Backend.loadWorkspaceComponents();
+  };
+
+  Backend.getElements = function() {
+    Backend.elements.$searchForm = $(Backend.identifiers.searchForm);
+    Backend.elements.$searchTextField = $(Backend.identifiers.searchTextField);
+    Backend.elements.$searchSubmitBtn = $(Backend.identifiers.searchSubmitBtn);
+    Backend.elements.$depthSelector = $(Backend.identifiers.depthSelector);
+    Backend.elements.$languageSelector = $(Backend.identifiers.languageSelector);
+    Backend.elements.$container = $(Backend.identifiers.container);
+    Backend.elements.$tableBody = Backend.elements.$container.find('tbody');
+    Backend.elements.$actionIcons = $(Backend.identifiers.actionIcons);
+    Backend.elements.$toggleAll = $(Backend.identifiers.toggleAll);
+    Backend.elements.$chooseStageAction = $(Backend.identifiers.chooseStageAction);
+    Backend.elements.$chooseSelectionAction = $(Backend.identifiers.chooseSelectionAction);
+    Backend.elements.$chooseMassAction = $(Backend.identifiers.chooseMassAction);
+    Backend.elements.$previewLinksButton = $(Backend.identifiers.previewLinksButton);
+    Backend.elements.$pagination = $(Backend.identifiers.pagination);
+  };
+
+  Backend.registerEvents = function() {
+    $(document).on('click', '[data-action="swap"]', function(e) {
+      var $tr = $(e.target).closest('tr');
+      Workspaces.checkIntegrity(
+        {
+          selection: [
+            {
+              liveId: $tr.data('uid'),
+              versionId: $tr.data('t3ver_oid'),
+              table: $tr.data('table')
+            }
+          ],
+          type: 'selection'
+        }
+      ).done(function(response) {
+        if (response[0].result.result === 'warning') {
+          Backend.addIntegrityCheckWarningToWizard();
+        }
+
+        Wizard.setup.forceSelection = false;
+        Wizard.addSlide(
+          'swap-confirm',
+          'Swap',
+          TYPO3.lang['window.swap.message'],
+          Severity.info
+        );
+        Wizard.addFinalProcessingSlide(function() {
+          // We passed this slide, swap the record now
+          Workspaces.sendRemoteRequest(
+            Workspaces.generateRemoteActionsPayload('swapSingleRecord', [
+              $tr.data('table'),
+              $tr.data('t3ver_oid'),
+              $tr.data('uid')
+            ])
+          ).done(function() {
+            Wizard.dismiss();
+            Backend.getWorkspaceInfos();
+            Backend.refreshPageTree();
+          });
+        }).done(function() {
+          Wizard.show();
+        });
+      });
+    }).on('click', '[data-action="prevstage"]', function(e) {
+      Backend.sendToStage($(e.target).closest('tr'), 'prev');
+    }).on('click', '[data-action="nextstage"]', function(e) {
+      Backend.sendToStage($(e.target).closest('tr'), 'next');
+    }).on('click', '[data-action="changes"]', Backend.viewChanges
+    ).on('click', '[data-action="preview"]', Backend.openPreview
+    ).on('click', '[data-action="open"]', function(e) {
+      var $tr = $(e.target).closest('tr'),
+        newUrl = TYPO3.settings.FormEngine.moduleUrl + '&returnUrl=' + encodeURIComponent(document.location.href) + '&id=' + TYPO3.settings.Workspaces.id + '&edit[' + $tr.data('table') + '][' + $tr.data('uid') + ']=edit';
+
+      // Append workspace of record in all-workspaces view
+      if (TYPO3.settings.Workspaces.allView) {
+        newUrl += '&workspace=' + $tr.data('t3ver_wsid');
+      }
+      window.location.href = newUrl;
+    }).on('click', '[data-action="version"]', function(e) {
+      var $tr = $(e.target).closest('tr');
+      if ($tr.data('table') === 'pages') {
+        top.loadEditId($tr.data('t3ver_oid'));
+      } else {
+        top.loadEditId($tr.data('pid'));
+      }
+    }).on('click', '[data-action="remove"]', Backend.confirmDeleteRecordFromWorkspace
+    ).on('click', '[data-action="expand"]', function(e) {
+      var $me = $(this),
+        $target = Backend.elements.$tableBody.find($me.data('target')),
+        iconIdentifier;
+
+      if ($target.first().attr('aria-expanded') === 'true') {
+        iconIdentifier = 'apps-pagetree-expand';
+      } else {
+        iconIdentifier = 'apps-pagetree-collapse';
+      }
+
+      $me.html(Backend.getPreRenderedIcon(iconIdentifier));
+    });
+
+    Backend.elements.$searchForm.on('submit', function(e) {
+      e.preventDefault();
+      Backend.settings.filterTxt = Backend.elements.$searchTextField.val();
+      Backend.getWorkspaceInfos();
+    });
+
+    Backend.elements.$searchTextField.on('keyup', function() {
+      var $me = $(this);
+
+      if ($me.val() !== '') {
+        Backend.elements.$searchSubmitBtn.removeClass('disabled');
+      } else {
+        Backend.elements.$searchSubmitBtn.addClass('disabled');
+        Backend.getWorkspaceInfos();
+      }
+    }).clearable(
+      {
+        onClear: function() {
+          Backend.elements.$searchSubmitBtn.addClass('disabled');
+          Backend.settings.filterTxt = '';
+          Backend.getWorkspaceInfos();
+        }
+      }
+    );
+
+    // checkboxes in the table
+    Backend.elements.$toggleAll.on('click', function() {
+      Backend.allToggled = !Backend.allToggled;
+      Backend.elements.$tableBody.find('input[type="checkbox"]').prop('checked', Backend.allToggled).trigger('change');
+    });
+    Backend.elements.$tableBody.on('change', 'tr input[type=checkbox]', Backend.handleCheckboxChange);
+
+    // Listen for depth changes
+    Backend.elements.$depthSelector.on('change', function(e) {
+      var $me = $(this);
+      Backend.settings.depth = $me.val();
+
+      Backend.getWorkspaceInfos();
+    });
+
+    // Generate preview links
+    Backend.elements.$previewLinksButton.on('click', Backend.generatePreviewLinks);
+
+    // Listen for language changes
+    Backend.elements.$languageSelector.on('change', function(e) {
+      var $me = $(this);
+      Backend.settings.language = $me.val();
+
+      Workspaces.sendRemoteRequest([
+        Workspaces.generateRemoteActionsPayload('saveLanguageSelection', [$me.val()]),
+        Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
+      ]).done(function(response) {
+        Backend.elements.$languageSelector.prev().html($me.find(':selected').data('icon'));
+        Backend.renderWorkspaceInfos(response[1].result);
+      });
+    });
+
+    // Listen for actions
+    Backend.elements.$chooseStageAction.on('change', Backend.sendToSpecificStageAction);
+    Backend.elements.$chooseSelectionAction.on('change', Backend.runSelectionAction);
+    Backend.elements.$chooseMassAction.on('change', Backend.runMassAction);
+
+    // clicking an action in the paginator
+    Backend.elements.$pagination.on('click', 'a[data-action]', function(e) {
+      e.preventDefault();
+
+      var $el = $(this),
+        reload = false;
+
+      switch ($el.data('action')) {
+        case 'previous':
+          if (Backend.paging.currentPage > 1) {
+            Backend.paging.currentPage--;
+            reload = true;
+          }
+          break;
+        case 'next':
+          if (Backend.paging.currentPage < Backend.paging.totalPages) {
+            Backend.paging.currentPage++;
+            reload = true;
+          }
+          break;
+        case 'page':
+          Backend.paging.currentPage = parseInt($el.data('page'));
+          reload = true;
+          break;
+      }
+
+      if (reload) {
+        // Adjust settings
+        Backend.settings.start = Backend.settings.limit * (Backend.paging.currentPage - 1);
+        Backend.getWorkspaceInfos();
+      }
+    });
+  };
+
+  Backend.handleCheckboxChange = function(e) {
+    var $checkbox = $(this),
+      $tr = $checkbox.parents('tr'),
+      table = $tr.data('table'),
+      uid = $tr.data('uid'),
+      t3ver_oid = $tr.data('t3ver_oid'),
+      record = table + ':' + uid + ':' + t3ver_oid;
+
+    if ($checkbox.prop('checked')) {
+      Backend.markedRecordsForMassAction.push(record);
+      $tr.addClass('warning');
+    } else {
+      var index = Backend.markedRecordsForMassAction.indexOf(record);
+      if (index > -1) {
+        Backend.markedRecordsForMassAction.splice(index, 1);
+      }
+      $tr.removeClass('warning');
+    }
+
+    Backend.elements.$chooseStageAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0);
+    Backend.elements.$chooseSelectionAction.prop('disabled', Backend.markedRecordsForMassAction.length === 0);
+    Backend.elements.$chooseMassAction.prop('disabled', Backend.markedRecordsForMassAction.length > 0);
+  };
+
+  /**
+   * Generates the diff view of a record
+   *
+   * @param {Object} diff
+   * @return {$}
+   */
+  Backend.generateDiffView = function(diff) {
+    var $diff = $('<div />', {class: 'diff'});
+
+    for (var i = 0; i < diff.length; ++i) {
+      $diff.append(
+        $('<div />', {class: 'diff-item'}).append(
+          $('<div />', {class: 'diff-item-title'}).text(diff[i].label),
+          $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(diff[i].content)
+        )
+      );
+    }
+    return $diff;
+  };
+
+  /**
+   * Generates the comments view of a record
+   *
+   * @param {Object} comments
+   * @return {$}
+   */
+  Backend.generateCommentView = function(comments) {
+    var $comments = $('<div />');
+
+    for (var i = 0; i < comments.length; ++i) {
+      var $panel = $('<div />', {class: 'panel panel-default'});
+
+      if (comments[i].user_comment.length > 0) {
+        $panel.append(
+          $('<div />', {class: 'panel-body'}).html(comments[i].user_comment)
+        );
+      }
+
+      $panel.append(
+        $('<div />', {class: 'panel-footer'}).append(
+          $('<span />', {class: 'label label-success'}).text(comments[i].stage_title),
+          $('<span />', {class: 'label label-info'}).text(comments[i].tstamp)
+        )
+      );
+
+      $comments.append(
+        $('<div />', {class: 'media'}).append(
+          $('<div />', {class: 'media-left text-center'}).text(comments[i].user_username).prepend(
+            $('<div />').html(comments[i].user_avatar)
+          ),
+          $('<div />', {class: 'media-body'}).append($panel)
+        )
+      );
+    }
+
+    return $comments;
+  };
+
+  /**
+   * Sends a record to a stage
+   *
+   * @param {Object} $row
+   * @param {String} direction
+   */
+  Backend.sendToStage = function($row, direction) {
+    var nextStage,
+      stageWindowAction,
+      stageExecuteAction;
+
+    if (direction === 'next') {
+      nextStage = $row.data('nextStage');
+      stageWindowAction = 'sendToNextStageWindow';
+      stageExecuteAction = 'sendToNextStageExecute';
+    } else if (direction === 'prev') {
+      nextStage = $row.data('prevStage');
+      stageWindowAction = 'sendToPrevStageWindow';
+      stageExecuteAction = 'sendToPrevStageExecute';
+    } else {
+      throw 'Invalid direction given.';
+    }
+
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemoteActionsPayload(stageWindowAction, [
+        $row.data('uid'), $row.data('table'), $row.data('t3ver_oid')
+      ])
+    ).done(function(response) {
+      var $modal = Workspaces.renderSendToStageWindow(response);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'ok') {
+          var $form = $(e.currentTarget).find('form'),
+            serializedForm = $form.serializeObject();
+
+          serializedForm.affects = {
+            table: $row.data('table'),
+            nextStage: nextStage,
+            t3ver_oid: $row.data('t3ver_oid'),
+            uid: $row.data('uid'),
+            elements: []
+          };
+
+          Workspaces.sendRemoteRequest([
+            Workspaces.generateRemoteActionsPayload(stageExecuteAction, [serializedForm]),
+            Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
+          ]).done(function(response) {
+            $modal.modal('hide');
+            Backend.renderWorkspaceInfos(response[1].result);
+            Backend.refreshPageTree();
+          });
+        }
+      });
+    });
+  };
+
+  /**
+   * Loads the workspace components, like available stage actions and items of the workspace
+   */
+  Backend.loadWorkspaceComponents = function() {
+    Workspaces.sendRemoteRequest([
+      Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings),
+      Workspaces.generateRemotePayload('getStageActions', {}),
+      Workspaces.generateRemoteMassActionsPayload('getMassStageActions', {}),
+      Workspaces.generateRemotePayload('getSystemLanguages', {})
+    ]).done(function(response) {
+      Backend.elements.$depthSelector.prop('disabled', false);
+
+      // Records
+      Backend.renderWorkspaceInfos(response[0].result);
+
+      // Stage actions
+      var stageActions = response[1].result.data,
+        i;
+      for (i = 0; i < stageActions.length; ++i) {
+        Backend.elements.$chooseStageAction.append(
+          $('<option />').val(stageActions[i].uid).text(stageActions[i].title)
+        );
+      }
+
+      // Mass actions
+      var massActions = response[2].result.data;
+      for (i = 0; i < massActions.length; ++i) {
+        Backend.elements.$chooseSelectionAction.append(
+          $('<option />').val(massActions[i].action).text(massActions[i].title)
+        );
+
+        Backend.elements.$chooseMassAction.append(
+          $('<option />').val(massActions[i].action).text(massActions[i].title)
+        );
+      }
+
+      // Languages
+      var languages = response[3].result.data;
+      for (i = 0; i < languages.length; ++i) {
+        var $option = $('<option />').val(languages[i].uid).text(languages[i].title).data('icon', languages[i].icon);
+        if (String(languages[i].uid) === String(TYPO3.settings.Workspaces.language)) {
+          $option.prop('selected', true);
+          Backend.elements.$languageSelector.prev().html(languages[i].icon);
+        }
+        Backend.elements.$languageSelector.append($option);
+      }
+      Backend.elements.$languageSelector.prop('disabled', false);
+    });
+  };
+
+  /**
+   * Gets the workspace infos
+   *
+   * @return {Promise}
+   * @protected
+   */
+  Backend.getWorkspaceInfos = function() {
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
+    ).done(function(response) {
+      Backend.renderWorkspaceInfos(response[0].result);
+    });
+  };
+
+  /**
+   * Renders fetched workspace informations
+   *
+   * @param {Object} result
+   */
+  Backend.renderWorkspaceInfos = function(result) {
+    Backend.elements.$tableBody.children().remove();
+    Backend.allToggled = false;
+    Backend.elements.$chooseStageAction.prop('disabled', true);
+    Backend.elements.$chooseSelectionAction.prop('disabled', true);
+    Backend.elements.$chooseMassAction.prop('disabled', result.data.length === 0);
+
+    Backend.buildPagination(result.total);
+
+    for (var i = 0; i < result.data.length; ++i) {
+      var item = result.data[i],
+        $actions = $('<div />', {class: 'btn-group'}),
+        $integrityIcon = '';
+      $actions.append(
+        Backend.getAction(item.Workspaces_CollectionChildren > 0 && item.Workspaces_CollectionCurrent !== '', 'expand', 'apps-pagetree-collapse').attr('title', TYPO3.lang['tooltip.expand']).attr('data-target', '[data-collection="' + item.Workspaces_CollectionCurrent + '"]').attr('data-toggle', 'collapse'),
+        $('<button />', {
+          class: 'btn btn-default',
+          'data-action': 'changes',
+          'data-toggle': 'tooltip',
+          title: TYPO3.lang['tooltip.showChanges']
+        }).append(Backend.getPreRenderedIcon('actions-document-info')),
+        Backend.getAction(item.allowedAction_swap && item.Workspaces_CollectionParent === '', 'swap', 'actions-version-swap-version').attr('title', TYPO3.lang['tooltip.swap']),
+        Backend.getAction(item.allowedAction_view, 'preview', 'actions-version-workspace-preview').attr('title', TYPO3.lang['tooltip.viewElementAction']),
+        $('<button />', {
+          class: 'btn btn-default',
+          'data-action': 'open',
+          'data-toggle': 'tooltip',
+          title: TYPO3.lang['tooltip.editElementAction']
+        }).append(Backend.getPreRenderedIcon('actions-open')),
+        $('<button />', {
+          class: 'btn btn-default',
+          'data-action': 'version',
+          'data-toggle': 'tooltip',
+          title: TYPO3.lang['tooltip.openPage']
+        }).append(Backend.getPreRenderedIcon('actions-version-page-open')),
+        Backend.getAction(item.allowedAction_delete, 'remove', 'actions-version-document-remove').attr('title', TYPO3.lang['tooltip.discardVersion']),
+        $('<label />', {class: 'btn btn-default btn-checkbox'}).append(
+          $('<input />', {type: 'checkbox'}),
+          $('<span />', {class: 't3-icon fa'})
+        )
+      );
+
+      if (item.integrity.messages !== '') {
+        $integrityIcon = $(TYPO3.settings.Workspaces.icons[item.integrity.status]);
+        $integrityIcon
+          .attr('data-toggle', 'tooltip')
+          .attr('data-placement', 'top')
+          .attr('data-html', true)
+          .attr('title', item.integrity.messages);
+      }
+
+      if (Backend.latestPath !== item.path_Workspace) {
+        Backend.latestPath = item.path_Workspace;
+        Backend.elements.$tableBody.append(
+          $('<tr />').append(
+            $('<th />', {colspan: 6}).text(Backend.latestPath)
+          )
+        );
+      }
+
+      var rowConfiguration = {
+        'data-uid': item.uid,
+        'data-pid': item.livepid,
+        'data-t3ver_oid': item.t3ver_oid,
+        'data-t3ver_wsid': item.t3ver_wsid,
+        'data-table': item.table,
+        'data-next-stage': item.value_nextStage,
+        'data-prev-stage': item.value_prevStage,
+        'data-stage': item.stage
+      };
+
+      if (item.Workspaces_CollectionParent !== '') {
+        rowConfiguration['data-collection'] = item.Workspaces_CollectionParent;
+        rowConfiguration['class'] = 'collapse';
+      }
+
+      Backend.elements.$tableBody.append(
+        $('<tr />', rowConfiguration).append(
+          $('<td />', {
+            class: 't3js-title-workspace',
+            style: item.Workspaces_CollectionLevel > 0 ? 'padding-left: ' + Backend.indentationPadding * item.Workspaces_CollectionLevel + 'px' : ''
+          }).html(item.icon_Workspace + '&nbsp;' + '<a href="#" data-action="changes"><span class="item-state-' + item.state_Workspace + '">' + item.label_Workspace + '</span></a>'),
+          $('<td />', {class: 't3js-title-live'}).html(item.icon_Live + '&nbsp;' + item.label_Live),
+          $('<td />').text(item.label_Stage),
+          $('<td />').html($integrityIcon),
+          $('<td />').html(item.language.icon),
+          $('<td />', {class: 'text-right nowrap'}).append($actions)
+        )
+      );
+
+      Tooltip.initialize('[data-toggle="tooltip"]', {
+        delay: {
+          show: 500,
+          hide: 100
+        },
+        trigger: 'hover',
+        container: 'body'
+      });
+    }
+  };
+
+  /**
+   * Renders the pagination
+   *
+   * @param {Number} totalItems
+   */
+  Backend.buildPagination = function(totalItems) {
+    if (totalItems === 0) {
+      Backend.elements.$pagination.contents().remove();
+      return;
+    }
+
+    Backend.paging.totalItems = totalItems;
+    Backend.paging.totalPages = Math.ceil(totalItems / Backend.settings.limit);
+
+    if (Backend.paging.totalPages === 1) {
+      // early abort if only one page is available
+      Backend.elements.$pagination.contents().remove();
+      return;
+    }
+
+    var $ul = $('<ul />', {class: 'pagination pagination-block'}),
+      liElements = [],
+      $controlFirstPage = $('<li />').append(
+        $('<a />', {'data-action': 'previous'}).append(
+          $('<span />', {class: 't3-icon fa fa-arrow-left'})
+        )
+      ),
+      $controlLastPage = $('<li />').append(
+        $('<a />', {'data-action': 'next'}).append(
+          $('<span />', {class: 't3-icon fa fa-arrow-right'})
+        )
+      );
+
+    if (Backend.paging.currentPage === 1) {
+      $controlFirstPage.disablePagingAction();
+    }
+
+    if (Backend.paging.currentPage === Backend.paging.totalPages) {
+      $controlLastPage.disablePagingAction();
+    }
+
+    for (var i = 1; i <= Backend.paging.totalPages; i++) {
+      var $li = $('<li />', {class: Backend.paging.currentPage === i ? 'active' : ''});
+      $li.append(
+        $('<a />', {'data-action': 'page', 'data-page': i}).append(
+          $('<span />').text(i)
+        )
+      );
+      liElements.push($li);
+    }
+
+    $ul.append($controlFirstPage, liElements, $controlLastPage);
+    Backend.elements.$pagination.html($ul);
+  };
+
+  /**
+   * View changes of a record
+   *
+   * @param {Event} e
+   */
+  Backend.viewChanges = function(e) {
+    e.preventDefault();
+
+    var $tr = $(e.target).closest('tr');
+
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemotePayload('getRowDetails', {
+        stage: $tr.data('stage'),
+        t3ver_oid: $tr.data('t3ver_oid'),
+        table: $tr.data('table'),
+        uid: $tr.data('uid')
+      })
+    ).done(function(response) {
+      var item = response[0].result.data[0],
+        $content = $('<div />'),
+        $tabsNav = $('<ul />', {class: 'nav nav-tabs', role: 'tablist'}),
+        $tabsContent = $('<div />', {class: 'tab-content'}),
+        modalButtons = [];
+
+      $content.append(
+        $('<p />').html(TYPO3.lang['path'].replace('{0}', item.path_Live)),
+        $('<p />').html(TYPO3.lang['current_step'].replace('{0}', item.label_Stage).replace('{1}', item.stage_position).replace('{2}', item.stage_count))
+      );
+
+      if (item.diff.length > 0) {
+        $tabsNav.append(
+          $('<li />', {role: 'presentation'}).append(
+            $('<a />', {
+              href: '#workspace-changes',
+              'aria-controls': 'workspace-changes',
+              role: 'tab',
+              'data-toggle': 'tab'
+            }).text(TYPO3.lang['window.recordChanges.tabs.changeSummary'])
+          )
+        );
+        $tabsContent.append(
+          $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-changes'}).append(
+            $('<div />', {class: 'form-section'}).append(
+              Backend.generateDiffView(item.diff)
+            )
+          )
+        );
+      }
+
+      if (item.comments.length > 0) {
+        $tabsNav.append(
+          $('<li />', {role: 'presentation'}).append(
+            $('<a />', {
+              href: '#workspace-comments',
+              'aria-controls': 'workspace-comments',
+              role: 'tab',
+              'data-toggle': 'tab'
+            }).html(TYPO3.lang['window.recordChanges.tabs.comments'] + '&nbsp;').append(
+              $('<span />', {class: 'badge'}).text(item.comments.length)
+            )
+          )
+        );
+        $tabsContent.append(
+          $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-comments'}).append(
+            $('<div />', {class: 'form-section'}).append(
+              Backend.generateCommentView(item.comments)
+            )
+          )
+        );
+      }
+
+      if (item.history.total > 0) {
+        $tabsNav.append(
+          $('<li />', {role: 'presentation'}).append(
+            $('<a />', {
+              href: '#workspace-history',
+              'aria-controls': 'workspace-history',
+              role: 'tab',
+              'data-toggle': 'tab'
+            }).text(TYPO3.lang['window.recordChanges.tabs.history'])
+          )
+        );
+
+        $tabsContent.append(
+          $('<div />', {role: 'tabpanel', class: 'tab-pane', id: 'workspace-history'}).append(
+            $('<div />', {class: 'form-section'}).append(
+              Backend.generateHistoryView(item.history.data)
+            )
+          )
+        );
+      }
+
+      // Mark the first tab and pane as active
+      $tabsNav.find('li').first().addClass('active');
+      $tabsContent.find('.tab-pane').first().addClass('active');
+
+      // Attach tabs
+      $content.append(
+        $('<div />').append(
+          $tabsNav,
+          $tabsContent
+        )
+      );
+
+      if ($tr.data('stage') !== $tr.data('prevStage')) {
+        modalButtons.push({
+          text: item.label_PrevStage.title,
+          active: true,
+          btnClass: 'btn-default',
+          name: 'prevstage',
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+            Backend.sendToStage($(e.target).closest('tr'), 'prev');
+          }
+        });
+      }
+
+      modalButtons.push({
+        text: item.label_NextStage.title,
+        active: true,
+        btnClass: 'btn-default',
+        name: 'nextstage',
+        trigger: function() {
+          Modal.currentModal.trigger('modal-dismiss');
+          Backend.sendToStage($(e.target).closest('tr'), 'next');
+        }
+      });
+      modalButtons.push({
+        text: TYPO3.lang['close'],
+        active: true,
+        btnClass: 'btn-info',
+        name: 'cancel',
+        trigger: function() {
+          Modal.currentModal.trigger('modal-dismiss');
+        }
+      });
+
+      Modal.show(
+        TYPO3.lang['window.recordInformation'].replace('{0}', $.trim($tr.find('.t3js-title-live').text())),
+        $content,
+        Severity.info,
+        modalButtons
+      );
+    });
+  };
+
+  /**
+   * Opens a record in a preview window
+   *
+   * @param {Event} e
+   */
+  Backend.openPreview = function(e) {
+    var $tr = $(e.target).closest('tr');
+
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemoteActionsPayload('viewSingleRecord', [
+        $tr.data('table'), $tr.data('uid')
+      ])
+    ).done(function(response) {
+      eval(response[0].result);
+    });
+  };
+
+  /**
+   * Renders the record's history
+   *
+   * @param {Object} data
+   */
+  Backend.generateHistoryView = function(data) {
+    var $history = $('<div />');
+
+    for (var i = 0; i < data.length; ++i) {
+      var $panel = $('<div />', {class: 'panel panel-default'}),
+        $diff;
+
+      if (typeof data[i].differences === 'object') {
+        if (data[i].differences.length === 0) {
+          // Somehow here are no differences. What a pity, skip that record
+          continue;
+        }
+        $diff = $('<div />', {class: 'diff'});
+
+        for (var j = 0; j < data[i].differences.length; ++j) {
+          $diff.append(
+            $('<div />', {class: 'diff-item'}).append(
+              $('<div />', {class: 'diff-item-title'}).text(data[i].differences[j].label),
+              $('<div />', {class: 'diff-item-result diff-item-result-inline'}).html(data[i].differences[j].html)
+            )
+          );
+        }
+
+        $panel.append(
+          $('<div />').append($diff)
+        );
+      } else {
+        $panel.append(
+          $('<div />', {class: 'panel-body'}).text(data[i].differences)
+        );
+      }
+      $panel.append(
+        $('<div />', {class: 'panel-footer'}).append(
+          $('<span />', {class: 'label label-info'}).text(data[i].datetime)
+        )
+      );
+
+      $history.append(
+        $('<div />', {class: 'media'}).append(
+          $('<div />', {class: 'media-left text-center'}).text(data[i].user).prepend(
+            $('<div />').html(data[i].user_avatar)
+          ),
+          $('<div />', {class: 'media-body'}).append($panel)
+        )
+      );
+    }
+
+    return $history;
+  };
+
+  /**
+   * Shows a confirmation modal and deletes the selected record from workspace.
+   *
+   * @param {Event} e
+   */
+  Backend.confirmDeleteRecordFromWorkspace = function(e) {
+    var $tr = $(e.target).closest('tr');
+    var $modal = Modal.confirm(
+      TYPO3.lang['window.discard.title'],
+      TYPO3.lang['window.discard.message'],
+      Severity.warning,
+      [
+        {
+          text: TYPO3.lang['cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel',
+          trigger: function() {
+            $modal.modal('hide');
+          }
+        }, {
+        text: TYPO3.lang['ok'],
+        btnClass: 'btn-warning',
+        name: 'ok'
+      }
+      ]
+    );
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'ok') {
+        Workspaces.sendRemoteRequest([
+          Workspaces.generateRemoteActionsPayload('deleteSingleRecord', [
+            $tr.data('table'),
+            $tr.data('uid')
+          ])
+        ]).done(function() {
+          $modal.modal('hide');
+          Backend.getWorkspaceInfos();
+          Backend.refreshPageTree();
+        });
+      }
+    });
+  };
+
+  /**
+   * Runs a mass action
+   */
+  Backend.runSelectionAction = function() {
+    var selectedAction = Backend.elements.$chooseSelectionAction.val(),
+      integrityCheckRequired = selectedAction !== 'discard';
+
+    if (selectedAction.length === 0) {
+      // Don't do anything if that value is empty
+      return;
+    }
+
+    var affectedRecords = [];
+    for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) {
+      var affected = Backend.markedRecordsForMassAction[i].split(':');
+      affectedRecords.push({
+        table: affected[0],
+        liveId: affected[2],
+        versionId: affected[1]
+      });
+    }
+
+    if (!integrityCheckRequired) {
+      Wizard.setup.forceSelection = false;
+      Backend.renderSelectionActionWizard(selectedAction, affectedRecords);
+    } else {
+      Workspaces.checkIntegrity(
+        {
+          selection: affectedRecords,
+          type: 'selection'
+        }
+      ).done(function(response) {
+        Wizard.setup.forceSelection = false;
+        if (response[0].result.result === 'warning') {
+          Backend.addIntegrityCheckWarningToWizard();
+        }
+        Backend.renderSelectionActionWizard(selectedAction, affectedRecords);
+      });
+    }
+  };
+
+  /**
+   * Adds a slide to the wizard concerning an integrity check warning.
+   */
+  Backend.addIntegrityCheckWarningToWizard = function() {
+    Wizard.addSlide(
+      'integrity-warning',
+      'Warning',
+      TYPO3.lang['integrity.hasIssuesDescription'] + '<br>' + TYPO3.lang['integrity.hasIssuesQuestion'],
+      Severity.warning
+    );
+  };
+
+  /**
+   * Renders the wizard for selection actions
+   *
+   * @param {String} selectedAction
+   * @param {Object} affectedRecords
+   */
+  Backend.renderSelectionActionWizard = function(selectedAction, affectedRecords) {
+    Wizard.addSlide(
+      'mass-action-confirmation',
+      TYPO3.lang['window.selectionAction.title'],
+      $('<p />').text(TYPO3.lang['tooltip.' + selectedAction + 'Selected']),
+      Severity.warning
+    );
+    Wizard.addFinalProcessingSlide(function() {
+      Workspaces.sendRemoteRequest(
+        Workspaces.generateRemoteActionsPayload('executeSelectionAction', {
+          action: selectedAction,
+          selection: affectedRecords
+        })
+      ).done(function() {
+        Backend.getWorkspaceInfos();
+        Wizard.dismiss();
+        Backend.refreshPageTree();
+      });
+    }).done(function() {
+      Wizard.show();
+
+      Wizard.getComponent().on('wizard-dismissed', function() {
+        Backend.elements.$chooseSelectionAction.val('');
+      });
+    });
+  };
+
+  /**
+   * Runs a mass action
+   */
+  Backend.runMassAction = function() {
+    var selectedAction = Backend.elements.$chooseMassAction.val(),
+      integrityCheckRequired = selectedAction !== 'discard';
+
+    if (selectedAction.length === 0) {
+      // Don't do anything if that value is empty
+      return;
+    }
+
+    if (!integrityCheckRequired) {
+      Wizard.setup.forceSelection = false;
+      Backend.renderMassActionWizard(selectedAction);
+    } else {
+      Workspaces.checkIntegrity(
+        {
+          language: Backend.settings.language,
+          type: selectedAction
+        }
+      ).done(function(response) {
+        Wizard.setup.forceSelection = false;
+        if (response[0].result.result === 'warning') {
+          Backend.addIntegrityCheckWarningToWizard();
+        }
+        Backend.renderMassActionWizard(selectedAction);
+      });
+    }
+  };
+
+  /**
+   * Renders the wizard for mass actions
+   *
+   * @param {String} selectedAction
+   */
+  Backend.renderMassActionWizard = function(selectedAction) {
+    var massAction,
+      doSwap = false;
+
+    switch (selectedAction) {
+      case 'publish':
+        massAction = 'publishWorkspace';
+        break;
+      case 'swap':
+        massAction = 'publishWorkspace';
+        doSwap = true;
+        break;
+      case 'discard':
+        massAction = 'flushWorkspace';
+        break;
+    }
+
+    if (massAction === null) {
+      throw 'Invalid mass action ' + selectedAction + ' called.';
+    }
+
+    Wizard.setup.forceSelection = false;
+    Wizard.addSlide(
+      'mass-action-confirmation',
+      TYPO3.lang['window.massAction.title'],
+      $('<p />').html(TYPO3.lang['tooltip.' + selectedAction + 'All'] + '<br><br>' + TYPO3.lang['tooltip.affectWholeWorkspace']),
+      Severity.warning
+    );
+    Wizard.addFinalProcessingSlide(function() {
+      Workspaces.sendRemoteRequest(
+        Workspaces.generateRemoteMassActionsPayload(massAction, {
+          init: true,
+          total: 0,
+          processed: 0,
+          language: Backend.settings.language,
+          swap: doSwap
+        })
+      ).done(function(response) {
+        var payload = response[0].result;
+        Workspaces.sendRemoteRequest(
+          Workspaces.generateRemoteMassActionsPayload(massAction, payload)
+        ).done(function() {
+          Backend.getWorkspaceInfos();
+          Wizard.dismiss();
+        });
+      });
+    }).done(function() {
+      Wizard.show();
+
+      Wizard.getComponent().on('wizard-dismissed', function() {
+        Backend.elements.$chooseMassAction.val('');
+      });
+    });
+  };
+
+  /**
+   * Sends marked records to a stage
+   *
+   * @param {Event} e
+   */
+  Backend.sendToSpecificStageAction = function(e) {
+    var affectedRecords = [],
+      stage = $(e.currentTarget).val();
+    for (var i = 0; i < Backend.markedRecordsForMassAction.length; ++i) {
+      var affected = Backend.markedRecordsForMassAction[i].split(':');
+      affectedRecords.push({
+        table: affected[0],
+        uid: affected[1],
+        t3ver_oid: affected[2]
+      });
+    }
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemoteActionsPayload('sendToSpecificStageWindow', [
+        stage, affectedRecords
+      ])
+    ).done(function(response) {
+      var $modal = Workspaces.renderSendToStageWindow(response);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'ok') {
+          var $form = $(e.currentTarget).find('form'),
+            serializedForm = $form.serializeObject();
+
+          serializedForm.affects = {
+            elements: affectedRecords,
+            nextStage: stage
+          };
+
+          Workspaces.sendRemoteRequest([
+            Workspaces.generateRemoteActionsPayload('sendToSpecificStageExecute', [serializedForm]),
+            Workspaces.generateRemotePayload('getWorkspaceInfos', Backend.settings)
+          ]).done(function(response) {
+            $modal.modal('hide');
+            Backend.renderWorkspaceInfos(response[1].result);
+            Backend.refreshPageTree();
+          });
+        }
+      }).on('modal-destroyed', function() {
+        Backend.elements.$chooseStageAction.val('');
+      });
+    });
+  };
+
+  /**
+   * Reloads the page tree
+   */
+  Backend.refreshPageTree = function() {
+    if (top.TYPO3 && top.TYPO3.Backend && top.TYPO3.Backend.NavigationContainer && top.TYPO3.Backend.NavigationContainer.PageTree) {
+      top.TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+    }
+  };
+
+  /**
+   * Renders the action button based on the user's permission.
+   *
+   * @returns {$}
+   * @private
+   */
+  Backend.getAction = function(condition, action, iconIdentifier) {
+    if (condition) {
+      return $('<button />', {
+        class: 'btn btn-default',
+        'data-action': action,
+        'data-toggle': 'tooltip'
+      }).append(Backend.getPreRenderedIcon(iconIdentifier))
+    }
+    return $('<span />', {class: 'btn btn-default disabled'}).append(Backend.getPreRenderedIcon('empty-empty'));
+  };
+
+  /**
+   * Fetches and renders available preview links
+   */
+  Backend.generatePreviewLinks = function() {
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemoteActionsPayload('generateWorkspacePreviewLinksForAllLanguages', [
+        Backend.settings.id
+      ])
+    ).done(function(response) {
+      var result = response[0].result,
+        $list = $('<dl />');
+
+      $.each(result, function(language, url) {
+        $list.append(
+          $('<dt />').text(language),
+          $('<dd />').append(
+            $('<a />', {href: url, target: '_blank'}).text(url)
+          )
+        );
+      });
+
+      Modal.show(
+        TYPO3.lang['previewLink'],
+        $list,
+        Severity.info,
+        [{
+          text: TYPO3.lang['ok'],
+          active: true,
+          btnClass: 'btn-info',
+          name: 'ok',
+          trigger: function() {
+            Modal.currentModal.trigger('modal-dismiss');
+          }
+        }],
+        ['modal-inner-scroll']
+      );
+    });
+  };
+
+  /**
+   * Gets the pre-rendered icon
+   * This method is intended to be dropped once we use Fluid's StandaloneView.
+   *
+   * @param {String} identifier
+   * @returns {$}
+   */
+  Backend.getPreRenderedIcon = function(identifier) {
+    return Backend.elements.$actionIcons.find('[data-identifier="' + identifier + '"]').clone();
+  };
+
+  /**
+   * Serialize a form to a JavaScript object
+   *
+   * @see http://stackoverflow.com/a/1186309/4828813
+   * @return {Object}
+   */
+  $.fn.serializeObject = function() {
+    var o = {};
+    var a = this.serializeArray();
+    $.each(a, function() {
+      if (typeof o[this.name] !== 'undefined') {
+        if (!o[this.name].push) {
+          o[this.name] = [o[this.name]];
+        }
+        o[this.name].push(this.value || '');
+      } else {
+        o[this.name] = this.value || '';
+      }
+    });
+    return o;
+  };
+
+  /**
+   * Changes the markup of a pagination action being disabled
+   */
+  $.fn.disablePagingAction = function() {
+    $(this).addClass('disabled').find('.t3-icon').unwrap().wrap($('<span />'));
+  };
+
+  $(Backend.initialize);
 });
diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js
index 78c2188d5cce..8ceaa66ed96e 100644
--- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js
+++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Preview.js
@@ -16,290 +16,290 @@
  * RequireJS module for workspace preview
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Workspaces/Workspaces',
-	'TYPO3/CMS/Backend/Severity',
-	'TYPO3/CMS/Backend/Modal',
-	'twbs/bootstrap-slider'
+  'jquery',
+  'TYPO3/CMS/Workspaces/Workspaces',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Modal',
+  'twbs/bootstrap-slider'
 ], function($, Workspaces, Severity, Modal) {
-	'use strict';
-
-	var Preview = {
-		identifiers: {
-			topbar: '#typo3-topbar',
-			workspacePanel: '.workspace-panel',
-			liveView: '#live-view',
-			workspaceTabs: '.t3js-workspace-tabs [data-toggle="tab"]',
-			workspaceActions: '.t3js-workspace-actions',
-			stageSlider: '#workspace-stage-slider',
-			workspaceView: '#workspace-view',
-			workspaceList: '#workspace-list',
-			sendToStageAction: '[data-action="send-to-stage"]',
-			discardAction: '[data-action="discard"]',
-			stageButtonsContainer: '.t3js-stage-buttons',
-			previewModeContainer: '.t3js-preview-mode',
-			activePreviewMode: '.t3js-active-preview-mode',
-			workspacePreview: '.t3js-workspace-preview'
-		},
-		currentSlidePosition: 100,
-		elements: {} // filled in Preview.getElements()
-	};
-
-	/**
-	 * Initializes the preview module
-	 */
-	Preview.initialize = function() {
-		Preview.getElements();
-		Preview.resizeViews();
-
-		Preview.adjustPreviewModeSelectorWidth();
-		Preview.elements.$stageSlider.slider();
-
-		Preview.registerEvents();
-	};
-
-	/**
-	 * Fetches and stores often required elements
-	 */
-	Preview.getElements = function() {
-		Preview.elements.$liveView = $(Preview.identifiers.liveView);
-		Preview.elements.$workspacePanel = $(Preview.identifiers.workspacePanel);
-		Preview.elements.$workspaceTabs = $(Preview.identifiers.workspaceTabs);
-		Preview.elements.$workspaceActions = $(Preview.identifiers.workspaceActions);
-		Preview.elements.$stageSlider = $(Preview.identifiers.stageSlider);
-		Preview.elements.$workspaceView = $(Preview.identifiers.workspaceView);
-		Preview.elements.$workspaceList = $(Preview.identifiers.workspaceList);
-		Preview.elements.$stageButtonsContainer = $(Preview.identifiers.stageButtonsContainer);
-		Preview.elements.$previewModeContainer = $(Preview.identifiers.previewModeContainer);
-		Preview.elements.$activePreviewMode = $(Preview.identifiers.activePreviewMode);
-		Preview.elements.$workspacePreview = $(Preview.identifiers.workspacePreview);
-	};
-
-	/**
-	 * Registers the events
-	 */
-	Preview.registerEvents = function() {
-		$(window).on('resize', function() {
-			Preview.resizeViews();
-		});
-		$(document)
-			.on('click', Preview.identifiers.discardAction, Preview.renderDiscardWindow)
-			.on('click', Preview.identifiers.sendToStageAction, Preview.renderSendPageToStageWindow)
-		;
-
-		Preview.elements.$workspaceTabs.on('show.bs.tab', function() {
-			Preview.elements.$workspaceActions.toggle($(this).data('actions'));
-		});
-		Preview.elements.$stageSlider.on('change', Preview.updateSlidePosition);
-		Preview.elements.$previewModeContainer.find('[data-preview-mode]').on('click', Preview.changePreviewMode);
-	};
-
-	/**
-	 * Renders the staging buttons
-	 *
-	 * @param {String} buttons
-	 */
-	Preview.renderStageButtons = function(buttons) {
-		Preview.elements.$stageButtonsContainer.html(buttons);
-	};
-
-	/**
-	 * Calculate the available space based on the viewport height
-	 *
-	 * @returns {Number}
-	 */
-	Preview.getAvailableSpace = function() {
-		var $viewportHeight = $(window).height(),
-			$topbarHeight = $(Preview.identifiers.topbar).outerHeight();
-
-		return $viewportHeight - $topbarHeight;
-	};
-
-	/**
-	 * Updates the position of the comparison slider
-	 *
-	 * @param {Event} e
-	 */
-	Preview.updateSlidePosition = function(e) {
-		Preview.currentSlidePosition = e.value.newValue;
-		Preview.resizeViews();
-	};
-
-	/**
-	 * Resize the views based on the current viewport height and slider position
-	 */
-	Preview.resizeViews = function() {
-		var availableSpace = Preview.getAvailableSpace(),
-			relativeHeightOfLiveView = (Preview.currentSlidePosition - 100) * -1,
-			absoluteHeightOfLiveView = Math.round(Math.abs(availableSpace * relativeHeightOfLiveView / 100)),
-			outerHeightDifference = Preview.elements.$liveView.outerHeight() - Preview.elements.$liveView.height();
-
-		Preview.elements.$workspacePreview.height(availableSpace);
-
-		if (Preview.elements.$activePreviewMode.data('activePreviewMode') === 'slider') {
-			Preview.elements.$liveView.height(absoluteHeightOfLiveView - outerHeightDifference);
-		}
-		Preview.elements.$workspaceList.height(availableSpace);
-	};
-
-	/**
-	 * Renders the discard window
-	 *
-	 * @private
-	 */
-	Preview.renderDiscardWindow = function() {
-		var $modal = Modal.confirm(
-			TYPO3.lang['window.discardAll.title'],
-			TYPO3.lang['window.discardAll.message'],
-			Severity.warning,
-			[
-				{
-					text: TYPO3.lang['cancel'],
-					active: true,
-					btnClass: 'btn-default',
-					name: 'cancel',
-					trigger: function() {
-						$modal.modal('hide');
-					}
-				}, {
-				text: TYPO3.lang['ok'],
-				btnClass: 'btn-warning',
-				name: 'ok'
-			}
-			]
-		);
-		$modal.on('button.clicked', function(e) {
-			if (e.target.name === 'ok') {
-				Workspaces.sendRemoteRequest([
-					Workspaces.generateRemoteActionsPayload('discardStagesFromPage', [TYPO3.settings.Workspaces.id]),
-					Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
-				]).done(function(response) {
-					$modal.modal('hide');
-					Preview.renderStageButtons(response[1].result);
-					// Reloading live view and and workspace list view IFRAME
-					Preview.elements.$workspaceView.attr('src', Preview.elements.$workspaceView.attr('src'));
-					Preview.elements.$workspaceList.attr('src', Preview.elements.$workspaceList.attr('src'));
-				});
-			}
-		});
-	};
-
-	/**
-	 * Adjusts the width of the preview mode selector to avoid jumping around due to different widths of the labels
-	 */
-	Preview.adjustPreviewModeSelectorWidth = function() {
-		var $btnGroup = Preview.elements.$previewModeContainer.find('.btn-group'),
-			maximumWidth = 0;
-
-		$btnGroup.addClass('open');
-		Preview.elements.$previewModeContainer.find('li > a > span').each(function(_, el) {
-			var width = $(el).width();
-			if (maximumWidth < width) {
-				maximumWidth = width;
-			}
-		});
-		$btnGroup.removeClass('open');
-		Preview.elements.$activePreviewMode.width(maximumWidth);
-	};
-
-	/**
-	 * Renders the "send page to stage" window
-	 *
-	 * @private
-	 */
-	Preview.renderSendPageToStageWindow = function() {
-		var $me = $(this),
-			direction = $me.data('direction'),
-			actionName;
-
-		if (direction === 'prev') {
-			actionName = 'sendPageToPreviousStage';
-		} else if (direction === 'next') {
-			actionName = 'sendPageToNextStage';
-		} else {
-			throw 'Invalid direction ' + direction + ' requested.';
-		}
-
-		Workspaces.sendRemoteRequest(
-			Workspaces.generateRemoteActionsPayload(actionName, [TYPO3.settings.Workspaces.id])
-		).done(function(response) {
-			var $modal = Workspaces.renderSendToStageWindow(response);
-			$modal.on('button.clicked', function (e) {
-				if (e.target.name === 'ok') {
-					var $form = $(e.currentTarget).find('form'),
-						serializedForm = $form.serializeObject();
-
-					serializedForm.affects = response[0].result.affects;
-					serializedForm.stageId = $me.data('stageId');
-
-					Workspaces.sendRemoteRequest([
-						Workspaces.generateRemoteActionsPayload('sentCollectionToStage', [serializedForm]),
-						Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
-					]).done(function(response) {
-						$modal.modal('hide');
-
-						Preview.renderStageButtons(response[1].result);
-					});
-				}
-			});
-		});
-	};
-
-	/**
-	 * Changes the preview mode
-	 *
-	 * @param {Event} e
-	 */
-	Preview.changePreviewMode = function(e) {
-		e.preventDefault();
-
-		var $trigger = $(this),
-			currentPreviewMode = Preview.elements.$activePreviewMode.data('activePreviewMode'),
-			newPreviewMode = $trigger.data('previewMode');
-
-		Preview.elements.$activePreviewMode.text($trigger.text()).data('activePreviewMode', newPreviewMode);
-		Preview.elements.$workspacePreview.parent()
-			.removeClass('preview-mode-' + currentPreviewMode)
-			.addClass('preview-mode-' + newPreviewMode);
-
-		if (newPreviewMode === 'slider') {
-			Preview.elements.$stageSlider.parent().toggle(true);
-			Preview.resizeViews();
-		} else {
-			Preview.elements.$stageSlider.parent().toggle(false);
-
-			if (newPreviewMode === 'vbox') {
-				Preview.elements.$liveView.height('100%');
-			} else {
-				Preview.elements.$liveView.height('50%');
-			}
-		}
-
-	};
-
-	/**
-	 * Serialize a form to a JavaScript object
-	 *
-	 * @see http://stackoverflow.com/a/1186309/4828813
-	 * @return {Object}
-	 */
-	$.fn.serializeObject = function() {
-		var o = {};
-		var a = this.serializeArray();
-		$.each(a, function() {
-			if (typeof o[this.name] !== 'undefined') {
-				if (!o[this.name].push) {
-					o[this.name] = [o[this.name]];
-				}
-				o[this.name].push(this.value || '');
-			} else {
-				o[this.name] = this.value || '';
-			}
-		});
-		return o;
-	};
-
-	$(document).ready(function() {
-		Preview.initialize();
-	});
+  'use strict';
+
+  var Preview = {
+    identifiers: {
+      topbar: '#typo3-topbar',
+      workspacePanel: '.workspace-panel',
+      liveView: '#live-view',
+      workspaceTabs: '.t3js-workspace-tabs [data-toggle="tab"]',
+      workspaceActions: '.t3js-workspace-actions',
+      stageSlider: '#workspace-stage-slider',
+      workspaceView: '#workspace-view',
+      workspaceList: '#workspace-list',
+      sendToStageAction: '[data-action="send-to-stage"]',
+      discardAction: '[data-action="discard"]',
+      stageButtonsContainer: '.t3js-stage-buttons',
+      previewModeContainer: '.t3js-preview-mode',
+      activePreviewMode: '.t3js-active-preview-mode',
+      workspacePreview: '.t3js-workspace-preview'
+    },
+    currentSlidePosition: 100,
+    elements: {} // filled in Preview.getElements()
+  };
+
+  /**
+   * Initializes the preview module
+   */
+  Preview.initialize = function() {
+    Preview.getElements();
+    Preview.resizeViews();
+
+    Preview.adjustPreviewModeSelectorWidth();
+    Preview.elements.$stageSlider.slider();
+
+    Preview.registerEvents();
+  };
+
+  /**
+   * Fetches and stores often required elements
+   */
+  Preview.getElements = function() {
+    Preview.elements.$liveView = $(Preview.identifiers.liveView);
+    Preview.elements.$workspacePanel = $(Preview.identifiers.workspacePanel);
+    Preview.elements.$workspaceTabs = $(Preview.identifiers.workspaceTabs);
+    Preview.elements.$workspaceActions = $(Preview.identifiers.workspaceActions);
+    Preview.elements.$stageSlider = $(Preview.identifiers.stageSlider);
+    Preview.elements.$workspaceView = $(Preview.identifiers.workspaceView);
+    Preview.elements.$workspaceList = $(Preview.identifiers.workspaceList);
+    Preview.elements.$stageButtonsContainer = $(Preview.identifiers.stageButtonsContainer);
+    Preview.elements.$previewModeContainer = $(Preview.identifiers.previewModeContainer);
+    Preview.elements.$activePreviewMode = $(Preview.identifiers.activePreviewMode);
+    Preview.elements.$workspacePreview = $(Preview.identifiers.workspacePreview);
+  };
+
+  /**
+   * Registers the events
+   */
+  Preview.registerEvents = function() {
+    $(window).on('resize', function() {
+      Preview.resizeViews();
+    });
+    $(document)
+      .on('click', Preview.identifiers.discardAction, Preview.renderDiscardWindow)
+      .on('click', Preview.identifiers.sendToStageAction, Preview.renderSendPageToStageWindow)
+    ;
+
+    Preview.elements.$workspaceTabs.on('show.bs.tab', function() {
+      Preview.elements.$workspaceActions.toggle($(this).data('actions'));
+    });
+    Preview.elements.$stageSlider.on('change', Preview.updateSlidePosition);
+    Preview.elements.$previewModeContainer.find('[data-preview-mode]').on('click', Preview.changePreviewMode);
+  };
+
+  /**
+   * Renders the staging buttons
+   *
+   * @param {String} buttons
+   */
+  Preview.renderStageButtons = function(buttons) {
+    Preview.elements.$stageButtonsContainer.html(buttons);
+  };
+
+  /**
+   * Calculate the available space based on the viewport height
+   *
+   * @returns {Number}
+   */
+  Preview.getAvailableSpace = function() {
+    var $viewportHeight = $(window).height(),
+      $topbarHeight = $(Preview.identifiers.topbar).outerHeight();
+
+    return $viewportHeight - $topbarHeight;
+  };
+
+  /**
+   * Updates the position of the comparison slider
+   *
+   * @param {Event} e
+   */
+  Preview.updateSlidePosition = function(e) {
+    Preview.currentSlidePosition = e.value.newValue;
+    Preview.resizeViews();
+  };
+
+  /**
+   * Resize the views based on the current viewport height and slider position
+   */
+  Preview.resizeViews = function() {
+    var availableSpace = Preview.getAvailableSpace(),
+      relativeHeightOfLiveView = (Preview.currentSlidePosition - 100) * -1,
+      absoluteHeightOfLiveView = Math.round(Math.abs(availableSpace * relativeHeightOfLiveView / 100)),
+      outerHeightDifference = Preview.elements.$liveView.outerHeight() - Preview.elements.$liveView.height();
+
+    Preview.elements.$workspacePreview.height(availableSpace);
+
+    if (Preview.elements.$activePreviewMode.data('activePreviewMode') === 'slider') {
+      Preview.elements.$liveView.height(absoluteHeightOfLiveView - outerHeightDifference);
+    }
+    Preview.elements.$workspaceList.height(availableSpace);
+  };
+
+  /**
+   * Renders the discard window
+   *
+   * @private
+   */
+  Preview.renderDiscardWindow = function() {
+    var $modal = Modal.confirm(
+      TYPO3.lang['window.discardAll.title'],
+      TYPO3.lang['window.discardAll.message'],
+      Severity.warning,
+      [
+        {
+          text: TYPO3.lang['cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel',
+          trigger: function() {
+            $modal.modal('hide');
+          }
+        }, {
+        text: TYPO3.lang['ok'],
+        btnClass: 'btn-warning',
+        name: 'ok'
+      }
+      ]
+    );
+    $modal.on('button.clicked', function(e) {
+      if (e.target.name === 'ok') {
+        Workspaces.sendRemoteRequest([
+          Workspaces.generateRemoteActionsPayload('discardStagesFromPage', [TYPO3.settings.Workspaces.id]),
+          Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
+        ]).done(function(response) {
+          $modal.modal('hide');
+          Preview.renderStageButtons(response[1].result);
+          // Reloading live view and and workspace list view IFRAME
+          Preview.elements.$workspaceView.attr('src', Preview.elements.$workspaceView.attr('src'));
+          Preview.elements.$workspaceList.attr('src', Preview.elements.$workspaceList.attr('src'));
+        });
+      }
+    });
+  };
+
+  /**
+   * Adjusts the width of the preview mode selector to avoid jumping around due to different widths of the labels
+   */
+  Preview.adjustPreviewModeSelectorWidth = function() {
+    var $btnGroup = Preview.elements.$previewModeContainer.find('.btn-group'),
+      maximumWidth = 0;
+
+    $btnGroup.addClass('open');
+    Preview.elements.$previewModeContainer.find('li > a > span').each(function(_, el) {
+      var width = $(el).width();
+      if (maximumWidth < width) {
+        maximumWidth = width;
+      }
+    });
+    $btnGroup.removeClass('open');
+    Preview.elements.$activePreviewMode.width(maximumWidth);
+  };
+
+  /**
+   * Renders the "send page to stage" window
+   *
+   * @private
+   */
+  Preview.renderSendPageToStageWindow = function() {
+    var $me = $(this),
+      direction = $me.data('direction'),
+      actionName;
+
+    if (direction === 'prev') {
+      actionName = 'sendPageToPreviousStage';
+    } else if (direction === 'next') {
+      actionName = 'sendPageToNextStage';
+    } else {
+      throw 'Invalid direction ' + direction + ' requested.';
+    }
+
+    Workspaces.sendRemoteRequest(
+      Workspaces.generateRemoteActionsPayload(actionName, [TYPO3.settings.Workspaces.id])
+    ).done(function(response) {
+      var $modal = Workspaces.renderSendToStageWindow(response);
+      $modal.on('button.clicked', function(e) {
+        if (e.target.name === 'ok') {
+          var $form = $(e.currentTarget).find('form'),
+            serializedForm = $form.serializeObject();
+
+          serializedForm.affects = response[0].result.affects;
+          serializedForm.stageId = $me.data('stageId');
+
+          Workspaces.sendRemoteRequest([
+            Workspaces.generateRemoteActionsPayload('sentCollectionToStage', [serializedForm]),
+            Workspaces.generateRemoteActionsPayload('updateStageChangeButtons', [TYPO3.settings.Workspaces.id])
+          ]).done(function(response) {
+            $modal.modal('hide');
+
+            Preview.renderStageButtons(response[1].result);
+          });
+        }
+      });
+    });
+  };
+
+  /**
+   * Changes the preview mode
+   *
+   * @param {Event} e
+   */
+  Preview.changePreviewMode = function(e) {
+    e.preventDefault();
+
+    var $trigger = $(this),
+      currentPreviewMode = Preview.elements.$activePreviewMode.data('activePreviewMode'),
+      newPreviewMode = $trigger.data('previewMode');
+
+    Preview.elements.$activePreviewMode.text($trigger.text()).data('activePreviewMode', newPreviewMode);
+    Preview.elements.$workspacePreview.parent()
+      .removeClass('preview-mode-' + currentPreviewMode)
+      .addClass('preview-mode-' + newPreviewMode);
+
+    if (newPreviewMode === 'slider') {
+      Preview.elements.$stageSlider.parent().toggle(true);
+      Preview.resizeViews();
+    } else {
+      Preview.elements.$stageSlider.parent().toggle(false);
+
+      if (newPreviewMode === 'vbox') {
+        Preview.elements.$liveView.height('100%');
+      } else {
+        Preview.elements.$liveView.height('50%');
+      }
+    }
+
+  };
+
+  /**
+   * Serialize a form to a JavaScript object
+   *
+   * @see http://stackoverflow.com/a/1186309/4828813
+   * @return {Object}
+   */
+  $.fn.serializeObject = function() {
+    var o = {};
+    var a = this.serializeArray();
+    $.each(a, function() {
+      if (typeof o[this.name] !== 'undefined') {
+        if (!o[this.name].push) {
+          o[this.name] = [o[this.name]];
+        }
+        o[this.name].push(this.value || '');
+      } else {
+        o[this.name] = this.value || '';
+      }
+    });
+    return o;
+  };
+
+  $(document).ready(function() {
+    Preview.initialize();
+  });
 });
diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js
index c73d780a5946..11d7380a420d 100644
--- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js
+++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Toolbar/WorkspacesMenu.js
@@ -17,156 +17,156 @@
  * and jump to the workspaces module
  */
 define(['jquery', 'TYPO3/CMS/Backend/Viewport'], function($, Viewport) {
-	'use strict';
-
-	/**
-	 *
-	 * @type {{options: {containerSelector: string, menuItemSelector: string, activeMenuItemSelector: string, toolbarItemSelector: string, workspaceBodyClass: string, workspacesTitleInToolbarClass: string, workspaceModuleLinkSelector: string}}}
-	 * @exports TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu
-	 */
-	var WorkspacesMenu = {
-		options: {
-			containerSelector: '#typo3-cms-workspaces-backend-toolbaritems-workspaceselectortoolbaritem',
-			menuItemSelector: '.t3js-workspaces-switchlink',
-			activeMenuItemSelector: '.dropdown-menu .selected',
-			toolbarItemSelector: '.dropdown-toggle',
-			workspaceBodyClass: 'typo3-in-workspace',	// attached to <body> when in a workspace
-			workspacesTitleInToolbarClass: 'toolbar-item-name',
-			workspaceModuleLinkSelector: '.t3js-workspaces-modulelink'
-		}
-	};
-
-	/**
-	 * registers event listeners
-	 */
-	WorkspacesMenu.initializeEvents = function() {
-
-		// link to the module
-		$(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.workspaceModuleLinkSelector, function(evt) {
-			evt.preventDefault();
-			top.goToModule($(this).data('module'));
-		});
-
-		// observe all clicks on workspace links in the menu
-		$(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.menuItemSelector, function(evt) {
-			evt.preventDefault();
-			WorkspacesMenu.switchWorkspace($(this).data('workspaceid'));
-		});
-	};
-
-	/**
-	 * switches the workspace via AJAX (which returns the new data, as JSON),
-	 * then reloads the module menu, and the content frame
-	 *
-	 * @param {String} workspaceId
-	 */
-	WorkspacesMenu.switchWorkspace = function(workspaceId) {
-		$.ajax({
-			url: TYPO3.settings.ajaxUrls['workspace_switch'],
-			type: 'post',
-			data: {
-				workspaceId: workspaceId,
-				pageId: fsMod.recentIds['web']
-			},
-			success: function(response) {
-				if (!response.workspaceId) {
-					response.workspaceId = 0;
-				}
-
-				WorkspacesMenu.performWorkspaceSwitch(response.workspaceId, response.title);
-
-				// append the returned page ID to the current module URL
-				if (response.pageId) {
-					fsMod.recentIds['web'] = response.pageId;
-					var url = TYPO3.Backend.ContentContainer.getUrl();
-					url += (url.indexOf('?') == -1 ? '?' : '&') + '&id=' + response.pageId;
-					if (TYPO3.Backend.NavigationContainer.PageTree) {
-						TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-					}
-					TYPO3.Backend.ContentContainer.setUrl(url);
-
-				// when in web module reload, otherwise send the user to the web module
-				} else if (currentModuleLoaded.indexOf('web_') === 0) {
-					if (TYPO3.Backend.NavigationContainer.PageTree) {
-						TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
-					}
-					TYPO3.ModuleMenu.App.reloadFrames();
-				} else if (TYPO3.configuration.pageModule) {
-					TYPO3.ModuleMenu.App.showModule(TYPO3.configuration.pageModule);
-				}
-
-				// reload the module menu
-				TYPO3.ModuleMenu.App.refreshMenu();
-			}
-		});
-	};
-
-	/**
-	 * changes the data in the module menu and the updates the backend context
-	 *
-	 * @param {String} id the workspace ID
-	 * @param {String} title the workspace title
-	 */
-	WorkspacesMenu.performWorkspaceSwitch = function(id, title) {
-		top.TYPO3.Backend.workspaceTitle = title;
-		top.TYPO3.configuration.inWorkspace = id !== 0;
-
-		WorkspacesMenu.updateBackendContext(title);
-
-		// first remove all checks, then set the check in front of the selected workspace
-		var stateActiveClass = 'fa fa-check';
-		var stateInactiveClass = 'fa fa-empty-empty';
-
-		// remove "selected" class and checkmark
-		$(WorkspacesMenu.options.activeMenuItemSelector + ' i', WorkspacesMenu.options.containerSelector).removeClass(stateActiveClass).addClass(stateInactiveClass);
-		$(WorkspacesMenu.options.activeMenuItemSelector, WorkspacesMenu.options.containerSelector).removeClass('selected');
-
-		// add "selected" class and checkmark
-		var $activeElement = $(WorkspacesMenu.options.menuItemSelector + '[data-workspaceid=' + id + ']', WorkspacesMenu.options.containerSelector);
-		$activeElement.parent().parent().find('i').removeClass(stateInactiveClass).addClass(stateActiveClass);
-		$activeElement.parent().parent().addClass('selected');
-	};
-
-	/**
-	 * checks if the TYPO3 backend is within a backend context and adds a class
-	 * also updates the workspaces title
-	 *
-	 * @param {String} title
-	 */
-	WorkspacesMenu.updateBackendContext = function(title) {
-
-		if (TYPO3.configuration.inWorkspace) {
-			$('body').addClass(WorkspacesMenu.options.workspaceBodyClass);
-			WorkspacesMenu.updateTopBar(title || TYPO3.lang['Workspaces.workspaceTitle']);
-		} else {
-			$('body').removeClass(WorkspacesMenu.options.workspaceBodyClass);
-			WorkspacesMenu.updateTopBar();
-		}
-	};
-
-	/**
-	 * adds the workspace title to the toolbar next to the username
-	 *
-	 * @param {String} workspaceTitle
-	 */
-	WorkspacesMenu.updateTopBar = function(workspaceTitle) {
-		$('.' + WorkspacesMenu.options.workspacesTitleInToolbarClass, WorkspacesMenu.options.containerSelector).remove();
-
-		if (workspaceTitle && workspaceTitle.length) {
-			var title = $('<span>', {
-				'class': WorkspacesMenu.options.workspacesTitleInToolbarClass
-			}).text(workspaceTitle);
-			$(WorkspacesMenu.options.toolbarItemSelector, WorkspacesMenu.options.containerSelector).append(title);
-		}
-	};
-
-	Viewport.Topbar.Toolbar.registerEvent(function() {
-		WorkspacesMenu.initializeEvents();
-		WorkspacesMenu.updateBackendContext();
-	});
-
-	// expose the module in a global object
-	TYPO3.WorkspacesMenu = WorkspacesMenu;
-
-	return WorkspacesMenu;
+  'use strict';
+
+  /**
+   *
+   * @type {{options: {containerSelector: string, menuItemSelector: string, activeMenuItemSelector: string, toolbarItemSelector: string, workspaceBodyClass: string, workspacesTitleInToolbarClass: string, workspaceModuleLinkSelector: string}}}
+   * @exports TYPO3/CMS/Workspaces/Toolbar/WorkspacesMenu
+   */
+  var WorkspacesMenu = {
+    options: {
+      containerSelector: '#typo3-cms-workspaces-backend-toolbaritems-workspaceselectortoolbaritem',
+      menuItemSelector: '.t3js-workspaces-switchlink',
+      activeMenuItemSelector: '.dropdown-menu .selected',
+      toolbarItemSelector: '.dropdown-toggle',
+      workspaceBodyClass: 'typo3-in-workspace',	// attached to <body> when in a workspace
+      workspacesTitleInToolbarClass: 'toolbar-item-name',
+      workspaceModuleLinkSelector: '.t3js-workspaces-modulelink'
+    }
+  };
+
+  /**
+   * registers event listeners
+   */
+  WorkspacesMenu.initializeEvents = function() {
+
+    // link to the module
+    $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.workspaceModuleLinkSelector, function(evt) {
+      evt.preventDefault();
+      top.goToModule($(this).data('module'));
+    });
+
+    // observe all clicks on workspace links in the menu
+    $(WorkspacesMenu.options.containerSelector).on('click', WorkspacesMenu.options.menuItemSelector, function(evt) {
+      evt.preventDefault();
+      WorkspacesMenu.switchWorkspace($(this).data('workspaceid'));
+    });
+  };
+
+  /**
+   * switches the workspace via AJAX (which returns the new data, as JSON),
+   * then reloads the module menu, and the content frame
+   *
+   * @param {String} workspaceId
+   */
+  WorkspacesMenu.switchWorkspace = function(workspaceId) {
+    $.ajax({
+      url: TYPO3.settings.ajaxUrls['workspace_switch'],
+      type: 'post',
+      data: {
+        workspaceId: workspaceId,
+        pageId: fsMod.recentIds['web']
+      },
+      success: function(response) {
+        if (!response.workspaceId) {
+          response.workspaceId = 0;
+        }
+
+        WorkspacesMenu.performWorkspaceSwitch(response.workspaceId, response.title);
+
+        // append the returned page ID to the current module URL
+        if (response.pageId) {
+          fsMod.recentIds['web'] = response.pageId;
+          var url = TYPO3.Backend.ContentContainer.getUrl();
+          url += (url.indexOf('?') == -1 ? '?' : '&') + '&id=' + response.pageId;
+          if (TYPO3.Backend.NavigationContainer.PageTree) {
+            TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+          }
+          TYPO3.Backend.ContentContainer.setUrl(url);
+
+          // when in web module reload, otherwise send the user to the web module
+        } else if (currentModuleLoaded.indexOf('web_') === 0) {
+          if (TYPO3.Backend.NavigationContainer.PageTree) {
+            TYPO3.Backend.NavigationContainer.PageTree.refreshTree();
+          }
+          TYPO3.ModuleMenu.App.reloadFrames();
+        } else if (TYPO3.configuration.pageModule) {
+          TYPO3.ModuleMenu.App.showModule(TYPO3.configuration.pageModule);
+        }
+
+        // reload the module menu
+        TYPO3.ModuleMenu.App.refreshMenu();
+      }
+    });
+  };
+
+  /**
+   * changes the data in the module menu and the updates the backend context
+   *
+   * @param {String} id the workspace ID
+   * @param {String} title the workspace title
+   */
+  WorkspacesMenu.performWorkspaceSwitch = function(id, title) {
+    top.TYPO3.Backend.workspaceTitle = title;
+    top.TYPO3.configuration.inWorkspace = id !== 0;
+
+    WorkspacesMenu.updateBackendContext(title);
+
+    // first remove all checks, then set the check in front of the selected workspace
+    var stateActiveClass = 'fa fa-check';
+    var stateInactiveClass = 'fa fa-empty-empty';
+
+    // remove "selected" class and checkmark
+    $(WorkspacesMenu.options.activeMenuItemSelector + ' i', WorkspacesMenu.options.containerSelector).removeClass(stateActiveClass).addClass(stateInactiveClass);
+    $(WorkspacesMenu.options.activeMenuItemSelector, WorkspacesMenu.options.containerSelector).removeClass('selected');
+
+    // add "selected" class and checkmark
+    var $activeElement = $(WorkspacesMenu.options.menuItemSelector + '[data-workspaceid=' + id + ']', WorkspacesMenu.options.containerSelector);
+    $activeElement.parent().parent().find('i').removeClass(stateInactiveClass).addClass(stateActiveClass);
+    $activeElement.parent().parent().addClass('selected');
+  };
+
+  /**
+   * checks if the TYPO3 backend is within a backend context and adds a class
+   * also updates the workspaces title
+   *
+   * @param {String} title
+   */
+  WorkspacesMenu.updateBackendContext = function(title) {
+
+    if (TYPO3.configuration.inWorkspace) {
+      $('body').addClass(WorkspacesMenu.options.workspaceBodyClass);
+      WorkspacesMenu.updateTopBar(title || TYPO3.lang['Workspaces.workspaceTitle']);
+    } else {
+      $('body').removeClass(WorkspacesMenu.options.workspaceBodyClass);
+      WorkspacesMenu.updateTopBar();
+    }
+  };
+
+  /**
+   * adds the workspace title to the toolbar next to the username
+   *
+   * @param {String} workspaceTitle
+   */
+  WorkspacesMenu.updateTopBar = function(workspaceTitle) {
+    $('.' + WorkspacesMenu.options.workspacesTitleInToolbarClass, WorkspacesMenu.options.containerSelector).remove();
+
+    if (workspaceTitle && workspaceTitle.length) {
+      var title = $('<span>', {
+        'class': WorkspacesMenu.options.workspacesTitleInToolbarClass
+      }).text(workspaceTitle);
+      $(WorkspacesMenu.options.toolbarItemSelector, WorkspacesMenu.options.containerSelector).append(title);
+    }
+  };
+
+  Viewport.Topbar.Toolbar.registerEvent(function() {
+    WorkspacesMenu.initializeEvents();
+    WorkspacesMenu.updateBackendContext();
+  });
+
+  // expose the module in a global object
+  TYPO3.WorkspacesMenu = WorkspacesMenu;
+
+  return WorkspacesMenu;
 });
diff --git a/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js b/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js
index 52f50e95e7d6..adcf2d3301ac 100644
--- a/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js
+++ b/typo3/sysext/workspaces/Resources/Public/JavaScript/Workspaces.js
@@ -16,201 +16,220 @@
  * RequireJS module for Workspaces
  */
 define([
-	'jquery',
-	'TYPO3/CMS/Backend/Severity',
-	'TYPO3/CMS/Backend/Modal'
+  'jquery',
+  'TYPO3/CMS/Backend/Severity',
+  'TYPO3/CMS/Backend/Modal'
 ], function($, Severity, Modal) {
-	'use strict';
-
-	var Workspaces = {
-		tid: 0
-	};
-
-	/**
-	 * Renders the send to stage window
-	 * @param {Object} response
-	 * @return {$}
-	 */
-	Workspaces.renderSendToStageWindow = function(response) {
-		var result = response[0].result,
-			$form = $('<form />');
-
-		if (typeof result.sendMailTo !== 'undefined' && result.sendMailTo.length > 0) {
-			$form.append(
-				$('<label />', {class: 'control-label'}).text(TYPO3.lang['window.sendToNextStageWindow.itemsWillBeSentTo'])
-			);
-
-			for (var i = 0; i < result.sendMailTo.length; ++i) {
-				var recipient = result.sendMailTo[i];
-
-				$form.append(
-					$('<div />', {class: 'checkbox'}).append(
-						$('<label />').text(recipient.label).prepend(
-							$('<input />', {type: 'checkbox', name: 'recipients', id: recipient.name, value: recipient.value}).prop('checked', recipient.checked).prop('disabled', recipient.disabled)
-						)
-					)
-				);
-			}
-		}
-
-		if (typeof result.additional !== 'undefined') {
-			$form.append(
-				$('<div />', {class: 'form-group'}).append(
-					$('<label />', {class: 'control-label', 'for': 'additional'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients']),
-					$('<textarea />', {class: 'form-control', name: 'additional', id: 'additional'}).text(result.additional.value),
-					$('<span />', {class: 'help-block'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients.hint'])
-				)
-			);
-		}
-
-		$form.append(
-			$('<div />', {class: 'form-group'}).append(
-				$('<label />', {class: 'control-label', 'for': 'comments'}).text(TYPO3.lang['window.sendToNextStageWindow.comments']),
-				$('<textarea />', {class: 'form-control', name: 'comments', id: 'comments'}).text(result.comments.value)
-			)
-		);
-
-		var $modal = Modal.show(
-			TYPO3.lang['actionSendToStage'],
-			$form,
-			Severity.info,
-			[
-				{
-					text: TYPO3.lang['cancel'],
-					active: true,
-					btnClass: 'btn-default',
-					name: 'cancel',
-					trigger: function() {
-						$modal.modal('hide');
-					}
-				}, {
-				text: TYPO3.lang['ok'],
-				btnClass: 'btn-info',
-				name: 'ok'
-			}
-			]
-		);
-
-		return $modal;
-	};
-
-	/**
-	 * Checks the integrity of a record
-	 *
-	 * @param {Array} payload
-	 * @return {$}
-	 */
-	Workspaces.checkIntegrity = function(payload) {
-		return Workspaces.sendRemoteRequest(
-			Workspaces.generateRemotePayload('checkIntegrity', payload)
-		);
-	};
-
-	/**
-	 * Sends an AJAX request
-	 *
-	 * @param {Object} payload
-	 * @return {$}
-	 */
-	Workspaces.sendRemoteRequest = function(payload) {
-		return $.ajax({
-			url: TYPO3.settings.ajaxUrls['workspace_dispatch'],
-			method: 'POST',
-			contentType: 'application/json; charset=utf-8',
-			dataType: 'json',
-			data: JSON.stringify(payload)
-		});
-	};
-
-	/**
-	 * Generates the payload for a remote call
-	 *
-	 * @param {String} method
-	 * @param {Object} data
-	 * @return {{action, data, method, type}}
-	 */
-	Workspaces.generateRemotePayload = function(method, data) {
-		if (typeof data === 'undefined') {
-			data = {};
-		}
-		return Workspaces.generateRemotePayloadBody('RemoteServer', method, data);
-	};
-
-	/**
-	 * Generates the payload for MassActions
-	 *
-	 * @param {String} method
-	 * @param {Object} data
-	 * @return {{action, data, method, type}}
-	 */
-	Workspaces.generateRemoteMassActionsPayload = function(method, data) {
-		if (typeof data === 'undefined') {
-			data = {};
-		}
-		return Workspaces.generateRemotePayloadBody('MassActions', method, data);
-	};
-
-	/**
-	 * Generates the payload for Actions
-	 *
-	 * @param {String} method
-	 * @param {Object} data
-	 * @return {{action, data, method, type}}
-	 */
-	Workspaces.generateRemoteActionsPayload = function(method, data) {
-		if (typeof data === 'undefined') {
-			data = [];
-		}
-		return Workspaces.generateRemotePayloadBody('Actions', method, data);
-	};
-
-	/**
-	 * Generates the payload body
-	 *
-	 * @param {String} action
-	 * @param {String} method
-	 * @param {Object} data
-	 * @return {{action: String, data: Object, method: String, type: string}}
-	 */
-	Workspaces.generateRemotePayloadBody = function(action, method, data) {
-		if (data instanceof Array) {
-			data.push(TYPO3.settings.Workspaces.token);
-		} else {
-			data = [
-				data,
-				TYPO3.settings.Workspaces.token
-			];
-		}
-		return {
-			action: action,
-			data: data,
-			method: method,
-			type: 'rpc',
-			tid: Workspaces.tid++
-		};
-	};
-
-	/**
-	 * Serialize a form to a JavaScript object
-	 *
-	 * @see http://stackoverflow.com/a/1186309/4828813
-	 * @return {Object}
-	 */
-	$.fn.serializeObject = function() {
-		var o = {};
-		var a = this.serializeArray();
-		$.each(a, function() {
-			if (typeof o[this.name] !== 'undefined') {
-				if (!o[this.name].push) {
-					o[this.name] = [o[this.name]];
-				}
-				o[this.name].push(this.value || '');
-			} else {
-				o[this.name] = this.value || '';
-			}
-		});
-		return o;
-	};
-
-	return Workspaces;
+  'use strict';
+
+  var Workspaces = {
+    tid: 0
+  };
+
+  /**
+   * Renders the send to stage window
+   * @param {Object} response
+   * @return {$}
+   */
+  Workspaces.renderSendToStageWindow = function(response) {
+    var result = response[0].result,
+      $form = $('<form />');
+
+    if (typeof result.sendMailTo !== 'undefined' && result.sendMailTo.length > 0) {
+      $form.append(
+        $('<label />', {class: 'control-label'}).text(TYPO3.lang['window.sendToNextStageWindow.itemsWillBeSentTo'])
+      );
+
+      for (var i = 0; i < result.sendMailTo.length; ++i) {
+        var recipient = result.sendMailTo[i];
+
+        $form.append(
+          $('<div />', {class: 'checkbox'}).append(
+            $('<label />').text(recipient.label).prepend(
+              $('<input />', {
+                type: 'checkbox',
+                name: 'recipients',
+                id: recipient.name,
+                value: recipient.value
+              }).prop('checked', recipient.checked).prop('disabled', recipient.disabled)
+            )
+          )
+        );
+      }
+    }
+
+    if (typeof result.additional !== 'undefined') {
+      $form.append(
+        $('<div />', {class: 'form-group'}).append(
+          $('<label />', {
+            class: 'control-label',
+            'for': 'additional'
+          }).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients']),
+          $('<textarea />', {
+            class: 'form-control',
+            name: 'additional',
+            id: 'additional'
+          }).text(result.additional.value),
+          $('<span />', {class: 'help-block'}).text(TYPO3.lang['window.sendToNextStageWindow.additionalRecipients.hint'])
+        )
+      );
+    }
+
+    $form.append(
+      $('<div />', {class: 'form-group'}).append(
+        $('<label />', {
+          class: 'control-label',
+          'for': 'comments'
+        }).text(TYPO3.lang['window.sendToNextStageWindow.comments']),
+        $('<textarea />', {
+          class: 'form-control',
+          name: 'comments',
+          id: 'comments'
+        }).text(result.comments.value)
+      )
+    );
+
+    var $modal = Modal.show(
+      TYPO3.lang['actionSendToStage'],
+      $form,
+      Severity.info,
+      [
+        {
+          text: TYPO3.lang['cancel'],
+          active: true,
+          btnClass: 'btn-default',
+          name: 'cancel',
+          trigger: function() {
+            $modal.modal('hide');
+          }
+        }, {
+        text: TYPO3.lang['ok'],
+        btnClass: 'btn-info',
+        name: 'ok'
+      }
+      ]
+    );
+
+    return $modal;
+  };
+
+  /**
+   * Checks the integrity of a record
+   *
+   * @param {Array} payload
+   * @return {$}
+   */
+  Workspaces.checkIntegrity = function(payload) {
+    return Workspaces.sendRemoteRequest(
+      Workspaces.generateRemotePayload('checkIntegrity', payload)
+    );
+  };
+
+  /**
+   * Sends an AJAX request
+   *
+   * @param {Object} payload
+   * @return {$}
+   */
+  Workspaces.sendRemoteRequest = function(payload) {
+    return $.ajax({
+      url: TYPO3.settings.ajaxUrls['workspace_dispatch'],
+      method: 'POST',
+      contentType: 'application/json; charset=utf-8',
+      dataType: 'json',
+      data: JSON.stringify(payload)
+    });
+  };
+
+  /**
+   * Generates the payload for a remote call
+   *
+   * @param {String} method
+   * @param {Object} data
+   * @return {{action, data, method, type}}
+   */
+  Workspaces.generateRemotePayload = function(method, data) {
+    if (typeof data === 'undefined') {
+      data = {};
+    }
+    return Workspaces.generateRemotePayloadBody('RemoteServer', method, data);
+  };
+
+  /**
+   * Generates the payload for MassActions
+   *
+   * @param {String} method
+   * @param {Object} data
+   * @return {{action, data, method, type}}
+   */
+  Workspaces.generateRemoteMassActionsPayload = function(method, data) {
+    if (typeof data === 'undefined') {
+      data = {};
+    }
+    return Workspaces.generateRemotePayloadBody('MassActions', method, data);
+  };
+
+  /**
+   * Generates the payload for Actions
+   *
+   * @param {String} method
+   * @param {Object} data
+   * @return {{action, data, method, type}}
+   */
+  Workspaces.generateRemoteActionsPayload = function(method, data) {
+    if (typeof data === 'undefined') {
+      data = [];
+    }
+    return Workspaces.generateRemotePayloadBody('Actions', method, data);
+  };
+
+  /**
+   * Generates the payload body
+   *
+   * @param {String} action
+   * @param {String} method
+   * @param {Object} data
+   * @return {{action: String, data: Object, method: String, type: string}}
+   */
+  Workspaces.generateRemotePayloadBody = function(action, method, data) {
+    if (data instanceof Array) {
+      data.push(TYPO3.settings.Workspaces.token);
+    } else {
+      data = [
+        data,
+        TYPO3.settings.Workspaces.token
+      ];
+    }
+    return {
+      action: action,
+      data: data,
+      method: method,
+      type: 'rpc',
+      tid: Workspaces.tid++
+    };
+  };
+
+  /**
+   * Serialize a form to a JavaScript object
+   *
+   * @see http://stackoverflow.com/a/1186309/4828813
+   * @return {Object}
+   */
+  $.fn.serializeObject = function() {
+    var o = {};
+    var a = this.serializeArray();
+    $.each(a, function() {
+      if (typeof o[this.name] !== 'undefined') {
+        if (!o[this.name].push) {
+          o[this.name] = [o[this.name]];
+        }
+        o[this.name].push(this.value || '');
+      } else {
+        o[this.name] = this.value || '';
+      }
+    });
+    return o;
+  };
+
+  return Workspaces;
 });
-- 
GitLab