Implement ColorSuggestionPicker page popup
authorkeishi@webkit.org <keishi@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2012 11:57:21 +0000 (11:57 +0000)
committerkeishi@webkit.org <keishi@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2012 11:57:21 +0000 (11:57 +0000)
https://bugs.webkit.org/show_bug.cgi?id=92109

Reviewed by Kent Tamura.

.:

* ManualTests/forms/color-suggestion-picker.html: Added. Tests colorSuggestionPicker.{js,css}

Source/WebCore:

Implements ColorSuggestionPicker page popup. This will be used in
certain ports as the datalist UI for <input type=color>.

No new tests because there is no way to open the popup yet.

* Resources/colorSuggestionPicker.css: Added.
(body):
(#main):
(.color-swatch):
(.color-swatch:hover):
(.color-swatch-container):
(.other-color):
* Resources/colorSuggestionPicker.js: Added.
(getScrollbarWidth):When there are more than 20 colors we need to
increase the window width to accommodate the scroll bar.
(createElement):
(handleMessage):
(initialize):
(handleArgumentsTimeout):
(validateArguments):
(submitValue): Calls setValueAndClosePopup with a numValue of 0.
(handleCancel): Calls setValueAndClosePopup with a numValue of -1.
(chooseOtherColor): Calls setValueAndClosePopup with a numValue of -2.
(ColorPicker):
(ColorPicker.prototype._layout): Lays out the color swatches in a 5x4
grid.
(ColorPicker.prototype._handleSwatchClick):
* WebCore.gyp/WebCore.gyp:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@123606 268f45cc-cd09-0410-ab3c-d52691b4dbfc

ChangeLog
ManualTests/forms/color-suggestion-picker.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Resources/colorSuggestionPicker.css [new file with mode: 0644]
Source/WebCore/Resources/colorSuggestionPicker.js [new file with mode: 0644]
Source/WebCore/WebCore.gyp/WebCore.gyp

index 10fc80e..e8ed8fe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2012-07-25  Keishi Hattori  <keishi@webkit.org>
+
+        Implement ColorSuggestionPicker page popup
+        https://bugs.webkit.org/show_bug.cgi?id=92109
+
+        Reviewed by Kent Tamura.
+
+        * ManualTests/forms/color-suggestion-picker.html: Added. Tests colorSuggestionPicker.{js,css}
+
 2012-07-23  Kent Tamura  <tkent@chromium.org>
 
         [GTK] Remove unnecessary trailing space in the previous commit.
diff --git a/ManualTests/forms/color-suggestion-picker.html b/ManualTests/forms/color-suggestion-picker.html
new file mode 100644 (file)
index 0000000..6a25c74
--- /dev/null
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<title>Color Suggestion Picker test</title>
+<style>
+body {
+    background-color: #eeffff;
+}
+iframe {
+    z-index: 2147483647;
+    width: 180px;
+    height: 240px;
+    border: 0;
+    overflow: hidden;
+}
+</style>
+</head>
+<body>
+
+<p>This is a testbed for a color suggestion picker.</p>
+
+<div><input type="color" id="color"></div>
+<iframe></iframe>
+
+<ol id="console" style="font-family:monospace;">
+</ol>
+
+<script>
+var arguments = {
+    values : ['#000000', '#404040', '#808080', '#c0c0c0', '#ffffff', '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff', '#404040', '#808080', '#c0c0c0', '#ffffff', '#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff'],
+    otherColorLabel: 'Other...'
+};
+
+function openColorPicker(args) {
+    var frame = document.getElementsByTagName('iframe')[0];
+    var doc = frame.contentDocument;
+    doc.documentElement.innerHTML = '<head></head><body><div id=main>Loading...</div></body>';
+    var link = doc.createElement('link');
+    link.rel = 'stylesheet';
+    link.href = '../../Source/WebCore/Resources/colorSuggestionPicker.css?' + (new Date()).getTime();
+    doc.head.appendChild(link);
+    var script = doc.createElement('script');
+    script.src = '../../Source/WebCore/Resources/colorSuggestionPicker.js?' + (new Date()).getTime();
+    doc.body.appendChild(script);
+
+    var pagePopupController = {
+        setValueAndClosePopup: function(numValue, stringValue) {
+            window.log('number=' + numValue + ', string="' + stringValue + '"');
+            if (numValue === 0)
+                window.document.getElementById('color').value = stringValue;
+        }
+    }
+
+    setTimeout(function() {
+        frame.contentWindow.postMessage(JSON.stringify(args), "*");
+        frame.contentWindow.pagePopupController = pagePopupController;
+    }, 100);
+}
+
+function log(str) {
+    var entry = document.createElement('li');
+    entry.innerText = str;
+    document.getElementById('console').appendChild(entry);
+}
+
+openColorPicker(arguments);
+</script>
+</body>
+</html>
\ No newline at end of file
index 805aae5..c12dc58 100644 (file)
@@ -1,3 +1,39 @@
+2012-07-25  Keishi Hattori  <keishi@webkit.org>
+
+        Implement ColorSuggestionPicker page popup
+        https://bugs.webkit.org/show_bug.cgi?id=92109
+
+        Reviewed by Kent Tamura.
+
+        Implements ColorSuggestionPicker page popup. This will be used in
+        certain ports as the datalist UI for <input type=color>.
+
+        No new tests because there is no way to open the popup yet.
+
+        * Resources/colorSuggestionPicker.css: Added.
+        (body):
+        (#main):
+        (.color-swatch):
+        (.color-swatch:hover):
+        (.color-swatch-container):
+        (.other-color):
+        * Resources/colorSuggestionPicker.js: Added.
+        (getScrollbarWidth):When there are more than 20 colors we need to
+        increase the window width to accommodate the scroll bar.
+        (createElement):
+        (handleMessage):
+        (initialize):
+        (handleArgumentsTimeout):
+        (validateArguments):
+        (submitValue): Calls setValueAndClosePopup with a numValue of 0.
+        (handleCancel): Calls setValueAndClosePopup with a numValue of -1.
+        (chooseOtherColor): Calls setValueAndClosePopup with a numValue of -2.
+        (ColorPicker):
+        (ColorPicker.prototype._layout): Lays out the color swatches in a 5x4
+        grid.
+        (ColorPicker.prototype._handleSwatchClick):
+        * WebCore.gyp/WebCore.gyp:
+
 2012-07-25  Allan Sandfeld Jensen  <allan.jensen@nokia.com>
 
         Fix arithmetic composite filter for auto-vectorization
diff --git a/Source/WebCore/Resources/colorSuggestionPicker.css b/Source/WebCore/Resources/colorSuggestionPicker.css
new file mode 100644 (file)
index 0000000..580dc9a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+body {
+    -webkit-user-select: none;
+    background-color: white;
+    font: -webkit-small-control;
+    margin: 0;
+    overflow: hidden;
+}
+
+#main {
+    background-color: white;
+    border: solid 1px #8899aa;
+    box-shadow: inset 2px 2px 2px white,
+        inset -2px -2px 1px rgba(0,0,0,0.1);
+    padding: 6px;
+    float: left;
+}
+
+.color-swatch {
+    float: left;
+    width: 20px;
+    height: 20px;
+    margin: 1px;
+    border: 1px solid #e0e0e0;
+}
+
+.color-swatch:hover {
+    border: 1px solid #000000;
+    margin: 1px;
+}
+
+.color-swatch-container {
+    width: 100%;
+    max-height: 104px;
+    overflow: auto;
+}
+
+.other-color {
+    width: 100%;
+    margin: 4px 0 0 0;
+}
diff --git a/Source/WebCore/Resources/colorSuggestionPicker.js b/Source/WebCore/Resources/colorSuggestionPicker.js
new file mode 100644 (file)
index 0000000..be20484
--- /dev/null
@@ -0,0 +1,192 @@
+"use strict";
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var global = {
+    argumentsReceived: false,
+    scrollbarWidth: null
+};
+
+/**
+ * @param {!string} id
+ */
+function $(id) {
+    return document.getElementById(id);
+}
+
+function bind(func, context) {
+    return function() {
+        return func.apply(context, arguments);
+    };
+}
+
+function getScrollbarWidth() {
+    if (gloabal.scrollbarWidth === null) {
+        var scrollDiv = document.createElement("div");
+        scrollDiv.style.opacity = "0";
+        scrollDiv.style.overflow = "scroll";
+        scrollDiv.style.width = "50px";
+        scrollDiv.style.height = "50px";
+        document.body.appendChild(scrollDiv);
+        gloabal.scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+        scrollDiv.parentNode.removeChild(scrollDiv);
+    }
+    return gloabal.scrollbarWidth;
+}
+
+/**
+ * @param {!string} tagName
+ * @param {string=} opt_class
+ * @param {string=} opt_text
+ * @return {!Element}
+ */
+function createElement(tagName, opt_class, opt_text) {
+    var element = document.createElement(tagName);
+    if (opt_class)
+        element.setAttribute("class", opt_class);
+    if (opt_text)
+        element.appendChild(document.createTextNode(opt_text));
+    return element;
+}
+
+/**
+ * @param {Event} event
+ */
+function handleMessage(event) {
+    initialize(JSON.parse(event.data));
+    global.argumentsReceived = true;
+}
+
+/**
+ * @param {!Object} args
+ */
+function initialize(args) {
+    var main = $("main");
+    main.innerHTML = "";
+    var errorString = validateArguments(args);
+    if (errorString)
+        main.textContent = "Internal error: " + errorString;
+    else
+        new ColorPicker(main, args);
+}
+
+// The DefaultColorPalette is used when the list of values are empty. 
+var DefaultColorPalette = ["#000000", "#404040", "#808080", "#c0c0c0",
+    "#ffffff", "#980000", "#ff0000", "#ff9900", "#ffff00", "#00ff00", "#00ffff",
+    "#4a86e8", "#0000ff", "#9900ff", "#ff00ff"];
+
+function handleArgumentsTimeout() {
+    if (global.argumentsReceived)
+        return;
+    var args = {
+        values : DefaultColorPalette,
+        otherColorLabel: "Other..."
+    };
+    initialize(args);
+}
+
+/**
+ * @param {!Object} args
+ * @return {?string} An error message, or null if the argument has no errors.
+ */
+function validateArguments(args) {
+    if (!args.values)
+        return "No values.";
+    if (!args.otherColorLabel)
+        return "No otherColorLabel.";
+    return null;
+}
+
+var Actions = {
+    ChooseOtherColor: -2,
+    Cancel: -1,
+    SetValue: 0
+};
+
+/**
+ * @param {string} value
+ */
+function submitValue(value) {
+    window.pagePopupController.setValueAndClosePopup(Actions.SetValue, value);
+}
+
+function handleCancel() {
+    window.pagePopupController.setValueAndClosePopup(Actions.Cancel, "");
+}
+
+function chooseOtherColor() {
+    window.pagePopupController.setValueAndClosePopup(Actions.ChooseOtherColor, "");
+}
+
+function ColorPicker(element, config) {
+    this._element = element;
+    this._config = config;
+    if (this._config.values.length === 0)
+        this._config.values = DefaultColorPalette;
+    this._layout();
+}
+
+var SwatchBorderBoxWidth = 24; // keep in sync with CSS
+var SwatchBorderBoxHeight = 24; // keep in sync with CSS
+var SwatchesPerRow = 5;
+var SwatchesMaxRow = 4;
+
+ColorPicker.prototype._layout = function() {
+    var container = createElement("div", "color-swatch-container");
+    container.addEventListener("click", bind(this._handleSwatchClick, this), false);
+    for (var i = 0; i < this._config.values.length; ++i) {
+        var swatch = createElement("div", "color-swatch");
+        swatch.dataset.value = this._config.values[i];
+        swatch.title = this._config.values[i];
+        swatch.style.backgroundColor = this._config.values[i];
+        container.appendChild(swatch);
+    }
+    var containerWidth = SwatchBorderBoxWidth * SwatchesPerRow;
+    if (this._config.values.length > SwatchesPerRow * SwatchesMaxRow)
+        containerWidth += getScrollbarWidth();
+    container.style.width = containerWidth + "px";
+    container.style.maxHeight = (SwatchBorderBoxHeight * SwatchesMaxRow) + "px";
+    this._element.appendChild(container);
+    var otherButton = createElement("button", "other-color", this._config.otherColorLabel);
+    otherButton.addEventListener("click", chooseOtherColor, false);
+    this._element.appendChild(otherButton);
+    if (window.frameElement) {
+        window.frameElement.style.width = this._element.offsetWidth + "px";
+        window.frameElement.style.height = this._element.offsetHeight + "px";
+    } else {
+        window.resizeTo(this._element.offsetWidth, this._element.offsetHeight);
+    }
+};
+
+ColorPicker.prototype._handleSwatchClick = function(event) {
+    if (event.target.classList.contains("color-swatch"))
+        submitValue(event.target.dataset.value);
+};
+
+if (window.dialogArguments) {
+    initialize(dialogArguments);
+} else {
+    window.addEventListener("message", handleMessage, false);
+    window.setTimeout(handleArgumentsTimeout, 1000);
+}
index dfb9ffa..6ba058e 100644 (file)
           ],
         },
         {
+          'action_name': 'ColorSuggestionPicker',
+          'inputs': [
+            '../Resources/colorSuggestionPicker.css',
+            '../Resources/colorSuggestionPicker.js',
+          ],
+          'outputs': [
+            '<(SHARED_INTERMEDIATE_DIR)/webkit/ColorSuggestionPicker.h',
+            '<(SHARED_INTERMEDIATE_DIR)/webkit/ColorSuggestionPicker.cpp',
+          ],
+          'action': [
+            'python',
+            '../make-file-arrays.py',
+            '--condition=ENABLE(INPUT_TYPE_COLOR) && ENABLE(DATALIST_ELEMENT) && ENABLE(PAGE_POPUP)',
+            '--out-h=<(SHARED_INTERMEDIATE_DIR)/webkit/ColorSuggestionPicker.h',
+            '--out-cpp=<(SHARED_INTERMEDIATE_DIR)/webkit/ColorSuggestionPicker.cpp',
+            '<@(_inputs)',
+          ],
+        },
+        {
           'action_name': 'XLinkNames',
           'inputs': [
             '../dom/make_names.pl',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/HTMLElementFactory.cpp',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/HTMLNames.cpp',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/CalendarPicker.cpp',
+        '<(SHARED_INTERMEDIATE_DIR)/webkit/ColorSuggestionPicker.cpp',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/EventFactory.cpp',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/EventHeaders.h',
         '<(SHARED_INTERMEDIATE_DIR)/webkit/EventInterfaces.h',