[TASK] Unify clearable input fields 82/34782/4
authorBenjamin Mack <benni@typo3.org>
Sat, 29 Nov 2014 21:51:28 +0000 (22:51 +0100)
committerBenjamin Mack <benni@typo3.org>
Sun, 30 Nov 2014 00:19:18 +0000 (01:19 +0100)
There are three places in the core
where clearables (cleaning the content
of a input field with an X at the end)
are used.

- FormEngine
- Documentation
- Extension Manager

For EXT:documentation a hand-written
jQuery plugin was added called
"jquery.clearable". This was also used in
Extension Manager. For FormEngine
there was a inline JS code changing
CSS classes on hover.

In recent changes the clearable logic
for FormEngine broke. The proposed
change now unifies the code.

1. The clearable plugin was solved
so it is not called multiple times
on the same input field, and also
takes into account if the input
field is used like in FormEngine
where "hidden" fields are used.

2. The FormEngine RequireJS module
is now cleaned so it has a method
"TYPO3.FormEngine.reinitialize" which
can be used from outside the module
for AJAX requests like IRRE.

3. The FormEngine now uses the clearable
plugin initialized via the new function
instead of its own inlineJS logic,
and removes the old broken logic.

4. The corresponding CSS is now included
in the LESS file instead of a separate file
with a few lines.

Resolves: #63432
Releases: master
Change-Id: I0f7d4acb9b31ae32ae766c1f56dbdeb0ea3f24e6
Reviewed-on: http://review.typo3.org/34782
Reviewed-by: Frank Nägler <typo3@naegler.net>
Tested-by: Frank Nägler <typo3@naegler.net>
Reviewed-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Tested-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
typo3/contrib/jquery/jquery.clearable.css [deleted file]
typo3/contrib/jquery/jquery.clearable.js
typo3/sysext/backend/Classes/Form/Element/InputElement.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
typo3/sysext/documentation/Resources/Private/Layouts/Default.html
typo3/sysext/extensionmanager/Resources/Private/Layouts/Main.html
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_element_tceforms.less
typo3/sysext/t3skin/Resources/Private/Styles/TYPO3/_main_form.less
typo3/sysext/t3skin/Resources/Public/Css/visual/t3skin.css

