зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1030889 - [rule view] Add keyframe rules with its associated element r=pbrosset
This commit is contained in:
Родитель
6346badd81
Коммит
c0bbd8f26d
|
@ -302,10 +302,13 @@ ElementStyle.prototype = {
|
||||||
*/
|
*/
|
||||||
markOverridden: function(pseudo="") {
|
markOverridden: function(pseudo="") {
|
||||||
// Gather all the text properties applied by these rules, ordered
|
// Gather all the text properties applied by these rules, ordered
|
||||||
// from more- to less-specific.
|
// from more- to less-specific. Text properties from keyframes rule are
|
||||||
|
// excluded from being marked as overridden since a number of criteria such
|
||||||
|
// as time, and animation overlay are required to be check in order to
|
||||||
|
// determine if the property is overridden.
|
||||||
let textProps = [];
|
let textProps = [];
|
||||||
for (let rule of this.rules) {
|
for (let rule of this.rules) {
|
||||||
if (rule.pseudoElement == pseudo) {
|
if (rule.pseudoElement == pseudo && !rule.keyframes) {
|
||||||
textProps = textProps.concat(rule.textProps.slice(0).reverse());
|
textProps = textProps.concat(rule.textProps.slice(0).reverse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -419,6 +422,7 @@ function Rule(aElementStyle, aOptions) {
|
||||||
|
|
||||||
this.isSystem = aOptions.isSystem;
|
this.isSystem = aOptions.isSystem;
|
||||||
this.inherited = aOptions.inherited || null;
|
this.inherited = aOptions.inherited || null;
|
||||||
|
this.keyframes = aOptions.keyframes || null;
|
||||||
this._modificationDepth = 0;
|
this._modificationDepth = 0;
|
||||||
|
|
||||||
if (this.domRule) {
|
if (this.domRule) {
|
||||||
|
@ -466,6 +470,18 @@ Rule.prototype = {
|
||||||
return this._inheritedSource;
|
return this._inheritedSource;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get keyframesName() {
|
||||||
|
if (this._keyframesName) {
|
||||||
|
return this._keyframesName;
|
||||||
|
}
|
||||||
|
this._keyframesName = "";
|
||||||
|
if (this.keyframes) {
|
||||||
|
this._keyframesName =
|
||||||
|
CssLogic._strings.formatStringFromName("rule.keyframe", [this.keyframes.name], 1);
|
||||||
|
}
|
||||||
|
return this._keyframesName;
|
||||||
|
},
|
||||||
|
|
||||||
get selectorText() {
|
get selectorText() {
|
||||||
return this.domRule.selectors ? this.domRule.selectors.join(", ") : CssLogic.l10n("rule.sourceElement");
|
return this.domRule.selectors ? this.domRule.selectors.join(", ") : CssLogic.l10n("rule.sourceElement");
|
||||||
},
|
},
|
||||||
|
@ -1627,25 +1643,6 @@ CssRuleView.prototype = {
|
||||||
return this._pseudoElementLabel;
|
return this._pseudoElementLabel;
|
||||||
},
|
},
|
||||||
|
|
||||||
togglePseudoElementVisibility: function(value) {
|
|
||||||
this._showPseudoElements = !!value;
|
|
||||||
let isOpen = this.showPseudoElements;
|
|
||||||
|
|
||||||
Services.prefs.setBoolPref("devtools.inspector.show_pseudo_elements",
|
|
||||||
isOpen);
|
|
||||||
|
|
||||||
this.element.classList.toggle("show-pseudo-elements", isOpen);
|
|
||||||
|
|
||||||
if (this.pseudoElementTwisty) {
|
|
||||||
if (isOpen) {
|
|
||||||
this.pseudoElementTwisty.setAttribute("open", "true");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.pseudoElementTwisty.removeAttribute("open");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
get showPseudoElements() {
|
get showPseudoElements() {
|
||||||
if (this._showPseudoElements === undefined) {
|
if (this._showPseudoElements === undefined) {
|
||||||
this._showPseudoElements =
|
this._showPseudoElements =
|
||||||
|
@ -1654,6 +1651,68 @@ CssRuleView.prototype = {
|
||||||
return this._showPseudoElements;
|
return this._showPseudoElements;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an expandable container in the rule view
|
||||||
|
* @param {String} aLabel The label for the container header
|
||||||
|
* @param {Boolean} isPseudo Whether or not the container will hold
|
||||||
|
* pseudo element rules
|
||||||
|
* @return {DOMNode} The container element
|
||||||
|
*/
|
||||||
|
createExpandableContainer: function(aLabel, isPseudo = false) {
|
||||||
|
let header = this.doc.createElementNS(HTML_NS, "div");
|
||||||
|
header.className = this._getRuleViewHeaderClassName(true);
|
||||||
|
header.classList.add("show-expandable-container");
|
||||||
|
header.textContent = aLabel;
|
||||||
|
|
||||||
|
let twisty = this.doc.createElementNS(HTML_NS, "span");
|
||||||
|
twisty.className = "ruleview-expander theme-twisty";
|
||||||
|
twisty.setAttribute("open", "true");
|
||||||
|
|
||||||
|
header.insertBefore(twisty, header.firstChild);
|
||||||
|
this.element.appendChild(header);
|
||||||
|
|
||||||
|
let container = this.doc.createElementNS(HTML_NS, "div");
|
||||||
|
container.classList.add("ruleview-expandable-container");
|
||||||
|
this.element.appendChild(container);
|
||||||
|
|
||||||
|
let toggleContainerVisibility = (isPseudo, showPseudo) => {
|
||||||
|
let isOpen = twisty.getAttribute("open");
|
||||||
|
|
||||||
|
if (isPseudo) {
|
||||||
|
this._showPseudoElements = !!showPseudo;
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("devtools.inspector.show_pseudo_elements",
|
||||||
|
this.showPseudoElements);
|
||||||
|
|
||||||
|
header.classList.toggle("show-expandable-container",
|
||||||
|
this.showPseudoElements);
|
||||||
|
|
||||||
|
isOpen = !this.showPseudoElements;
|
||||||
|
} else {
|
||||||
|
header.classList.toggle("show-expandable-container");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
twisty.removeAttribute("open");
|
||||||
|
} else {
|
||||||
|
twisty.setAttribute("open", "true");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
header.addEventListener("dblclick", () => {
|
||||||
|
toggleContainerVisibility(isPseudo, !this.showPseudoElements);
|
||||||
|
}, false);
|
||||||
|
twisty.addEventListener("click", () => {
|
||||||
|
toggleContainerVisibility(isPseudo, !this.showPseudoElements);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
if (isPseudo) {
|
||||||
|
toggleContainerVisibility(isPseudo, this.showPseudoElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
},
|
||||||
|
|
||||||
_getRuleViewHeaderClassName: function(isPseudo) {
|
_getRuleViewHeaderClassName: function(isPseudo) {
|
||||||
let baseClassName = "theme-gutter ruleview-header";
|
let baseClassName = "theme-gutter ruleview-header";
|
||||||
return isPseudo ? baseClassName + " ruleview-expandable-header" : baseClassName;
|
return isPseudo ? baseClassName + " ruleview-expandable-header" : baseClassName;
|
||||||
|
@ -1666,8 +1725,10 @@ CssRuleView.prototype = {
|
||||||
// Run through the current list of rules, attaching
|
// Run through the current list of rules, attaching
|
||||||
// their editors in order. Create editors if needed.
|
// their editors in order. Create editors if needed.
|
||||||
let lastInheritedSource = "";
|
let lastInheritedSource = "";
|
||||||
|
let lastKeyframes = null;
|
||||||
let seenPseudoElement = false;
|
let seenPseudoElement = false;
|
||||||
let seenNormalElement = false;
|
let seenNormalElement = false;
|
||||||
|
let container = null;
|
||||||
|
|
||||||
if (!this._elementStyle.rules) {
|
if (!this._elementStyle.rules) {
|
||||||
return;
|
return;
|
||||||
|
@ -1688,7 +1749,7 @@ CssRuleView.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
let inheritedSource = rule.inheritedSource;
|
let inheritedSource = rule.inheritedSource;
|
||||||
if (inheritedSource != lastInheritedSource) {
|
if (inheritedSource && inheritedSource != lastInheritedSource) {
|
||||||
let div = this.doc.createElementNS(HTML_NS, "div");
|
let div = this.doc.createElementNS(HTML_NS, "div");
|
||||||
div.className = this._getRuleViewHeaderClassName();
|
div.className = this._getRuleViewHeaderClassName();
|
||||||
div.textContent = inheritedSource;
|
div.textContent = inheritedSource;
|
||||||
|
@ -1698,33 +1759,25 @@ CssRuleView.prototype = {
|
||||||
|
|
||||||
if (!seenPseudoElement && rule.pseudoElement) {
|
if (!seenPseudoElement && rule.pseudoElement) {
|
||||||
seenPseudoElement = true;
|
seenPseudoElement = true;
|
||||||
|
container = this.createExpandableContainer(this.pseudoElementLabel, true);
|
||||||
|
}
|
||||||
|
|
||||||
let div = this.doc.createElementNS(HTML_NS, "div");
|
let keyframes = rule.keyframes;
|
||||||
div.className = this._getRuleViewHeaderClassName(true);
|
if (keyframes && keyframes != lastKeyframes) {
|
||||||
div.textContent = this.pseudoElementLabel;
|
lastKeyframes = keyframes;
|
||||||
div.addEventListener("dblclick", () => {
|
container = this.createExpandableContainer(rule.keyframesName);
|
||||||
this.togglePseudoElementVisibility(!this.showPseudoElements);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
let twisty = this.pseudoElementTwisty =
|
|
||||||
this.doc.createElementNS(HTML_NS, "span");
|
|
||||||
twisty.className = "ruleview-expander theme-twisty";
|
|
||||||
twisty.addEventListener("click", () => {
|
|
||||||
this.togglePseudoElementVisibility(!this.showPseudoElements);
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
div.insertBefore(twisty, div.firstChild);
|
|
||||||
this.element.appendChild(div);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rule.editor) {
|
if (!rule.editor) {
|
||||||
rule.editor = new RuleEditor(this, rule);
|
rule.editor = new RuleEditor(this, rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.appendChild(rule.editor.element);
|
if (container && (rule.pseudoElement || keyframes)) {
|
||||||
|
container.appendChild(rule.editor.element);
|
||||||
|
} else {
|
||||||
|
this.element.appendChild(rule.editor.element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.togglePseudoElementVisibility(this.showPseudoElements);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1756,7 +1809,10 @@ function RuleEditor(aRuleView, aRule) {
|
||||||
RuleEditor.prototype = {
|
RuleEditor.prototype = {
|
||||||
get isSelectorEditable() {
|
get isSelectorEditable() {
|
||||||
let toolbox = this.ruleView.inspector.toolbox;
|
let toolbox = this.ruleView.inspector.toolbox;
|
||||||
return toolbox.target.client.traits.selectorEditable;
|
return this.isEditable &&
|
||||||
|
toolbox.target.client.traits.selectorEditable &&
|
||||||
|
this.rule.domRule.type !== ELEMENT_STYLE &&
|
||||||
|
this.rule.domRule.type !== Ci.nsIDOMCSSRule.KEYFRAME_RULE
|
||||||
},
|
},
|
||||||
|
|
||||||
_create: function() {
|
_create: function() {
|
||||||
|
@ -1764,9 +1820,6 @@ RuleEditor.prototype = {
|
||||||
this.element.className = "ruleview-rule theme-separator";
|
this.element.className = "ruleview-rule theme-separator";
|
||||||
this.element.setAttribute("uneditable", !this.isEditable);
|
this.element.setAttribute("uneditable", !this.isEditable);
|
||||||
this.element._ruleEditor = this;
|
this.element._ruleEditor = this;
|
||||||
if (this.rule.pseudoElement) {
|
|
||||||
this.element.classList.add("ruleview-rule-pseudo-element");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Give a relative position for the inplace editor's measurement
|
// Give a relative position for the inplace editor's measurement
|
||||||
// span to be placed absolutely against.
|
// span to be placed absolutely against.
|
||||||
|
@ -1808,8 +1861,7 @@ RuleEditor.prototype = {
|
||||||
class: "ruleview-selector theme-fg-color3"
|
class: "ruleview-selector theme-fg-color3"
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.isEditable && this.rule.domRule.type !== ELEMENT_STYLE &&
|
if (this.isSelectorEditable) {
|
||||||
this.isSelectorEditable) {
|
|
||||||
this.selectorContainer.addEventListener("click", aEvent => {
|
this.selectorContainer.addEventListener("click", aEvent => {
|
||||||
// Clicks within the selector shouldn't propagate any further.
|
// Clicks within the selector shouldn't propagate any further.
|
||||||
aEvent.stopPropagation();
|
aEvent.stopPropagation();
|
||||||
|
@ -1925,6 +1977,8 @@ RuleEditor.prototype = {
|
||||||
// style, just show the text directly.
|
// style, just show the text directly.
|
||||||
if (this.rule.domRule.type === ELEMENT_STYLE) {
|
if (this.rule.domRule.type === ELEMENT_STYLE) {
|
||||||
this.selectorText.textContent = this.rule.selectorText;
|
this.selectorText.textContent = this.rule.selectorText;
|
||||||
|
} else if (this.rule.domRule.type === Ci.nsIDOMCSSRule.KEYFRAME_RULE) {
|
||||||
|
this.selectorText.textContent = this.rule.domRule.keyText;
|
||||||
} else {
|
} else {
|
||||||
this.rule.domRule.selectors.forEach((selector, i) => {
|
this.rule.domRule.selectors.forEach((selector, i) => {
|
||||||
if (i != 0) {
|
if (i != 0) {
|
||||||
|
|
|
@ -38,11 +38,11 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruleview-rule-pseudo-element {
|
.ruleview-expandable-container {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-pseudo-elements .ruleview-rule-pseudo-element {
|
.show-expandable-container + .ruleview-expandable-container {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ support-files =
|
||||||
doc_content_stylesheet_linked.css
|
doc_content_stylesheet_linked.css
|
||||||
doc_content_stylesheet_script.css
|
doc_content_stylesheet_script.css
|
||||||
doc_content_stylesheet_xul.css
|
doc_content_stylesheet_xul.css
|
||||||
|
doc_keyframeanimation.html
|
||||||
|
doc_keyframeanimation.css
|
||||||
doc_matched_selectors.html
|
doc_matched_selectors.html
|
||||||
doc_media_queries.html
|
doc_media_queries.html
|
||||||
doc_pseudoelement.html
|
doc_pseudoelement.html
|
||||||
|
@ -75,6 +77,8 @@ support-files =
|
||||||
skip-if = os == "win" && debug # bug 963492
|
skip-if = os == "win" && debug # bug 963492
|
||||||
[browser_ruleview_inherit.js]
|
[browser_ruleview_inherit.js]
|
||||||
[browser_ruleview_keybindings.js]
|
[browser_ruleview_keybindings.js]
|
||||||
|
[browser_ruleview_keyframes-rule_01.js]
|
||||||
|
[browser_ruleview_keyframes-rule_02.js]
|
||||||
[browser_ruleview_livepreview.js]
|
[browser_ruleview_livepreview.js]
|
||||||
[browser_ruleview_mathml-element.js]
|
[browser_ruleview_mathml-element.js]
|
||||||
[browser_ruleview_media-queries.js]
|
[browser_ruleview_media-queries.js]
|
||||||
|
|
|
@ -51,7 +51,8 @@ let test = asyncTest(function*() {
|
||||||
function* testEditSelector(view, name) {
|
function* testEditSelector(view, name) {
|
||||||
info("Test editing existing selector fields");
|
info("Test editing existing selector fields");
|
||||||
|
|
||||||
let idRuleEditor = getRuleViewRuleEditor(view, 1);
|
let idRuleEditor = getRuleViewRuleEditor(view, 1) ||
|
||||||
|
getRuleViewRuleEditor(view, 1, 0);
|
||||||
|
|
||||||
info("Focusing an existing selector name in the rule-view");
|
info("Focusing an existing selector name in the rule-view");
|
||||||
let editor = yield focusEditableField(idRuleEditor.selectorText);
|
let editor = yield focusEditableField(idRuleEditor.selectorText);
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test that keyframe rules and gutters are displayed correctly in the rule view
|
||||||
|
|
||||||
|
const TEST_URI = TEST_URL_ROOT + "doc_keyframeanimation.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
yield addTab(TEST_URI);
|
||||||
|
|
||||||
|
let {toolbox, inspector, view} = yield openRuleView();
|
||||||
|
|
||||||
|
yield testPacman(inspector, view);
|
||||||
|
yield testBoxy(inspector, view);
|
||||||
|
yield testMoxy(inspector, view);
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testPacman(inspector, view) {
|
||||||
|
info("Test content and gutter in the keyframes rule of #pacman");
|
||||||
|
|
||||||
|
let {
|
||||||
|
rules,
|
||||||
|
element,
|
||||||
|
elementStyle
|
||||||
|
} = yield assertKeyframeRules("#pacman", inspector, view, {
|
||||||
|
elementRulesNb: 2,
|
||||||
|
keyframeRulesNb: 2,
|
||||||
|
keyframesRules: ["pacman", "pacman"],
|
||||||
|
keyframeRules: ["100%", "100%"]
|
||||||
|
});
|
||||||
|
|
||||||
|
let gutters = assertGutters(view, {
|
||||||
|
guttersNbs: 2,
|
||||||
|
gutterHeading: ["Keyframes pacman", "Keyframes pacman"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function* testBoxy(inspector, view) {
|
||||||
|
info("Test content and gutter in the keyframes rule of #boxy");
|
||||||
|
|
||||||
|
let {
|
||||||
|
rules,
|
||||||
|
element,
|
||||||
|
elementStyle
|
||||||
|
} = yield assertKeyframeRules("#boxy", inspector, view, {
|
||||||
|
elementRulesNb: 3,
|
||||||
|
keyframeRulesNb: 3,
|
||||||
|
keyframesRules: ["boxy", "boxy", "boxy"],
|
||||||
|
keyframeRules: ["10%", "20%", "100%"]
|
||||||
|
});
|
||||||
|
|
||||||
|
let gutters = assertGutters(view, {
|
||||||
|
guttersNbs: 1,
|
||||||
|
gutterHeading: ["Keyframes boxy"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMoxy(inspector, view) {
|
||||||
|
info("Test content and gutter in the keyframes rule of #moxy");
|
||||||
|
|
||||||
|
let {
|
||||||
|
rules,
|
||||||
|
element,
|
||||||
|
elementStyle
|
||||||
|
} = yield assertKeyframeRules("#moxy", inspector, view, {
|
||||||
|
elementRulesNb: 3,
|
||||||
|
keyframeRulesNb: 4,
|
||||||
|
keyframesRules: ["boxy", "boxy", "boxy", "moxy"],
|
||||||
|
keyframeRules: ["10%", "20%", "100%", "100%"]
|
||||||
|
});
|
||||||
|
|
||||||
|
let gutters = assertGutters(view, {
|
||||||
|
guttersNbs: 2,
|
||||||
|
gutterHeading: ["Keyframes boxy", "Keyframes moxy"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function* testNode(selector, inspector, view) {
|
||||||
|
let element = getNode(selector);
|
||||||
|
yield selectNode(element, inspector);
|
||||||
|
let elementStyle = view._elementStyle;
|
||||||
|
return {element, elementStyle};
|
||||||
|
}
|
||||||
|
|
||||||
|
function* assertKeyframeRules(selector, inspector, view, expected) {
|
||||||
|
let {element, elementStyle} = yield testNode(selector, inspector, view);
|
||||||
|
|
||||||
|
let rules = {
|
||||||
|
elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
|
||||||
|
keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
|
||||||
|
};
|
||||||
|
|
||||||
|
is(rules.elementRules.length, expected.elementRulesNb, selector +
|
||||||
|
" has the correct number of non keyframe element rules");
|
||||||
|
is(rules.keyframeRules.length, expected.keyframeRulesNb, selector +
|
||||||
|
" has the correct number of keyframe rules");
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (let keyframeRule of rules.keyframeRules) {
|
||||||
|
ok(keyframeRule.keyframes.name == expected.keyframesRules[i],
|
||||||
|
keyframeRule.keyframes.name + " has the correct keyframes name");
|
||||||
|
ok(keyframeRule.domRule.keyText == expected.keyframeRules[i],
|
||||||
|
keyframeRule.domRule.keyText + " selector heading is correct");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {rules, element, elementStyle};
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertGutters(view, expected) {
|
||||||
|
let gutters = view.element.querySelectorAll(".theme-gutter");
|
||||||
|
|
||||||
|
is(gutters.length, expected.guttersNbs,
|
||||||
|
"There are " + gutters.length + " gutter headings");
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (let gutter of gutters) {
|
||||||
|
is(gutter.textContent, expected.gutterHeading[i],
|
||||||
|
"Correct " + gutter.textContent + " gutter headings");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return gutters;
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test that verifies the content of the keyframes rule and property changes
|
||||||
|
// to keyframe rules
|
||||||
|
|
||||||
|
const TEST_URI = TEST_URL_ROOT + "doc_keyframeanimation.html";
|
||||||
|
|
||||||
|
let test = asyncTest(function*() {
|
||||||
|
yield addTab(TEST_URI);
|
||||||
|
|
||||||
|
let {toolbox, inspector, view} = yield openRuleView();
|
||||||
|
|
||||||
|
yield testPacman(inspector, view);
|
||||||
|
yield testBoxy(inspector, view);
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testPacman(inspector, view) {
|
||||||
|
info("Test content in the keyframes rule of #pacman");
|
||||||
|
|
||||||
|
let {
|
||||||
|
rules,
|
||||||
|
element,
|
||||||
|
elementStyle
|
||||||
|
} = yield getKeyframeRules("#pacman", inspector, view);
|
||||||
|
|
||||||
|
info("Test text properties for Keyframes #pacman");
|
||||||
|
|
||||||
|
is
|
||||||
|
(
|
||||||
|
convertTextPropsToString(rules.keyframeRules[0].textProps),
|
||||||
|
"left: 750px",
|
||||||
|
"Keyframe pacman (100%) property is correct"
|
||||||
|
);
|
||||||
|
|
||||||
|
info("Test dynamic changes to keyframe rule for #pacman");
|
||||||
|
|
||||||
|
let defaultView = element.ownerDocument.defaultView;
|
||||||
|
let ruleEditor = view.element.children[5].childNodes[0]._ruleEditor;
|
||||||
|
ruleEditor.addProperty("opacity", "0");
|
||||||
|
ruleEditor.addProperty("top", "750px");
|
||||||
|
|
||||||
|
yield ruleEditor._applyingModifications;
|
||||||
|
yield once(element, "animationend");
|
||||||
|
|
||||||
|
is
|
||||||
|
(
|
||||||
|
convertTextPropsToString(rules.keyframeRules[1].textProps),
|
||||||
|
"left: 750px; opacity: 0; top: 750px",
|
||||||
|
"Keyframe pacman (100%) property is correct"
|
||||||
|
);
|
||||||
|
|
||||||
|
is(defaultView.getComputedStyle(element).getPropertyValue("opacity"), "0",
|
||||||
|
"Added opacity property should have been used.");
|
||||||
|
is(defaultView.getComputedStyle(element).getPropertyValue("top"), "750px",
|
||||||
|
"Added top property should have been used.");
|
||||||
|
}
|
||||||
|
|
||||||
|
function* testBoxy(inspector, view) {
|
||||||
|
info("Test content in the keyframes rule of #boxy");
|
||||||
|
|
||||||
|
let {
|
||||||
|
rules,
|
||||||
|
element,
|
||||||
|
elementStyle
|
||||||
|
} = yield getKeyframeRules("#boxy", inspector, view);
|
||||||
|
|
||||||
|
info("Test text properties for Keyframes #boxy");
|
||||||
|
|
||||||
|
is
|
||||||
|
(
|
||||||
|
convertTextPropsToString(rules.keyframeRules[0].textProps),
|
||||||
|
"background-color: blue",
|
||||||
|
"Keyframe boxy (10%) property is correct"
|
||||||
|
);
|
||||||
|
|
||||||
|
is
|
||||||
|
(
|
||||||
|
convertTextPropsToString(rules.keyframeRules[1].textProps),
|
||||||
|
"background-color: green",
|
||||||
|
"Keyframe boxy (20%) property is correct"
|
||||||
|
);
|
||||||
|
|
||||||
|
is
|
||||||
|
(
|
||||||
|
convertTextPropsToString(rules.keyframeRules[2].textProps),
|
||||||
|
"opacity: 0",
|
||||||
|
"Keyframe boxy (100%) property is correct"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertTextPropsToString(textProps) {
|
||||||
|
return textProps.map(t => t.name + ": " + t.value).join("; ");
|
||||||
|
}
|
||||||
|
|
||||||
|
function* getKeyframeRules(selector, inspector, view) {
|
||||||
|
let element = getNode(selector);
|
||||||
|
|
||||||
|
yield selectNode(element, inspector);
|
||||||
|
let elementStyle = view._elementStyle;
|
||||||
|
|
||||||
|
let rules = {
|
||||||
|
elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
|
||||||
|
keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
|
||||||
|
};
|
||||||
|
|
||||||
|
return {rules, element, elementStyle};
|
||||||
|
}
|
|
@ -38,24 +38,22 @@ function* testTopLeft(inspector, view) {
|
||||||
|
|
||||||
// Make sure that clicking on the twisty hides pseudo elements
|
// Make sure that clicking on the twisty hides pseudo elements
|
||||||
let expander = gutters[0].querySelector(".ruleview-expander");
|
let expander = gutters[0].querySelector(".ruleview-expander");
|
||||||
ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded");
|
ok (view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are expanded");
|
||||||
expander.click();
|
expander.click();
|
||||||
ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty");
|
ok (!view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are collapsed by twisty");
|
||||||
expander.click();
|
expander.click();
|
||||||
ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again");
|
ok (view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are expanded again");
|
||||||
|
|
||||||
// Make sure that dblclicking on the header container also toggles the pseudo elements
|
// Make sure that dblclicking on the header container also toggles the pseudo elements
|
||||||
EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview"));
|
EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview"));
|
||||||
ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking");
|
ok (!view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are collapsed by dblclicking");
|
||||||
|
|
||||||
let defaultView = element.ownerDocument.defaultView;
|
let defaultView = element.ownerDocument.defaultView;
|
||||||
let elementRule = rules.elementRules[0];
|
let elementRule = rules.elementRules[0];
|
||||||
let elementRuleView = [].filter.call(view.element.children, e => {
|
let elementRuleView = getRuleViewRuleEditor(view, 3);
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementRule;
|
|
||||||
})[0]._ruleEditor;
|
|
||||||
|
|
||||||
let elementAfterRule = rules.afterRules[0];
|
let elementAfterRule = rules.afterRules[0];
|
||||||
let elementAfterRuleView = [].filter.call(view.element.children, (e) => {
|
let elementAfterRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
|
@ -68,7 +66,7 @@ function* testTopLeft(inspector, view) {
|
||||||
);
|
);
|
||||||
|
|
||||||
let elementBeforeRule = rules.beforeRules[0];
|
let elementBeforeRule = rules.beforeRules[0];
|
||||||
let elementBeforeRuleView = [].filter.call(view.element.children, (e) => {
|
let elementBeforeRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
|
@ -138,10 +136,10 @@ function* testTopRight(inspector, view) {
|
||||||
let gutters = assertGutters(view);
|
let gutters = assertGutters(view);
|
||||||
|
|
||||||
let expander = gutters[0].querySelector(".ruleview-expander");
|
let expander = gutters[0].querySelector(".ruleview-expander");
|
||||||
ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements remain collapsed after switching element");
|
ok (!view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements remain collapsed after switching element");
|
||||||
expander.scrollIntoView();
|
expander.scrollIntoView();
|
||||||
expander.click();
|
expander.click();
|
||||||
ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are shown again after clicking twisty");
|
ok (view.element.firstChild.classList.contains("show-expandable-container"), "Pseudo Elements are shown again after clicking twisty");
|
||||||
}
|
}
|
||||||
|
|
||||||
function* testBottomRight(inspector, view) {
|
function* testBottomRight(inspector, view) {
|
||||||
|
@ -183,7 +181,7 @@ function* testParagraph(inspector, view) {
|
||||||
let gutters = assertGutters(view);
|
let gutters = assertGutters(view);
|
||||||
|
|
||||||
let elementFirstLineRule = rules.firstLineRules[0];
|
let elementFirstLineRule = rules.firstLineRules[0];
|
||||||
let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => {
|
let elementFirstLineRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
|
@ -195,7 +193,7 @@ function* testParagraph(inspector, view) {
|
||||||
);
|
);
|
||||||
|
|
||||||
let elementFirstLetterRule = rules.firstLetterRules[0];
|
let elementFirstLetterRule = rules.firstLetterRules[0];
|
||||||
let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => {
|
let elementFirstLetterRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
|
@ -207,7 +205,7 @@ function* testParagraph(inspector, view) {
|
||||||
);
|
);
|
||||||
|
|
||||||
let elementSelectionRule = rules.selectionRules[0];
|
let elementSelectionRule = rules.selectionRules[0];
|
||||||
let elementSelectionRuleView = [].filter.call(view.element.children, (e) => {
|
let elementSelectionRuleView = [].filter.call(view.element.children[1].children, (e) => {
|
||||||
return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule;
|
return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule;
|
||||||
})[0]._ruleEditor;
|
})[0]._ruleEditor;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
.box {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #FFCB01;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pacman {
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
border-right: 60px solid transparent;
|
||||||
|
border-top: 60px solid #FFCB01;
|
||||||
|
border-left: 60px solid #FFCB01;
|
||||||
|
border-bottom: 60px solid #FFCB01;
|
||||||
|
border-top-left-radius: 60px;
|
||||||
|
border-bottom-left-radius: 60px;
|
||||||
|
border-top-right-radius: 60px;
|
||||||
|
border-bottom-right-radius: 60px;
|
||||||
|
top: 120px;
|
||||||
|
left: 150px;
|
||||||
|
position: absolute;
|
||||||
|
animation-name: pacman;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-duration: 15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#boxy {
|
||||||
|
top: 170px;
|
||||||
|
left: 450px;
|
||||||
|
position: absolute;
|
||||||
|
animation: 4s linear 0s normal none infinite boxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#moxy {
|
||||||
|
animation-name: moxy, boxy;
|
||||||
|
animation-delay: 3.5s;
|
||||||
|
animation-duration: 2s;
|
||||||
|
top: 170px;
|
||||||
|
left: 650px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-moz-keyframes pacman {
|
||||||
|
100% {
|
||||||
|
left: 750px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pacman {
|
||||||
|
100% {
|
||||||
|
left: 750px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes boxy {
|
||||||
|
10% {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes moxy {
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>test case for keyframes rule in rule-view</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="doc_keyframeanimation.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="pacman"></div>
|
||||||
|
<div id="boxy" class="circle"></div>
|
||||||
|
<div id="moxy" class="circle"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -619,11 +619,14 @@ function getRuleViewLinkByIndex(view, index) {
|
||||||
/**
|
/**
|
||||||
* Get the rule editor from the rule-view given its index
|
* Get the rule editor from the rule-view given its index
|
||||||
* @param {CssRuleView} view The instance of the rule-view panel
|
* @param {CssRuleView} view The instance of the rule-view panel
|
||||||
* @param {Number} index The index of the link to get
|
* @param {Number} childrenIndex The children index of the element to get
|
||||||
|
* @param {Number} nodeIndex The child node index of the element to get
|
||||||
* @return {DOMNode} The rule editor if any at this index
|
* @return {DOMNode} The rule editor if any at this index
|
||||||
*/
|
*/
|
||||||
function getRuleViewRuleEditor(view, index) {
|
function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) {
|
||||||
return view.element.children[index]._ruleEditor;
|
return nodeIndex !== undefined ?
|
||||||
|
view.element.children[childrenIndex].childNodes[nodeIndex]._ruleEditor :
|
||||||
|
view.element.children[childrenIndex]._ruleEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -45,7 +45,8 @@ types.addLifetime("walker", "walker");
|
||||||
*/
|
*/
|
||||||
types.addDictType("appliedstyle", {
|
types.addDictType("appliedstyle", {
|
||||||
rule: "domstylerule#actorid",
|
rule: "domstylerule#actorid",
|
||||||
inherited: "nullable:domnode#actorid"
|
inherited: "nullable:domnode#actorid",
|
||||||
|
keyframes: "nullable:domstylerule#actorid"
|
||||||
});
|
});
|
||||||
|
|
||||||
types.addDictType("matchedselector", {
|
types.addDictType("matchedselector", {
|
||||||
|
@ -154,7 +155,7 @@ var PageStyleActor = protocol.ActorClass({
|
||||||
|
|
||||||
this.cssLogic.sourceFilter = options.filter || CssLogic.FILTER.UA;
|
this.cssLogic.sourceFilter = options.filter || CssLogic.FILTER.UA;
|
||||||
this.cssLogic.highlight(node.rawNode);
|
this.cssLogic.highlight(node.rawNode);
|
||||||
let computed = this.cssLogic._computedStyle || [];
|
let computed = this.cssLogic.computedStyle || [];
|
||||||
|
|
||||||
Array.prototype.forEach.call(computed, name => {
|
Array.prototype.forEach.call(computed, name => {
|
||||||
let matched = undefined;
|
let matched = undefined;
|
||||||
|
@ -324,8 +325,7 @@ var PageStyleActor = protocol.ActorClass({
|
||||||
* Helper function for getApplied, adds all the rules from a given
|
* Helper function for getApplied, adds all the rules from a given
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
addElementRules: function(element, inherited, options, rules)
|
addElementRules: function(element, inherited, options, rules) {
|
||||||
{
|
|
||||||
if (!element.style) {
|
if (!element.style) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,6 @@ var PageStyleActor = protocol.ActorClass({
|
||||||
isSystem: isSystem
|
isSystem: isSystem
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -431,6 +430,28 @@ var PageStyleActor = protocol.ActorClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add all the keyframes rule associated with the element
|
||||||
|
let computedStyle = this.cssLogic.computedStyle;
|
||||||
|
if (computedStyle) {
|
||||||
|
let animationNames = computedStyle.animationName.split(",");
|
||||||
|
animationNames = animationNames.map(name => name.trim());
|
||||||
|
|
||||||
|
if (animationNames) {
|
||||||
|
// Traverse through all the available keyframes rule and add
|
||||||
|
// the keyframes rule that matches the computed animation name
|
||||||
|
for (let keyframesRule of this.cssLogic.keyframesRules) {
|
||||||
|
if (animationNames.indexOf(keyframesRule.name) > -1) {
|
||||||
|
for (let rule of keyframesRule.cssRules) {
|
||||||
|
entries.push({
|
||||||
|
rule: this._styleRef(rule),
|
||||||
|
keyframes: this._styleRef(keyframesRule)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let rules = new Set;
|
let rules = new Set;
|
||||||
let sheets = new Set;
|
let sheets = new Set;
|
||||||
entries.forEach(entry => rules.add(entry.rule));
|
entries.forEach(entry => rules.add(entry.rule));
|
||||||
|
@ -661,7 +682,9 @@ var StyleRuleActor = protocol.ActorClass({
|
||||||
if (item instanceof (Ci.nsIDOMCSSRule)) {
|
if (item instanceof (Ci.nsIDOMCSSRule)) {
|
||||||
this.type = item.type;
|
this.type = item.type;
|
||||||
this.rawRule = item;
|
this.rawRule = item;
|
||||||
if (this.rawRule instanceof Ci.nsIDOMCSSStyleRule && this.rawRule.parentStyleSheet) {
|
if ((this.rawRule instanceof Ci.nsIDOMCSSStyleRule ||
|
||||||
|
this.rawRule instanceof Ci.nsIDOMMozCSSKeyframeRule) &&
|
||||||
|
this.rawRule.parentStyleSheet) {
|
||||||
this.line = DOMUtils.getRuleLine(this.rawRule);
|
this.line = DOMUtils.getRuleLine(this.rawRule);
|
||||||
this.column = DOMUtils.getRuleColumn(this.rawRule);
|
this.column = DOMUtils.getRuleColumn(this.rawRule);
|
||||||
}
|
}
|
||||||
|
@ -739,6 +762,14 @@ var StyleRuleActor = protocol.ActorClass({
|
||||||
form.media.push(this.rawRule.media.item(i));
|
form.media.push(this.rawRule.media.item(i));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Ci.nsIDOMCSSRule.KEYFRAMES_RULE:
|
||||||
|
form.cssText = this.rawRule.cssText;
|
||||||
|
form.name = this.rawRule.name;
|
||||||
|
break;
|
||||||
|
case Ci.nsIDOMCSSRule.KEYFRAME_RULE:
|
||||||
|
form.cssText = this.rawStyle.cssText || "";
|
||||||
|
form.keyText = this.rawRule.keyText || "";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return form;
|
return form;
|
||||||
|
@ -884,7 +915,7 @@ var StyleRuleFront = protocol.FrontClass(StyleRuleActor, {
|
||||||
* Return a new RuleModificationList for this node.
|
* Return a new RuleModificationList for this node.
|
||||||
*/
|
*/
|
||||||
startModifyingProperties: function() {
|
startModifyingProperties: function() {
|
||||||
return new RuleModificationList(this);
|
return new RuleModificationList(this);
|
||||||
},
|
},
|
||||||
|
|
||||||
get type() this._form.type,
|
get type() this._form.type,
|
||||||
|
@ -893,6 +924,12 @@ var StyleRuleFront = protocol.FrontClass(StyleRuleActor, {
|
||||||
get cssText() {
|
get cssText() {
|
||||||
return this._form.cssText;
|
return this._form.cssText;
|
||||||
},
|
},
|
||||||
|
get keyText() {
|
||||||
|
return this._form.keyText;
|
||||||
|
},
|
||||||
|
get name() {
|
||||||
|
return this._form.name;
|
||||||
|
},
|
||||||
get selectors() {
|
get selectors() {
|
||||||
return this._form.selectors;
|
return this._form.selectors;
|
||||||
},
|
},
|
||||||
|
|
|
@ -129,6 +129,9 @@ CssLogic.prototype = {
|
||||||
_matchedRules: null,
|
_matchedRules: null,
|
||||||
_matchedSelectors: null,
|
_matchedSelectors: null,
|
||||||
|
|
||||||
|
// Cached keyframes rules in all stylesheets
|
||||||
|
_keyframesRules: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset various properties
|
* Reset various properties
|
||||||
*/
|
*/
|
||||||
|
@ -141,6 +144,7 @@ CssLogic.prototype = {
|
||||||
this._sheetsCached = false;
|
this._sheetsCached = false;
|
||||||
this._matchedRules = null;
|
this._matchedRules = null;
|
||||||
this._matchedSelectors = null;
|
this._matchedSelectors = null;
|
||||||
|
this._keyframesRules = [];
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,6 +183,15 @@ CssLogic.prototype = {
|
||||||
this._computedStyle = win.getComputedStyle(this.viewedElement, "");
|
this._computedStyle = win.getComputedStyle(this.viewedElement, "");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the values of all the computed CSS properties for the highlighted
|
||||||
|
* element.
|
||||||
|
* @returns {object} The computed CSS properties for a selected element
|
||||||
|
*/
|
||||||
|
get computedStyle() {
|
||||||
|
return this._computedStyle;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the source filter.
|
* Get the source filter.
|
||||||
* @returns {string} The source filter being used.
|
* @returns {string} The source filter being used.
|
||||||
|
@ -270,7 +283,7 @@ CssLogic.prototype = {
|
||||||
* Cache a stylesheet if it falls within the requirements: if it's enabled,
|
* Cache a stylesheet if it falls within the requirements: if it's enabled,
|
||||||
* and if the @media is allowed. This method also walks through the stylesheet
|
* and if the @media is allowed. This method also walks through the stylesheet
|
||||||
* cssRules to find @imported rules, to cache the stylesheets of those rules
|
* cssRules to find @imported rules, to cache the stylesheets of those rules
|
||||||
* as well.
|
* as well. In addition, the @keyframes rules in the stylesheet are cached.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {CSSStyleSheet} aDomSheet the CSSStyleSheet object to cache.
|
* @param {CSSStyleSheet} aDomSheet the CSSStyleSheet object to cache.
|
||||||
|
@ -291,13 +304,15 @@ CssLogic.prototype = {
|
||||||
if (cssSheet._passId != this._passId) {
|
if (cssSheet._passId != this._passId) {
|
||||||
cssSheet._passId = this._passId;
|
cssSheet._passId = this._passId;
|
||||||
|
|
||||||
// Find import rules.
|
// Find import and keyframes rules.
|
||||||
Array.prototype.forEach.call(aDomSheet.cssRules, function(aDomRule) {
|
for (let aDomRule of aDomSheet.cssRules) {
|
||||||
if (aDomRule.type == Ci.nsIDOMCSSRule.IMPORT_RULE && aDomRule.styleSheet &&
|
if (aDomRule.type == Ci.nsIDOMCSSRule.IMPORT_RULE && aDomRule.styleSheet &&
|
||||||
this.mediaMatches(aDomRule)) {
|
this.mediaMatches(aDomRule)) {
|
||||||
this._cacheSheet(aDomRule.styleSheet);
|
this._cacheSheet(aDomRule.styleSheet);
|
||||||
|
} else if (aDomRule.type == Ci.nsIDOMCSSRule.KEYFRAMES_RULE) {
|
||||||
|
this._keyframesRules.push(aDomRule);
|
||||||
}
|
}
|
||||||
}, this);
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -322,6 +337,19 @@ CssLogic.prototype = {
|
||||||
return sheets;
|
return sheets;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the list of keyframes rules in the document.
|
||||||
|
*
|
||||||
|
* @ return {array} the list of keyframes rules in the document.
|
||||||
|
*/
|
||||||
|
get keyframesRules()
|
||||||
|
{
|
||||||
|
if (!this._sheetsCached) {
|
||||||
|
this._cacheSheets();
|
||||||
|
}
|
||||||
|
return this._keyframesRules;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a CssSheet object for a given a CSSStyleSheet object. If the
|
* Retrieve a CssSheet object for a given a CSSStyleSheet object. If the
|
||||||
* stylesheet is already cached, you get the existing CssSheet object,
|
* stylesheet is already cached, you get the existing CssSheet object,
|
||||||
|
@ -620,7 +648,6 @@ CssLogic.prototype = {
|
||||||
this._matchedRules.push([rule, status]);
|
this._matchedRules.push([rule, status]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add element.style information.
|
// Add element.style information.
|
||||||
if (element.style && element.style.length > 0) {
|
if (element.style && element.style.length > 0) {
|
||||||
let rule = new CssRule(null, { style: element.style }, element);
|
let rule = new CssRule(null, { style: element.style }, element);
|
||||||
|
@ -644,7 +671,7 @@ CssLogic.prototype = {
|
||||||
let mediaText = aDomObject.media.mediaText;
|
let mediaText = aDomObject.media.mediaText;
|
||||||
return !mediaText || this.viewedDocument.defaultView.
|
return !mediaText || this.viewedDocument.defaultView.
|
||||||
matchMedia(mediaText).matches;
|
matchMedia(mediaText).matches;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1535,9 +1562,9 @@ CssPropertyInfo.prototype = {
|
||||||
*/
|
*/
|
||||||
get value()
|
get value()
|
||||||
{
|
{
|
||||||
if (!this._value && this._cssLogic._computedStyle) {
|
if (!this._value && this._cssLogic.computedStyle) {
|
||||||
try {
|
try {
|
||||||
this._value = this._cssLogic._computedStyle.getPropertyValue(this.property);
|
this._value = this._cssLogic.computedStyle.getPropertyValue(this.property);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
Services.console.logStringMessage('Error reading computed style for ' +
|
Services.console.logStringMessage('Error reading computed style for ' +
|
||||||
this.property);
|
this.property);
|
||||||
|
|
|
@ -35,6 +35,10 @@ rule.sourceElement=element
|
||||||
# e.g "Inherited from body#bodyID"
|
# e.g "Inherited from body#bodyID"
|
||||||
rule.inheritedFrom=Inherited from %S
|
rule.inheritedFrom=Inherited from %S
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (rule.keyframe): Shown for CSS Rules keyframe header.
|
||||||
|
# Will be passed an identifier of the keyframe animation name.
|
||||||
|
rule.keyframe=Keyframes %S
|
||||||
|
|
||||||
# LOCALIZATION NOTE (rule.userAgentStyles): Shown next to the style sheet
|
# LOCALIZATION NOTE (rule.userAgentStyles): Shown next to the style sheet
|
||||||
# link for CSS rules that were loaded from a user agent style sheet.
|
# link for CSS rules that were loaded from a user agent style sheet.
|
||||||
# These styles will not be editable, and will only be visible if the
|
# These styles will not be editable, and will only be visible if the
|
||||||
|
|
Загрузка…
Ссылка в новой задаче