[TASK] Refactoring of the QueryGenerator Interface Part 2 94/40694/8
authorFrank Nägler <typo3@naegler.net>
Sat, 27 Jun 2015 15:43:37 +0000 (17:43 +0200)
committerBenjamin Mack <benni@typo3.org>
Mon, 29 Jun 2015 20:18:02 +0000 (22:18 +0200)
Next step of QueryGenerator Refactoring.

Main goals:
- Remove all inline JavaScript
- Remove usage of TBE_EDITOR
- Introduce QueryGenerator AMD module
- Improve HTML output
- Improve styling
- Use htmlspecialchars for all output

Resolves: #67790
Releases: master
Change-Id: I0a4f6ecf52e226f49f434ad8d472a969cb3b160b
Reviewed-on: http://review.typo3.org/40694
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Benjamin Mack <benni@typo3.org>
Tested-by: Benjamin Mack <benni@typo3.org>
typo3/sysext/core/Classes/Database/QueryGenerator.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-67790-DeprecateQueryGeneratorJSbottom.rst [new file with mode: 0644]
typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator.js [new file with mode: 0644]
typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.evalfield.js [deleted file]
typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.tbe_editor.js [deleted file]
typo3/sysext/lowlevel/Classes/View/DatabaseIntegrityView.php
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_module_database.less
typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css

