diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69bee416733fb2a5d668b1a0b749d91c5ebfe3ea..1c54ae07765ab72a70b010cb938bcf765718b2a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,63 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
+Version 18.6.0
+--------------
+
+Date: 13.06.2018
+
+Notes
+^^^^^
+
+* config.qfq.ini migrated to config.qfq.php - the old config.qfq.ini get's `chmod 000`.
+* Most of config.qfq.ini migrated to Typo3 / Extension Manager - all but the DB /LDAP credentials.
+* Keep in config.qfq.ini: ::
+
+    # Rename DB credentials from DB_<key> to DB_1_<key>, with key = 'NAME|HOST|USER|PASSWORD'
+    DB_1_USER = ...
+    DB_1_SERVER = ...
+    DB_1_PASSWORD = ...
+    DB_1_NAME = ...
+
+* NEW: Drag and drop to sort elements! Check the Manual.
+* `URL forwardMode`
+
+  * `client` renamed to `auto`.
+  * `close` added.
+
+Features
+^^^^^^^^
+
+ * #6100 / Url Forward Auto: Update Manual.rst. The F.parameter.saveAndClose has been removed again. Mode 'close' can be assigned statically or dynamic.
+ * #6178 / Input: Step: New option 'step' for FE.parameter.
+ * Download.php: references to non existing files now reported as missing file, not 'wrong mimetype' anymore.
+ * #4918 / Drag'n'Drop reorder elements DRAGANDDROP.md, PROTOCOL.md: Doc for "drag'n' drop" implementation.
+   dragAndDrop.php: API endpoint DragAndDrop.php: Class for implementing drag'n' drop functionality.
+   Link.php: implement new renderMode=8 - returning only the sip. QuickFormQuery.php: New entry point for processing "drag'n' drop".
+ * #3971 / Form title: new design from form title
+
+Bug Fixes
+^^^^^^^^^
+
+* #5077 / Dynamic Update & FE.type=required: Server fixed -
+
+  a) dynamic calculated modeSql respected,
+  b) formModeGlobal=requiredOff respected,
+  c) dynamic FE with mode='hidden' are not saved anymore.
+
+ * #6176 / Icon not aligned when error text: Buttons now wrapped in one 'input-group'.
+ * Manual.rst: reformat autocron QFQ code
+ * #5880 / Skip Error Message during dynamicUpdate
+ * #5870 / Missing file config.qfq.ini: Clean QFQ message
+ * #5924 / config.qfq.ini/LocalConfiguration.php: several places in formEditor.sql still contained the 'dbIndex...'
+   instead of 'index...'. fixed.
+ * #6168 Configuration language setting ignored: Form and FormElement editor still used uppercase config values for
+   language configuration. Updated to the new camel case notation.
+ * #5890 / config.qfq.ini is public readable. Renamed file to config.qfq.php. Implement a basic migration assistant to
+   copy DB credentials to new config.qfq.php. All other values have to be copied to extmanager/qfq-configuration manually.
+ * #6216 / Oops, an error occurred! Code - unhandled exception will be caught now.
+
+
 Version 18.4.4
 --------------
 
@@ -119,7 +176,7 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
-* #5706 Fixed that problematic characters in 'fileDestination' has not been sanatized.
+* #5706 / Fixed that problematic characters in 'fileDestination' has not been sanatized.
 * Fixed problem with buttons clipping trough alert
 * Client: wrong variable, updated CSS for long errors
 
diff --git a/Makefile b/Makefile
index 9e5c4b876e28c6de75c97d6a4b9fe8d43fb3b871..8c1d6f4ce5185438abdfa71b4a5d91c012023cd8 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ RELEASE_DATE = $(shell date '+%Y%m%d%H%M')
 GIT_REVISION_SHORT = $(shell git rev-parse --short HEAD || true)
 GIT_REVISION_LONG = $(shell git rev-parse HEAD || true)
 
-EXTENSION_CONTENT = Classes Configuration Documentation qfq Resources ext_emconf.php ext_localconf.php ext_tables.php ext_icon.png ext_conf_template.txt config.qfq.example.ini RELEASE.txt
+EXTENSION_CONTENT = Classes Configuration Documentation qfq Resources ext_emconf.php ext_localconf.php ext_tables.php ext_icon.png ext_conf_template.txt config.qfq.example.php RELEASE.txt
 
 DISTDIR=dist
 
diff --git a/doc/DRAGANDDROP.md b/doc/DRAGANDDROP.md
new file mode 100644
index 0000000000000000000000000000000000000000..14d9b9cd5216ac4d23fdc6d8b618fc8810067b7b
--- /dev/null
+++ b/doc/DRAGANDDROP.md
@@ -0,0 +1,22 @@
+# Drag And Drop
+
+## Sort
+Initialize a dnd container by adding the class "qfq-dnd"
+
+Set container object class to `class="qfq-dnd qfq-dnd-sort"`.
+
+Add the data elements: `data-dnd-api="url"` and `data-dnd-key="key"`.
+
+For the children inside of the container (just the first children):
+add `data-dnd-id` to a reference you can handle (probably record id).
+
+Request will be sent containing following GET variables:
+
+* dragId = `data-dnd-id` of the dragged object,
+* dragPosition = client internal old position of the dragged object.
+* setTo = "after" or "before",
+* hoverId = `data-dnd-id` id of the element the dragged element is now hovering, meaning before or after.
+* hoverPosition = client internal position of currently hovered element.
+
+
+Example: http://something/bla?dragId=uno&dragPosition=1&setTo=before&hoverId=tre&hoverPosition=3
\ No newline at end of file
diff --git a/doc/NewVersion.md b/doc/NewVersion.md
index f467e14aef1b04f2d7d16fd1320f4a38f4d53414..e232462f7457d7c2d0bc8847d6b15051338ed376 100644
--- a/doc/NewVersion.md
+++ b/doc/NewVersion.md
@@ -47,8 +47,8 @@ Neue Versionsnummer
 
 6) **New Tag**: 
 
-   git tag v18.4.4
-   git push -u origin v18.4.4
+   git tag v18.6.0
+   git push -u origin v18.6.0
 
 7) PhpStorm: **Sync** all files to VM qfq.
 
diff --git a/doc/PROTOCOL.md b/doc/PROTOCOL.md
index a7fa4211f1225e2f9a6fd9087b573729d519b2ac..0e8157dd00fc56cc3baf719aa593eec98ef73bac 100644
--- a/doc/PROTOCOL.md
+++ b/doc/PROTOCOL.md
@@ -73,11 +73,11 @@ the Client by adding following name/value pairs to the response JSON
 Stream
 
 	{
-		"status": "error",
-		...
-	   "field-name": "<field name>",
-		"field-message": "<message>",
-		...
+        "status": "error",
+        ...
+        "field-name": "<field name>",
+        "field-message": "<message>",
+        ...
 	}
 	
 Only one validation failure per request can be reported to Client.
@@ -224,18 +224,22 @@ The format of redirect information is outlined below
 
 	{
 		...
-		"redirect": "no" | "url" | "url-skip-history" | "client"
+		"redirect": "no" | "url" | "url-skip-history" | "auto" | "close"
 		"redirect-url": "<url>"
 		...
 	}
 	
 
 `"redirect"`
-:	type of redirection. `"no"` advises the Client to stay on the
-	Current Page. `"client"` advises the Client to decide where to
-	redirect to. `"url"` advices the Client to redirect to the URL
-	provided in `"redirect-url"`. `"url-skip-history"` behaves like
-	`"url"` but the current page will skip the browser history.
+:	type of redirection. 
+
+ * `"no"` advises the Client to stay on the	Current Page. 
+ * `"close"` the client goes back one in history - if there is no history, stays on the same page.
+ * `"auto"` the Client decide where to redirect to.
+   * if the user clicks 'save', stay on the same page.
+   * if the user clicks 'close', go back one in history - if there is no history, stays on the same page. 
+ * `"url"` advices the Client to redirect to the URL provided in `"redirect-url"`. 
+ * `"url-skip-history"` behaves like `"url"` but the current page will skip the browser history.
 	
 `"redirect-url"`
 :	Used to provide an URL when `"redirect"` is set to `"url"`. It
@@ -465,7 +469,7 @@ Request Method
 :	GET
 
 URL Parameters
-:	`s=<SIP>`   (form, r)
+:  `s=<SIP>`   (form, r)
 :  `action=lock`, `action=extend`, `action=release>`
 :  `recordHashMd5=<value of hidden form element 'recordHashMd5'>`
 
@@ -479,7 +483,7 @@ JSON Response from the server (extended [Minimal Response]) containing:
 
 	{
 		"status": "success"|"error"|"conflict"|"conflict_allow_force",
-		"message": "<message>"
+		"message": "<message>"e5
     }
    
 `status` indicates how the request has been fulfilled by the server. 
@@ -488,6 +492,29 @@ On one of`"error"|"conflict"|"conflict_allow_force"` the Client must display `"<
 On `"conflict"` the Client opens the alert as modal dialog (user can't change anything on the form) with a 'reload current
 form' button.
 On `"conflict_allow_force"` the Client opens the alert non-modal (default).
+
+
+### Drag And Drop (sort)
+
+Request
+:	api/dragAndDrop.php
+
+Request Method
+:	GET
+
+URL Parameters:
+
+: `s=<SIP>`  (`form=<formname>`)
+:  
+: `dragId=<data-dnd-id of dragged element>`
+: `dragPosition=<client internal position (numbering) of element before dragging>`
+: `setTo=before`, `setTo=after`
+: `hoverId=<data-dnd-id of dragged element>`
+: `hoverPosition=<client internal position (numbering) of element after dragging>`
+
+Server Response
+:   The response contains at least a [Minimal Response]. In addition, a
+	[HTML Element Update] may be included.
   
 ## Glossary
 
diff --git a/extension/Classes/Controller/QfqController.php b/extension/Classes/Controller/QfqController.php
index b62115c9ab10b59aab82fc6a6abe264555af7e17..508c9d3efd760386b2d0deacd908bdd61897a5a1 100644
--- a/extension/Classes/Controller/QfqController.php
+++ b/extension/Classes/Controller/QfqController.php
@@ -13,8 +13,17 @@ require_once(__DIR__ . '/../../qfq/qfq/exceptions/UserReportException.php');
 require_once(__DIR__ . '/../../qfq/qfq/exceptions/CodeException.php');
 require_once(__DIR__ . '/../../qfq/qfq/exceptions/DbException.php');
 
+/**
+ * Class QfqController
+ * @package IMATHUZH\Qfq\Controller
+ */
 class QfqController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
 
+    /**
+     * @return string
+     * @throws qfq\CodeException
+     * @throws qfq\UserFormException
+     */
     public function showAction() {
 
         $origErrorReporting = '';
diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst
index 353e8e9ea3f7bccee6bcf629c9283d38a50bfd5d..a8bb18561c426e19813d07c9c66e9846ecdb45db 100644
--- a/extension/Documentation/Manual.rst
+++ b/extension/Documentation/Manual.rst
@@ -150,6 +150,8 @@ via commandline options. A basic HTML email support is implemented.
 The latest version is v1.56, which has at least one bug. That one is patched in the QFQ internal version v1.56p1 (see
 QFQ GIT sources in directory 'patches/sendEmail.patch').
 
+Nevertheless, on latest system the TLS support is broken - please check _`sendEmailProblem`.
+
 The Typo3 sendmail eco-system is not used at all by QFQ.
 
 Thumbnail
@@ -172,7 +174,7 @@ Setup
 
   * If the Extensionmanager stops after importing: check your memory limit in php.ini.
 
-* Copy/rename the file *<site path>/typo3conf/ext/qfq/config.example.qfq.ini* to *config.qfq.in*.
+* Copy/rename the file *<site path>/typo3conf/ext/qfq/config.example.qfq.php* to *config.qfq.php*.
   Configure the necessary settings `configuration`_
   The configuration file is outside the of extension directory, to not loose it during updates.
 * When the QFQ Extension is called the first time on the Typo3 Frontend, the file *<ext_dir>/qfq/sql/formEditor.sql* will
@@ -226,36 +228,34 @@ Setup a *report* to manage all *forms*:
 * Create a Typo3 page.
 * Set the 'URL Alias' to `form` (default) or the individual defined value in parameter `editFormPage` (configuration_).
 * Insert a content record of type *qfq*.
-* In the bodytext insert the following code:
-
-::
+* In the bodytext insert the following code: ::
 
-	# If there is a form given by SIP: show
-	form={{form:SE}}
+    # If there is a form given by SIP: show
+    form={{form:SE}}
 
-	# In case indexQfq is different from indexData, set indexQfq.
-	dbIndex = {{indexQfq:Y}}
+    # In case indexQfq is different from indexData, set indexQfq.
+    dbIndex = {{indexQfq:Y}}
 
-	10 {
-		# List of Forms: Do not show this list of forms if there is a form given by SIP.
-		# Table header.
-		sql = SELECT CONCAT('p:{{pageId:T}}&form=form') as _pagen, '#', 'Name', 'Title', 'Table', '' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'=''
-		head = <table class="table table-hover qfq-table-50">
-		tail = </table>
-		rbeg = <thead><tr>
-		rend = </tr></thead>
-		fbeg = <th>
-		fend = </th>
-
-		10 {
-			# All forms
-			sql = SELECT CONCAT('p:{{pageId:T}}&form=form&r=', f.id) as _pagee, f.id, f.name, f.title, f.tableName, CONCAT('form=form&r=', f.id) as _Paged FROM Form AS f ORDER BY f.name
-			rbeg = <tr>
-			rend = </tr>
-			fbeg = <td>
-			fend = </td>
-		}
-	}
+    10 {
+        # List of Forms: Do not show this list of forms if there is a form given by SIP.
+        # Table header.
+        sql = SELECT CONCAT('p:{{pageId:T}}&form=form') as _pagen, '#', 'Name', 'Title', 'Table', '' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'=''
+        head = <table class="table table-hover qfq-table-50">
+        tail = </table>
+        rbeg = <thead><tr>
+        rend = </tr></thead>
+        fbeg = <th>
+        fend = </th>
+
+        10 {
+            # All forms
+            sql = SELECT CONCAT('p:{{pageId:T}}&form=form&r=', f.id) as _pagee, f.id, f.name, f.title, f.tableName, CONCAT('form=form&r=', f.id) as _Paged FROM Form AS f ORDER BY f.name
+            rbeg = <tr>
+            rend = </tr>
+            fbeg = <td>
+            fend = </td>
+        }
+    }
 
 .. _install-checklist:
 
@@ -300,7 +300,7 @@ Extension Manager: QFQ Configuration
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | sendEMailOptions              | -o tls=yes                                            | General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| dateFormat                    | yyyy-mm-dd                                            | Possible options: yyyy-mm-dd, dd.mm.yyyy                                   |
+| dateFormat                    | yyyy-mm-dd                                            | Possible options: yyyy-mm-dd, dd.mm.yyyy.                                  |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | Dynamic                                                                                                                                                            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
@@ -334,44 +334,44 @@ Extension Manager: QFQ Configuration
 |                               |                                                       | time QFQ is called - *not* recommended!                                    |
 |                               |                                                       | 'never': never apply DB Updates.                                           |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| indexData                     | 1                                                     | Optional. Default: 1. Retrieve the current setting via {{_dbNameData:Y}}   |
+| indexData                     | 1                                                     | Optional. Default: 1. Retrieve the current setting via {{_dbNameData:Y}}.  |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| indexQfq                      | 1                                                     | Optional. Default: 1. Retrieve the current setting via {{_dbNameQfq:Y}}    |
+| indexQfq                      | 1                                                     | Optional. Default: 1. Retrieve the current setting via {{_dbNameQfq:Y}}.   |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | Security                                                                                                                                                           |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | escapeTypeDefault             | m                                                     | All variables `{{...}}` get this escape class by default.                  |
 |                               |                                                       | See `variable-escape`_.                                                    |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| securityVarsHoneypot          | email,username,password                               | If empty: no check. All named variables will rendered as INPUT elements    |
+| securityVarsHoneypot          | email,username,password                               | If empty: no check. All named variables will rendered as INPUT elements.   |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| securityAttackDelay           | 5                                                     | If an attack is detected, sleep 'x' seconds and exit PHP process           |
+| securityAttackDelay           | 5                                                     | If an attack is detected, sleep 'x' seconds and exit PHP process.          |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| securityShowMessage           | true                                                  | If an attack is detected, show a message                                   |
+| securityShowMessage           | true                                                  | If an attack is detected, show a message.                                  |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | securityGetMaxLength          | 50                                                    | GET vars longer than 'x' chars triggers an `attack-recognized`.            |
-|                               |                                                       | `ExceptionMaxLength`_                                                      |
+|                               |                                                       | `ExceptionMaxLength`_.                                                     |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | Form-Config                                                                                                                                                        |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| recordLockTimeoutSeconds      | 900                                                   | Timeout for record locking. After this time, a record will be replaced     |
+| recordLockTimeoutSeconds      | 900                                                   | Timeout for record locking. After this time, a record will be replaced.    |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| enterAsSubmit                 | enterAsSubmit = 1                                     | 0: off, 1: Pressing *enter* in a form means *save* and *close*             |
+| enterAsSubmit                 | enterAsSubmit = 1                                     | 0: off, 1: Pressing *enter* in a form means *save* and *close*.            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | editFormPage                  | form                                                  | T3 Pagealias to edit a form.                                               |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formDataPatternError          | please check pattern error                            | Customizable error message used in validator.js. 'pattern' violation       |
+| formDataPatternError          | please check pattern error                            | Customizable error message used in validator.js. 'pattern' violation.      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formDataRequiredError         | missing value                                         | Customizable error message used in validator.js. 'required' fields         |
+| formDataRequiredError         | missing value                                         | Customizable error message used in validator.js. 'required' fields.        |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formDataMatchError            | type error                                            | Customizable error message used in validator.js. 'match' retype mismatch   |
+| formDataMatchError            | type error                                            | Customizable error message used in validator.js. 'match' retype mismatch.  |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formDataError                 | generic error                                         | Customizable error message used in validator.js. 'no specific' given       |
+| formDataError                 | generic error                                         | Customizable error message used in validator.js. 'no specific' given.      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | Form-Layout                                                                                                                                                        |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | cssClassQfqContainer          | container                                             | QFQ with own Bootstrap: 'container'.                                       |
-|                               |                                                       | QFQ already nested in Bootstrap of mainpage: <empty>                       |
+|                               |                                                       | QFQ already nested in Bootstrap of mainpage: <empty>.                      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | cssClassQfqForm               | qfq-color-base                                        | Wrap around QFQ 'Form'.                                                    |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
@@ -379,21 +379,21 @@ Extension Manager: QFQ Configuration
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | cssClassQfqFormBody           | qfq-color-grey-2                                      | Wrap around FormElements: CSS Class, typically a background color.         |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formBsColumns                 | 12                                                    | The whole form will be wrapped in 'col-md-??'. Default is 12 for 100%      |
+| formBsColumns                 | 12                                                    | The whole form will be wrapped in 'col-md-??'. Default is 12 for 100%.     |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formBsLabelColumns            | 3                                                     | Default number of BS columns for the 'label'-column                        |
+| formBsLabelColumns            | 3                                                     | Default number of BS columns for the 'label'-column.                       |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formBsInputColumns            | 6                                                     | Default number of BS columns for the 'input'-column                        |
+| formBsInputColumns            | 6                                                     | Default number of BS columns for the 'input'-column.                       |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| formBsNoteColumns             | 3                                                     | Default number of BS columns for the 'note'-column                         |
+| formBsNoteColumns             | 3                                                     | Default number of BS columns for the 'note'-column.                        |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| extraButtonInfoInline         | <img src="info.png">                                  | Image for `extraButtonInfo`_ (inline)                                      |
+| extraButtonInfoInline         | <img src="info.png">                                  | Image for `extraButtonInfo`_ (inline).                                     |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| extraButtonInfoBelow          | <img src="info.png">                                  | Image for `extraButtonInfo`_ (below)                                       |
+| extraButtonInfoBelow          | <img src="info.png">                                  | Image for `extraButtonInfo`_ (below).                                      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| extraButtonInfoPosition       | below                                                 | 'auto' (default) or 'below'. See `extraButtonInfo`_                        |
+| extraButtonInfoPosition       | below                                                 | 'auto' (default) or 'below'. See `extraButtonInfo`_.                       |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| extraButtonInfoClass          | pull-right                                            | '' (default) or 'pull-right'. See `extraButtonInfo`_                       |
+| extraButtonInfoClass          | pull-right                                            | '' (default) or 'pull-right'. See `extraButtonInfo`_.                      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | Form-Language                                                                                                                                                      |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
@@ -405,41 +405,45 @@ Extension Manager: QFQ Configuration
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | saveButtonTooltip             | Save                                                  | Tooltip on the form save button.                                           |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| saveButtonClass               | btn btn-default navbar-btn                            | Bootstrap CSS class for save button on top of the form                     |
+| saveButtonClass               | btn btn-default navbar-btn                            | Bootstrap CSS class for save button on top of the form.                    |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| saveButtonClassOnChange       | alert-info btn-info                                   | Bootstrap CSS class for save button showing 'data changed'                 |
+| saveButtonClassOnChange       | alert-info btn-info                                   | Bootstrap CSS class for save button showing 'data changed'.                |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| saveButtonGlyphIcon           | glyphicon-ok                                          | Icon for the form save button                                              |
+| saveButtonGlyphIcon           | glyphicon-ok                                          | Icon for the form save button.                                             |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | closeButtonText               | -                                                     | Text on the form close button. Typically none.                             |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | closeButtonTooltip            | close                                                 | Tooltip on the form close button.                                          |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| closeButtonClass              | btn btn-default navbar-btn                            | Bootstrap CSS class for close button on top of the form                    |
+| closeButtonClass              | btn btn-default navbar-btn                            | Bootstrap CSS class for close button on top of the form.                   |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| closeButtonGlyphIcon          | glyphicon-remove                                      | Icon for the form close button                                             |
+| closeButtonGlyphIcon          | glyphicon-remove                                      | Icon for the form close button.                                            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | deleteButtonText              | -                                                     | Text on the form delete button. Typically none.                            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | deleteButtonTooltip           | delete                                                | Tooltip on the form delete button.                                         |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| deleteButtonClass             | btn btn-default navbar-btn                            | Bootstrap CSS class for delete button on top of the form                   |
+| deleteButtonClass             | btn btn-default navbar-btn                            | Bootstrap CSS class for delete button on top of the form.                  |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| deleteButtonGlyphIcon         | glyphicon-trash                                       | Icon for the form delete button                                            |
+| deleteButtonGlyphIcon         | glyphicon-trash                                       | Icon for the form delete button.                                           |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | newButtonText                 | -                                                     | Text on the form new button. Typically none.                               |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 | newButtonTooltip              | new                                                   | Tooltip on the form new button.                                            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| newButtonClass                | btn btn-default navbar-btn                            | Bootstrap CSS class for new button on top of the form                      |
+| newButtonClass                | btn btn-default navbar-btn                            | Bootstrap CSS class for new button on top of the form.                     |
++-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
+| newButtonGlyphIcon            | glyphicon-plus                                        | Icon for the form new button.                                              |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
-| newButtonGlyphIcon            | glyphicon-plus                                        | Icon for the form new button                                               |
+| showIdInFormTitle             | 0 (off), 1 (on)                                       | Append at the form title the current record id.                            |
++-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
+| cssClassColumnId              | text-muted                                            | A column in a subrecord with the name id|ID|Id gets this class.            |
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
 
 
-.. _config-qfq-ini:
+.. _config-qfq-php:
 
-config.qfq.ini
+config.qfq.php
 --------------
 
 +-------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
@@ -456,58 +460,59 @@ config.qfq.ini
 
 
 
-Example: *typo3conf/config.qfq.ini*
-
-::
+Example: *typo3conf/config.qfq.php*: ::
 
-	; QFQ configuration
-	;
-	; Save this file as: <site path>/typo3conf/config.qfq.ini
+    <?php
 
-	DB_1_USER = <DBUSER>
-	DB_1_SERVER = <DBSERVER>
-	DB_1_PASSWORD = <DBPW>
-	DB_1_NAME = <DB>
+    // QFQ configuration
+    //
+    // Save this file as: <site path>/typo3conf/config.qfq.php
 
-	; DB_2_USER = <DBUSER>
-	; DB_2_SERVER = <DBSERVER>
-	; DB_2_PASSWORD = <DBPW>
-	; DB_2_NAME = <DB>
+    return [
+        'DB_1_USER' => '<DBUSER>',
+        'DB_1_SERVER' => '<DBSERVER>',
+        'DB_1_PASSWORD' => '<DBPW>',
+        'DB_1_NAME' => '<DB>',
 
-	; Access via {{TECHNICAL_CONTACT:Y}}
-	; TECHNICAL_CONTACT = john@doe.com
+        //DB_2_USER = <DBUSER>
+        //DB_2_SERVER = <DBSERVER>
+        //DB_2_PASSWORD = <DBPW>
+        //DB_2_NAME = <DB>
 
-	; LDAP_1_RDN =
-	; LDAP_1_PASSWORD =
+        // DB_n ...
+        // ...
 
+        // LDAP_1_RDN =
+        // LDAP_1_PASSWORD =
+    ];
 
 After parsing the configuration, the following variables will be set automatically in STORE_SYSTEM:
 
-+----------------+--------------------------------------------------------------------------+
-| _dbNameData    | Can be used to dynamically access the current selected database          |
-+----------------+--------------------------------------------------------------------------+
-| _dbNameQfq     | Can be used to dynamically access the current selected database          |
-+----------------+--------------------------------------------------------------------------+
++----------------+-----------------------------------------------------------------------------------+
+| _dbNameData    | Can be used to dynamically access the current selected database: {{dbNameData:Y}} |
++----------------+-----------------------------------------------------------------------------------+
+| _dbNameQfq     | Can be used to dynamically access the current selected database: {{dbNameQfq:Y}}  |
++----------------+-----------------------------------------------------------------------------------+
 
 .. _`CustomVariables`:
 
 Custom variables
 ^^^^^^^^^^^^^^^^
 
-It's also possible to setup custom variables in `config.qfq.ini`.
-
-E.g. to setup a contact address and reuse the information inside your installation do:
+Up to 30 custom variables can be defined in `configuration`_.
 
- * `config.qfq.in`::
+E.g. to setup a contact address and reuse the information inside your installation do: ::
 
-		ADMINISTRATIVE_CONTACT = john@doe.com
-		ADMINISTRATIVE_ADDRESS = John Doe, Hollywood Blvd. 1, L.A.
-		ADMINISTRATIVE_NAME = John Doe
+   custom1: ADMINISTRATIVE_CONTACT = john@doe.com
+   custom2: ADMINISTRATIVE_ADDRESS = John Doe, Hollywood Blvd. 1, L.A.
+   custom3: ADMINISTRATIVE_NAME = John Doe
 
  * Somewhere in a `Form` or in `Report`::
 
       {{ADMINISTRATIVE_CONTACT:Y}}, {{ADMINISTRATIVE_ADDRESS:Y}}, {{ADMINISTRATIVE_NAME}}
 
+It's also possible to configure such variables directly in `config.qfq.php`_.
+
 .. _`fillStoreSystemBySql`:
 
 Fill STORE_SYSTEM by SQL
@@ -541,7 +546,7 @@ After a full QFQ installation:
 * a table `Period` (extend / change it to your needs, fill them with your periods),
 * one sample record in table `Period`,
 
-Websites, delivering semester data, schoolyears schedules, or any other type or periods, often need an index to the
+Websites, delivering semester data, school year schedules, or any other type or periods, often need an index to the
 *current* period.
 
 In configuration_: ::
@@ -776,7 +781,7 @@ in `indexQfq`. If specific forms or reports should use a different database than
 A `Form` will:
 
 * load the own definition from `indexQfq` (table `Form` and `FormElement`),
-* loads and save data from/in `indexData` (config.qfq.in) / `dbIndex` (form.parameter.dbIndex),
+* loads and save data from/in `indexData` (config.qfq.php) / `dbIndex` (form.parameter.dbIndex),
 * retrieve extra information via `dbIndexExtra` - this is useful to offer information from a database and save them in a
   different one.
 
@@ -815,7 +820,7 @@ Note:
 | C | appC3.edu      | 'wAppC3'     | <dbHostAppC3>, <dbnameC3>_t3  | <dbHostC3>, <dbnameSysC3>_db | <dbHostData>_db, <dbNameData>_db |
 +---+----------------+--------------+-------------------------------+------------------------------+----------------------------------+
 
-In config-qfq-ini_ mutliple database credentials can be prepared. Mandatory is at least one credential setup like
+In config-qfq-php_ mutliple database credentials can be prepared. Mandatory is at least one credential setup like
 `DB_1_USER`, `DB_1_SERVER`, `DB_1_PASSWORD`, `DB_1_NAME`. The number '1' indicates the `dbIndex`. Increment the number
 to specify further database credential setups.
 
@@ -1593,7 +1598,7 @@ To decide which Parameter should be placed on *Form.parameter* and which on *For
 +-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
 | ldapTimeLimit               | 3 (default)                      | Maximum time to wait for an answer of the LDAP Server         | x    | x           | TA, FSL  |
 +-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
-| ldapUseBindCredentials      | ldapUseBindCredentials=1         | Use LDAP_1_* crendentials from config-qfq-ini_ for ldap_bind()| x    | x           | TA, FSL  |
+| ldapUseBindCredentials      | ldapUseBindCredentials=1         | Use LDAP_1_* crendentials from config-qfq-php_ for ldap_bind()| x    | x           | TA, FSL  |
 +-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
 | typeAheadLdap               | -                                | Enable LDAP as 'Typeahead' data source                        |      | x           | TA       |
 +-----------------------------+----------------------------------+---------------------------------------------------------------+------+-------------+----------+
@@ -1619,7 +1624,7 @@ To decide which Parameter should be placed on *Form.parameter* and which on *For
 
 * *typeAheadLimit*: there might be a hard limit on the server side (e.g. 100) - which can't be extended.
 * *ldapUseBindCredentials* is only necessary if `anonymous` access is not possible. RDN and password has to be configured in
-  config-qfq-ini_.
+  config-qfq-php_.
 
 .. _LDAP_Typeahead:
 
@@ -1888,7 +1893,7 @@ Definition
 +-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
 |Show button              | 'new, delete, close, save' (Default: 'new,delete,close,save'): Shown named buttons in the upper right corner of the form.  See `form-showButton`_  |
 +-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
-|Forward Mode             | 'client | no | url | url-skip-history' (Default: client): See `form-forward`_.                                                                     |
+|Forward Mode             | 'auto | close | no | url | url-skip-history' (Default: auto): See `form-forward`_.                                                                 |
 +-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
 |Forward (Mode) Page      | a) URL / Typo3 page id/alias or b) Forward Mode (via '{{...}}') or combination of a) & b). See `form-forward`_.                                    |
 +-------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -2003,14 +2008,15 @@ Forward (=forwardMode)
 
 After the user presses *Save*, *Close*, *Delete* or *New*, different actions are possible where the browser redirects to.
 
-* `client` (default) - the QFQ browser Javascript logic, decides to stay on the page or to force a redirection
-  to a previous page.
+* `auto` (default) - the QFQ browser Javascript logic, decides to stay on the page or to force a redirection
+  to a previous page. The decision depends on:
   
-  * *Close* closes the current page and goes back to the previous page. Note: if a new tab is opened and the user presses
-    QFQ close (in any way) - in that new browser tab there is no previous page! QFQ won't close the tab, instead a message
-    is shown
+  * *Close* goes back (feels like close) to the previous page. Note: if there is no history, QFQ won't close the tab,
+     instead a message is shown.
   * *Save* stays on the current page.
-  
+
+* `close` - goes back (feels like close) to the previous page. Note: if there is no history, QFQ won't close the tab,
+     instead a message is shown.
 * `no` - no change, the browser remains on the current side. Close does not close the page. It just triggers a save if 
   there are modified data.
 * `url` - the browser redirects to the URL or T3 page named in `Forward URL / Page`. Independent if the user presses `save` or `close`.
@@ -2031,14 +2037,14 @@ Format: [<url>] or [<mode>|<url>]
   * `{{SELECT ...}}`
   * `<mode>|<url>`
 
-* `<mode>` - Valid keywords are as above: `no|client|url|url-skip-history`
+* `<mode>` - Valid keywords are as above: `auto|close|no|url|url-skip-history`
 
 Specifying the mode in `forwardPage` overwrites `formMode` (but only if `formMode` is `url...`).
 
 Also regular QFQ statements like {{var}} or {{SELECT ...}} are possible in `forwardPage`. This is useful to dynamically
 redirect to different targets, depending on user input or any other dependencies.
 
-If a forwardMode 'url...' is specified and there is no `forwardPage`, QFQ falls down to `client` mode.
+If a forwardMode 'url...' is specified and there is no `forwardPage`, QFQ falls down to `auto` mode.
 
 On a form, the user might click 'save' or 'save,close' or 'close' (with modified data this leads to 'save,close').
 The CLIENT `submit_reason` shows the user action:
@@ -2048,7 +2054,7 @@ The CLIENT `submit_reason` shows the user action:
 Example forwardPage
 ^^^^^^^^^^^^^^^^^^^
 
-* `{{SELECT IF('{{formModeGlobal:S:alnumx}}'='requiredOff', 'no', 'client') }}`
+* `{{SELECT IF('{{formModeGlobal:S:alnumx}}'='requiredOff', 'no', 'auto') }}`
 * `{{SELECT IF('{{submit_reason:CE:alnumx}}'='save', 'no', 'url'), '|http://example.com' }}`
 
 Type: combined dynamic mode & URL/page
@@ -2069,7 +2075,7 @@ Parameter
 +-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
 | Name                        | Type   | Description                                                                                              |
 +=============================+========+==========================================================================================================+
-| dbIndex                     | int    | Database credential index, given via `config-qfq-ini`_ to let the current `Form` operate on the database.|
+| dbIndex                     | int    | Database credential index, given via `config-qfq-php`_ to let the current `Form` operate on the database.|
 +-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
 | bsColumns                   | int    | Wrap the whole form in '<div class="col-md-??">                                                          |
 +-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
@@ -2163,6 +2169,8 @@ Parameter
 +-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
 | fillStoreVar                | string | Fill the STORE_VAR with custom values. See `STORE_VARS`_.                                                |
 +-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
+| showIdInFormTitle           | string | Overwrite default from configuration_                                                                    |
++-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
 
 * Example:
 
@@ -2556,7 +2564,7 @@ See also at specific *FormElement* definitions.
 +------------------------+--------+----------------------------------------------------------------------------------------------------------+
 | htmlAfter              | string | HTML Code wrapped after the complete *FormElement*                                                       |
 +------------------------+--------+----------------------------------------------------------------------------------------------------------+
-| wrapRow                | string | If specified, skip default wrapping (`<div class='col-md-?>`). Instead the given string is used.         |
+| wrapRow                | string | If specified, skip default wrapping (`<div class='col-md-?'>`). Instead the given string is used.        |
 +------------------------+--------+                                                                                                          |
 | wrapLabel              | string |                                                                                                          |
 +------------------------+--------+                                                                                                          |
@@ -2937,6 +2945,8 @@ Type: text
     the value is an empty string
   * *inputType* = number (optional). Typically the HTML tag 'type' will be 'text', 'textarea' or 'number' (detected automatically).
     If necessary, the HTML tag 'type' might be forced to a specific given value.
+  * *step* = Step size of the up/down buttons which increase/decrease the number of in the input field. Optional.
+    Default 1. Only useful with `inputType=number` (defined explicit via `inputType` or detected automatically).
 
 .. _`input-typeahead`:
 
@@ -4119,6 +4129,21 @@ Best practice
 Custom default value only for 'new records'
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+Method 1
+''''''''
+
+On `Form.parameter` define a `fillStoreVar` query with a column name equal to a form field. That's all.
+
+Example: ::
+
+  FormElement.name = technicalContact
+  Form.parameter.fillStoreVar = {{!SELECT CONCAT(p.firstName, ' ', p.name) AS technicalContact FROM Person AS p WHERE p.account='{{feUser:T}}' }}
+
+What we use here is the default STORE prio FSRVD. If the form loads with r=0, 'F', 'S' and 'R' are empty. 'V' is filled.
+If r>0, than 'F' and 'S' are empty and 'R' is filled.
+
+Method 2
+''''''''
 In the specific `FormElement` set `value={{columnName:RSE}}`. The link to the form should be rendered with
 '"...&columnName=<data>&..." AS _page'. The trick is that the STORE_RECORD is empty for new records, and therefore the
 corresponding value from STORE_SIP will be returned. Existing records will use the already saved value.
@@ -6218,8 +6243,139 @@ E.g.::
 
     10.sql = SELECT "p:home&r=0|t:Home|c:qfq-100 qfq-left" AS _pagev
 
-Examples
---------
+.. _drag_and_drop:
+
+Drag and drop
+-------------
+
+Sort/order elements
+^^^^^^^^^^^^^^^^^^^
+
+Manually sorting and ordering of elements via `HTML5 drag and drop` is supported via QFQ. Any element to sort
+should be represented by a database record with an order column. If the elements are unordered, they will be ordered after
+the first 'drag and drop' move of an element.
+
+Functionality is divided into:
+
+* Display list: the records will be displayed via QFQ/report.
+* Sort records: updates of the order column are managed by a specific definition form. The form is not a regular form
+  (e.g. there are no FormElements), instead it's only a container to held the SQL update query as well as providing
+  access control via SIP. The form is automatically called via AJAX.
+
+Part 1: Display list
+''''''''''''''''''''
+
+Display the list of elements via a regular QFQ content record. All 'drag and drop' elements have to be nested by an HTML
+element:
+
+* With `class="qfq-dnd-sort"`.
+* With a form name: `{{'form=<form name>' AS _data-dnd-api}}`
+* Only direct children of such element can be dragged.
+* Every children needs a unique identifier `data-dnd-id="<unique>"`. Typically this is the corresponding record id.
+* The record needs a dedicated order column, which will be updated through API calls in time.
+
+A `<div>` example HTML output: ::
+
+    <div class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234">
+        <div class="anyClass" id="<uniq1>" data-dnd-id="55">
+            Numbero Uno
+        </div>
+        <div class="anyClass" id="<uniq2>" data-dnd-id="18">
+            Numbero Deux
+        </div>
+        <div class="anyClass" id="<uniq3>" data-dnd-id="27">
+            Numbero Tre
+        </div>
+    </div>
+
+
+A typical QFQ report which generates those `<div>` HTML: ::
+
+    10 {
+      sql = SELECT '<div id="anytag-', n.id,'" data-dnd-id="', n.id,'">' , n.note, '</div>'
+                   FROM Note AS n
+                   WHERE grId=28
+                   ORDER BY n.ord
+
+      head = <div class="qfq-dnd-sort" data-dnd-api="{{'form=dndSortNote&grId=28|A:dnd-sort' AS _api}}">
+      tail = </div>
+    }
+
+
+A `<table>` based setup is also possible. Note the attribute  `data-columns="3"` - those generates a dropzone
+which the same width as the outer table. ::
+
+    <table>
+        <tbody class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234" data-columns="3">
+            <tr> class="anyClass" id="<uniq1>" data-dnd-id="55">
+                <td>Numbero Uno</td><td>Numbero Uno.2</td><td>Numbero Uno.3</td>
+            </tr>
+            <tr class="anyClass" id="<uniq2>" data-dnd-id="18">
+                <td>Numbero Deux</td><td>Numbero Deux.2</td><td>Numbero Deux.3</td>
+            </tr>
+            <tr class="anyClass" id="<uniq3>" data-dnd-id="27">
+                <td>Numbero Tre</td><td>Numbero Tre.2</td><td>Numbero Tre.3</td>
+            </tr>
+        </tbody>
+    </table>
+
+A typical QFQ report which generates those HTML: ::
+
+    10 {
+      sql = SELECT '<tr id="anytag-', n.id,'" data-dnd-id="', n.id,'" data-columns="3">' , n.id AS '_+td', n.note AS '_+td', n.ord AS '_+td', '</tr>'
+                   FROM Note AS n
+                   WHERE grId=28
+                   ORDER BY n.ord
+
+      head = <table><tbody class="qfq-dnd-sort" {{'form=dndSortNote&grId=28' AS _data-dnd-api}} data-columns="3">
+      tail = </tbody><table>
+    }
+
+Part 2: Sort records
+''''''''''''''''''''
+
+A dedicated `Form`, without any `FormElements`, is used to define the database update definition.
+
+Fields:
+
+* Name: <custom form name> - used in Part 1 in the  `_data-dnd-api` variable.
+* Table: <table with the element records> - used to the update the records specified by `dragAndDropOrderSql`.
+
+* Parameter:
+
++-------------------------------------+--------------------------------------------------------------------------------+
+| Attribute                           | Description                                                                    |
++=====================================+================================================================================+
+| orderInterval = <number>            | Optional. By default '10'. Might be any number > 0.                            |
++-------------------------------------+--------------------------------------------------------------------------------+
+| orderColumn = <column name>         | Optional. By default 'ord'.                                                    |
++-------------------------------------+--------------------------------------------------------------------------------+
+| dragAndDropOrderSql =                                 | Query to selects the *same* records as the report in the     |
+| {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n     | same *order!* Inconsistencies results in sort differences.   |
+| ORDER BY n.ord}}                                      | The columns `id` and `ord` are *mandatory.*                  |
++-------------------------------------------------------+--------------------------------------------------------------+
+
+The form related to the example of part 1 ('div' or 'table'): ::
+
+  Form.name: dndSortNote
+  Form.table: Note
+  Form.parameter: orderInterval = 1
+  Form.parameter: orderColumn = ord
+  Form.parameter: dragAndDropOrderSql = {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n WHERE n.grId={{grId:S0}} ORDER BY n.ord}}
+
+QFQ iterates over the result set of `dragAndDropOrderSql`. The value of column `id` have to correspond to the dragged HTML
+ element (given by `data-dnd-id`). Reordering always start with `orderInterval` and is incremented by `orderInterval` with each
+ record of the result set. The client reports a) the id of the dragged HTML element, b) the id of the hovered element and
+ c) the dropped position of above or below the hovered element. This information is compared to the result set and
+ changes are applied where appropriate.
+
+ Take care that the query of part 1 (display list) does a) select the same records and b) in the same order as the query
+ defined in part 2 (sort records) via `dragAndDropOrderSql`.
+
+ If you find that the reorder does not work at expected, those two sql queries are not identically.
+
+Report Examples
+---------------
 
 The following section gives some examples of typical reports
 
@@ -6571,42 +6727,42 @@ Create / edit `AutoCron` jobs
 Create a T3 page with a QFQ record (similar to the formeditor). Such page should be access restricted and is only needed
 to edit `AutoCron` jobs: ::
 
-	dbIndex={{indexQfq:Y}}
-	form={{form:S}}
+    dbIndex={{indexQfq:Y}}
+    form={{form:S}}
 
-	10 {
-		# Table header.
-		sql = SELECT CONCAT('p:{{pageId:T}}&form=cron') AS _pagen, 'id', 'Next run','Frequency','Comment','Last run','In progress', 'Status' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'=''
-		head = <table class='table table-hover qfq-table-50'>
-		tail = </table>
-		rbeg = <thead><tr>
-		rend = </tr></thead>
-		fbeg = <th>
-		fend = </th>
-
-		10 {
-			# All Cron Jobs
-			sql = SELECT CONCAT('<tr class="',
-										IF(c.lastStatus LIKE 'Error%','danger',''),
- 										IF(c.inProgress!=0 AND DATE_ADD(c.inProgress, INTERVAL 10 MINUTE)<NOW(),' warning',''),
-										IF(c.status='enable','',' text-muted'),'" ',
-
-										IF(c.inProgress!=0 AND DATE_ADD(c.inProgress, INTERVAL 10 MINUTE)<NOW(),'title="inProgress > 10mins"',
-										IF(c.lastStatus LIKE 'Error%','title="Status: Error"','')),
-										'>'),
-								'<td>', CONCAT('p:{{pageId:T}}&form=cron&r=', c.id) AS _pagee, '</td><td>',
-								c.id, '</td><td>',
-								IF(c.nextrun=0,"", DATE_FORMAT(c.nextrun, "%d.%m.%y %H:%i:%s")), '</td><td>',
-								c.frequency, '</td><td>',
-								c.comment, '</td><td>',
-								IF(c.lastrun=0,"", DATE_FORMAT(c.lastrun,"%d.%m.%y %H:%i:%s")), '</td><td>',
-								IF(c.inProgress=0,"", DATE_FORMAT(c.inProgress,"%d.%m.%y %H:%i:%s")), '</td><td>',
-								LEFT(c.laststatus,40) AS '_+pre', '</td><td>',
-								CONCAT('U:form=cron&r=', c.id) AS _paged, '</td></tr>'
-						FROM Cron AS c
-						ORDER BY c.id
-		}
-	}
+    10 {
+        # Table header.
+        sql = SELECT CONCAT('p:{{pageId:T}}&form=cron') AS _pagen, 'id', 'Next run','Frequency','Comment','Last run','In progress', 'Status' FROM (SELECT 1) AS fake WHERE '{{form:SE}}'=''
+        head = <table class='table table-hover qfq-table-50'>
+        tail = </table>
+        rbeg = <thead><tr>
+        rend = </tr></thead>
+        fbeg = <th>
+        fend = </th>
+
+        10 {
+        # All Cron Jobs
+        sql = SELECT CONCAT('<tr class="',
+                            IF(c.lastStatus LIKE 'Error%','danger',''),
+                            IF(c.inProgress!=0 AND DATE_ADD(c.inProgress, INTERVAL 10 MINUTE)<NOW(),' warning',''),
+                            IF(c.status='enable','',' text-muted'),'" ',
+
+                            IF(c.inProgress!=0 AND DATE_ADD(c.inProgress, INTERVAL 10 MINUTE)<NOW(),'title="inProgress > 10mins"',
+                            IF(c.lastStatus LIKE 'Error%','title="Status: Error"','')),
+                            '>'),
+                        '<td>', CONCAT('p:{{pageId:T}}&form=cron&r=', c.id) AS _pagee, '</td><td>',
+                        c.id, '</td><td>',
+                        IF(c.nextrun=0,"", DATE_FORMAT(c.nextrun, "%d.%m.%y %H:%i:%s")), '</td><td>',
+                        c.frequency, '</td><td>',
+                        c.comment, '</td><td>',
+                        IF(c.lastrun=0,"", DATE_FORMAT(c.lastrun,"%d.%m.%y %H:%i:%s")), '</td><td>',
+                        IF(c.inProgress=0,"", DATE_FORMAT(c.inProgress,"%d.%m.%y %H:%i:%s")), '</td><td>',
+                        LEFT(c.laststatus,40) AS '_+pre', '</td><td>',
+                        CONCAT('U:form=cron&r=', c.id) AS _paged, '</td></tr>'
+                FROM Cron AS c
+        ORDER BY c.id
+        }
+    }
 
 
 Usage
