[TASK] Use bootstrap colorpicker consistent over the whole backend 70/47570/13
authorKay Strobach <info@kay-strobach.de>
Sun, 10 Apr 2016 19:02:33 +0000 (21:02 +0200)
committerWouter Wolters <typo3@wouterwolters.nl>
Fri, 15 Apr 2016 09:22:48 +0000 (11:22 +0200)
This patch inserts the same colorpicker on all places where a colorpicker
is used in the TYPO3 backend.

So it tackles:

 - formengine
 - constant editor
 - extension manager

Releases: master
Resolves: #73728
Change-Id: I0efd9f1e90dce3a66a80bb9969c03b87fb2f851d
Reviewed-on: https://review.typo3.org/47570
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
19 files changed:
Build/Gruntfile.js
Build/Resources/Public/Less/Component/colorpicker.less [new file with mode: 0644]
Build/Resources/Public/Less/backend.less
Build/bower.json
typo3/sysext/backend/Classes/Form/Element/AbstractFormElement.php
typo3/sysext/backend/Classes/Form/Element/InputColorPickerElement.php [new file with mode: 0644]
typo3/sysext/backend/Classes/Form/NodeFactory.php
typo3/sysext/backend/Resources/Public/JavaScript/FormEngine.js
typo3/sysext/core/Classes/Migrations/TcaMigration.php
typo3/sysext/core/Classes/TypoScript/ExtendedTemplateService.php
typo3/sysext/core/Documentation/Changelog/master/Deprecation-73728-WizardTypeColorboxIsDeprecated.rst [new file with mode: 0644]
typo3/sysext/core/Resources/Public/Images/colorpicker/jquery.minicolors.png [new file with mode: 0644]
typo3/sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors.js [new file with mode: 0644]
typo3/sysext/css_styled_content/Configuration/TypoScript/v7/constants.txt
typo3/sysext/css_styled_content/static/constants.txt
typo3/sysext/extensionmanager/Classes/ViewHelpers/Form/TypoScriptConstantsViewHelper.php
typo3/sysext/fluid_styled_content/Configuration/TypoScript/Static/constants.txt
typo3/sysext/t3skin/Resources/Public/Css/backend.css
typo3/sysext/tstemplate/Classes/Controller/TypoScriptTemplateConstantEditorModuleFunctionController.php