index 1757ad2..3374bfe 100644 (file)
@@ -184,6 +184,11 @@ class QueryGenerator {
        public $table;
 
        /**
+        * @var array
+        */
+       public $tableArray;
+
+       /**
         * Field list
         *
         * @var string
@@ -221,6 +226,7 @@ class QueryGenerator {
 
        /**
         * @var string
+        * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
         */
        public $extJSCODE = '';
 
@@ -326,7 +332,7 @@ class QueryGenerator {
                                                        break;
                                                case 'group':
                                                        $this->fields[$fieldName]['type'] = 'files';
-                                                       if ($this->fields[$fieldName]['internal_type'] == 'db') {
+                                                       if ($this->fields[$fieldName]['internal_type'] === 'db') {
                                                                $this->fields[$fieldName]['type'] = 'relation';
                                                        }
                                                        break;
@@ -510,7 +516,7 @@ class QueryGenerator {
                        // Do stuff:
                        $tempEl = $workArr[$ssArr[$i]];
                        if (is_array($tempEl)) {
-                               if ($tempEl['type'] == 'newlevel') {
+                               if ($tempEl['type'] === 'newlevel') {
                                        $a1 = array_slice($workArr, 0, $ssArr[$i]);
                                        $a2 = array_slice($workArr, $ssArr[$i]);
                                        array_shift($a2);
@@ -541,10 +547,10 @@ class QueryGenerator {
                // Traverse:
                foreach ($queryConfig as $key => $conf) {
                        $fieldName = '';
-                       if (substr($conf['type'], 0, 6) == 'FIELD_') {
+                       if (substr($conf['type'], 0, 6) === 'FIELD_') {
                                $fieldName = substr($conf['type'], 6);
                                $fieldType = $this->fields[$fieldName]['type'];
-                       } elseif ($conf['type'] == 'newlevel') {
+                       } elseif ($conf['type'] === 'newlevel') {
                                $fieldType = $conf['type'];
                        } else {
                                $fieldType = 'ignore';
@@ -589,7 +595,7 @@ class QueryGenerator {
                }
                $c = 0;
                $arrCount = 0;
-               $loopcount = 0;
+               $loopCount = 0;
                foreach ($queryConfig as $key => $conf) {
                        $fieldName = '';
                        $subscript = $parent . '[' . $key . ']';
@@ -611,6 +617,7 @@ class QueryGenerator {
                        } else {
                                $fieldType = 'ignore';
                        }
+                       $fieldPrefix = htmlspecialchars($this->name . $subscript);
                        switch ($fieldType) {
                                case 'ignore':
                                        break;
@@ -618,39 +625,33 @@ class QueryGenerator {
                                        if (!$queryConfig[$key]['nl']) {
                                                $queryConfig[$key]['nl'][0]['type'] = 'FIELD_';
                                        }
-                                       $lineHTML[] = '<input type="hidden" name="' . $this->name . $subscript . '[type]" value="newlevel">';
+                                       $lineHTML[] = '<input type="hidden" name="' . $fieldPrefix . '[type]" value="newlevel">';
                                        $codeArr[$arrCount]['sub'] = $this->getFormElements($subLevel + 1, $queryConfig[$key]['nl'], $subscript . '[nl]');
                                        break;
                                case 'userdef':
-                                       $lineHTML[] = $this->userDef($this->name . $subscript, $conf, $fieldName, $fieldType);
+                                       $lineHTML[] = $this->userDef($fieldPrefix, $conf, $fieldName, $fieldType);
                                        break;
                                case 'date':
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       if ($conf['comparison'] == 100 || $conf['comparison'] == 101) {
+                                       if ($conf['comparison'] === 100 || $conf['comparison'] === 101) {
                                                // between
-                                               $lineHTML[] = '<input class="form-control" type="text" name="' . $this->name . $subscript . '[inputValue]_hr' . '" value="' . strftime('%e-%m-%Y', $conf['inputValue']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue]\', \'date\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
-                                               $lineHTML[] = '<input class="form-control" type="text" name="' . $this->name . $subscript . '[inputValue1]_hr' . '" value="' . strftime('%e-%m-%Y', $conf['inputValue1']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue1]\', \'date\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $this->name . $subscript . '[inputValue1]' . '">';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue]", "date", "", 0,0);';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue1]", "date", "", 0,0);';
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue]', $conf['inputValue'], 'date');
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue1]', $conf['inputValue1'], 'date');
                                        } else {
-                                               $lineHTML[] = '<input type="text" name="' . $this->name . $subscript . '[inputValue]_hr' . '" value="' . strftime('%e-%m-%Y', $conf['inputValue']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue]\', \'date\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue]", "date", "", 0,0);';
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue]', $conf['inputValue'], 'date');
                                        }
                                        $lineHTML[] = '</div>';
                                        break;
                                case 'time':
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       if ($conf['comparison'] == 100 || $conf['comparison'] == 101) {
+                                       if ($conf['comparison'] === 100 || $conf['comparison'] === 101) {
                                                // between:
-                                               $lineHTML[] = '<input class="form-control" type="text" name="' . $this->name . $subscript . '[inputValue]_hr' . '" value="' . strftime('%H:%M %e-%m-%Y', $conf['inputValue']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue]\', \'datetime\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
-                                               $lineHTML[] = '<input class="form-control" type="text" name="' . $this->name . $subscript . '[inputValue1]_hr' . '" value="' . strftime('%H:%M %e-%m-%Y', $conf['inputValue1']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue1]\', \'datetime\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $this->name . $subscript . '[inputValue1]' . '">';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue]", "datetime", "", 0,0);';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue1]", "datetime", "", 0,0);';
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue]', $conf['inputValue'], 'datetime');
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue1]', $conf['inputValue1'], 'datetime');
                                        } else {
-                                               $lineHTML[] = '<input class="form-control" type="text" name="' . $this->name . $subscript . '[inputValue]_hr' . '" value="' . strftime('%H:%M %e-%m-%Y', (int)$conf['inputValue']) . '" onChange="typo3form.fieldGet(\'' . $this->name . $subscript . '[inputValue]\', \'datetime\', \'\', 0,0);"><input type="hidden" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
-                                               $this->extJSCODE .= 'typo3form.fieldSet("' . $this->name . $subscript . '[inputValue]", "datetime", "", 0,0);';
+                                               $lineHTML[] = $this->getDateTimePickerField($fieldPrefix . '[inputValue]', $conf['inputValue'], 'datetime');
                                        }
                                        $lineHTML[] = '</div>';
                                        break;
@@ -659,15 +660,15 @@ class QueryGenerator {
                                case 'relation':
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       if ($conf['comparison'] == 68 || $conf['comparison'] == 69 || $conf['comparison'] == 162 || $conf['comparison'] == 163) {
-                                               $lineHTML[] = '<select class="form-control" name="' . $this->name . $subscript . '[inputValue]' . '[]" style="vertical-align:top;" size="5" multiple>';
-                                       } elseif ($conf['comparison'] == 66 || $conf['comparison'] == 67) {
+                                       if ($conf['comparison'] === 68 || $conf['comparison'] === 69 || $conf['comparison'] === 162 || $conf['comparison'] === 163) {
+                                               $lineHTML[] = '<select class="form-control" name="' . $fieldPrefix . '[inputValue]' . '[]" multiple="multiple">';
+                                       } elseif ($conf['comparison'] === 66 || $conf['comparison'] === 67) {
                                                if (is_array($conf['inputValue'])) {
                                                        $conf['inputValue'] = implode(',', $conf['inputValue']);
                                                }
-                                               $lineHTML[] = '<input class="form-control" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
+                                               $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $fieldPrefix . '[inputValue]' . '">';
                                        } else {
-                                               $lineHTML[] = '<select class="form-control" name="' . $this->name . $subscript . '[inputValue]' . '" style="vertical-align:top;" onChange="submit();">';
+                                               $lineHTML[] = '<select class="form-control t3js-submit-change" name="' . $fieldPrefix . '[inputValue]' . '">';
                                        }
                                        if ($conf['comparison'] != 66 && $conf['comparison'] != 67) {
                                                $lineHTML[] = $this->makeOptionList($fieldName, $conf, $this->table);
@@ -678,51 +679,51 @@ class QueryGenerator {
                                case 'files':
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       if ($conf['comparison'] == 68 || $conf['comparison'] == 69) {
-                                               $lineHTML[] = '<select class="form-control" name="' . $this->name . $subscript . '[inputValue]' . '[]" style="vertical-align:top;" size="5" multiple>';
+                                       if ($conf['comparison'] === 68 || $conf['comparison'] === 69) {
+                                               $lineHTML[] = '<select class="form-control" name="' . $fieldPrefix . '[inputValue]' . '[]" multiple="multiple">';
                                        } else {
-                                               $lineHTML[] = '<select class="form-control" name="' . $this->name . $subscript . '[inputValue]' . '" style="vertical-align:top;" onChange="submit();">';
+                                               $lineHTML[] = '<select class="form-control t3js-submit-change" name="' . $fieldPrefix . '[inputValue]' . '">';
                                        }
                                        $lineHTML[] = '<option value=""></option>' . $this->makeOptionList($fieldName, $conf, $this->table);
                                        $lineHTML[] = '</select>';
-                                       if ($conf['comparison'] == 66 || $conf['comparison'] == 67) {
-                                               $lineHTML[] = ' + <input class="form-control" type="text" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $this->name . $subscript . '[inputValue1]' . '">';
+                                       if ($conf['comparison'] === 66 || $conf['comparison'] === 67) {
+                                               $lineHTML[] = ' + <input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $fieldPrefix . '[inputValue1]' . '">';
                                        }
                                        $lineHTML[] = '</div>';
                                        break;
                                case 'boolean':
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       $lineHTML[] = '<input type="hidden" value="1" name="' . $this->name . $subscript . '[inputValue]' . '">';
+                                       $lineHTML[] = '<input type="hidden" value="1" name="' . $fieldPrefix . '[inputValue]' . '">';
                                        $lineHTML[] = '</div>';
                                        break;
                                default:
                                        $lineHTML[] = '<div class="form-inline">';
                                        $lineHTML[] = $this->makeComparisonSelector($subscript, $fieldName, $conf);
-                                       if ($conf['comparison'] == 37 || $conf['comparison'] == 36) {
+                                       if ($conf['comparison'] === 37 || $conf['comparison'] === 36) {
                                                // between:
-                                               $lineHTML[] = '<input class="form-control" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
-                                               $lineHTML[] = '<input class="form-control" type="text" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $this->name . $subscript . '[inputValue1]' . '">';
+                                               $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $fieldPrefix . '[inputValue]' . '">';
+                                               $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue1']) . '" name="' . $fieldPrefix . '[inputValue1]' . '">';
                                        } else {
-                                               $lineHTML[] = '<input class="form-control" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $this->name . $subscript . '[inputValue]' . '">';
+                                               $lineHTML[] = '<input class="form-control t3js-clearable" type="text" value="' . htmlspecialchars($conf['inputValue']) . '" name="' . $fieldPrefix . '[inputValue]' . '">';
                                        }
                                        $lineHTML[] = '</div>';
                        }
                        if ($fieldType !== 'ignore') {
                                $lineHTML[] = '<div class="btn-group action-button-group">';
                                $lineHTML[] = $this->updateIcon();
-                               if ($loopcount) {
-                                       $lineHTML[] = '<button class="btn btn-default" title="Remove condition" name="qG_del' . $subscript . '"><i class="fa fa-trash fa-fw"></i></button>';
+                               if ($loopCount) {
+                                       $lineHTML[] = '<button class="btn btn-default" title="Remove condition" name="qG_del' . htmlspecialchars($subscript) . '"><i class="fa fa-trash fa-fw"></i></button>';
                                }
-                               $lineHTML[] = '<button class="btn btn-default" title="Add condition" name="qG_ins' . $subscript . '"><i class="fa fa-plus fa-fw"></i></button>';
+                               $lineHTML[] = '<button class="btn btn-default" title="Add condition" name="qG_ins' . htmlspecialchars($subscript) . '"><i class="fa fa-plus fa-fw"></i></button>';
                                if ($c != 0) {
-                                       $lineHTML[] = '<button class="btn btn-default" title="Move up" name="qG_up' . $subscript . '"><i class="fa fa-chevron-up fa-fw"></i></button>';
+                                       $lineHTML[] = '<button class="btn btn-default" title="Move up" name="qG_up' . htmlspecialchars($subscript) . '"><i class="fa fa-chevron-up fa-fw"></i></button>';
                                }
                                if ($c != 0 && $fieldType != 'newlevel') {
-                                       $lineHTML[] = '<button class="btn btn-default" title="New level" name="qG_nl' . $subscript . '"><i class="fa fa-chevron-right fa-fw"></i></button>';
+                                       $lineHTML[] = '<button class="btn btn-default" title="New level" name="qG_nl' . htmlspecialchars($subscript) . '"><i class="fa fa-chevron-right fa-fw"></i></button>';
                                }
-                               if ($fieldType == 'newlevel') {
-                                       $lineHTML[] = '<button class="btn btn-default" title="Collapse new level" name="qG_remnl' . $subscript . '"><i class="fa fa-chevron-left fa-fw"></i></button>';
+                               if ($fieldType === 'newlevel') {
+                                       $lineHTML[] = '<button class="btn btn-default" title="Collapse new level" name="qG_remnl' . htmlspecialchars($subscript) . '"><i class="fa fa-chevron-left fa-fw"></i></button>';
                                }
                                $lineHTML[] = '</div>';
                                $codeArr[$arrCount]['html'] = implode(LF, $lineHTML);
@@ -730,7 +731,7 @@ class QueryGenerator {
                                $arrCount++;
                                $c++;
                        }
-                       $loopcount = 1;
+                       $loopCount = 1;
                }
                $this->queryConfig = $queryConfig;
                return $codeArr;
@@ -744,12 +745,13 @@ class QueryGenerator {
         * @return string
         */
        protected function makeComparisonSelector($subscript, $fieldName, $conf) {
+               $fieldPrefix = $this->name . $subscript;
                $lineHTML = array();
-               $lineHTML[] = $this->mkTypeSelect($this->name . $subscript . '[type]', $fieldName);
+               $lineHTML[] = $this->mkTypeSelect($fieldPrefix . '[type]', $fieldName);
                $lineHTML[] = ' <div class="input-group">';
-               $lineHTML[] = $this->mkCompSelect($this->name . $subscript . '[comparison]', $conf['comparison'], $conf['negate'] ? 1 : 0);
+               $lineHTML[] = $this->mkCompSelect($fieldPrefix . '[comparison]', $conf['comparison'], $conf['negate'] ? 1 : 0);
                $lineHTML[] = ' <div class="input-group-addon">';
-               $lineHTML[] = '         <input type="checkbox" class="checkbox"' . ($conf['negate'] ? ' checked' : '') . ' name="' . $this->name . $subscript . '[negate]' . '" onClick="submit();">';
+               $lineHTML[] = '         <input type="checkbox" class="checkbox t3js-submit-click"' . ($conf['negate'] ? ' checked' : '') . ' name="' . htmlspecialchars($fieldPrefix) . '[negate]' . '">';
                $lineHTML[] = ' </div>';
                $lineHTML[] = ' </div>';
                return implode(LF, $lineHTML);
@@ -767,21 +769,21 @@ class QueryGenerator {
                $out = array();
                $fieldSetup = $this->fields[$fieldName];
                $languageService = $this->getLanguageService();
-               if ($fieldSetup['type'] == 'files') {
-                       if ($conf['comparison'] == 66 || $conf['comparison'] == 67) {
+               if ($fieldSetup['type'] === 'files') {
+                       if ($conf['comparison'] === 66 || $conf['comparison'] === 67) {
                                $fileExtArray = explode(',', $fieldSetup['allowed']);
                                natcasesort($fileExtArray);
                                foreach ($fileExtArray as $fileExt) {
                                        if (GeneralUtility::inList($conf['inputValue'], $fileExt)) {
-                                               $out[] = '<option value="' . $fileExt . '" selected>.' . $fileExt . '</option>';
+                                               $out[] = '<option value="' . htmlspecialchars($fileExt) . '" selected>.' . htmlspecialchars($fileExt) . '</option>';
                                        } else {
-                                               $out[] = '<option value="' . $fileExt . '">.' . $fileExt . '</option>';
+                                               $out[] = '<option value="' . htmlspecialchars($fileExt) . '">.' . htmlspecialchars($fileExt) . '</option>';
                                        }
                                }
                        }
                        $d = dir(PATH_site . $fieldSetup['uploadfolder']);
                        while (FALSE !== ($entry = $d->read())) {
-                               if ($entry == '.' || $entry == '..') {
+                               if ($entry === '.' || $entry === '..') {
                                        continue;
                                }
                                $fileArray[] = $entry;
@@ -790,55 +792,55 @@ class QueryGenerator {
                        natcasesort($fileArray);
                        foreach ($fileArray as $fileName) {
                                if (GeneralUtility::inList($conf['inputValue'], $fileName)) {
-                                       $out[] = '<option value="' . $fileName . '" selected>' . $fileName . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($fileName) . '" selected>' . htmlspecialchars($fileName) . '</option>';
                                } else {
-                                       $out[] = '<option value="' . $fileName . '">' . $fileName . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($fileName) . '">' . htmlspecialchars($fileName) . '</option>';
                                }
                        }
                }
-               if ($fieldSetup['type'] == 'multiple') {
+               if ($fieldSetup['type'] === 'multiple') {
                        foreach ($fieldSetup['items'] as $key => $val) {
-                               if (substr($val[0], 0, 4) == 'LLL:') {
+                               if (substr($val[0], 0, 4) === 'LLL:') {
                                        $value = $languageService->sL($val[0]);
                                } else {
                                        $value = $val[0];
                                }
                                if (GeneralUtility::inList($conf['inputValue'], $val[1])) {
-                                       $out[] = '<option value="' . $val[1] . '" selected>' . $value . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($val[1]) . '" selected>' . htmlspecialchars($value) . '</option>';
                                } else {
-                                       $out[] = '<option value="' . $val[1] . '">' . $value . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($val[1]) . '">' . htmlspecialchars($value) . '</option>';
                                }
                        }
                }
-               if ($fieldSetup['type'] == 'binary') {
+               if ($fieldSetup['type'] === 'binary') {
                        foreach ($fieldSetup['items'] as $key => $val) {
-                               if (substr($val[0], 0, 4) == 'LLL:') {
+                               if (substr($val[0], 0, 4) === 'LLL:') {
                                        $value = $languageService->sL($val[0]);
                                } else {
                                        $value = $val[0];
                                }
                                if (GeneralUtility::inList($conf['inputValue'], pow(2, $key))) {
-                                       $out[] = '<option value="' . pow(2, $key) . '" selected>' . $value . '</option>';
+                                       $out[] = '<option value="' . pow(2, $key) . '" selected>' . htmlspecialchars($value) . '</option>';
                                } else {
-                                       $out[] = '<option value="' . pow(2, $key) . '">' . $value . '</option>';
+                                       $out[] = '<option value="' . pow(2, $key) . '">' . htmlspecialchars($value) . '</option>';
                                }
                        }
                }
-               if ($fieldSetup['type'] == 'relation') {
+               if ($fieldSetup['type'] === 'relation') {
                        $databaseConnection = $this->getDatabaseConnection();
                        $useTablePrefix = 0;
                        $dontPrefixFirstTable = 0;
                        if ($fieldSetup['items']) {
                                foreach ($fieldSetup['items'] as $key => $val) {
-                                       if (substr($val[0], 0, 4) == 'LLL:') {
+                                       if (substr($val[0], 0, 4) === 'LLL:') {
                                                $value = $languageService->sL($val[0]);
                                        } else {
                                                $value = $val[0];
                                        }
                                        if (GeneralUtility::inList($conf['inputValue'], $val[1])) {
-                                               $out[] = '<option value="' . $val[1] . '" selected>' . $value . '</option>';
+                                               $out[] = '<option value="' . htmlspecialchars($val[1]) . '" selected>' . htmlspecialchars($value) . '</option>';
                                        } else {
-                                               $out[] = '<option value="' . $val[1] . '">' . $value . '</option>';
+                                               $out[] = '<option value="' . htmlspecialchars($val[1]) . '">' . htmlspecialchars($value) . '</option>';
                                        }
                                }
                        }
@@ -880,8 +882,12 @@ class QueryGenerator {
                        $tablePrefix = '';
                        $backendUserAuthentication = $this->getBackendUserAuthentication();
                        $module = $this->getModule();
+                       $outArray = array();
+                       $labelFieldSelect = array();
                        foreach ($from_table_Arr as $from_table) {
-                               if ($useTablePrefix && !$dontPrefixFirstTable && $counter != 1 || $counter == 1) {
+                               $useSelectLabels = FALSE;
+                               $useAltSelectLabels = FALSE;
+                               if ($useTablePrefix && !$dontPrefixFirstTable && $counter != 1 || $counter === 1) {
                                        $tablePrefix = $from_table . '_';
                                }
                                $counter = 1;
@@ -890,23 +896,23 @@ class QueryGenerator {
                                        $altLabelField = $GLOBALS['TCA'][$from_table]['ctrl']['label_alt'];
                                        if ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items']) {
                                                foreach ($GLOBALS['TCA'][$from_table]['columns'][$labelField]['config']['items'] as $labelArray) {
-                                                       if (substr($labelArray[0], 0, 4) == 'LLL:') {
+                                                       if (substr($labelArray[0], 0, 4) === 'LLL:') {
                                                                $labelFieldSelect[$labelArray[1]] = $languageService->sL($labelArray[0]);
                                                        } else {
                                                                $labelFieldSelect[$labelArray[1]] = $labelArray[0];
                                                        }
                                                }
-                                               $useSelectLabels = 1;
+                                               $useSelectLabels = TRUE;
                                        }
                                        if ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items']) {
                                                foreach ($GLOBALS['TCA'][$from_table]['columns'][$altLabelField]['config']['items'] as $altLabelArray) {
-                                                       if (substr($altLabelArray[0], 0, 4) == 'LLL:') {
+                                                       if (substr($altLabelArray[0], 0, 4) === 'LLL:') {
                                                                $altLabelFieldSelect[$altLabelArray[1]] = $languageService->sL($altLabelArray[0]);
                                                        } else {
                                                                $altLabelFieldSelect[$altLabelArray[1]] = $altLabelArray[0];
                                                        }
                                                }
-                                               $useAltSelectLabels = 1;
+                                               $useAltSelectLabels = TRUE;
                                        }
                                        $altLabelFieldSelect = $altLabelField ? ',' . $altLabelField : '';
                                        $select_fields = 'uid,' . $labelField . $altLabelFieldSelect;
@@ -920,7 +926,7 @@ class QueryGenerator {
                                                        }
                                                        $webMountPageTree .= $webMountPageTreePrefix . $this->getTreeList($val, 999, ($begin = 0), $perms_clause);
                                                }
-                                               if ($from_table == 'pages') {
+                                               if ($from_table === 'pages') {
                                                        $where_clause = 'uid IN (' . $webMountPageTree . ') ';
                                                        if (!$module->MOD_SETTINGS['show_deleted']) {
                                                                $where_clause .= BackendUtility::deleteClause($from_table) . ' AND' . $perms_clause;
@@ -938,15 +944,14 @@ class QueryGenerator {
                                                }
                                        }
                                        $orderBy = 'uid';
-                                       // @TODO: $this->tableArray is never set!?!
                                        if (!$this->tableArray[$from_table]) {
                                                $res = $databaseConnection->exec_SELECTquery($select_fields, $from_table, $where_clause, ($groupBy = ''), $orderBy, ($limit = ''));
-                                       }
-                                       if ($res) {
-                                               while ($row = $databaseConnection->sql_fetch_assoc($res)) {
-                                                       $this->tableArray[$from_table][] = $row;
+                                               if ($res) {
+                                                       while ($row = $databaseConnection->sql_fetch_assoc($res)) {
+                                                               $this->tableArray[$from_table][] = $row;
+                                                       }
+                                                       $databaseConnection->sql_free_result($res);
                                                }
-                                               $databaseConnection->sql_free_result($res);
                                        }
                                        foreach ($this->tableArray[$from_table] as $key => $val) {
                                                if ($useSelectLabels) {
@@ -966,9 +971,9 @@ class QueryGenerator {
                        }
                        foreach ($outArray as $key2 => $val2) {
                                if (GeneralUtility::inList($conf['inputValue'], $key2)) {
-                                       $out[] = '<option value="' . $key2 . '" selected>[' . $key2 . '] ' . $val2 . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($key2) . '" selected>[' . htmlspecialchars($key2) . '] ' . htmlspecialchars($val2) . '</option>';
                                } else {
-                                       $out[] = '<option value="' . $key2 . '">[' . $key2 . '] ' . $val2 . '</option>';
+                                       $out[] = '<option value="' . htmlspecialchars($key2) . '">[' . htmlspecialchars($key2) . '] ' . htmlspecialchars($val2) . '</option>';
                                }
                        }
                }
@@ -993,9 +998,9 @@ class QueryGenerator {
                        $out[] = $v['html'];
 
                        if ($this->enableQueryParts) {
-                               $out[] = '<div class="' . $indent . '">';
+                               $out[] = '<pre>';
                                $out[] = htmlspecialchars($v['query']);
-                               $out[] = '</div>';
+                               $out[] = '</pre>';
                        }
                        if (is_array($v['sub'])) {
                                $out[] = '<div class="' . $indent . '">';
@@ -1032,12 +1037,12 @@ class QueryGenerator {
        public function mkOperatorSelect($name, $op, $draw, $submit) {
                $out = array();
                if ($draw) {
-                       $out[] = '<select class="form-control from-control-operator" name="' . $name . '[operator]"' . ($submit ? ' onChange="submit();"' : '') . '>';
-                       $out[] = '      <option value="AND"' . (!$op || $op == 'AND' ? ' selected' : '') . '>' . $this->lang['AND'] . '</option>';
-                       $out[] = '      <option value="OR"' . ($op == 'OR' ? ' selected' : '') . '>' . $this->lang['OR'] . '</option>';
+                       $out[] = '<select class="form-control from-control-operator' . ($submit ? ' t3js-submit-change' : '') . '" name="' . htmlspecialchars($name) . '[operator]">';
+                       $out[] = '      <option value="AND"' . (!$op || $op === 'AND' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['AND']) . '</option>';
+                       $out[] = '      <option value="OR"' . ($op === 'OR' ? ' selected' : '') . '>' . htmlspecialchars($this->lang['OR']) . '</option>';
                        $out[] = '</select>';
                } else {
-                       $out[] = '<input type="hidden" value="' . $op . '" name="' . $name . '[operator]">';
+                       $out[] = '<input type="hidden" value="' . htmlspecialchars($op) . '" name="' . htmlspecialchars($name) . '[operator]">';
                }
                return implode(LF, $out);
        }
@@ -1052,12 +1057,12 @@ class QueryGenerator {
         */
        public function mkTypeSelect($name, $fieldName, $prepend = 'FIELD_') {
                $out = array();
-               $out[] = '<select class="form-control" name="' . $name . '" onChange="submit();">';
+               $out[] = '<select class="form-control t3js-submit-change" name="' . htmlspecialchars($name) . '">';
                $out[] = '<option value=""></option>';
                foreach ($this->fields as $key => $value) {
                        if (!$value['exclude'] || $this->getBackendUserAuthentication()->check('non_exclude_fields', $this->table . ':' . $key)) {
                                $label = $this->fields[$key]['label'];
-                               $out[] = '<option value="' . $prepend . $key . '"' . ($key == $fieldName ? ' selected' : '') . '>' . $label . '</option>';
+                               $out[] = '<option value="' . htmlspecialchars($prepend . $key) . '"' . ($key === $fieldName ? ' selected' : '') . '>' . htmlspecialchars($label) . '</option>';
                        }
                }
                $out[] = '</select>';
@@ -1094,10 +1099,10 @@ class QueryGenerator {
                $compOffSet = $comparison >> 5;
                $first = -1;
                for ($i = 32 * $compOffSet + $neg; $i < 32 * ($compOffSet + 1); $i += 2) {
-                       if ($first == -1) {
+                       if ($first === -1) {
                                $first = $i;
                        }
-                       if ($i >> 1 == $comparison >> 1) {
+                       if ($i >> 1 === $comparison >> 1) {
                                return $i;
                        }
                }
@@ -1115,17 +1120,18 @@ class QueryGenerator {
                $out = array();
                $out[] = '<div class="input-group">';
                $out[] = '      <div class="input-group-addon">';
-               $out[] = $this->updateIcon('sm');
-               $out[] = '<button onClick="document.forms[0][\'' . $name . '\'].value=\'\';return false;" class="btn btn-sm"><i class="fa fa-trash fa-fw"></i></button>';
+               $out[] = '              <span class="input-group-btn">';
+               $out[] = $this->updateIcon();
+               $out[] = '              </span>';
                $out[] = '      </div>';
-               $out[] = '      <input type="text" class="form-control" value="' . htmlspecialchars($fieldName) . '" name="' . $name . '">';
+               $out[] = '      <input type="text" class="form-control t3js-clearable" value="' . htmlspecialchars($fieldName) . '" name="' . htmlspecialchars($name) . '">';
                $out[] = '</div>';
 
-               $out[] = '<select class="form-control" name="_fieldListDummy" size="5" onChange="document.forms[0][\'' . $name . '\'].value+=\',\'+this.value">';
+               $out[] = '<select class="form-control t3js-addfield" name="_fieldListDummy" size="5" data-field="' . htmlspecialchars($name) . '">';
                foreach ($this->fields as $key => $value) {
                        if (!$value['exclude'] || $this->getBackendUserAuthentication()->check('non_exclude_fields', $this->table . ':' . $key)) {
                                $label = $this->fields[$key]['label'];
-                               $out[] = '<option value="' . $key . '"' . ($key == $fieldName ? ' selected' : '') . '>' . $label . '</option>';
+                               $out[] = '<option value="' . htmlspecialchars($key) . '"' . ($key === $fieldName ? ' selected' : '') . '>' . htmlspecialchars($label) . '</option>';
                        }
                }
                $out[] = '</select>';
@@ -1141,11 +1147,11 @@ class QueryGenerator {
         */
        public function mkTableSelect($name, $cur) {
                $out = array();
-               $out[] = '<select class="form-control" name="' . $name . '" onChange="submit();">';
+               $out[] = '<select class="form-control t3js-submit-change" name="' . $name . '">';
                $out[] = '<option value=""></option>';
                foreach ($GLOBALS['TCA'] as $tN => $value) {
                        if ($this->getBackendUserAuthentication()->check('tables_select', $tN)) {
-                               $out[] = '<option value="' . $tN . '"' . ($tN == $cur ? ' selected' : '') . '>' . $this->getLanguageService()->sl($GLOBALS['TCA'][$tN]['ctrl']['title']) . '</option>';
+                               $out[] = '<option value="' . htmlspecialchars($tN) . '"' . ($tN === $cur ? ' selected' : '') . '>' . htmlspecialchars($this->getLanguageService()->sl($GLOBALS['TCA'][$tN]['ctrl']['title'])) . '</option>';
                        }
                }
                $out[] = '</select>';
@@ -1163,10 +1169,10 @@ class QueryGenerator {
        public function mkCompSelect($name, $comparison, $neg) {
                $compOffSet = $comparison >> 5;
                $out = array();
-               $out[] = '<select class="form-control" name="' . $name . '" onChange="submit();">';
+               $out[] = '<select class="form-control t3js-submit-change" name="' . $name . '">';
                for ($i = 32 * $compOffSet + $neg; $i < 32 * ($compOffSet + 1); $i += 2) {
                        if ($this->lang['comparison'][$i . '_']) {
-                               $out[] = '<option value="' . $i . '"' . ($i >> 1 == $comparison >> 1 ? ' selected' : '') . '>' . $this->lang['comparison'][($i . '_')] . '</option>';
+                               $out[] = '<option value="' . $i . '"' . ($i >> 1 === $comparison >> 1 ? ' selected' : '') . '>' . htmlspecialchars($this->lang['comparison'][($i . '_')]) . '</option>';
                        }
                }
                $out[] = '</select>';
@@ -1202,10 +1208,15 @@ class QueryGenerator {
        /**
         * User definition
         *
-        * @return void
+        * @param string $fieldPrefix
+        * @param array $conf
+        * @param string $fieldName
+        * @param string $fieldType
+        *
+        * @return string
         */
-       public function userDef() {
-
+       public function userDef($fieldPrefix, $conf, $fieldName, $fieldType) {
+               return '';
        }
 
        /**
@@ -1263,14 +1274,14 @@ class QueryGenerator {
                }
                $qsTmp = str_replace('#FIELD#', $prefix . trim(substr($conf['type'], 6)), $this->compSQL[$conf['comparison']]);
                $inputVal = $this->cleanInputVal($conf);
-               if ($conf['comparison'] == 68 || $conf['comparison'] == 69) {
+               if ($conf['comparison'] === 68 || $conf['comparison'] === 69) {
                        $inputVal = explode(',', $inputVal);
                        foreach ($inputVal as $key => $fileName) {
                                $inputVal[$key] = '\'' . $fileName . '\'';
                        }
                        $inputVal = implode(',', $inputVal);
                        $qsTmp = str_replace('#VALUE#', $inputVal, $qsTmp);
-               } elseif ($conf['comparison'] == 162 || $conf['comparison'] == 163) {
+               } elseif ($conf['comparison'] === 162 || $conf['comparison'] === 163) {
                        $inputValArray = explode(',', $inputVal);
                        $inputVal = 0;
                        foreach ($inputValArray as $fileName) {
@@ -1280,7 +1291,7 @@ class QueryGenerator {
                } else {
                        $qsTmp = str_replace('#VALUE#', $databaseConnection->quoteStr($inputVal, $this->table), $qsTmp);
                }
-               if ($conf['comparison'] == 37 || $conf['comparison'] == 36 || $conf['comparison'] == 66 || $conf['comparison'] == 67 || $conf['comparison'] == 100 || $conf['comparison'] == 101) {
+               if ($conf['comparison'] === 37 || $conf['comparison'] === 36 || $conf['comparison'] === 66 || $conf['comparison'] === 67 || $conf['comparison'] === 100 || $conf['comparison'] === 101) {
                        // between:
                        $inputVal = $this->cleanInputVal($conf, '1');
                        $qsTmp = str_replace('#VALUE1#', $databaseConnection->quoteStr($inputVal, $this->table), $qsTmp);
@@ -1297,12 +1308,12 @@ class QueryGenerator {
         * @return string
         */
        public function cleanInputVal($conf, $suffix = '') {
-               if ($conf['comparison'] >> 5 == 0 || ($conf['comparison'] == 32 || $conf['comparison'] == 33 || $conf['comparison'] == 64 || $conf['comparison'] == 65 || $conf['comparison'] == 66 || $conf['comparison'] == 67 || $conf['comparison'] == 96 || $conf['comparison'] == 97)) {
+               if ($conf['comparison'] >> 5 === 0 || ($conf['comparison'] === 32 || $conf['comparison'] === 33 || $conf['comparison'] === 64 || $conf['comparison'] === 65 || $conf['comparison'] === 66 || $conf['comparison'] === 67 || $conf['comparison'] === 96 || $conf['comparison'] === 97)) {
                        $inputVal = $conf['inputValue' . $suffix];
-               } elseif ($conf['comparison'] == 39 || $conf['comparison'] == 38) {
+               } elseif ($conf['comparison'] === 39 || $conf['comparison'] === 38) {
                        // in list:
                        $inputVal = implode(',', GeneralUtility::intExplode(',', $conf['inputValue' . $suffix]));
-               } elseif ($conf['comparison'] == 68 || $conf['comparison'] == 69 || $conf['comparison'] == 162 || $conf['comparison'] == 163) {
+               } elseif ($conf['comparison'] === 68 || $conf['comparison'] === 69 || $conf['comparison'] === 162 || $conf['comparison'] === 163) {
                        // in list:
                        if (is_array($conf['inputValue' . $suffix])) {
                                $inputVal = implode(',', $conf['inputValue' . $suffix]);
@@ -1331,12 +1342,10 @@ class QueryGenerator {
        /**
         * Update icon
         *
-        * @param string $buttonType the bootstrap appendix (default, sm, etc.)
-        *
         * @return string
         */
-       public function updateIcon($buttonType = 'default') {
-               return '<button class="btn btn-' . htmlspecialchars($buttonType) . '" title="Update" name="just_update"><i class="fa fa-refresh fa-fw"></i></button>';
+       public function updateIcon() {
+               return '<button class="btn btn-default" title="Update" name="just_update"><i class="fa fa-refresh fa-fw"></i></button>';
        }
 
        /**
@@ -1446,7 +1455,9 @@ class QueryGenerator {
                                $limit = array();
                                $limit[] = '<div class="input-group">';
                                $limit[] = '    <div class="input-group-addon">';
-                               $limit[] =                      $this->updateIcon('sm');
+                               $limit[] = '            <span class="input-group-btn">';
+                               $limit[] = $this->updateIcon();
+                               $limit[] = '            </span>';
                                $limit[] = '    </div>';
                                $limit[] = '    <input type="text" class="form-control" value="' . htmlspecialchars($this->extFieldLists['queryLimit']) . '" name="SET[queryLimit]" id="queryLimit">';
                                $limit[] = '</div>';
@@ -1456,7 +1467,7 @@ class QueryGenerator {
                                $nextButton = '';
 
                                if ($this->limitBegin) {
-                                       $prevButton = '<input type="button" class="btn btn-default" value="previous ' . $this->limitLength . '" onclick=\'document.getElementById("queryLimit").value="' . $prevLimit . ',' . $this->limitLength . '";document.forms[0].submit();\'>';
+                                       $prevButton = '<input type="button" class="btn btn-default" value="previous ' . htmlspecialchars($this->limitLength) . '" data-value="' . htmlspecialchars($prevLimit . ',' . $this->limitLength) . '">';
                                }
                                if (!$this->limitLength) {
                                        $this->limitLength = 100;
@@ -1467,7 +1478,7 @@ class QueryGenerator {
                                        $nextLimit = 0;
                                }
                                if ($nextLimit) {
-                                       $nextButton = '<input type="button" class="btn btn-default" value="next ' . $this->limitLength . '" onclick=\'document.getElementById("queryLimit").value="' . $nextLimit . ',' . $this->limitLength . '";document.forms[0].submit();\'>';
+                                       $nextButton = '<input type="button" class="btn btn-default" value="next ' . htmlspecialchars($this->limitLength) . '" data-value="' . htmlspecialchars($nextLimit . ',' . $this->limitLength) . '">';
                                }
 
                                $out[] = '<div class="form-group form-group-with-button-addon">';
@@ -1475,15 +1486,15 @@ class QueryGenerator {
                                $out[] = '      <div class="form-inline">';
                                $out[] =                implode(LF, $limit);
                                $out[] = '              <div class="input-group">';
-                               $out[] = '                      <div class="btn-group">';
+                               $out[] = '                      <div class="btn-group t3js-limit-submit">';
                                $out[] =                                $prevButton;
                                $out[] =                                $nextButton;
                                $out[] = '                      </div>';
-                               $out[] = '                      <div class="btn-group">';
-                               $out[] = '                              <input type="button" class="btn btn-default" value="10" onclick=\'document.getElementById("queryLimit").value="10";document.forms[0].submit();\'>';
-                               $out[] = '                              <input type="button" class="btn btn-default" value="20" onclick=\'document.getElementById("queryLimit").value="20";document.forms[0].submit();\'>';
-                               $out[] = '                              <input type="button" class="btn btn-default" value="50" onclick=\'document.getElementById("queryLimit").value="50";document.forms[0].submit();\'>';
-                               $out[] = '                              <input type="button" class="btn btn-default" value="100" onclick=\'document.getElementById("queryLimit").value="100";document.forms[0].submit();\'>';
+                               $out[] = '                      <div class="btn-group t3js-limit-submit">';
+                               $out[] = '                              <input type="button" class="btn btn-default" data-value="10" value="10">';
+                               $out[] = '                              <input type="button" class="btn btn-default" data-value="20" value="20">';
+                               $out[] = '                              <input type="button" class="btn btn-default" data-value="50" value="50">';
+                               $out[] = '                              <input type="button" class="btn btn-default" data-value="100" value="100">';
                                $out[] = '                      </div>';
                                $out[] = '              </div>';
                                $out[] = '      </div>';
@@ -1510,7 +1521,7 @@ class QueryGenerator {
                if ($id < 0) {
                        $id = abs($id);
                }
-               if ($begin == 0) {
+               if ($begin === 0) {
                        $theList = $id;
                } else {
                        $theList = '';
@@ -1555,7 +1566,7 @@ class QueryGenerator {
                                }
                                $webMountPageTree .= $webMountPageTreePrefix . $this->getTreeList($val, 999, ($begin = 0), $perms_clause);
                        }
-                       if ($this->table == 'pages') {
+                       if ($this->table === 'pages') {
                                $qString .= ' AND uid IN (' . $webMountPageTree . ')';
                        } else {
                                $qString .= ' AND pid IN (' . $webMountPageTree . ')';
@@ -1574,15 +1585,13 @@ class QueryGenerator {
         *
         * @param string $formname
         * @return string
+        * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
         */
        public function JSbottom($formname) {
+               GeneralUtility::logDeprecatedFunction();
                $out = array();
                if ($this->extJSCODE) {
-                       $out[] = '<script language="javascript" type="text/javascript" src="' . $GLOBALS['BACK_PATH'] . 'sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.evalfield.js"></script>';
-                       $out[] = '<script language="javascript" type="text/javascript" src="' . $GLOBALS['BACK_PATH'] . 'sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.tbe_editor.js"></script>';
                        $out[] = '<script language="javascript" type="text/javascript">';
-                       $out[] = '      TBE_EDITOR.formname = "' . $formname . '"';
-                       $out[] = '      TBE_EDITOR.formnameUENC = "' . rawurlencode($formname) . '"';
                        $out[] = '      ' . $this->extJSCODE;
                        $out[] = '</script>';
                }
@@ -1590,6 +1599,30 @@ class QueryGenerator {
        }
 
        /**
+        * @param string $name the field name
+        * @param int $timestamp the unix timestamp
+        * @param string $type [datetime, date, time, timesec, year]
+        *
+        * @return string
+        */
+       protected function getDateTimePickerField($name, $timestamp, $type) {
+               $dateFormat = $GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat'] ? '%H:%M %m-%d-%Y' : '%H:%M %d-%m-%Y';
+               $value = ($timestamp > 0 ? strftime($dateFormat, $timestamp) : '');
+               $id = uniqid('dt_');
+               $html = array();
+               $html[] = '<div class="input-group" id="' . $id . '-wrapper">';
+               $html[] = '             <input name="' . htmlspecialchars($name) . '_hr" value="' . $value . '" class="form-control t3js-datetimepicker t3js-clearable" data-date-type="' . htmlspecialchars($type) . '" data-date-offset="0" type="text" id="' . $id . '">';
+               $html[] = '             <input name="' . htmlspecialchars($name) . '" value="' . (int)$timestamp . '" type="hidden">';
+               $html[] = '             <span class="input-group-btn">';
+               $html[] = '                     <label class="btn btn-default" for="' . $id . '">';
+               $html[] = '                             <span class="fa fa-calendar"></span>';
+               $html[] = '                     </label>';
+               $html[] = '     </span>';
+               $html[] = '</div>';
+               return implode(LF, $html);
+       }
+
+       /**
         * Sets the current name of the input form.
         *
         * @param string $formName The name of the form.
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-67790-DeprecateQueryGeneratorJSbottom.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-67790-DeprecateQueryGeneratorJSbottom.rst
new file mode 100644 (file)
index 0000000..8a19a0c
--- /dev/null
@@ -0,0 +1,26 @@
+==========================================================
+Deprecation: #67790 - Deprecate QueryGenerator::JSbottom()
+==========================================================
+
+Description
+===========
+
+The method ``QueryGenerator::JSbottom()``, which was used to append JavaScript code, has been marked for deprecation.
+
+
+Impact
+======
+
+All calls to the PHP method will throw a deprecation warning.
+
+
+Affected Installations
+======================
+
+Instances which make use of ``QueryGenerator::JSbottom()``.
+
+
+Migration
+=========
+
+No migration, use requireJS module and register the module through pageRenderer.
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator.js b/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator.js
new file mode 100644 (file)
index 0000000..ba70c78
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * This module handle the QueryGenerator forms.
+ */
+define('TYPO3/CMS/Core/QueryGenerator', ['jquery', 'TYPO3/CMS/Backend/DateTimePicker', 'TYPO3/CMS/Backend/jquery.clearable'], function ($) {
+
+       /**
+        * The QueryGenerator AMD module
+        *
+        * @type {{form: null, limitField: null}}
+        */
+       var QueryGenerator = {
+               form: null,
+               limitField: null
+       };
+
+       /**
+        * Initialize the QueryGenerator object
+        */
+       QueryGenerator.initialize = function() {
+               QueryGenerator.form = $('form[name="queryform"]');
+               QueryGenerator.limitField = $('#queryLimit');
+               QueryGenerator.form.on('click', '.t3js-submit-click', function(e) {
+                       e.preventDefault();
+                       QueryGenerator.doSubmit();
+               });
+               QueryGenerator.form.on('change', '.t3js-submit-change', function(e) {
+                       e.preventDefault();
+                       QueryGenerator.doSubmit();
+               });
+               QueryGenerator.form.on('click', '.t3js-limit-submit button', function(e) {
+                       e.preventDefault();
+                       QueryGenerator.setLimit($(this).data('value'));
+                       QueryGenerator.doSubmit();
+               });
+               QueryGenerator.form.on('click', '.t3js-addfield', function(e) {
+                       e.preventDefault();
+                       QueryGenerator.addValueToField($(this).data('field'), $(this).val());
+               });
+               QueryGenerator.form.find('.t3js-clearable').clearable({
+                       onClear: function() {
+                               QueryGenerator.doSubmit();
+                       }
+               });
+       };
+
+       /**
+        * Submit the form
+        */
+       QueryGenerator.doSubmit = function() {
+               QueryGenerator.form.submit();
+       };
+
+       /**
+        * Set query limit
+        *
+        * @param {string} value
+        */
+       QueryGenerator.setLimit = function(value) {
+               QueryGenerator.limitField.val(value);
+       };
+
+       /**
+        * Add value to text field
+        *
+        * @param {string} field the name of the field
+        * @param {string} value the value to add
+        */
+       QueryGenerator.addValueToField = function(field, value) {
+               var $target = QueryGenerator.form.find('[name="' + field + '"]');
+               var currentValue = $target.val();
+               $target.val(currentValue + ',' + value);
+       };
+
+       // Initialize
+       QueryGenerator.initialize();
+       return QueryGenerator;
+});
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.evalfield.js b/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.evalfield.js
deleted file mode 100644 (file)
index e37c3b8..0000000
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Evaluation of TYPO3 form field content, used in QueryGenerator. Do not use elsewhere.
- */
-
-function evalFunc() {
-       this.input = evalFunc_input;
-       this.output = evalFunc_output;
-       this.parseInt = evalFunc_parseInt;
-       this.getNumChars = evalFunc_getNumChars;
-       this.parseDouble = evalFunc_parseDouble;
-       this.noSpace = evalFunc_noSpace;
-       this.getSecs = evalFunc_getSecs;
-       this.getYear = evalFunc_getYear;
-       this.getTimeSecs = evalFunc_getTimeSecs;
-       this.getTime = evalFunc_getTime;
-       this.getDate = evalFunc_getDate;
-       this.getTimestamp = evalFunc_getTimestamp;
-       this.caseSwitch = evalFunc_caseSwitch;
-       this.evalObjValue = evalFunc_evalObjValue;
-       this.outputObjValue = evalFunc_outputObjValue;
-       this.split = evalFunc_splitStr;
-       this.pol = evalFunc_pol;
-       this.convertClientTimestampToUTC = evalFunc_convertClientTimestampToUTC;
-
-       this.ltrim = evalFunc_ltrim;
-       this.btrim = evalFunc_btrim;
-       var today = new Date();
-       this.lastYear = this.getYear(today);
-       this.lastDate = this.getDate(today);
-       this.lastTime = 0;
-       this.refDate = today;
-       this.isInString = '';
-       this.USmode = 0;
-}
-function evalFunc_pol(foreign, value) {
-       return eval (((foreign=="-")?'-':'')+value);
-}
-function evalFunc_evalObjValue(FObj,value) {
-       var evallist = FObj.evallist;
-       this.isInString = (FObj.is_in) ? ''+FObj.is_in : '';
-       var index=1;
-       var theEvalType = (FObj.evallist) ? this.split(evallist, ",", index) : false;
-       var newValue=value;
-       while (theEvalType) {
-               if (typeof TBE_EDITOR == 'object' && TBE_EDITOR.customEvalFunctions[theEvalType] && typeof TBE_EDITOR.customEvalFunctions[theEvalType] == 'function') {
-                       newValue = TBE_EDITOR.customEvalFunctions[theEvalType](newValue);
-               } else {
-                       newValue = evalFunc.input(theEvalType, newValue);
-               }
-               index++;
-               theEvalType = this.split(evallist, ",", index);
-       }
-       return newValue;
-}
-function evalFunc_outputObjValue(FObj,value) {
-       var evallist = FObj.evallist;
-       var index=1;
-       var theEvalType = this.split(evallist, ",", index);
-       var newValue=value;
-       while (theEvalType) {
-               if (theEvalType != 'required') {
-                       newValue = evalFunc.output(theEvalType, value, FObj);
-               }
-               index++;
-               theEvalType = this.split(evallist, ",", index);
-       }
-       return newValue;
-}
-function evalFunc_caseSwitch(type,inVal) {
-       var theVal = ''+inVal;
-       var newString = '';
-       switch (type) {
-               case "alpha":
-               case "num":
-               case "alphanum":
-               case "alphanum_x":
-                       for (var a=0;a<theVal.length;a++) {
-                               var theChar = theVal.substr(a,1);
-                               var special = (theChar == '_' || theChar == '-');
-                               var alpha = (theChar >= 'a' && theChar <= 'z') || (theChar >= 'A' && theChar <= 'Z');
-                               var num = (theChar>='0' && theChar<='9');
-                               switch(type) {
-                                       case "alphanum":        special=0;              break;
-                                       case "alpha":   num=0; special=0;               break;
-                                       case "num":     alpha=0; special=0;             break;
-                               }
-                               if (alpha || num || theChar==' ' || special) {
-                                       newString+=theChar;
-                               }
-                       }
-               break;
-               case "is_in":
-                       if (this.isInString) {
-                               for (var a=0;a<theVal.length;a++) {
-                                       var theChar = theVal.substr(a,1);
-                                       if (this.isInString.indexOf(theChar)!=-1) {
-                                               newString+=theChar;
-                                       }
-                               }
-                       } else {newString = theVal;}
-               break;
-               case "nospace":
-                       newString = this.noSpace(theVal);
-               break;
-               case "upper":
-                       newString = theVal.toUpperCase();
-               break;
-               case "lower":
-                       newString = theVal.toLowerCase();
-               break;
-               default:
-                       return inVal;
-       }
-       return newString;
-}
-function evalFunc_parseInt(value) {
-       var theVal = ''+value;
-       if (!value) {
-               return 0;
-       }
-       for (var a = 0; a < theVal.length; a++) {
-               if (theVal.substr(a,1)!='0') {
-                       return parseInt(theVal.substr(a,theVal.length)) || 0;
-               }
-       }
-       return 0;
-}
-function evalFunc_getNumChars(value) {
-       var theVal = ''+value;
-       if (!value) {
-               return 0;
-       }
-       var outVal="";
-       for (var a = 0; a < theVal.length; a++) {
-               if (theVal.substr(a,1)==parseInt(theVal.substr(a,1))) {
-                       outVal+=theVal.substr(a,1);
-               }
-       }
-       return outVal;
-}
-function evalFunc_parseDouble(value) {
-       var theVal = "" + value;
-       theVal = theVal.replace(/[^0-9,\.-]/g, "");
-       var negative = theVal.substring(0, 1) === '-';
-       theVal = theVal.replace(/-/g, "");
-       theVal = theVal.replace(/,/g, ".");
-       if (theVal.indexOf(".") == -1) {
-               theVal += ".0";
-       }
-       var parts = theVal.split(".");
-       var dec = parts.pop();
-       theVal = Number(parts.join("") + "." + dec);
-       if (negative) {
-           theVal *= -1;
-       }
-       theVal = theVal.toFixed(2);
-
-       return theVal;
-}
-function evalFunc_noSpace(value) {
-       var theVal = ''+value;
-       var newString="";
-       for (var a=0;a<theVal.length;a++) {
-               var theChar = theVal.substr(a,1);
-               if (theChar!=' ') {
-                       newString+=theChar;
-               }
-       }
-       return newString;
-}
-function evalFunc_ltrim(value) {
-       var theVal = ''+value;
-       if (!value) {
-               return '';
-       }
-       for (var a = 0; a < theVal.length; a++) {
-               if (theVal.substr(a,1)!=' ') {
-                       return theVal.substr(a,theVal.length);
-               }
-       }
-       return '';
-}
-function evalFunc_btrim(value) {
-       var theVal = ''+value;
-       if (!value) {
-               return '';
-       }
-       for (var a = theVal.length; a > 0; a--) {
-               if (theVal.substr(a-1,1)!=' ') {
-                       return theVal.substr(0,a);
-               }
-       }
-       return '';
-}
-function evalFunc_splitSingle(value) {
-       var theVal = ''+value;
-       this.values = new Array();
-       this.pointer = 3;
-       this.values[1]=theVal.substr(0,2);
-       this.values[2]=theVal.substr(2,2);
-       this.values[3]=theVal.substr(4,10);
-}
-function evalFunc_split(value) {
-       this.values = new Array();
-       this.valPol = new Array();
-       this.pointer = 0;
-       var numberMode = 0;
-       var theVal = "";
-       value+=" ";
-       for (var a=0;a<value.length;a++) {
-               var theChar = value.substr(a,1);
-               if (theChar<"0" || theChar>"9") {
-                       if (numberMode) {
-                               this.pointer++;
-                               this.values[this.pointer]=theVal;
-                               theVal = "";
-                               numberMode=0;
-                       }
-                       if (theChar=="+" || theChar=="-") {
-                               this.valPol[this.pointer+1] = theChar;
-                       }
-               } else {
-                       theVal+=theChar;
-                       numberMode=1;
-               }
-       }
-}
-function evalFunc_input(type,inVal) {
-       if (type=="md5") {
-               return MD5(inVal);
-       }
-       if (type=="trim") {
-               return this.ltrim(this.btrim(inVal));
-       }
-       if (type=="int") {
-               return this.parseInt(inVal);
-       }
-       if (type=="double2") {
-               return this.parseDouble(inVal);
-       }
-
-       var today = new Date();
-       var add=0;
-       var value = this.ltrim(inVal);
-       var values = new evalFunc_split(value);
-       var theCmd = value.substr(0,1);
-       value = this.caseSwitch(type,value);
-       if (value=="") {
-               return "";
-               return 0;       // Why would I ever return a zero??? (20/12/01)
-       }
-       switch (type) {
-               case "datetime":
-                       switch (theCmd) {
-                               case "d":
-                               case "t":
-                               case "n":
-                                       this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               case "+":
-                               case "-":
-                                       if (this.lastTime == 0) {
-                                               this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(today), 0);
-                                       }
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               default:
-                                       var index = value.indexOf(' ');
-                                       if (index!=-1) {
-                                               var dateVal = this.input("date",value.substr(index,value.length));
-                                                       // set refDate so that evalFunc_input on time will work with correct DST information
-                                               this.refDate = new Date(dateVal*1000);
-                                               this.lastTime = dateVal + this.input("time",value.substr(0,index));
-                                       } else  {
-                                                       // only date, no time
-                                               this.lastTime = this.input("date", value);
-                                       }
-                       }
-                       this.lastTime+=add*24*60*60;
-                       return this.lastTime;
-               break;
-               case "year":
-                       switch (theCmd) {
-                               case "d":
-                               case "t":
-                               case "n":
-                                       this.lastYear = this.getYear(today);
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               case "+":
-                               case "-":
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               default:
-                                       if (values.valPol[2]) {
-                                               add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-                                       }
-                                       var year = (values.values[1])?this.parseInt(values.values[1]):this.getYear(today);
-                                       if ((year >= 0 && year < 38) || (year >= 70 && year<100) || (year >= 1902 && year < 2038)) {
-                                               if (year<100) {
-                                                       year = (year<38) ? year+=2000 : year+=1900;
-                                               }
-                                       } else {
-                                               year = this.getYear(today);
-                                       }
-                                       this.lastYear = year;
-                       }
-                       this.lastYear+=add;
-                       return this.lastYear;
-               break;
-               case "date":
-                       switch (theCmd) {
-                               case "d":
-                               case "t":
-                               case "n":
-                                       this.lastDate = this.getTimestamp(today);
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               case "+":
-                               case "-":
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               default:
-                                       var index = 4;
-                                       if (values.valPol[index]) {
-                                               add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
-                                       }
-                                       if (values.values[1] && values.values[1].length>2) {
-                                               if (values.valPol[2]) {
-                                                       add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-                                               }
-                                               var temp = values.values[1];
-                                               values = new evalFunc_splitSingle(temp);
-                                       }
-
-                                       var year = (values.values[3])?this.parseInt(values.values[3]):this.getYear(today);
-                                       if ((year >= 0 && year < 38) || (year >= 70 && year < 100) || (year >= 1902 && year<2038)) {
-                                               if (year<100) {
-                                                       year = (year<38) ? year+=2000 : year+=1900;
-                                               }
-                                       } else {
-                                               year = this.getYear(today);
-                                       }
-                                       var month = (values.values[this.USmode?1:2])?this.parseInt(values.values[this.USmode?1:2]):today.getUTCMonth()+1;
-                                       var day = (values.values[this.USmode?2:1])?this.parseInt(values.values[this.USmode?2:1]):today.getUTCDate();
-
-                                       var theTime = new Date(parseInt(year), parseInt(month)-1, parseInt(day));
-
-                                               // Substract timezone offset from client
-                                       this.lastDate = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 0);
-                       }
-                       this.lastDate+=add*24*60*60;
-                       return this.lastDate;
-               break;
-               case "time":
-               case "timesec":
-                       switch (theCmd) {
-                               case "d":
-                               case "t":
-                               case "n":
-                                       this.lastTime = this.getTimeSecs(today);
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               case "+":
-                               case "-":
-                                       if (this.lastTime == 0) {
-                                               this.lastTime = this.getTimeSecs(today);
-                                       }
-                                       if (values.valPol[1]) {
-                                               add = this.pol(values.valPol[1],this.parseInt(values.values[1]));
-                                       }
-                               break;
-                               default:
-                                       var index = (type=="timesec")?4:3;
-                                       if (values.valPol[index]) {
-                                               add = this.pol(values.valPol[index],this.parseInt(values.values[index]));
-                                       }
-                                       if (values.values[1] && values.values[1].length>2) {
-                                               if (values.valPol[2]) {
-                                                       add = this.pol(values.valPol[2],this.parseInt(values.values[2]));
-                                               }
-                                               var temp = values.values[1];
-                                               values = new evalFunc_splitSingle(temp);
-                                       }
-                                       var sec = (values.values[3])?this.parseInt(values.values[3]):today.getUTCSeconds();
-                                       if (sec > 59)   {sec=59;}
-                                       var min = (values.values[2])?this.parseInt(values.values[2]):today.getUTCMinutes();
-                                       if (min > 59)   {min=59;}
-                                       var hour = (values.values[1])?this.parseInt(values.values[1]):today.getUTCHours();
-                                       if (hour >= 24) {hour=0;}
-
-                                       var theTime = new Date(this.getYear(this.refDate), this.refDate.getUTCMonth(), this.refDate.getUTCDate(), hour, min, ((type=="timesec")?sec:0));
-
-                                               // Substract timezone offset from client
-                                       this.lastTime = this.convertClientTimestampToUTC(this.getTimestamp(theTime), 1);
-                       }
-                       this.lastTime+=add*60;
-                       if (this.lastTime<0) {this.lastTime+=24*60*60;}
-                       return this.lastTime;
-               break;
-               default:
-                       return value;
-       }
-}
-function evalFunc_output(type,value,FObj) {
-       var theString = "";
-       switch (type) {
-               case "date":
-                       if (!parseInt(value))   {return '';}
-                       var theTime = new Date(parseInt(value) * 1000);
-                       if (this.USmode) {
-                               theString = (theTime.getUTCMonth()+1)+'-'+theTime.getUTCDate()+'-'+this.getYear(theTime);
-                       } else {
-                               theString = theTime.getUTCDate()+'-'+(theTime.getUTCMonth()+1)+'-'+this.getYear(theTime);
-                       }
-               break;
-               case "datetime":
-                       if (!parseInt(value))   {return '';}
-                       theString = this.output("time",value)+' '+this.output("date",value);
-               break;
-               case "time":
-               case "timesec":
-                       if (!parseInt(value))   {return '';}
-                       var theTime = new Date(parseInt(value) * 1000);
-                       var h = theTime.getUTCHours();
-                       var m = theTime.getUTCMinutes();
-                       var s = theTime.getUTCSeconds();
-                       theString = h+':'+((m<10)?'0':'')+m + ((type=="timesec")?':'+((s<10)?'0':'')+s:'');
-               break;
-               case "password":
-                       theString = (value)     ? TS.passwordDummy : "";
-               break;
-               case "int":
-                       theString = (FObj.checkbox && value==FObj.checkboxValue)?'':value;
-               break;
-               default:
-                       theString = value;
-       }
-       return theString;
-}
-function evalFunc_getSecs(timeObj) {
-       return timeObj.getUTCSeconds();
-}
-// Seconds since midnight:
-function evalFunc_getTime(timeObj) {
-       return timeObj.getUTCHours() * 60 * 60 + timeObj.getUTCMinutes() * 60 + this.getSecs(timeObj);
-}
-function evalFunc_getYear(timeObj) {
-       return timeObj.getUTCFullYear();
-}
-// Seconds since midnight with client timezone offset:
-function evalFunc_getTimeSecs(timeObj) {
-       return timeObj.getHours()*60*60+timeObj.getMinutes()*60+timeObj.getSeconds();
-}
-function evalFunc_getDate(timeObj) {
-       var theTime = new Date(this.getYear(timeObj), timeObj.getUTCMonth(), timeObj.getUTCDate());
-       return this.getTimestamp(theTime);
-}
-function evalFunc_dummy (evallist,is_in,checkbox,checkboxValue) {
-       this.evallist = evallist;
-       this.is_in = is_in;
-       this.checkboxValue = checkboxValue;
-       this.checkbox = checkbox;
-}
-function evalFunc_splitStr(theStr1, delim, index) {
-       var theStr = ''+theStr1;
-       var lengthOfDelim = delim.length;
-       sPos = -lengthOfDelim;
-       if (index<1) {index=1;}
-       for (a=1; a<index; a++) {
-               sPos = theStr.indexOf(delim, sPos+lengthOfDelim);
-               if (sPos==-1)   {return null;}
-       }
-       ePos = theStr.indexOf(delim, sPos+lengthOfDelim);
-       if(ePos == -1)  {ePos = theStr.length;}
-       return (theStr.substring(sPos+lengthOfDelim,ePos));
-}
-function evalFunc_getTimestamp(timeObj) {
-       return Date.parse(timeObj)/1000;
-}
-
-// Substract timezone offset from client to a timestamp to get UTC-timestamp to be send to server
-function evalFunc_convertClientTimestampToUTC(timestamp, timeonly) {
-       var timeObj = new Date(timestamp*1000);
-       timeObj.setTime((timestamp - timeObj.getTimezoneOffset()*60)*1000);
-       if (timeonly) {
-                       // only seconds since midnight
-               return this.getTime(timeObj);
-       } else  {
-                       // seconds since the "unix-epoch"
-               return this.getTimestamp(timeObj);
-       }
-}
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.tbe_editor.js b/typo3/sysext/core/Resources/Public/JavaScript/QueryGenerator/jsfunc.tbe_editor.js
deleted file mode 100644 (file)
index 4858343..0000000
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-/**
- * Contains JavaScript for TYPO3 Core Form generator, used in QueryGenerator. Do not use elsewhere.
- *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
- * @coauthor   Oliver Hader <oh@inpublica.de>
- */
-
-
-var TBE_EDITOR = {
-       /* Example:
-               elements: {
-                       'data-parentPid-table-uid': {
-                               'field': {
-                                       'range':                [0, 100],
-                                       'rangeImg':             '',
-                                       'required':             true,
-                                       'requiredImg':  ''
-                               }
-                       }
-               },
-       */
-
-       elements: {},
-       nested: {'field':{}, 'level':{}},
-       ignoreElements: [],
-       recentUpdatedElements: {},
-       actionChecks: { submit: [] },
-
-       formname: '',
-       formnameUENC: '',
-       isChanged: 0,
-
-       backPath: '',
-
-       isPalettedoc: null,
-       doSaveFieldName: 0,
-
-       labels: {},
-       images: {
-               req: new Image(),
-               cm: new Image(),
-               sel: new Image(),
-               clear: new Image()
-       },
-
-       clearBeforeSettingFormValueFromBrowseWin: [],
-
-       // Handling of data structures:
-       addElements: function(elements) {
-               TBE_EDITOR.recentUpdatedElements = elements;
-               TBE_EDITOR.elements = $H(TBE_EDITOR.elements).merge(elements).toObject();
-       },
-       addNested: function(elements) {
-               // Merge data structures:
-               if (elements) {
-                       $H(elements).each(function(element) {
-                               var levelMax, i, currentLevel, subLevel;
-                               var nested = element.value;
-                               if (nested.level && nested.level.length) {
-                                               // If the first level is of type 'inline', it could be created by a AJAX request to IRRE.
-                                               // So, try to get the upper levels this dynamic level is nested in:
-                                       if (typeof inline!='undefined' && nested.level[0][0]=='inline') {
-                                               nested.level = inline.findContinuedNestedLevel(nested.level, nested.level[0][1]);
-                                       }
-                                       levelMax = nested.level.length-1;
-                                       for (i=0; i<=levelMax; i++) {
-                                               currentLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i]);
-                                               if (typeof TBE_EDITOR.nested.level[currentLevel] == 'undefined') {
-                                                       TBE_EDITOR.nested.level[currentLevel] = { 'clean': true, 'item': {}, 'sub': {} };
-                                               }
-                                                       // Add next sub level to the current level:
-                                               if (i<levelMax) {
-                                                       subLevel = TBE_EDITOR.getNestedLevelIdent(nested.level[i+1]);
-                                                       TBE_EDITOR.nested.level[currentLevel].sub[subLevel] = true;
-                                                       // Add the current item to the last level in nesting:
-                                               } else {
-                                                       TBE_EDITOR.nested.level[currentLevel].item[element.key] = nested.parts;
-                                               }
-                                       }
-                               }
-                       });
-                               // Merge the nested fields:
-                       TBE_EDITOR.nested.field = $H(TBE_EDITOR.nested.field).merge(elements).toObject();
-               }
-       },
-       removeElement: function(record) {
-               if (TBE_EDITOR.elements && TBE_EDITOR.elements[record]) {
-                               // Inform envolved levels the this record is removed and the missing requirements are resolved:
-                       $H(TBE_EDITOR.elements[record]).each(
-                               function(pair) {
-                                       TBE_EDITOR.notifyNested(record+'['+pair.key+']', true);
-                               }
-                       );
-                       delete(TBE_EDITOR.elements[record]);
-               }
-       },
-       removeElementArray: function(removeStack) {
-               if (removeStack && removeStack.length) {
-                       TBE_EDITOR.ignoreElements = removeStack;
-                       for (var i=removeStack.length; i>=0; i--) {
-                               TBE_EDITOR.removeElement(removeStack[i]);
-                       }
-                       TBE_EDITOR.ignoreElements = [];
-               }
-       },
-       getElement: function(record, field, type) {
-               var result = null;
-               var element;
-
-               if (TBE_EDITOR.elements && TBE_EDITOR.elements[record] && TBE_EDITOR.elements[record][field]) {
-                       element = TBE_EDITOR.elements[record][field];
-                       if (type) {
-                               if (element[type]) result = element;
-                       } else {
-                               result = element;
-                       }
-               }
-
-               return result;
-       },
-       checkElements: function(type, recentUpdated, record, field) {
-               var result = 1;
-               var elementName, elementData, elementRecord, elementField;
-               var source = (recentUpdated ? TBE_EDITOR.recentUpdatedElements : TBE_EDITOR.elements);
-
-               if (TBE_EDITOR.ignoreElements.length && TBE_EDITOR.ignoreElements.indexOf(record)!=-1) {
-                       return result;
-               }
-
-               if (type) {
-                       if (record && field) {
-                               elementName = record+'['+field+']';
-                               elementData = TBE_EDITOR.getElement(record, field, type);
-                               if (elementData) {
-                                       if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
-                                               result = 0;
-                                       }
-                               }
-
-                       } else {
-                               var elementFieldList, elRecIndex, elRecCnt, elFldIndex, elFldCnt;
-                               var elementRecordList = $H(source).keys();
-                               for (elRecIndex=0, elRecCnt=elementRecordList.length; elRecIndex<elRecCnt; elRecIndex++) {
-                                       elementRecord = elementRecordList[elRecIndex];
-                                       elementFieldList = $H(source[elementRecord]).keys();
-                                       for (elFldIndex=0, elFldCnt=elementFieldList.length; elFldIndex<elFldCnt; elFldIndex++) {
-                                               elementField = elementFieldList[elFldIndex];
-                                               elementData = TBE_EDITOR.getElement(elementRecord, elementField, type);
-                                               if (elementData) {
-                                                       elementName = elementRecord+'['+elementField+']';
-                                                       if (!TBE_EDITOR.checkElementByType(type, elementName, elementData, recentUpdated)) {
-                                                               result = 0;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               return result;
-       },
-       checkElementByType: function(type, elementName, elementData, autoNotify) {
-               var form, result = 1;
-
-               if (type) {
-                       if (type == 'required') {
-                               form = document[TBE_EDITOR.formname][elementName];
-                               if (form) {
-                                               // Check if we are within a deleted inline element
-                                       var testNode = $(form.parentNode);
-                                       while(testNode) {
-                                               if (testNode.hasClassName && testNode.hasClassName('inlineIsDeletedRecord')) {
-                                                       return result;
-                                               }
-                                               testNode = $(testNode.parentNode);
-                                       }
-
-                                       var value = form.value;
-                                       if (!value || elementData.additional && elementData.additional.isPositiveNumber && (isNaN(value) || Number(value) <= 0)) {
-                                               result = 0;
-                                               if (autoNotify) {
-                                                       TBE_EDITOR.setImage('req_'+elementData.requiredImg, TBE_EDITOR.images.req);
-                                                       TBE_EDITOR.notifyNested(elementName, false);
-                                               }
-                                       }
-                               }
-                       } else if (type == 'range' && elementData.range) {
-                               var numberOfElements = 0;
-                               form = document[TBE_EDITOR.formname][elementName+'_list'];
-                               if (!form) {
-                                               // special treatment for IRRE fields:
-                                       var tempObj = document[TBE_EDITOR.formname][elementName];
-                                       if (tempObj && (Element.hasClassName(tempObj, 'inlineRecord') || Element.hasClassName(tempObj, 'treeRecord'))) {
-                                               form = tempObj.value ? tempObj.value.split(',') : [];
-                                               numberOfElements = form.length;
-                                       }
-
-                               } else {
-                                               // special treatment for file uploads
-                                       var tempObj = document[TBE_EDITOR.formname][elementName.replace(/^data/, 'data_files') + '[]'];
-                                       numberOfElements = form.length;
-
-                                       if (tempObj && tempObj.type == 'file' && tempObj.value) {
-                                               numberOfElements++; // Add new uploaded file to the number of elements
-                                       }
-                               }
-
-                               if (!TBE_EDITOR.checkRange(numberOfElements, elementData.range[0], elementData.range[1])) {
-                                       result = 0;
-                                       if (autoNotify) {
-                                               TBE_EDITOR.setImage('req_'+elementData.rangeImg, TBE_EDITOR.images.req);
-                                               TBE_EDITOR.notifyNested(elementName, false);
-                                       }
-                               }
-                       }
-               }
-
-               return result;
-       },
-       // Notify tabs and inline levels with nested requiredFields/requiredElements:
-       notifyNested: function(elementName, resolved) {
-               if (TBE_EDITOR.nested.field[elementName]) {
-                       var i, nested, element, fieldLevels, fieldLevelIdent, nestedLevelType, nestedLevelName;
-                       fieldLevels = TBE_EDITOR.nested.field[elementName].level;
-                       TBE_EDITOR.nestedCache = {};
-
-                       for (i=fieldLevels.length-1; i>=0; i--) {
-                               nestedLevelType = fieldLevels[i][0];
-                               nestedLevelName = fieldLevels[i][1];
-                               fieldLevelIdent = TBE_EDITOR.getNestedLevelIdent(fieldLevels[i]);
-                                       // Construct the CSS id strings of the image/icon tags showing the notification:
-                               if (nestedLevelType == 'tab') {
-                                       element = nestedLevelName+'-REQ';
-                               } else if (nestedLevelType == 'inline') {
-                                       element = nestedLevelName+'_req';
-                               } else {
-                                       continue;
-                               }
-                                       // Set the icons:
-                               if (resolved) {
-                                       if (TBE_EDITOR.checkNested(fieldLevelIdent)) {
-                                               TBE_EDITOR.setImage(element, TBE_EDITOR.images.clear);
-                                       } else {
-                                               break;
-                                       }
-                               } else {
-                                       if (TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[fieldLevelIdent]) {
-                                               TBE_EDITOR.nested.level[fieldLevelIdent].clean = false;
-                                       }
-                                       TBE_EDITOR.setImage(element, TBE_EDITOR.images.req);
-                               }
-                       }
-               }
-       },
-       // Check all the input fields on a given level of nesting - if only on is unfilled, the whole level is marked as required:
-       checkNested: function(nestedLevelIdent) {
-               var nestedLevel, isClean;
-               if (nestedLevelIdent && TBE_EDITOR.nested.level && TBE_EDITOR.nested.level[nestedLevelIdent]) {
-                       nestedLevel = TBE_EDITOR.nested.level[nestedLevelIdent];
-                       if (!nestedLevel.clean) {
-                               if (typeof nestedLevel.item == 'object') {
-                                       $H(nestedLevel.item).each(
-                                               function(pair) {
-                                                       if (isClean || typeof isClean == 'undefined') {
-                                                               isClean = (
-                                                                       TBE_EDITOR.checkElements('required', false, pair.value[0], pair.value[1]) &&
-                                                                       TBE_EDITOR.checkElements('range', false, pair.value[0], pair.value[1])
-                                                               );
-                                                       }
-                                               }
-                                       );
-                                       if (typeof isClean != 'undefined' && !isClean) {
-                                               return false;
-                                       }
-                               }
-                               if (typeof nestedLevel.sub == 'object') {
-                                       $H(nestedLevel.sub).each(
-                                               function(pair) {
-                                                       if (isClean || typeof isClean == 'undefined') {
-                                                               isClean = TBE_EDITOR.checkNested(pair.key);
-                                                       }
-                                               }
-                                       );
-                                       if (typeof isClean != 'undefined' && !isClean) {
-                                               return false;
-                                       }
-                               }
-                                       // Store the result, that this level (the fields on this and the sub levels) are clean:
-                               nestedLevel.clean = true;
-                       }
-               }
-               return true;
-       },
-       getNestedLevelIdent: function(level) {
-               return level.join('::');
-       },
-       addActionChecks: function(type, checks) {
-               TBE_EDITOR.actionChecks[type].push(checks);
-       },
-
-       fieldChanged_fName: function(fName,el) {
-               var idx=2;
-               var table = TBE_EDITOR.split(fName, "[", idx);
-               var uid = TBE_EDITOR.split(fName, "[", idx+1);
-               var field = TBE_EDITOR.split(fName, "[", idx+2);
-
-               table = table.substr(0,table.length-1);
-               uid = uid.substr(0,uid.length-1);
-               field = field.substr(0,field.length-1);
-               TBE_EDITOR.fieldChanged(table,uid,field,el);
-       },
-       fieldChanged: function(table,uid,field,el) {
-               var theField = 'data['+table+']['+uid+']['+field+']';
-               var theRecord = 'data['+table+']['+uid+']';
-               TBE_EDITOR.isChanged = 1;
-
-               // modify the "field has changed" info by adding a class to the container element (based on palette or main field)
-               var $formField = TYPO3.jQuery('[name="' + el + '"]');
-               var $paletteField = $formField.closest('.t3js-formengine-palette-field');
-               $paletteField.addClass('has-change');
-
-               // Set required flag:
-               var imgReqObjName = "req_"+table+"_"+uid+"_"+field;
-               if (TBE_EDITOR.getElement(theRecord,field,'required') && document[TBE_EDITOR.formname][theField]) {
-                       if (TBE_EDITOR.checkElements('required', false, theRecord, field)) {
-                               TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
-                               TBE_EDITOR.notifyNested(theField, true);
-                       } else {
-                               TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
-                               TBE_EDITOR.notifyNested(theField, false);
-                       }
-               }
-               if (TBE_EDITOR.getElement(theRecord,field,'range') && document[TBE_EDITOR.formname][theField]) {
-                       if (TBE_EDITOR.checkElements('range', false, theRecord, field)) {
-                               TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.clear);
-                               TBE_EDITOR.notifyNested(theField, true);
-                       } else {
-                               TBE_EDITOR.setImage(imgReqObjName,TBE_EDITOR.images.req);
-                               TBE_EDITOR.notifyNested(theField, false);
-                       }
-               }
-
-               if (TBE_EDITOR.isPalettedoc) { TBE_EDITOR.setOriginalFormFieldValue(theField) };
-       },
-       setOriginalFormFieldValue: function(theField) {
-               if (TBE_EDITOR.isPalettedoc && (TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname] && (TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname][theField]) {
-                       (TBE_EDITOR.isPalettedoc).document[TBE_EDITOR.formname][theField].value = document[TBE_EDITOR.formname][theField].value;
-               }
-       },
-       isFormChanged: function(noAlert) {
-               if (TBE_EDITOR.isChanged && !noAlert && confirm(TBE_EDITOR.labels.fieldsChanged)) {
-                       return 0;
-               }
-               return TBE_EDITOR.isChanged;
-       },
-       checkAndDoSubmit: function(sendAlert) {
-               if (TBE_EDITOR.checkSubmit(sendAlert)) { TBE_EDITOR.submitForm(); }
-       },
-       /**
-        * Checks if the form can be submitted according to any possible restrains like required values, item numbers etc.
-        * Returns true if the form can be submitted, otherwise false (and might issue an alert message, if "sendAlert" is 1)
-        * If "sendAlert" is false, no error message will be shown upon false return value (if "1" then it will).
-        * If "sendAlert" is "-1" then the function will ALWAYS return true regardless of constraints (except if login has expired) - this is used in the case where a form field change requests a form update and where it is accepted that constraints are not observed (form layout might change so other fields are shown...)
-        */
-       checkSubmit: function(sendAlert) {
-               var funcIndex, funcMax, funcRes;
-               var OK=1;
-
-               // $this->additionalJS_submit:
-               if (TBE_EDITOR.actionChecks && TBE_EDITOR.actionChecks.submit) {
-                       for (funcIndex=0, funcMax=TBE_EDITOR.actionChecks.submit.length; funcIndex<funcMax; funcIndex++) {
-                               try {
-                                       eval(TBE_EDITOR.actionChecks.submit[funcIndex]);
-                               } catch(error) {}
-                       }
-               }
-
-               if(!OK) {
-                       if (!confirm(unescape("SYSTEM ERROR: One or more Rich Text Editors on the page could not be contacted. This IS an error, although it should not be regular.\nYou can save the form now by pressing OK, but you will loose the Rich Text Editor content if you do.\n\nPlease report the error to your administrator if it persists."))) {
-                               return false;
-                       } else {
-                               OK = 1;
-                       }
-               }
-               // $reqLinesCheck
-               if (!TBE_EDITOR.checkElements('required', false)) { OK = 0; }
-               // $reqRangeCheck
-               if (!TBE_EDITOR.checkElements('range', false)) { OK = 0; }
-
-               if (OK || sendAlert==-1) {
-                       return true;
-               } else {
-                       if(sendAlert) alert(TBE_EDITOR.labels.fieldsMissing);
-                       return false;
-               }
-       },
-       checkRange: function(numberOfElements, lower, upper) {
-                       // for backwards compatibility, check if we're dealing with an element as first parameter
-               if(typeof numberOfElements == 'object') {
-                       numberOfElements = numberOfElements.length;
-               }
-
-               if (numberOfElements >= lower && numberOfElements <= upper) {
-                       return true;
-               } else {
-                       return false;
-               }
-       },
-       initRequired: function() {
-               // $reqLinesCheck
-               TBE_EDITOR.checkElements('required', true);
-
-               // $reqRangeCheck
-               TBE_EDITOR.checkElements('range', true);
-       },
-       setImage: function(name,image) {
-               var object;
-               if (document[name]) {
-                       object = document[name];
-               } else if (document.getElementById(name)) {
-                       object = document.getElementById(name);
-               }
-               if (object) {
-                       if (typeof image == 'object') {
-                               document[name].src = image.src;
-                       } else {
-                               document[name].src = eval(image+'.src');
-                       }
-               }
-       },
-       submitForm: function() {
-               if (TBE_EDITOR.doSaveFieldName) {
-                       document[TBE_EDITOR.formname][TBE_EDITOR.doSaveFieldName].value=1;
-               }
-               // Set a short timeout to allow other JS processes to complete, in particular those from
-               // EXT:backend/Resources/Public/JavaScript/FormEngine.js (reference: http://forge.typo3.org/issues/58755).
-               // TODO: This should be solved in a better way when this script is refactored.
-               window.setTimeout('document[TBE_EDITOR.formname].submit()', 10);
-       },
-       split: function(theStr1, delim, index) {
-               var theStr = ""+theStr1;
-               var lengthOfDelim = delim.length;
-               sPos = -lengthOfDelim;
-               if (index<1) {index=1;}
-               for (var a=1; a<index; a++) {
-                       sPos = theStr.indexOf(delim, sPos+lengthOfDelim);
-                       if (sPos==-1) { return null; }
-               }
-               ePos = theStr.indexOf(delim, sPos+lengthOfDelim);
-               if(ePos == -1) { ePos = theStr.length; }
-               return (theStr.substring(sPos+lengthOfDelim,ePos));
-       },
-       curSelected: function(theField) {
-               var fObjSel = document[TBE_EDITOR.formname][theField];
-               var retVal="";
-               if (fObjSel) {
-                       if (fObjSel.type=='select-multiple' || fObjSel.type=='select-one') {
-                               var l=fObjSel.length;
-                               for (a=0;a<l;a++) {
-                                       if (fObjSel.options[a].selected==1) {
-                                               retVal+=fObjSel.options[a].value+",";
-                                       }
-                               }
-                       }
-               }
-               return retVal;
-       },
-       rawurlencode: function(str,maxlen) {
-               var output = str;
-               if (maxlen)     output = output.substr(0,200);
-               output = encodeURIComponent(output);
-               return output;
-       },
-       str_replace: function(match,replace,string) {
-               var input = ''+string;
-               var matchStr = ''+match;
-               if (!matchStr) { return string; }
-               var output = '';
-               var pointer=0;
-               var pos = input.indexOf(matchStr);
-               while (pos!=-1) {
-                       output+=''+input.substr(pointer, pos-pointer)+replace;
-                       pointer=pos+matchStr.length;
-                       pos = input.indexOf(match,pos+1);
-               }
-               output+=''+input.substr(pointer);
-               return output;
-       },
-       toggle_display_states: function(id, state_1, state_2) {
-               var node = document.getElementById(id);
-               if (node) {
-                       switch (node.style.display) {
-                               case state_1:
-                                       node.style.display = state_2;
-                                       break;
-                               case state_2:
-                                       node.style.display = state_1;
-                                       break;
-                       }
-               }
-               return false;
-       },
-
-       /**
-        * Determines backend path to be used for e.g. ajax.php
-        * @return string
-        * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8
-        */
-       getBackendPath: function() {
-               if (typeof console != 'undefined') {
-                       console.log('TS.getBackendPath() is deprecated since TYPO3 CMS 7, and will be removed in TYPO3 CMS 8.');
-               }
-               if (TYPO3) {
-                       if (TYPO3.configuration && TYPO3.configuration.PATH_typo3) {
-                               backendPath = TYPO3.configuration.PATH_typo3;
-                       } else if (TYPO3.settings && TYPO3.settings.PATH_typo3) {
-                               backendPath = TYPO3.settings.PATH_typo3;
-                       }
-               }
-               return backendPath;
-       }
-};
-
-function typoSetup     () {
-       this.passwordDummy = '********';
-       this.decimalSign = '.';
-}
-var TS = new typoSetup();
-var evalFunc = new evalFunc();
-
-// backwards compatibility for extensions
-var TBE_EDITOR_setHiddenContent = TBE_EDITOR.setHiddenContent;
-var TBE_EDITOR_isChanged = TBE_EDITOR.isChanged;
-var TBE_EDITOR_fieldChanged_fName = TBE_EDITOR.fieldChanged_fName;
-var TBE_EDITOR_fieldChanged = TBE_EDITOR.fieldChanged;
-var TBE_EDITOR_setOriginalFormFieldValue = TBE_EDITOR.setOriginalFormFieldValue;
-var TBE_EDITOR_isFormChanged = TBE_EDITOR.isFormChanged;
-var TBE_EDITOR_checkAndDoSubmit = TBE_EDITOR.checkAndDoSubmit;
-var TBE_EDITOR_checkSubmit = TBE_EDITOR.checkSubmit;
-var TBE_EDITOR_checkRange = TBE_EDITOR.checkRange;
-var TBE_EDITOR_initRequired = TBE_EDITOR.initRequired;
-var TBE_EDITOR_setImage = TBE_EDITOR.setImage;
-var TBE_EDITOR_submitForm = TBE_EDITOR.submitForm;
-var TBE_EDITOR_split = TBE_EDITOR.split;
-var TBE_EDITOR_curSelected = TBE_EDITOR.curSelected;
-var TBE_EDITOR_rawurlencode = TBE_EDITOR.rawurlencode;
-var TBE_EDITOR_str_replace = TBE_EDITOR.str_replace;
-
-
-var typo3form = {
-       fieldSetNull: function(fieldName, isNull) {
-               if (document[TBE_EDITOR.formname][fieldName]) {
-                       var formFieldItemWrapper = Element.up(document[TBE_EDITOR.formname][fieldName], '.t3js-formengine-field-item');
-
-                       if (isNull) {
-                               formFieldItemWrapper.addClassName('disabled');
-                       } else {
-                               formFieldItemWrapper.removeClassName('disabled');
-                       }
-               }
-       },
-       fieldTogglePlaceholder: function(fieldName, showPlaceholder) {
-               if (!document[TBE_EDITOR.formname][fieldName]) {
-                       return;
-               }
-
-               var formFieldItemWrapper = Element.up(document[TBE_EDITOR.formname][fieldName], '.t3js-formengine-field-item');
-               var placeholder = formFieldItemWrapper.select('.t3js-formengine-placeholder-placeholder')[0];
-               var formField = formFieldItemWrapper.select('.t3js-formengine-placeholder-formfield')[0];
-               if (showPlaceholder) {
-                       placeholder.show();
-                       formField.hide();
-               } else {
-                       placeholder.hide();
-                       formField.show();
-               }
-       },
-       fieldSet: function(theField, evallist, is_in, checkbox, checkboxValue) {
-               var i;
-
-               if (document[TBE_EDITOR.formname][theField]) {
-                       var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-                       var theValue = document[TBE_EDITOR.formname][theField].value;
-                       if (checkbox && theValue==checkboxValue) {
-                               document[TBE_EDITOR.formname][theField+"_hr"].value="";
-                               if (document[TBE_EDITOR.formname][theField+"_cb"])      document[TBE_EDITOR.formname][theField+"_cb"].checked = "";
-                       } else {
-                               document[TBE_EDITOR.formname][theField+"_hr"].value = evalFunc.outputObjValue(theFObj, theValue);
-                               if (document[TBE_EDITOR.formname][theField+"_cb"])      document[TBE_EDITOR.formname][theField+"_cb"].checked = "on";
-                       }
-               }
-       },
-       fieldGet: function(theField, evallist, is_in, checkbox, checkboxValue, checkbox_off, checkSetValue) {
-               if (document[TBE_EDITOR.formname][theField]) {
-                       var theFObj = new evalFunc_dummy (evallist,is_in, checkbox, checkboxValue);
-                       if (checkbox_off) {
-                               if (document[TBE_EDITOR.formname][theField+"_cb"].checked) {
-                                       var split = evallist.split(',');
-                                       for (var i = 0; split.length > i; i++) {
-                                               var el = split[i].replace(/ /g, '');
-                                               if (el == 'datetime' || el == 'date') {
-                                                       var now = new Date();
-                                                       checkSetValue = Date.parse(now)/1000 - now.getTimezoneOffset()*60;
-                                                       break;
-                                               } else if (el == 'time' || el == 'timesec') {
-                                                       checkSetValue = evalFunc_getTimeSecs(new Date());
-                                                       break;
-                                               }
-                                       }
-                                       document[TBE_EDITOR.formname][theField].value=checkSetValue;
-                               } else {
-                                       document[TBE_EDITOR.formname][theField].value=checkboxValue;
-                               }
-                       }else{
-                               document[TBE_EDITOR.formname][theField].value = evalFunc.evalObjValue(theFObj, document[TBE_EDITOR.formname][theField+"_hr"].value);
-                       }
-                       typo3form.fieldSet(theField, evallist, is_in, checkbox, checkboxValue);
-               }
-       }
-};
-
-// backwards compatibility for extensions
-var typo3FormFieldSet = typo3form.fieldSet;
-var typo3FormFieldGet = typo3form.fieldGet;
index 006c019..00b8f6f 100644 (file)
@@ -302,6 +302,7 @@ class DatabaseIntegrityView extends BaseScriptClass {
                $this->view->assign('searchMode', $searchMode);
                switch ($searchMode) {
                        case 'query':
+                               $this->doc->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Core/QueryGenerator');
                                $this->view->assign('queryMaker', $fullsearch->queryMaker());
                                break;
                        case 'raw':
index 3a4a177..01c00d0 100644 (file)
@@ -2,11 +2,17 @@
 // Query-Builder
 //
 .query-builder {
+       .form-inline > .form-control-clearable {
+               display: inline;
+       }
        .form-group-with-button-addon {
                .input-group {
                        margin-bottom: 10px;
                        .input-group-addon {
-                               padding: 2px;
+                               padding: 0 0 0 1px;
+                               .btn-default {
+                                       border: 0;
+                               }
                        }
                }
        }
@@ -18,7 +24,6 @@
                margin: 10px 0;
        }
        .row-group {
-               background-color: @gray-lighter;
                margin: 10px 0;
                padding: 10px;
                border-color: #999;
index 6425259..7c8c333 100644 (file)
@@ -12295,11 +12295,17 @@ iframe {
 .typo3-module-menu-snapped .typo3-module-menu-item-title {
   display: none;
 }
+.query-builder .form-inline > .form-control-clearable {
+  display: inline;
+}
 .query-builder .form-group-with-button-addon .input-group {
   margin-bottom: 10px;
 }
 .query-builder .form-group-with-button-addon .input-group .input-group-addon {
-  padding: 2px;
+  padding: 0 0 0 1px;
+}
+.query-builder .form-group-with-button-addon .input-group .input-group-addon .btn-default {
+  border: 0;
 }
 .query-builder .from-control-operator {
   width: 70px;
@@ -12309,7 +12315,6 @@ iframe {
   margin: 10px 0;
 }
 .query-builder .row-group {
-  background-color: #f5f5f5;
   margin: 10px 0;
   padding: 10px;
   border-color: #999;