@@ -6742,7 +6898,7 @@ Tip on Report: In case the query did not contain any double ticks, just wrap all
 
 
 
-Error read file config.qfq.ini: syntax error on line xx
+Error read file config.qfq.php: syntax error on line xx
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Check the given line number. If it's a SQL statement, enclose it in single or double ticks.
@@ -6774,7 +6930,27 @@ The browser shows a red popup with 'Internal Server Error'. The message is gener
 request response of QFQ (=Server) is broken. This might happen e.g. if PHP can't start successfully or PHP fails to run
 due to  a missing php module or broken configuration.
 
+Oops, an error occurred! Code: 20180612205917761fc593
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You see this message on all places where a QFQ content record should produce some output. Typically the extension fails
+to load. If the error message disappears when the QFQ extension is disabled (instead a message `qfq_qfq can't be rendered`
+is shown), than QFQ is the problem.
+
+Search the given code in `typo3temp/logs/*`, in this example 20180612205917761fc593. You'll should find a stacktrace with
+a more detailed message.
+
+The error might occur if there are problematic characters in config.qfq.php, like single or double ticks inside strings,
+ wich are not enclosed (correctly).
+
+.. _`sendEmailProblem`:
+
+sendEmail: Error => TLS setup failed
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Switch off the TLS encryption. In `configuration`_ specify for *config.sendEMailOptions*: ::
 
+   -o tls=no
 
 .. _`javascriptProblem`:
 
diff --git a/extension/Documentation/Release.rst b/extension/Documentation/Release.rst
index 69bee416733fb2a5d668b1a0b749d91c5ebfe3ea..718f191d696029a7f94ec4e98e43aa8cbcae91c5 100644
--- a/extension/Documentation/Release.rst
+++ b/extension/Documentation/Release.rst
@@ -36,6 +36,63 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
+Version 18.6.0
+--------------
+
+Date: 13.06.2018
+
+Notes
+^^^^^
+
+* config.qfq.ini migrated to config.qfq.php - the old config.qfq.ini get's `chmod 000`.
+* Most of config.qfq.ini migrated to Typo3 / Extension Manager - all but the DB /LDAP credentials.
+* Keep in config.qfq.ini: ::
+
+    # Rename DB credentials from DB_<key> to DB_1_<key>, with key = 'NAME|HOST|USER|PASSWORD'
+    DB_1_USER = ...
+    DB_1_SERVER = ...
+    DB_1_PASSWORD = ...
+    DB_1_NAME = ...
+
+* NEW: Drag and drop to sort elements! Check the Manual.
+* `URL forwardMode`
+
+  * `client` renamed to `auto`.
+  * `close` added.
+
+Features
+^^^^^^^^
+
+ * #6100 / Url Forward Auto: Update Manual.rst. The F.parameter.saveAndClose has been removed again. Mode 'close' can be assigned statically or dynamic.
+ * #6178 / Input: Step: New option 'step' for FE.parameter.
+ * Download.php: references to non existing files now reported as missing file, not 'wrong mimetype' anymore.
+ * #4918 / Drag'n'Drop reorder elements DRAGANDDROP.md, PROTOCOL.md: Doc for "drag'n' drop" implementation.
+   dragAndDrop.php: API endpoint DragAndDrop.php: Class for implementing drag'n' drop functionality.
+   Link.php: implement new renderMode=8 - returning only the sip. QuickFormQuery.php: New entry point for processing "drag'n' drop".
+ * #3971 / Form title: new design from form title
+
+Bug Fixes
+^^^^^^^^^
+
+ * #5077 / Dynamic Update & FE.type=required: Server fixed -
+
+    a) dynamic calculated modeSql respected,
+    b) formModeGlobal=requiredOff respected,
+    c) dynamic FE with mode='hidden' are not saved anymore.
+
+ * #6176 / Icon not aligned when error text: Buttons now wrapped in one 'input-group'.
+ * Manual.rst: reformat autocron QFQ code
+ * #5880 / Skip Error Message during dynamicUpdate
+ * #5870 / Missing file config.qfq.ini: Clean QFQ message
+ * #5924 / config.qfq.ini/LocalConfiguration.php: several places in formEditor.sql still contained the 'dbIndex...'
+   instead of 'index...'. fixed.
+ * #6168 Configuration language setting ignored: Form and FormElement editor still used uppercase config values for
+   language configuration. Updated to the new camel case notation.
+ * #5890 / config.qfq.ini is public readable. Renamed file to config.qfq.php. Implement a basic migration assistant to
+   copy DB credentials to new config.qfq.php. All other values have to be copied to extmanager/qfq-configuration manually.
+ * #6216 / Oops, an error occurred! Code - unhandled exception will be caught now.
+
+
 Version 18.4.4
 --------------
 
@@ -119,7 +176,7 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
-* #5706 Fixed that problematic characters in 'fileDestination' has not been sanatized.
+* #5706 / Fixed that problematic characters in 'fileDestination' has not been sanatized.
 * Fixed problem with buttons clipping trough alert
 * Client: wrong variable, updated CSS for long errors
 
diff --git a/extension/Documentation/Settings.cfg b/extension/Documentation/Settings.cfg
index e3a1de6fcc8716c7d18111f15e5cb23491a6b6b9..447110ff33ddf0f1ca43bb29c811447c44b63bb8 100644
--- a/extension/Documentation/Settings.cfg
+++ b/extension/Documentation/Settings.cfg
@@ -2,8 +2,8 @@
 [general]
 
 project     = QFQ - Quick Form Query
-version     = 18.4
-release     = 18.4.4
+version     = 18.6
+release     = 18.6.0
 t3author    = Carsten Rose
 copyright   = since 2017 by the author
 
diff --git a/extension/Documentation/_make/conf.py b/extension/Documentation/_make/conf.py
index 095ec825396e8365b80c9215d31bd33afc8c3d21..2d71e00d05a642fb2c21eb15dd211d5908e9f734 100644
--- a/extension/Documentation/_make/conf.py
+++ b/extension/Documentation/_make/conf.py
@@ -57,9 +57,9 @@ copyright = u'2017, Carsten Rose'
 # built documents.lease
 #
 # The short X.Y version.
-version = '18.4'
+version = '18.6'
 # The full version, including alpha/beta/rc tags.
-release = '18.4.4'
+release = '18.6.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/extension/RELEASE.txt b/extension/RELEASE.txt
index 69bee416733fb2a5d668b1a0b749d91c5ebfe3ea..1c54ae07765ab72a70b010cb938bcf765718b2a1 100644
--- a/extension/RELEASE.txt
+++ b/extension/RELEASE.txt
@@ -36,6 +36,63 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
+Version 18.6.0
+--------------
+
+Date: 13.06.2018
+
+Notes
+^^^^^
+
+* config.qfq.ini migrated to config.qfq.php - the old config.qfq.ini get's `chmod 000`.
+* Most of config.qfq.ini migrated to Typo3 / Extension Manager - all but the DB /LDAP credentials.
+* Keep in config.qfq.ini: ::
+
+    # Rename DB credentials from DB_<key> to DB_1_<key>, with key = 'NAME|HOST|USER|PASSWORD'
+    DB_1_USER = ...
+    DB_1_SERVER = ...
+    DB_1_PASSWORD = ...
+    DB_1_NAME = ...
+
+* NEW: Drag and drop to sort elements! Check the Manual.
+* `URL forwardMode`
+
+  * `client` renamed to `auto`.
+  * `close` added.
+
+Features
+^^^^^^^^
+
+ * #6100 / Url Forward Auto: Update Manual.rst. The F.parameter.saveAndClose has been removed again. Mode 'close' can be assigned statically or dynamic.
+ * #6178 / Input: Step: New option 'step' for FE.parameter.
+ * Download.php: references to non existing files now reported as missing file, not 'wrong mimetype' anymore.
+ * #4918 / Drag'n'Drop reorder elements DRAGANDDROP.md, PROTOCOL.md: Doc for "drag'n' drop" implementation.
+   dragAndDrop.php: API endpoint DragAndDrop.php: Class for implementing drag'n' drop functionality.
+   Link.php: implement new renderMode=8 - returning only the sip. QuickFormQuery.php: New entry point for processing "drag'n' drop".
+ * #3971 / Form title: new design from form title
+
+Bug Fixes
+^^^^^^^^^
+
+* #5077 / Dynamic Update & FE.type=required: Server fixed -
+
+  a) dynamic calculated modeSql respected,
+  b) formModeGlobal=requiredOff respected,
+  c) dynamic FE with mode='hidden' are not saved anymore.
+
+ * #6176 / Icon not aligned when error text: Buttons now wrapped in one 'input-group'.
+ * Manual.rst: reformat autocron QFQ code
+ * #5880 / Skip Error Message during dynamicUpdate
+ * #5870 / Missing file config.qfq.ini: Clean QFQ message
+ * #5924 / config.qfq.ini/LocalConfiguration.php: several places in formEditor.sql still contained the 'dbIndex...'
+   instead of 'index...'. fixed.
+ * #6168 Configuration language setting ignored: Form and FormElement editor still used uppercase config values for
+   language configuration. Updated to the new camel case notation.
+ * #5890 / config.qfq.ini is public readable. Renamed file to config.qfq.php. Implement a basic migration assistant to
+   copy DB credentials to new config.qfq.php. All other values have to be copied to extmanager/qfq-configuration manually.
+ * #6216 / Oops, an error occurred! Code - unhandled exception will be caught now.
+
+
 Version 18.4.4
 --------------
 
@@ -119,7 +176,7 @@ Features
 Bug Fixes
 ^^^^^^^^^
 
-* #5706 Fixed that problematic characters in 'fileDestination' has not been sanatized.
+* #5706 / Fixed that problematic characters in 'fileDestination' has not been sanatized.
 * Fixed problem with buttons clipping trough alert
 * Client: wrong variable, updated CSS for long errors
 
diff --git a/extension/config.qfq.example.ini b/extension/config.qfq.example.ini
deleted file mode 100644
index db74dec2bf5d278e432d2e82a572d11867e2b21a..0000000000000000000000000000000000000000
--- a/extension/config.qfq.example.ini
+++ /dev/null
@@ -1,17 +0,0 @@
-; QFQ configuration
-;
-; Save this file as: <site path>/typo3conf/config.qfq.ini
-
-DB_1_USER = <DBUSER>
-DB_1_SERVER = <DBSERVER>
-DB_1_PASSWORD = <DBPW>
-DB_1_NAME = <DB>
-
-; DB_2_USER = <DBUSER>
-; DB_2_SERVER = <DBSERVER>
-; DB_2_PASSWORD = <DBPW>
-; DB_2_NAME = <DB>
-
-; LDAP_1_RDN =
-; LDAP_1_PASSWORD =
-
diff --git a/extension/config.qfq.example.php b/extension/config.qfq.example.php
new file mode 100644
index 0000000000000000000000000000000000000000..08f975f79d006490385eb3b7282aa76a6fd9c26f
--- /dev/null
+++ b/extension/config.qfq.example.php
@@ -0,0 +1,23 @@
+<?php
+
+// QFQ configuration
+//
+// Save this file as: <site path>/typo3conf/config.qfq.php
+
+return [
+    'DB_1_USER' => '<DBUSER>',
+    'DB_1_SERVER' => '<DBSERVER>',
+    'DB_1_PASSWORD' => '<DBPW>',
+    'DB_1_NAME' => '<DB>',
+
+    //DB_2_USER = <DBUSER>
+    //DB_2_SERVER = <DBSERVER>
+    //DB_2_PASSWORD = <DBPW>
+    //DB_2_NAME = <DB>
+
+    // DB_n ...
+    // ...
+
+    // LDAP_1_RDN =
+    // LDAP_1_PASSWORD =
+];
diff --git a/extension/ext_conf_template.txt b/extension/ext_conf_template.txt
index eb6234e81348452b5988a96fba6b003756c99336..4878b6c051a05d79e6b3cc6daa75f6eb15110e22 100644
--- a/extension/ext_conf_template.txt
+++ b/extension/ext_conf_template.txt
@@ -120,7 +120,11 @@ formDataMatchError = match error
 # cat=form-config/config; type=string; label=Form data error message:Default is 'error'. Customizable error message used in validator.js. generic violation.
 formDataError = error
 
+# cat=form-config/config; type=boolean; label=Show record-id in form title:Default is off (0). If on (1), append the current record id on the title. New records get '(new)'.
+showIdInFormTitle = 0
 
+# cat=form-config/config; type=string; label=Wrap the subrecord column 'id|ID|Id' with the given class. E.g. 'text-muted' is rendered as ...<span class="text-muted">value</span>.
+cssClassColumnId = text-muted
 
 
 
@@ -245,5 +249,96 @@ newButtonClass = btn btn-default navbar-btn
 newButtonGlyphIcon = glyphicon-plus
 
 