diff --git a/typo3/contrib/jquery/jquery.clearable.css b/typo3/contrib/jquery/jquery.clearable.css
deleted file mode 100644 (file)
index 4413d88..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Styles for the "clearable" jquery plugin.
- */
-
-.t3-clearable-wrapper {
-       position: relative;
-    display: inline-block;
-}
-
-.t3-clearable {
-       padding-right: 15px;
-}
-
-.t3-clearable-wrapper .t3-tceforms-input-clearer {
-       position: absolute;
-       right: 5px;
-       top: 5px;
-}
index 2c0c72f..caaf4b6 100644 (file)
@@ -1,26 +1,15 @@
-/***************************************************************
- *  Copyright notice
- *
- *  (c) 2013 Jost Baron <j.baron@netzkoenig.de>
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
+/**
+ * This file is part of the TYPO3 CMS project.
  *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
+ * 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.
  *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
  *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
+ * The TYPO3 project - inspiring people to share!
+ */
 /**
  * This file provides a jQuery plugin for generating 'clearable' input fields.
  * These fields show a "clear"-button when someone hovers over them and
@@ -34,7 +23,7 @@
        $.fn.clearable = function(options) {
 
                var defaults = {
-                       'onClear'       : function() {}
+                       'onClear': function() {}
                };
 
                // Merge defaults and given options. Given options have higher priority
                        // The input element to make clearable.
                        var $input = $(this);
 
-                       // Wrap it with a div and add a span that is the trigger for
-                       // clearing.
-                       $input.wrap('<div class="t3-clearable-wrapper"/>');
-                       $input.after('<span class="t3-icon t3-icon-actions t3-icon-actions-input t3-icon-input-clear t3-tceforms-input-clearer"/>');
-                       $input.addClass('t3-clearable');
+                       // make sure the input field is not used twice for a clearable
+                       if (!$input.data('clearable')) {
+                               $input.data('clearable', 'loaded');
+
+                               var $inputFieldWithValue = $input;
+                               // the hidden field that holds the real data, used in FormEngine
+                               if ($input.next('input[type=hidden]').length) {
+                                       $inputFieldWithValue = $input.next('input[type=hidden]');
+                               }
 
-                       var $wrapper = $input.parent();
-                       var $clearer = $input.next();
+                               // Wrap it with a div and add a span that is the trigger for
+                               // clearing.
+                               $input.wrap('<div class="t3-clearable-wrapper"/>');
+                               $input.after('<span class="t3-icon t3-icon-actions t3-icon-actions-input t3-icon-input-clear t3-input-clearer"/>');
+                               $input.addClass('t3-clearable');
 
-                       // Add some data to the wrapper indicating if it is currently being
-                       // hovered or not.
-                       $input.data('isHovering', false);
-                       $wrapper.hover(
-                               function() {
+                               var $wrapper = $input.parent();
+                               var $clearer = $input.next();
+
+                               // Add some data to the wrapper indicating if it is currently being
+                               // hovered or not.
+                               $input.data('isHovering', false);
+                               $wrapper.hover(function() {
                                        $input.data('isHovering', true);
-                               },
-                               function() {
+                               }, function() {
                                        $input.data('isHovering', false);
-                       });
+                               });
 
-                       // Register a listener the various events triggering the clearer to
-                       // be shown or hidden.
-                       var handler = function() {
-                               if ($input.data('isHovering') && ($input.val() != '')) {
-                                       $clearer.show();
-                               }
-                               else {
-                                       $clearer.hide();
-                               }
-                       };
+                               // Register a listener the various events triggering the clearer to
+                               // be shown or hidden.
+                               var handler = function() {
+                                       var value = $inputFieldWithValue.val();
+                                       if ($input.data('isHovering') && value.length > 0) {
+                                               $clearer.show();
+                                       } else {
+                                               $clearer.hide();
+                                       }
+                               };
 
-                       $wrapper.on('mouseover mouseout', handler);
-                       $input.on('keypress', handler);
+                               $wrapper.on('mouseover mouseout', handler);
+                               $input.on('keypress', handler);
 
 
-                       // The actual clearing action. Focus the input element afterwards,
-                       // the user probably wants to type into it after clearing.
-                       $clearer.click(function() {
-                               $input.val('');
-                               $input.focus();
-                               handler();
+                               // The actual clearing action. Focus the input element afterwards,
+                               // the user probably wants to type into it after clearing.
+                               $clearer.click(function() {
+                                       $input.val('').change().focus();
+                                       handler();
 
-                               if ('function' === typeof(settings.onClear)) {
-                                       settings.onClear.call($input.get());
-                               }
-                       });
+                                       if ('function' === typeof(settings.onClear)) {
+                                               settings.onClear.call($input.get());
+                                       }
+                               });
 
-                       // Initialize the clearer icon
-                       handler();
+                               // Initialize the clearer icon
+                               handler();
+                       }
                });
        };
-})(jQuery);
\ No newline at end of file
+})(jQuery || TYPO3.jQuery);
\ No newline at end of file
index 261603c..8dd7c51 100644 (file)
@@ -133,19 +133,16 @@ class InputElement extends AbstractFormElement {
                }
                $paramsList = '\'' . $additionalInformation['itemFormElName'] . '\',\'' . implode(',', $evalList) . '\',\'' . trim($config['is_in']) . '\',' . (isset($config['checkbox']) ? 1 : 0) . ',\'' . $config['checkbox'] . '\'';
                if (in_array('date', $evalList) || in_array('datetime', $evalList)) {
-                       $item .= '<span class="t3-tceforms-input-wrapper-datetime" onmouseOver="if (document.getElementById(\'' . $inputId . '\').value) {this.className=\'t3-tceforms-input-wrapper-datetime-hover\';} else {this.className=\'t3-tceforms-input-wrapper-datetime\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper-datetime\';">';
+                       $item .= '<span class="t3-tceforms-input-wrapper-datetime">';
                        // Add server timezone offset to UTC to our stored date
                        if ($additionalInformation['itemFormElValue'] > 0) {
                                $additionalInformation['itemFormElValue'] += date('Z', $additionalInformation['itemFormElValue']);
                        }
                } else {
-                       $item .= '<span class="t3-tceforms-input-wrapper" onmouseOver="if (document.getElementById(\'' . $inputId . '\').value) {this.className=\'t3-tceforms-input-wrapper-hover\';} else {this.className=\'t3-tceforms-input-wrapper\';};" onmouseOut="this.className=\'t3-tceforms-input-wrapper\';">';
+                       $item .= '<span class="t3-tceforms-input-wrapper">';
                }
                $additionalInformation['fieldChangeFunc'] = array_merge(array('typo3form.fieldGet' => 'typo3form.fieldGet(' . $paramsList . ');'), $additionalInformation['fieldChangeFunc']);
-               // Old function "checkbox" now the option to set the date / remove the date
-               if (isset($config['checkbox'])) {
-                       $item .= IconUtility::getSpriteIcon('actions-input-clear', array('tag' => 'a', 'class' => 't3-tceforms-input-clearer', 'onclick' => 'document.getElementById(\'' . $inputId . '\').value=\'\';document.getElementById(\'' . $inputId . '\').focus();' . implode('', $additionalInformation['fieldChangeFunc'])));
-               }
+
                $mLgd = $config['max'] ?: 256;
                $iOnChange = implode('', $additionalInformation['fieldChangeFunc']);
                $cssClasses[] = 'hasDefaultValue';
index d22475f..fc7c1bb 100644 (file)
@@ -514,6 +514,8 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
 
        /**
         * initialize events for all form engine relevant tasks
+        * this function only needs to be called once on page load,
+        * as it using deferrer methods only
         */
        FormEngine.initializeEvents = function() {
 
@@ -575,6 +577,8 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
 
        /**
         * make sure that all selectors and input filters are recognized
+        * note: this also works on elements that are loaded asynchronously via AJAX, no need to call this method
+        * after an AJAX load.
         */
        FormEngine.SelectBoxFilter.initializeEvents = function() {
                $(document).on('keyup', FormEngine.SelectBoxFilter.options.filterTextFieldSelector, function() {
@@ -619,13 +623,32 @@ define('TYPO3/CMS/Backend/FormEngine', ['jquery'], function ($) {
                }
        };
 
+       /**
+        * this is the main function that is called on page load, but also after elements are asynchroniously
+        * called e.g. after IRRE elements are loaded again, or a new flexform section is added.
+        * use this function in your extension like this "TYPO3.FormEngine.initialize()"
+        * if you add new fields dynamically.
+        *
+        */
+       FormEngine.reinitialize = function() {
+               // apply "close" button to all input / datetime fields
+               if ($('.t3-tceforms-input-wrapper, .t3-tceforms-input-wrapper-datetime').length) {
+                       require(['jquery/jquery.clearable'], function() {
+                               $('.t3-tceforms-input-wrapper .formfield-input, .t3-tceforms-input-wrapper-datetime .formfield-input').clearable();
+                       });
+               }
+               // note, this will be migrated to FormEngine itself soon
+               TYPO3.TCEFORMS.convertDateFieldsToDatePicker();
+       };
 
        /**
         * initialize function, always require possible post-render hooks return the main object
         */
        return function() {
+               // the functions are both using delegates, thus no need to be called again
                FormEngine.initializeEvents();
                FormEngine.SelectBoxFilter.initializeEvents();
+               FormEngine.reinitialize();
 
                // load required modules to hook in the post initialize function
                if (undefined !== TYPO3.settings.RequireJS && undefined !== TYPO3.settings.RequireJS.PostInitializationModules['TYPO3/CMS/Backend/FormEngine']) {
index a0257a4..3e4448f 100644 (file)
@@ -273,7 +273,7 @@ var inline = {
                                        eval(value);
                                });
                        }
-                       TYPO3.TCEFORMS.convertDateFieldsToDatePicker();
+                       TYPO3.FormEngine.reinitialize();
                }
        },
 
index 4d50a22..a4bd056 100644 (file)
@@ -3,8 +3,7 @@
 <f:be.container pageTitle="{f:translate(key: 'documentation_manager')}" enableClickMenu="false" loadPrototype="false" loadScriptaculous="false" loadExtJs="false" loadExtJsTheme="true" loadJQuery="true"
 
        includeCssFiles="{
-               0:'{f:uri.resource(path:\'Css/main.css\')}',
-               1:'contrib/jquery/jquery.clearable.css'
+               0:'{f:uri.resource(path:\'Css/main.css\')}'
        }"
        includeJsFiles="{
                0:'contrib/jquery/jquery.dataTables-1.10.2.min.js',
index e9e492b..ab4ecc3 100644 (file)
@@ -5,8 +5,7 @@
        includeCssFiles="{
                0:'{f:uri.resource(path:\'Contrib/jQueryUI/jquery-ui-1.10.3.custom.min.css\')}',
                1:'{f:uri.resource(path:\'Contrib/LoadMask/jquery.loadmask.css\')}',
-               2:'{f:uri.resource(path:\'Css/main.css\')}',
-               3:'contrib/jquery/jquery.clearable.css'
+               2:'{f:uri.resource(path:\'Css/main.css\')}'
        }"
        includeJsFiles="{
                0:'contrib/jquery/jquery.dataTables-1.10.2.min.js',
