[FEATURE] Improve usability of field selector in record listview 86/33386/19
authorTorben Hansen <derhansen@gmail.com>
Sun, 19 Oct 2014 12:14:24 +0000 (14:14 +0200)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sun, 9 Aug 2015 09:45:04 +0000 (11:45 +0200)
The field selector for the record listview and the element
browser is currently a select field (with multiple options)
and a user must use the control key to select multiple fields.
This is not very user friendly nowadays.

This patch replaces the select field with a list of checkboxes
like used in other places in TYPO3 backend, so a user can
select multiple fields without using the control key. Also the
default column is selected by default and the checkbox is
disabled, because you can't deselect the default column.

Resolves: #62323
Related: #5370
Releases: master
Change-Id: I2a60a0c87766f5b4ea0854d3d8063197c32feea1
Reviewed-on: http://review.typo3.org/33386
Reviewed-by: Jan Helke <typo3@helke.de>
Tested-by: Jan Helke <typo3@helke.de>
Tested-by: Daniel Goerz <ervaude@gmail.com>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Build/Resources/Public/Less/backend.less
typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
typo3/sysext/recordlist/Classes/RecordList.php
typo3/sysext/recordlist/Classes/RecordList/DatabaseRecordList.php
typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js [new file with mode: 0644]
typo3/sysext/recordlist/Tests/Unit/Browser/ElementBrowserTest.php
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_fieldselectbox.less [new file with mode: 0644]
typo3/sysext/t3skin/Resources/Public/Css/backend.css

index 693a390..3a7b7f1 100644 (file)
@@ -51,6 +51,7 @@
 @import "TYPO3/_element_tceforms.less";
 @import "TYPO3/_element_tree.less";
 @import "TYPO3/_element_pagination.less";
+@import "TYPO3/_element_fieldselectbox.less";
 @import "TYPO3/_element_label.less";
 @import "TYPO3/_element_badges.less";
 @import "TYPO3/_element_buttons.less";
