addButton.className = "pane-title-button add";
addButton.id = "add-style-button-test-id";
addButton.title = WebInspector.UIString("New Style Rule");
- addButton.addEventListener("click", this._createNewRule.bind(this), false);
+ addButton.addEventListener("click", this._createNewRuleInViaInspectorStyleSheet.bind(this), false);
this.titleElement.appendChild(addButton);
+ addButton.createChild("div", "long-click-glyph fill");
+
+ this._addButtonLongClickController = new WebInspector.LongClickController(addButton);
+ this._addButtonLongClickController.addEventListener(WebInspector.LongClickController.Events.LongClick, this._onAddButtonLongClick.bind(this));
+ this._addButtonLongClickController.enable();
this._computedStylePane = computedStylePane;
computedStylePane.setHostingPane(this);
this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
WebInspector.settings.colorFormat.addChangeListener(this._colorFormatSettingChanged.bind(this));
WebInspector.settings.showUserAgentStyles.addChangeListener(this._showUserAgentStylesSettingChanged.bind(this));
+ WebInspector.settings.showInheritedComputedStyleProperties.addChangeListener(this._showInheritedComputedStyleChanged.bind(this));
this._createElementStatePane();
this.bodyElement.appendChild(this._elementStatePane);
// FIXME: find a way of generating this mapping or getting it from combination of RenderStyleConstants and CSSSelector.cpp at
// runtime.
WebInspector.StylesSidebarPane.PseudoIdNames = [
- "", "first-line", "first-letter", "before", "after", "selection", "", "-webkit-scrollbar", "-webkit-file-upload-button",
- "-webkit-input-placeholder", "-webkit-slider-thumb", "-webkit-search-cancel-button", "-webkit-search-decoration",
- "-webkit-search-results-decoration", "-webkit-search-results-button", "-webkit-media-controls-panel",
- "-webkit-media-controls-play-button", "-webkit-media-controls-mute-button", "-webkit-media-controls-timeline",
- "-webkit-media-controls-timeline-container", "-webkit-media-controls-volume-slider",
- "-webkit-media-controls-volume-slider-container", "-webkit-media-controls-current-time-display",
- "-webkit-media-controls-time-remaining-display", "-webkit-media-controls-fullscreen-button",
- "-webkit-media-controls-toggle-closed-captions-button", "-webkit-media-controls-status-display", "-webkit-scrollbar-thumb",
- "-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece", "-webkit-scrollbar-corner",
- "-webkit-resizer", "-webkit-inner-spin-button", "-webkit-outer-spin-button"
+ "", "first-line", "first-letter", "before", "after", "backdrop", "selection", "", "-webkit-scrollbar",
+ "-webkit-scrollbar-thumb", "-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece",
+ "-webkit-scrollbar-corner", "-webkit-resizer"
];
WebInspector.StylesSidebarPane._colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g;
/**
+ * @enum {string}
+ */
+WebInspector.StylesSidebarPane.Events = {
+ SelectorEditingStarted: "SelectorEditingStarted",
+ SelectorEditingEnded: "SelectorEditingEnded"
+};
+
+/**
* @param {!WebInspector.CSSProperty} property
+ * @return {!Element}
*/
WebInspector.StylesSidebarPane.createExclamationMark = function(property)
{
}
WebInspector.StylesSidebarPane.prototype = {
+ _showInheritedComputedStyleChanged: function()
+ {
+ if (!this.sections || !this.sections[0])
+ return;
+ for (var i = 0; i < this.sections[0].length; ++i) {
+ var section = this.sections[0][i];
+ if (section instanceof WebInspector.ComputedStylePropertiesSection)
+ section.onShowInheritedChanged();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _onAddButtonLongClick: function(event)
+ {
+ this._addButtonLongClickController.reset();
+ var cssModel = this._target.cssModel;
+ var headers = cssModel.styleSheetHeaders().filter(styleSheetResourceHeader);
+
+ /** @type {!Array.<{text: string, handler: function()}>} */
+ var contextMenuDescriptors = [];
+ for (var i = 0; i < headers.length; ++i) {
+ var header = headers[i];
+ var handler = this._createNewRuleInStyleSheet.bind(this, header);
+ contextMenuDescriptors.push({
+ text: WebInspector.displayNameForURL(header.resourceURL()),
+ handler: handler
+ });
+ }
+
+ contextMenuDescriptors.sort(compareDescriptors);
+
+ var contextMenu = new WebInspector.ContextMenu(/** @type {!Event} */(event.data));
+ for (var i = 0; i < contextMenuDescriptors.length; ++i) {
+ var descriptor = contextMenuDescriptors[i];
+ contextMenu.appendItem(descriptor.text, descriptor.handler);
+ }
+ if (!contextMenu.isEmpty())
+ contextMenu.appendSeparator();
+ contextMenu.appendItem("inspector-stylesheet", this._createNewRuleInViaInspectorStyleSheet.bind(this));
+ contextMenu.show();
+
+ /**
+ * @param {!{text: string, handler: function()}} descriptor1
+ * @param {!{text: string, handler: function()}} descriptor2
+ * @return {number}
+ */
+ function compareDescriptors(descriptor1, descriptor2)
+ {
+ return String.naturalOrderComparator(descriptor1.text, descriptor2.text);
+ }
+
+ /**
+ * @param {!WebInspector.CSSStyleSheetHeader} header
+ */
+ function styleSheetResourceHeader(header)
+ {
+ return !header.isViaInspector() && !header.isInline && header.resourceURL();
+ }
+ },
+
+ /**
+ * @param {!WebInspector.DOMNode} node
+ */
+ updateEditingSelectorForNode: function(node)
+ {
+ var selectorText = WebInspector.DOMPresentationUtils.simpleSelector(node);
+ if (!selectorText)
+ return;
+ this._editingSelectorSection.setSelectorText(selectorText);
+ },
+
+ /**
+ * @return {boolean}
+ */
+ isEditingSelector: function()
+ {
+ return !!this._editingSelectorSection;
+ },
+
+ /**
+ * @param {!WebInspector.StylePropertiesSection} section
+ */
+ _startEditingSelector: function(section)
+ {
+ this._editingSelectorSection = section;
+ this.dispatchEventToListeners(WebInspector.StylesSidebarPane.Events.SelectorEditingStarted);
+ },
+
+ _finishEditingSelector: function()
+ {
+ delete this._editingSelectorSection;
+ this.dispatchEventToListeners(WebInspector.StylesSidebarPane.Events.SelectorEditingEnded);
+ },
+
/**
* @param {!WebInspector.CSSRule} editedRule
* @param {!WebInspector.TextRange} oldRange
*/
_styleSheetRuleEdited: function(editedRule, oldRange, newRange)
{
- var styleRuleSections = this.sections[0];
- for (var i = 1; i < styleRuleSections.length; ++i)
- styleRuleSections[i]._styleSheetRuleEdited(editedRule, oldRange, newRange);
+ for (var pseudoId in this.sections) {
+ var styleRuleSections = this.sections[pseudoId];
+ for (var i = 0; i < styleRuleSections.length; ++i) {
+ var section = styleRuleSections[i];
+ if (section.computedStyle)
+ continue;
+ section._styleSheetRuleEdited(editedRule, oldRange, newRange);
+ }
+ }
},
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
_contextMenuEventFired: function(event)
{
this._rebuildUpdate();
return;
}
+ if (matchedResult && this._node === node)
+ this._nodeStylesUpdatedForTest(node, true);
}
/**
if (this._computedStylePane.isShowing())
this._target.cssModel.getComputedStyleAsync(node.id, computedCallback);
this._target.cssModel.getInlineStylesAsync(node.id, inlineCallback);
- this._target.cssModel.getMatchedStylesAsync(node.id, true, true, stylesCallback.bind(this));
+ this._target.cssModel.getMatchedStylesAsync(node.id, false, false, stylesCallback.bind(this));
},
/**
// Add rules in reverse order to match the cascade order.
for (var j = pseudoElementCSSRules.rules.length - 1; j >= 0; --j) {
var rule = pseudoElementCSSRules.rules[j];
- styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.resourceURL(), rule: rule, editable: !!(rule.style && rule.style.styleSheetId) });
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, rule: rule, editable: !!(rule.style && rule.style.styleSheetId) });
}
usedProperties = {};
this._markUsedProperties(styleRules, usedProperties);
if (this._filterRegex)
this._updateFilter(false);
- this._nodeStylesUpdatedForTest(node, true);
},
_nodeStylesUpdatedForTest: function(node, rebuild)
addedAttributesStyle = true;
addAttributesStyle();
}
- styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.resourceURL(), rule: rule, editable: !!(rule.style && rule.style.styleSheetId) });
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, rule: rule, editable: !!(rule.style && rule.style.styleSheetId) });
}
if (!addedAttributesStyle)
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
}
- styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.resourceURL(), rule: rule, isInherited: true, parentNode: parentNode, editable: !!(rule.style && rule.style.styleSheetId) });
+ styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, rule: rule, isInherited: true, parentNode: parentNode, editable: !!(rule.style && rule.style.styleSheetId) });
}
parentNode = parentNode.parentNode;
}
separatorElement.className = "sidebar-separator";
if (styleRule.node) {
var link = WebInspector.DOMPresentationUtils.linkifyNodeReference(styleRule.node);
- separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " "));
+ separatorElement.createTextChild(WebInspector.UIString("Inherited from") + " ");
separatorElement.appendChild(link);
if (!sections.inheritedPropertiesSeparatorElement)
sections.inheritedPropertiesSeparatorElement = separatorElement;
}
},
- _createNewRule: function(event)
+ /**
+ * @param {?Event} event
+ */
+ _createNewRuleInViaInspectorStyleSheet: function(event)
{
- event.consume();
- this.expand();
- this.addBlankSection().startEditingSelector();
+ var cssModel = this._target.cssModel;
+ cssModel.requestViaInspectorStylesheet(this._node, this._createNewRuleInStyleSheet.bind(this));
},
/**
- * @return {!WebInspector.BlankStylePropertiesSection}
+ * @param {?WebInspector.CSSStyleSheetHeader} styleSheetHeader
*/
- addBlankSection: function()
+ _createNewRuleInStyleSheet: function(styleSheetHeader)
{
- var blankSection = new WebInspector.BlankStylePropertiesSection(this, this._node ? WebInspector.DOMPresentationUtils.simpleSelector(this._node) : "");
+ if (!styleSheetHeader)
+ return;
+ styleSheetHeader.requestContent(onStyleSheetContent.bind(this, styleSheetHeader.id));
- var elementStyleSection = this.sections[0][1];
- this._sectionsContainer.insertBefore(blankSection.element, elementStyleSection.element.nextSibling);
+ /**
+ * @param {string} styleSheetId
+ * @param {string} text
+ * @this {WebInspector.StylesSidebarPane}
+ */
+ function onStyleSheetContent(styleSheetId, text)
+ {
+ var lines = text.split("\n");
+ var range = WebInspector.TextRange.createFromLocation(lines.length - 1, lines[lines.length - 1].length);
+ this._addBlankSection(this.sections[0][1], styleSheetId, range);
+ }
+ },
- this.sections[0].splice(2, 0, blankSection);
+ /**
+ * @param {!WebInspector.StylePropertiesSection} insertAfterSection
+ * @param {string} styleSheetId
+ * @param {!WebInspector.TextRange} ruleLocation
+ */
+ _addBlankSection: function(insertAfterSection, styleSheetId, ruleLocation)
+ {
+ this.expand();
+ var blankSection = new WebInspector.BlankStylePropertiesSection(this, this._node ? WebInspector.DOMPresentationUtils.simpleSelector(this._node) : "", styleSheetId, ruleLocation, insertAfterSection.rule);
+
+ this._sectionsContainer.insertBefore(blankSection.element, insertAfterSection.element.nextSibling);
- return blankSection;
+ var index = this.sections[0].indexOf(insertAfterSection);
+ this.sections[0].splice(index + 1, 0, blankSection);
+ blankSection.startEditingSelector();
},
removeSection: function(section)
this._elementStatePane.inputs = inputs;
/**
- * @param {?Event} event
+ * @param {!Event} event
* @this {WebInspector.StylesSidebarPane}
*/
function clickListener(event)
input.addEventListener("click", clickListener.bind(this), false);
inputs.push(input);
label.appendChild(input);
- label.appendChild(document.createTextNode(":" + state));
+ label.createTextChild(":" + state);
td.appendChild(label);
return td;
}
input.addEventListener("input", boundSearchHandler, false);
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
function keydownHandler(event)
{
closeBrace.textContent = "}";
this.element.appendChild(closeBrace);
+ if (this.editable && this.rule) {
+ var newRuleButton = closeBrace.createChild("div", "sidebar-pane-button-new-rule");
+ newRuleButton.title = WebInspector.UIString("Insert Style Rule");
+ newRuleButton.addEventListener("click", this._onNewRuleClick.bind(this), false);
+ }
+
this._selectorElement.addEventListener("click", this._handleSelectorClick.bind(this), false);
this.element.addEventListener("mousedown", this._handleEmptySpaceMouseDown.bind(this), false);
this.element.addEventListener("click", this._handleEmptySpaceClick.bind(this), false);
WebInspector.StylePropertiesSection.prototype = {
/**
+ * @param {?Event} event
+ */
+ _onNewRuleClick: function(event)
+ {
+ event.consume();
+ var range = WebInspector.TextRange.createFromLocation(this.rule.style.range.endLine, this.rule.style.range.endColumn + 1);
+ this._parentPane._addBlankSection(this, this.rule.styleSheetId, range);
+ },
+
+ /**
* @param {!WebInspector.CSSRule} editedRule
* @param {!WebInspector.TextRange} oldRange
* @param {!WebInspector.TextRange} newRange
if (!this.rule || !this.rule.styleSheetId)
return;
if (this.rule !== editedRule)
- this.rule.sourceStyleSheetEdited(this.rule.styleSheetId, oldRange, newRange);
+ this.rule.sourceStyleSheetEdited(editedRule.styleSheetId, oldRange, newRange);
this._updateMediaList();
this._updateRuleOrigin();
},
/**
- * @param {!Object} styleRule
+ * @param {?Array.<!WebInspector.CSSMedia>} mediaRules
*/
- _createMediaList: function(styleRule)
+ _createMediaList: function(mediaRules)
{
- if (!styleRule.media)
+ if (!mediaRules)
return;
- for (var i = styleRule.media.length - 1; i >= 0; --i) {
- var media = styleRule.media[i];
+ for (var i = mediaRules.length - 1; i >= 0; --i) {
+ var media = mediaRules[i];
var mediaDataElement = this._mediaListElement.createChild("div", "media");
var mediaText;
switch (media.source) {
if (media.sourceURL) {
var refElement = mediaDataElement.createChild("div", "subtitle");
- var rawLocation;
- var mediaHeader;
- if (media.range) {
- mediaHeader = media.header();
- if (mediaHeader) {
- var lineNumber = media.lineNumberInSource();
- var columnNumber = media.columnNumberInSource();
- console.assert(typeof lineNumber !== "undefined" && typeof columnNumber !== "undefined");
- rawLocation = new WebInspector.CSSLocation(this._parentPane._target, media.sourceURL, lineNumber, columnNumber);
- }
- }
-
- var anchor;
- if (rawLocation)
- anchor = this._parentPane._linkifier.linkifyCSSLocation(mediaHeader.id, rawLocation);
- else {
- // The "linkedStylesheet" case.
- anchor = WebInspector.linkifyResourceAsNode(media.sourceURL, undefined, "subtitle", media.sourceURL);
- }
+ var anchor = this._parentPane._linkifier.linkifyMedia(media);
anchor.style.float = "right";
refElement.appendChild(anchor);
}
_updateMediaList: function()
{
this._mediaListElement.removeChildren();
- this._createMediaList(this.styleRule);
+ this._createMediaList(this.styleRule.media);
},
collapse: function()
if (this._afterUpdate) {
this._afterUpdate(this);
delete this._afterUpdate;
+ this._afterUpdateFinishedForTest();
}
},
+ _afterUpdateFinishedForTest: function()
+ {
+ },
+
onpopulate: function()
{
var style = this.styleRule.style;
var currentMatch = 0;
for (var i = 0; i < selectors.length ; ++i) {
if (i)
- fragment.appendChild(document.createTextNode(", "));
+ fragment.createTextChild(", ");
var isSelectorMatching = matchingSelectors[currentMatch] === i;
if (isSelectorMatching)
++currentMatch;
- var rawLocation = new WebInspector.CSSLocation(this._parentPane._target, rule.sourceURL, rule.lineNumberInSource(i), rule.columnNumberInSource(i));
var matchingSelectorClass = isSelectorMatching ? " selector-matches" : "";
var selectorElement = document.createElement("span");
selectorElement.className = "simple-selector" + matchingSelectorClass;
{
if (this._checkWillCancelEditing() || !this.editable)
return;
- if (event.target === this._selectorContainer)
+ if (event.target === this._selectorContainer) {
this.addNewBlankProperty(0).startEditing();
+ event.consume(true);
+ }
},
/**
return item;
},
- _createRuleOriginNode: function()
+ /**
+ * @param {?WebInspector.CSSRule} rule
+ * @param {!WebInspector.TextRange=} ruleLocation
+ * @return {!Node}
+ */
+ _createRuleOriginNode: function(rule, ruleLocation)
+ {
+ if (!rule)
+ return document.createTextNode("");
+
+ if (!ruleLocation) {
+ var firstMatchingIndex = rule.matchingSelectors && rule.matchingSelectors.length ? rule.matchingSelectors[0] : 0;
+ ruleLocation = rule.selectors[firstMatchingIndex].range;
+ }
+
+ if (ruleLocation && rule.styleSheetId)
+ return this._linkifyRuleLocation(rule.styleSheetId, ruleLocation);
+
+ if (rule.isUserAgent)
+ return document.createTextNode(WebInspector.UIString("user agent stylesheet"));
+ if (rule.isUser)
+ return document.createTextNode(WebInspector.UIString("user stylesheet"));
+ if (rule.isViaInspector)
+ return document.createTextNode(WebInspector.UIString("via inspector"));
+ return document.createTextNode("");
+ },
+
+ /**
+ * @param {string} styleSheetId
+ * @param {!WebInspector.TextRange} ruleLocation
+ * @return {!Node}
+ */
+ _linkifyRuleLocation: function(styleSheetId, ruleLocation)
{
/**
* @param {string} url
return link;
}
- if (this.styleRule.sourceURL) {
- var firstMatchingIndex = this.styleRule.rule.matchingSelectors && this.rule.matchingSelectors.length ? this.rule.matchingSelectors[0] : 0;
- var matchingSelectorLocation = new WebInspector.CSSLocation(this._parentPane._target, this.styleRule.sourceURL, this.rule.lineNumberInSource(firstMatchingIndex), this.rule.columnNumberInSource(firstMatchingIndex));
- return this._parentPane._linkifier.linkifyCSSLocation(this.rule.styleSheetId, matchingSelectorLocation) || linkifyUncopyable(this.styleRule.sourceURL, this.rule.lineNumberInSource());
- }
-
- if (!this.rule)
- return document.createTextNode("");
-
- if (this.rule.isUserAgent)
- return document.createTextNode(WebInspector.UIString("user agent stylesheet"));
- if (this.rule.isUser)
- return document.createTextNode(WebInspector.UIString("user stylesheet"));
- if (this.rule.isViaInspector)
- return document.createTextNode(WebInspector.UIString("via inspector"));
- return document.createTextNode("");
+ var styleSheetHeader = this._parentPane._target.cssModel.styleSheetHeaderForId(styleSheetId);
+ var sourceURL = styleSheetHeader.resourceURL();
+ var lineNumber = styleSheetHeader.lineNumberInSource(ruleLocation.startLine);
+ var columnNumber = styleSheetHeader.columnNumberInSource(ruleLocation.startLine, ruleLocation.startColumn);
+ var matchingSelectorLocation = new WebInspector.CSSLocation(this._parentPane._target, styleSheetId, sourceURL, lineNumber, columnNumber);
+ return this._parentPane._linkifier.linkifyCSSLocation(matchingSelectorLocation) || linkifyUncopyable(sourceURL, 0);
},
_handleEmptySpaceMouseDown: function()
}
this.expand();
this.addNewBlankProperty().startEditing();
+ event.consume(true)
},
_handleSelectorClick: function(event)
{
if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && this.navigable && event.target.classList.contains("simple-selector")) {
var index = event.target._selectorIndex;
- var styleSheetHeader = this._parentPane._target.cssModel.styleSheetHeaderForId(this.rule.styleSheetId);
- var uiLocation = styleSheetHeader.rawLocationToUILocation(this.rule.lineNumberInSource(index), this.rule.columnNumberInSource(index));
+ var target = this._parentPane._target;
+ var rawLocation = new WebInspector.CSSLocation(target, this.rule.styleSheetId, this.rule.sourceURL, this.rule.lineNumberInSource(index), this.rule.columnNumberInSource(index));
+ var uiLocation = WebInspector.cssWorkspaceBinding.rawLocationToUILocation(rawLocation);
WebInspector.Revealer.reveal(uiLocation);
+ event.consume(true);
return;
}
this._startEditingOnMouseEvent();
element.scrollIntoViewIfNeeded(false);
element.textContent = element.textContent; // Reset selector marks in group.
- var config = new WebInspector.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this));
+ var config = new WebInspector.InplaceEditor.Config(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this), undefined, this._editingSelectorBlurHandler.bind(this));
WebInspector.InplaceEditor.startEditing(this._selectorElement, config);
window.getSelection().setBaseAndExtent(element, 0, element, 1);
this._parentPane._isEditingStyle = true;
+ this._parentPane._startEditingSelector(this);
+ },
+
+ /**
+ * @param {string} text
+ */
+ setSelectorText: function(text)
+ {
+ this._selectorElement.textContent = text;
+ window.getSelection().setBaseAndExtent(this._selectorElement, 0, this._selectorElement, 1);
+ },
+
+ /**
+ * @param {!Element} editor
+ * @param {!Event} blurEvent
+ * @return {boolean}
+ */
+ _editingSelectorBlurHandler: function(editor, blurEvent)
+ {
+ if (!blurEvent.relatedTarget)
+ return true;
+ var elementTreeOutline = blurEvent.relatedTarget.enclosingNodeOrSelfWithClass("elements-tree-outline");
+ if (!elementTreeOutline)
+ return true;
+ editor.focus();
+ return false;
},
_moveEditorFromSelector: function(moveDirection)
return;
}
- var selectedNode = this._parentPane._node;
-
/**
* @param {!WebInspector.CSSRule} newRule
* @this {WebInspector.StylePropertiesSection}
var oldSelectorRange = this.rule.selectorRange;
this.rule = newRule;
- this.styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, media: newRule.media, sourceURL: newRule.resourceURL(), rule: newRule };
+ this.styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, media: newRule.media, rule: newRule };
- this._parentPane.update(selectedNode);
+ this._parentPane._refreshUpdate(this, false);
this._parentPane._styleSheetRuleEdited(this.rule, oldSelectorRange, this.rule.selectorRange);
finishOperationAndMoveEditor.call(this, moveDirection);
// This gets deleted in finishOperationAndMoveEditor(), which is called both on success and failure.
this._parentPane._userOperation = true;
+ var selectedNode = this._parentPane._node;
this._parentPane._target.cssModel.setRuleSelector(this.rule, selectedNode ? selectedNode.id : 0, newContent, successCallback.bind(this), finishOperationAndMoveEditor.bind(this, moveDirection));
},
_updateRuleOrigin: function()
{
this._selectorRefElement.removeChildren();
- this._selectorRefElement.appendChild(this._createRuleOriginNode());
+ this._selectorRefElement.appendChild(this._createRuleOriginNode(this.rule));
},
_editingSelectorEnded: function()
{
delete this._parentPane._isEditingStyle;
+ this._parentPane._finishEditingSelector();
},
editingSelectorCancelled: function()
WebInspector.ComputedStylePropertiesSection = function(stylesPane, styleRule, usedProperties)
{
WebInspector.PropertiesSection.call(this, "");
-
- var subtitle = this.headerElement.createChild("div", "sidebar-pane-subtitle vbox");
- var showInheritedCheckbox = new WebInspector.Checkbox(WebInspector.UIString("Show inherited properties"), "hbox");
- subtitle.appendChild(showInheritedCheckbox.element);
-
this._hasFreshContent = false;
-
- /**
- * @this {WebInspector.ComputedStylePropertiesSection}
- */
- function showInheritedToggleFunction()
- {
- var showInherited = showInheritedCheckbox.checked;
- WebInspector.settings.showInheritedComputedStyleProperties.set(showInherited);
- if (showInherited)
- this.element.classList.add("styles-show-inherited");
- else
- this.element.classList.remove("styles-show-inherited");
- }
-
- showInheritedCheckbox.addEventListener(showInheritedToggleFunction.bind(this));
-
this.element.className = "styles-section monospace read-only computed-style";
- if (WebInspector.settings.showInheritedComputedStyleProperties.get()) {
- this.element.classList.add("styles-show-inherited");
- showInheritedCheckbox.checked = true;
- }
+
+ this.headerElement.appendChild(WebInspector.ComputedStylePropertiesSection._showInheritedCheckbox());
+ this.onShowInheritedChanged();
this._stylesPane = stylesPane;
this.styleRule = styleRule;
this._expandedPropertyNames = {};
}
+/**
+ * @return {!Element}
+ */
+WebInspector.ComputedStylePropertiesSection._showInheritedCheckbox = function()
+{
+ if (!WebInspector.ComputedStylePropertiesSection._showInheritedCheckboxElement) {
+ WebInspector.ComputedStylePropertiesSection._showInheritedCheckboxElement = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Show inherited properties"), WebInspector.settings.showInheritedComputedStyleProperties, true);
+ WebInspector.ComputedStylePropertiesSection._showInheritedCheckboxElement.classList.add("checkbox-with-label");
+ }
+ return WebInspector.ComputedStylePropertiesSection._showInheritedCheckboxElement;
+}
+
WebInspector.ComputedStylePropertiesSection.prototype = {
+ onShowInheritedChanged: function()
+ {
+ this.element.classList.toggle("styles-show-inherited", WebInspector.settings.showInheritedComputedStyleProperties.get());
+ },
+
collapse: function(dontRememberState)
{
// Overriding with empty body.
var selector = fragment.createChild("span");
selector.style.color = "gray";
selector.textContent = section.styleRule.selectorText;
- fragment.appendChild(document.createTextNode(" - " + property.value + " "));
+ fragment.createTextChild(" - " + property.value + " ");
var subtitle = fragment.createChild("span");
subtitle.style.float = "right";
- subtitle.appendChild(section._createRuleOriginNode());
+ subtitle.appendChild(section._createRuleOriginNode(section.rule));
var childElement = new TreeElement(fragment, null, false);
treeElement.appendChild(childElement);
if (property.inactive || section.isPropertyOverloaded(property.name))
* @extends {WebInspector.StylePropertiesSection}
* @param {!WebInspector.StylesSidebarPane} stylesPane
* @param {string} defaultSelectorText
+ * @param {string} styleSheetId
+ * @param {!WebInspector.TextRange} ruleLocation
+ * @param {!WebInspector.CSSRule=} insertAfterRule
*/
-WebInspector.BlankStylePropertiesSection = function(stylesPane, defaultSelectorText)
+WebInspector.BlankStylePropertiesSection = function(stylesPane, defaultSelectorText, styleSheetId, ruleLocation, insertAfterRule)
{
- WebInspector.StylePropertiesSection.call(this, stylesPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false);
+ var styleSheetHeader = WebInspector.cssModel.styleSheetHeaderForId(styleSheetId);
+ WebInspector.StylePropertiesSection.call(this, stylesPane, { selectorText: defaultSelectorText }, true, false);
+ this._ruleLocation = ruleLocation;
+ this._styleSheetId = styleSheetId;
+ this._selectorRefElement.removeChildren();
+ this._selectorRefElement.appendChild(this._linkifyRuleLocation(styleSheetId, this._actualRuleLocation()));
+ if (insertAfterRule)
+ this._createMediaList(insertAfterRule.media);
this.element.classList.add("blank-section");
}
WebInspector.BlankStylePropertiesSection.prototype = {
+ /**
+ * @return {!WebInspector.TextRange}
+ */
+ _actualRuleLocation: function()
+ {
+ var prefix = this._rulePrefix();
+ var lines = prefix.split("\n");
+ var editRange = new WebInspector.TextRange(0, 0, lines.length - 1, lines.peekLast().length);
+ return this._ruleLocation.rebaseAfterTextEdit(WebInspector.TextRange.createFromLocation(0, 0), editRange);
+ },
+
+ /**
+ * @return {string}
+ */
+ _rulePrefix: function()
+ {
+ return this._ruleLocation.startLine === 0 && this._ruleLocation.startColumn === 0 ? "" : "\n\n";
+ },
+
get isBlank()
{
return !this._normal;
function successCallback(newRule)
{
var doesSelectorAffectSelectedNode = newRule.matchingSelectors.length > 0;
- var styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.resourceURL(), rule: newRule };
- this.makeNormal(styleRule);
+ var styleRule = { media: newRule.media, section: this, style: newRule.style, selectorText: newRule.selectorText, rule: newRule };
+ this._makeNormal(styleRule);
if (!doesSelectorAffectSelectedNode) {
this.noAffect = true;
this.element.classList.add("no-affect");
}
+ var ruleTextLines = ruleText.split("\n");
+ var startLine = this._ruleLocation.startLine;
+ var startColumn = this._ruleLocation.startColumn;
+ var newRange = new WebInspector.TextRange(startLine, startColumn, startLine + ruleTextLines.length - 1, startColumn + ruleTextLines[ruleTextLines.length - 1].length);
+ this._parentPane._styleSheetRuleEdited(newRule, this._ruleLocation, newRange);
+
this._updateRuleOrigin();
this.expand();
if (this.element.parentElement) // Might have been detached already.
this._parentPane._userOperation = true;
var cssModel = this._parentPane._target.cssModel;
- cssModel.requestViaInspectorStylesheet(this._parentPane._node, viaInspectorCallback.bind(this));
-
- /**
- * @this {WebInspector.BlankStylePropertiesSection}
- * @param {?WebInspector.CSSStyleSheetHeader} styleSheetHeader
- */
- function viaInspectorCallback(styleSheetHeader)
- {
- if (!styleSheetHeader) {
- this.editingSelectorCancelled();
- return;
- }
- cssModel.addRule(styleSheetHeader.id, this._parentPane._node, newContent, successCallback.bind(this), this.editingSelectorCancelled.bind(this));
- }
+ var ruleText = this._rulePrefix() + newContent + " {}";
+ cssModel.addRule(this._styleSheetId, this._parentPane._node, ruleText, this._ruleLocation, successCallback.bind(this), this.editingSelectorCancelled.bind(this));
},
editingSelectorCancelled: function()
this._parentPane.removeSection(this);
},
- makeNormal: function(styleRule)
+ _makeNormal: function(styleRule)
{
this.element.classList.remove("blank-section");
this.styleRule = styleRule;
/**
* @param {!RegExp} regex
+ * @param {function(string):!Node} processor
+ * @param {?function(string):!Node} nextProcessor
+ * @param {string} valueText
* @return {!DocumentFragment}
*/
function processValue(regex, processor, nextProcessor, valueText)
if (nextProcessor)
container.appendChild(nextProcessor(items[i]));
else
- container.appendChild(document.createTextNode(items[i]));
+ container.createTextChild(items[i]);
} else {
var processedNode = processor(items[i]);
if (processedNode)
if (match)
hrefUrl = match[1];
var container = document.createDocumentFragment();
- container.appendChild(document.createTextNode("url("));
- if (this._styleRule.sourceURL)
- hrefUrl = WebInspector.ParsedURL.completeURL(this._styleRule.sourceURL, hrefUrl);
+ container.createTextChild("url(");
+ if (this._styleRule.rule && this._styleRule.rule.resourceURL())
+ hrefUrl = WebInspector.ParsedURL.completeURL(this._styleRule.rule.resourceURL(), hrefUrl);
else if (this.node())
hrefUrl = this.node().resolveURL(hrefUrl);
var hasResource = hrefUrl && !!WebInspector.resourceForURL(hrefUrl);
// FIXME: WebInspector.linkifyURLAsNode() should really use baseURI.
container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl || url, url, undefined, !hasResource));
- container.appendChild(document.createTextNode(")"));
+ container.createTextChild(")");
return container;
}
if (this.disabled)
this.listItemElement.createChild("span", "styles-clipboard-only").createTextChild("/* ");
this.listItemElement.appendChild(nameElement);
- this.listItemElement.appendChild(document.createTextNode(": "));
+ this.listItemElement.createTextChild(": ");
this.listItemElement.appendChild(this._expandElement);
this.listItemElement.appendChild(valueElement);
- this.listItemElement.appendChild(document.createTextNode(";"));
+ this.listItemElement.createTextChild(";");
if (this.disabled)
this.listItemElement.createChild("span", "styles-clipboard-only").createTextChild(" */");
* @param {!Element} nameElement
* @param {!Element} valueElement
* @param {string} text
+ * @return {!Node}
*/
_processColor: function(nameElement, valueElement, text)
{
}
/**
- * @param {?Event} e
+ * @param {!Event} e
* @this {WebInspector.StylePropertyTreeElementBase}
*/
function swatchClick(e)
spectrum.addEventListener(WebInspector.Spectrum.Events.ColorChanged, boundSpectrumChanged);
spectrumHelper.addEventListener(WebInspector.SpectrumPopupHelper.Events.Hidden, boundSpectrumHidden);
- scrollerElement = colorSwatch.element.enclosingNodeOrSelfWithClass("scroll-target");
+ scrollerElement = colorSwatch.element.enclosingNodeOrSelfWithClass("style-panes-wrapper");
if (scrollerElement)
scrollerElement.addEventListener("scroll", repositionSpectrum, false);
else
}
var colorValueElement = document.createElement("span");
- colorValueElement.textContent = color.toString(format);
+ if (format === WebInspector.Color.Format.Original)
+ colorValueElement.textContent = text;
+ else
+ colorValueElement.textContent = color.toString(format);
/**
* @param {string} curFormat
WebInspector.StylePropertyTreeElementBase.call(this, styleRule, style, property, inherited, overloaded, isShorthand);
this._parentPane = stylesPane;
this.isShorthand = isShorthand;
+ this._applyStyleThrottler = new WebInspector.Throttler(0);
}
+/** @typedef {{expanded: boolean, hasChildren: boolean, isEditingName: boolean, previousContent: string}} */
+WebInspector.StylePropertyTreeElement.Context;
+
WebInspector.StylePropertyTreeElement.prototype = {
/**
* @return {?WebInspector.DOMNode}
},
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
toggleEnabled: function(event)
{
{
console.assert(this.section().navigable);
var propertyNameClicked = element === this.nameElement;
- WebInspector.Revealer.reveal(this.property.uiLocation(propertyNameClicked));
+ WebInspector.Revealer.reveal(WebInspector.cssWorkspaceBinding.propertyUILocation(this.property, propertyNameClicked));
},
/**
},
/**
- * @param {!Element=} selectElement
+ * @param {?Element=} selectElement
*/
startEditing: function(selectElement)
{
return splitFieldValue.join("");
}
+ /** @type {!WebInspector.StylePropertyTreeElement.Context} */
var context = {
expanded: this.expanded,
hasChildren: this.hasChildren,
selectElement.textContent = selectElement.textContent; // remove color swatch and the like
/**
+ * @param {!WebInspector.StylePropertyTreeElement.Context} context
+ * @param {!Event} event
* @this {WebInspector.StylePropertyTreeElement}
*/
function pasteHandler(context, event)
}
/**
+ * @param {!WebInspector.StylePropertyTreeElement.Context} context
+ * @param {!Event} event
* @this {WebInspector.StylePropertyTreeElement}
*/
function blurListener(context, event)
if (selectElement.parentElement)
selectElement.parentElement.scrollIntoViewIfNeeded(false);
- var applyItemCallback = !isEditingName ? this._applyFreeFlowStyleTextEdit.bind(this, true) : undefined;
+ var applyItemCallback = !isEditingName ? this._applyFreeFlowStyleTextEdit.bind(this) : undefined;
this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(isEditingName ? WebInspector.CSSMetadata.cssPropertiesMetainfo : WebInspector.CSSMetadata.keywordsForProperty(this.nameElement.textContent), this, isEditingName);
if (applyItemCallback) {
this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemApplied, applyItemCallback, this);
}
var proxyElement = this._prompt.attachAndStartEditing(selectElement, blurListener.bind(this, context));
- proxyElement.addEventListener("keydown", this.editingNameValueKeyDown.bind(this, context), false);
- proxyElement.addEventListener("keypress", this.editingNameValueKeyPress.bind(this, context), false);
+ proxyElement.addEventListener("keydown", this._editingNameValueKeyDown.bind(this, context), false);
+ proxyElement.addEventListener("keypress", this._editingNameValueKeyPress.bind(this, context), false);
+ proxyElement.addEventListener("input", this._editingNameValueInput.bind(this, context), false);
if (isEditingName)
proxyElement.addEventListener("paste", pasteHandler.bind(this, context), false);
window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
},
- editingNameValueKeyDown: function(context, event)
+ /**
+ * @param {!WebInspector.StylePropertyTreeElement.Context} context
+ * @param {!Event} event
+ */
+ _editingNameValueKeyDown: function(context, event)
{
if (event.handled)
return;
- var isEditingName = context.isEditingName;
var result;
if (isEnterKey(event)) {
result = "forward";
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B")
result = "cancel";
- else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) {
+ else if (!context.isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) {
// For a new property, when Backspace is pressed at the beginning of new property value, move back to the property name.
var selection = window.getSelection();
if (selection.isCollapsed && !selection.focusOffset) {
event.consume();
return;
}
-
- if (!isEditingName)
- this._applyFreeFlowStyleTextEdit(false);
},
- editingNameValueKeyPress: function(context, event)
+ /**
+ * @param {!WebInspector.StylePropertyTreeElement.Context} context
+ * @param {!Event} event
+ */
+ _editingNameValueKeyPress: function(context, event)
{
function shouldCommitValueSemicolon(text, cursorPosition)
{
}
},
- _applyFreeFlowStyleTextEdit: function(now)
+ /**
+ * @param {!WebInspector.StylePropertyTreeElement.Context} context
+ * @param {!Event} event
+ */
+ _editingNameValueInput: function(context, event)
{
- if (this._applyFreeFlowStyleTextEditTimer)
- clearTimeout(this._applyFreeFlowStyleTextEditTimer);
+ if (!context.isEditingName)
+ this._applyFreeFlowStyleTextEdit();
+ },
- /**
- * @this {WebInspector.StylePropertyTreeElement}
- */
- function apply()
- {
- var valueText = this.valueElement.textContent;
- if (valueText.indexOf(";") === -1)
- this.applyStyleText(this.nameElement.textContent + ": " + valueText, false, false, false);
- }
- if (now)
- apply.call(this);
- else
- this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100);
+ _applyFreeFlowStyleTextEdit: function()
+ {
+ var valueText = this.valueElement.textContent;
+ if (valueText.indexOf(";") === -1)
+ this.applyStyleText(this.nameElement.textContent + ": " + valueText, false, false, false);
},
kickFreeFlowStyleEditForTest: function()
{
- this._applyFreeFlowStyleTextEdit(true);
+ this._applyFreeFlowStyleTextEdit();
},
editingEnded: function(context)
{
this._resetMouseDownElement();
- if (this._applyFreeFlowStyleTextEditTimer)
- clearTimeout(this._applyFreeFlowStyleTextEditTimer);
this.hasChildren = context.hasChildren;
if (context.expanded)
{
},
+ /**
+ * @param {string} styleText
+ * @param {boolean} updateInterface
+ * @param {boolean} majorChange
+ * @param {boolean} isRevert
+ */
applyStyleText: function(styleText, updateInterface, majorChange, isRevert)
{
+ this._applyStyleThrottler.schedule(this._innerApplyStyleText.bind(this, styleText, updateInterface, majorChange, isRevert));
+ },
+
+ /**
+ * @param {string} styleText
+ * @param {boolean} updateInterface
+ * @param {boolean} majorChange
+ * @param {boolean} isRevert
+ * @param {!WebInspector.Throttler.FinishCallback} finishedCallback
+ */
+ _innerApplyStyleText: function(styleText, updateInterface, majorChange, isRevert, finishedCallback)
+ {
+ /**
+ * @param {!WebInspector.StylesSidebarPane} parentPane
+ * @param {boolean} updateInterface
+ */
function userOperationFinishedCallback(parentPane, updateInterface)
{
if (updateInterface)
delete parentPane._userOperation;
+ finishedCallback();
}
// Leave a way to cancel editing after incremental changes.
this._revertStyleUponEditingCanceled(originalPropertyText);
}
userCallback();
+ this.styleTextAppliedForTest();
return;
}
this._applyNewStyle(newStyle);
if (styleText.length && !/;\s*$/.test(styleText))
styleText += ";";
var overwriteProperty = !!(!this._newProperty || this._newPropertyInStyle);
- this.property.setText(styleText, majorChange, overwriteProperty, callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText));
+ var boundCallback = callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText);
+ if (overwriteProperty && styleText === this.property.propertyText)
+ boundCallback.call(null, this.property.ownerStyle)
+ else
+ this.property.setText(styleText, majorChange, overwriteProperty, boundCallback);
},
/**
},
/**
- * @param {?Event} event
+ * @param {!Event} event
* @return {boolean}
*/
isEventWithinDisclosureTriangle: function(event)
WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = {
/**
- * @param {?Event} event
+ * @param {!Event} event
*/
onKeyDown: function(event)
{
},
/**
- * @param {?Event} event
+ * @param {!Event} event
* @return {boolean}
*/
_handleNameOrValueUpDown: function(event)
this._sidebarPane.applyStyleText(this._sidebarPane.nameElement.textContent + ": " + this._sidebarPane.valueElement.textContent, false, false, false);
}
+ /**
+ * @param {string} prefix
+ * @param {number} number
+ * @param {string} suffix
+ * @return {string}
+ * @this {WebInspector.StylesSidebarPane.CSSPropertyPrompt}
+ */
+ function customNumberHandler(prefix, number, suffix)
+ {
+ if (number !== 0 && !suffix.length && WebInspector.CSSMetadata.isLengthProperty(this._sidebarPane.property.name))
+ suffix = "px";
+ return prefix + number + suffix;
+ }
+
// Handle numeric value increment/decrement only at this point.
- if (!this._isEditingName && WebInspector.handleElementValueModifications(event, this._sidebarPane.valueElement, finishHandler.bind(this), this._isValueSuggestion.bind(this)))
+ if (!this._isEditingName && WebInspector.handleElementValueModifications(event, this._sidebarPane.valueElement, finishHandler.bind(this), this._isValueSuggestion.bind(this), customNumberHandler.bind(this)))
return true;
return false;
}
var results = this._cssCompletions.startsWith(prefix);
+ var userEnteredText = wordRange.toString().replace("-", "");
+ if (userEnteredText && (userEnteredText === userEnteredText.toUpperCase())) {
+ for (var i = 0; i < results.length; ++i)
+ results[i] = results[i].toUpperCase();
+ }
var selectedIndex = this._cssCompletions.mostUsedOf(results);
completionsReadyCallback(results, selectedIndex);
},