summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 10:00:22 +0000
committerpfeldman@chromium.org <pfeldman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-30 10:00:22 +0000
commite91a73a43d79d437c59a5a44396e919628f3f707 (patch)
tree8ce266f9e73111a80fde6d913ca0e0f36cfb67c4 /webkit
parent028b8e5430ac280daf75c962020464e36e1f5a3f (diff)
downloadchromium_src-e91a73a43d79d437c59a5a44396e919628f3f707.zip
chromium_src-e91a73a43d79d437c59a5a44396e919628f3f707.tar.gz
chromium_src-e91a73a43d79d437c59a5a44396e919628f3f707.tar.bz2
DevTools: Implement styles editing.
Review URL: http://codereview.chromium.org/100199 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14936 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/devtools/js/devtools.js23
-rw-r--r--webkit/glue/devtools/js/devtools_host_stub.js5
-rw-r--r--webkit/glue/devtools/js/dom_agent.js51
-rw-r--r--webkit/glue/devtools/js/inject.js204
4 files changed, 235 insertions, 48 deletions
diff --git a/webkit/glue/devtools/js/devtools.js b/webkit/glue/devtools/js/devtools.js
index 972ca02..2d387e4 100644
--- a/webkit/glue/devtools/js/devtools.js
+++ b/webkit/glue/devtools/js/devtools.js
@@ -564,12 +564,29 @@ WebInspector.ScopeChainSidebarPane.TreeElement.prototype.didResolveChildren_ =
*/
WebInspector.StylePropertyTreeElement.prototype.toggleEnabled =
function(event) {
- var disabled = !event.target.checked;
- var self = this;
- devtools.tools.getDomAgent().toggleNodeStyleAsync(this.style, !disabled,
+ var enabled = event.target.checked;
+ devtools.tools.getDomAgent().toggleNodeStyleAsync(
+ this.style,
+ enabled,
this.name,
function() {
WebInspector.panels.elements.sidebarPanes.styles.needsUpdate = true;
WebInspector.panels.elements.updateStyles(true);
});
};
+
+
+/**
+ * @override
+ */
+WebInspector.StylePropertyTreeElement.prototype.applyStyleText = function(
+ styleText, updateInterface) {
+ devtools.tools.getDomAgent().applyStyleTextAsync(this.style, this.name,
+ styleText,
+ function() {
+ if (updateInterface) {
+ WebInspector.panels.elements.sidebarPanes.styles.needsUpdate = true;
+ WebInspector.panels.elements.updateStyles(true);
+ }
+ });
+};
diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js
index 60cf583..33b8535 100644
--- a/webkit/glue/devtools/js/devtools_host_stub.js
+++ b/webkit/glue/devtools/js/devtools_host_stub.js
@@ -185,8 +185,9 @@ RemoteToolsAgentStub.prototype.ExecuteUtilityFunction = function(callId,
}
]
};
- } else if (functionName == 'toggleNodeStyle') {
- alert('toggleNodeStyle ' + args);
+ } else if (functionName == 'toggleNodeStyle' ||
+ functionName == 'applyStyleText') {
+ alert(functionName + '(' + args + ')');
} else {
alert('Unexpected utility function:' + functionName);
}
diff --git a/webkit/glue/devtools/js/dom_agent.js b/webkit/glue/devtools/js/dom_agent.js
index d0c8f70..5f50fa1 100644
--- a/webkit/glue/devtools/js/dom_agent.js
+++ b/webkit/glue/devtools/js/dom_agent.js
@@ -829,9 +829,7 @@ devtools.DomAgent.prototype.getSearchResultNode = function(index) {
*/
devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
path, protoDepth, callback) {
- var mycallback =
- goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
- var callbackId = devtools.Callback.wrap(mycallback);
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
'getProperties', nodeId,
goog.json.serialize([path, protoDepth]));
@@ -845,9 +843,7 @@ devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId,
*/
devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
callback) {
- var mycallback =
- goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
- var callbackId = devtools.Callback.wrap(mycallback);
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
'getPrototypes', nodeId, '[]');
};
@@ -861,9 +857,7 @@ devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId,
*/
devtools.DomAgent.prototype.getNodeStylesAsync = function(node,
authorOnly, callback) {
- var mycallback =
- goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
- var callbackId = devtools.Callback.wrap(mycallback);
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
'getStyles',
node.id_,
@@ -880,9 +874,7 @@ devtools.DomAgent.prototype.getNodeStylesAsync = function(node,
*/
devtools.DomAgent.prototype.toggleNodeStyleAsync = function(
style, enabled, name, callback) {
- var mycallback =
- goog.bind(this.utilityFunctionCallbackWrapper_, this, callback);
- var callbackId = devtools.Callback.wrap(mycallback);
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
RemoteToolsAgent.ExecuteUtilityFunction(callbackId,
'toggleNodeStyle',
style.nodeId_,
@@ -891,15 +883,38 @@ devtools.DomAgent.prototype.toggleNodeStyleAsync = function(
/**
+ * Applies new text to a style.
+ * @param {devtools.CSSStyleDeclaration} style Style to edit.
+ * @param {string} name Property name to edit.
+ * @param {string} styleText Text to set the style from.
+ * @param {Function} callback.
+ */
+devtools.DomAgent.prototype.applyStyleTextAsync = function(
+ style, name, styleText, callback) {
+ var callbackId = this.utilityFunctionCallbackWrapper_(callback);
+ RemoteToolsAgent.ExecuteUtilityFunction(
+ callbackId,
+ 'applyStyleText',
+ style.nodeId_,
+ goog.json.serialize([style.id_, name, styleText]));
+};
+
+
+/**
* Dumps exception if something went wrong in ExecuteUtilityFunction.
+ * @param {Function} callback Callback to wrap.
+ * @return {number} Callback id.
*/
devtools.DomAgent.prototype.utilityFunctionCallbackWrapper_ =
- function(callback, result, exception) {
- if (exception && exception.length) {
- debugPrint('Exception in ExecuteUtilityFunction styles:' + exception);
- return;
- }
- callback(result);
+ function(callback) {
+ var mycallback = function(result, exception) {
+ if (exception && exception.length) {
+ debugPrint('Exception in ExecuteUtilityFunction styles:' + exception);
+ return;
+ }
+ callback(result);
+ };
+ return devtools.Callback.wrap(mycallback);
};
diff --git a/webkit/glue/devtools/js/inject.js b/webkit/glue/devtools/js/inject.js
index 1ef97b0..a6d7d0b 100644
--- a/webkit/glue/devtools/js/inject.js
+++ b/webkit/glue/devtools/js/inject.js
@@ -111,28 +111,28 @@ devtools.Injected.prototype.getStyles = function(node, authorOnly) {
if (!node.nodeType == Node.ELEMENT_NODE) {
return {};
}
- var matchedRules = window.getMatchedCSSRules(node, '', authorOnly);
+ var matchedRules = window.getMatchedCSSRules(node, '', false);
var matchedCSSRulesObj = [];
for (var i = 0; matchedRules && i < matchedRules.length; ++i) {
- var rule = matchedRules[i];
- var style = this.serializeStyle_(rule.style);
+ var rule = matchedRules[i];
+ var parentStyleSheet = rule.parentStyleSheet;
+ var isUserAgent = parentStyleSheet && !parentStyleSheet.ownerNode &&
+ !parentStyleSheet.href;
+ var isUser = parentStyleSheet && parentStyleSheet.ownerNode &&
+ parentStyleSheet.ownerNode.nodeName == '#document';
+
+ var style = this.serializeStyle_(rule.style, !isUserAgent && !isUser);
var ruleValue = {
'selector' : rule.selectorText,
'style' : style
};
- if (rule.parentStyleSheet) {
+ if (parentStyleSheet) {
ruleValue['parentStyleSheet'] = {
- 'href' : rule.parentStyleSheet.href,
- 'ownerNodeName' : rule.parentStyleSheet.ownerNode ?
- rule.parentStyleSheet.ownerNode.name : null
+ 'href' : parentStyleSheet.href,
+ 'ownerNodeName' : parentStyleSheet.ownerNode ?
+ parentStyleSheet.ownerNode.name : null
};
}
- var parentStyleSheetHref = (rule.parentStyleSheet ?
- rule.parentStyleSheet.href : undefined);
- var parentStyleSheetOwnerNodeName;
- if (rule.parentStyleSheet && rule.parentStyleSheet.ownerNode) {
- parentStyleSheetOwnerNodeName = rule.parentStyleSheet.ownerNode.name;
- }
matchedCSSRulesObj.push(ruleValue);
}
@@ -141,12 +141,11 @@ devtools.Injected.prototype.getStyles = function(node, authorOnly) {
for (var i = 0; attributes && i < attributes.length; ++i) {
if (attributes[i].style) {
attributeStyles[attributes[i].name] =
- this.serializeStyle_(attributes[i].style);
+ this.serializeStyle_(attributes[i].style, true);
}
}
-
var result = {
- 'inlineStyle' : this.serializeStyle_(node.style),
+ 'inlineStyle' : this.serializeStyle_(node.style, true),
'computedStyle' : this.serializeStyle_(
window.getComputedStyle(node, '')),
'matchedCSSRules' : matchedCSSRulesObj,
@@ -189,19 +188,21 @@ devtools.Injected.prototype.getStyleForId_ = function(node, id) {
/**
* Converts given style into serializable object.
* @param {CSSStyleDeclaration} style Style to serialize.
+ * @param {boolean} opt_bind Determins whether this style should be bound.
* @return {Array<Object>} Serializable object.
* @private
*/
-devtools.Injected.prototype.serializeStyle_ = function(style) {
+devtools.Injected.prototype.serializeStyle_ = function(style, opt_bind) {
if (!style) {
return [];
}
- if (!style.__id) {
- style.__id = this.lastStyleId_++;
+ var id = style.__id;
+ if (opt_bind && !id) {
+ id = style.__id = this.lastStyleId_++;
this.styles_.push(style);
}
var result = [
- style.__id,
+ id,
style.__disabledProperties,
style.__disabledPropertyValues,
style.__disabledPropertyPriorities
@@ -270,11 +271,75 @@ devtools.Injected.prototype.toggleNodeStyle = function(node, styleId, enabled,
/**
- * Returns longhand proeprties for a given shorthand one.
- * @param {CSSStyleDeclaration} style Style declaration to use for lookup.
- * @param {string} shorthandProperty Shorthand property to get longhands for.
- * @return {Array.<string>} Array with longhand properties.
- * @private
+ * Applies given text to a style.
+ * @param {Node} node Node to get prorotypes for.
+ * @param {number} styleId Id of style to toggle.
+ * @param {string} name Style element name.
+ * @param {string} styleText New style text.
+ * @return {boolean} True iff style has been edited successfully.
+ */
+devtools.Injected.prototype.applyStyleText = function(node, styleId,
+ name, styleText) {
+ var style = this.getStyleForId_(node, styleId);
+ if (!style) {
+ return false;
+ }
+
+ var styleTextLength = this.trimWhitespace_(styleText).length;
+
+ // Create a new element to parse the user input CSS.
+ var parseElement = document.createElement("span");
+ parseElement.setAttribute("style", styleText);
+
+ var tempStyle = parseElement.style;
+ if (tempStyle.length || !styleTextLength) {
+ // The input was parsable or the user deleted everything, so remove the
+ // original property from the real style declaration. If this represents
+ // a shorthand remove all the longhand properties.
+ if (style.getPropertyShorthand(name)) {
+ var longhandProperties = this.getLonghandProperties_(style, name);
+ for (var i = 0; i < longhandProperties.length; ++i) {
+ style.removeProperty(longhandProperties[i]);
+ }
+ } else {
+ style.removeProperty(name);
+ }
+ }
+ if (!tempStyle.length) {
+ // The user typed something, but it didn't parse. Just abort and restore
+ // the original title for this property.
+ return false;
+ }
+
+ // Iterate of the properties on the test element's style declaration and
+ // add them to the real style declaration. We take care to move shorthands.
+ var foundShorthands = {};
+ var uniqueProperties = this.getUniqueStyleProperties_(tempStyle);
+ for (var i = 0; i < uniqueProperties.length; ++i) {
+ var name = uniqueProperties[i];
+ var shorthand = tempStyle.getPropertyShorthand(name);
+
+ if (shorthand && shorthand in foundShorthands) {
+ continue;
+ }
+
+ if (shorthand) {
+ var value = this.getShorthandValue_(tempStyle, shorthand);
+ var priority = this.getShorthandPriority_(tempStyle, shorthand);
+ foundShorthands[shorthand] = true;
+ } else {
+ var value = tempStyle.getPropertyValue(name);
+ var priority = tempStyle.getPropertyPriority(name);
+ }
+ // Set the property on the real style declaration.
+ style.setProperty((shorthand || name), value, priority);
+ }
+ return true;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
*/
devtools.Injected.prototype.getLonghandProperties_ = function(style,
shorthandProperty) {
@@ -292,3 +357,92 @@ devtools.Injected.prototype.getLonghandProperties_ = function(style,
}
return properties;
};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandValue_ = function(style,
+ shorthandProperty) {
+ var value = style.getPropertyValue(shorthandProperty);
+ if (!value) {
+ // Some shorthands (like border) return a null value, so compute a
+ // shorthand value.
+ // FIXME: remove this when http://bugs.webkit.org/show_bug.cgi?id=15823
+ // is fixed.
+
+ var foundProperties = {};
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (individualProperty in foundProperties ||
+ style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+
+ var individualValue = style.getPropertyValue(individualProperty);
+ if (style.isPropertyImplicit(individualProperty) ||
+ individualValue === "initial") {
+ continue;
+ }
+
+ foundProperties[individualProperty] = true;
+
+ if (!value) {
+ value = "";
+ } else if (value.length) {
+ value += " ";
+ }
+ value += individualValue;
+ }
+ }
+ return value;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getShorthandPriority_ = function(style,
+ shorthandProperty) {
+ var priority = style.getPropertyPriority(shorthandProperty);
+ if (!priority) {
+ for (var i = 0; i < style.length; ++i) {
+ var individualProperty = style[i];
+ if (style.getPropertyShorthand(individualProperty) !==
+ shorthandProperty) {
+ continue;
+ }
+ priority = style.getPropertyPriority(individualProperty);
+ break;
+ }
+ }
+ return priority;
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.trimWhitespace_ = function(str) {
+ return str.replace(/^[\s\xA0]+|[\s\xA0]+$/g, '');
+};
+
+
+/**
+ * Taken from utilities.js as is for injected evaluation.
+ */
+devtools.Injected.prototype.getUniqueStyleProperties_ = function(style) {
+ var properties = [];
+ var foundProperties = {};
+
+ for (var i = 0; i < style.length; ++i) {
+ var property = style[i];
+ if (property in foundProperties) {
+ continue;
+ }
+ foundProperties[property] = true;
+ properties.push(property);
+ }
+ return properties;
+};