index e8ace7f..2f6d9fa 100755 (executable)
@@ -266,6 +266,9 @@ class ElementBrowser {
        */
        public function __construct() {
                $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
+               $this->pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
+               $this->pageRenderer->loadJquery();
+               $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
        }
 
        /**
index 8e3f42d..e4c6d2e 100644 (file)
@@ -190,6 +190,9 @@ class RecordList {
         */
        public function __construct() {
                $this->getLanguageService()->includeLLFile('EXT:lang/locallang_mod_web_list.xlf');
+               $this->pageRenderer = $GLOBALS['TBE_TEMPLATE']->getPageRenderer();
+               $this->pageRenderer->loadJquery();
+               $this->pageRenderer->loadRequireJsModule('TYPO3/CMS/Recordlist/FieldSelectBox');
        }
 
        /**
index f09edfa..eb10d44 100644 (file)
@@ -1661,18 +1661,18 @@ class DatabaseRecordList extends AbstractDatabaseRecordList {
        }
 
        /**
-        * Create the selector box for selecting fields to display from a table:
+        * Creates a checkbox list for selecting fields to display from a table:
         *
         * @param string $table Table name
         * @param bool $formFields If TRUE, form-fields will be wrapped around the table.
-        * @return string HTML table with the selector box (name: displayFields['.$table.'][])
+        * @return string HTML table with the selector check box (name: displayFields['.$table.'][])
         */
        public function fieldSelectBox($table, $formFields = TRUE) {
                $lang = $this->getLanguageService();
                // Init:
                $formElements = array('', '');
                if ($formFields) {
-                       $formElements = array('<form action="' . htmlspecialchars($this->listURL()) . '" method="post">', '</form>');
+                       $formElements = array('<form action="' . htmlspecialchars($this->listURL()) . '" method="post" name="fieldSelectBox">', '</form>');
                }
                // Load already selected fields, if any:
                $setFields = is_array($this->setFields[$table]) ? $this->setFields[$table] : array();
@@ -1684,38 +1684,47 @@ class DatabaseRecordList extends AbstractDatabaseRecordList {
                $fields[] = '_LOCALIZATION_';
                $fields[] = '_CONTROL_';
                $fields[] = '_CLIPBOARD_';
-               // Create an option for each field:
-               $opt = array();
-               $opt[] = '<option value=""></option>';
-               foreach ($fields as $fN) {
+               // Create a checkbox for each field:
+               $checkboxes = array();
+               $checkAllChecked = TRUE;
+               foreach ($fields as $fieldName) {
+                       // Determine, if checkbox should be checked
+                       if (in_array($fieldName, $setFields, TRUE) || $fieldName === $this->fieldArray[0]) {
+                               $checked = ' checked="checked"';
+                       } else {
+                               $checkAllChecked = FALSE;
+                               $checked = '';
+                       }
                        // Field label
-                       $fL = is_array($GLOBALS['TCA'][$table]['columns'][$fN])
-                               ? rtrim($lang->sL($GLOBALS['TCA'][$table]['columns'][$fN]['label']), ':')
-                               : '[' . $fN . ']';
-                       $opt[] = '<option value="' . $fN . '"' . (in_array($fN, $setFields) ? ' selected="selected"' : '') . '>'
-                               . htmlspecialchars($fL) . '</option>';
-               }
-               // Compile the options into a multiple selector box:
-               $lMenu = '<select size="' . MathUtility::forceIntegerInRange(count($fields) + 1, 3, 20)
-                       . '" multiple="multiple" name="displayFields[' . $table . '][]">' . implode('', $opt) . '</select>';
+                       $fL = is_array($GLOBALS['TCA'][$table]['columns'][$fieldName])
+                               ? rtrim($lang->sL($GLOBALS['TCA'][$table]['columns'][$fieldName]['label']), ':')
+                               : '[' . $fieldName . ']';
+                       $checkboxes[] = '<tr><td class="col-checkbox"><input type="checkbox" id="check-' . $fieldName . '" name="displayFields['
+                               . $table . '][]" value="' . $fieldName . '"' . $checked
+                               . ($fieldName === $this->fieldArray[0] ? ' disabled="disabled"' : '') . '></td><td class="col-title">'
+                               . '<label class="label-block" for="check-' . $fieldName . '">' . htmlspecialchars($fL) . '</label></td></tr>';
+               }
                // Table with the field selector::
                $content = $formElements[0] . '
-                       <!--
-                               Field selector for extended table view:
-                       -->
-                       <table border="0" cellpadding="0" cellspacing="0" id="typo3-dblist-fieldSelect">
-                               <tr>
-                                       <td>
-                                               ' . $lMenu . '
-                                       </td>
-                                       <td>
-                                               <input class="btn btn-default" type="submit" name="search" value="'
-                                               . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.setFields', TRUE) . '" />
-                                       </td>
-                               </tr>
-                       </table>
+                       <input type="hidden" name="displayFields[' . $table . '][]" value="">
+                       <div class="table-fit">
+                               <table border="0" cellpadding="0" cellspacing="0" class="table table-transparent table-hover">
+                                       <thead>
+                                               <tr>
+                                                       <th class="col-checkbox" colspan="2">
+                                                               <input type="checkbox" class="checkbox checkAll" ' . ($checkAllChecked ? ' checked="checked"' : '') .'>
+                                                       </th>
+                                               </tr>
+                                       </thead>
+                                       <tbody>
+                                       ' . implode('', $checkboxes) . '
+                                       </tbody>
+                               </table>
+                       </div>
+                       <input type="submit" name="search" class="btn btn-default" value="'
+                       . $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.setFields', TRUE) . '"/>
                        ' . $formElements[1];
-               return '<div class="db_list-fieldSelect">' . $content . '</div>';
+               return '<div class="fieldSelectBox">' . $content . '</div>';
        }
 
        /*********************************
diff --git a/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js b/typo3/sysext/recordlist/Resources/Public/JavaScript/FieldSelectBox.js
new file mode 100644 (file)
index 0000000..03b53cc
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * 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!
+ */
+
+/**
+ * Check-all / uncheck-all for the Database Recordlist fieldSelectBox
+ */
+define('TYPO3/CMS/Recordlist/FieldSelectBox', ['jquery'], function($) {
+
+       var FieldSelectBox = {};
+
+       FieldSelectBox.initializeEvents = function() {
+               $('.fieldSelectBox .checkAll').change(function() {
+                       var checked = $(this).prop('checked');
+                       var $checkboxes = $('.fieldSelectBox tbody').find(':checkbox');
+                       $checkboxes.each(function() {
+                               if (!$(this).prop('disabled')) {
+                                       $(this).prop('checked', checked);
+                               }
+                       });
+               });
+       };
+
+       // initialize and return the FieldSelectBox object
+       return function() {
+               $(document).ready(function() {
+                       FieldSelectBox.initializeEvents();
+               });
+
+               TYPO3.FieldSelectBox = FieldSelectBox;
+               return FieldSelectBox;
+       }();
+});
index 60b3617..cf9f6c3 100644 (file)
@@ -23,6 +23,11 @@ class ElementBrowserTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
         * @test
         */
        public function printCurrentUrlWithAnyTextReturnsThatText() {
+               $mockPageRenderer = $this->getMock(\TYPO3\CMS\Core\Page\PageRenderer::class, array(), array(), '', FALSE);
+               $mockDocumentTemplate = $this->getMock(\TYPO3\CMS\Backend\Template\DocumentTemplate::class, array(), array(), '', FALSE);
+               $mockDocumentTemplate->expects($this->once())->method('getPageRenderer')->will($this->returnValue($mockPageRenderer));
+               $GLOBALS['TBE_TEMPLATE'] = $mockDocumentTemplate;
+
                $GLOBALS['LANG'] = $this->getMock(\TYPO3\CMS\Lang\LanguageService::class, array(), array(), '', FALSE);
                $subject = new \TYPO3\CMS\Recordlist\Browser\ElementBrowser();
                $subject->act = 'file';
diff --git a/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_fieldselectbox.less b/typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_fieldselectbox.less
new file mode 100644 (file)
index 0000000..3ad2769
--- /dev/null
@@ -0,0 +1,12 @@
+//
+// Database Recordlist fieldSelectBox
+//
+.fieldSelectBox table {
+  .col-title {
+    padding: 0 @padding-base-vertical;
+  }
+  .label-block {
+    line-height: 32px;
+    height: 32px;
+  }
+}
index 8a8d395..723f600 100644 (file)
@@ -1,14 +1,14 @@
-/*!\r
- * This file is part of the TYPO3 CMS project.\r
- *\r
- * It is free software; you can redistribute it and/or modify it under\r
- * the terms of the GNU General Public License, either version 2\r
- * of the License, or any later version.\r
- *\r
- * For the full copyright and license information, please read the\r
- * LICENSE.txt file that was distributed with this source code.\r
- *\r
- * The TYPO3 project - inspiring people to share!\r
+/*!
+ * 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!
  */
 /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
 html {
@@ -11185,6 +11185,13 @@ body#ext-backend-Modules-FileSystemNavigationFrame-index-php {
 .pagination-block {
   display: block;
 }
+.fieldSelectBox table .col-title {
+  padding: 0 6px;
+}
+.fieldSelectBox table .label-block {
+  line-height: 32px;
+  height: 32px;
+}
 .label-inline,
 .label-block {
   margin: 0;