Commit e91a73a4 authored by pfeldman@chromium.org's avatar pfeldman@chromium.org

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
parent 028b8e54
......@@ -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);
}
});
};
......@@ -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);
}
......
......@@ -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_,
......@@ -890,16 +882,39 @@ 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);
};
......
......@@ -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;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment