diff --git a/CHANGELOG.md b/CHANGELOG.md
index 69bee416733fb2a5d668b1a0b749d91c5ebfe3ea..7f6c59c50137d82263e90c166e7cadf237b2e530 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1203,7 +1203,7 @@ Bug Fixes
 
  * Dynamic Update has been broken since implementing of 'element-update' (#3180). Now both methods, 'element-update' and 'form-update' should be fine.
  * qfq-bs.css.less: Fixed problem with 'typeahead input elements' not expanded to Bootstrap column width. Changed
-   Layout/Design Typeahead drop-down box. Add hoover for the drop-down box with a blue background
+   Layout/Design Typeahead drop-down box. Add hover for the drop-down box with a blue background
  * AbstractBuildForm.php: #3374 - textarea elements now contains 'maxlength' attribute.
  * BuildFormBootstrap.php: wrapping of optional 'submitButtonText' now done with the 'per form' values.
  * typeahead.php: if there is an exception, the message body is sent as regular 'content' for the drop-down box. At the
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/PROTOCOL.md b/doc/PROTOCOL.md
index a7fa4211f1225e2f9a6fd9087b573729d519b2ac..a7ef5fc514f64e5d708c480436a7ba807fefaf62 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.
@@ -465,7 +465,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 +479,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 +488,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/Documentation/Manual.rst b/extension/Documentation/Manual.rst
index 353e8e9ea3f7bccee6bcf629c9283d38a50bfd5d..e721d7b186b7c7dad23933e09a28406c1cc3d442 100644
--- a/extension/Documentation/Manual.rst
+++ b/extension/Documentation/Manual.rst
@@ -2556,7 +2556,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 +2937,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 +4121,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 +6235,125 @@ E.g.::
 
     10.sql = SELECT "p:home&r=0|t:Home|c:qfq-100 qfq-left" AS _pagev
 
-Examples
---------
+
+Drag and drop
+-------------
+
+Sort/order elements
+^^^^^^^^^^^^^^^^^^^
+
+Manually sorting and ordering of elements via `HTML5 drag and drop` is supported via QFQ. Any sortable element
+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.
+* Update database: updates of the order column are managed by a specific 'drag and drop' definition form.
+
+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 an automatically SIP protected 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 is 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: Update database
+'''''''''''''''''''''''
+
+A dedicated `Form`, without any `FormElements`, is needed 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: ::
+
+  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}}
+
+Report Examples
+---------------
 
 The following section gives some examples of typical reports
 
@@ -6571,42 +6705,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
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/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index 6dc85c838d5026dbce982f9eef30a0b89d0ff66f..54d53da30f57309a960e401448f2869719c24521 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -86,6 +86,8 @@ abstract class AbstractBuildForm {
      * @param array $feSpecAction
      * @param array $feSpecNative
      * @param array $db
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function __construct(array $formSpec, array $feSpecAction, array $feSpecNative, array $db = null) {
         $this->formSpec = $formSpec;
@@ -172,6 +174,8 @@ abstract class AbstractBuildForm {
      * @param array $latestFeSpecNative
      * @return array|string $mode=LOAD_FORM: The whole form as HTML, $mode=FORM_UPDATE: array of all
      *                        formElement.dynamicUpdate-yes  values/states
+     * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
      */
     public function process($mode, $htmlElementNameIdZero = false, $latestFeSpecNative = array()) {
@@ -247,6 +251,8 @@ abstract class AbstractBuildForm {
      *
      * @param string $mode
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function head($mode = FORM_LOAD) {
         $html = '';
@@ -276,6 +282,8 @@ abstract class AbstractBuildForm {
      *
      * @return string String: <a href="?pageId&sip=....">Edit</a> <small>[sip:..., r:..., urlparam:...,
      *                ...]</small>
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function createFormEditorUrl($form, $recordId, array $param = array()) {
 
@@ -321,6 +329,9 @@ abstract class AbstractBuildForm {
      * Returns '<form ...>'-tag with various attributes.
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function getFormTag() {
         $md5 = '';
@@ -338,6 +349,9 @@ abstract class AbstractBuildForm {
      * Build MD5 from the current record. Return HTML Input element.
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function buildInputRecordHashMd5() {
 
@@ -357,6 +371,9 @@ abstract class AbstractBuildForm {
      * @param $recordId
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function buildRecordHashMd5($tableName, $recordId) {
         $record = array();
@@ -372,6 +389,8 @@ abstract class AbstractBuildForm {
      * Create HTML Input vars to detect bot automatic filling of forms.
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function getHoneypotVars() {
         $html = '';
@@ -442,6 +461,9 @@ abstract class AbstractBuildForm {
      * See: https://www.w3.org/wiki/HTML/Elements/form#HTML_Attributes
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     public function getEncType() {
 
@@ -457,6 +479,10 @@ abstract class AbstractBuildForm {
      * @param array|string $value
      *
      * @return array|string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     private function processReportSyntax($value) {
 
@@ -502,6 +528,10 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     public function elements($recordId, $filter = FORM_ELEMENTS_NATIVE, $feIdContainer = 0, array &$json,
                              $modeCollectFe = FLAG_DYNAMIC_UPDATE, $htmlElementNameIdZero = false,
@@ -672,6 +702,10 @@ abstract class AbstractBuildForm {
      * @param array $formElement
      *
      * @return array
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     private function prepareFillStoreFireLdap(array $formElement) {
 
@@ -767,6 +801,8 @@ abstract class AbstractBuildForm {
      * save/update.
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function prepareT3VarsForSave() {
 
@@ -802,6 +838,8 @@ abstract class AbstractBuildForm {
      * Get all elements from STORE_ADDITIONAL_FORM_ELEMENTS and return them as a string.
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function buildAdditionalFormElements() {
 
@@ -816,6 +854,8 @@ abstract class AbstractBuildForm {
      * @param array $json
      *
      * @return string  <input type='hidden' name='s' value='<sip>'>
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildHiddenSip(array &$json) {
 
@@ -921,6 +961,7 @@ abstract class AbstractBuildForm {
      * @param array $feMode
      *
      * @return array
+     * @throws UserFormException
      */
     private function getJsonFeMode($feMode) {
 
@@ -970,6 +1011,7 @@ abstract class AbstractBuildForm {
      * @param string $addClass
      *
      * @return string
+     * @throws CodeException
      */
     public function buildLabel($htmlFormElementName, $label, $addClass = '') {
         $attributes = Support::doAttribute('for', $htmlFormElementName);
@@ -985,6 +1027,8 @@ abstract class AbstractBuildForm {
      *
      * @param $toolTipNew
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function deriveNewRecordUrlFromExistingSip(&$toolTipNew) {
 
@@ -1048,6 +1092,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string complete rendered HTML input element.
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildInput(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $textarea = '';
@@ -1154,7 +1200,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]);
 
@@ -1192,6 +1238,7 @@ abstract class AbstractBuildForm {
      * @param array $formElement
      *
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     private function typeAheadBuildParam(array &$formElement) {
@@ -1297,6 +1344,7 @@ abstract class AbstractBuildForm {
      * @param bool $flagOmitEmpty
      *
      * @return string
+     * @throws CodeException
      */
     private function getAttributeList(array $formElement, array $attributeList, $flagOmitEmpty = true) {
         $attribute = '';
@@ -1315,6 +1363,7 @@ abstract class AbstractBuildForm {
      *
      * @param bool $cssDisable
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     private function getAttributeFeMode($feMode, $cssDisable = true) {
@@ -1371,6 +1420,7 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE*
      *
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     public function buildCheckbox(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
@@ -1426,6 +1476,7 @@ abstract class AbstractBuildForm {
      * @param array $itemKey
      * @param array $itemValue
      *
+     * @throws CodeException
      * @throws UserFormException
      */
     public function getKeyValueListFromSqlEnumSpec(array $formElement, array &$itemKey, array &$itemValue) {
@@ -1498,6 +1549,7 @@ abstract class AbstractBuildForm {
      * @param string $fieldType
      *
      * @return array
+     * @throws CodeException
      * @throws UserFormException
      */
     private function getItemsForEnumOrSet($column, &$fieldType) {
@@ -1543,6 +1595,7 @@ abstract class AbstractBuildForm {
      * @param array $itemKey
      * @param array $formElement
      *
+     * @throws CodeException
      * @throws UserFormException
      */
     private function prepareCheckboxCheckedUncheckedValue(array $itemKey, array &$formElement) {
@@ -1583,6 +1636,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) {
 
@@ -1616,6 +1671,8 @@ abstract class AbstractBuildForm {
      * @param array $json
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function constructCheckboxSingleButton(array $formElement, $htmlFormElementName, $attribute, $value, array &$json) {
         $html = '';
@@ -1674,6 +1731,8 @@ abstract class AbstractBuildForm {
      * @param array $json
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function constructCheckboxSinglePlain(array $formElement, $htmlFormElementName, $attribute, $value, array &$json) {
         $html = '';
@@ -1722,6 +1781,7 @@ abstract class AbstractBuildForm {
      * @param array $itemValue
      * @param array $json
      * @return string
+     * @throws CodeException
      */
     public function buildCheckboxMulti(array $formElement, $htmlFormElementName, $attributeBase, $value, array $itemKey, array $itemValue, array &$json) {
 
@@ -1741,7 +1801,8 @@ abstract class AbstractBuildForm {
      * @param array $formElement
      * @param string $htmlFormElementName
      * @param string $htmlHidden
-     *
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function fillStoreAdditionalFormElementsCheckboxHidden(array $formElement, $htmlFormElementName, $htmlHidden) {
 
@@ -1771,6 +1832,7 @@ abstract class AbstractBuildForm {
      * @param array $json
      *
      * @return string
+     * @throws CodeException
      */
     public function constructCheckboxMultiButton(array $formElement, $htmlFormElementName, $attributeBase, $value, array $itemKey, array $itemValue, array &$json) {
         $json = array();
@@ -1842,6 +1904,7 @@ abstract class AbstractBuildForm {
      * @param array $json
      *
      * @return string
+     * @throws CodeException
      */
     public function constructCheckboxMultiPlain(array $formElement, $htmlFormElementName, $attributeBase, $value, array $itemKey, array $itemValue, array &$json) {
         $json = array();
@@ -1930,6 +1993,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildExtra(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
 
@@ -1954,6 +2019,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildRadio(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
 
@@ -2000,6 +2067,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function constructRadioButton(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $itemKey = array();
@@ -2081,6 +2150,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function constructRadioPlain(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $attributeBase = '';
@@ -2169,6 +2240,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return mixed
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildSelect(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $itemKey = array();
@@ -2242,6 +2315,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) {
 
@@ -2274,6 +2348,9 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildSubrecord(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $rcText = false;
@@ -2431,6 +2508,8 @@ abstract class AbstractBuildForm {
      * @param $toolTip
      * @param array $currentRow
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function createFormLink(array $formElement, $targetRecordId, array $record, $symbol, $toolTip, $currentRow = array()) {
 
@@ -2498,6 +2577,9 @@ abstract class AbstractBuildForm {
      * @param string $formName
      *
      * @return string   tableName for $formName
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
      */
     private function getFormTable($formName) {
         $row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT " . F_TABLE_NAME . " FROM Form AS f WHERE f.name = ?", ROW_EXPECT_0_1, [$formName]);
@@ -2528,6 +2610,7 @@ abstract class AbstractBuildForm {
      * @param array $titleRaw
      *
      * @return array
+     * @throws UserFormException
      */
     private function getSubrecordColumnControl(array $titleRaw) {
         $control = array();
@@ -2605,6 +2688,9 @@ abstract class AbstractBuildForm {
      * @param string $columnValue
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     private function renderCell(array $control, $columnName, $columnValue) {
         $link = null;
@@ -2667,6 +2753,8 @@ abstract class AbstractBuildForm {
      *                          parameters.
      *
      * @return string String: "API_DIR/delete.php?sip=...."
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function createDeleteUrl($formName, $recordId, $mode = RETURN_URL) {
 
@@ -2694,7 +2782,10 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildFile(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $attribute = '';
@@ -2811,6 +2902,7 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     public function buildAnnotate(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
@@ -2863,6 +2955,7 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     public function buildImageCut(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
@@ -2930,6 +3023,8 @@ abstract class AbstractBuildForm {
     /**
      * @param string $pathFileName
      * @return string SIP encoded URL
+     * @throws CodeException
+     * @throws UserFormException
      */
     private function fileToSipUrl($pathFileName) {
         $param[DOWNLOAD_MODE] = DOWNLOAD_MODE_FILE;
@@ -2953,6 +3048,7 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
      * @throws UserFormException
      */
     public function buildDateTime(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
@@ -3065,6 +3161,8 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildDateJQW(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $arrMinMax = null;
@@ -3147,6 +3245,8 @@ abstract class AbstractBuildForm {
      * @param string $mode
      *
      * @return string
+     * @throws CodeException
+     * @throws UserFormException
      */
     public function buildEditor(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $attribute = '';
@@ -3297,6 +3397,7 @@ abstract class AbstractBuildForm {
      *
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      * @return mixed
+     * @throws CodeException
      */
     public function buildNote(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
 
@@ -3331,6 +3432,10 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return mixed
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildFieldset(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $attribute = '';
@@ -3397,6 +3502,10 @@ abstract class AbstractBuildForm {
      * @param string $mode FORM_LOAD | FORM_UPDATE | FORM_SAVE
      *
      * @return mixed
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildTemplateGroup(array $formElement, $htmlFormElementName, $value, array &$json, $mode = FORM_LOAD) {
         $attribute = '';
@@ -3509,6 +3618,10 @@ EOT;
      * @param array $json
      *
      * @return string
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     private function templateGroupCollectFilledElements($max, $htmlDelete, array &$json) {
 
@@ -3591,6 +3704,10 @@ EOT;
      * Additional the maximum count of all select rows will be determined and returned.
      *
      * @return int   max number of records in FormElement[FE_VALUE] over all FormElements.
+     * @throws CodeException
+     * @throws DbException
+     * @throws UserFormException
+     * @throws UserReportException
      */
     private function templateGroupDoValue() {
 
diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php
index 0a686799147e0d6012c59bf732b373e44f83aa12..280f8a7814baf420ad39cb7363a2aebfd23f765c 100644
--- a/extension/qfq/qfq/BuildFormBootstrap.php
+++ b/extension/qfq/qfq/BuildFormBootstrap.php
@@ -113,6 +113,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function head($mode = FORM_LOAD) {
         $html = '';
@@ -383,7 +384,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 +516,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
      * @return string
      * @throws CodeException
      * @throws DbException
+     * @throws UserFormException
      */
     public function getFormTag() {
 
@@ -595,6 +599,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
                     fileDeleteUrl: '$apiDir/file.php?$actionDelete'
                 });
 
+               
                 var qfqRecordList = new QfqNS.QfqRecordList('$apiDeletePhp');
             })
          </script>
@@ -614,6 +619,7 @@ EOF;
      * @throws CodeException
      * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function buildPill(array $formElement, $htmlFormElementName, $value, array &$json) {
         $html = '';
@@ -809,6 +815,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 b7d84ed492a81619d031b1755a838812125c4a3a..da2e77b05b9cba473246bab267bfb86f87389338 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -33,6 +33,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 +144,11 @@ 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_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;
@@ -169,7 +171,7 @@ const ERROR_MISSING_OPEN_DELIMITER = 1060;
 const ERROR_MISSING_CLOSE_DELIMITER = 1061;
 const ERROR_EXPECTED_ARRAY = 1062;
 const ERROR_REPORT_FAILED_ACTION = 1063;
-const ERROR_MISSING_MESSAGE_FAIL = 1064;
+
 const ERROR_MISSING_TABLE_NAME = 1065;
 const ERROR_MISSING_TABLE = 1066;
 const ERROR_RECORD_NOT_FOUND = 1067;
@@ -247,6 +249,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;
@@ -546,6 +549,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 +651,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';
@@ -851,6 +856,11 @@ 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';
+
 // FORM_ELEMENT_STATI
 const FE_MODE_SHOW = 'show';
 const FE_MODE_READONLY = 'readonly';
@@ -994,6 +1004,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 +1081,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
@@ -1420,3 +1433,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 0f2cb03d5eb102cf908a9e581865612c2337c1bb..161c53b0edd91b5641e40a0c9fc87d9340443650 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);
@@ -265,6 +272,7 @@ class QuickFormQuery {
         }
     }
 
+
     /**
      * Process form.
      * $mode=
@@ -278,6 +286,7 @@ class QuickFormQuery {
      * @return array|string
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -286,7 +295,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 +304,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 +325,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;
@@ -476,6 +492,14 @@ class QuickFormQuery {
                 }
 
                 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:
                 throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
@@ -764,7 +788,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 +926,7 @@ class QuickFormQuery {
             case FORM_SAVE:
             case FORM_UPDATE:
             case FORM_DELETE:
+            case FORM_DRAG_AND_DROP:
                 $store = STORE_SIP;
                 break;
             default:
@@ -1218,7 +1243,6 @@ class QuickFormQuery {
         $html = $report->process($this->t3data['bodytext']);
 
         return $html;
-
     }
 
     /**
@@ -1227,6 +1251,7 @@ class QuickFormQuery {
      * @return string
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -1243,6 +1268,7 @@ class QuickFormQuery {
      * @return array
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -1253,12 +1279,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
      */
@@ -1343,5 +1387,32 @@ 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/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 ca924704faf44e07e5f6b7e03ef16e3f11b66367..bfe6c7665f82aa228e251c59d8a8bf600877ad0d 100644
--- a/extension/qfq/qfq/helper/Support.php
+++ b/extension/qfq/qfq/helper/Support.php
@@ -867,7 +867,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 +887,7 @@ class Support {
                 break;
 
             case 'bit':
-                $inputType = 'number';
+                $inputType = HTML_INPUT_TYPE_NUMBER;
                 $checkType = SANITIZE_ALLOW_DIGIT;
                 break;
 
diff --git a/extension/qfq/qfq/report/Download.php b/extension/qfq/qfq/report/Download.php
index 6d63a592887bb689e75ce6e15c84572c97970d67..8a2b0ac9f6ed52ec36be5b0135c7a12b347c8594 100644
--- a/extension/qfq/qfq/report/Download.php
+++ b/extension/qfq/qfq/report/Download.php
@@ -94,6 +94,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/Link.php b/extension/qfq/qfq/report/Link.php
index 6e3a6990ca9d7585d42d489c230470db91ed4008..578df997a038386fe3652a5899bf6f9685ad17bd 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);
@@ -1321,7 +1329,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/report/Report.php b/extension/qfq/qfq/report/Report.php
index 6c44a55ce5723e5c50cd22bcb170773563f3bad0..1afd6c4fd33f2b5b544f1e7d6e9ad9c83e760b59 100644
--- a/extension/qfq/qfq/report/Report.php
+++ b/extension/qfq/qfq/report/Report.php
@@ -668,6 +668,7 @@ class Report {
      * @return string rendered column
      * @throws CodeException
      * @throws DbException
+     * @throws DownloadException
      * @throws UserFormException
      * @throws UserReportException
      */
@@ -709,10 +710,10 @@ class Report {
             case COLUMN_PPAGEI:
             case COLUMN_PPAGEN:
             case COLUMN_PPAGES:
-            $lowerColumnName = strtolower($columnName);
+                $lowerColumnName = strtolower($columnName);
                 $tokenizedValue = $this->doFixColPosPage($columnName, $columnValue);
-            $linkValue = $this->doPage($lowerColumnName, $tokenizedValue);
-            $content .= $this->link->renderLink($linkValue);
+                $linkValue = $this->doPage($lowerColumnName, $tokenizedValue);
+                $content .= $this->link->renderLink($linkValue);
                 break;
 
             // Lowercase 'P'
@@ -725,7 +726,7 @@ class Report {
             case COLUMN_PAGEN:
             case COLUMN_PAGES:
                 $linkValue = $this->doPage($columnName, $columnValue);
-            $content .= $this->link->renderLink($linkValue);
+                $content .= $this->link->renderLink($linkValue);
                 break;
 
             case COLUMN_PPDF:
diff --git a/extension/qfq/qfq/store/FillStoreForm.php b/extension/qfq/qfq/store/FillStoreForm.php
index 2ef50b3d85cff9ff42388d0e4aa0d950bb5ca116..1ad8daf06e508854531a30e6631a95da916c96f1 100644
--- a/extension/qfq/qfq/store/FillStoreForm.php
+++ b/extension/qfq/qfq/store/FillStoreForm.php
@@ -81,7 +81,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);
 
@@ -148,7 +148,9 @@ class FillStoreForm {
      * @param string $formMode
      *
      * @throws CodeException
+     * @throws DbException
      * @throws UserFormException
+     * @throws UserReportException
      */
     public function process($formMode = FORM_SAVE) {
 
@@ -263,7 +265,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) {
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/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..cc46c35341664afdbf39f378728dd317d425ad2a 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: 10px 10px 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);
+  height: 45px;
+  font-size: 1.2em;
+  padding: 10px 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