+# cat=custom/layout; type=string; label=Custom variable 01:Default empty. Can be used the centrally define variables. E.g. "CONTACT_EMAIL = 'john@doe.com'". Retrieve them via '{{CONTACT_EMAIL:Y}}'.
+custom1 =
+
+# cat=custom/layout; type=string; label=Custom variable 02
+custom2 =
+
+# cat=custom/layout; type=string; label=Custom variable 03
+custom3 =
+
+# cat=custom/layout; type=string; label=Custom variable 04
+custom4 =
+
+# cat=custom/layout; type=string; label=Custom variable 05
+custom5 =
+
+# cat=custom/layout; type=string; label=Custom variable 06
+custom6 =
+
+# cat=custom/layout; type=string; label=Custom variable 07
+custom7 =
+
+# cat=custom/layout; type=string; label=Custom variable 08
+custom8 =
+
+# cat=custom/layout; type=string; label=Custom variable 09
+custom9 =
+
+# cat=custom/layout; type=string; label=Custom variable 10
+custom10 =
+
+# cat=custom/layout; type=string; label=Custom variable 11
+custom11 =
+
+# cat=custom/layout; type=string; label=Custom variable 12
+custom12 =
+
+# cat=custom/layout; type=string; label=Custom variable 13
+custom13 =
+
+# cat=custom/layout; type=string; label=Custom variable 14
+custom14 =
+
+# cat=custom/layout; type=string; label=Custom variable 15
+custom15 =
+
+# cat=custom/layout; type=string; label=Custom variable 16
+custom16 =
+
+# cat=custom/layout; type=string; label=Custom variable 17
+custom17 =
+
+# cat=custom/layout; type=string; label=Custom variable 18
+custom18 =
+
+# cat=custom/layout; type=string; label=Custom variable 19
+custom19 =
+
+# cat=custom/layout; type=string; label=Custom variable 20
+custom20 =
+
+# cat=custom/layout; type=string; label=Custom variable 21
+custom21 =
+
+# cat=custom/layout; type=string; label=Custom variable 22
+custom22 =
+
+# cat=custom/layout; type=string; label=Custom variable 23
+custom23 =
+
+# cat=custom/layout; type=string; label=Custom variable 24
+custom24 =
+
+# cat=custom/layout; type=string; label=Custom variable 25
+custom25 =
+
+# cat=custom/layout; type=string; label=Custom variable 26
+custom26 =
+
+# cat=custom/layout; type=string; label=Custom variable 27
+custom27 =
+
+# cat=custom/layout; type=string; label=Custom variable 28
+custom28 =
+
+# cat=custom/layout; type=string; label=Custom variable 29
+custom29 =
+
+# cat=custom/layout; type=string; label=Custom variable 30
+custom30 =
+
+
 
 
diff --git a/extension/ext_emconf.php b/extension/ext_emconf.php
index 71147016b502ee8a0f7d73a6a565088dd562ee13..9c05c55a95d40f159e1bc3a93f86e093865c61e8 100644
--- a/extension/ext_emconf.php
+++ b/extension/ext_emconf.php
@@ -11,7 +11,7 @@ $EM_CONF[$_EXTKEY] = array(
     'dependencies' => 'fluid,extbase',
     'clearcacheonload' => true,
     'state' => 'stable',
-    'version' => '18.4.4',
+    'version' => '18.6.0',
     'constraints' => [
         'depends' => [
             'typo3' => '6.0.0-9.2.99',
diff --git a/extension/qfq/api/delete.php b/extension/qfq/api/delete.php
index d1bfcc37d169a65a9becb6d93ebe4d8a5be27b18..c188480a48bfdb3558ad896da4f97b72bc23cc87 100644
--- a/extension/qfq/api/delete.php
+++ b/extension/qfq/api/delete.php
@@ -89,7 +89,7 @@ try {
             $answer = array();
             if ($flagSuccess) {
                 $answer[API_MESSAGE] = 'Deleted';
-                $answer[API_REDIRECT] = API_ANSWER_REDIRECT_CLIENT;
+                $answer[API_REDIRECT] = API_ANSWER_REDIRECT_AUTO;
                 $answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS;
             } else {
                 $answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
diff --git a/extension/qfq/api/dragAndDrop.php b/extension/qfq/api/dragAndDrop.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4b8d21895ebd490bda0bf5ef90e26e2d44d7ddb
--- /dev/null
+++ b/extension/qfq/api/dragAndDrop.php
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: ep
+ * Date: 12/23/15
+ * Time: 6:17 PM
+ */
+
+namespace qfq;
+
+use qfq;
+
+require_once(__DIR__ . '/../qfq/store/Store.php');
+require_once(__DIR__ . '/../qfq/Constants.php');
+require_once(__DIR__ . '/../qfq/QuickFormQuery.php');
+//require_once(__DIR__ . '/../qfq/exceptions/UserFormException.php');
+//require_once(__DIR__ . '/../qfq/exceptions/CodeException.php');
+//require_once(__DIR__ . '/../qfq/exceptions/DbException.php');
+//require_once(__DIR__ . '/../qfq/exceptions/ErrorHandler.php');
+
+
+/**
+ * Return JSON encoded answer
+ *
+ * status: success|error
+ * message: <message>
+ * redirect: client|url|no
+ * redirect-url: <url>
+ * field-name: <field name>
+ * field-message: <message>
+ * form-data: [ fieldname1 => value1, fieldname2 => value2, ... ]
+ * form-control: [ fieldname1 => status1, fieldname2 => status2, ... ]  status: show|hide, enabled|disabled,
+ * readonly|readwrite
+ *
+ * Description:
+ *
+ * Save successful. Button 'close', 'new'. Form.forward: 'auto'. Client logic decide to redirect or not. Show message
+ * if no redirect. status = 'success' message = <message> redirect = 'client'
+ *
+ * Save successful. Button 'close': Form.forward: 'page'. Client redirect to url.
+ *  status = 'success'
+ *  message = <message>
+ *  redirect = 'url'
+ *  redirect-url = <URL>
+ *
+ * Save failed: Button: any. Show message and set 'alert' on _optional_ specified form element. Bring 'pill' of
+ * specified form element to front. status = 'error' message = <message> redirect = 'no' Optional: field-name = <field
+ * name> field-message = <message appearing as tooltip (or similar) near the form element>
+ */
+
+$answer = array();
+
+$answer[API_REDIRECT] = API_ANSWER_REDIRECT_NO;
+$answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
+$answer[API_MESSAGE] = '';
+
+try {
+    $qfq = new QuickFormQuery(['bodytext' => '']);
+
+    $data = $qfq->dragAndDrop();
+
+    $answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS;
+    $answer[API_MESSAGE] = 'reorder: success';
+//    $answer[API_FORM_UPDATE] = $data[API_FORM_UPDATE];
+//    $answer[API_ELEMENT_UPDATE] = $data[API_ELEMENT_UPDATE];
+//    unset($answer[API_FORM_UPDATE][API_ELEMENT_UPDATE]);
+
+} catch (qfq\UserFormException $e) {
+    $answer[API_MESSAGE] = $e->formatMessage();
+} catch (qfq\CodeException $e) {
+    $answer[API_MESSAGE] = $e->formatMessage();
+} catch (qfq\DbException $e) {
+    $answer[API_MESSAGE] = $e->formatMessage();
+} catch (\Exception $e) {
+    $answer[API_MESSAGE] = "Generic Exception: " . $e->getMessage();
+}
+
+header("Content-Type: application/json");
+echo json_encode($answer);
+
diff --git a/extension/qfq/api/save.php b/extension/qfq/api/save.php
index fcf5a6a09265b9dfd072e2cfde5a2c45ecf4ef45..a873190a9ab56428ded8fb4e6afe5fd2c81ac6f1 100644
--- a/extension/qfq/api/save.php
+++ b/extension/qfq/api/save.php
@@ -49,12 +49,12 @@ require_once(__DIR__ . '/../qfq/exceptions/DbException.php');
 
 $answer = array();
 
-$answer[API_REDIRECT] = API_ANSWER_REDIRECT_CLIENT;
+$answer[API_REDIRECT] = API_ANSWER_REDIRECT_AUTO;
 $answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
 $answer[API_MESSAGE] = '';
 
 try {
-    $qfq = new \qfq\QuickFormQuery(['bodytext' => ""]);
+    $qfq = new QuickFormQuery(['bodytext' => ""]);
 
     $data = $qfq->saveForm();
 
diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index 4be683fbc8e06f225b86ebe077368c16c966f4df..5f3e6d45406e151c40d2739cbc9b2775ff05fac2 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -88,6 +88,7 @@ abstract class AbstractBuildForm {
      * @param array $db
      * @throws CodeException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative, array $db = null) {
         $this->formSpec = $formSpec;
@@ -177,6 +178,7 @@ abstract class AbstractBuildForm {
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function process($mode, $htmlElementNameIdZero = false, $latestFeSpecNative = array()) {
         $htmlHead = '';
@@ -252,6 +254,7 @@ abstract class AbstractBuildForm {
      * @param string $mode
      * @return string
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
      */
     public function head($mode = FORM_LOAD) {
@@ -329,6 +332,9 @@ abstract class AbstractBuildForm {
      * Returns '<form ...>'-tag with various attributes.
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function getFormTag() {
         $md5 = '';
@@ -347,6 +353,7 @@ abstract class AbstractBuildForm {
      *
      * @return string
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
      */
     public function buildInputRecordHashMd5() {
@@ -411,6 +418,9 @@ abstract class AbstractBuildForm {
      * Build an assoc array with standard form attributes.
      *
      * @return array
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function getFormTagAttributes() {
 
@@ -882,6 +892,8 @@ abstract class AbstractBuildForm {
      * @param array $formElement
      *
      * @return array
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function getFormElementForJson($htmlFormElementName, $value, array $formElement) {
 
@@ -924,6 +936,8 @@ abstract class AbstractBuildForm {
                 $class = 'col-md-' . $formElement[FE_BS_INPUT_COLUMNS] . ' ';
                 $class .= ($formElement[FE_MODE] == FE_MODE_HIDDEN) ? 'hidden' : '';
                 $json[API_ELEMENT_UPDATE][$key][API_ELEMENT_ATTRIBUTE]['class'] = $class;
+                $json[API_ELEMENT_UPDATE][$key][API_ELEMENT_ATTRIBUTE]['required'] = $formElement[FE_MODE] == 'required';
+                $json[API_ELEMENT_UPDATE][$key][API_ELEMENT_ATTRIBUTE]['hidden'] = $formElement[FE_MODE] == 'hidden';
             }
 
             // #3647
@@ -933,6 +947,8 @@ abstract class AbstractBuildForm {
             //TODO #5016 - exception for FE_TYPE_CHECKBOX should be removed ASAP
             if ($formElement[FE_TYPE] != FE_TYPE_SELECT && $formElement[FE_TYPE] != FE_TYPE_UPLOAD && $formElement[FE_TYPE] != FE_TYPE_CHECKBOX) {
                 $json[API_ELEMENT_UPDATE][$formElement[FE_HTML_ID]][API_ELEMENT_ATTRIBUTE]['value'] = $value;
+                $json[API_ELEMENT_UPDATE][$formElement[FE_HTML_ID]][API_ELEMENT_ATTRIBUTE]['required'] = $formElement[FE_MODE] == 'required';
+                $json[API_ELEMENT_UPDATE][$formElement[FE_HTML_ID]][API_ELEMENT_ATTRIBUTE]['hidden'] =  $formElement[FE_MODE] == 'hidden';
             }
         }
 
@@ -1174,6 +1190,7 @@ abstract class AbstractBuildForm {
         }
 
         $formElement = HelperFormElement::prepareExtraButton($formElement, !$flagTextarea);
+
         if ($flagTextarea) {
             $htmlTag = '<textarea';
 
@@ -1196,7 +1213,7 @@ abstract class AbstractBuildForm {
         if (empty($formElement[F_FE_DATA_PATTERN_ERROR])) {
             $formElement[F_FE_DATA_PATTERN_ERROR] = $sanitizeMessage;
         };
-        $attribute .= $this->getAttributeList($formElement, [F_FE_DATA_PATTERN_ERROR, F_FE_DATA_REQUIRED_ERROR, F_FE_DATA_MATCH_ERROR, F_FE_DATA_ERROR, FE_MIN, FE_MAX]);
+        $attribute .= $this->getAttributeList($formElement, [F_FE_DATA_PATTERN_ERROR, F_FE_DATA_REQUIRED_ERROR, F_FE_DATA_MATCH_ERROR, F_FE_DATA_ERROR, FE_MIN, FE_MAX, FE_STEP]);
         $attribute .= Support::doAttribute('data-load', ($formElement[FE_DYNAMIC_UPDATE] === 'yes') ? 'data-load' : '');
         $attribute .= Support::doAttribute('title', $formElement[FE_TOOLTIP]);
 
@@ -1205,7 +1222,7 @@ abstract class AbstractBuildForm {
 
         $json = $this->getFormElementForJson($htmlFormElementName, $value, $formElement);
 
-        $input = "$htmlTag $attribute>$textarea" . $this->getHelpBlock();
+        $input = "$htmlTag $attribute>$textarea";
 
         if ($formElement[FE_TMP_EXTRA_BUTTON_HTML] !== '') {
 
@@ -1216,14 +1233,13 @@ abstract class AbstractBuildForm {
             }
         }
 
-        $input .= $elementCharacterCount;
+        $input .=  $this->getHelpBlock() . $elementCharacterCount;
 
         if (isset($formElement[FE_INPUT_EXTRA_BUTTON_INFO])) {
             $input .= $formElement[FE_INPUT_EXTRA_BUTTON_INFO];
         }
 
         return $input;
-
     }
 
     /**
@@ -1632,6 +1648,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildCheckboxSingle(array $formElement, $htmlFormElementName, $attribute, $value, array &$json, $mode = FORM_LOAD) {
 
@@ -1775,6 +1793,8 @@ abstract class AbstractBuildForm {
      * @param array $itemValue
      * @param array $json
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildCheckboxMulti(array $formElement, $htmlFormElementName, $attributeBase, $value, array $itemKey, array $itemValue, array &$json) {
 
@@ -2310,6 +2330,7 @@ abstract class AbstractBuildForm {
      * @param array $control Array with <th> column names / format.
      *
      * @return string
+     * @throws UserFormException
      */
     private function subrecordHead($linkNew, $flagDelete, array $firstRow, array &$control) {
 
@@ -2344,6 +2365,7 @@ abstract class AbstractBuildForm {
      * @return string
      * @throws CodeException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildSubrecord(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $rcText = false;
@@ -2356,6 +2378,7 @@ abstract class AbstractBuildForm {
         $control = array();
 
         $primaryRecord = $this->store->getStore(STORE_RECORD);
+        $cssClassColumnId = $this->store->getVar(SYSTEM_CSS_CLASS_COLUMN_ID, STORE_SYSTEM . STORE_EMPTY);
 
         if (!$this->prepareSubrecord($formElement, $primaryRecord, $rcText, $nameColumnId)) {
             return $rcText;
@@ -2392,7 +2415,7 @@ abstract class AbstractBuildForm {
             // All columns
             foreach ($row as $columnName => $value) {
                 if (isset($control[SUBRECORD_COLUMN_TITLE][$columnName])) {
-                    $rowHtml .= Support::wrapTag("<td>", $this->renderCell($control, $columnName, $value));
+                    $rowHtml .= Support::wrapTag("<td>", $this->renderCell($control, $columnName, $value, $cssClassColumnId));
                 }
             }
 
@@ -2679,13 +2702,14 @@ abstract class AbstractBuildForm {
      * @param array $control
      * @param string $columnName
      * @param string $columnValue
+     * @param string $cssClassColumnId
      *
      * @return string
      * @throws CodeException
      * @throws UserFormException
      * @throws UserReportException
      */
-    private function renderCell(array $control, $columnName, $columnValue) {
+    private function renderCell(array $control, $columnName, $columnValue, $cssClassColumnId) {
         $link = null;
 
         switch ($columnName) {
@@ -2731,6 +2755,9 @@ abstract class AbstractBuildForm {
             $cell = $link->renderLink($columnValue);
         }
 
+        if(strcasecmp($columnName, 'id')==0){
+            $cell = Support::wrapTag('<span class="'. $cssClassColumnId .'">', $cell,true);
+        }
         return $cell;
     }
 
@@ -3391,6 +3418,7 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      * @return mixed
      * @throws CodeException
+     * @throws UserFormException
      */
     public function buildNote(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
 
diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php
index 0a686799147e0d6012c59bf732b373e44f83aa12..0b86343d6c340738774c7a02ee7f949dcd7cb7c6 100644
--- a/extension/qfq/qfq/BuildFormBootstrap.php
+++ b/extension/qfq/qfq/BuildFormBootstrap.php
@@ -44,7 +44,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
 //        $this->wrap[WRAP_SETUP_OUTER][WRAP_SETUP_START] = '<div class="tab-content">';
 //        $this->wrap[WRAP_SETUP_OUTER][WRAP_SETUP_END] = '</div>';
 
-        $this->wrap[WRAP_SETUP_TITLE][WRAP_SETUP_START] = "<div class='row hidden-xs'><div class='col-md-12'><h1>";
+        $this->wrap[WRAP_SETUP_TITLE][WRAP_SETUP_START] = "<div class='row'><div class='col-md-12'><h1>";
         $this->wrap[WRAP_SETUP_TITLE][WRAP_SETUP_END] = "</h1></div></div>";
 
         // Element: Label + Input + Note
@@ -113,16 +113,18 @@ class BuildFormBootstrap extends AbstractBuildForm {
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function head($mode = FORM_LOAD) {
         $html = '';
 
         $html .= '<div ' . Support::doAttribute('class', $this->formSpec[F_CLASS], true) . '>'; // main <div class=...> around everything, Whole FORM; class="container" or class="container-fluid"
 
-        //TODO: nicer error reporting - make test with 'unknown index' here - unset($this->formSpec['title']) - See #3424
-        $title = Support::wrapTag('<div class="hidden-xs col-sm-6 col-md-8">', Support::wrapTag('<h3>', $this->formSpec[F_TITLE]));
-        $button = Support::wrapTag('<div class="col-xs-12 col-sm-6 col-md-4">', $this->buildButtons());
-        $html .= Support::wrapTag('<div class="row">', $title . $button);
+        $button = Support::wrapTag('<div class="row"><div class="col-md-12">', $this->buildButtons());
+
+        $title = Support::wrapTag('<div class="row"><div class="col-md-12">', Support::wrapTag('<div class="qfq-form-title">', $this->formSpec[F_TITLE]));
+
+        $html .= $button . $title;
 
         $dummy = array();
         $pill = $this->buildPillNavigation($mode, OnArray::filter($this->feSpecNative, FE_TYPE, FE_TYPE_PILL), $dummy);
@@ -305,12 +307,17 @@ class BuildFormBootstrap extends AbstractBuildForm {
         // Arrangement: Edit Form / Save / Close / Delete / New
         // Specified in reverse order cause 'pull-right' inverts the order. http://getbootstrap.com/css/#helper-classes-floats
         $html = '';
-        $html .= Support::wrapTag('<div class="btn-group pull-right" role="group">', $buttonNew);
-        $html .= Support::wrapTag('<div class="btn-group pull-right" role="group">', $buttonDelete);
-        $html .= Support::wrapTag('<div class="btn-group pull-right" role="group">', $buttonSave . $buttonClose);
-        $html .= Support::wrapTag('<div class="btn-group pull-right" role="group">', $buttonEditForm);
+//        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonNew);
+//        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonDelete);
+//        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonSave . $buttonClose);
+//        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonEditForm);
+
+        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonEditForm);
+        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonSave . $buttonClose);
+        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonDelete);
+        $html .= Support::wrapTag('<div class="btn-group" role="group">', $buttonNew);
 
-        $html = Support::wrapTag('<div class="btn-toolbar" role="toolbar">', $html);
+        $html = Support::wrapTag('<div class="btn-toolbar pull-right" role="toolbar">', $html);
 
         return $html;
     }
@@ -383,7 +390,9 @@ class BuildFormBootstrap extends AbstractBuildForm {
      * @param array $json
      * @return string
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     private function buildPillNavigation($mode = FORM_LOAD, array $pillArray, array &$json) {
         $pillButton = '';
@@ -513,6 +522,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
      * @return string
      * @throws CodeException
      * @throws DbException
+     * @throws UserFormException
      */
     public function getFormTag() {
 
@@ -595,6 +605,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
                     fileDeleteUrl: '$apiDir/file.php?$actionDelete'
                 });
 
+               
                 var qfqRecordList = new QfqNS.QfqRecordList('$apiDeletePhp');
             })
          </script>
@@ -614,6 +625,7 @@ EOF;
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildPill(array $formElement, $htmlFormElementName, $value, array &$json) {
         $html = '';
@@ -809,6 +821,7 @@ EOF;
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function process($mode, $htmlElementNameIdZero = false, $latestFeSpecNative = array()) {
 
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index fdd3750748f0949026c175317ff3e093ed200b65..33a8cf17ee8e7f750cfed44b54cae900a05c143b 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -7,7 +7,8 @@
  */
 
 const EXT_KEY = 'qfq';
-const CONFIG_QFQ = "config.qfq.ini";  // QFQ configuration file: db access
+const CONFIG_QFQ_INI = "config.qfq.ini";  // QFQ configuration file: db access
+const CONFIG_QFQ_PHP = "config.qfq.php";  // QFQ configuration file: db access
 const CONFIG_T3 = 'LocalConfiguration.php'; // T3 config file
 
 const GFX_INFO = 'typo3conf/ext/qfq/Resources/Public/icons/note.gif';
@@ -33,6 +34,7 @@ const FORM_LOAD = 'form_load';
 const FORM_SAVE = 'form_save';
 const FORM_UPDATE = 'form_update';
 const FORM_DELETE = 'form_delete';
+const FORM_DRAG_AND_DROP = 'form_drag_and_drop';
 const FORM_PERMISSION_SIP = 'sip';
 const FORM_PERMISSION_LOGGED_IN = 'logged_id';
 const FORM_PERMISSION_LOGGED_OUT = 'logged_out';
@@ -143,10 +145,12 @@ const ERROR_DEBUG = 1031;
 const ERROR_UNKNOWN_MODE = 1032;
 const ERROR_NOT_IMPLEMENTED = 1033;
 const ERROR_RESERVED_KEY_NAME = 1034;
+const ERROR_MISSING_FORM = 1035;
 const ERROR_MISSING_PARAMETER_FILE = 1035;
 const ERROR_UNKNOWN_FORWARD_MODE = 1036;
-
-const ERROR_MISSING_HIDDEN_FIELD_IN_SIP = 1038;
+const ERROR_MISSING_MESSAGE_FAIL = 1037;
+const ERROR_MISSING_EXPECT_RECORDS = 1038;
+const ERROR_MISSING_HIDDEN_FIELD_IN_SIP = 1039;
 
 const ERROR_UNKNOWN_CHECKTYPE = 1042;
 const ERROR_PATTERN_VIOLATION = 1043;
@@ -247,6 +251,7 @@ const ERROR_DOWNLOAD_NO_FILES = 1701;
 const ERROR_DOWNLOAD_NOTHING_TO_DO = 1702;
 const ERROR_DOWNLOAD_UNEXPECTED_MIME_TYPE = 1703;
 const ERROR_DOWNLOAD_UNEXPECTED_NUMBER_OF_SOURCES = 1704;
+const ERROR_DOWNLOAD_FILE_NOT_READABLE = 1705;
 
 // KeyValueParser
 const ERROR_KVP_VALUE_HAS_NO_KEY = 1900;
@@ -390,8 +395,8 @@ const SYSTEM_DB_INIT = 'init';
 const SYSTEM_DB_INDEX_DATA = "indexData";
 const SYSTEM_DB_INDEX_QFQ = "indexQfq";
 
-const SYSTEM_DB_INDEX_DATA_DEPRECATED = "DB_INDEX_DATA";
-const SYSTEM_DB_INDEX_QFQ_DEPRECATED = "DB_INDEX_QFQ";
+//const SYSTEM_DB_INDEX_DATA_DEPRECATED = "DB_INDEX_DATA";
+//const SYSTEM_DB_INDEX_QFQ_DEPRECATED = "DB_INDEX_QFQ";
 
 // Computed dynamically
 const SYSTEM_DB_NAME_DATA = '_dbNameData';
@@ -418,6 +423,8 @@ const SYSTEM_CSS_CLASS_QFQ_FORM = 'cssClassQfqForm';
 const SYSTEM_CSS_CLASS_QFQ_FORM_PILL = 'cssClassQfqFormPill';
 const SYSTEM_CSS_CLASS_QFQ_FORM_BODY = 'cssClassQfqFormBody';
 
+const SYSTEM_CSS_CLASS_COLUMN_ID = 'cssClassColumnId';
+
 // Textmessages used for Form validation.
 const SYSTEM_FORM_DATA_PATTERN_ERROR = 'formDataPatternError';
 const SYSTEM_FORM_DATA_REQUIRED_ERROR = 'formDataRequiredError';
@@ -511,6 +518,7 @@ const SYSTEM_FORM_LANGUAGE_D_ID = 'formLanguageDId';
 const SYSTEM_FORM_LANGUAGE_D_LABEL = 'formLanguageDLabel';
 
 const SYSTEM_ENTER_AS_SUBMIT = 'enterAsSubmit';
+const SYSTEM_SHOW_ID_IN_FORM_TITLE = 'showIdInFormTitle';
 
 const SYSTEM_CMD_WKHTMLTOPDF = 'cmdWkhtmltopdf';
 
@@ -546,6 +554,7 @@ const SYSTEM_DOWNLOAD_POPUP = 'hasDownloadPopup'; // Marker which is set to 'tru
 const DOWNLOAD_POPUP_REQUEST = 'true';
 const DOWNLOAD_POPUP_REPLACE_TEXT = '#downloadPopupReplaceText#';
 const DOWNLOAD_POPUP_REPLACE_TITLE = '#downloadPopupReplaceTitle#';
+const SYSTEM_DRAG_AND_DROP_JS = 'hasDragAndDropJS';
 
 const SYSTEM_PARAMETER_LANGUAGE_FIELD_NAME = 'parameterLanguageFieldName';
 const CSS_REQUIRED = 'required-field';
@@ -647,6 +656,7 @@ const MODE_LDAP_MULTI = 'ldapMulti';
 // api/save.php, api/delete.php, api/load.php
 const API_DELETE_PHP = 'delete.php';
 const API_DOWNLOAD_PHP = 'download.php';
+const API_DRAG_AND_DROP_PHP = 'dragAndDrop.php';
 
 const API_STATUS = 'status';
 const API_MESSAGE = 'message';
@@ -679,7 +689,8 @@ const API_ANSWER_STATUS_SUCCESS = 'success';
 const API_ANSWER_STATUS_CONFLICT = 'conflict';
 const API_ANSWER_STATUS_CONFLICT_ALLOW_FORCE = 'conflict_allow_force';
 const API_ANSWER_STATUS_ERROR = 'error';
-const API_ANSWER_REDIRECT_CLIENT = 'client';
+const API_ANSWER_REDIRECT_AUTO = 'auto';
+const API_ANSWER_REDIRECT_CLOSE = 'close';
 const API_ANSWER_REDIRECT_NO = 'no';
 const API_ANSWER_REDIRECT_URL = 'url';
 const API_ANSWER_REDIRECT_URL_SKIP_HISTORY = 'url-skip-history';
@@ -786,7 +797,8 @@ const F_SHOW_BUTTON = 'showButton';
 const F_FORWARD_MODE = 'forwardMode';
 const F_FORWARD_PAGE = 'forwardPage';
 
-const F_FORWARD_MODE_CLIENT = API_ANSWER_REDIRECT_CLIENT;
+const F_FORWARD_MODE_AUTO = API_ANSWER_REDIRECT_AUTO;
+const F_FORWARD_MODE_CLOSE = API_ANSWER_REDIRECT_CLOSE;
 const F_FORWARD_MODE_NO = API_ANSWER_REDIRECT_NO;
 const F_FORWARD_MODE_URL = API_ANSWER_REDIRECT_URL;
 const F_FORWARD_MODE_URL_SKIP_HISTORY = API_ANSWER_REDIRECT_URL_SKIP_HISTORY;
@@ -851,6 +863,13 @@ const F_NEW_BUTTON_GLYPH_ICON = SYSTEM_NEW_BUTTON_GLYPH_ICON;
 
 const F_ENTER_AS_SUBMIT = SYSTEM_ENTER_AS_SUBMIT;
 
+const F_DRAG_AND_DROP_ORDER_SQL = 'dragAndDropOrderSql';
+const F_ORDER_INTERVAL = 'orderInterval';
+const F_ORDER_COLUMN = 'orderColumn';
+const F_ORDER_COLUMN_NAME = 'ord';
+
+const F_SHOW_ID_IN_FORM_TITLE = SYSTEM_SHOW_ID_IN_FORM_TITLE;
+
 // FORM_ELEMENT_STATI
 const FE_MODE_SHOW = 'show';
 const FE_MODE_READONLY = 'readonly';
@@ -994,6 +1013,7 @@ const FE_SUBRECORD_TABLE_CLASS = 'subrecordTableClass';
 const FE_FILE_BUTTON_TEXT = 'fileButtonText';
 const FE_FILE_BUTTON_TEXT_DEFAULT = 'Choose File';
 const FE_INPUT_TYPE = 'inputType';
+const FE_STEP = 'step';
 
 const FE_IMAGE_CUT_RESIZE_WIDTH = 'resizeWidth';
 const FE_IMAGE_CUT_KEEP_ORIGINAL = 'keepOriginal';
@@ -1070,6 +1090,8 @@ const HTML_ATTR_ID = 'id';
 const HTML_ATTR_NAME = 'name';
 const HTML_ATTR_CLASS = 'class';
 
+const HTML_INPUT_TYPE_NUMBER = 'number';
+
 const SHEBANG_REPORT = '#!report';
 
 // SUPPORT
@@ -1429,3 +1451,15 @@ const EXCEPTION_STACKTRACE = 'Stacktrace';
 
 const EXCEPTION_TABLE_CLASS = 'table table-hover qfq-table-80';
 
+// Drag And Drop
+const DND_DRAG_ID = 'dragId';
+const DND_DRAG_POSITION = 'dragPosition';
+const DND_SET_TO = 'setTo';
+const DND_SET_TO_BEFORE = 'before';
+const DND_SET_TO_AFTER = 'after';
+const DND_HOVER_ID = 'hoverId';
+const DND_HOVER_POSITION = 'hoverPosition';
+const DND_COLUMN_ID = 'id';
+const DND_COLUMN_ORD = 'ord';
+const DND_COLUMN_ORD_NEW = 'ordNew';
+const DND_DATA_DND_API = 'data-dnd-api';
\ No newline at end of file
diff --git a/extension/qfq/qfq/Delete.php b/extension/qfq/qfq/Delete.php
index afd4ec52101ba9a08f6d96123fbc53dc66a1020a..70abc44f504aacfb002c4c220072db1914173807 100644
--- a/extension/qfq/qfq/Delete.php
+++ b/extension/qfq/qfq/Delete.php
@@ -32,6 +32,7 @@ class Delete {
      * @param bool $dbIndexData
      * @param bool $phpUnit
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
      */
     public function __construct($dbIndexData = false, $phpUnit = false) {
diff --git a/extension/qfq/qfq/Evaluate.php b/extension/qfq/qfq/Evaluate.php
index b29a27101aadbd1475977026aea2108a6b3cd00c..c84538ac9283f2ad88ad4ef3c9ac6888c4a7d0f5 100644
--- a/extension/qfq/qfq/Evaluate.php
+++ b/extension/qfq/qfq/Evaluate.php
@@ -197,6 +197,59 @@ class Evaluate {
         return $result;
     }
 
+    /**
+     * @param $arrToken
+     * @param $dbIndex
+     * @param $foundInStore
+     * @return string
+     * @throws CodeException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    private function inlineLink($arrToken, $dbIndex, &$foundInStore){
+
+        $token = OnString::trimQuote(trim(implode(' ', $arrToken)));
+
+        if ($this->link === null) {
+            $this->link = new Link($this->store->getSipInstance(), $dbIndex);
+        }
+
+        $foundInStore = TOKEN_FOUND_AS_COLUMN;
+
+        return $this->link->renderLink($token);
+    }
+
+    /**
+     * @param $arrToken
+     * @param $dbIndex
+     * @param $foundInStore
+     * @return string
+     * @throws CodeException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    private function inlineDataDndApi($arrToken, $dbIndex, &$foundInStore){
+
+        $token = OnString::trimQuote(trim(implode(' ', $arrToken)));
+        if(empty($token)){
+            throw new UserReportException('Missing form name for "data-dnd-api"', ERROR_MISSING_FORM);
+        }
+
+        if ($this->link === null) {
+            $this->link = new Link($this->store->getSipInstance(), $dbIndex);
+        }
+
+        $foundInStore = TOKEN_FOUND_AS_COLUMN;
+
+        $s = $this->link->renderLink('U:' . $token . '|s|r:8');
+
+        // Flag to add DND JS code later on.
+        $this->store->setVar(SYSTEM_DRAG_AND_DROP_JS, 'true', STORE_SYSTEM);
+
+        // data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s={{'U:form=<form name>[&paramX=<any value>]|s|r:8' AS _link}}"
+        return DND_DATA_DND_API . '="' . API_DIR . '/' . API_DRAG_AND_DROP_PHP . '?s=' . $s . '"';
+    }
+
     /**
      * Tries to substitute $token.
      * Token might be:
@@ -244,7 +297,7 @@ class Evaluate {
             $sqlMode = ROW_REGULAR;
         }
 
-        // Extract token: check if this is a SQL Statement
+        // Extract token: check if this is a 'variable', 'SQL Statement', 'link', 'data-dnd-api'
         $arrToken = explode(' ', $token);
 
         // Variable Type 'SQL Statement'
@@ -254,23 +307,22 @@ class Evaluate {
             return $this->dbArray[$dbIndex]->sql($token, $sqlMode);
         }
 
-        // Variable Type '... AS LINK'
+        // Variable Type '... AS _link', '... as data-dnd-api'
         $countToken = count($arrToken);
         if ($countToken > 2 && strcasecmp($arrToken[$countToken - 2], 'as') == 0) {
 
             $type = OnString::stripFirstCharIf('_', $arrToken[$countToken - 1]);
 
-            if (strcasecmp($type, 'link') == 0) {
-
-                $str = OnString::trimQuote(substr($token, 0, strlen($token) - 8));  // strlen('_as_link')=8
+            array_pop($arrToken); // remove 'link' | 'data-dnd-api'
+            array_pop($arrToken); // remove 'as'
 
-                if ($this->link === null) {
-                    $this->link = new Link($this->store->getSipInstance(), $dbIndex);
-                }
+            if (strcasecmp($type, COLUMN_LINK ) == 0) {
+                return($this->inlineLink($arrToken, $dbIndex,$foundInStore));
+            }
 
-                $foundInStore = TOKEN_FOUND_AS_COLUMN;
+            if($type == DND_DATA_DND_API){
+                return($this->inlineDataDndApi($arrToken, $dbIndex,$foundInStore));
 
-                return $this->link->renderLink($str);
             }
         }
 
diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php
index f16ce9182cdbb250618c8eeddb3dde560936d731..07ebc4987b01f9d080c1d236e1c96c98e9611320 100644
--- a/extension/qfq/qfq/QuickFormQuery.php
+++ b/extension/qfq/qfq/QuickFormQuery.php
@@ -44,6 +44,7 @@ require_once(__DIR__ . '/BodytextParser.php');
 require_once(__DIR__ . '/Delete.php');
 require_once(__DIR__ . '/form/FormAction.php');
 require_once(__DIR__ . '/form/Dirty.php');
+require_once(__DIR__ . '/form/DragAndDrop.php');
 
 /*
  * Form will be called
@@ -219,6 +220,7 @@ class QuickFormQuery {
      * @return string
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -238,6 +240,11 @@ class QuickFormQuery {
             $html .= $this->getModalCode();
         }
 
+        // Only needed if there are 'drag and drop' elements.
+        if ($this->store->getVar(SYSTEM_DRAG_AND_DROP_JS, STORE_SYSTEM) == 'true') {
+            $html .= $this->getDragAndDropCode();
+        }
+
         $class = $this->store->getVar(SYSTEM_CSS_CLASS_QFQ_CONTAINER, STORE_SYSTEM);
         if ($class) {
             $html = Support::wrapTag("<div class='$class'>", $html);
@@ -248,6 +255,9 @@ class QuickFormQuery {
 
     /**
      * Determine the name of the language parameter field, which has to be taken to fill language specific defintions.
+     *
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function setParameterLanguageFieldName() {
 
@@ -265,6 +275,7 @@ class QuickFormQuery {
         }
     }
 
+
     /**
      * Process form.
      * $mode=
@@ -278,6 +289,7 @@ class QuickFormQuery {
      * @return array|string
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -286,7 +298,7 @@ class QuickFormQuery {
         $foundInStore = '';
 
         // Fill STORE_FORM
-        if ($formMode === FORM_UPDATE || $formMode === FORM_SAVE) {
+        if ($formMode === FORM_UPDATE || $formMode === FORM_SAVE || $formMode === FORM_DRAG_AND_DROP) {
             $fillStoreForm = new FillStoreForm();
             $fillStoreForm->process($formMode);
         }
@@ -295,9 +307,15 @@ class QuickFormQuery {
         $this->setParameterLanguageFieldName();
 
         $formName = $this->loadFormSpecification($formMode, $recordId, $foundInStore);
-        if ($formName === false && $formMode !== FORM_DELETE) {
-            // No form found: do nothing
-            return '';
+        if ($formName === false) {
+            switch ($formName) {
+                case FORM_DELETE:
+                    break;
+                case FORM_DRAG_AND_DROP:
+                    throw new CodeException('Missing form in SIP', ERROR_MISSING_FORM);
+                default:
+                    return '';// No form found: do nothing
+            }
         }
 
         if ($formName !== false) {
@@ -310,6 +328,7 @@ class QuickFormQuery {
             if ($table === false) {
                 throw new UserFormException("No 'form' and no 'table' definition found.", ERROR_MISSING_VALUE);
             }
+
             $sipFound = true;
             $this->formSpec[F_NAME] = '';
             $this->formSpec[F_TABLE_NAME] = $table;
@@ -423,6 +442,7 @@ class QuickFormQuery {
                 $save = new Save($this->formSpec, $this->feSpecAction, $this->feSpecNative, $this->feSpecNativeRaw);
 
                 $save->processAllImageCutFE();
+                $save->checkRequiredHidden();
 
                 $rc = $save->process();
 
@@ -474,7 +494,15 @@ class QuickFormQuery {
                     // $data = $build->process($formMode, $htmlElementNameIdZero);
                     $data = $build->process($formMode, false, $this->feSpecNative);
                 }
+                break;
 
+            case FORM_DRAG_AND_DROP:
+                $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
+
+                $dragAndDrop = new DragAndDrop($this->formSpec);
+                $dragAndDrop->process($this->formSpec);
+
+                $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_LOAD);
                 break;
 
             default:
@@ -524,7 +552,8 @@ class QuickFormQuery {
         $forward = trim($forwardArray[0]);
         switch ($forward) {
 
-            case F_FORWARD_MODE_CLIENT:
+            case F_FORWARD_MODE_AUTO:
+            case F_FORWARD_MODE_CLOSE:
             case F_FORWARD_MODE_NO:
             case F_FORWARD_MODE_URL:
             case F_FORWARD_MODE_URL_SKIP_HISTORY:
@@ -544,7 +573,7 @@ class QuickFormQuery {
 
         if ('url' == substr($this->formSpec[F_FORWARD_MODE], 0, 3)) {
             if ($this->formSpec[F_FORWARD_PAGE] == '') {
-                $this->formSpec[F_FORWARD_MODE] = F_FORWARD_MODE_CLIENT;
+                $this->formSpec[F_FORWARD_MODE] = F_FORWARD_MODE_AUTO;
                 $customForward = false;
             } else {
                 $customForward = true;
@@ -722,7 +751,7 @@ class QuickFormQuery {
         $formSpec = HelperFormElement::setLanguage($formSpec, $parameterLanguageFieldName);
 
         $formSpec = $this->syncSystemFormConfig($formSpec);
-        $formSpec = $this->initForm($formSpec);
+        $formSpec = $this->initForm($formSpec, $recordId);
 
         $formSpec = array_merge($formSpec, $parseLater);
 
@@ -764,7 +793,7 @@ class QuickFormQuery {
 
             case FORM_SAVE:
             case FORM_UPDATE:
-            $feSpecNative = $this->getNativeFormElements(SQL_FORM_ELEMENT_NATIVE_TG_COUNT, [$this->formSpec[F_ID]], $this->formSpec);
+                $feSpecNative = $this->getNativeFormElements(SQL_FORM_ELEMENT_NATIVE_TG_COUNT, [$this->formSpec[F_ID]], $this->formSpec);
                 break;
 
             case FORM_DELETE:
@@ -902,6 +931,7 @@ class QuickFormQuery {
             case FORM_SAVE:
             case FORM_UPDATE:
             case FORM_DELETE:
+            case FORM_DRAG_AND_DROP:
                 $store = STORE_SIP;
                 break;
             default:
@@ -950,7 +980,7 @@ class QuickFormQuery {
     /**
      * The named $keys will be synced between STORE_SYSTEM and $formSpec (both directions).
      * The per form definition has precedence over STORE_SYSTEM.
-     * STORE_SYSTEM if filled with the default values (config.qfq.ini or if note exist than QFQ hardcoded)
+     * STORE_SYSTEM if filled with the default values (config.qfq.php or if note exist than QFQ hardcoded)
      * Copying the 'Form' definition back to the system store helps to access the values
      * by '{{ ...:Y}}' (system store). E.g. the value of bs-*-columns might be displayed as placeholder in the
      * corresponding input field.
@@ -999,6 +1029,7 @@ class QuickFormQuery {
             F_RECORD_LOCK_TIMEOUT_SECONDS,
 
             FE_INPUT_EXTRA_BUTTON_INFO_CLASS,
+            F_SHOW_ID_IN_FORM_TITLE,
         ];
 
         // By definition: existing vars which are empty, means: EMPTY - do not use any default!
@@ -1026,12 +1057,13 @@ class QuickFormQuery {
      * Set form parameter which are expected to exist.
      *
      * @param array $formSpec
+     * @param int $recordId
      *
      * @return array
      * @throws CodeException
      * @throws UserFormException
      */
-    private function initForm(array $formSpec) {
+    private function initForm(array $formSpec, $recordId) {
 
         Support::setIfNotSet($formSpec, F_EXTRA_DELETE_FORM, '');
         Support::setIfNotSet($formSpec, F_SUBMIT_BUTTON_TEXT, '');
@@ -1058,6 +1090,11 @@ class QuickFormQuery {
             $formSpec[F_ESCAPE_TYPE_DEFAULT] = $this->store->getVar(F_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
         }
 
+        // Append recordId to title
+        if($formSpec[F_SHOW_ID_IN_FORM_TITLE]=='1'){
+            $formSpec[F_TITLE] .= ($recordId==0) ? " (new)" : " ($recordId)";
+        }
+
         return $formSpec;
     }
 
@@ -1218,7 +1255,6 @@ class QuickFormQuery {
         $html = $report->process($this->t3data['bodytext']);
 
         return $html;
-
     }
 
     /**
@@ -1227,6 +1263,7 @@ class QuickFormQuery {
      * @return string
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -1243,6 +1280,7 @@ class QuickFormQuery {
      * @return array
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -1253,12 +1291,30 @@ class QuickFormQuery {
         return $json;
     }
 
+    /**
+     * Update FormElements and form values. Receives the current form values via POST.
+     *
+     * @return array
+     * @throws CodeException
+     * @throws DbException
+     * @throws DownloadException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    public function dragAndDrop() {
+
+        $json = $this->doForm(FORM_DRAG_AND_DROP);
+
+        return $json;
+    }
+
     /**
      * Delete a record (tablename and recordid are given) or process a 'delete form'
      *
      * @return array
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -1342,4 +1398,33 @@ EOF;
 
         return $code;
     }
+
+    /**
+     * @return string
+     */
+    private function getDragAndDropCode() {
+
+        $code = <<<EOF
+            <script type="text/javascript">
+                $(function () {
+            
+            
+                    $('.qfq-dnd-sort').each(function() {
+                        var dndObject = new QfqNS.DragAndDrop($(this));
+                        dndObject.makeSortable();
+                    });
+            
+                    var zoni = new QfqNS.DragAndDrop($('.qfq-dnd'));
+                    zoni.makeBasketCase();
+            
+            
+                });
+            </script>
+EOF;
+
+        return $code;
+
+    }
+
+
 }
\ No newline at end of file
diff --git a/extension/qfq/qfq/Save.php b/extension/qfq/qfq/Save.php
index bd523da9eac15e255862050e4876b81a89877ea9..ad7c23b95667f7a24789afe3cfe310bcec1c70a6 100644
--- a/extension/qfq/qfq/Save.php
+++ b/extension/qfq/qfq/Save.php
@@ -43,6 +43,7 @@ class Save {
      * @param array $feSpecNative
      * @param array $feSpecNativeRaw
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
      */
     public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative, array $feSpecNativeRaw) {
@@ -389,9 +390,11 @@ class Save {
     }
 
     /**
-     * Process all Upload Formelements for the given $recordId. After processing &$formValues will be updated with the
-     * final filenames.
+     * Process all Upload FormElements for the given $recordId.
+     * After processing, &$formValues will be updated with the final filename.
      *
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function processAllImageCutFE() {
 
@@ -405,6 +408,47 @@ class Save {
         }
     }
 
+
+    /**
+     * Iterates over all FE and checks all 'required' (mode & modeSql) FE.
+     * If a required FE is empty, throw an exception.
+     * Take care to remove all FE with modeSql='hidden'.
+     *
+     * Typically, the browser does not allow a submit if a required field is empty.
+     *
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    public function checkRequiredHidden() {
+
+        $requiredOff = ($this->store->getVar(F_MODE_GLOBAL, STORE_SIP) == F_MODE_REQUIRED_OFF);
+
+        $clientValues = $this->store::getStore(STORE_FORM);
+
+        foreach ($this->feSpecNative AS $key => $formElement) {
+
+            $this->store->setVar(SYSTEM_FORM_ELEMENT, "Column: " . $formElement[FE_NAME], STORE_SYSTEM);
+
+            if (empty($formElement[FE_MODE_SQL])) {
+                $mode = $formElement[FE_MODE];
+            } else {
+                $mode = $this->evaluate->parse($formElement[FE_MODE_SQL]);
+                $this->feSpecNative[$key][FE_MODE_SQL] = $mode;
+            }
+
+            if (!$requiredOff && $mode == FE_MODE_REQUIRED && empty($clientValues[$formElement[FE_NAME]])) {
+                throw new UserFormException("Missing required value: " . $formElement[FE_LABEL], ERROR_REQUIRED_VALUE_EMPTY);
+            }
+
+            if ($mode == FE_MODE_HIDDEN) {
+                // Removing the value from the store, forces that the value won't be stored.
+                $this->store::unsetVar($formElement[FE_NAME], STORE_FORM);
+            }
+        }
+    }
+
     /**
      *
      * @param array $formElement
@@ -420,7 +464,7 @@ class Save {
             throw new UserFormException("getcwd() failed or SITE_PATH undefined or chdir('$sitePath') failed.", ERROR_IO_CHDIR);
         }
 
-        // Get original pathfilename
+        // Get original pathFileName
         $field = HelperFormElement::AppendFormElementNameImageCut($formElement);
         $pathFileName = $this->store->getVar($field, STORE_SIP);
         if ($pathFileName == '' || !file_exists($pathFileName)) {
diff --git a/extension/qfq/qfq/database/DatabaseUpdateData.php b/extension/qfq/qfq/database/DatabaseUpdateData.php
index 7c0b010ef84ebea1e15dbf17808e54192ef990dc..e86958364ac9d0555d1008af0b5cf3dd2c343459 100644
--- a/extension/qfq/qfq/database/DatabaseUpdateData.php
+++ b/extension/qfq/qfq/database/DatabaseUpdateData.php
@@ -114,6 +114,12 @@ $UPDATE_ARRAY = array(
         "ALTER TABLE `Cron` ADD `outputPattern` VARCHAR(255) NOT NULL AFTER `outputMode`",
     ],
 
+    '18.06.0' => [
+        "ALTER TABLE `Form` CHANGE `forwardMode` `forwardMode` ENUM('auto', 'client','no','url','url-skip-history','url-sip') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'client'",
+        "UPDATE `Form` SET forwardMode='auto' WHERE  forwardMode='client'",
+        "ALTER TABLE `Form` CHANGE `forwardMode` `forwardMode` ENUM('auto', 'close', 'no','url','url-skip-history','url-sip') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'auto';",
+    ],
+
 
 );
 
diff --git a/extension/qfq/qfq/exceptions/AbstractException.php b/extension/qfq/qfq/exceptions/AbstractException.php
index 14ca5f6bd776dd2e99e0950e34d19b8fba6bbc1a..baee036b42567fc1b1cf7d7848d8895af36fb593 100644
--- a/extension/qfq/qfq/exceptions/AbstractException.php
+++ b/extension/qfq/qfq/exceptions/AbstractException.php
@@ -48,6 +48,8 @@ class AbstractException extends \Exception {
             $t3Vars = $store->getStore(STORE_TYPO3);
         } catch (CodeException $e) {
             $store = null;
+        } catch (\Exception $exception){
+            $store = null;
         }
 
         if (empty($t3Vars)) {
@@ -66,9 +68,6 @@ class AbstractException extends \Exception {
             }
         }
 
-//        $html .= "Code: " . htmlspecialchars($this->messageArray['Code']) . "<br>";
-//        $html .= "Message: " . Support::wrapTag("<strong>", htmlspecialchars($this->messageArray['Message'])) . "<br>";
-
         // Debug Information
         if ($store !== null && Support::findInSet(SYSTEM_SHOW_DEBUG_INFO_YES, $store->getVar(SYSTEM_SHOW_DEBUG_INFO, STORE_SYSTEM))) {
 
@@ -103,7 +102,6 @@ class AbstractException extends \Exception {
             $htmlDebug = OnArray::arrayToHtmlTable($arrDebugShow, 'Debug', EXCEPTION_TABLE_CLASS);
             $hidden = OnArray::arrayToHtmlTable($arrDebugHidden, 'Details', EXCEPTION_TABLE_CLASS);
 
-//            $hidden = 'mein test<br>und mehr content';
             // Show / hide with just CSS: http://jsfiddle.net/t5Nf8/1/
             $htmlDebug .= "<style>input[type=checkbox]:checked + label + table { display: none; }</style>" .
                 "<input type='checkbox' checked id='stacktrace'><label for='stacktrace'>&nbsp;Show/hide more details</label>$hidden";
@@ -112,10 +110,6 @@ class AbstractException extends \Exception {
         // Sanitize any HTML content.
         $arrShow = OnArray::htmlentitiesOnArray($arrShow);
         $html = OnArray::arrayToHtmlTable($arrShow, 'Error', EXCEPTION_TABLE_CLASS);
-//        foreach ($show as $key => $value) {
-//            $html .= "$key: " . Support::wrapTag("<strong>", $value) . "<br>";
-//        }
-//        $html ='Houston, we have a problem';
 
         return $html . $htmlDebug;
     }
diff --git a/extension/qfq/qfq/exceptions/UserFormException.php b/extension/qfq/qfq/exceptions/UserFormException.php
index ae08a04e2b71f7a642b8ed8947952f6afde7983d..a35548beb9fab1a3efa49b9bb611757bd1297d61 100644
--- a/extension/qfq/qfq/exceptions/UserFormException.php
+++ b/extension/qfq/qfq/exceptions/UserFormException.php
@@ -20,9 +20,6 @@ require_once(__DIR__ . '/AbstractException.php');
  */
 class UserFormException extends AbstractException {
 
-    /*
-    * @return string HTML formatted error string
-    */
     /**
      * @return string
      * @throws CodeException
diff --git a/extension/qfq/qfq/form/DragAndDrop.php b/extension/qfq/qfq/form/DragAndDrop.php
new file mode 100644
index 0000000000000000000000000000000000000000..9be716f0fe64059ca7972cbe5a07c17bcf0c2f9a
--- /dev/null
+++ b/extension/qfq/qfq/form/DragAndDrop.php
@@ -0,0 +1,162 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: crose
+ * Date: 3/13/17
+ * Time: 9:29 PM
+ */
+
+namespace qfq;
+
+//use TYPO3\CMS\Core\FormProtection\Exception;
+
+//require_once(__DIR__ . '/../store/Sip.php');
+//require_once(__DIR__ . '/../store/Session.php');
+require_once(__DIR__ . '/../store/Store.php');
+require_once(__DIR__ . '/../Constants.php');
+//require_once(__DIR__ . '/../helper/Ldap.php');
+require_once(__DIR__ . '/../database/Database.php');
+require_once(__DIR__ . '/../Evaluate.php');
+
+
+/**
+ * Class DragAndDrop
+ * @package qfq
+ */
+class DragAndDrop {
+
+    /**
+     * @var Database instantiated class
+     */
+    private $db = null;
+
+    /**
+     * @var Store
+     */
+    private $store = null;
+
+    /**
+     * @var Evaluate instantiated class
+     */
+    protected $evaluate = null;  // copy of the loaded form
+
+    /**
+     * @var array
+     */
+    private $formSpec = null;
+
+    /**
+     * @param array $formSpec F_TABLE_NAME, F_DRAG_AND_DROP_ORDER_SQL, F_DRAG_AND_DROP_INTERVAL
+     * @param bool|false $phpUnit
+     *
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     */
+    public function __construct(array $formSpec = array(), $phpUnit = false) {
+
+        $this->formSpec = $formSpec;
+
+        $dbIndex = DB_INDEX_DEFAULT;  //TODO hier muss noch die aktuelle DB ermittelt werden (kann im Form angegeben sein) - Gerade im Formular FORM Editor genau testen!
+        $this->db = new Database($dbIndex);
+
+        $this->store = Store::getInstance('', $phpUnit);
+//        $this->evaluate = new Evaluate($this->store, $this->db);
+    }
+
+    /**
+     *
+     * @return array|int
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
+     */
+    public function process() {
+
+        $dragId = $this->store->getVar(DND_DRAG_ID, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
+        $setTo = $this->store->getVar(DND_SET_TO, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
+        $hoverId = $this->store->getVar(DND_HOVER_ID, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
+
+        $orderInterval = empty($this->formSpec[F_ORDER_INTERVAL]) ? 1 : $this->formSpec[F_ORDER_INTERVAL];
+        $orderColumn = empty($this->formSpec[F_ORDER_COLUMN]) ? F_ORDER_COLUMN_NAME : $this->formSpec[F_ORDER_COLUMN];
+
+        if (!is_array($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL])) {
+            return [];
+        }
+
+        $this->reorder($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL], $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $this->formSpec[F_TABLE_NAME]);
+
+        return [];
+    }
+
+    /**
+     * @param array $rows
+     * @param $dragId
+     * @param $setTo
+     * @param $hoverId
+     * @param $orderColumn
+     * @param $orderInterval
+     * @param $tableName
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     */
+    private function reorder(array $rows, $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $tableName) {
+        $ord = $orderInterval;
+        $ordDragOld = -1;
+
+        // Reorder. Get index for 'drag' and 'hover'
+        foreach ($rows as $key => $row) {
+
+            // the dragged element: skip old position.
+            if ($row[DND_COLUMN_ID] == $dragId) {
+                $ordDragOld = $row[DND_COLUMN_ORD];
+                continue;
+            }
+
+            // the dragged element: new position.
+            if ($row[DND_COLUMN_ID] == $hoverId) {
+
+                switch ($setTo) {
+                    case DND_SET_TO_BEFORE:
+                        $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord);
+                        $ord += $orderInterval;
+                        $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
+                        break;
+
+                    case DND_SET_TO_AFTER:
+                        $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
+                        $ord += $orderInterval;
+                        $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord);
+                        break;
+
+                    default:
+                        throw new CodeException('Unkown setTo string', $setTo, ERROR_UNKNOWN_TOKEN);
+                }
+            } else {
+                $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
+            }
+            $ord += $orderInterval;
+        }
+    }
+
+    /**
+     * @param $tableName
+     * @param $orderColumn
+     * @param $id
+     * @param $ordOld
+     * @param $ordNew
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     */
+    private function setNewOrder($tableName, $orderColumn, $id, $ordOld, $ordNew) {
+
+        if ($ordNew == $ordOld) {
+            return;
+        }
+
+        $this->db->sql("UPDATE $tableName SET $orderColumn=? WHERE id=?", ROW_REGULAR, [$ordNew, $id]);
+    }
+}
\ No newline at end of file
diff --git a/extension/qfq/qfq/form/FormAction.php b/extension/qfq/qfq/form/FormAction.php
index 43edcf6bfb3b36bf92e7cddd736b6c0784d91c0b..c816f8dc3b8eaaa446708013c4f74dfd54dcfd10 100644
--- a/extension/qfq/qfq/form/FormAction.php
+++ b/extension/qfq/qfq/form/FormAction.php
@@ -28,12 +28,15 @@ class FormAction {
      * @var Evaluate instantiated class
      */
     protected $evaluate = null;  // copy of the loaded form
+
     private $formSpec = array();
     private $primaryTableName = '';
+
     /**
      * @var Database
      */
     private $db = null;
+
     /**
      * @var Store
      */
@@ -71,6 +74,7 @@ class FormAction {
      *              ACTION_ELEMENT_DELETED:  if a record has been deleted (only in recursive calls, not the initial one)
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -245,6 +249,7 @@ class FormAction {
      * @param array $feSpecAction
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -294,10 +299,13 @@ class FormAction {
             return;
         }
 
+        if($fe[FE_EXPECT_RECORDS]===''){
+            throw new UserFormException("Missing parameter '" . FE_EXPECT_RECORDS . "'", ERROR_MISSING_EXPECT_RECORDS);
+        }
         $expect = $this->evaluate->parse($fe[FE_EXPECT_RECORDS]);
 
         if ($fe[FE_MESSAGE_FAIL] === '') {
-            throw new UserFormException("Missing error message. Column: " . FE_MESSAGE_FAIL, ERROR_MISSING_MESSAGE_FAIL);
+            throw new UserFormException("Missing parameter '" . FE_MESSAGE_FAIL . "'", ERROR_MISSING_MESSAGE_FAIL);
         }
 
         // Do the check
diff --git a/extension/qfq/qfq/helper/HelperFormElement.php b/extension/qfq/qfq/helper/HelperFormElement.php
index d10b71ba01a435bde14e0fa771439548879f0ade..97547f9fb97c20cdbde040e5c4ae916681b6f7e6 100644
--- a/extension/qfq/qfq/helper/HelperFormElement.php
+++ b/extension/qfq/qfq/helper/HelperFormElement.php
@@ -335,11 +335,9 @@ class HelperFormElement {
         // INFO: $showinline =- TRUE ('input' elemente)
         if (isset($formElement[FE_INPUT_EXTRA_BUTTON_INFO]) && $showInline) {
             $extraButton .= <<<EOF
-            <div class="input-group-btn">
-                <button class="btn btn-info" onclick="$('#$id-extra-info').slideToggle('swing')">
-                    $infoSymbolInside
-                </button>
-            </div>
+            <button class="btn btn-info" onclick="$('#$id-extra-info').slideToggle('swing')">
+                $infoSymbolInside
+            </button>
 EOF;
 
             $value = $formElement[FE_INPUT_EXTRA_BUTTON_INFO];
@@ -379,12 +377,10 @@ EOF;
             $formElement[FE_MODE] = FE_MODE_READONLY;
 
             $extraButton .= <<<EOF
-            <div class="input-group-btn">
-                <button class="btn btn-info"
-                        onclick="$('#$id').prop('readonly',!$('#$id').prop('readonly'))">
-                    <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
-                </button>
-            </div>
+            <button class="btn btn-info"
+                    onclick="$('#$id').prop('readonly',!$('#$id').prop('readonly'))">
+                <span class="glyphicon glyphicon-lock" aria-hidden="true"></span>
+            </button>
 EOF;
         }
 
@@ -394,16 +390,14 @@ EOF;
             $formElement[FE_TYPE] = 'password';
 
             $extraButton .= <<<EOF
-            <div class="input-group-btn">
-                <button class="btn btn-info"
-                        onclick="$('#$id').attr('type',$('#$id').attr('type')==='password' ? 'text': 'password')">
-                    <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
-                </button>
-            </div>
+            <button class="btn btn-info"
+                    onclick="$('#$id').attr('type',$('#$id').attr('type')==='password' ? 'text': 'password')">
+                <span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
+            </button>
 EOF;
         }
 
-        $formElement[FE_TMP_EXTRA_BUTTON_HTML] = $extraButton;
+        $formElement[FE_TMP_EXTRA_BUTTON_HTML] = Support::wrapTag('<div class="input-group-btn">', $extraButton, true);
         Support::setIfNotSet($formElement, FE_INPUT_EXTRA_BUTTON_INFO);
 
         return $formElement;
diff --git a/extension/qfq/qfq/helper/Support.php b/extension/qfq/qfq/helper/Support.php
index d122ab7c22b34f08c6c8f3a5ee0a50a2530541cd..2a46ae9174a2dbe28ce50d908e775e4d59d4c634 100644
--- a/extension/qfq/qfq/helper/Support.php
+++ b/extension/qfq/qfq/helper/Support.php
@@ -27,8 +27,6 @@ class Support {
      * @throws UserFormException
      */
     public static function appendTypo3ParameterToArray(array &$queryArray, $mode = PARAM_T3_ALL) {
-//        if (isset($_GET['id']))
-//            $queryArray['id'] = self::getCurrentPage();
 
         $store = Store::getInstance();
 
@@ -612,8 +610,7 @@ class Support {
      *
      * @return mixed
      */
-    public
-    static function encryptDoubleCurlyBraces($text) {
+    public static function encryptDoubleCurlyBraces($text) {
         $text = str_replace('{{', LONG_CURLY_OPEN, $text);
         $text = str_replace('}}', LONG_CURLY_CLOSE, $text);
 
@@ -764,7 +761,7 @@ class Support {
         }
 
         // set typeAheadPedantic
-        if (isset($formElement[FE_TYPEAHEAD_PEDANTIC]) && $formElement[FE_TYPEAHEAD_PEDANTIC] === '')  {
+        if (isset($formElement[FE_TYPEAHEAD_PEDANTIC]) && $formElement[FE_TYPEAHEAD_PEDANTIC] === '') {
             $formElement[FE_TYPEAHEAD_PEDANTIC] = '1'; // support legacy option of 'typeAheadPedantic' without a value
         }
         if (isset($formElement[FE_TYPEAHEAD_LDAP]) || isset($formElement[FE_TYPEAHEAD_SQL])) {
@@ -867,7 +864,7 @@ class Support {
             case 'mediumint':
             case 'int':
             case 'bigint':
-                $inputType = 'number';
+                $inputType = HTML_INPUT_TYPE_NUMBER;
                 $arr = $control[$token];
                 if ($sign == 'signed') {
                     $min = $arr[0];
@@ -887,7 +884,7 @@ class Support {
                 break;
 
             case 'bit':
-                $inputType = 'number';
+                $inputType = HTML_INPUT_TYPE_NUMBER;
                 $checkType = SANITIZE_ALLOW_DIGIT;
                 break;
 
@@ -897,8 +894,9 @@ class Support {
         }
 
         // Numbers don't need a maxLength because they are being handled by min/max and/or decimalFormat
-        if ($isANumber)
+        if ($isANumber) {
             $formElement[FE_MAX_LENGTH] = '';
+        }
 
         if (!empty($formElement[FE_TYPEAHEAD_SQL]) || !empty($formElement[FE_TYPEAHEAD_LDAP])) {
             $inputType = '';
@@ -910,9 +908,20 @@ class Support {
         if ($formElement[FE_CHECK_TYPE] === SANITIZE_ALLOW_AUTO) {
             $formElement[FE_CHECK_TYPE] = $checkType;
         }
+
         if (empty($formElement[FE_MIN])) $formElement[FE_MIN] = $min;
         if (empty($formElement[FE_MAX])) $formElement[FE_MAX] = $max;
         if (empty($formElement[FE_INPUT_TYPE])) $formElement[FE_INPUT_TYPE] = $inputType;
+
+        // If a  $formElement[FE_STEP] is given, the optional boundaries (FE_MIN / FE_MAX) have to be aligned to a multiple of $formElement[FE_STEP].
+        if (!empty($formElement[FE_STEP])) {
+            if (!empty($formElement[FE_MIN])) {
+                $formElement[FE_MIN] = ceil($formElement[FE_MIN] / $formElement[FE_STEP]) * $formElement[FE_STEP];
+            }
+            if (!empty($formElement[FE_MAX])) {
+                $formElement[FE_MAX] = floor($formElement[FE_MAX] / $formElement[FE_STEP]) * $formElement[FE_STEP];
+            }
+        }
     }
 
     /**
@@ -923,7 +932,7 @@ class Support {
      * @param $typeSpec
      * @throws UserFormException
      */
-    private function adjustDecimalFormat(array &$formElement, $typeSpec) {
+    private static function adjustDecimalFormat(array &$formElement, $typeSpec) {
         if (isset($formElement[FE_DECIMAL_FORMAT])) {
             if ($formElement[FE_DECIMAL_FORMAT] === '') {
                 // Get decimal format from column definition
@@ -954,7 +963,7 @@ class Support {
      * @param array $formElement
      * @param $typeSpec
      */
-    private function adjustMaxLength(array &$formElement, $typeSpec) {
+    private static function adjustMaxLength(array &$formElement, $typeSpec) {
 
         // MIN( $formElement['maxLength'], table definition)
         $maxLength = self::getColumnSize($typeSpec);
@@ -1001,7 +1010,7 @@ class Support {
      * @return bool|int a) 'false' if there is no length definition, b) length definition, c)
      *                   date|time|datetime|timestamp use hardcoded length
      */
-    private function getColumnSize($typeSpec) {
+    private static function getColumnSize($typeSpec) {
 
         $matches = array();
 
@@ -1036,7 +1045,7 @@ class Support {
      *
      * @return int
      */
-    private function maxLengthSetEnum($typeSpec) {
+    private static function maxLengthSetEnum($typeSpec) {
         $startPos = (substr($typeSpec, 0, 4) === 'set(') ? 4 : 5;
         $max = 0;
 
@@ -1065,7 +1074,7 @@ class Support {
      * @return array|string
      * @throws CodeException
      */
-    private function applyFormModeToFormElement($feMode, $formMode) {
+    private static function applyFormModeToFormElement($feMode, $formMode) {
 
         if ($formMode == '') {
             return $feMode; //no change
diff --git a/extension/qfq/qfq/report/Download.php b/extension/qfq/qfq/report/Download.php
index 83295de42ecd62dc321a78b1851db422eb477445..cb475e614f53bc2732e662df22bebea58062fee8 100644
--- a/extension/qfq/qfq/report/Download.php
+++ b/extension/qfq/qfq/report/Download.php
@@ -95,6 +95,16 @@ class Download {
      */
     private function concatPdfFiles(array $files) {
 
+        // Remove empty entries. Might happen if there was no upload
+        $files = OnArray::removeEmptyElementsFromArray($files);
+
+        // Check that all files exist and readable
+        foreach ($files AS $filename) {
+            if(!is_readable($filename)){
+                throw new downloadException("Error reading file $filename. Not found or no permission", ERROR_DOWNLOAD_FILE_NOT_READABLE);
+            }
+        }
+
         switch (count($files)) {
             case 0:
                 return '';
diff --git a/extension/qfq/qfq/report/Html2Pdf.php b/extension/qfq/qfq/report/Html2Pdf.php
index 90718c31793f5a5277d9e24a201bed498887964b..7fada38eff52b9fdc0b19c77627f1df9808867ab 100644
--- a/extension/qfq/qfq/report/Html2Pdf.php
+++ b/extension/qfq/qfq/report/Html2Pdf.php
@@ -64,8 +64,7 @@ class Html2Pdf {
     public function __construct(array $config = array(), $phpUnit = false) {
 
         if (count($config) == 0) {
-            $cfg = new Config();
-            $config = $cfg->readConfig('');
+            $config = Config::readConfig('');
         }
 
         $this->config = $config;
diff --git a/extension/qfq/qfq/report/Link.php b/extension/qfq/qfq/report/Link.php
index 923445bd9c01f0a97334980aa4d1f71216df0de8..4eea7243530e543c26eec3937783366ea0f739f5 100644
--- a/extension/qfq/qfq/report/Link.php
+++ b/extension/qfq/qfq/report/Link.php
@@ -262,6 +262,7 @@ class Link {
          * 4: <a href=url>Text</a>
          * 5: text
          * 6: url
+         * 8: SIP only - 's=badcaffee1234'
          *
          *  r=render mode, u=url, t:text and/or image.
          *
@@ -308,10 +309,15 @@ class Link {
         $this->renderControl[7][1][0] = 6;
         $this->renderControl[7][1][1] = 6;
 
+        $this->renderControl[8][0][0] = 0;
+        $this->renderControl[8][0][1] = 0;
+        $this->renderControl[8][1][0] = 8;
+        $this->renderControl[8][1][1] = 8;
+
     }
 
     /**
-     * In render mode 3,4,5 there is no '<a href ...>'. Nevertheless, tooltip and BS Button should be displaye.
+     * In render mode 3,4,5 there is no '<a href ...>'. Nevertheless, tooltip and BS Button should be displayed.
      * Do this by applying a '<span>' attribute around the text.
      *
      * @param array $vars
@@ -421,10 +427,10 @@ class Link {
             case '22':
             case '23':
             case '24':
-            //TODO: Alter Code, umstellen auf JS Client von RO. Vorlage koennte 'Delete' in Subrecord sein.
-            $link = "<a href=\"javascript: void(0);\" onClick=\"var del = new FR.Delete({recordId:'',sip:'',forward:'" .
-                $vars[NAME_PAGE] . "'});\" " . $vars[NAME_LINK_CLASS] . ">" . $vars[NAME_TEXT] . "</a>";
-            break;
+                //TODO: Alter Code, umstellen auf JS Client von RO. Vorlage koennte 'Delete' in Subrecord sein.
+                $link = "<a href=\"javascript: void(0);\" onClick=\"var del = new FR.Delete({recordId:'',sip:'',forward:'" .
+                    $vars[NAME_PAGE] . "'});\" " . $vars[NAME_LINK_CLASS] . ">" . $vars[NAME_TEXT] . "</a>";
+                break;
 
             // 5: plain text, no <span> around
             case '5':
@@ -442,7 +448,9 @@ class Link {
             case '26':
                 throw new UserReportException ("Mode not implemented. internal render mode=$mode", ERROR_UNKNOWN_MODE);
                 break;
-
+            case '8':
+                $link = substr($vars[FINAL_HREF],12); // strip 'index.php?s='
+                break;
 
             default:
                 throw new UserReportException ("Mode not implemented. internal render mode=$mode", ERROR_UNKNOWN_MODE);
@@ -1322,7 +1330,7 @@ EOF;
 //        if ($vars[NAME_BOOTSTRAP_BUTTON] == '0') {
 //            $vars[NAME_EXTRA_CONTENT_WRAP] = '<button type="button" ' . $attributes . $onClick . '>';
 //        } else {
-            $vars[NAME_EXTRA_CONTENT_WRAP] = '<span ' . $attributes . $onClick . '>';
+        $vars[NAME_EXTRA_CONTENT_WRAP] = '<span ' . $attributes . $onClick . '>';
         $vars[NAME_BOOTSTRAP_BUTTON] = '0';
 
 //        }
diff --git a/extension/qfq/qfq/store/Config.php b/extension/qfq/qfq/store/Config.php
index 39e1004b36f8ff9e641975670bc1fe1ed88abc6e..ac41d1fd09fb954ee5d149521660104463ab785a 100644
--- a/extension/qfq/qfq/store/Config.php
+++ b/extension/qfq/qfq/store/Config.php
@@ -19,14 +19,70 @@ require_once(__DIR__ . '/../helper/Support.php');
  */
 class Config {
 
+    /**
+     * Migrate config.qfq.ini to config.qfq.php
+     * @param $configIni
+     * @param $configPhp
+     */
+    private static function migrateConfigIniToPhp($configIni, $configPhp) {
+
+        $config = parse_ini_file($configIni, false);
+
+        $pre = isset($config[SYSTEM_DB_NAME]) ? 'DB' : 'DB_1';
+
+        $content = '<?php' . PHP_EOL . 'return [' . PHP_EOL;
+
+        foreach ([$pre . '_NAME', $pre . '_PASSWORD', $pre . '_SERVER', $pre . '_USER', SYSTEM_LDAP_1_RDN, SYSTEM_LDAP_1_PASSWORD] as $key) {
+            $content .= "  '$key' => '" . $config[$key] . "'," . PHP_EOL;
+        }
+
+        $content .= "];" . PHP_EOL;
+
+        // Write new config file
+        file_put_contents($configPhp, $content);
+
+        // Make old file unreadable
+        chmod($configIni, 000);
+    }
+
+    /**
+     * Iterates over all 30 custom vars, explode them to split between key and value, append to $config.
+     *
+     * @param array $config
+     * @return array
+     * @throws UserReportException
+     */
+    private static function getCustomVariable(array $config) {
+
+        for ($i = 1; $i <= 30; $i++) {
+            if (isset($config['custom' . $i])) {
+                $arr = explode('=', $config['custom' . $i], 2);
+                if (!empty($arr[0]) && !empty($arr[1])) {
+
+                    $arr[0] = trim($arr[0]);
+                    $arr[1] = OnString::trimQuote(trim($arr[1]));
+
+                    if (isset($config[$arr[0]])) {
+                        throw new UserReportException("Variable '$arr[0]' already defined", ERROR_INVALID_OR_MISSING_PARAMETER);
+                    }
+
+                    $config[$arr[0]] = $arr[1];
+                }
+            }
+        }
+
+        return $config;
+    }
+
     /**
      * Read config.qfq.ini.
      *
      * @param string $configIni
      * @return array
      * @throws UserFormException
+     * @throws UserReportException
      */
-    public function readConfig($configIni = '') {
+    public static function readConfig($configIni = '') {
         $configT3qfq = array();
 
         // Production Path to CONFIG_INI
@@ -46,24 +102,33 @@ class Config {
                 $configT3qfq = unserialize($all['EXT']['extConf'][EXT_KEY]);
                 unset($all);
             }
-            $configIni = $pathTypo3Conf . '/' . CONFIG_QFQ;
+            $configIni = $pathTypo3Conf . '/' . CONFIG_QFQ_INI;
+            $configPhp = $pathTypo3Conf . '/' . CONFIG_QFQ_PHP;
         }
 
-        try {
-            $config = parse_ini_file($configIni, false);
-            // in case $configIni doesn't exist: just skip
-            if ($config === false) {
-                $config = array();
-            }
-        } catch (\Exception $e) {
-            throw new qfq\UserFormException ("Error read file " . $pathTypo3Conf . ": " . $e->getMessage(), ERROR_IO_READ_FILE);
+        // Migrate legacy config file.
+        if (is_readable($configIni) && !is_readable($configPhp)) {
+            self::migrateConfigIniToPhp($configIni, $configPhp);
+        }
+
+        $config = include($configPhp);
+
+        if ($config === false) {
+            throw new qfq\UserFormException ("Error read file: " . $configPhp, ERROR_IO_READ_FILE);
+        }
+        // in case $configIni doesn't exist: just skip
+        if (!is_array($config)) {
+            $config = array();
         }
+
+        $configT3qfq = self::getCustomVariable($configT3qfq);
         // Settings in  config.qfq.ini overwrite T3 settings
         $config = array_merge($configT3qfq, $config);
 
         $config = self::renameConfigElements($config);
         $config = self::setDefaults($config);
         self::checkDeprecated($config);
+
         self::checkForAttack($config);
 
         return $config;
@@ -84,7 +149,7 @@ class Config {
                     case SYSTEM_VAR_ADD_BY_SQL:
                         $msg = 'Replaced by: ' . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . '1|2|3';
                 }
-                throw new qfq\UserFormException ("Deprecated option in " . CONFIG_QFQ . ": " . SYSTEM_VAR_ADD_BY_SQL . " - " . $msg);
+                throw new qfq\UserFormException ("Deprecated option in " . CONFIG_QFQ_PHP . ": " . SYSTEM_VAR_ADD_BY_SQL . " - " . $msg);
             }
         }
     }
@@ -93,6 +158,7 @@ class Config {
     /**
      * @param array $config
      * @throws UserFormException
+     * @throws UserReportException
      */
     private static function checkForAttack(array $config) {
         $attack = false;
@@ -143,6 +209,7 @@ class Config {
      * @param array $config
      * @param string $getParamName
      * @throws UserFormException
+     * @throws UserReportException
      */
     public static function attackDetectedExitNow(array $config = array(), $getParamName = '') {
 
@@ -248,8 +315,8 @@ class Config {
         ];
 
         // To let run legacy code
-        $config[SYSTEM_DB_INDEX_DATA_DEPRECATED] = $config[SYSTEM_DB_INDEX_DATA];
-        $config[SYSTEM_DB_INDEX_QFQ_DEPRECATED] = $config[SYSTEM_DB_INDEX_QFQ];
+//        $config[SYSTEM_DB_INDEX_DATA_DEPRECATED] = $config[SYSTEM_DB_INDEX_DATA];
+//        $config[SYSTEM_DB_INDEX_QFQ_DEPRECATED] = $config[SYSTEM_DB_INDEX_QFQ];
 
         return array_merge($default, $config);
     }
diff --git a/extension/qfq/qfq/store/FillStoreForm.php b/extension/qfq/qfq/store/FillStoreForm.php
index 2ef50b3d85cff9ff42388d0e4aa0d950bb5ca116..6c8cdc6a572e156ad8200e18019704ce538cba12 100644
--- a/extension/qfq/qfq/store/FillStoreForm.php
+++ b/extension/qfq/qfq/store/FillStoreForm.php
@@ -45,7 +45,10 @@ class FillStoreForm {
     private $evaluate = null;
 
     /**
-     *
+     * FillStoreForm constructor.
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function __construct() {
 
@@ -81,7 +84,7 @@ class FillStoreForm {
         // Preparation for Log, Debug
         $this->store->setVar(SYSTEM_FORM, $formName, STORE_SYSTEM);
 
-        $feSpecNative = $this->dbArray[$this->dbIndexQfq]->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_EXPECT_GE_1, [$formName],
+        $feSpecNative = $this->dbArray[$this->dbIndexQfq]->sql(SQL_FORM_ELEMENT_SIMPLE_ALL_CONTAINER, ROW_REGULAR, [$formName],
             'Form or FormElements not found: ' . ERROR_FORM_NOT_FOUND);
         HelperFormElement::explodeParameterInArrayElements($feSpecNative, FE_PARAMETER);
 
@@ -90,7 +93,6 @@ class FillStoreForm {
 
         $feSpecNative = $this->expandTemplateGroupFormElement($feSpecTemplateGroup, $feSpecNative);
 
-
         return $feSpecNative;
     }
 
@@ -148,7 +150,9 @@ class FillStoreForm {
      * @param string $formMode
      *
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function process($formMode = FORM_SAVE) {
 
@@ -238,11 +242,12 @@ class FillStoreForm {
                     break;
             }
 
-            if ($formElement[FE_MODE] === FE_MODE_REQUIRED) {
-                if (!isset($clientValues[$clientFieldName]) || ($clientValues[$clientFieldName] === '')) {
-                    throw new UserFormException("Missing required value.", ERROR_REQUIRED_VALUE_EMPTY);
-                }
-            }
+            // Bug #5077 / 'Required' FormElement with Dynamic Update - required FE will be checked later - at this point there is no F, R store.
+//            if ($formElement[FE_MODE] === FE_MODE_REQUIRED) {
+//                if (!isset($clientValues[$clientFieldName]) || ($clientValues[$clientFieldName] === '')) {
+//                    throw new UserFormException("Missing required value.", ERROR_REQUIRED_VALUE_EMPTY);
+//                }
+//            }
 
             // copy value to $newValues
             if (isset($clientValues[$clientFieldName])) {
@@ -256,6 +261,7 @@ class FillStoreForm {
                             if ($clientValues[$clientFieldName] !== '') // do not check empty values
                                 $val = $this->doDateTime($formElement, $val);
                             break;
+
                         default:
                             if ($formElement[FE_TYPE] == FE_TYPE_EDITOR) {
                                 // Tiny MCE always wrap a '<p>' around the content. Remove it before saving.
@@ -263,7 +269,7 @@ class FillStoreForm {
                             }
 
                             // Check only if there is something.
-                            if ($val !== '') {
+                            if ($val !== '' && $formMode!=FORM_UPDATE) {
                                 $val = Sanitize::sanitize($val, $formElement[FE_CHECK_TYPE], $formElement[FE_CHECK_PATTERN],
                                     $formElement[FE_DECIMAL_FORMAT], SANITIZE_EXCEPTION);
                                 if ($formElement[FE_ENCODE] === FE_ENCODE_SPECIALCHAR) {
@@ -274,8 +280,9 @@ class FillStoreForm {
                             break;
                     }
 
-                    if ($val !== '')
+                    if ($val !== '') {
                         $val = Sanitize::checkMinMax($val, $formElement[FE_MIN], $formElement[FE_MAX], SANITIZE_EXCEPTION);
+                    }
 
                     $newValues[$formElement[FE_NAME]] = $val;
                 }
diff --git a/extension/qfq/qfq/store/Store.php b/extension/qfq/qfq/store/Store.php
index 8a222bf9096cf342552860e18cf3178997b1c8ca..90c6dfd72ea36501a3f5e85d08035388895352bc 100644
--- a/extension/qfq/qfq/store/Store.php
+++ b/extension/qfq/qfq/store/Store.php
@@ -82,8 +82,9 @@ class Store {
      * @param string $bodytext
      * @param string $fileConfigIni
      *
+     * @throws CodeException
      * @throws UserFormException
-     * @throws \qfq\CodeException
+     * @throws UserReportException
      */
     private function __construct($bodytext = '', $fileConfigIni = '') {
 
@@ -181,11 +182,11 @@ class Store {
      * @param string $fileConfigIni
      * @throws CodeException
      * @throws UserFormException
+     * @throws UserReportException
      */
     private static function fillStoreSystem($fileConfigIni = '') {
 
-        $cfg = new Config();
-        $config = $cfg->readConfig($fileConfigIni);
+        $config = Config::readConfig($fileConfigIni);
 
         $config = self::doSystemPath($config);
         $config = self::adjustConfig($config);
@@ -307,7 +308,7 @@ class Store {
 
         foreach ($names as $name) {
             if (!isset($config[$name])) {
-                throw new qfq\UserFormException ("Missing configuration in `" . CONFIG_QFQ . "`: $name", ERROR_MISSING_CONFIG_INI_VALUE);
+                throw new qfq\UserFormException ("Missing configuration in `" . CONFIG_QFQ_PHP . "`: $name", ERROR_MISSING_CONFIG_INI_VALUE);
             }
         }
     }
@@ -418,6 +419,19 @@ class Store {
         }
     }
 
+    /**
+     * Unset a variable in store.
+     *
+     * @param $key
+     * @param $store
+     */
+    public static function unsetVar($key, $store){
+
+        if(isset(self::$raw[$store][$key])) {
+            unset(self::$raw[$store][$key]);
+        }
+    }
+
     /**
      * Cycles through all stores in $useStore.
      * First match will return the found value.
@@ -517,10 +531,8 @@ class Store {
         } else {
             self::setStore($_SESSION[SESSION_NAME][STORE_EXTRA], STORE_EXTRA, true);
         }
-
     }
 
-
     /**
      * Returns a pointer to this Class.
      *
@@ -529,8 +541,9 @@ class Store {
      * @param string $fileConfigIni
      *
      * @return null|Store
+     * @throws CodeException
      * @throws UserFormException
-     * @throws \qfq\CodeException
+     * @throws UserReportException
      */
     public static function getInstance($bodytext = '', $phpUnit = false, $fileConfigIni = '') {
 
@@ -583,12 +596,14 @@ class Store {
      * @throws \qfq\CodeException
      */
     public static function unsetStore($store) {
-        // Check valid Storename
-        if (!isset(self::$sanitizeStore))
+        // Check valid store name
+        if (!isset(self::$sanitizeStore)) {
             throw new UserFormException("Unknown Store: $store", ERROR_UNNOWN_STORE);
+        }
 
-        if ($store === STORE_ZERO)
+        if ($store === STORE_ZERO) {
             throw new CodeException("unsetStore() for STORE_ZERO is impossible - there are no values.", ERROR_SET_STORE_ZERO);
+        }
 
         if (isset(self::$raw[$store])) {
             self::$raw[$store] = array();
@@ -837,6 +852,10 @@ class Store {
      * Read SYSTEM_FILL_STORE_SYSTEM_BY_SQL_1|2|3 from SYSTEM_STORE and if set:
      * a) fire the SQL
      * b) merge all columns to STORE_SYSTEM
+     *
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public static function StoreSystemUpdate() {
 
@@ -853,7 +872,7 @@ class Store {
                 $db = new qfq\Database();
             }
 
-            $errMsg = "More than 1 record found. " . CONFIG_QFQ . ": " . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . "$ii";
+            $errMsg = "More than 1 record found. " . CONFIG_QFQ_PHP . ": " . SYSTEM_FILL_STORE_SYSTEM_BY_SQL . "$ii";
             $mode = ROW_EXPECT_0_1;
 
             // If there is an error message defined, this means there should be exactly one record.
@@ -881,6 +900,7 @@ class Store {
      * @param $storeName
      * @throws CodeException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public static function appendToStore($dataArray, $storeName) {
 
@@ -903,7 +923,3 @@ class Store {
     }
 
 }
-
-
-
-
diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql
index 10cf2d60672278c55bd5160762bed6ffe1f825c2..0e4bdb22fae1c7d9371e6def67027850cae87d1d 100644
--- a/extension/qfq/sql/formEditor.sql
+++ b/extension/qfq/sql/formEditor.sql
@@ -162,7 +162,7 @@ WHERE FIND_IN_SET(Form.name, 'form,formElement,copyForm,cron') > 0;
 INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) VALUES
   (1, 'form', 'Form Editor: {{SELECT id, " / ", name FROM Form WHERE id = {{r:S0}}}} (DB: {{_dbNameQfq:Y}})',
    'FormElement Editor',
-   'Form', 'sip', 'sip', 'bootstrap', '', 'maxVisiblePill=5\nclass=container-fluid\ndbIndex={{dbIndexQfq:Y}}');
+   'Form', 'sip', 'sip', 'bootstrap', '', 'maxVisiblePill=5\nclass=container-fluid\ndbIndex={{indexQfq:Y}}');
 
 # FormEditor: FormElements for 'form'
 INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value,
@@ -185,16 +185,16 @@ VALUES
    1, '', '', '', 'specialchar', 'no', '[a-zA-Z0-9._+-]+'),
   (1, 'title', 'Title', 'show', 'text', 'all', 'native', 130, 0, 0, '<a href="{{documentation:Y}}#form-title">Info</a>', '', '', '', '', 1, '', '', '', 'none', 'no', ''),
   (1, 'noteInternal', 'Note', 'show', 'text', 'all', 'native', 140, '40,3', 0, '<a href="{{documentation:Y}}#form-note">Info</a>', '', '', '', '', 1, '', '', '', 'specialchar', 'no', ''),
-  (1, 'tableName', 'Table', 'required', 'select', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#form-tablename">Info</a>', '', '', '{{[{{dbIndexData:Y}}]!SHOW tables}}',
+  (1, 'tableName', 'Table', 'required', 'select', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#form-tablename">Info</a>', '', '', '{{[{{indexData:Y}}]!SHOW tables}}',
    'emptyItemAtStart', 1, '', '', '', 'specialchar', 'no', ''),
-  (1, 'parameterLanguageA', 'Language: {{FORM_LANGUAGE_A_LABEL:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{FORM_LANGUAGE_A_ID:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
-  (1, 'parameterLanguageB', 'Language: {{FORM_LANGUAGE_B_LABEL:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{FORM_LANGUAGE_B_ID:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
-  (1, 'parameterLanguageC', 'Language: {{FORM_LANGUAGE_C_LABEL:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{FORM_LANGUAGE_C_ID:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
-  (1, 'parameterLanguageD', 'Language: {{FORM_LANGUAGE_D_LABEL:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{FORM_LANGUAGE_D_ID:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
+  (1, 'parameterLanguageA', 'Language: {{formLanguageALabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageAId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
+  (1, 'parameterLanguageB', 'Language: {{formLanguageBLabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageBId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
+  (1, 'parameterLanguageC', 'Language: {{formLanguageCLabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageCId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
+  (1, 'parameterLanguageD', 'Language: {{formLanguageDLabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageDId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
   (1, 'requiredParameterNew', 'Required Parameter NEW', 'show', 'text', 'all', 'native', 200, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
   (1, 'requiredParameterEdit', 'Required Parameter EDIT', 'show', 'text', 'all', 'native', 200, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
   (1, 'permitNew', 'Permit New', 'show', 'radio', 'all', 'native', 210, 0, 10, '<a href="{{documentation:Y}}#form-permitnewedit">Info</a>', '', '', '', 'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
@@ -204,7 +204,7 @@ VALUES
   (1, 'dirtyMode', 'Record Locking', 'show', 'radio', 'all', 'native', 240, 0, 10, '<a href="{{documentation:Y}}#locking-record">Info</a>', '', '', '',
    'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
   (1, 'recordLockTimeoutSeconds', 'Lock timeout (seconds)', 'show', 'text', 'all', 'native', 245, 0, 0, '<a href="{{documentation:Y}}#locking-record">Info</a>', '',
-   '{{SELECT IF("{{recordLockTimeoutSeconds:R0}}"=0,"{{RECORD_LOCK_TIMEOUT_SECONDS:Y0}}","{{recordLockTimeoutSeconds:R0}}")}}', '', '', 2, '', '', '', 'specialchar', 'no', ''),
+   '{{SELECT IF("{{recordLockTimeoutSeconds:R0}}"=0,"{{recordLockTimeoutSeconds:Y0}}","{{recordLockTimeoutSeconds:R0}}")}}', '', '', 2, '', '', '', 'specialchar', 'no', ''),
   (1, 'showButton', 'Show button', 'show', 'checkbox', 'all', 'native', 250, 0, 5, '<a href="{{documentation:Y}}#showbutton">Info</a>', '', '', '', 'checkBoxMode = multi\norientation=vertical', 2, '', '', '', 'specialchar', 'no', ''),
   (1, 'forwardMode', 'Forward', 'show', 'radio', 'all', 'native', 300, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', 'buttonClass=btn-default', 3, '', '', '', 'specialchar', 'no', ''),
   (1, 'forwardPage', 'Forward URL / Page', 'show', 'text', 'all', 'native', 310, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', '', 3, '',
@@ -241,7 +241,7 @@ VALUES
    'Form Element Editor. Form : {{SELECT f.id, " / ",  f.name  FROM Form AS f WHERE f.id = {{formId:S0}}  }} (DB: {{_dbNameQfq:Y}})',
    'Please secure the form',
    'FormElement', 'sip', 'sip', 'bootstrap', '',
-   'maxVisiblePill=5\nclassBody=qfq-color-blue-1\ndbIndex={{dbIndexQfq:Y}}', 'formId');
+   'maxVisiblePill=5\nclassBody=qfq-color-blue-1\ndbIndex={{indexQfq:Y}}', 'formId');
 
 # FormEditor: FormElements for 'formElement'
 INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value,
@@ -270,7 +270,7 @@ VALUES
   (2, 'dynamicUpdate', 'Dynamic Update', 'show', 'checkbox', 'all', 'native', 135, 0, 0, '<a href="{{documentation:Y}}#dynamic-update">Info</a>',
    '', '', '', '', 100, '', 'no', '', '', '', '', '', 'specialchar'),
   (2, 'name', 'Name', 'show', 'text', 'all', 'native', 140, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', '', '', '',
-   'typeAheadSql = [{{dbIndexData:Y}}]SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = "{{DB_1_NAME:Y}}" AND table_name = "{{SELECT f.tableName FROM Form AS f WHERE f.id={{formId:S0}}}}" AND COLUMN_NAME LIKE ? ORDER BY COLUMN_NAME\ntypeAheadMinLength = 1\ntypeAheadLimit = 100\ntypeAheadPedantic = 0\n',
+   'typeAheadSql = [{{indexData:Y}}]SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = "{{DB_1_NAME:Y}}" AND table_name = "{{SELECT f.tableName FROM Form AS f WHERE f.id={{formId:S0}}}}" AND COLUMN_NAME LIKE ? ORDER BY COLUMN_NAME\ntypeAheadMinLength = 1\ntypeAheadLimit = 100\ntypeAheadPedantic = 0\n',
    100, '<a href="{{documentation:Y}}#class-native">Info</a>', 'no', '', '', '', '', '', 'specialchar'),
   (2, 'label', 'Label', 'show', 'text', 'all', 'native', 150, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '', '', 'none'),
   (2, 'mode', 'Mode', 'show', 'radio', 'all', 'native', 160, 0, 0, '<a href="{{documentation:Y}}#class-native">Info</a>', '', '', '', 'buttonClass=btn-default', 100, '', 'no', '', '', '', '', '', 'specialchar'),
@@ -284,14 +284,14 @@ VALUES
    100, '', 'yes', '', '', '', '', '', 'specialchar'),
   (2, 'subrecordOption', 'Subrecord Option', 'show', 'checkbox', 'all', 'native', 200, 0, 0, '<a href="{{documentation:Y}}#subrecord-option">Info</a>', '', '', '',
    '', 100, '', 'yes', '', '', '', '{{ SELECT IF("{{type:FRE:alnumx}}"="subrecord" AND "{{class:FRE:alnumx}}"="native", "show", "hidden") }}', '', 'specialchar'),
-  (2, 'parameterLanguageA', 'Language: {{FORM_LANGUAGE_A_LABEL:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{FORM_LANGUAGE_A_ID:YE}}"="","hidden","show" ) }}', '', 'none'),
-  (2, 'parameterLanguageB', 'Language: {{FORM_LANGUAGE_B_LABEL:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{FORM_LANGUAGE_B_ID:YE}}"="","hidden","show" ) }}', '', 'none'),
-  (2, 'parameterLanguageC', 'Language: {{FORM_LANGUAGE_C_LABEL:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{FORM_LANGUAGE_C_ID:YE}}"="","hidden","show" ) }}', '', 'none'),
-  (2, 'parameterLanguageD', 'Language: {{FORM_LANGUAGE_D_LABEL:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
-   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{FORM_LANGUAGE_D_ID:YE}}"="","hidden","show" ) }}', '', 'none'),
+  (2, 'parameterLanguageA', 'Language: {{formLanguageALabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{formLanguageAId:YE}}"="","hidden","show" ) }}', '', 'none'),
+  (2, 'parameterLanguageB', 'Language: {{formLanguageBLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{formLanguageBId:YE}}"="","hidden","show" ) }}', '', 'none'),
+  (2, 'parameterLanguageC', 'Language: {{formLanguageCLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{formLanguageCId:YE}}"="","hidden","show" ) }}', '', 'none'),
+  (2, 'parameterLanguageD', 'Language: {{formLanguageDLabel:YE}}', 'show', 'text', 'all', 'native', 210, '60,2', 0,
+   '<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 100, '', 'no', '', '', '', '{{SELECT IF("{{formLanguageDId:YE}}"="","hidden","show" ) }}', '', 'none'),
   (2, 'encode', 'Encode', 'show', 'radio', 'all', 'native', 300, 0, 0, '<a href="{{documentation:Y}}#field-encode">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'no', '', '', '', '', '', 'specialchar'),
   (2, 'checkType', 'Check Type', 'show', 'radio', 'all', 'native', 310, 0, 0, '<a href="{{documentation:Y}}#field-checktype">Info</a>', '', '', '', 'buttonClass=btn-default', 101, '', 'yes', '', '', '', '', '', 'specialchar'),
   (2, 'checkPattern', 'Check Pattern', 'show', 'text', 'all', 'native', 320, 0, 0, '<a href="{{documentation:Y}}#field-checkpattern">Info</a>, <a href="https://regex101.com/">Regex101</a>', '', '', '', '', 101, '', 'yes', '', '', '',
@@ -424,7 +424,7 @@ CREATE TABLE IF NOT EXISTS `Cron` (
 # Form: AutoCron
 INSERT INTO Form (id, name, title, tableName, parameter, dirtyMode)
 VALUES
-  (4, 'cron', 'cron {{SELECT IF("{{r}}" = "0", "(new)", "(Id: {{r}})") }}', 'Cron', 'dbIndex={{dbIndexQfq:Y}}',
+  (4, 'cron', 'cron {{SELECT IF("{{r}}" = "0", "(new)", "(Id: {{r}})") }}', 'Cron', 'dbIndex={{indexQfq:Y}}',
    'none');
 
 # FormElements: AutoCron
diff --git a/extension/qfq/tests/phpunit/AbstractDatabaseTest.php b/extension/qfq/tests/phpunit/AbstractDatabaseTest.php
index ff4979ca9685fc8f7f8a926e87ea311366daf0b9..2a240391a7cbd120ce96206f418547670995fffc 100644
--- a/extension/qfq/tests/phpunit/AbstractDatabaseTest.php
+++ b/extension/qfq/tests/phpunit/AbstractDatabaseTest.php
@@ -82,7 +82,7 @@ abstract class AbstractDatabaseTest extends TestCase {
 //        $this->store->setVar('DB_1_NAME', $dbNamePhpUnit, STORE_SYSTEM);
         $dbName = $this->store->getVar('DB_NAME_TEST', STORE_SYSTEM);
         if ($dbName == '') {
-            throw new \qfq\CodeException('Missing DB_NAME_TEST in ' . CONFIG_QFQ, ERROR_MISSING_REQUIRED_PARAMETER);
+            throw new \qfq\CodeException('Missing DB_NAME_TEST in ' . CONFIG_QFQ_PHP, ERROR_MISSING_REQUIRED_PARAMETER);
         } else {
             $this->store->setVar('DB_1_NAME', $dbName, STORE_SYSTEM);
         }
diff --git a/javascript/src/Alert.js b/javascript/src/Alert.js
index a5f177b24096e9625c37e84b83f059019bfd29cb..1bf253ad9b96042121a579589c3a1692d109b0b0 100644
--- a/javascript/src/Alert.js
+++ b/javascript/src/Alert.js
@@ -230,7 +230,9 @@ var QfqNS = QfqNS || {};
 
         $alertContainer = this.makeAlertContainerSingleton();
         if (this.modal) {
-            this.$modalDiv = $("<div>");
+            this.$modalDiv = $("<div>", {
+                class: "removeMe"
+            });
             this.$modalDiv.css('z-index', 1000);
             $alertContainer.css('position', 'fixed');
             $alertContainer.css('left', 0);
@@ -333,9 +335,8 @@ var QfqNS = QfqNS || {};
                 that.shown = false;
                 that.removeAlertContainer();
             });
-
         }
-
+        $(".removeMe").remove();
 
     };
 
diff --git a/javascript/src/DragAndDrop.js b/javascript/src/DragAndDrop.js
new file mode 100644
index 0000000000000000000000000000000000000000..e20fbf57f29d6244769153d5ed8e4c78e662c2f2
--- /dev/null
+++ b/javascript/src/DragAndDrop.js
@@ -0,0 +1,271 @@
+/**
+ * @author Benjamin Baer <benjamin.baer@math.uzh.ch>
+ */
+
+/* global $ */
+/* global EventEmitter */
+/* @depend QfqEvents.js */
+/* @depend Alert.js */
+
+/**
+ * Qfq Namespace
+ *
+ * @namespace QfqNS
+ */
+var QfqNS = QfqNS || {};
+
+(function (n) {
+    'use strict';
+
+    /**
+     * Dragging and dropping area!
+     */
+    n.DragAndDrop = function ($hook) {
+        this.$container = $hook;
+        this.eventEmitter = new EventEmitter();
+        this.dropZones = [];
+        this.elements = [];
+        this.active = false;
+        this.api = $hook.data("dnd-api");
+        this.draggedId = "";
+        this.lastChild = "";
+        this.$tempObject = {};
+    };
+
+    n.DragAndDrop.prototype.on = n.EventEmitter.onMixin;
+
+    n.DragAndDrop.prototype.buildDropArea = function(position, relatedId, otherPos) {
+        var that = this;
+        var $dropArea = {};
+
+        if (this.$container.data("columns")) {
+            $dropArea = $("<tr />", {
+                class: "qfqDropTarget"
+            });
+            var $fluff = $("<td />", {
+                class: "qfqDropTarget",
+                colspan: this.$container.data("columns")
+            });
+            $fluff.appendTo($dropArea);
+        } else {
+            $dropArea = $("<div />", {
+                class: "qfqDropTarget"
+            });
+        }
+
+        $dropArea.data("position", position);
+        $dropArea.data("related", relatedId);
+        $dropArea.data("other-pos", otherPos);
+        $dropArea.on("dragenter", function(e) {
+            e.preventDefault();
+            $dropArea.addClass("qfqTargetDisplay");
+        });
+        $dropArea.on("dragover", function(e) {
+            e.preventDefault();
+            e.originalEvent.dataTransfer.dropEffect = "move";
+        });
+        $dropArea.on("drop", function(e) {
+            e.originalEvent.preventDefault();
+            that._moveObjectBefore(e, $dropArea);
+        });
+
+        return $dropArea;
+    };
+
+    n.DragAndDrop.prototype.setDropZones = function($objects) {
+        var that = this;
+
+        $objects.each(function() {
+            var $dropZone = $(this);
+            $dropZone.on("dragenter", function(e) {
+                e.preventDefault();
+                $dropZone.addClass("qfqTargetDisplay");
+                e.Effect = "all";
+                that._handleDragEnter(e);
+            });
+            $dropZone.on("dragleave", function(e) {
+                e.preventDefault();
+                $dropZone.removeClass("qfqTargetDisplay");
+                that._handleDragLeave(e);
+            });
+            $dropZone.on("dragover", function(e) {
+                e.preventDefault();
+                e.stopPropagation();
+            });
+            $dropZone.on("drop", function(e) {
+                e.preventDefault();
+                e.stopPropagation();
+                that._dropHandler(e);
+            });
+            $dropZone.css("z-index", 5);
+            that.dropZones.push($dropZone);
+        });
+    };
+
+    n.DragAndDrop.prototype.setElements = function($objects) {
+        var that = this;
+
+        $objects.each(function() {
+            var $element = $(this);
+            $element.prop("draggable", true);
+            $element.on("dragstart", function(e) {
+                that.draggedId = $element[0].id;
+            });
+            that.elements.push($element);
+        });
+    };
+
+    n.DragAndDrop.prototype._handleDragEnter = function(event) {
+        var $tempObject = $("#" + this.draggedId).clone();
+        $tempObject.css("opacity", 0.5);
+        $tempObject.css("z-index", 0);
+        $tempObject.off();
+        if (this.$tempObject[0]) {
+            if ($tempObject[0].id !== this.$tempObject[0].id) {
+                this.$tempObject = $tempObject;
+                this.$tempObject.appendTo($("#" + event.currentTarget.id));
+            }
+        } else {
+            this.$tempObject = $tempObject;
+            this.$tempObject.appendTo($("#" + event.currentTarget.id));
+        }
+    };
+
+    n.DragAndDrop.prototype._handleDragLeave = function(event) {
+        if(this.$tempObject[0]) {
+            this.$tempObject.remove();
+            this.$tempObject = {};
+        }
+    };
+
+    n.DragAndDrop.prototype.makeBasketCase = function() {
+        var dzSelector = this.$container.data("dnd-dropzone") || false;
+        var elSelector = this.$container.data("dnd-element") || false;
+
+        if (elSelector) {
+            this.setElements($("." + elSelector));
+        }
+        if (dzSelector) {
+            this.setDropZones($("." + dzSelector));
+        }
+    };
+
+    n.DragAndDrop.prototype._dropHandler = function(event) {
+        if(this.$tempObject[0]) {
+            this.$tempObject.remove();
+            this.$tempObject = {};
+        }
+        $("#" + this.draggedId).appendTo($("#" + event.currentTarget.id));
+    };
+
+    n.DragAndDrop.prototype._buildOrderDropZones = function($object, e) {
+        this.removeDropAreas();
+
+        if ($object[0].id !== this.draggedId) {
+            if ($object.data("dnd-position") !== $("#" + this.draggedId).data("dnd-position") + 1) {
+                var $dropArea = this.buildDropArea("before", $object.data("dnd-id"), $object.data("dnd-position"));
+                $object.before($dropArea);
+            }
+
+            if ($object[0].id === this.lastChild) {
+                var $lastDrop = this.buildDropArea("after", $object.data("dnd-id"), $object.data("dnd-position"));
+                $lastDrop.appendTo(this.$container);
+            }
+        }
+    };
+
+    n.DragAndDrop.prototype.removeDropAreas = function() {
+        if (this.$container.data("column")) {
+            this.$container.children(".qfqTempTable").remove();
+        }
+        this.$container.children(".qfqDropTarget").remove();
+    };
+
+    n.DragAndDrop.prototype.makeSortable = function() {
+        var that = this;
+        var numberOfChildren = this.$container.children().length;
+        var count = 0;
+
+        this.$container.children().each( function() {
+            count++;
+
+            var child = $(this);
+            if (numberOfChildren === count) {
+                that.lastChild = child[0].id;
+            }
+            child.data("dnd-position", count);
+            child.prop("draggable", true);
+            child.on("dragstart", function(e) {
+                e.originalEvent.dataTransfer.setData("text", child[0].id);
+                that.draggedId = child[0].id;
+                that.active = true;
+                e.originalEvent.dataTransfer.effectAllowed = "move";
+            });
+            child.on("dragenter", function(e) {
+                if (that.active) {
+                    that._buildOrderDropZones($(this), e);
+                }
+            });
+            child.on("dragend", function() {
+                that.active = false;
+                that.removeDropAreas();
+            });
+        });
+    };
+
+    n.DragAndDrop.prototype._moveObjectBefore = function(e, $hook) {
+        var id = e.originalEvent.dataTransfer.getData("text");
+        var $object = $("#" + id);
+        var posTo = $hook.data("position");
+
+        if (posTo === "after") {
+            this.lastChild = $object[0].id;
+        }
+
+        $hook.before(document.getElementById(id));
+        this._buildOrderUpdate($object, $hook.data("position"), $hook.data("related"), $hook.data("other-pos"));
+        this.removeDropAreas();
+    };
+
+    n.DragAndDrop.prototype._buildOrderUpdate = function($object, position, otherId, otherPos) {
+        var jObject = {};
+        jObject.dragId = $object.data("dnd-id");
+        jObject.dragPosition = $object.data("dnd-position");
+        jObject.setTo = position;
+        jObject.hoverId = otherId;
+        jObject.hoverPosition = otherPos;
+        this._sendToAPI(jObject);
+    };
+
+    n.DragAndDrop.prototype._sendToAPI = function(object) {
+        var that = this;
+        $.getJSON(this.api, object, function(data) {
+            that._successHandler(data);
+        });
+    };
+
+    n.DragAndDrop.prototype._successHandler = function(data) {
+        if (data.status === "error") {
+            var alert = new n.Alert({
+                type: data.status,
+                message: data.message,
+                modal: true,
+                buttons: [{
+                    label: "Ok", eventName: "ok"
+                }]
+            });
+            alert.show();
+            console.error(data.message);
+        } else {
+            console.log("status:" + data.status + " message: " + data.message);
+            if (data.elementUpdate) {
+                if (!this.elementUpdate) {
+                    this.elementUpdate = new n.ElementUpdate();
+                }
+                this.elementUpdate.updateAll(data.elementUpdate);
+            }
+        }
+    };
+
+
+})(QfqNS);
\ No newline at end of file
diff --git a/javascript/src/Element/FormGroup.js b/javascript/src/Element/FormGroup.js
index d2f298b307d06f92f66e21d429c00f81da775cf8..70fbe7d684e707e37c1ec3f8aa73a0b986b2257d 100644
--- a/javascript/src/Element/FormGroup.js
+++ b/javascript/src/Element/FormGroup.js
@@ -99,7 +99,11 @@ QfqNS.Element = QfqNS.Element || {};
         }
 
         if ($formGroup.length > 1) {
-            throw new Error("enclosed element yields ambiguous form group");
+            $formGroup = $('#' + $enclosedElement.attr('id') + '-r');
+            console.log("Enclosed Element Id: " + $enclosedElement.attr('id'));
+            if ($formGroup.length !== 1) {
+                throw new Error("enclosed element yields ambiguous form group");
+            }
         }
 
         return $formGroup;
diff --git a/javascript/src/Form.js b/javascript/src/Form.js
index 64b6df453bdbaaef9d2f532bf1c3b5905c584314..81971d3b124ee41466e9e0683d411e9a24ab2211 100644
--- a/javascript/src/Form.js
+++ b/javascript/src/Form.js
@@ -222,14 +222,18 @@ var QfqNS = QfqNS || {};
     };
 
     /**
+     * Uses standard HTML Validation in native javascript for input elements
+     *
      * @public
      */
     n.Form.prototype.getFirstNonValidElement = function () {
         var index;
-        var elementNumber = document.forms[this.formId].length;
+        var form = document.getElementById(this.formId);
+        var inputs = form.getElementsByTagName("input");
+        var elementNumber = inputs.length;
 
         for (index = 0; index < elementNumber; index++) {
-            var element = document.forms[this.formId][index];
+            var element = inputs[index];
             if (!element.willValidate) {
                 continue;
             }
diff --git a/javascript/src/QfqForm.js b/javascript/src/QfqForm.js
index f04aff2124b990ef480875a490d5a903b566607e..6560667066b1be4ce28689a9c5b2686db6496f2c 100644
--- a/javascript/src/QfqForm.js
+++ b/javascript/src/QfqForm.js
@@ -293,14 +293,27 @@ var QfqNS = QfqNS || {};
     n.QfqForm.prototype.validationError = function (info) {
         var $formControl = $(info.data.element);
         var $messageContainer = $formControl.siblings('.hidden.with-errors');
+
+        if ($messageContainer.length === 0) {
+            if ($formControl.parent().hasClass('input-group')) {
+                $messageContainer = $formControl.parent().siblings('.hidden.with-errors');
+            }
+        }
+
         $messageContainer.data('qfq.hidden.message', true);
         $messageContainer.removeClass('hidden');
-
     };
 
     n.QfqForm.prototype.validationSuccess = function (info) {
         var $formControl = $(info.data.element);
         var $messageContainer = $formControl.siblings('.with-errors');
+
+        if ($messageContainer.length === 0) {
+            if ($formControl.parent().hasClass('input-group')) {
+                $messageContainer = $formControl.parent().siblings('.hidden.with-errors');
+            }
+        }
+
         if ($messageContainer.data('qfq.hidden.message') === true) {
             $messageContainer.addClass('hidden');
         }
@@ -604,6 +617,7 @@ var QfqNS = QfqNS || {};
             this.form.$form.validator('validate');
 
             alert = new n.Alert("Form is incomplete.", "warning");
+            alert.timeout = 3000;
             alert.show();
             return;
         }
@@ -727,7 +741,7 @@ var QfqNS = QfqNS || {};
         this.setButtonEnabled(this.getNewButton(), false);
         this.destroyFormAndSetText("Record has been deleted!");
 
-        if (!data.redirect || data.redirect === "client") {
+        if (!data.redirect || data.redirect === "auto") {
             this.goBack();
             return;
         }
@@ -772,7 +786,6 @@ var QfqNS = QfqNS || {};
         if (this.formImmutableDueToConcurrentAccess) {
             return;
         }
-        console.log("QFQForm Changehandler");
         this.getSaveButton().removeClass("disabled");
         this.getSaveButton().addClass(this.getSaveButtonAttentionClass());
         this.getSaveButton().removeAttr("disabled");
@@ -988,13 +1001,18 @@ var QfqNS = QfqNS || {};
                     return;
                 }
 
+                if (data.redirect === "close") {
+                    this.goBack();
+                    return;
+                }
+
                 break;
             case 'close':
                 if (!data.redirect || data.redirect === "no") {
                     return;
                 }
 
-                if (data.redirect === "client") {
+                if (data.redirect === "auto" || data.redirect === "close") {
                     this.goBack();
                     return;
                 }
@@ -1017,7 +1035,7 @@ var QfqNS = QfqNS || {};
                 return;
 
             default:
-                if (data.redirect === "client") {
+                if (data.redirect === "auto") {
                     this.goBack();
                     return;
                 }
diff --git a/javascript/src/TypeAhead.js b/javascript/src/TypeAhead.js
index 204050c5421ef41af31ab8136f323f9e654af5d5..0a6e12b5410061523b3b5c3266790055fe553e1f 100644
--- a/javascript/src/TypeAhead.js
+++ b/javascript/src/TypeAhead.js
@@ -16,7 +16,6 @@ var QfqNS = QfqNS || {};
 
     n.TypeAhead = {};
 
-
     /**
      * Coerce corejs-typeahead into our use-case.
      *
@@ -219,5 +218,4 @@ var QfqNS = QfqNS || {};
         }
         $element.typeahead('val', results[0].value);
     };
-})(QfqNS);
-
+})(QfqNS);
\ No newline at end of file
diff --git a/less/qfq-bs.css.less b/less/qfq-bs.css.less
index e4ed45466dff97ef85131c4ba110b48b32360564..4c4cc7cac940a13366b1da2cf7faabd8cb5fa7fa 100644
--- a/less/qfq-bs.css.less
+++ b/less/qfq-bs.css.less
@@ -110,16 +110,23 @@ i.@{spinner_class} {
   width: auto;
 }
 
+
 .qfq-form-pill {
+  /*
   border-top-right-radius: 4px;
-  border-top-left-radius: 4px;
+  border-top-left-radius: 4px; */
+  border: 1px solid #ccc;
+  border-top: none;
 }
 
+
 .qfq-form-body {
   padding-top: 5px;
   padding-bottom: 5px;
   border-bottom-right-radius: 4px;
   border-bottom-left-radius: 4px;
+  border: 1px solid #ccc;
+  border-top: none;
 }
 
 /* adjust BS padding of input elements: center */
@@ -134,6 +141,21 @@ i.@{spinner_class} {
   padding-top: 4px;
 }
 
+.qfq-form-title {
+  border: 1px solid #ccc;
+  border-radius: 4px 4px 0 0;
+  background-image: linear-gradient(to bottom, #fefefe 0, #dedede 100%);
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
+  min-height: 45px;
+  font-size: 1.2em;
+  padding: 13px 15px;
+  font-weight: bold;
+}
+
+.nav-pills>li>a {
+  border-radius: 0;
+}
+
 .qfq-color-white {
   background-color: #ffffff;
 }
@@ -412,4 +434,14 @@ i.@{spinner_class} {
 .alert-interactive p.buttons {
   margin-top: 20px;
   text-align: center;
+}
+
+.qfqDropTarget {
+  height: 50px;
+  margin: 1px;
+  border: 1px dashed #ccc;
+}
+
+.qfqTargetDisplay {
+  border: 1px dashed #25adf1;
 }
\ No newline at end of file
diff --git a/mockup/dragAndDrop.html b/mockup/dragAndDrop.html
new file mode 100644
index 0000000000000000000000000000000000000000..43a3d30db07a06fb505cb1904675ec9bf7d2e382
--- /dev/null
+++ b/mockup/dragAndDrop.html
@@ -0,0 +1,181 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+
+    <style type="text/css">
+        .anyClass {
+            height: 40px;
+            background-color: #5cb85c;
+            line-height: 40px;
+            color: white;
+            text-align: center;
+        }
+
+        .someClass {
+            min-height: 160px;
+            width: 160px;
+            border: 1px dashed #ccc;
+            margin: 15px;
+            padding-bottom: 30px;
+        }
+
+        .anotherClass {
+            margin: 15px;
+            padding: 15px;
+            border-radius: 5px;
+            text-align: center;
+            background-color: #5cb85c;
+            color: #fff;
+            width: 130px;
+        }
+    </style>
+
+    <link rel="stylesheet" href="../css/bootstrap.min.css">
+    <link rel="stylesheet" href="../css/bootstrap-theme.min.css">
+    <link rel="stylesheet" href="../css/jqx.base.css">
+    <link rel="stylesheet" href="../css/jqx.bootstrap.css">
+    <link rel="stylesheet" href="../extension/Resources/Public/Css/qfq-bs.css">
+    <title>Input Mode Switcher</title>
+
+</head>
+<body style="background-color: #f5f5f5;">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-md-10 ">
+            <div class="btn-toolbar pull-right" role="toolbar">
+                <div class="btn-group" role="group">
+                    <button id="save-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-ok"></span></button>
+                    <button id="close-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-remove"></span></button>
+                </div>
+                <div class="btn-group" role="group">
+                    <button id="delete-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-trash"></span></button>
+                </div>
+                <div class="btn-group" role="group">
+                    <a id="form-new-button" href="personmock.html?s=badcaffe1" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-plus"></span></a>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="row">
+        <div class="col-md-3"></div>
+        <div class="col-md-6">
+
+            <div class="qfq-dnd-sort" data-dnd-api="http://something/bla">
+                <div class="anyClass" id="e1" data-dnd-id="uno" data-dnd-value="10">
+                    Numbero Uno
+                </div>
+                <div class="anyClass" id="e2" data-dnd-id="deux">
+                    Numbero Deux
+                </div>
+                <div class="anyClass" id="e3" data-dnd-id="tre">
+                    Numbero Tre
+                </div>
+                <div class="anyClass" id="e4" data-dnd-id="quattro">
+                    Numbero Quattro
+                </div>
+                <div class="anyClass" id="e5" data-dnd-id="cinge">
+                    Numbero Cinge
+                </div>
+                <div class="anyClass" id="e6" data-dnd-id="siesta">
+                    Numbero Siesta
+                </div>
+            </div>
+
+            <h2>Table</h2>
+
+            <table class="table table-hover">
+                <tbody class="qfq-dnd-sort"
+                       data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=5b15109182850"
+                       data-columns="3">
+                <tr id="table-125" data-dnd-id="125">
+                    <td>125</td>
+                    <td>eins</td>
+                    <td>10</td>
+                </tr>
+                <tr id="table-126" data-dnd-id="126">
+                    <td>126</td>
+                    <td>zwei</td>
+                    <td>20</td>
+                </tr>
+                <tr id="table-128" data-dnd-id="128">
+                    <td>128</td>
+                    <td>vier</td>
+                    <td>30</td>
+                </tr>
+                <tr id="table-127" data-dnd-id="127">
+                    <td>127</td>
+                    <td>drei</td>
+                    <td>40</td>
+                </tr>
+                </tbody>
+            </table>
+
+            <hr>
+            <h2>Playing with baskets</h2>
+            <div class="qfq-dnd" style="margin-top: 20px;"
+                 data-dnd-api="http://somethingelse/bla"c
+                 data-dnd-dropzone="someClass"
+                 data-dnd-element="anotherClass"
+            >
+                <div class="col-md-6">
+                    <div class="someClass" id="dz1">
+
+                    </div>
+                    <div class="someClass" id="dz2">
+
+                    </div>
+                </div>
+
+                <div class="col-md-6">
+                    <div class="anotherClass" id="d1">
+                        Somebody
+                    </div>
+                    <div class="anotherClass" id="d2">
+                        Otherbody
+                    </div>
+                    <div class="anotherClass" id="d3">
+                        Thatbody
+                    </div>
+                    <div class="anotherClass" id="d4">
+                        Not me
+                    </div>
+                    <div class="anotherClass" id="d5">
+                        Otherguy
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<p><br></p>
+<script src="../js/jquery.min.js"></script>
+<script src="../js/bootstrap.min.js"></script>
+<script src="../js/validator.min.js"></script>
+<script src="../js/EventEmitter.min.js"></script>
+<script src="../js/qfq.debug.js"></script>
+
+<script type="text/javascript">
+    $(function () {
+
+        $('.qfq-dnd-sort').each(function() {
+            var dndObject = new QfqNS.DragAndDrop($(this));
+            dndObject.makeSortable();
+        });
+
+        $('.qfq-dnd').each(function() {
+            var zoni = new QfqNS.DragAndDrop($(this));
+            zoni.makeBasketCase();
+        });
+
+    });
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/mockup/fabric.html b/mockup/fabric.html
index a5100746350720abd9dd652b072a1dc90e967340..7d2f82cbe4713b582b3c01e4ce034fce2055fe10 100644
--- a/mockup/fabric.html
+++ b/mockup/fabric.html
@@ -11,6 +11,7 @@
     <link rel="stylesheet" href="../css/jqx.bootstrap.css">
     <link rel="stylesheet" href="../extension/Resources/Public/Css/qfq-bs.css">
     <title>Input Mode Switcher</title>
+    <link rel="stylesheet" href="../less/qfq-bs.css.less">
 
 </head>
 <body>
diff --git a/mockup/form.html b/mockup/form.html
index 116f098d039c8326673d653fc538f935729f3e1f..dbaac9689481080d1a095bd599bd88a5939edcdf 100644
--- a/mockup/form.html
+++ b/mockup/form.html
@@ -2,59 +2,185 @@
 <html lang="en">
 <head>
     <meta charset="UTF-8">
-    <title>Form</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+
+    <link rel="stylesheet" href="../css/bootstrap.min.css">
+    <link rel="stylesheet" href="../css/bootstrap-theme.min.css">
+    <link rel="stylesheet" href="../css/jqx.base.css">
+    <link rel="stylesheet" href="../css/jqx.bootstrap.css">
+    <link rel="stylesheet" href="../extension/Resources/Public/Css/qfq-bs.css">
+    <title>Input Mode Switcher</title>
+
 </head>
 <body>
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-md-3"></div>
+        <div class="col-md-6">
+            <div class="btn-toolbar pull-right" role="toolbar">
+                <div class="btn-group" role="group">
+                    <button id="save-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-ok"></span></button>
+                    <button id="close-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-remove"></span></button>
+                </div>
+                <div class="btn-group" role="group">
+                    <button id="delete-button" type="button" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-trash"></span></button>
+                </div>
+                <div class="btn-group" role="group">
+                    <a id="form-new-button" href="personmock.html?s=badcaffe1" class="btn btn-default navbar-btn"><span
+                            class="glyphicon glyphicon-plus"></span></a>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- remove this
+    <img src="mockData/Scan2a.jpeg" class="qfq-fabric-image" id="qfq-fabric-image-1"> </img>
+    -->
+    <div class="row">
+        <div class="col-md-3"></div>
+        <div class="col-md-6">
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="qfq-form-title">
+                        This is a title
+                    </div>
+                </div>
+            </div>
+            <div class="row">
+                <div class="col-md-12">
+                    <ul id="qfqTabs" class="nav nav-pills qfq-form-pill qfq-color-grey-1" role="tablist">
+                        <li role="presentation" class="active">
+                            <a href="#">Active</a>
+                        </li>
+                        <li role="presentation">
+                            <a href="#">Inactive</a>
+                        </li>
+                    </ul>
+                </div>
+            </div>
+            <form class="form-horizontal">
+                <div class="col-md-12 qfq-form-body qfq-color-grey-2">
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label required-field">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label required-field">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                </div>
+            </form>
+
+
+            <p style="margin-bottom: 40px;"><br>&nbsp;</p>
 
-<form id="theform">
-    <label>
-        Text input
-        <input type="text" name="textinput">
-    </label>
-    <label>
-        Select list
-        <select name="selectlist">
-            <option>1</option>
-            <option>2</option>
-        </select>
-    </label>
-    <label>
-        Radio
-        <input type="radio" name="radioinput" value="1">
-    </label>
-    <label>
-        Other radio
-        <input type="radio" name="radioinput" value="2">
-    </label>
-    <label>
-        Checkbox
-        <input type="checkbox" name="checkboxinput" value="3">
-    </label>
-
-    <fieldset name="userinfo">
-        <legend>User information</legend>
-        <label for="name">Name</label>
-        <input type="text" name="name" id="name" size="40">
-        <label for="address">Address</label>
-        <input type="text" name="address" id="address" size="40">
-        <label for="phone">Phone</label>
-        <input type="text" name="phone" id="phone" size="40">
-    </fieldset>
-
-</form>
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="qfq-form-title">
+                        This is a title
+                    </div>
+                </div>
+            </div>
+
+            <form class="form-horizontal">
+                <div class="col-md-12 qfq-form-body qfq-color-grey-2">
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label required-field">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label required-field">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                    <div class="form-group clearfix">
+                        <div class="col-md-3 qfq-label">
+                            <label class="control-label">
+                                Name
+                            </label>
+                        </div>
+                        <div class="col-md-6"><input class="form-control" type="text"></div>
+                        <div class="col-md-3"></div>
+                    </div>
+                </div>
+            </form>
+        </div>
+    </div>
+</div>
 
 <script src="../js/jquery.min.js"></script>
+<script src="../js/bootstrap.min.js"></script>
+<script src="../js/fabric.min.js"></script>
+<script src="../js/validator.min.js"></script>
+<script src="../js/jqx-all.js"></script>
 <script src="../js/EventEmitter.min.js"></script>
 <script src="../js/qfq.debug.js"></script>
+<script src="../javascript/src/Plugins/qfq.fabric.js"></script>
 
-<script>
+<script type="text/javascript">
     $(function () {
-        var form = new QfqNS.Form("theform");
-        form.addChangeHandler(function (form) {
-            console.log("form changed");
+        var qfqPage = new QfqNS.QfqPage({
+            tabsId: 'myTabs',
+            formId: 'myForm',
+            submitTo: 'api/' + $("#submitTo").val(),
+            deleteUrl: 'api/' + $("#deleteUrl").val(),
+            fileUploadTo: 'api/' + $("#uploadTo").val(),
+            fileDeleteUrl: 'api/' + $("#fileDeleteUrl").val()
         });
+
+        QfqNS.Log.level = 0;
+        // Just for mockup, init() function called from new QfqNS.Plugin class maybe.
+
     });
 </script>
-
 </body>
 </html>
\ No newline at end of file
diff --git a/mockup/qfqform.html b/mockup/qfqform.html
index a50d23c1427f9ecd30708cc67f5dcc4b1f24214d..ebda7499fa25bd73c665dc56875538dd20ce8cfa 100644
--- a/mockup/qfqform.html
+++ b/mockup/qfqform.html
@@ -64,6 +64,10 @@
 
 
 <div class="container-fluid">
+    <div class="row">
+        <div class="col-md-2"></div>
+        <div class="col-md-8">
+
     <div class="row hidden-xs">
         <div class="col-md-12">
             <h1>Title with a long text</h1>
@@ -333,6 +337,8 @@
     </form>
     <a href="https://www.google.ch">away</a>
 </div>
+    </div>
+</div>
 
 <script type="application/jqw-combobox-source" id="combobox1_source">
     [
diff --git a/version b/version
index d8215eea75da6975344bef1e411cc0fd681d443a..4b5ebaf0fc65007cf0713605bbd13629da660552 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-18.4.4
+18.6.0