index 22b54c2..60cc70e 100644 (file)
@@ -664,14 +664,6 @@ table#typo3-altdoc-header input,
        border: 0;
 }
 
-.t3-tceforms-input-wrapper,
-.t3-tceforms-input-wrapper-hover,
-.t3-tceforms-input-wrapper-datetime,
-.t3-tceforms-input-wrapper-datetime-hover {
-       display: block;
-       position: relative;
-}
-
 .t3-tceforms-widget-null-wrapper {
        display: inline-block;
        float: right;
@@ -684,46 +676,10 @@ table#typo3-altdoc-header input,
        margin-left: 2px;
        margin-top: 42%;
 }
-
-
-.t3-tceforms-input-wrapper .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-hover .t3-tceforms-input-clearer {
-       position: absolute;
-       right: 10px;
-       top: 5px;
-       z-index: 1000;
-       cursor: pointer;
-}
-
-.t3-tceforms-input-wrapper-datetime .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-datetime-hover .t3-tceforms-input-clearer {
-       position: absolute;
-       right: 27px;
-       top: 5px;
-       z-index: 1000;
-       cursor: pointer;
-}
-.t3-tceforms-input-wrapper-datetime .t3-icon-edit-pick-date,
-.t3-tceforms-input-wrapper-datetime-hover .t3-icon-edit-pick-date {
+.t3-tceforms-input-wrapper-datetime .t3-icon-edit-pick-date {
        top: -4px;
 }
-.t3-tceforms-input-wrapper .tceforms-textfield,
-.t3-tceforms-input-wrapper-hover .tceforms-textfield,
-.t3-tceforms-input-wrapper .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-hover .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-datetime .tceforms-textfield,
-.t3-tceforms-input-wrapper-datetime-hover .tceforms-textfield,
-.t3-tceforms-input-wrapper-datetime .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-datetime-hover .tceforms-datetimefield {
-       position: relative;
-       z-index: 2000;
-       padding-right: 30px!important;
-}
 
-.t3-tceforms-input-wrapper-hover .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-datetime-hover .t3-tceforms-input-clearer {
-       z-index: 3700;
-}
 
 .typo3-TCEforms table#typo3-altdoc-header input:hover,
 .c-inputButton:hover {
index d3f4b6d..87aebf3 100644 (file)
@@ -104,3 +104,22 @@ span.typo3-moduleHeader img {
 a.typo3-goBack {
        font-weight: bold;
 }
+
+/* - - - - - - - - - - - - - - - - - - - - -
+   Styles for the "clearable" jquery plugin.
+- - - - - - - - - - - - - - - - - - - - - */
+
+.t3-clearable-wrapper {
+       position: relative;
+       display: inline-block;
+}
+
+.t3-clearable {
+       padding-right: 15px;
+}
+
+.t3-clearable-wrapper .t3-input-clearer {
+       position: absolute;
+       right: 5px;
+       top: 5px;
+}
index 68c35ce..b5b1cb4 100644 (file)
@@ -9747,13 +9747,6 @@ table#typo3-altdoc-header input,
   background: #efeff4;
   border: 0;
 }
-.t3-tceforms-input-wrapper,
-.t3-tceforms-input-wrapper-hover,
-.t3-tceforms-input-wrapper-datetime,
-.t3-tceforms-input-wrapper-datetime-hover {
-  display: block;
-  position: relative;
-}
 .t3-tceforms-widget-null-wrapper {
   display: inline-block;
   float: right;
@@ -9765,42 +9758,9 @@ table#typo3-altdoc-header input,
   margin-left: 2px;
   margin-top: 42%;
 }
-.t3-tceforms-input-wrapper .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-hover .t3-tceforms-input-clearer {
-  position: absolute;
-  right: 10px;
-  top: 5px;
-  z-index: 1000;
-  cursor: pointer;
-}
-.t3-tceforms-input-wrapper-datetime .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-datetime-hover .t3-tceforms-input-clearer {
-  position: absolute;
-  right: 27px;
-  top: 5px;
-  z-index: 1000;
-  cursor: pointer;
-}
-.t3-tceforms-input-wrapper-datetime .t3-icon-edit-pick-date,
-.t3-tceforms-input-wrapper-datetime-hover .t3-icon-edit-pick-date {
+.t3-tceforms-input-wrapper-datetime .t3-icon-edit-pick-date {
   top: -4px;
 }
-.t3-tceforms-input-wrapper .tceforms-textfield,
-.t3-tceforms-input-wrapper-hover .tceforms-textfield,
-.t3-tceforms-input-wrapper .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-hover .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-datetime .tceforms-textfield,
-.t3-tceforms-input-wrapper-datetime-hover .tceforms-textfield,
-.t3-tceforms-input-wrapper-datetime .tceforms-datetimefield,
-.t3-tceforms-input-wrapper-datetime-hover .tceforms-datetimefield {
-  position: relative;
-  z-index: 2000;
-  padding-right: 30px!important;
-}
-.t3-tceforms-input-wrapper-hover .t3-tceforms-input-clearer,
-.t3-tceforms-input-wrapper-datetime-hover .t3-tceforms-input-clearer {
-  z-index: 3700;
-}
 .typo3-TCEforms table#typo3-altdoc-header input:hover,
 .c-inputButton:hover {
   background: none;
@@ -11079,6 +11039,21 @@ span.typo3-moduleHeader img {
 a.typo3-goBack {
   font-weight: bold;
 }
+/* - - - - - - - - - - - - - - - - - - - - -
+   Styles for the "clearable" jquery plugin.
+- - - - - - - - - - - - - - - - - - - - - */
+.t3-clearable-wrapper {
+  position: relative;
+  display: inline-block;
+}
+.t3-clearable {
+  padding-right: 15px;
+}
+.t3-clearable-wrapper .t3-input-clearer {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+}
 /**
  * This file is part of the TYPO3 CMS project.
  *