index 65b99fc..6e6fae1 100644 (file)
@@ -112,6 +112,9 @@ module.exports = function(grunt) {
                        }
                },
                watch: {
+                       options: {
+                               livereload: true
+                       },
                        less: {
                                files: '<%= paths.less %>**/*.less',
                                tasks: 'css'
@@ -169,6 +172,17 @@ module.exports = function(grunt) {
                                runBower: false,
                                srcPrefix: "bower_components/"
                        },
+                       glob: {
+                               files: {
+                                       // When using glob patterns, destinations are *always* folder names
+                                       // into which matching files will be copied
+                                       // Also note that subdirectories are **not** maintained
+                                       // if a destination is specified
+                                       // For example, one of the files copied here is
+                                       // 'lodash/dist/lodash.js' -> 'public/js/libs/lodash/lodash.js'
+                                       '<%= paths.sysext %>core/Resources/Public/Images/colorpicker': 'jquery-minicolors/*.png'
+                               }
+                       },
                        all: {
                                options: {
                                        destPrefix: "<%= paths.core %>Public/JavaScript/Contrib"
@@ -186,6 +200,7 @@ module.exports = function(grunt) {
                                        'autosize.js': 'autosize/dist/autosize.min.js',
                                        'taboverride.min.js': 'taboverride/build/output/taboverride.min.js',
                                        'bootstrap-slider.min.js': 'seiyria-bootstrap-slider/dist/bootstrap-slider.min.js',
+                                       'jquery.minicolors.js': 'jquery-minicolors/jquery.minicolors.min.js',
                                        /* disabled until autocomplete groupBy is fixed by the author
                                                see https://github.com/devbridge/jQuery-Autocomplete/pull/387
                                        'jquery.autocomplete.js': 'devbridge-autocomplete/src/jquery.autocomplete.js',
diff --git a/Build/Resources/Public/Less/Component/colorpicker.less b/Build/Resources/Public/Less/Component/colorpicker.less
new file mode 100644 (file)
index 0000000..75c5b02
--- /dev/null
@@ -0,0 +1,247 @@
+//
+// Minicolors
+// ============
+// Optimized version of http://labs.abeautifulsite.net/jquery-minicolors/
+// for TYPO3 CMS colorpicker used in the backend.
+//
+
+
+//
+// Variables
+//
+@minicolors-swatch-height: 20px;
+@minicolors-swatch-width: 20px;
+@minicolors-swatch-border-radius: 1px;
+@minicolors-swatch-border: @input-border;
+@minicolors-panel-bg: #fff;
+@minicolors-panel-border: @input-border;
+@minicolors-panel-border-radius: @border-radius-base;
+
+//
+// Component
+//
+.minicolors {
+       position: relative;
+}
+
+.userTS .minicolors {
+       // fix for constantmanager
+       position: absolute;
+}
+
+.minicolors-sprite {
+       background-image: url("@{path-sysext}/core/Resources/Public/Images/colorpicker/jquery.minicolors.png");
+}
+
+//
+// Swatch
+//
+.minicolors-swatch {
+       position: absolute;
+       vertical-align: middle;
+       background-position: -80px 0;
+       cursor: text;
+       padding: 0;
+       margin: 0;
+       display: inline-block;
+       top: 50%;
+       left: @padding-base-horizontal;
+       z-index: 2;
+       transform: translate(0,-50%);
+       width: @minicolors-swatch-width;
+       height: @minicolors-swatch-height;
+       border-radius: @minicolors-swatch-border-radius;
+}
+.minicolors-swatch-color {
+       position: absolute;
+       top: 0;
+       left: 0;
+       right: 0;
+       bottom: 0;
+       border-radius: inherit;
+}
+
+//
+// Input
+//
+.minicolors-input {
+       float: none;
+       padding-left: (@padding-base-horizontal * 2) + @minicolors-swatch-width;
+}
+
+//
+// Panel
+//
+.minicolors-panel {
+       margin-top: 1px;
+       overflow: hidden;
+       border-radius: @minicolors-panel-border-radius;
+       position: absolute;
+       width: 173px;
+       height: 152px;
+       background: @minicolors-panel-bg;
+       border: solid 1px @minicolors-panel-border;
+       box-shadow: 0 0 20px rgba(0, 0, 0, .2);
+       z-index: 99999;
+       box-sizing: content-box;
+       display: none;
+}
+.minicolors-panel.minicolors-with-swatches {
+       height: 182px;
+}
+.minicolors-panel.minicolors-visible {
+       display: block;
+}
+
+//
+// Position
+//
+.minicolors-position-top .minicolors-panel {
+       top: -154px;
+}
+.minicolors-position-right .minicolors-panel {
+       right: 0;
+}
+.minicolors-position-bottom .minicolors-panel {
+       top: auto;
+}
+.minicolors-position-left .minicolors-panel {
+       left: 0;
+}
+.minicolors-with-opacity .minicolors-panel {
+       width: 194px;
+}
+
+//
+// Grid
+//
+.minicolors .minicolors-grid {
+       position: absolute;
+       top: 1px;
+       left: 1px;
+       width: 150px;
+       height: 150px;
+       background-position: -120px 0;
+       cursor: crosshair;
+}
+.minicolors .minicolors-grid-inner {
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 150px;
+       height: 150px;
+}
+
+//
+// Slider
+//
+.minicolors-slider-saturation .minicolors-grid {
+       background-position: -420px 0;
+}
+.minicolors-slider-saturation .minicolors-grid-inner {
+       background-position: -270px 0;
+       background-image: inherit;
+}
+.minicolors-slider-brightness .minicolors-grid {
+       background-position: -570px 0;
+}
+.minicolors-slider-brightness .minicolors-grid-inner {
+       background-color: black;
+}
+.minicolors-slider-wheel .minicolors-grid {
+       background-position: -720px 0;
+}
+.minicolors-slider,
+.minicolors-opacity-slider {
+       position: absolute;
+       top: 1px;
+       left: 152px;
+       width: 20px;
+       height: 150px;
+       background-color: white;
+       background-position: 0 0;
+       cursor: row-resize;
+}
+.minicolors-slider-saturation .minicolors-slider {
+       background-position: -60px 0;
+}
+.minicolors-slider-brightness .minicolors-slider {
+       background-position: -20px 0;
+}
+.minicolors-slider-wheel .minicolors-slider {
+       background-position: -20px 0;
+}
+.minicolors-opacity-slider {
+       left: 173px;
+       background-position: -40px 0;
+       display: none;
+}
+.minicolors-with-opacity .minicolors-opacity-slider {
+       display: block;
+}
+
+//
+// Picker
+//
+.minicolors-grid .minicolors-picker {
+       position: absolute;
+       top: 70px;
+       left: 70px;
+       width: 12px;
+       height: 12px;
+       border: solid 1px black;
+       border-radius: 10px;
+       margin-top: -6px;
+       margin-left: -6px;
+       background: none;
+}
+.minicolors-grid .minicolors-picker > div {
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 8px;
+       height: 8px;
+       border-radius: 8px;
+       border: solid 2px white;
+       box-sizing: content-box;
+}
+.minicolors-picker {
+       position: absolute;
+       top: 0;
+       left: 0;
+       width: 18px;
+       height: 2px;
+       background: white;
+       border: solid 1px black;
+       margin-top: -2px;
+       box-sizing: content-box;
+}
+
+//
+// Swatches
+//
+.minicolors-swatches,.minicolors-swatches li {
+       margin: 0;
+       padding: 0;
+       list-style: none;
+       overflow: hidden;
+       position: absolute;
+       top: 157px;
+       left: 5px;
+}
+.minicolors-swatches .minicolors-swatch {
+       position: relative;
+       float: left;
+       cursor: pointer;
+       margin:0 4px 0 0;
+       top: 0;
+       left: 0;
+       width: 20px;
+       height: 20px;
+}
+.minicolors-with-opacity .minicolors-swatches .minicolors-swatch {
+       margin-right:7px;
+}
+.minicolors-swatch.selected {
+       border-color:#000;
+}
index 72c6cd8..bb6533b 100644 (file)
 @import "_minimal.less";
 
 //
+// Components
+//
+@import "Component/colorpicker.less";
+
+//
 // Components from bootstrap plugins
 //
 @import "@{path-bower}/eonasdan-bootstrap-datetimepicker/src/less/_bootstrap-datetimepicker.less";
index 2cb60e8..8f4d2e6 100644 (file)
@@ -43,6 +43,7 @@
     "devbridge-autocomplete": "1.2.24",
     "region-flags": "*",
     "wmdbsystems-typo3-icons": "0.0.10",
-    "matchHeight": "matchheight#^0.7.0"
+    "matchHeight": "matchheight#^0.7.0",
+    "jquery-minicolors": "^2.2.4"
   }
 }
index 01177f7..940c3f4 100644 (file)
@@ -66,6 +66,11 @@ abstract class AbstractFormElement extends AbstractNode
     protected $clipboard = null;
 
     /**
+     * @var NodeFactory
+     */
+    protected $nodeFactory;
+
+    /**
      * Container objects give $nodeFactory down to other containers.
      *
      * @param NodeFactory $nodeFactory
@@ -306,46 +311,6 @@ abstract class AbstractFormElement extends AbstractNode
                         '</a>';
                     break;
 
-                case 'colorbox':
-                    $params = array();
-                    $params['params'] = $wizardConfiguration['params'];
-                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
-                    $params['table'] = $table;
-                    $params['uid'] = $row['uid'];
-                    $params['pid'] = $row['pid'];
-                    $params['field'] = $field;
-                    $params['flexFormPath'] = $flexFormPath;
-                    $params['md5ID'] = $md5ID;
-                    $params['returnUrl'] = $this->data['returnUrl'];
-
-                    $params['formName'] = 'editform';
-                    $params['itemName'] = $itemName;
-                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
-                    $params['fieldChangeFunc'] = $fieldChangeFunc;
-                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
-
-                    // Resolving script filename and setting URL.
-                    $urlParameters = array();
-                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
-                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
-                    }
-                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
-                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', array('P' => $params));
-
-                    $aOnClick =
-                        'this.blur();' .
-                        'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url) . '+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode(' .
-                            'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value,300' .
-                            ')' .
-                            '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName) . '),' .
-                            GeneralUtility::quoteJSvalue('popUp' . $md5ID) . ',' .
-                            GeneralUtility::quoteJSvalue($wizardConfiguration['JSopenParams']) .
-                        ');' .
-                        'vHWin.focus();' .
-                        'return false;';
-
-                    $otherWizards[] = '<a id="' . $md5ID . '" class="btn btn-default" href="#" onclick="' . htmlspecialchars($aOnClick) . '"><span class="t3-icon fa fa-eyedropper"></span></a>';
-                    break;
                 case 'slider':
                     $params = array();
                     $params['fieldConfig'] = $PA['fieldConf']['config'];
diff --git a/typo3/sysext/backend/Classes/Form/Element/InputColorPickerElement.php b/typo3/sysext/backend/Classes/Form/Element/InputColorPickerElement.php
new file mode 100644 (file)
index 0000000..9b525b2
--- /dev/null
@@ -0,0 +1,162 @@
+<?php
+namespace TYPO3\CMS\Backend\Form\Element;
+
+/*
+ * 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!
+ */
+
+use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Imaging\Icon;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Utility\StringUtility;
+
+/**
+ * Class InputColorPickerElement
+ */
+class InputColorPickerElement extends AbstractFormElement
+{
+
+    /**
+     * This will render a single-line input form field, possibly with various control/validation features
+     *
+     * @return array As defined in initializeResultArray() of AbstractNode
+     */
+    public function render()
+    {
+        $table = $this->data['tableName'];
+        $fieldName = $this->data['fieldName'];
+        $row = $this->data['databaseRow'];
+        $parameterArray = $this->data['parameterArray'];
+        $resultArray = $this->initializeResultArray();
+
+        $config = $parameterArray['fieldConf']['config'];
+        $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
+        $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
+        $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
+        $classes = array();
+        $attributes = array();
+
+        // readonly
+        if ($config['readOnly']) {
+            $itemFormElValue = $parameterArray['itemFormElValue'];
+            $options = $this->data;
+            $options['parameterArray'] = array(
+                'fieldConf' => array(
+                    'config' => $config,
+                ),
+                'itemFormElValue' => $itemFormElValue,
+            );
+            $options['renderType'] = 'none';
+            return $this->nodeFactory->create($options)->render();
+        }
+
+        // @todo: The whole eval handling is a mess and needs refactoring
+        foreach ($evalList as $func) {
+            switch ($func) {
+                case 'required':
+                    $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
+                    break;
+                default:
+                    // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
+                    // @todo: keyword like "date", or a class reference. The global registration could be dropped then
+                    // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
+                    if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
+                        if (class_exists($func)) {
+                            $evalObj = GeneralUtility::makeInstance($func);
+                            if (method_exists($evalObj, 'deevaluateFieldValue')) {
+                                $_params = array(
+                                    'value' => $parameterArray['itemFormElValue']
+                                );
+                                $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
+                            }
+                        }
+                    }
+            }
+        }
+
+        $paramsList = array(
+            'field' => $parameterArray['itemFormElName'],
+            'evalList' => implode(',', $evalList),
+            'is_in' => trim($config['is_in']),
+        );
+
+        // set classes
+        $classes[] = 'form-control';
+        $classes[] = 'hasDefaultValue';
+        $classes[] = 't3js-clearable';
+        $classes[] = 'formengine-colorpickerelement';
+        $attributes['class'] = implode(' ', $classes);
+
+        // calculate attributes
+        $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString($config);
+        $attributes['data-formengine-input-params'] = json_encode($paramsList);
+        $attributes['data-formengine-input-name'] = $parameterArray['itemFormElName'];
+        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
+        $attributes['value'] = '';
+        if (isset($config['max']) && (int)$config['max'] > 0) {
+            $attributes['maxlength'] = (int)$config['max'];
+        }
+
+        // This is the EDITABLE form field.
+        if (!empty($config['placeholder'])) {
+            $attributes['placeholder'] = trim($config['placeholder']);
+        }
+
+        if (isset($config['autocomplete'])) {
+            $attributes['autocomplete'] = empty($config['autocomplete']) ? 'off' : 'on';
+        }
+
+        // Build the attribute string
+        $attributeString = '';
+        foreach ($attributes as $attributeName => $attributeValue) {
+            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
+        }
+
+        $html = '<input type="text" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" ' . $attributeString . ' />';
+
+        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
+        $html .= '<input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
+
+        // Going through all custom evaluations configured for this field
+        // @todo: Similar to above code!
+        foreach ($evalList as $evalData) {
+            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
+                if (class_exists($evalData)) {
+                    $evalObj = GeneralUtility::makeInstance($evalData);
+                    if (method_exists($evalObj, 'returnFieldJS')) {
+                        $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
+                    }
+                }
+            }
+        }
+
+        // Wrap a wizard around the item?
+        $html = $this->renderWizards(
+            array($html),
+            $config['wizards'],
+            $table,
+            $row,
+            $fieldName,
+            $parameterArray,
+            $parameterArray['itemFormElName'],
+            $specConf
+        );
+
+        // Add a wrapper to remain maximum width
+        $width = (int)$this->formMaxWidth($size);
+        $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
+        $resultArray['html'] = $html;
+        return $resultArray;
+    }
+}
index d6b4273..04ea9b4 100644 (file)
@@ -58,6 +58,7 @@ class NodeFactory
         'selectTree' => Element\SelectTreeElement::class,
         'selectSingle' => Element\SelectSingleElement::class,
         'selectSingleBox' => Element\SelectSingleBoxElement::class,
+        'colorpicker' => Element\InputColorPickerElement::class,
         // t3editor is defined with a fallback so extensions can use it even if ext:t3editor is not loaded
         't3editor' => Element\TextElement::class,
         'text' => Element\TextElement::class,
index 219c19e..3c09f7d 100644 (file)
@@ -893,6 +893,17 @@ define(['jquery',
                require(['TYPO3/CMS/Backend/DateTimePicker'], function(DateTimePicker) {
                        DateTimePicker.initialize();
                });
+
+               if ($('.formengine-colorpickerelement').length) {
+                       require(['TYPO3/CMS/Core/Contrib/jquery.minicolors'], function(minicolor) {
+                               $('.formengine-colorpickerelement').minicolors({
+                                               theme: 'bootstrap',
+                                               format: 'hex',
+                                               position: 'bottom left'
+                               });
+                       });
+               }
+
                FormEngine.convertTextareasResizable();
                FormEngine.convertTextareasEnableTab();
        };
index d418590..87528e1 100644 (file)
@@ -53,6 +53,7 @@ class TcaMigration
         $tca = $this->migrateSelectFieldIconTable($tca);
         $tca = $this->migrateElementBrowserWizardToLinkHandler($tca);
         $tca = $this->migrateDefaultExtrasRteTransFormOptions($tca);
+        $tca = $this->migrateColorPickerWizardToRenderType($tca);
         // @todo: if showitem/defaultExtras wizards[xy] is migrated to columnsOverrides here, enableByTypeConfig could be dropped
         return $tca;
     }
@@ -631,7 +632,7 @@ class TcaMigration
             foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
                 if (
                     isset($fieldConfig['config']['wizards']['link']['module']['name']) && $fieldConfig['config']['wizards']['link']['module']['name'] === 'wizard_element_browser'
-                    && isset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']) &&  $fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode'] === 'wizard'
+                    && isset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']) && $fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode'] === 'wizard'
                 ) {
                     $fieldConfig['config']['wizards']['link']['module']['name'] = 'wizard_link';
                     unset($fieldConfig['config']['wizards']['link']['module']['urlParameters']['mode']);
@@ -710,4 +711,38 @@ class TcaMigration
 
         return $tca;
     }
+
+    /**
+     * Migrates fields having a colorpicker wizard to a color field
+     *
+     * @param array $tca Incoming TCA
+     * @return array Migrated TCA
+     */
+    protected function migrateColorPickerWizardToRenderType(array $tca)
+    {
+        foreach ($tca as $table => &$tableDefinition) {
+            if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
+                continue;
+            }
+            foreach ($tableDefinition['columns'] as $fieldName => &$fieldConfig) {
+                if (isset($fieldConfig['config'])) {
+                    if (isset($fieldConfig['config']['wizards'])) {
+                        foreach ($fieldConfig['config']['wizards'] as $wizardName => $wizard) {
+                            if (isset($wizard['type']) && ($wizard['type'] === 'colorbox')) {
+                                unset($fieldConfig['config']['wizards'][$wizardName]);
+                                $fieldConfig['config']['renderType'] = 'colorpicker';
+
+                                $this->messages[] = 'The color-picker wizard using \'colorbox\' is deprecated'
+                                    . ' in TCA ' . $table . '[\'columns\'][\'' . $fieldName . '\'][\'config\']'
+                                    . '[\'wizards\'][\'' . $wizardName . '\'] and is changed to ' . $table
+                                    . '[\'columns\'][\'' . $fieldName . '\'][\'config\'] = \'colorpicker\'';
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return $tca;
+    }
 }
index f1c904e..6a06b38 100644 (file)
@@ -41,11 +41,6 @@ class ExtendedTemplateService extends TemplateService
     public $edit_divider = '###MOD_TS:EDITABLE_CONSTANTS###';
 
     /**
-     * @var string
-     */
-    public $HTMLcolorList = 'aqua,beige,black,blue,brown,fuchsia,gold,gray,green,lime,maroon,navy,olive,orange,purple,red,silver,tan,teal,turquoise,yellow,white';
-
-    /**
      * @var array
      */
     public $categories = array(
@@ -267,6 +262,21 @@ class ExtendedTemplateService extends TemplateService
     public $lastComment = '';
 
     /**
+     * @var array
+     */
+    protected $inlineJavaScript = [];
+
+    /**
+     * Gets the inline JavaScript.
+     *
+     * @return array
+     */
+    public function getInlineJavaScript()
+    {
+        return $this->inlineJavaScript;
+    }
+
+    /**
      * Substitute constant
      *
      * @param string $all
@@ -1199,17 +1209,20 @@ class ExtendedTemplateService extends TemplateService
                                 . ' name="' . $fN . '" value="' . $fV . '"' . ' onChange="uFormUrl(' . $aname . ')" />';
                             break;
                         case 'color':
-                            $colorNames = explode(',', ',' . $this->HTMLcolorList);
-                            $p_field = '';
-                            foreach ($colorNames as $val) {
-                                $sel = '';
-                                if ($val == strtolower($params['value'])) {
-                                    $sel = ' selected';
-                                }
-                                $p_field .= '<option value="' . htmlspecialchars($val) . '"' . $sel . '>' . $val . '</option>';
+                            $p_field = '
+                                <input class="form-control formengine-colorpickerelement" type="text" id="input-' . $idName . '" rel="' . $idName .
+                                '" name="' . $fN . '" value="' . $fV . '"' . $this->getDocumentTemplate()->formWidth(7) . ' onChange="uFormUrl(' . $aname . ')" />';
+
+                            if (empty($this->inlineJavaScript[$typeDat['type']])) {
+                                $this->inlineJavaScript[$typeDat['type']] = '
+                                    require([\'TYPO3/CMS/Core/Contrib/jquery.minicolors\'], function() {
+                                        TYPO3.jQuery(\'.formengine-colorpickerelement\').minicolors({
+                                            theme: \'bootstrap\',
+                                            format: \'hex\',
+                                            align: \'bottom left\'
+                                        });
+                                    });';
                             }
-                            $p_field = '<select class="form-control t3js-color-select" id="select-' . $idName . '" rel="' . $idName . '" name="C' . $fN . '" onChange="uFormUrl(' . $aname . ');"' . $this->getDocumentTemplate()->formWidth(7) . '>' . $p_field . '</select>';
-                            $p_field .= '<input class="form-control t3js-color-input" type="text" id="input-' . $idName . '" rel="' . $idName . '" name="' . $fN . '" value="' . $fV . '"' . $this->getDocumentTemplate()->formWidth(7) . ' onChange="uFormUrl(' . $aname . ')" />';
                             break;
                         case 'wrap':
                             $wArr = explode('|', $fV);
@@ -1297,12 +1310,6 @@ class ExtendedTemplateService extends TemplateService
                     $defaultTyposcriptID = 'defaultTS-' . $idName;
                     $checkboxName = 'check[' . $params['name'] . ']';
                     $checkboxID = 'check-' . $idName;
-                    // Handle type=color specially
-                    if ($typeDat['type'] === 'color' && substr($params['value'], 0, 2) != '{$') {
-                        $appendedGroupAddon = '<span class="input-group-addon colorbox" id="colorbox-' . $idName . '" style="background-color:' . $params['value'] . ';"></span>';
-                    } else {
-                        $appendedGroupAddon = '';
-                    }
                     $userTyposcriptStyle = '';
                     $deleteIconHTML = '';
                     $constantCheckbox = '';
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-73728-WizardTypeColorboxIsDeprecated.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-73728-WizardTypeColorboxIsDeprecated.rst
new file mode 100644 (file)
index 0000000..18da337
--- /dev/null
@@ -0,0 +1,44 @@
+========================================================
+Deprecation: #73728 - Wizard type colorbox is deprecated
+========================================================
+
+Description
+===========
+
+The color-picker is now available as dedicated render-type which will integrate
+an inline color-picker widget based on bootstrap. Thus, the old wizard type
+``colorbox`` is deprecated.
+
+
+Impact
+======
+
+Using the TCA wizard type ``colorbox`` will trigger an internal deprecation
+message. The possibility to pick the color from a custom image has been removed
+without any substitution as well as the possibility to use color names like
+"red" or "white".
+
+
+Affected Installations
+======================
+
+All TCA fields that are using the wizard type ``colorbox``, like e.g.
+
+
+.. code-block:: php
+
+   $GLOBALS['TCA']['tableName']['fieldName']['config']['wizards']['colorbox'] = [
+      'type' => 'colorbox',
+      'script' => 'wizard_colorpicker.php',
+      ...
+   ];
+
+
+Migration
+=========
+
+Use the new render-type ``colorpicker`` in the TCA field configuration, like e.g.
+
+.. code-block:: php
+
+   $GLOBALS['TCA']['tableName']['fieldName']['config']['renderType'] = 'colorpicker';
diff --git a/typo3/sysext/core/Resources/Public/Images/colorpicker/jquery.minicolors.png b/typo3/sysext/core/Resources/Public/Images/colorpicker/jquery.minicolors.png
new file mode 100644 (file)
index 0000000..bccc201
Binary files /dev/null and b/typo3/sysext/core/Resources/Public/Images/colorpicker/jquery.minicolors.png differ
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors.js b/typo3/sysext/core/Resources/Public/JavaScript/Contrib/jquery.minicolors.js
new file mode 100644 (file)
index 0000000..346f7f9
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * jQuery MiniColors: A tiny color picker built on jQuery
+ *
+ * Copyright: Cory LaViska for A Beautiful Site, LLC: http://www.abeautifulsite.net/
+ *
+ * Contribute: https://github.com/claviska/jquery-minicolors
+ *
+ * @license: http://opensource.org/licenses/MIT
+ *
+ */
+!function(i){"function"==typeof define&&define.amd?define(["jquery"],i):"object"==typeof exports?module.exports=i(require("jquery")):i(jQuery)}(function($){"use strict";function i(i,t){var o=$('<div class="minicolors" />'),s=$.minicolors.defaults,a,n,r,c,l;if(!i.data("minicolors-initialized")){if(t=$.extend(!0,{},s,t),o.addClass("minicolors-theme-"+t.theme).toggleClass("minicolors-with-opacity",t.opacity).toggleClass("minicolors-no-data-uris",t.dataUris!==!0),void 0!==t.position&&$.each(t.position.split(" "),function(){o.addClass("minicolors-position-"+this)}),a="rgb"===t.format?t.opacity?"25":"20":t.keywords?"11":"7",i.addClass("minicolors-input").data("minicolors-initialized",!1).data("minicolors-settings",t).prop("size",a).wrap(o).after('<div class="minicolors-panel minicolors-slider-'+t.control+'"><div class="minicolors-slider minicolors-sprite"><div class="minicolors-picker"></div></div><div class="minicolors-opacity-slider minicolors-sprite"><div class="minicolors-picker"></div></div><div class="minicolors-grid minicolors-sprite"><div class="minicolors-grid-inner"></div><div class="minicolors-picker"><div></div></div></div></div>'),t.inline||(i.after('<span class="minicolors-swatch minicolors-sprite minicolors-input-swatch"><span class="minicolors-swatch-color"></span></span>'),i.next(".minicolors-input-swatch").on("click",function(t){t.preventDefault(),i.focus()})),c=i.parent().find(".minicolors-panel"),c.on("selectstart",function(){return!1}).end(),t.swatches&&0!==t.swatches.length)for(t.swatches.length>7&&(t.swatches.length=7),c.addClass("minicolors-with-swatches"),n=$('<ul class="minicolors-swatches"></ul>').appendTo(c),l=0;l<t.swatches.length;++l)r=t.swatches[l],r=f(r)?u(r,!0):x(p(r,!0)),$('<li class="minicolors-swatch minicolors-sprite"><span class="minicolors-swatch-color"></span></li>').appendTo(n).data("swatch-color",t.swatches[l]).find(".minicolors-swatch-color").css({backgroundColor:y(r),opacity:r.a}),t.swatches[l]=r;t.inline&&i.parent().addClass("minicolors-inline"),e(i,!1),i.data("minicolors-initialized",!0)}}function t(i){var t=i.parent();i.removeData("minicolors-initialized").removeData("minicolors-settings").removeProp("size").removeClass("minicolors-input"),t.before(i).remove()}function o(i){var t=i.parent(),o=t.find(".minicolors-panel"),a=i.data("minicolors-settings");!i.data("minicolors-initialized")||i.prop("disabled")||t.hasClass("minicolors-inline")||t.hasClass("minicolors-focus")||(s(),t.addClass("minicolors-focus"),o.stop(!0,!0).fadeIn(a.showSpeed,function(){a.show&&a.show.call(i.get(0))}))}function s(){$(".minicolors-focus").each(function(){var i=$(this),t=i.find(".minicolors-input"),o=i.find(".minicolors-panel"),s=t.data("minicolors-settings");o.fadeOut(s.hideSpeed,function(){s.hide&&s.hide.call(t.get(0)),i.removeClass("minicolors-focus")})})}function a(i,t,o){var s=i.parents(".minicolors").find(".minicolors-input"),a=s.data("minicolors-settings"),r=i.find("[class$=-picker]"),e=i.offset().left,c=i.offset().top,l=Math.round(t.pageX-e),h=Math.round(t.pageY-c),d=o?a.animationSpeed:0,p,u,g,m;t.originalEvent.changedTouches&&(l=t.originalEvent.changedTouches[0].pageX-e,h=t.originalEvent.changedTouches[0].pageY-c),0>l&&(l=0),0>h&&(h=0),l>i.width()&&(l=i.width()),h>i.height()&&(h=i.height()),i.parent().is(".minicolors-slider-wheel")&&r.parent().is(".minicolors-grid")&&(p=75-l,u=75-h,g=Math.sqrt(p*p+u*u),m=Math.atan2(u,p),0>m&&(m+=2*Math.PI),g>75&&(g=75,l=75-75*Math.cos(m),h=75-75*Math.sin(m)),l=Math.round(l),h=Math.round(h)),i.is(".minicolors-grid")?r.stop(!0).animate({top:h+"px",left:l+"px"},d,a.animationEasing,function(){n(s,i)}):r.stop(!0).animate({top:h+"px"},d,a.animationEasing,function(){n(s,i)})}function n(i,t){function o(i,t){var o,s;return i.length&&t?(o=i.offset().left,s=i.offset().top,{x:o-t.offset().left+i.outerWidth()/2,y:s-t.offset().top+i.outerHeight()/2}):null}var s,a,n,e,l,h,d,p=i.val(),u=i.attr("data-opacity"),g=i.parent(),f=i.data("minicolors-settings"),v=g.find(".minicolors-input-swatch"),b=g.find(".minicolors-grid"),w=g.find(".minicolors-slider"),y=g.find(".minicolors-opacity-slider"),k=b.find("[class$=-picker]"),M=w.find("[class$=-picker]"),x=y.find("[class$=-picker]"),I=o(k,b),S=o(M,w),z=o(x,y);if(t.is(".minicolors-grid, .minicolors-slider, .minicolors-opacity-slider")){switch(f.control){case"wheel":e=b.width()/2-I.x,l=b.height()/2-I.y,h=Math.sqrt(e*e+l*l),d=Math.atan2(l,e),0>d&&(d+=2*Math.PI),h>75&&(h=75,I.x=69-75*Math.cos(d),I.y=69-75*Math.sin(d)),a=m(h/.75,0,100),s=m(180*d/Math.PI,0,360),n=m(100-Math.floor(S.y*(100/w.height())),0,100),p=C({h:s,s:a,b:n}),w.css("backgroundColor",C({h:s,s:a,b:100}));break;case"saturation":s=m(parseInt(I.x*(360/b.width()),10),0,360),a=m(100-Math.floor(S.y*(100/w.height())),0,100),n=m(100-Math.floor(I.y*(100/b.height())),0,100),p=C({h:s,s:a,b:n}),w.css("backgroundColor",C({h:s,s:100,b:n})),g.find(".minicolors-grid-inner").css("opacity",a/100);break;case"brightness":s=m(parseInt(I.x*(360/b.width()),10),0,360),a=m(100-Math.floor(I.y*(100/b.height())),0,100),n=m(100-Math.floor(S.y*(100/w.height())),0,100),p=C({h:s,s:a,b:n}),w.css("backgroundColor",C({h:s,s:a,b:100})),g.find(".minicolors-grid-inner").css("opacity",1-n/100);break;default:s=m(360-parseInt(S.y*(360/w.height()),10),0,360),a=m(Math.floor(I.x*(100/b.width())),0,100),n=m(100-Math.floor(I.y*(100/b.height())),0,100),p=C({h:s,s:a,b:n}),b.css("backgroundColor",C({h:s,s:100,b:100}))}u=f.opacity?parseFloat(1-z.y/y.height()).toFixed(2):1,r(i,p,u)}else v.find("span").css({backgroundColor:p,opacity:u}),c(i,p,u)}function r(i,t,o){var s,a=i.parent(),n=i.data("minicolors-settings"),r=a.find(".minicolors-input-swatch");n.opacity&&i.attr("data-opacity",o),"rgb"===n.format?(s=f(t)?u(t,!0):x(p(t,!0)),o=""===i.attr("data-opacity")?1:m(parseFloat(i.attr("data-opacity")).toFixed(2),0,1),(isNaN(o)||!n.opacity)&&(o=1),t=i.minicolors("rgbObject").a<=1&&s&&n.opacity?"rgba("+s.r+", "+s.g+", "+s.b+", "+parseFloat(o)+")":"rgb("+s.r+", "+s.g+", "+s.b+")"):(f(t)&&(t=w(t)),t=d(t,n.letterCase)),i.val(t),r.find("span").css({backgroundColor:t,opacity:o}),c(i,t,o)}function e(i,t){var o,s,a,n,r,e,l,h,b,y,M=i.parent(),x=i.data("minicolors-settings"),I=M.find(".minicolors-input-swatch"),S=M.find(".minicolors-grid"),z=M.find(".minicolors-slider"),F=M.find(".minicolors-opacity-slider"),D=S.find("[class$=-picker]"),T=z.find("[class$=-picker]"),j=F.find("[class$=-picker]");switch(f(i.val())?(o=w(i.val()),r=m(parseFloat(v(i.val())).toFixed(2),0,1),r&&i.attr("data-opacity",r)):o=d(p(i.val(),!0),x.letterCase),o||(o=d(g(x.defaultValue,!0),x.letterCase)),s=k(o),n=x.keywords?$.map(x.keywords.split(","),function(i){return $.trim(i.toLowerCase())}):[],e=""!==i.val()&&$.inArray(i.val().toLowerCase(),n)>-1?d(i.val()):f(i.val())?u(i.val()):o,t||i.val(e),x.opacity&&(a=""===i.attr("data-opacity")?1:m(parseFloat(i.attr("data-opacity")).toFixed(2),0,1),isNaN(a)&&(a=1),i.attr("data-opacity",a),I.find("span").css("opacity",a),h=m(F.height()-F.height()*a,0,F.height()),j.css("top",h+"px")),"transparent"===i.val().toLowerCase()&&I.find("span").css("opacity",0),I.find("span").css("backgroundColor",o),x.control){case"wheel":b=m(Math.ceil(.75*s.s),0,S.height()/2),y=s.h*Math.PI/180,l=m(75-Math.cos(y)*b,0,S.width()),h=m(75-Math.sin(y)*b,0,S.height()),D.css({top:h+"px",left:l+"px"}),h=150-s.b/(100/S.height()),""===o&&(h=0),T.css("top",h+"px"),z.css("backgroundColor",C({h:s.h,s:s.s,b:100}));break;case"saturation":l=m(5*s.h/12,0,150),h=m(S.height()-Math.ceil(s.b/(100/S.height())),0,S.height()),D.css({top:h+"px",left:l+"px"}),h=m(z.height()-s.s*(z.height()/100),0,z.height()),T.css("top",h+"px"),z.css("backgroundColor",C({h:s.h,s:100,b:s.b})),M.find(".minicolors-grid-inner").css("opacity",s.s/100);break;case"brightness":l=m(5*s.h/12,0,150),h=m(S.height()-Math.ceil(s.s/(100/S.height())),0,S.height()),D.css({top:h+"px",left:l+"px"}),h=m(z.height()-s.b*(z.height()/100),0,z.height()),T.css("top",h+"px"),z.css("backgroundColor",C({h:s.h,s:s.s,b:100})),M.find(".minicolors-grid-inner").css("opacity",1-s.b/100);break;default:l=m(Math.ceil(s.s/(100/S.width())),0,S.width()),h=m(S.height()-Math.ceil(s.b/(100/S.height())),0,S.height()),D.css({top:h+"px",left:l+"px"}),h=m(z.height()-s.h/(360/z.height()),0,z.height()),T.css("top",h+"px"),S.css("backgroundColor",C({h:s.h,s:100,b:100}))}i.data("minicolors-initialized")&&c(i,e,a)}function c(i,t,o){var s=i.data("minicolors-settings"),a=i.data("minicolors-lastChange"),n,r,e;if(!a||a.value!==t||a.opacity!==o){if(i.data("minicolors-lastChange",{value:t,opacity:o}),s.swatches&&0!==s.swatches.length){for(n=f(t)?u(t,!0):x(t),r=-1,e=0;e<s.swatches.length;++e)if(n.r===s.swatches[e].r&&n.g===s.swatches[e].g&&n.b===s.swatches[e].b&&n.a===s.swatches[e].a){r=e;break}i.parent().find(".minicolors-swatches .minicolors-swatch").removeClass("selected"),-1!==e&&i.parent().find(".minicolors-swatches .minicolors-swatch").eq(e).addClass("selected")}s.change&&(s.changeDelay?(clearTimeout(i.data("minicolors-changeTimeout")),i.data("minicolors-changeTimeout",setTimeout(function(){s.change.call(i.get(0),t,o)},s.changeDelay))):s.change.call(i.get(0),t,o)),i.trigger("change").trigger("input")}}function l(i){var t=p($(i).val(),!0),o=x(t),s=$(i).attr("data-opacity");return o?(void 0!==s&&$.extend(o,{a:parseFloat(s)}),o):null}function h(i,t){var o=p($(i).val(),!0),s=x(o),a=$(i).attr("data-opacity");return s?(void 0===a&&(a=1),t?"rgba("+s.r+", "+s.g+", "+s.b+", "+parseFloat(a)+")":"rgb("+s.r+", "+s.g+", "+s.b+")"):null}function d(i,t){return"uppercase"===t?i.toUpperCase():i.toLowerCase()}function p(i,t){return i=i.replace(/^#/g,""),i.match(/^[A-F0-9]{3,6}/gi)?3!==i.length&&6!==i.length?"":(3===i.length&&t&&(i=i[0]+i[0]+i[1]+i[1]+i[2]+i[2]),"#"+i):""}function u(i,t){var o=i.replace(/[^\d,.]/g,""),s=o.split(",");return s[0]=m(parseInt(s[0],10),0,255),s[1]=m(parseInt(s[1],10),0,255),s[2]=m(parseInt(s[2],10),0,255),s[3]&&(s[3]=m(parseFloat(s[3],10),0,1)),t?{r:s[0],g:s[1],b:s[2],a:s[3]?s[3]:null}:"undefined"!=typeof s[3]&&s[3]<=1?"rgba("+s[0]+", "+s[1]+", "+s[2]+", "+s[3]+")":"rgb("+s[0]+", "+s[1]+", "+s[2]+")"}function g(i,t){return f(i)?u(i):p(i,t)}function m(i,t,o){return t>i&&(i=t),i>o&&(i=o),i}function f(i){var t=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);return t&&4===t.length?!0:!1}function v(i){return i=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+(\.\d{1,2})?|\.\d{1,2})[\s+]?/i),i&&6===i.length?i[4]:"1"}function b(i){var t={},o=Math.round(i.h),s=Math.round(255*i.s/100),a=Math.round(255*i.b/100);if(0===s)t.r=t.g=t.b=a;else{var n=a,r=(255-s)*a/255,e=(n-r)*(o%60)/60;360===o&&(o=0),60>o?(t.r=n,t.b=r,t.g=r+e):120>o?(t.g=n,t.b=r,t.r=n-e):180>o?(t.g=n,t.r=r,t.b=r+e):240>o?(t.b=n,t.r=r,t.g=n-e):300>o?(t.b=n,t.g=r,t.r=r+e):360>o?(t.r=n,t.g=r,t.b=n-e):(t.r=0,t.g=0,t.b=0)}return{r:Math.round(t.r),g:Math.round(t.g),b:Math.round(t.b)}}function w(i){return i=i.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i),i&&4===i.length?"#"+("0"+parseInt(i[1],10).toString(16)).slice(-2)+("0"+parseInt(i[2],10).toString(16)).slice(-2)+("0"+parseInt(i[3],10).toString(16)).slice(-2):""}function y(i){var t=[i.r.toString(16),i.g.toString(16),i.b.toString(16)];return $.each(t,function(i,o){1===o.length&&(t[i]="0"+o)}),"#"+t.join("")}function C(i){return y(b(i))}function k(i){var t=M(x(i));return 0===t.s&&(t.h=360),t}function M(i){var t={h:0,s:0,b:0},o=Math.min(i.r,i.g,i.b),s=Math.max(i.r,i.g,i.b),a=s-o;return t.b=s,t.s=0!==s?255*a/s:0,0!==t.s?i.r===s?t.h=(i.g-i.b)/a:i.g===s?t.h=2+(i.b-i.r)/a:t.h=4+(i.r-i.g)/a:t.h=-1,t.h*=60,t.h<0&&(t.h+=360),t.s*=100/255,t.b*=100/255,t}function x(i){return i=parseInt(i.indexOf("#")>-1?i.substring(1):i,16),{r:i>>16,g:(65280&i)>>8,b:255&i}}$.minicolors={defaults:{animationSpeed:50,animationEasing:"swing",change:null,changeDelay:0,control:"hue",dataUris:!0,defaultValue:"",format:"hex",hide:null,hideSpeed:100,inline:!1,keywords:"",letterCase:"lowercase",opacity:!1,position:"bottom left",show:null,showSpeed:100,theme:"default",swatches:[]}},$.extend($.fn,{minicolors:function(a,n){switch(a){case"destroy":return $(this).each(function(){t($(this))}),$(this);case"hide":return s(),$(this);case"opacity":return void 0===n?$(this).attr("data-opacity"):($(this).each(function(){e($(this).attr("data-opacity",n))}),$(this));case"rgbObject":return l($(this),"rgbaObject"===a);case"rgbString":case"rgbaString":return h($(this),"rgbaString"===a);case"settings":return void 0===n?$(this).data("minicolors-settings"):($(this).each(function(){var i=$(this).data("minicolors-settings")||{};t($(this)),$(this).minicolors($.extend(!0,i,n))}),$(this));case"show":return o($(this).eq(0)),$(this);case"value":return void 0===n?$(this).val():($(this).each(function(){"object"==typeof n?(n.opacity&&$(this).attr("data-opacity",m(n.opacity,0,1)),n.color&&$(this).val(n.color)):$(this).val(n),e($(this))}),$(this));default:return"create"!==a&&(n=a),$(this).each(function(){i($(this),n)}),$(this)}}}),$(document).on("mousedown.minicolors touchstart.minicolors",function(i){$(i.target).parents().add(i.target).hasClass("minicolors")||s()}).on("mousedown.minicolors touchstart.minicolors",".minicolors-grid, .minicolors-slider, .minicolors-opacity-slider",function(i){var t=$(this);i.preventDefault(),$(document).data("minicolors-target",t),a(t,i,!0)}).on("mousemove.minicolors touchmove.minicolors",function(i){var t=$(document).data("minicolors-target");t&&a(t,i)}).on("mouseup.minicolors touchend.minicolors",function(){$(this).removeData("minicolors-target")}).on("click.minicolors",".minicolors-swatches li",function(i){i.preventDefault();var t=$(this),o=t.parents(".minicolors").find(".minicolors-input"),s=t.data("swatch-color");r(o,s,v(s)),e(o)}).on("mousedown.minicolors touchstart.minicolors",".minicolors-input-swatch",function(i){var t=$(this).parent().find(".minicolors-input");i.preventDefault(),o(t)}).on("focus.minicolors",".minicolors-input",function(){var i=$(this);i.data("minicolors-initialized")&&o(i)}).on("blur.minicolors",".minicolors-input",function(){var i=$(this),t=i.data("minicolors-settings"),o,s,a,n,r;i.data("minicolors-initialized")&&(o=t.keywords?$.map(t.keywords.split(","),function(i){return $.trim(i.toLowerCase())}):[],""!==i.val()&&$.inArray(i.val().toLowerCase(),o)>-1?r=i.val():(f(i.val())?a=u(i.val(),!0):(s=p(i.val(),!0),a=s?x(s):null),r=null===a?t.defaultValue:"rgb"===t.format?u(t.opacity?"rgba("+a.r+","+a.g+","+a.b+","+i.attr("data-opacity")+")":"rgb("+a.r+","+a.g+","+a.b+")"):y(a)),n=t.opacity?i.attr("data-opacity"):1,"transparent"===r.toLowerCase()&&(n=0),i.closest(".minicolors").find(".minicolors-input-swatch > span").css("opacity",n),i.val(r),""===i.val()&&i.val(g(t.defaultValue,!0)),i.val(d(i.val(),t.letterCase)))}).on("keydown.minicolors",".minicolors-input",function(i){var t=$(this);if(t.data("minicolors-initialized"))switch(i.keyCode){case 9:s();break;case 13:case 27:s(),t.blur()}}).on("keyup.minicolors",".minicolors-input",function(){var i=$(this);i.data("minicolors-initialized")&&e(i,!0)}).on("paste.minicolors",".minicolors-input",function(){var i=$(this);i.data("minicolors-initialized")&&setTimeout(function(){e(i,!0)},1)})});
\ No newline at end of file
index 2de506d..ff5c5af 100644 (file)
@@ -65,7 +65,7 @@ styles.content.imgtext {
   textMargin = 10
 
     # cat=content/cImage/i1; type=color; label= Image border, color: Bordercolor of images in content elements when "Border"-option for element is set.
-  borderColor = black
+  borderColor = #000000
     # cat=content/cImage/i2; type=int[0-100]; label= Image border, thickness: Thickness of border around images in content elements when "Border"-option for element is set.
   borderThick = 2
     # cat=content/cImage/i3; type=int+; label= Image border, padding: Padding left and right to the image, around the border.
@@ -101,15 +101,15 @@ styles.content.table {
     # cat=content/cTable/k3; type=color; label= Table background color, Color 2: Background color for table when "Backgr. Color" has been set to "Color 2"
   backgroundColor.2 = #F5FFAA
     # cat=content/cTable/k5; type=color; label= Table background color, Black: Background color for table when "Backgr. Color" has been set to "Black"
-  backgroundColor.240 = black
+  backgroundColor.240 = #000000
     # cat=content/cTable/k6; type=color; label= Table background color, White: Background color for table when "Backgr. Color" has been set to "White"
-  backgroundColor.241 = white
+  backgroundColor.241 = #FFFFFF
     # cat=content/cTable/k7; type=color; label= Table background color, Dark Gray: Background color for table when "Backgr. Color" has been set to "Dark Gray"
   backgroundColor.242 = #333333
     # cat=content/cTable/k8; type=color; label= Table background color, Gray: Background color for table when "Backgr. Color" has been set to "Gray"
-  backgroundColor.243 = gray
+  backgroundColor.243 = #808080
     # cat=content/cTable/k9; type=color; label= Table background color, Silver: Background color for table when "Backgr. Color" has been set to "Silver"
-  backgroundColor.244 = silver
+  backgroundColor.244 = #C0C0C0
 }
 
  # cat=advanced/links; type=small; label= Target for internal links: Should match the name of the content PAGE-object in TypoScript when used with frames. Most cases: set to "" (empty). If you have frames in the template set to "page"
index 70b7f1d..ab0e1d1 100644 (file)
@@ -63,7 +63,9 @@ styles.content.imgtext {
   textMargin = 10
 
     # cat=content/cImage/i1; type=color; label= Image border, color: Bordercolor of images in content elements when "Border"-option for element is set.
-  borderColor = black
+  borderColor = #000000
+    # cat=content/cImage/i1; type=color; label= Image border, color: Bordercolor of images in content elements when "Border"-option for element is set.
+  borderColor2 = #000000
     # cat=content/cImage/i2; type=int[0-100]; label= Image border, thickness: Thickness of border around images in content elements when "Border"-option for element is set.
   borderThick = 2
     # cat=content/cImage/i3; type=int+; label= Image border, padding: Padding left and right to the image, around the border.
@@ -91,15 +93,15 @@ styles.content.table {
     # cat=content/cTable/k3; type=color; label= Table background color, Color 2: Background color for table when "Backgr. Color" has been set to "Color 2"
   backgroundColor.2 = #F5FFAA
     # cat=content/cTable/k5; type=color; label= Table background color, Black: Background color for table when "Backgr. Color" has been set to "Black"
-  backgroundColor.240 = black
+  backgroundColor.240 = #000000
     # cat=content/cTable/k6; type=color; label= Table background color, White: Background color for table when "Backgr. Color" has been set to "White"
-  backgroundColor.241 = white
+  backgroundColor.241 = #FFFFFF
     # cat=content/cTable/k7; type=color; label= Table background color, Dark Gray: Background color for table when "Backgr. Color" has been set to "Dark Gray"
   backgroundColor.242 = #333333
     # cat=content/cTable/k8; type=color; label= Table background color, Gray: Background color for table when "Backgr. Color" has been set to "Gray"
-  backgroundColor.243 = gray
+  backgroundColor.243 = #808080
     # cat=content/cTable/k9; type=color; label= Table background color, Silver: Background color for table when "Backgr. Color" has been set to "Silver"
-  backgroundColor.244 = silver
+  backgroundColor.244 = #C0C0C0
 }
 
  # cat=advanced/links; type=small; label= Target for internal links: Should match the name of the content PAGE-object in TypoScript when used with frames. Most cases: set to "" (empty). If you have frames in the template set to "page"
index a63cbc3..78d2436 100644 (file)
@@ -101,26 +101,20 @@ class TypoScriptConstantsViewHelper extends \TYPO3\CMS\Fluid\Core\ViewHelper\Abs
             $this->tag->addAttribute('value', $configuration->getValue());
         }
 
-        // configure colorpicker wizard
-        $params = array(
-            'formName' => 'configurationform',
-            'itemName' => $elementName,
-        );
-        $onClick =
-            'this.blur();' .
-            'vHWin=window.open(' .
-                GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('wizard_colorpicker', array('P' => $params))) . ' + \'&P[currentValue]=\' + encodeURIComponent(document.getElementById(' . GeneralUtility::quoteJSvalue($elementId) . ').value),' .
-                '\'popUpem-' . GeneralUtility::shortMD5($elementName) . '\',' .
-                '\'height=400,width=400,status=0,menubar=0,scrollbars=1\'' .
-            ');' .
-            'vHWin.focus();' .
-            'return false;';
-
-        // wrap the field
-        $output = '<div class="form-wizards-wrap form-wizards-aside">'
-                . '<div class="form-wizards-element">' . $this->tag->render() . '</div>'
-                . '<div class="form-wizards-items"><a href="#" onClick="' . htmlspecialchars($onClick) . '" class="btn btn-default"><span class="t3-icon fa fa-eyedropper"></span></a></div>'
-                . '</div>';
+        $output = '
+            <div class="form-wizards-element">
+                <input class="form-control t3js-color-input formengine-colorpickerelement" type="text"
+                  name="' . htmlspecialchars($elementName) . '" value="' . $this->tag->getAttribute('value') . '"/>
+                <script type="text/javascript">
+                    require([\'TYPO3/CMS/Core/Contrib/jquery.minicolors\'], function () {
+                        $(\'.formengine-colorpickerelement\').minicolors({
+                            theme: \'bootstrap\',
+                            format: \'hex\',
+                            position: \'bottom left\'
+                        });
+                    });
+                </script>
+            </div>';
 
         return $output;
     }
index 483471b..c6a315e 100644 (file)
@@ -31,7 +31,7 @@ styles.content {
                textMargin = 10
 
                # cat=content/cTextmedia/i1; type=color; label= Media element border, color: Bordercolor of media elements in content elements when "Border"-option for an element is set
-               borderColor = black
+               borderColor = #000000
                # cat=content/cTextmedia/i2; type=int[0-100]; label= Media element border, thickness: Thickness of border around media elements in content elements when "Border"-option for element is set
                borderWidth = 2
                # cat=content/cTextmedia/i3; type=int+; label= Media element border, padding: Padding left and right to the media element, around the border
index d095ed6..539d833 100644 (file)
@@ -7875,6 +7875,198 @@ button.close {
     display: none !important;
   }
 }
+.minicolors {
+  position: relative;
+}
+.userTS .minicolors {
+  position: absolute;
+}
+.minicolors-sprite {
+  background-image: url("../../../../../../typo3/sysext/core/Resources/Public/Images/colorpicker/jquery.minicolors.png");
+}
+.minicolors-swatch {
+  position: absolute;
+  vertical-align: middle;
+  background-position: -80px 0;
+  cursor: text;
+  padding: 0;
+  margin: 0;
+  display: inline-block;
+  top: 50%;
+  left: 6px;
+  z-index: 2;
+  -webkit-transform: translate(0, -50%);
+          transform: translate(0, -50%);
+  width: 20px;
+  height: 20px;
+  border-radius: 1px;
+}
+.minicolors-swatch-color {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  border-radius: inherit;
+}
+.minicolors-input {
+  float: none;
+  padding-left: 32px;
+}
+.minicolors-panel {
+  margin-top: 1px;
+  overflow: hidden;
+  border-radius: 2px;
+  position: absolute;
+  width: 173px;
+  height: 152px;
+  background: #ffffff;
+  border: solid 1px #bbbbbb;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
+  z-index: 99999;
+  box-sizing: content-box;
+  display: none;
+}
+.minicolors-panel.minicolors-with-swatches {
+  height: 182px;
+}
+.minicolors-panel.minicolors-visible {
+  display: block;
+}
+.minicolors-position-top .minicolors-panel {
+  top: -154px;
+}
+.minicolors-position-right .minicolors-panel {
+  right: 0;
+}
+.minicolors-position-bottom .minicolors-panel {
+  top: auto;
+}
+.minicolors-position-left .minicolors-panel {
+  left: 0;
+}
+.minicolors-with-opacity .minicolors-panel {
+  width: 194px;
+}
+.minicolors .minicolors-grid {
+  position: absolute;
+  top: 1px;
+  left: 1px;
+  width: 150px;
+  height: 150px;
+  background-position: -120px 0;
+  cursor: crosshair;
+}
+.minicolors .minicolors-grid-inner {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 150px;
+  height: 150px;
+}
+.minicolors-slider-saturation .minicolors-grid {
+  background-position: -420px 0;
+}
+.minicolors-slider-saturation .minicolors-grid-inner {
+  background-position: -270px 0;
+  background-image: inherit;
+}
+.minicolors-slider-brightness .minicolors-grid {
+  background-position: -570px 0;
+}
+.minicolors-slider-brightness .minicolors-grid-inner {
+  background-color: black;
+}
+.minicolors-slider-wheel .minicolors-grid {
+  background-position: -720px 0;
+}
+.minicolors-slider,
+.minicolors-opacity-slider {
+  position: absolute;
+  top: 1px;
+  left: 152px;
+  width: 20px;
+  height: 150px;
+  background-color: white;
+  background-position: 0 0;
+  cursor: row-resize;
+}
+.minicolors-slider-saturation .minicolors-slider {
+  background-position: -60px 0;
+}
+.minicolors-slider-brightness .minicolors-slider {
+  background-position: -20px 0;
+}
+.minicolors-slider-wheel .minicolors-slider {
+  background-position: -20px 0;
+}
+.minicolors-opacity-slider {
+  left: 173px;
+  background-position: -40px 0;
+  display: none;
+}
+.minicolors-with-opacity .minicolors-opacity-slider {
+  display: block;
+}
+.minicolors-grid .minicolors-picker {
+  position: absolute;
+  top: 70px;
+  left: 70px;
+  width: 12px;
+  height: 12px;
+  border: solid 1px black;
+  border-radius: 10px;
+  margin-top: -6px;
+  margin-left: -6px;
+  background: none;
+}
+.minicolors-grid .minicolors-picker > div {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 8px;
+  height: 8px;
+  border-radius: 8px;
+  border: solid 2px white;
+  box-sizing: content-box;
+}
+.minicolors-picker {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 18px;
+  height: 2px;
+  background: white;
+  border: solid 1px black;
+  margin-top: -2px;
+  box-sizing: content-box;
+}
+.minicolors-swatches,
+.minicolors-swatches li {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  overflow: hidden;
+  position: absolute;
+  top: 157px;
+  left: 5px;
+}
+.minicolors-swatches .minicolors-swatch {
+  position: relative;
+  float: left;
+  cursor: pointer;
+  margin: 0 4px 0 0;
+  top: 0;
+  left: 0;
+  width: 20px;
+  height: 20px;
+}
+.minicolors-with-opacity .minicolors-swatches .minicolors-swatch {
+  margin-right: 7px;
+}
+.minicolors-swatch.selected {
+  border-color: #000;
+}
 /*!
  * Datetimepicker for Bootstrap 3
  * version : 4.17.37
index 7877c38..2ccf67d 100644 (file)
@@ -172,6 +172,10 @@ class TypoScriptTemplateConstantEditorModuleFunctionController extends AbstractF
             $templateService->ext_getTSCE_config($category);
 
             $printFields = trim($templateService->ext_printFields($theConstants, $category));
+            foreach ($templateService->getInlineJavaScript() as $name => $inlineJavaScript) {
+                $this->pageRenderer->addJsInlineCode($name, $inlineJavaScript);
+            }
+
             if ($printFields) {
                 $theOutput .= '<div>' . $printFields . '</div>';
             }