Bug 911748 - Add default color dropdown to devtools options panel. r=jwalker
This commit is contained in:
@@ -1092,6 +1092,9 @@ pref("devtools.inspector.markupPreview", false);
|
||||
pref("devtools.inspector.remote", false);
|
||||
pref("devtools.inspector.show_pseudo_elements", true);
|
||||
|
||||
// DevTools default color unit
|
||||
pref("devtools.defaultColorUnit", "hex");
|
||||
|
||||
// Enable the Responsive UI tool
|
||||
pref("devtools.responsiveUI.enabled", true);
|
||||
pref("devtools.responsiveUI.no-reload-notification", false);
|
||||
|
||||
@@ -178,6 +178,27 @@ OptionsPanel.prototype = {
|
||||
gDevTools.emit("pref-changed", data);
|
||||
}.bind(radiogroup));
|
||||
}
|
||||
let prefMenulists = this.panelDoc.querySelectorAll("menulist[data-pref]");
|
||||
for (let menulist of prefMenulists) {
|
||||
let pref = Services.prefs.getCharPref(menulist.getAttribute("data-pref"));
|
||||
let menuitems = menulist.querySelectorAll("menuitem");
|
||||
for (let menuitem of menuitems) {
|
||||
let value = menuitem.getAttribute("value");
|
||||
if (value === pref) {
|
||||
menulist.selectedItem = menuitem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
menulist.addEventListener("command", function() {
|
||||
let data = {
|
||||
pref: this.getAttribute("data-pref"),
|
||||
newValue: this.value
|
||||
};
|
||||
data.oldValue = Services.prefs.getCharPref(data.pref);
|
||||
Services.prefs.setCharPref(data.pref, data.newValue);
|
||||
gDevTools.emit("pref-changed", data);
|
||||
}.bind(menulist));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,24 @@
|
||||
<radio value="light" label="&options.lightTheme.label;"/>
|
||||
<radio value="dark" label="&options.darkTheme.label;"/>
|
||||
</radiogroup>
|
||||
<label value="&options.context.inspector;"/>
|
||||
<vbox id="inspector-options" class="options-groupbox">
|
||||
<hbox align="center">
|
||||
<label value="&options.defaultColorUnit.label;"
|
||||
control="defaultColorUnitMenuList"
|
||||
accesskey="&options.defaultColorUnit.accesskey;"/>
|
||||
<menulist id="defaultColorUnitMenuList"
|
||||
label="&options.defaultColorUnit.label;"
|
||||
data-pref="devtools.defaultColorUnit">
|
||||
<menupopup>
|
||||
<menuitem label="&options.defaultColorUnit.hex;" value="hex"/>
|
||||
<menuitem label="&options.defaultColorUnit.hsl;" value="hsl"/>
|
||||
<menuitem label="&options.defaultColorUnit.rgb;" value="rgb"/>
|
||||
<menuitem label="&options.defaultColorUnit.name;" value="name"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<label value="&options.webconsole.label;"/>
|
||||
<vbox id="webconsole-options" class="options-groupbox">
|
||||
<checkbox label="&options.enablePersistentLogging.label;"
|
||||
|
||||
@@ -16,6 +16,8 @@ const COLLAPSE_DATA_URL_LENGTH = 60;
|
||||
|
||||
const {UndoStack} = require("devtools/shared/undo");
|
||||
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
|
||||
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
const {colorUtils} = require("devtools/shared/css-color");
|
||||
const promise = require("sdk/core/promise");
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm");
|
||||
@@ -75,7 +77,7 @@ function MarkupView(aInspector, aFrame, aControllerWindow)
|
||||
this._containers = new WeakMap();
|
||||
|
||||
this._boundMutationObserver = this._mutationObserver.bind(this);
|
||||
this.walker.on("mutations", this._boundMutationObserver)
|
||||
this.walker.on("mutations", this._boundMutationObserver);
|
||||
|
||||
this._boundOnNewSelection = this._onNewSelection.bind(this);
|
||||
this._inspector.selection.on("new-node-front", this._boundOnNewSelection);
|
||||
@@ -87,6 +89,9 @@ function MarkupView(aInspector, aFrame, aControllerWindow)
|
||||
this._boundFocus = this._onFocus.bind(this);
|
||||
this._frame.addEventListener("focus", this._boundFocus, false);
|
||||
|
||||
this._handlePrefChange = this._handlePrefChange.bind(this);
|
||||
gDevTools.on("pref-changed", this._handlePrefChange);
|
||||
|
||||
this._initPreview();
|
||||
}
|
||||
|
||||
@@ -112,6 +117,33 @@ MarkupView.prototype = {
|
||||
return this._containers.get(aNode);
|
||||
},
|
||||
|
||||
_handlePrefChange: function(event, data) {
|
||||
if (data.pref == "devtools.defaultColorUnit") {
|
||||
this.update();
|
||||
}
|
||||
},
|
||||
|
||||
update: function() {
|
||||
let updateChildren = function(node) {
|
||||
this.getContainer(node).update();
|
||||
for (let child of node.treeChildren()) {
|
||||
updateChildren(child);
|
||||
}
|
||||
}.bind(this);
|
||||
|
||||
// Start with the documentElement
|
||||
let documentElement;
|
||||
for (let node of this._rootNode.treeChildren()) {
|
||||
if (node.isDocumentElement === true) {
|
||||
documentElement = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Recursively update each node starting with documentElement.
|
||||
updateChildren(documentElement);
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight the inspector selected node.
|
||||
*/
|
||||
@@ -380,7 +412,7 @@ MarkupView.prototype = {
|
||||
continue;
|
||||
}
|
||||
if (type === "attributes" || type === "characterData") {
|
||||
container.update();
|
||||
container.update(false);
|
||||
} else if (type === "childList") {
|
||||
container.childrenDirty = true;
|
||||
this._updateChildren(container);
|
||||
@@ -697,6 +729,8 @@ MarkupView.prototype = {
|
||||
*/
|
||||
destroy: function MT_destroy()
|
||||
{
|
||||
gDevTools.off("pref-changed", this._handlePrefChange);
|
||||
|
||||
this.undo.destroy();
|
||||
delete this.undo;
|
||||
|
||||
@@ -1020,9 +1054,9 @@ MarkupContainer.prototype = {
|
||||
* Update the container's editor to the current state of the
|
||||
* viewed node.
|
||||
*/
|
||||
update: function() {
|
||||
update: function(parseColors=true) {
|
||||
if (this.editor.update) {
|
||||
this.editor.update();
|
||||
this.editor.update(parseColors);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1241,7 +1275,7 @@ ElementEditor.prototype = {
|
||||
/**
|
||||
* Update the state of the editor from the node.
|
||||
*/
|
||||
update: function EE_update()
|
||||
update: function EE_update(parseColors=true)
|
||||
{
|
||||
let attrs = this.node.attributes;
|
||||
if (!attrs) {
|
||||
@@ -1260,10 +1294,13 @@ ElementEditor.prototype = {
|
||||
|
||||
// Get the attribute editor for each attribute that exists on
|
||||
// the node and show it.
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
let attr = this._createAttribute(attrs[i]);
|
||||
if (!attr.inplaceEditor) {
|
||||
attr.style.removeProperty("display");
|
||||
for (let attr of attrs) {
|
||||
if (parseColors && typeof attr.value !== "undefined") {
|
||||
attr.value = colorUtils.processCSSString(attr.value);
|
||||
}
|
||||
let attribute = this._createAttribute(attr);
|
||||
if (!attribute.inplaceEditor) {
|
||||
attribute.style.removeProperty("display");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_BROWSER_FILES := \
|
||||
browser_inspector_markup_colorconversion.js \
|
||||
browser_inspector_markup_navigation.html \
|
||||
browser_inspector_markup_navigation.js \
|
||||
browser_inspector_markup_mutation.html \
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/* Any copyright", " is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
let inspector;
|
||||
let doc;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,browser_inspector_markupview_colorconversion.js";
|
||||
|
||||
function createDocument() {
|
||||
doc.body.innerHTML = '' +
|
||||
'<span style="color:red; border-radius:10px; ' +
|
||||
'background-color:rgba(0, 255, 0, 1); display: inline-block;">' +
|
||||
'Some styled text</span>';
|
||||
|
||||
doc.title = "Style Inspector key binding test";
|
||||
|
||||
setupTest();
|
||||
}
|
||||
|
||||
function setupTest() {
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
inspector = toolbox.getCurrentPanel();
|
||||
inspector.once("inspector-updated", checkColors);
|
||||
});
|
||||
}
|
||||
|
||||
function checkColors() {
|
||||
let node = content.document.querySelector("span");
|
||||
assertAttributes(node, {
|
||||
style: "color:#F00; border-radius:10px; background-color:#0F0; display: inline-block;"
|
||||
}).then(() => {
|
||||
finishUp();
|
||||
});
|
||||
}
|
||||
|
||||
// This version of assertAttributes is different from that in other markup
|
||||
// view tests. This is because in most tests we are checking the node
|
||||
// attributes but here we need the actual values displayed in the markup panel.
|
||||
function assertAttributes(node, attributes) {
|
||||
let deferred = promise.defer();
|
||||
let attrsToCheck = Object.getOwnPropertyNames(attributes);
|
||||
ok(node, "captain, we have the node");
|
||||
|
||||
let checkAttrs = function() {
|
||||
let container = inspector.markup._selectedContainer;
|
||||
let nodeAttrs = container.editor.attrs;
|
||||
|
||||
is(node.attributes.length, attrsToCheck.length,
|
||||
"Node has the correct number of attributes");
|
||||
|
||||
for (let attr of attrsToCheck) {
|
||||
ok(nodeAttrs[attr], "Node has a " + attr + "attribute");
|
||||
|
||||
let nodeAttributeText = nodeAttrs[attr].textContent;
|
||||
[, nodeAttributeText] = nodeAttributeText.match(/^\s*[\w-]+\s*=\s*"(.*)"$/);
|
||||
is(nodeAttributeText, attributes[attr],
|
||||
"Node has the correct " + attr + " attribute value.");
|
||||
}
|
||||
deferred.resolve();
|
||||
};
|
||||
|
||||
if (inspector.selection.node == node) {
|
||||
checkAttrs();
|
||||
} else {
|
||||
inspector.once("inspector-updated", () => {
|
||||
checkAttrs();
|
||||
});
|
||||
inspector.selection.setNode(node);
|
||||
}
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
doc = inspector = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
398
browser/devtools/shared/css-color.js
Normal file
398
browser/devtools/shared/css-color.js
Normal file
@@ -0,0 +1,398 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const COLOR_UNIT_PREF = "devtools.defaultColorUnit";
|
||||
const {Cc, Ci, Cu} = require("chrome");
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
/**
|
||||
* This module is used to convert between various color types.
|
||||
*
|
||||
* Usage:
|
||||
* let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
* let {colorUtils} = devtools.require("devtools/shared/css-color");
|
||||
*
|
||||
* color.authored === "red"
|
||||
* color.hasAlpha === false
|
||||
* color.valid === true
|
||||
* color.transparent === false // transparent has a special status.
|
||||
* color.name === "red" // returns hex or rgba when no name available.
|
||||
* color.hex === "#F00" // returns shortHex when available else returns
|
||||
* longHex. If alpha channel is present then we
|
||||
* return this.rgba.
|
||||
* color.longHex === "#FF0000" // If alpha channel is present then we return
|
||||
* this.rgba.
|
||||
* color.rgb === "rgb(255, 0, 0)" // If alpha channel is present then we return
|
||||
* this.rgba.
|
||||
* color.rgba === "rgba(255, 0, 0, 1)"
|
||||
* color.hsl === "hsl(0, 100%, 50%)"
|
||||
* color.hsla === "hsla(0, 100%, 50%, 1)" // If alpha channel is present
|
||||
* then we return this.rgba.
|
||||
*
|
||||
* color.toString() === "#F00"; // Outputs the color type determined in the
|
||||
* COLOR_UNIT_PREF constant (above).
|
||||
* // Color objects can be reused
|
||||
* color.newColor("green") === "#0F0"; // true
|
||||
*
|
||||
* let processed = colorUtils.processCSSString("color:red; background-color:green;");
|
||||
* // Returns "color:#F00; background-color:#0F0;"
|
||||
*
|
||||
* Valid values for COLOR_UNIT_PREF are contained in CssColor.COLORUNIT.
|
||||
*/
|
||||
|
||||
function CssColor(colorValue) {
|
||||
this.newColor(colorValue);
|
||||
}
|
||||
|
||||
module.exports.colorUtils = {
|
||||
CssColor: CssColor,
|
||||
processCSSString: processCSSString
|
||||
};
|
||||
|
||||
/**
|
||||
* Values used in COLOR_UNIT_PREF
|
||||
*/
|
||||
CssColor.COLORUNIT = {
|
||||
"authored": "authored",
|
||||
"hex": "hex",
|
||||
"name": "name",
|
||||
"rgb": "rgb",
|
||||
"hsl": "hsl"
|
||||
};
|
||||
|
||||
CssColor.prototype = {
|
||||
authored: null,
|
||||
|
||||
get hasAlpha() {
|
||||
if (!this.valid || this.transparent) {
|
||||
return false;
|
||||
}
|
||||
return this._getRGBATuple().a !== 1;
|
||||
},
|
||||
|
||||
get valid() {
|
||||
return this._validateColor(this.authored);
|
||||
},
|
||||
|
||||
get transparent() {
|
||||
try {
|
||||
let tuple = this._getRGBATuple();
|
||||
return tuple === "transparent";
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
get name() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.authored === "transparent") {
|
||||
return "transparent";
|
||||
}
|
||||
try {
|
||||
let tuple = this._getRGBATuple();
|
||||
|
||||
if (tuple === "transparent") {
|
||||
return "transparent";
|
||||
}
|
||||
if (tuple.a !== 1) {
|
||||
return this.rgb;
|
||||
}
|
||||
let {r, g, b} = tuple;
|
||||
return DOMUtils.rgbToColorName(r, g, b);
|
||||
} catch(e) {
|
||||
return this.hex;
|
||||
}
|
||||
},
|
||||
|
||||
get hex() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.hasAlpha) {
|
||||
return this.rgba;
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
let hex = this.longHex;
|
||||
if (hex.charAt(1) == hex.charAt(2) &&
|
||||
hex.charAt(3) == hex.charAt(4) &&
|
||||
hex.charAt(5) == hex.charAt(6)) {
|
||||
hex = "#" + hex.charAt(1) + hex.charAt(3) + hex.charAt(5);
|
||||
}
|
||||
return hex;
|
||||
},
|
||||
|
||||
get longHex() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.hasAlpha) {
|
||||
return this.rgba;
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
return this.rgb.replace(/\brgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)/gi, function(_, r, g, b) {
|
||||
return "#" + ((1 << 24) + (r << 16) + (g << 8) + (b << 0)).toString(16).substr(-6).toUpperCase();
|
||||
});
|
||||
},
|
||||
|
||||
get rgb() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
if (!this.hasAlpha) {
|
||||
let tuple = this._getRGBATuple();
|
||||
return "rgb(" + tuple.r + ", " + tuple.g + ", " + tuple.b + ")";
|
||||
}
|
||||
return this.rgba;
|
||||
},
|
||||
|
||||
get rgba() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
let components = this._getRGBATuple();
|
||||
return "rgba(" + components.r + ", " +
|
||||
components.g + ", " +
|
||||
components.b + ", " +
|
||||
components.a + ")";
|
||||
},
|
||||
|
||||
get hsl() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
if (this.hasAlpha) {
|
||||
return this.hsla;
|
||||
}
|
||||
return this._hslNoAlpha();
|
||||
},
|
||||
|
||||
get hsla() {
|
||||
if (!this.valid) {
|
||||
return "";
|
||||
}
|
||||
if (this.transparent) {
|
||||
return "transparent";
|
||||
}
|
||||
// Because an hsla rbg roundtrip would lose accuracy we use the authored
|
||||
// values if this is an hsla color.
|
||||
if (this.authored.startsWith("hsla(")) {
|
||||
let [, h, s, l, a] = /^\bhsla\(([\d.]+),\s*([\d.]+%),\s*([\d.]+%),\s*([\d.]+|0|1)\)$/gi.exec(this.authored);
|
||||
return "hsla(" + h + ", " + s + ", " + l + ", " + a + ")";
|
||||
}
|
||||
if (this.hasAlpha) {
|
||||
let a = this._getRGBATuple().a;
|
||||
return this._hslNoAlpha().replace("hsl", "hsla").replace(")", ", " + a + ")");
|
||||
}
|
||||
return this._hslNoAlpha().replace("hsl", "hsla").replace(")", ", 1)");
|
||||
},
|
||||
|
||||
/**
|
||||
* Change color
|
||||
*
|
||||
* @param {String} color
|
||||
* Any valid color string
|
||||
*/
|
||||
newColor: function(color) {
|
||||
this.authored = color.toLowerCase();
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a string representing a color of type defined in COLOR_UNIT_PREF.
|
||||
*/
|
||||
toString: function() {
|
||||
let color;
|
||||
let defaultUnit = Services.prefs.getCharPref(COLOR_UNIT_PREF);
|
||||
let unit = CssColor.COLORUNIT[defaultUnit];
|
||||
|
||||
switch(unit) {
|
||||
case CssColor.COLORUNIT.authored:
|
||||
color = this.authored;
|
||||
break;
|
||||
case CssColor.COLORUNIT.hex:
|
||||
color = this.hex;
|
||||
break;
|
||||
case CssColor.COLORUNIT.hsl:
|
||||
color = this.hsl;
|
||||
break;
|
||||
case CssColor.COLORUNIT.name:
|
||||
color = this.name;
|
||||
break;
|
||||
case CssColor.COLORUNIT.rgb:
|
||||
color = this.rgb;
|
||||
break;
|
||||
default:
|
||||
color = this.rgb;
|
||||
}
|
||||
return color;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a RGBA 4-Tuple representation of a color or transparent as
|
||||
* appropriate.
|
||||
*/
|
||||
_getRGBATuple: function() {
|
||||
let win = Services.appShell.hiddenDOMWindow;
|
||||
let doc = win.document;
|
||||
let span = doc.createElement("span");
|
||||
span.style.color = this.authored;
|
||||
let computed = win.getComputedStyle(span).color;
|
||||
|
||||
if (computed === "transparent") {
|
||||
return "transparent";
|
||||
}
|
||||
|
||||
let rgba = /^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+\.\d+|1|0)\)$/gi.exec(computed);
|
||||
|
||||
if (rgba) {
|
||||
let [, r, g, b, a] = rgba;
|
||||
return {r: r, g: g, b: b, a: a};
|
||||
} else {
|
||||
let rgb = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/gi.exec(computed);
|
||||
let [, r, g, b] = rgb;
|
||||
|
||||
return {r: r, g: g, b: b, a: 1};
|
||||
}
|
||||
},
|
||||
|
||||
_hslNoAlpha: function() {
|
||||
let {r, g, b} = this._getRGBATuple();
|
||||
|
||||
// Because an hsl rbg roundtrip would lose accuracy we use the authored
|
||||
// values if this is an hsla color.
|
||||
if (this.authored.startsWith("hsl(")) {
|
||||
let [, h, s, l] = /^\bhsl\(([\d.]+),\s*([\d.]+%),\s*([\d.]+%)\)$/gi.exec(this.authored);
|
||||
return "hsl(" + h + ", " + s + ", " + l + ")";
|
||||
}
|
||||
|
||||
r = r / 255;
|
||||
g = g / 255;
|
||||
b = b / 255;
|
||||
|
||||
let max = Math.max(r, g, b);
|
||||
let min = Math.min(r, g, b);
|
||||
let h;
|
||||
let s;
|
||||
let l = (max + min) / 2;
|
||||
|
||||
if(max == min){
|
||||
h = s = 0;
|
||||
} else {
|
||||
let d = max - min;
|
||||
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||
|
||||
switch(max) {
|
||||
case r:
|
||||
h = ((g - b) / d) % 6;
|
||||
break;
|
||||
case g:
|
||||
h = (b - r) / d + 2;
|
||||
break;
|
||||
case b:
|
||||
h = (r - g) / d + 4;
|
||||
break;
|
||||
}
|
||||
h *= 60;
|
||||
if (h < 0) {
|
||||
h += 360;
|
||||
}
|
||||
}
|
||||
return "hsl(" + (Math.round(h * 1000)) / 1000 +
|
||||
", " + Math.round(s * 100) +
|
||||
"%, " + Math.round(l * 100) + "%)";
|
||||
},
|
||||
|
||||
/**
|
||||
* This method allows comparison of CssColor objects using ===.
|
||||
*/
|
||||
valueOf: function() {
|
||||
return this.rgba;
|
||||
},
|
||||
|
||||
_validateColor: function(color) {
|
||||
if (typeof color !== "string" || color === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
let win = Services.appShell.hiddenDOMWindow;
|
||||
let doc = win.document;
|
||||
|
||||
// Create a black span in a hidden window.
|
||||
let span = doc.createElement("span");
|
||||
span.style.color = "rgb(0, 0, 0)";
|
||||
|
||||
// Attempt to set the color. If the color is no longer black we know that
|
||||
// color is valid.
|
||||
span.style.color = color;
|
||||
if (span.style.color !== "rgb(0, 0, 0)") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the color is black then the above check will have failed. We change
|
||||
// the span to white and attempt to reapply the color. If the span is not
|
||||
// white then we know that the color is valid otherwise we return invalid.
|
||||
span.style.color = "rgb(255, 255, 255)";
|
||||
span.style.color = color;
|
||||
return span.style.color !== "rgb(255, 255, 255)";
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Process a CSS string
|
||||
*
|
||||
* @param {String} value
|
||||
* CSS string e.g. "color:red; background-color:green;"
|
||||
* @return {String}
|
||||
* Converted CSS String e.g. "color:#F00; background-color:#0F0;"
|
||||
*/
|
||||
function processCSSString(value) {
|
||||
if (value && /^""$/.test(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// This regex matches:
|
||||
// - #F00
|
||||
// - #FF0000
|
||||
// - hsl()
|
||||
// - hsla()
|
||||
// - rgb()
|
||||
// - rgba()
|
||||
// - red
|
||||
//
|
||||
// It also matches css keywords e.g. "background-color" otherwise
|
||||
// "background" would be replaced with #6363CE ("background" is a platform
|
||||
// color).
|
||||
let colorPattern = /#[0-9a-fA-F]{3}\b|#[0-9a-fA-F]{6}\b|hsl\(.*?\)|hsla\(.*?\)|rgba?\(.*?\)|\b[a-zA-Z-]+\b/g;
|
||||
|
||||
value = value.replace(colorPattern, function(match) {
|
||||
let color = new CssColor(match);
|
||||
if (color.valid) {
|
||||
return color;
|
||||
}
|
||||
return match;
|
||||
});
|
||||
return value;
|
||||
}
|
||||
|
||||
loader.lazyGetter(this, "DOMUtils", function () {
|
||||
return Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
|
||||
});
|
||||
@@ -4,6 +4,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
browser_css_color.js \
|
||||
browser_eventemitter_basic.js \
|
||||
browser_observableobject.js \
|
||||
browser_layoutHelpers.js \
|
||||
|
||||
310
browser/devtools/shared/test/browser_css_color.js
Normal file
310
browser/devtools/shared/test/browser_css_color.js
Normal file
@@ -0,0 +1,310 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const COLOR_UNIT_PREF = "devtools.defaultColorUnit";
|
||||
|
||||
let origColorUnit;
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
let {Loader} = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {});
|
||||
let {colorUtils} = devtools.require("devtools/shared/css-color");
|
||||
|
||||
function test() {
|
||||
// FIXME: Enable this test on Linux once bug 916544 is fixed
|
||||
if (Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS === "Linux") {
|
||||
Services = colorUtils.CssColor = Loader = null;
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
waitForFocus(init, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,browser_css_color.js";
|
||||
}
|
||||
|
||||
function init() {
|
||||
origColorUnit = Services.prefs.getCharPref(COLOR_UNIT_PREF);
|
||||
createDocument();
|
||||
}
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
let doc = content.document;
|
||||
|
||||
let canvas = doc.createElement("canvas");
|
||||
canvas.width = canvas.height = 10;
|
||||
doc.body.appendChild(canvas);
|
||||
|
||||
testColorUtils();
|
||||
}
|
||||
|
||||
function testColorUtils() {
|
||||
let data = getTestData();
|
||||
|
||||
for (let {authored, name, hex, hsl, rgb} of data) {
|
||||
let color = new colorUtils.CssColor(authored);
|
||||
|
||||
// Check all values.
|
||||
is(color.name, name, "color.name === name");
|
||||
is(color.hex, hex, "color.hex === hex");
|
||||
is(color.hsl, hsl, "color.hsl === hsl");
|
||||
is(color.rgb, rgb, "color.rgb === rgb");
|
||||
|
||||
testToString(color, name, hex, hsl, rgb);
|
||||
testColorMatch(name, hex, hsl, rgb, color.rgba);
|
||||
}
|
||||
testProcessCSSString();
|
||||
finishUp();
|
||||
}
|
||||
|
||||
function testToString(color, name, hex, hsl, rgb) {
|
||||
switchColorUnit(colorUtils.CssColor.COLORUNIT.name);
|
||||
is(color.toString(), name, "toString() with authored type");
|
||||
|
||||
switchColorUnit(colorUtils.CssColor.COLORUNIT.hex);
|
||||
is(color.toString(), hex, "toString() with hex type");
|
||||
|
||||
switchColorUnit(colorUtils.CssColor.COLORUNIT.hsl);
|
||||
is(color.toString(), hsl, "toString() with hsl type");
|
||||
|
||||
switchColorUnit(colorUtils.CssColor.COLORUNIT.rgb);
|
||||
is(color.toString(), rgb, "toString() with rgb type");
|
||||
|
||||
}
|
||||
|
||||
function switchColorUnit(unit) {
|
||||
Services.prefs.setCharPref(COLOR_UNIT_PREF, unit);
|
||||
}
|
||||
|
||||
function testColorMatch(name, hex, hsl, rgb, rgba) {
|
||||
let target;
|
||||
|
||||
let canvas = content.document.querySelector("canvas");
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let clearCanvas = function() {
|
||||
canvas.width = 1;
|
||||
};
|
||||
let setColor = function(aColor) {
|
||||
ctx.fillStyle = aColor;
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
};
|
||||
let setTargetColor = function() {
|
||||
clearCanvas();
|
||||
// All colors have rgba so we can use this to compare against.
|
||||
setColor(rgba);
|
||||
let [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
|
||||
target = {r: r, g: g, b: b, a: a};
|
||||
};
|
||||
let test = function(aColor, type) {
|
||||
let tolerance = 3; // hsla -> rgba -> hsla produces inaccurate results so we
|
||||
// need some tolerence here.
|
||||
clearCanvas();
|
||||
|
||||
setColor(aColor);
|
||||
let [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
|
||||
|
||||
let rgbFail = Math.abs(r - target.r) > tolerance ||
|
||||
Math.abs(g - target.g) > tolerance ||
|
||||
Math.abs(b - target.b) > tolerance;
|
||||
ok(!rgbFail, "color " + rgba + " matches target. Type: " + type);
|
||||
if (rgbFail) {
|
||||
info("target: " + (target.toSource()) + ", color: [r: " + r + ", g: " + g + ", b: " + b + ", a: " + a + "]");
|
||||
}
|
||||
|
||||
let alphaFail = a !== target.a;
|
||||
ok(!alphaFail, "color " + rgba + " alpha value matches target.");
|
||||
};
|
||||
|
||||
setTargetColor();
|
||||
|
||||
test(name, "name");
|
||||
test(hex, "hex");
|
||||
test(hsl, "hsl");
|
||||
test(rgb, "rgb");
|
||||
switchColorUnit(origColorUnit);
|
||||
}
|
||||
|
||||
function testProcessCSSString() {
|
||||
let before = "border: 1px solid red; border-radius: 5px; " +
|
||||
"color rgb(0, 255, 0); font-weight: bold; " +
|
||||
"background-color: transparent; " +
|
||||
"border-top-color: rgba(0, 0, 255, 0.5);";
|
||||
let expected = "border: 1px solid #F00; border-radius: 5px; " +
|
||||
"color #0F0; font-weight: bold; " +
|
||||
"background-color: transparent; " +
|
||||
"border-top-color: rgba(0, 0, 255, 0.5);";
|
||||
let after = colorUtils.processCSSString(before);
|
||||
|
||||
is(after, expected, "CSS string processed correctly");
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
Services = colorUtils.CssColor = Loader = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function getTestData() {
|
||||
return [
|
||||
{authored: "aliceblue", name: "aliceblue", hex: "#F0F8FF", hsl: "hsl(208, 100%, 97%)", rgb: "rgb(240, 248, 255)"},
|
||||
{authored: "antiquewhite", name: "antiquewhite", hex: "#FAEBD7", hsl: "hsl(34.286, 78%, 91%)", rgb: "rgb(250, 235, 215)"},
|
||||
{authored: "aqua", name: "aqua", hex: "#0FF", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
|
||||
{authored: "aquamarine", name: "aquamarine", hex: "#7FFFD4", hsl: "hsl(159.844, 100%, 75%)", rgb: "rgb(127, 255, 212)"},
|
||||
{authored: "azure", name: "azure", hex: "#F0FFFF", hsl: "hsl(180, 100%, 97%)", rgb: "rgb(240, 255, 255)"},
|
||||
{authored: "beige", name: "beige", hex: "#F5F5DC", hsl: "hsl(60, 56%, 91%)", rgb: "rgb(245, 245, 220)"},
|
||||
{authored: "bisque", name: "bisque", hex: "#FFE4C4", hsl: "hsl(32.542, 100%, 88%)", rgb: "rgb(255, 228, 196)"},
|
||||
{authored: "black", name: "black", hex: "#000", hsl: "hsl(0, 0%, 0%)", rgb: "rgb(0, 0, 0)"},
|
||||
{authored: "blanchedalmond", name: "blanchedalmond", hex: "#FFEBCD", hsl: "hsl(36, 100%, 90%)", rgb: "rgb(255, 235, 205)"},
|
||||
{authored: "blue", name: "blue", hex: "#00F", hsl: "hsl(240, 100%, 50%)", rgb: "rgb(0, 0, 255)"},
|
||||
{authored: "blueviolet", name: "blueviolet", hex: "#8A2BE2", hsl: "hsl(271.148, 76%, 53%)", rgb: "rgb(138, 43, 226)"},
|
||||
{authored: "brown", name: "brown", hex: "#A52A2A", hsl: "hsl(0, 59%, 41%)", rgb: "rgb(165, 42, 42)"},
|
||||
{authored: "burlywood", name: "burlywood", hex: "#DEB887", hsl: "hsl(33.793, 57%, 70%)", rgb: "rgb(222, 184, 135)"},
|
||||
{authored: "cadetblue", name: "cadetblue", hex: "#5F9EA0", hsl: "hsl(181.846, 25%, 50%)", rgb: "rgb(95, 158, 160)"},
|
||||
{authored: "chartreuse", name: "chartreuse", hex: "#7FFF00", hsl: "hsl(90.118, 100%, 50%)", rgb: "rgb(127, 255, 0)"},
|
||||
{authored: "chocolate", name: "chocolate", hex: "#D2691E", hsl: "hsl(25, 75%, 47%)", rgb: "rgb(210, 105, 30)"},
|
||||
{authored: "coral", name: "coral", hex: "#FF7F50", hsl: "hsl(16.114, 100%, 66%)", rgb: "rgb(255, 127, 80)"},
|
||||
{authored: "cornflowerblue", name: "cornflowerblue", hex: "#6495ED", hsl: "hsl(218.54, 79%, 66%)", rgb: "rgb(100, 149, 237)"},
|
||||
{authored: "cornsilk", name: "cornsilk", hex: "#FFF8DC", hsl: "hsl(48, 100%, 93%)", rgb: "rgb(255, 248, 220)"},
|
||||
{authored: "crimson", name: "crimson", hex: "#DC143C", hsl: "hsl(348, 83%, 47%)", rgb: "rgb(220, 20, 60)"},
|
||||
{authored: "cyan", name: "aqua", hex: "#0FF", hsl: "hsl(180, 100%, 50%)", rgb: "rgb(0, 255, 255)"},
|
||||
{authored: "darkblue", name: "darkblue", hex: "#00008B", hsl: "hsl(240, 100%, 27%)", rgb: "rgb(0, 0, 139)"},
|
||||
{authored: "darkcyan", name: "darkcyan", hex: "#008B8B", hsl: "hsl(180, 100%, 27%)", rgb: "rgb(0, 139, 139)"},
|
||||
{authored: "darkgoldenrod", name: "darkgoldenrod", hex: "#B8860B", hsl: "hsl(42.659, 89%, 38%)", rgb: "rgb(184, 134, 11)"},
|
||||
{authored: "darkgray", name: "darkgray", hex: "#A9A9A9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
|
||||
{authored: "darkgreen", name: "darkgreen", hex: "#006400", hsl: "hsl(120, 100%, 20%)", rgb: "rgb(0, 100, 0)"},
|
||||
{authored: "darkgrey", name: "darkgray", hex: "#A9A9A9", hsl: "hsl(0, 0%, 66%)", rgb: "rgb(169, 169, 169)"},
|
||||
{authored: "darkkhaki", name: "darkkhaki", hex: "#BDB76B", hsl: "hsl(55.61, 38%, 58%)", rgb: "rgb(189, 183, 107)"},
|
||||
{authored: "darkmagenta", name: "darkmagenta", hex: "#8B008B", hsl: "hsl(300, 100%, 27%)", rgb: "rgb(139, 0, 139)"},
|
||||
{authored: "darkolivegreen", name: "darkolivegreen", hex: "#556B2F", hsl: "hsl(82, 39%, 30%)", rgb: "rgb(85, 107, 47)"},
|
||||
{authored: "darkorange", name: "darkorange", hex: "#FF8C00", hsl: "hsl(32.941, 100%, 50%)", rgb: "rgb(255, 140, 0)"},
|
||||
{authored: "darkorchid", name: "darkorchid", hex: "#9932CC", hsl: "hsl(280.13, 61%, 50%)", rgb: "rgb(153, 50, 204)"},
|
||||
{authored: "darkred", name: "darkred", hex: "#8B0000", hsl: "hsl(0, 100%, 27%)", rgb: "rgb(139, 0, 0)"},
|
||||
{authored: "darksalmon", name: "darksalmon", hex: "#E9967A", hsl: "hsl(15.135, 72%, 70%)", rgb: "rgb(233, 150, 122)"},
|
||||
{authored: "darkseagreen", name: "darkseagreen", hex: "#8FBC8F", hsl: "hsl(120, 25%, 65%)", rgb: "rgb(143, 188, 143)"},
|
||||
{authored: "darkslateblue", name: "darkslateblue", hex: "#483D8B", hsl: "hsl(248.462, 39%, 39%)", rgb: "rgb(72, 61, 139)"},
|
||||
{authored: "darkslategray", name: "darkslategray", hex: "#2F4F4F", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
|
||||
{authored: "darkslategrey", name: "darkslategray", hex: "#2F4F4F", hsl: "hsl(180, 25%, 25%)", rgb: "rgb(47, 79, 79)"},
|
||||
{authored: "darkturquoise", name: "darkturquoise", hex: "#00CED1", hsl: "hsl(180.861, 100%, 41%)", rgb: "rgb(0, 206, 209)"},
|
||||
{authored: "darkviolet", name: "darkviolet", hex: "#9400D3", hsl: "hsl(282.085, 100%, 41%)", rgb: "rgb(148, 0, 211)"},
|
||||
{authored: "deeppink", name: "deeppink", hex: "#FF1493", hsl: "hsl(327.574, 100%, 54%)", rgb: "rgb(255, 20, 147)"},
|
||||
{authored: "deepskyblue", name: "deepskyblue", hex: "#00BFFF", hsl: "hsl(195.059, 100%, 50%)", rgb: "rgb(0, 191, 255)"},
|
||||
{authored: "dimgray", name: "dimgray", hex: "#696969", hsl: "hsl(0, 0%, 41%)", rgb: "rgb(105, 105, 105)"},
|
||||
{authored: "dodgerblue", name: "dodgerblue", hex: "#1E90FF", hsl: "hsl(209.6, 100%, 56%)", rgb: "rgb(30, 144, 255)"},
|
||||
{authored: "firebrick", name: "firebrick", hex: "#B22222", hsl: "hsl(0, 68%, 42%)", rgb: "rgb(178, 34, 34)"},
|
||||
{authored: "floralwhite", name: "floralwhite", hex: "#FFFAF0", hsl: "hsl(40, 100%, 97%)", rgb: "rgb(255, 250, 240)"},
|
||||
{authored: "forestgreen", name: "forestgreen", hex: "#228B22", hsl: "hsl(120, 61%, 34%)", rgb: "rgb(34, 139, 34)"},
|
||||
{authored: "fuchsia", name: "fuchsia", hex: "#F0F", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
|
||||
{authored: "gainsboro", name: "gainsboro", hex: "#DCDCDC", hsl: "hsl(0, 0%, 86%)", rgb: "rgb(220, 220, 220)"},
|
||||
{authored: "ghostwhite", name: "ghostwhite", hex: "#F8F8FF", hsl: "hsl(240, 100%, 99%)", rgb: "rgb(248, 248, 255)"},
|
||||
{authored: "gold", name: "gold", hex: "#FFD700", hsl: "hsl(50.588, 100%, 50%)", rgb: "rgb(255, 215, 0)"},
|
||||
{authored: "goldenrod", name: "goldenrod", hex: "#DAA520", hsl: "hsl(42.903, 74%, 49%)", rgb: "rgb(218, 165, 32)"},
|
||||
{authored: "gray", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
|
||||
{authored: "green", name: "green", hex: "#008000", hsl: "hsl(120, 100%, 25%)", rgb: "rgb(0, 128, 0)"},
|
||||
{authored: "greenyellow", name: "greenyellow", hex: "#ADFF2F", hsl: "hsl(83.654, 100%, 59%)", rgb: "rgb(173, 255, 47)"},
|
||||
{authored: "grey", name: "gray", hex: "#808080", hsl: "hsl(0, 0%, 50%)", rgb: "rgb(128, 128, 128)"},
|
||||
{authored: "honeydew", name: "honeydew", hex: "#F0FFF0", hsl: "hsl(120, 100%, 97%)", rgb: "rgb(240, 255, 240)"},
|
||||
{authored: "hotpink", name: "hotpink", hex: "#FF69B4", hsl: "hsl(330, 100%, 71%)", rgb: "rgb(255, 105, 180)"},
|
||||
{authored: "indianred", name: "indianred", hex: "#CD5C5C", hsl: "hsl(0, 53%, 58%)", rgb: "rgb(205, 92, 92)"},
|
||||
{authored: "indigo", name: "indigo", hex: "#4B0082", hsl: "hsl(274.615, 100%, 25%)", rgb: "rgb(75, 0, 130)"},
|
||||
{authored: "ivory", name: "ivory", hex: "#FFFFF0", hsl: "hsl(60, 100%, 97%)", rgb: "rgb(255, 255, 240)"},
|
||||
{authored: "khaki", name: "khaki", hex: "#F0E68C", hsl: "hsl(54, 77%, 75%)", rgb: "rgb(240, 230, 140)"},
|
||||
{authored: "lavender", name: "lavender", hex: "#E6E6FA", hsl: "hsl(240, 67%, 94%)", rgb: "rgb(230, 230, 250)"},
|
||||
{authored: "lavenderblush", name: "lavenderblush", hex: "#FFF0F5", hsl: "hsl(340, 100%, 97%)", rgb: "rgb(255, 240, 245)"},
|
||||
{authored: "lawngreen", name: "lawngreen", hex: "#7CFC00", hsl: "hsl(90.476, 100%, 49%)", rgb: "rgb(124, 252, 0)"},
|
||||
{authored: "lemonchiffon", name: "lemonchiffon", hex: "#FFFACD", hsl: "hsl(54, 100%, 90%)", rgb: "rgb(255, 250, 205)"},
|
||||
{authored: "lightblue", name: "lightblue", hex: "#ADD8E6", hsl: "hsl(194.737, 53%, 79%)", rgb: "rgb(173, 216, 230)"},
|
||||
{authored: "lightcoral", name: "lightcoral", hex: "#F08080", hsl: "hsl(0, 79%, 72%)", rgb: "rgb(240, 128, 128)"},
|
||||
{authored: "lightcyan", name: "lightcyan", hex: "#E0FFFF", hsl: "hsl(180, 100%, 94%)", rgb: "rgb(224, 255, 255)"},
|
||||
{authored: "lightgoldenrodyellow", name: "lightgoldenrodyellow", hex: "#FAFAD2", hsl: "hsl(60, 80%, 90%)", rgb: "rgb(250, 250, 210)"},
|
||||
{authored: "lightgray", name: "lightgray", hex: "#D3D3D3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
|
||||
{authored: "lightgreen", name: "lightgreen", hex: "#90EE90", hsl: "hsl(120, 73%, 75%)", rgb: "rgb(144, 238, 144)"},
|
||||
{authored: "lightgrey", name: "lightgray", hex: "#D3D3D3", hsl: "hsl(0, 0%, 83%)", rgb: "rgb(211, 211, 211)"},
|
||||
{authored: "lightpink", name: "lightpink", hex: "#FFB6C1", hsl: "hsl(350.959, 100%, 86%)", rgb: "rgb(255, 182, 193)"},
|
||||
{authored: "lightsalmon", name: "lightsalmon", hex: "#FFA07A", hsl: "hsl(17.143, 100%, 74%)", rgb: "rgb(255, 160, 122)"},
|
||||
{authored: "lightseagreen", name: "lightseagreen", hex: "#20B2AA", hsl: "hsl(176.712, 70%, 41%)", rgb: "rgb(32, 178, 170)"},
|
||||
{authored: "lightskyblue", name: "lightskyblue", hex: "#87CEFA", hsl: "hsl(202.957, 92%, 75%)", rgb: "rgb(135, 206, 250)"},
|
||||
{authored: "lightslategray", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
|
||||
{authored: "lightslategrey", name: "lightslategray", hex: "#789", hsl: "hsl(210, 14%, 53%)", rgb: "rgb(119, 136, 153)"},
|
||||
{authored: "lightsteelblue", name: "lightsteelblue", hex: "#B0C4DE", hsl: "hsl(213.913, 41%, 78%)", rgb: "rgb(176, 196, 222)"},
|
||||
{authored: "lightyellow", name: "lightyellow", hex: "#FFFFE0", hsl: "hsl(60, 100%, 94%)", rgb: "rgb(255, 255, 224)"},
|
||||
{authored: "lime", name: "lime", hex: "#0F0", hsl: "hsl(120, 100%, 50%)", rgb: "rgb(0, 255, 0)"},
|
||||
{authored: "limegreen", name: "limegreen", hex: "#32CD32", hsl: "hsl(120, 61%, 50%)", rgb: "rgb(50, 205, 50)"},
|
||||
{authored: "linen", name: "linen", hex: "#FAF0E6", hsl: "hsl(30, 67%, 94%)", rgb: "rgb(250, 240, 230)"},
|
||||
{authored: "magenta", name: "fuchsia", hex: "#F0F", hsl: "hsl(300, 100%, 50%)", rgb: "rgb(255, 0, 255)"},
|
||||
{authored: "maroon", name: "maroon", hex: "#800000", hsl: "hsl(0, 100%, 25%)", rgb: "rgb(128, 0, 0)"},
|
||||
{authored: "mediumaquamarine", name: "mediumaquamarine", hex: "#66CDAA", hsl: "hsl(159.612, 51%, 60%)", rgb: "rgb(102, 205, 170)"},
|
||||
{authored: "mediumblue", name: "mediumblue", hex: "#0000CD", hsl: "hsl(240, 100%, 40%)", rgb: "rgb(0, 0, 205)"},
|
||||
{authored: "mediumorchid", name: "mediumorchid", hex: "#BA55D3", hsl: "hsl(288.095, 59%, 58%)", rgb: "rgb(186, 85, 211)"},
|
||||
{authored: "mediumpurple", name: "mediumpurple", hex: "#9370DB", hsl: "hsl(259.626, 60%, 65%)", rgb: "rgb(147, 112, 219)"},
|
||||
{authored: "mediumseagreen", name: "mediumseagreen", hex: "#3CB371", hsl: "hsl(146.723, 50%, 47%)", rgb: "rgb(60, 179, 113)"},
|
||||
{authored: "mediumslateblue", name: "mediumslateblue", hex: "#7B68EE", hsl: "hsl(248.507, 80%, 67%)", rgb: "rgb(123, 104, 238)"},
|
||||
{authored: "mediumspringgreen", name: "mediumspringgreen", hex: "#00FA9A", hsl: "hsl(156.96, 100%, 49%)", rgb: "rgb(0, 250, 154)"},
|
||||
{authored: "mediumturquoise", name: "mediumturquoise", hex: "#48D1CC", hsl: "hsl(177.81, 60%, 55%)", rgb: "rgb(72, 209, 204)"},
|
||||
{authored: "mediumvioletred", name: "mediumvioletred", hex: "#C71585", hsl: "hsl(322.247, 81%, 43%)", rgb: "rgb(199, 21, 133)"},
|
||||
{authored: "midnightblue", name: "midnightblue", hex: "#191970", hsl: "hsl(240, 64%, 27%)", rgb: "rgb(25, 25, 112)"},
|
||||
{authored: "mintcream", name: "mintcream", hex: "#F5FFFA", hsl: "hsl(150, 100%, 98%)", rgb: "rgb(245, 255, 250)"},
|
||||
{authored: "mistyrose", name: "mistyrose", hex: "#FFE4E1", hsl: "hsl(6, 100%, 94%)", rgb: "rgb(255, 228, 225)"},
|
||||
{authored: "moccasin", name: "moccasin", hex: "#FFE4B5", hsl: "hsl(38.108, 100%, 85%)", rgb: "rgb(255, 228, 181)"},
|
||||
{authored: "navajowhite", name: "navajowhite", hex: "#FFDEAD", hsl: "hsl(35.854, 100%, 84%)", rgb: "rgb(255, 222, 173)"},
|
||||
{authored: "navy", name: "navy", hex: "#000080", hsl: "hsl(240, 100%, 25%)", rgb: "rgb(0, 0, 128)"},
|
||||
{authored: "oldlace", name: "oldlace", hex: "#FDF5E6", hsl: "hsl(39.13, 85%, 95%)", rgb: "rgb(253, 245, 230)"},
|
||||
{authored: "olive", name: "olive", hex: "#808000", hsl: "hsl(60, 100%, 25%)", rgb: "rgb(128, 128, 0)"},
|
||||
{authored: "olivedrab", name: "olivedrab", hex: "#6B8E23", hsl: "hsl(79.626, 60%, 35%)", rgb: "rgb(107, 142, 35)"},
|
||||
{authored: "orange", name: "orange", hex: "#FFA500", hsl: "hsl(38.824, 100%, 50%)", rgb: "rgb(255, 165, 0)"},
|
||||
{authored: "orangered", name: "orangered", hex: "#FF4500", hsl: "hsl(16.235, 100%, 50%)", rgb: "rgb(255, 69, 0)"},
|
||||
{authored: "orchid", name: "orchid", hex: "#DA70D6", hsl: "hsl(302.264, 59%, 65%)", rgb: "rgb(218, 112, 214)"},
|
||||
{authored: "palegoldenrod", name: "palegoldenrod", hex: "#EEE8AA", hsl: "hsl(54.706, 67%, 80%)", rgb: "rgb(238, 232, 170)"},
|
||||
{authored: "palegreen", name: "palegreen", hex: "#98FB98", hsl: "hsl(120, 93%, 79%)", rgb: "rgb(152, 251, 152)"},
|
||||
{authored: "paleturquoise", name: "paleturquoise", hex: "#AFEEEE", hsl: "hsl(180, 65%, 81%)", rgb: "rgb(175, 238, 238)"},
|
||||
{authored: "palevioletred", name: "palevioletred", hex: "#DB7093", hsl: "hsl(340.374, 60%, 65%)", rgb: "rgb(219, 112, 147)"},
|
||||
{authored: "papayawhip", name: "papayawhip", hex: "#FFEFD5", hsl: "hsl(37.143, 100%, 92%)", rgb: "rgb(255, 239, 213)"},
|
||||
{authored: "peachpuff", name: "peachpuff", hex: "#FFDAB9", hsl: "hsl(28.286, 100%, 86%)", rgb: "rgb(255, 218, 185)"},
|
||||
{authored: "peru", name: "peru", hex: "#CD853F", hsl: "hsl(29.577, 59%, 53%)", rgb: "rgb(205, 133, 63)"},
|
||||
{authored: "pink", name: "pink", hex: "#FFC0CB", hsl: "hsl(349.524, 100%, 88%)", rgb: "rgb(255, 192, 203)"},
|
||||
{authored: "plum", name: "plum", hex: "#DDA0DD", hsl: "hsl(300, 47%, 75%)", rgb: "rgb(221, 160, 221)"},
|
||||
{authored: "powderblue", name: "powderblue", hex: "#B0E0E6", hsl: "hsl(186.667, 52%, 80%)", rgb: "rgb(176, 224, 230)"},
|
||||
{authored: "purple", name: "purple", hex: "#800080", hsl: "hsl(300, 100%, 25%)", rgb: "rgb(128, 0, 128)"},
|
||||
{authored: "red", name: "red", hex: "#F00", hsl: "hsl(0, 100%, 50%)", rgb: "rgb(255, 0, 0)"},
|
||||
{authored: "rosybrown", name: "rosybrown", hex: "#BC8F8F", hsl: "hsl(0, 25%, 65%)", rgb: "rgb(188, 143, 143)"},
|
||||
{authored: "royalblue", name: "royalblue", hex: "#4169E1", hsl: "hsl(225, 73%, 57%)", rgb: "rgb(65, 105, 225)"},
|
||||
{authored: "saddlebrown", name: "saddlebrown", hex: "#8B4513", hsl: "hsl(25, 76%, 31%)", rgb: "rgb(139, 69, 19)"},
|
||||
{authored: "salmon", name: "salmon", hex: "#FA8072", hsl: "hsl(6.176, 93%, 71%)", rgb: "rgb(250, 128, 114)"},
|
||||
{authored: "sandybrown", name: "sandybrown", hex: "#F4A460", hsl: "hsl(27.568, 87%, 67%)", rgb: "rgb(244, 164, 96)"},
|
||||
{authored: "seagreen", name: "seagreen", hex: "#2E8B57", hsl: "hsl(146.452, 50%, 36%)", rgb: "rgb(46, 139, 87)"},
|
||||
{authored: "seashell", name: "seashell", hex: "#FFF5EE", hsl: "hsl(24.706, 100%, 97%)", rgb: "rgb(255, 245, 238)"},
|
||||
{authored: "sienna", name: "sienna", hex: "#A0522D", hsl: "hsl(19.304, 56%, 40%)", rgb: "rgb(160, 82, 45)"},
|
||||
{authored: "silver", name: "silver", hex: "#C0C0C0", hsl: "hsl(0, 0%, 75%)", rgb: "rgb(192, 192, 192)"},
|
||||
{authored: "skyblue", name: "skyblue", hex: "#87CEEB", hsl: "hsl(197.4, 71%, 73%)", rgb: "rgb(135, 206, 235)"},
|
||||
{authored: "slateblue", name: "slateblue", hex: "#6A5ACD", hsl: "hsl(248.348, 53%, 58%)", rgb: "rgb(106, 90, 205)"},
|
||||
{authored: "slategray", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
|
||||
{authored: "slategrey", name: "slategray", hex: "#708090", hsl: "hsl(210, 13%, 50%)", rgb: "rgb(112, 128, 144)"},
|
||||
{authored: "snow", name: "snow", hex: "#FFFAFA", hsl: "hsl(0, 100%, 99%)", rgb: "rgb(255, 250, 250)"},
|
||||
{authored: "springgreen", name: "springgreen", hex: "#00FF7F", hsl: "hsl(149.882, 100%, 50%)", rgb: "rgb(0, 255, 127)"},
|
||||
{authored: "steelblue", name: "steelblue", hex: "#4682B4", hsl: "hsl(207.273, 44%, 49%)", rgb: "rgb(70, 130, 180)"},
|
||||
{authored: "tan", name: "tan", hex: "#D2B48C", hsl: "hsl(34.286, 44%, 69%)", rgb: "rgb(210, 180, 140)"},
|
||||
{authored: "teal", name: "teal", hex: "#008080", hsl: "hsl(180, 100%, 25%)", rgb: "rgb(0, 128, 128)"},
|
||||
{authored: "thistle", name: "thistle", hex: "#D8BFD8", hsl: "hsl(300, 24%, 80%)", rgb: "rgb(216, 191, 216)"},
|
||||
{authored: "tomato", name: "tomato", hex: "#FF6347", hsl: "hsl(9.13, 100%, 64%)", rgb: "rgb(255, 99, 71)"},
|
||||
{authored: "turquoise", name: "turquoise", hex: "#40E0D0", hsl: "hsl(174, 72%, 56%)", rgb: "rgb(64, 224, 208)"},
|
||||
{authored: "violet", name: "violet", hex: "#EE82EE", hsl: "hsl(300, 76%, 72%)", rgb: "rgb(238, 130, 238)"},
|
||||
{authored: "wheat", name: "wheat", hex: "#F5DEB3", hsl: "hsl(39.091, 77%, 83%)", rgb: "rgb(245, 222, 179)"},
|
||||
{authored: "white", name: "white", hex: "#FFF", hsl: "hsl(0, 0%, 100%)", rgb: "rgb(255, 255, 255)"},
|
||||
{authored: "whitesmoke", name: "whitesmoke", hex: "#F5F5F5", hsl: "hsl(0, 0%, 96%)", rgb: "rgb(245, 245, 245)"},
|
||||
{authored: "yellow", name: "yellow", hex: "#FF0", hsl: "hsl(60, 100%, 50%)", rgb: "rgb(255, 255, 0)"},
|
||||
{authored: "yellowgreen", name: "yellowgreen", hex: "#9ACD32", hsl: "hsl(79.742, 61%, 50%)", rgb: "rgb(154, 205, 50)"},
|
||||
{authored: "transparent", name: "transparent", hex: "transparent", hsl: "transparent", rgb: "transparent"},
|
||||
{authored: "rgba(0, 0, 0, 0)", name: "transparent", hex: "transparent", hsl: "transparent", rgb: "transparent"},
|
||||
{authored: "hsla(0, 0%, 0%, 0)", name: "transparent", hex: "transparent", hsl: "transparent", rgb: "transparent"},
|
||||
{authored: "rgba(50, 60, 70, 0.5)", name: "rgba(50, 60, 70, 0.5)", hex: "rgba(50, 60, 70, 0.5)", hsl: "hsla(210, 17%, 24%, 0.5)", rgb: "rgba(50, 60, 70, 0.5)"},
|
||||
{authored: "rgba(0, 0, 0, 0.3)", name: "rgba(0, 0, 0, 0.3)", hex: "rgba(0, 0, 0, 0.3)", hsl: "hsla(0, 0%, 0%, 0.3)", rgb: "rgba(0, 0, 0, 0.3)"},
|
||||
{authored: "rgba(255, 255, 255, 0.7)", name: "rgba(255, 255, 255, 0.7)", hex: "rgba(255, 255, 255, 0.7)", hsl: "hsla(0, 0%, 100%, 0.7)", rgb: "rgba(255, 255, 255, 0.7)"},
|
||||
{authored: "rgba(127, 89, 45, 1)", name: "#7F592D", hex: "#7F592D", hsl: "hsl(32.195, 48%, 34%)", rgb: "rgb(127, 89, 45)"},
|
||||
{authored: "hsla(19.304, 56%, 40%, 1)", name: "#9F512C", hex: "#9F512C", hsl: "hsl(19.304, 57%, 40%)", rgb: "rgb(159, 81, 44)"},
|
||||
{authored: "invalidColor", name: "", hex: "", hsl: "", rgb: ""}
|
||||
];
|
||||
}
|
||||
@@ -11,13 +11,14 @@ let {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||
let {ELEMENT_STYLE} = require("devtools/server/actors/styles");
|
||||
let promise = require("sdk/core/promise");
|
||||
let {EventEmitter} = require("devtools/shared/event-emitter");
|
||||
let {colorUtils} = require("devtools/shared/css-color");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PluralForm.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Templater.jsm");
|
||||
|
||||
Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
|
||||
const FILTER_CHANGED_TIMEOUT = 300;
|
||||
|
||||
@@ -152,6 +153,10 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
|
||||
// No results text.
|
||||
this.noResults = this.styleDocument.getElementById("noResults");
|
||||
|
||||
// Refresh panel when color unit changed.
|
||||
this._handlePrefChange = this._handlePrefChange.bind(this);
|
||||
gDevTools.on("pref-changed", this._handlePrefChange);
|
||||
|
||||
CssHtmlTree.processTemplate(this.templateRoot, this.root, this);
|
||||
|
||||
// The element that we're inspecting, and the document that it comes from.
|
||||
@@ -244,6 +249,12 @@ CssHtmlTree.prototype = {
|
||||
return this.includeBrowserStylesCheckbox.checked;
|
||||
},
|
||||
|
||||
_handlePrefChange: function(event, data) {
|
||||
if (data.pref == "devtools.defaultColorUnit" && this._computed) {
|
||||
this.refreshPanel();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the highlighted element. The CssHtmlTree panel will show the style
|
||||
* information for the given element.
|
||||
@@ -256,7 +267,7 @@ CssHtmlTree.prototype = {
|
||||
if (this._refreshProcess) {
|
||||
this._refreshProcess.cancel();
|
||||
}
|
||||
return promise.resolve(undefined)
|
||||
return promise.resolve(undefined);
|
||||
}
|
||||
|
||||
if (aElement === this.viewedElement) {
|
||||
@@ -495,6 +506,7 @@ CssHtmlTree.prototype = {
|
||||
this.includeBrowserStylesCheckbox.removeEventListener("command",
|
||||
this.includeBrowserStylesChanged);
|
||||
this.searchField.removeEventListener("command", this.filterChanged);
|
||||
gDevTools.off("pref-changed", this._handlePrefChange);
|
||||
|
||||
// Cancel tree construction
|
||||
if (this._createViewsProcess) {
|
||||
@@ -553,8 +565,13 @@ function PropertyInfo(aTree, aName) {
|
||||
this.name = aName;
|
||||
}
|
||||
PropertyInfo.prototype = {
|
||||
get value() this.tree._computed ? this.tree._computed[this.name].value : ""
|
||||
}
|
||||
get value() {
|
||||
if (this.tree._computed) {
|
||||
let value = this.tree._computed[this.name].value;
|
||||
return colorUtils.processCSSString(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A container to give easy access to property data from the template engine.
|
||||
@@ -935,7 +952,8 @@ SelectorView.prototype = {
|
||||
|
||||
get value()
|
||||
{
|
||||
return this.selectorInfo.value;
|
||||
let val = this.selectorInfo.value;
|
||||
return colorUtils.processCSSString(val);
|
||||
},
|
||||
|
||||
maybeOpenStyleEditor: function(aEvent)
|
||||
|
||||
@@ -12,6 +12,8 @@ const promise = require("sdk/core/promise");
|
||||
let {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||
let {InplaceEditor, editableField, editableItem} = require("devtools/shared/inplace-editor");
|
||||
let {ELEMENT_STYLE, PSEUDO_ELEMENTS} = require("devtools/server/actors/styles");
|
||||
let {colorUtils} = require("devtools/shared/css-color");
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
@@ -910,7 +912,7 @@ function TextProperty(aRule, aName, aValue, aPriority)
|
||||
{
|
||||
this.rule = aRule;
|
||||
this.name = aName;
|
||||
this.value = aValue;
|
||||
this.value = colorUtils.processCSSString(aValue);
|
||||
this.priority = aPriority;
|
||||
this.enabled = true;
|
||||
this.updateComputed();
|
||||
@@ -1000,7 +1002,7 @@ TextProperty.prototype = {
|
||||
remove: function TextProperty_remove()
|
||||
{
|
||||
this.rule.removeProperty(this);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1048,6 +1050,9 @@ function CssRuleView(aDoc, aStore, aPageStyle)
|
||||
this._boundCopy = this._onCopy.bind(this);
|
||||
this.element.addEventListener("copy", this._boundCopy);
|
||||
|
||||
this._handlePrefChange = this._handlePrefChange.bind(this);
|
||||
gDevTools.on("pref-changed", this._handlePrefChange);
|
||||
|
||||
let options = {
|
||||
fixedWidth: true,
|
||||
autoSelect: true,
|
||||
@@ -1075,10 +1080,20 @@ CssRuleView.prototype = {
|
||||
return this.element.querySelectorAll(".styleinspector-propertyeditor").length > 0;
|
||||
},
|
||||
|
||||
_handlePrefChange: function(event, data) {
|
||||
if (data.pref == "devtools.defaultColorUnit") {
|
||||
let element = this._viewedElement;
|
||||
this._viewedElement = null;
|
||||
this.highlight(element);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function CssRuleView_destroy()
|
||||
{
|
||||
this.clear();
|
||||
|
||||
gDevTools.off("pref-changed", this._handlePrefChange);
|
||||
|
||||
this.element.removeEventListener("copy", this._boundCopy);
|
||||
delete this._boundCopy;
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ function checkCopySelection()
|
||||
info("Checking that cssHtmlTree.siBoundCopy() " +
|
||||
" returns the correct clipboard value");
|
||||
|
||||
let expectedPattern = "color: rgb\\(255, 255, 0\\);[\\r\\n]+" +
|
||||
let expectedPattern = "color: #FF0;[\\r\\n]+" +
|
||||
"font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||
"font-size: 16px;[\\r\\n]+" +
|
||||
"font-variant: small-caps;[\\r\\n]*";
|
||||
|
||||
@@ -9,7 +9,7 @@ let doc;
|
||||
let ruleWindow;
|
||||
let ruleView;
|
||||
let inspector;
|
||||
let originalValue = "blue";
|
||||
let originalValue = "#00F";
|
||||
|
||||
// Test data format
|
||||
// {
|
||||
@@ -54,7 +54,7 @@ function runTestData(index)
|
||||
let idRuleEditor = ruleView.element.children[1]._ruleEditor;
|
||||
let propEditor = idRuleEditor.rule.textProps[0].editor;
|
||||
waitForEditorFocus(propEditor.element, function(aEditor) {
|
||||
is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value.");
|
||||
is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value span.");
|
||||
|
||||
for (let ch of testData[index].value) {
|
||||
EventUtils.sendChar(ch, ruleWindow);
|
||||
|
||||
@@ -71,10 +71,10 @@ function checkCopySelection()
|
||||
let expectedPattern = " margin: 10em;[\\r\\n]+" +
|
||||
" font-size: 14pt;[\\r\\n]+" +
|
||||
" font-family: helvetica,sans-serif;[\\r\\n]+" +
|
||||
" color: rgb\\(170, 170, 170\\);[\\r\\n]+" +
|
||||
" color: #AAA;[\\r\\n]+" +
|
||||
"}[\\r\\n]+" +
|
||||
"html {[\\r\\n]+" +
|
||||
" color: rgb\\(0, 0, 0\\);[\\r\\n]*";
|
||||
" color: #000;[\\r\\n]*";
|
||||
|
||||
SimpleTest.waitForClipboard(function IUI_boundCopyCheck() {
|
||||
return checkClipboardData(expectedPattern);
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
let doc;
|
||||
|
||||
|
||||
|
||||
function simpleOverride(aInspector, aRuleView)
|
||||
{
|
||||
doc.body.innerHTML = '<div id="testid">Styled Node</div>';
|
||||
@@ -22,17 +20,17 @@ function simpleOverride(aInspector, aRuleView)
|
||||
is(elementRule.textProps[1], secondProp, "Rules should be in addition order.");
|
||||
|
||||
promiseDone(elementRule._applyingModifications.then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "blue", "Second property should have been used.");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Second property should have been used.");
|
||||
|
||||
secondProp.remove();
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "green", "After deleting second property, first should be used.");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 128, 0)", "After deleting second property, first should be used.");
|
||||
|
||||
secondProp = elementRule.createProperty("background-color", "blue", "");
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "blue", "New property should be used.");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "New property should be used.");
|
||||
|
||||
is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
|
||||
is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
|
||||
@@ -40,7 +38,7 @@ function simpleOverride(aInspector, aRuleView)
|
||||
secondProp.setEnabled(false);
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "green", "After disabling second property, first value should be used");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 128, 0)", "After disabling second property, first value should be used");
|
||||
|
||||
firstProp.setEnabled(false);
|
||||
return elementRule._applyingModifications;
|
||||
@@ -50,19 +48,19 @@ function simpleOverride(aInspector, aRuleView)
|
||||
secondProp.setEnabled(true);
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "blue", "Value should be set correctly after re-enabling");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Value should be set correctly after re-enabling");
|
||||
|
||||
firstProp.setEnabled(true);
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "blue", "Re-enabling an earlier property shouldn't make it override a later property.");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Re-enabling an earlier property shouldn't make it override a later property.");
|
||||
is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
|
||||
is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
|
||||
|
||||
firstProp.setValue("purple", "");
|
||||
return elementRule._applyingModifications;
|
||||
}).then(() => {
|
||||
is(element.style.getPropertyValue("background-color"), "blue", "Modifying an earlier property shouldn't override a later property.");
|
||||
is(element.style.getPropertyValue("background-color"), "rgb(0, 0, 255)", "Modifying an earlier property shouldn't override a later property.");
|
||||
finishTest();
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ function testTopLeft()
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementAfterRule.textProps),
|
||||
"background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " +
|
||||
"background: none repeat scroll 0% 0% #F00; content: \" \"; position: absolute; " +
|
||||
"border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px",
|
||||
"TopLeft after properties are correct"
|
||||
);
|
||||
@@ -242,7 +242,7 @@ function testParagraph()
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementFirstLineRule.textProps),
|
||||
"background: none repeat scroll 0% 0% blue",
|
||||
"background: none repeat scroll 0% 0% #00F",
|
||||
"Paragraph first-line properties are correct"
|
||||
);
|
||||
|
||||
@@ -254,7 +254,7 @@ function testParagraph()
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementFirstLetterRule.textProps),
|
||||
"color: red; font-size: 130%",
|
||||
"color: #F00; font-size: 130%",
|
||||
"Paragraph first-letter properties are correct"
|
||||
);
|
||||
|
||||
@@ -266,7 +266,7 @@ function testParagraph()
|
||||
is
|
||||
(
|
||||
convertTextPropsToString(elementSelectionRule.textProps),
|
||||
"color: white; background: none repeat scroll 0% 0% black",
|
||||
"color: #FFF; background: none repeat scroll 0% 0% #000",
|
||||
"Paragraph first-letter properties are correct"
|
||||
);
|
||||
|
||||
|
||||
@@ -21,6 +21,37 @@
|
||||
- the heading of the advanced settings group in the options panel. -->
|
||||
<!ENTITY options.context.advancedSettings "Advanced settings">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.context.inspector): This is the label for
|
||||
- the heading of the Inspector group in the options panel. -->
|
||||
<!ENTITY options.context.inspector "Inspector">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.label): This is the label for a
|
||||
- dropdown list that controls the default color unit used in the inspector.
|
||||
- This label is visible in the options panel. -->
|
||||
<!ENTITY options.defaultColorUnit.label "Default color unit">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.accesskey): This is the access
|
||||
- key for a dropdown list that controls the default color unit used in the
|
||||
- inspector. This is visible in the options panel. -->
|
||||
<!ENTITY options.defaultColorUnit.accesskey "U">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.hex): This is used in the
|
||||
- 'Default color unit' dropdown list and is visible in the options panel. -->
|
||||
<!ENTITY options.defaultColorUnit.hex "Hex">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.hsl): This is used in the
|
||||
- 'Default color unit' dropdown list and is visible in the options panel. -->
|
||||
<!ENTITY options.defaultColorUnit.hsl "HSL(A)">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.rgb): This is used in the
|
||||
- 'Default color unit' dropdown list and is visible in the options panel. -->
|
||||
<!ENTITY options.defaultColorUnit.rgb "RGB(A)">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.defaultColorUnit.name): This is used in
|
||||
- the 'Default color unit' dropdown list and is visible in the options panel.
|
||||
- -->
|
||||
<!ENTITY options.defaultColorUnit.name "Color Names">
|
||||
|
||||
<!-- LOCALIZATION NOTE (options.context.requiresRestart2): This is the requires
|
||||
- restart label at right of settings that require a browser restart to be
|
||||
- effective. -->
|
||||
|
||||
@@ -51,6 +51,8 @@ const RX_PSEUDO = /\s*:?:([\w-]+)(\(?\)?)\s*/g;
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let {colorUtils} = require("devtools/shared/css-color");
|
||||
|
||||
function CssLogic()
|
||||
{
|
||||
// The cache of examined CSS properties.
|
||||
@@ -1452,7 +1454,6 @@ CssPropertyInfo.prototype = {
|
||||
Services.console.logStringMessage(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return this._value;
|
||||
},
|
||||
|
||||
@@ -1601,9 +1602,8 @@ function CssSelectorInfo(aSelector, aProperty, aValue, aStatus)
|
||||
{
|
||||
this.selector = aSelector;
|
||||
this.property = aProperty;
|
||||
this.value = aValue;
|
||||
this.status = aStatus;
|
||||
|
||||
this.value = colorUtils.processCSSString(aValue);
|
||||
let priority = this.selector.cssRule.getPropertyPriority(this.property);
|
||||
this.important = (priority === "important");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user