diff --git a/browser/devtools/shared/test/browser_outputparser.js b/browser/devtools/shared/test/browser_outputparser.js
index 5cc0e0abdfac..ab34bf14d7dc 100644
--- a/browser/devtools/shared/test/browser_outputparser.js
+++ b/browser/devtools/shared/test/browser_outputparser.js
@@ -37,11 +37,23 @@ function testParseCssProperty() {
target.appendChild(frag);
is(target.innerHTML,
- '1px solid #F00',
+ '1px solid #F00',
"CSS property correctly parsed");
target.innerHTML = "";
+ let frag = parser.parseCssProperty("background-image", "linear-gradient(to right, #F60 10%, rgba(0,0,0,1))", {
+ colorSwatchClass: "test-colorswatch",
+ colorClass: "test-color"
+ });
+ target.appendChild(frag);
+ is(target.innerHTML,
+ 'linear-gradient(to right, #F60 10%, ' +
+ '#000)',
+ "Gradient CSS property correctly parsed");
+
+ target.innerHTML = "";
+
testParseHTMLAttribute();
}
@@ -49,14 +61,15 @@ function testParseHTMLAttribute() {
let attrib = "color:red; font-size: 12px; background-image: " +
"url(chrome://branding/content/about-logo.png)";
let frag = parser.parseHTMLAttribute(attrib, {
- urlClass: "theme-link"
+ urlClass: "theme-link",
+ colorClass: "theme-color"
});
let target = doc.querySelector("div");
ok(target, "captain, we have the div");
target.appendChild(frag);
- let expected = 'color:#F00; font-size: 12px; ' +
+ let expected = 'color:#F00; font-size: 12px; ' +
'background-image: url(\'chrome://branding/content/about-logo.png\')';
diff --git a/browser/devtools/styleinspector/rule-view.js b/browser/devtools/styleinspector/rule-view.js
index 09d677d2530d..01e4879c4ef1 100644
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -2023,6 +2023,7 @@ TextPropertyEditor.prototype = {
let outputParser = this.ruleEditor.ruleView._outputParser;
let frag = outputParser.parseCssProperty(name, val, {
colorSwatchClass: swatchClass,
+ colorClass: "ruleview-color",
defaultColorType: !propDirty,
urlClass: "theme-link",
baseURI: this.sheetURI
diff --git a/browser/devtools/styleinspector/test/browser.ini b/browser/devtools/styleinspector/test/browser.ini
index 0ca9347280a9..d0e21683383c 100644
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -53,3 +53,4 @@ support-files = browser_ruleview_pseudoelement.html
[browser_bug913014_matched_expand.js]
[browser_bug765105_background_image_tooltip.js]
[browser_bug889638_rule_view_color_picker.js]
+[browser_bug940500_rule_view_pick_gradient_color.js]
diff --git a/browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js b/browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js
new file mode 100644
index 000000000000..d52cae7090ac
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js
@@ -0,0 +1,135 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that changing a color in a gradient css declaration using the tooltip
+// color picker works
+
+let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
+
+let contentDoc;
+let contentWin;
+let inspector;
+let ruleView;
+
+const PAGE_CONTENT = [
+ '',
+ 'Updating a gradient declaration with the color picker tooltip'
+].join("\n");
+
+function test() {
+ waitForExplicitFinish();
+
+ gBrowser.selectedTab = gBrowser.addTab();
+ gBrowser.selectedBrowser.addEventListener("load", function(evt) {
+ gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
+ contentDoc = content.document;
+ contentWin = contentDoc.defaultView;
+ waitForFocus(createDocument, content);
+ }, true);
+
+ content.location = "data:text/html,rule view color picker tooltip test";
+}
+
+function createDocument() {
+ contentDoc.body.innerHTML = PAGE_CONTENT;
+
+ openRuleView((aInspector, aRuleView) => {
+ inspector = aInspector;
+ ruleView = aRuleView;
+ startTests();
+ });
+}
+
+function startTests() {
+ inspector.selection.setNode(contentDoc.body);
+ inspector.once("inspector-updated", testColorParsing);
+}
+
+function endTests() {
+ executeSoon(function() {
+ gDevTools.once("toolbox-destroyed", () => {
+ contentDoc = contentWin = inspector = ruleView = null;
+ gBrowser.removeCurrentTab();
+ finish();
+ });
+ inspector._toolbox.destroy();
+ });
+}
+
+function testColorParsing() {
+ let ruleEl = getRuleViewProperty("background-image");
+ ok(ruleEl, "The background-image gradient declaration was found");
+
+ let swatchEls = ruleEl.valueSpan.querySelectorAll(".ruleview-colorswatch");
+ ok(swatchEls, "The color swatch elements were found");
+ is(swatchEls.length, 3, "There are 3 color swatches");
+
+ let colorEls = ruleEl.valueSpan.querySelectorAll(".ruleview-color");
+ ok(colorEls, "The color elements were found");
+ is(colorEls.length, 3, "There are 3 color values");
+
+ let colors = ["#F06", "#333", "#000"];
+ for (let i = 0; i < colors.length; i ++) {
+ is(colorEls[i].textContent, colors[i], "The right color value was found");
+ }
+
+ testPickingNewColor();
+}
+
+function testPickingNewColor() {
+ // Grab the first color swatch and color in the gradient
+ let ruleEl = getRuleViewProperty("background-image");
+ let swatchEl = ruleEl.valueSpan.querySelector(".ruleview-colorswatch");
+ let colorEl = ruleEl.valueSpan.querySelector(".ruleview-color");
+
+ // Get the color picker tooltip
+ let cPicker = ruleView.colorPicker;
+
+ cPicker.tooltip.once("shown", () => {
+ simulateColorChange(cPicker, [1, 1, 1, 1]);
+
+ executeSoon(() => {
+ is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
+ "The color swatch's background was updated");
+ is(colorEl.textContent, "rgba(1, 1, 1, 1)",
+ "The color text was updated");
+ is(content.getComputedStyle(content.document.body).backgroundImage,
+ "linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
+ "The gradient has been updated correctly");
+
+ cPicker.hide();
+ endTests();
+ });
+ });
+ swatchEl.click();
+}
+
+function simulateColorChange(colorPicker, newRgba) {
+ // Note that this test isn't concerned with simulating events to test how the
+ // spectrum color picker reacts, see browser_spectrum.js for this.
+ // This test only cares about the color swatch <-> color picker <-> rule view
+ // interactions. That's why there's no event simulations here
+ colorPicker.spectrum.then(spectrum => {
+ spectrum.rgb = newRgba;
+ spectrum.updateUI();
+ spectrum.onChange();
+ });
+}
+
+function getRuleViewProperty(name) {
+ let prop = null;
+ [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
+ let nameSpan = property.querySelector(".ruleview-propertyname");
+ let valueSpan = property.querySelector(".ruleview-propertyvalue");
+
+ if (nameSpan.textContent === name) {
+ prop = {nameSpan: nameSpan, valueSpan: valueSpan};
+ }
+ });
+ return prop;
+}
diff --git a/toolkit/devtools/output-parser.js b/toolkit/devtools/output-parser.js
index 036378b1bd4c..a17a419b1dc9 100644
--- a/toolkit/devtools/output-parser.js
+++ b/toolkit/devtools/output-parser.js
@@ -304,7 +304,9 @@ OutputParser.prototype = {
if (options.defaultColorType) {
color = colorObj.toString();
}
- this._appendTextNode(color);
+ this._appendNode("span", {
+ class: options.colorClass
+ }, color);
return true;
}
return false;
@@ -362,7 +364,9 @@ OutputParser.prototype = {
let attrs = Object.getOwnPropertyNames(attributes);
for (let attr of attrs) {
- node.setAttribute(attr, attributes[attr]);
+ if (attributes[attr]) {
+ node.setAttribute(attr, attributes[attr]);
+ }
}
if (value) {
@@ -422,6 +426,8 @@ OutputParser.prototype = {
* - defaultColorType: true // Convert colors to the default type
* // selected in the options panel.
* - colorSwatchClass: "" // The class to use for color swatches.
+ * - colorClass: "" // The class to use for the color value
+ * // that follows the swatch.
* - isHTMLAttribute: false // This property indicates whether we
* // are parsing an HTML attribute value.
* // When the value is passed in from an
@@ -439,6 +445,7 @@ OutputParser.prototype = {
let defaults = {
defaultColorType: true,
colorSwatchClass: "",
+ colorClass: "",
isHTMLAttribute: false,
urlClass: "",
baseURI: ""