updateSource: function () { let rule = this.selectorInfo.rule; this.sheet = rule.parentStyleSheet; if (!rule || !this.sheet) { let oldSource = this.source; this.source = CssLogic.l10n("rule.sourceElement"); return promise.resolve(oldSource); } let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES); if (showOrig && rule.type !== ELEMENT_STYLE) { let deferred = defer(); // set as this first so we show something while we're fetching this.source = CssLogic.shortSource(this.sheet) + ":" + rule.line; rule.getOriginalLocation().then(({href, line}) => { let oldSource = this.source; this.source = CssLogic.shortSource({href: href}) + ":" + line; deferred.resolve(oldSource); }); return deferred.promise; } let oldSource = this.source; this.source = CssLogic.shortSource(this.sheet) + ":" + rule.line; return promise.resolve(oldSource); },
return this.domRule.getOriginalLocation().then(({href, line, mediaText}) => { let mediaString = mediaText ? " @" + mediaText : ""; let linePart = line > 0 ? (":" + line) : ""; let sourceStrings = { full: (href || CssLogic.l10n("rule.sourceInline")) + linePart + mediaString, short: CssLogic.shortSource({href: href}) + linePart + mediaString }; return sourceStrings; });
_create: function () { this.element = this.doc.createElementNS(HTML_NS, "li"); this.element.classList.add("ruleview-property"); this.element._textPropertyEditor = this; this.container = createChild(this.element, "div", { class: "ruleview-propertycontainer" }); // The enable checkbox will disable or enable the rule. this.enable = createChild(this.container, "div", { class: "ruleview-enableproperty theme-checkbox", tabindex: "-1" }); // Click to expand the computed properties of the text property. this.expander = createChild(this.container, "span", { class: "ruleview-expander theme-twisty" }); this.expander.addEventListener("click", this._onExpandClicked, true); this.nameContainer = createChild(this.container, "span", { class: "ruleview-namecontainer" }); // Property name, editable when focused. Property name // is committed when the editor is unfocused. this.nameSpan = createChild(this.nameContainer, "span", { class: "ruleview-propertyname theme-fg-color5", tabindex: this.ruleEditor.isEditable ? "0" : "-1", }); appendText(this.nameContainer, ": "); // Create a span that will hold the property and semicolon. // Use this span to create a slightly larger click target // for the value. this.valueContainer = createChild(this.container, "span", { class: "ruleview-propertyvaluecontainer" }); // Property value, editable when focused. Changes to the // property value are applied as they are typed, and reverted // if the user presses escape. this.valueSpan = createChild(this.valueContainer, "span", { class: "ruleview-propertyvalue theme-fg-color1", tabindex: this.ruleEditor.isEditable ? "0" : "-1", }); // Storing the TextProperty on the elements for easy access // (for instance by the tooltip) this.valueSpan.textProperty = this.prop; this.nameSpan.textProperty = this.prop; // If the value is a color property we need to put it through the parser // so that colors can be coerced into the default color type. This prevents // us from thinking that when colors are coerced they have been changed by // the user. let outputParser = this.ruleView._outputParser; let frag = outputParser.parseCssProperty(this.prop.name, this.prop.value); let parsedValue = frag.textContent; // Save the initial value as the last committed value, // for restoring after pressing escape. this.committed = { name: this.prop.name, value: parsedValue, priority: this.prop.priority }; appendText(this.valueContainer, ";"); this.warning = createChild(this.container, "div", { class: "ruleview-warning", hidden: "", title: CssLogic.l10n("rule.warning.title"), }); // Filter button that filters for the current property name and is // displayed when the property is overridden by another rule. this.filterProperty = createChild(this.container, "div", { class: "ruleview-overridden-rule-filter", hidden: "", title: CssLogic.l10n("rule.filterProperty.title"), }); this.filterProperty.addEventListener("click", event => { this.ruleEditor.ruleView.setFilterStyles("`" + this.prop.name + "`"); event.stopPropagation(); }, false); // Holds the viewers for the computed properties. // will be populated in |_updateComputed|. this.computed = createChild(this.element, "ul", { class: "ruleview-computedlist", }); // Only bind event handlers if the rule is editable. if (this.ruleEditor.isEditable) { this.enable.addEventListener("click", this._onEnableClicked, true); this.nameContainer.addEventListener("click", (event) => { // Clicks within the name shouldn't propagate any further. event.stopPropagation(); // Forward clicks on nameContainer to the editable nameSpan if (event.target === this.nameContainer) { this.nameSpan.click(); } }, false); editableField({ start: this._onStartEditing, element: this.nameSpan, done: this._onNameDone, destroy: this.update, advanceChars: ":", contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY, popup: this.popup }); // Auto blur name field on multiple CSS rules get pasted in. this.nameContainer.addEventListener("paste", blurOnMultipleProperties(this.cssProperties), false); this.valueContainer.addEventListener("click", (event) => { // Clicks within the value shouldn't propagate any further. event.stopPropagation(); // Forward clicks on valueContainer to the editable valueSpan if (event.target === this.valueContainer) { this.valueSpan.click(); } }, false); this.valueSpan.addEventListener("click", (event) => { let target = event.target; if (target.nodeName === "a") { event.stopPropagation(); event.preventDefault(); this.browserWindow.openUILinkIn(target.href, "tab"); } }, false); editableField({ start: this._onStartEditing, element: this.valueSpan, done: this._onValueDone, destroy: this.update, validate: this._onValidate, advanceChars: advanceValidate, contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE, property: this.prop, popup: this.popup, multiline: true, maxWidth: () => this.container.getBoundingClientRect().width }); } },
rule.getOriginalLocation().then(({href, line}) => { let oldSource = this.source; this.source = CssLogic.shortSource({href: href}) + ":" + line; deferred.resolve(oldSource); });
this.mediaText = this.domRule.mediaText; } this.cssProperties = this.elementStyle.ruleView.cssProperties; // Populate the text properties with the style's current authoredText // value, and add in any disabled properties from the store. this.textProps = this._getTextProperties(); this.textProps = this.textProps.concat(this._getDisabledProperties()); } Rule.prototype = { mediaText: "", get title() { let title = CssLogic.shortSource(this.sheet); if (this.domRule.type !== ELEMENT_STYLE && this.ruleLine > 0) { title += ":" + this.ruleLine; } return title + (this.mediaText ? " @media " + this.mediaText : ""); }, get inheritedSource() { if (this._inheritedSource) { return this._inheritedSource; } this._inheritedSource = ""; if (this.inherited) { let eltText = this.inherited.displayName; if (this.inherited.id) {
_create: function () { this.element = this.doc.createElementNS(HTML_NS, "div"); this.element.className = "ruleview-rule theme-separator"; this.element.setAttribute("uneditable", !this.isEditable); this.element.setAttribute("unmatched", this.rule.isUnmatched); this.element._ruleEditor = this; // Give a relative position for the inplace editor's measurement // span to be placed absolutely against. this.element.style.position = "relative"; // Add the source link. this.source = createChild(this.element, "div", { class: "ruleview-rule-source theme-link" }); this.source.addEventListener("click", function () { if (this.source.hasAttribute("unselectable")) { return; } let rule = this.rule.domRule; this.ruleView.emit("ruleview-linked-clicked", rule); }.bind(this)); let sourceLabel = this.doc.createElementNS(XUL_NS, "label"); sourceLabel.setAttribute("crop", "center"); sourceLabel.classList.add("ruleview-rule-source-label"); this.source.appendChild(sourceLabel); this.updateSourceLink(); let code = createChild(this.element, "div", { class: "ruleview-code" }); let header = createChild(code, "div", {}); this.selectorText = createChild(header, "span", { class: "ruleview-selectorcontainer theme-fg-color3", tabindex: this.isSelectorEditable ? "0" : "-1", }); if (this.isSelectorEditable) { this.selectorText.addEventListener("click", event => { // Clicks within the selector shouldn't propagate any further. event.stopPropagation(); }, false); editableField({ element: this.selectorText, done: this._onSelectorDone, }); } if (this.rule.domRule.type !== Ci.nsIDOMCSSRule.KEYFRAME_RULE && this.rule.domRule.selectors) { let selector = this.rule.domRule.selectors.join(", "); let selectorHighlighter = createChild(header, "span", { class: "ruleview-selectorhighlighter" + (this.ruleView.highlightedSelector === selector ? " highlighted" : ""), title: CssLogic.l10n("rule.selectorHighlighter.tooltip") }); selectorHighlighter.addEventListener("click", () => { this.ruleView.toggleSelectorHighlighter(selectorHighlighter, selector); }); } this.openBrace = createChild(header, "span", { class: "ruleview-ruleopen", textContent: " {" }); this.propertyList = createChild(code, "ul", { class: "ruleview-propertylist" }); this.populate(); this.closeBrace = createChild(code, "div", { class: "ruleview-ruleclose", tabindex: this.isEditable ? "0" : "-1", textContent: "}" }); if (this.isEditable) { // A newProperty editor should only be created when no editor was // previously displayed. Since the editors are cleared on blur, // check this.ruleview.isEditing on mousedown this._ruleViewIsEditing = false; code.addEventListener("mousedown", () => { this._ruleViewIsEditing = this.ruleView.isEditing; }); code.addEventListener("click", () => { let selection = this.doc.defaultView.getSelection(); if (selection.isCollapsed && !this._ruleViewIsEditing) { this.newProperty(); } // Cleanup the _ruleViewIsEditing flag this._ruleViewIsEditing = false; }, false); this.element.addEventListener("mousedown", () => { this.doc.defaultView.focus(); }, false); // Create a property editor when the close brace is clicked. editableItem({ element: this.closeBrace }, () => { this.newProperty(); }); } },