OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Dom and DomNode are used to represent remote DOM in the | 6 * @fileoverview Dom and DomNode are used to represent remote DOM in the |
7 * web inspector. | 7 * web inspector. |
8 */ | 8 */ |
9 goog.provide('devtools.DomAgent'); | 9 goog.provide('devtools.DomAgent'); |
10 goog.provide('devtools.DomDocument'); | 10 goog.provide('devtools.DomDocument'); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 } | 49 } |
50 | 50 |
51 this.childNodesCount_ = payload[devtools.PayloadIndex.HAS_CHILDREN]; | 51 this.childNodesCount_ = payload[devtools.PayloadIndex.HAS_CHILDREN]; |
52 this.children = null; | 52 this.children = null; |
53 | 53 |
54 this.nextSibling = null; | 54 this.nextSibling = null; |
55 this.prevSibling = null; | 55 this.prevSibling = null; |
56 this.firstChild = null; | 56 this.firstChild = null; |
57 this.parentNode = null; | 57 this.parentNode = null; |
58 | 58 |
59 this.styles_ = null; | |
60 this.disabledStyleProperties_ = {}; | 59 this.disabledStyleProperties_ = {}; |
61 | 60 |
62 if (payload.length > devtools.PayloadIndex.CHILD_NODES) { | 61 if (payload.length > devtools.PayloadIndex.CHILD_NODES) { |
63 // Has children payloads | 62 // Has children payloads |
64 this.setChildrenPayload_( | 63 this.setChildrenPayload_( |
65 payload[devtools.PayloadIndex.CHILD_NODES]); | 64 payload[devtools.PayloadIndex.CHILD_NODES]); |
66 } | 65 } |
| 66 |
| 67 this.computedStyle_ = null; |
| 68 this.style = null; |
| 69 this.matchedCSSRules_ = []; |
67 }; | 70 }; |
68 | 71 |
69 | 72 |
70 /** | 73 /** |
71 * Overrides for getters and setters. | 74 * Overrides for getters and setters. |
72 */ | 75 */ |
73 devtools.DomNode.prototype = { | 76 devtools.DomNode.prototype = { |
74 get nodeValue() { | 77 get nodeValue() { |
75 return this.nodeValue_; | 78 return this.nodeValue_; |
76 }, | 79 }, |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 }; | 218 }; |
216 | 219 |
217 | 220 |
218 /** | 221 /** |
219 * Creates an attribute-like object and adds it to the object. | 222 * Creates an attribute-like object and adds it to the object. |
220 * @param {string} name Attribute name to set value for. | 223 * @param {string} name Attribute name to set value for. |
221 * @param {string} value Attribute value to set. | 224 * @param {string} value Attribute value to set. |
222 */ | 225 */ |
223 devtools.DomNode.prototype.addAttribute_ = function(name, value) { | 226 devtools.DomNode.prototype.addAttribute_ = function(name, value) { |
224 var attr = { | 227 var attr = { |
225 'name': name, | 228 'name': name, |
226 'value': value, | 229 'value': value, |
227 node_: this, | 230 node_: this |
228 /* Must be called after node.setStyles_. */ | |
229 get style() { | |
230 return this.node_.styles_.attributes[this.name]; | |
231 } | |
232 }; | 231 }; |
233 | 232 |
234 this.attributesMap_[name] = attr; | 233 this.attributesMap_[name] = attr; |
235 this.attributes.push(attr); | 234 this.attributes.push(attr); |
236 }; | 235 }; |
237 | 236 |
238 | 237 |
239 /** | 238 /** |
240 * Sends 'remove attribute' command to the remote agent. | 239 * Sends 'remove attribute' command to the remote agent. |
241 * @param {string} name Attribute name to set value for. | 240 * @param {string} name Attribute name to set value for. |
242 */ | 241 */ |
243 devtools.DomNode.prototype.removeAttribute = function(name) { | 242 devtools.DomNode.prototype.removeAttribute = function(name) { |
244 var self = this; | 243 var self = this; |
245 this.ownerDocument.domAgent_.removeAttributeAsync(this, name, function() { | 244 this.ownerDocument.domAgent_.removeAttributeAsync(this, name, function() { |
246 delete self.attributesMap_[name]; | 245 delete self.attributesMap_[name]; |
247 for (var i = 0; i < self.attributes.length; ++i) { | 246 for (var i = 0; i < self.attributes.length; ++i) { |
248 if (self.attributes[i].name == name) { | 247 if (self.attributes[i].name == name) { |
249 self.attributes.splice(i, 1); | 248 self.attributes.splice(i, 1); |
250 break; | 249 break; |
251 } | 250 } |
252 } | 251 } |
253 }); | 252 }); |
254 }; | 253 }; |
255 | 254 |
256 | 255 |
257 /** | 256 /** |
258 * Returns inline style (if styles has loaded). Must be called after | |
259 * node.setStyles_. | |
260 */ | |
261 devtools.DomNode.prototype.__defineGetter__('style', function() { | |
262 return this.styles_.inlineStyle; | |
263 }); | |
264 | |
265 | |
266 /** | |
267 * Makes available the following methods and properties: | 257 * Makes available the following methods and properties: |
268 * - node.style property | 258 * - node.style property |
269 * - node.document.defaultView.getComputedStyles(node) | 259 * - node.document.defaultView.getComputedStyles(node) |
270 * - node.document.defaultView.getMatchedCSSRules(node, ...) | 260 * - node.document.defaultView.getMatchedCSSRules(node, ...) |
271 * - style attribute of node's attributes | 261 * - style attribute of node's attributes |
272 * @param {string} computedStyle is a cssText of result of getComputedStyle(). | 262 * @param {string} computedStyle is a cssText of result of getComputedStyle(). |
273 * @param {string} inlineStyle is a style.cssText (defined in the STYLE | 263 * @param {string} inlineStyle is a style.cssText (defined in the STYLE |
274 * attribute). | 264 * attribute). |
275 * @param {Object} styleAttributes represents 'style' property | 265 * @param {Object} styleAttributes represents 'style' property |
276 * of attributes. | 266 * of attributes. |
277 * @param {Array.<object>} matchedCSSRules represents result of the | 267 * @param {Array.<object>} matchedCSSRules represents result of the |
278 * getMatchedCSSRules(node, '', authorOnly). Each elemet consists of: | 268 * getMatchedCSSRules(node, '', authorOnly). Each elemet consists of: |
279 * selector, rule.style.cssText[, rule.parentStyleSheet.href | 269 * selector, rule.style.cssText[, rule.parentStyleSheet.href |
280 * [, rule.parentStyleSheet.ownerNode.nodeName]]. | 270 * [, rule.parentStyleSheet.ownerNode.nodeName]]. |
281 */ | 271 */ |
282 devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle, | 272 devtools.DomNode.prototype.setStyles = function(computedStyle, inlineStyle, |
283 styleAttributes, matchedCSSRules) { | 273 styleAttributes, matchedCSSRules) { |
284 var styles = {}; | 274 this.computedStyle_ = this.makeStyle_(computedStyle); |
285 styles.computedStyle = this.makeStyle_(computedStyle); | 275 this.style = this.makeStyle_(inlineStyle); |
286 styles.inlineStyle = this.makeStyle_(inlineStyle); | |
287 | 276 |
288 styles.attributes = {}; | |
289 for (var name in styleAttributes) { | 277 for (var name in styleAttributes) { |
290 var style = this.makeStyle_(styleAttributes[name]); | 278 if (this.attributesMap_[name]) { |
291 styles.attributes[name] = style; | 279 this.attributesMap_[name].style = |
| 280 this.makeStyle_(styleAttributes[name]); |
| 281 } |
292 } | 282 } |
293 | 283 |
294 styles.matchedCSSRules = []; | 284 this.matchedCSSRules_ = []; |
295 for (var i = 0; i < matchedCSSRules.length; i++) { | 285 for (var i = 0; i < matchedCSSRules.length; i++) { |
296 var descr = matchedCSSRules[i]; | 286 var descr = matchedCSSRules[i]; |
297 var selector = descr.selector; | |
298 var style = this.makeStyle_(descr.style); | |
299 | 287 |
300 var parentStyleSheet = undefined; | 288 var rule = {}; |
301 if (descr.parentStyleSheetHref) { | 289 rule.selectorText = descr['selector']; |
302 parentStyleSheet = {href: descr.parentStyleSheetHref}; | 290 rule.style = this.makeStyle_(descr['style']); |
303 | 291 |
304 if (descr.parentStyleSheetOwnerNodeName) { | 292 if (descr['parentStyleSheet']) { |
305 parentStyleSheet.ownerNode = | 293 var parentStyleMock = {}; |
306 {nodeName: descr.parentStyleSheetOwnerNodeName}; | 294 parentStyleMock.href = descr['parentStyleSheet']['href']; |
| 295 var nodeName = descr['parentStyleSheet']['ownerNodeName']; |
| 296 if (nodeName) { |
| 297 parentStyleMock.ownerNode = { |
| 298 'nodeName': nodeName |
| 299 }; |
307 } | 300 } |
| 301 rule.parentStyleSheet = parentStyleMock; |
308 } | 302 } |
309 | 303 this.matchedCSSRules_.push(rule); |
310 styles.matchedCSSRules.push({ | |
311 'selectorText': selector, | |
312 'style': style, | |
313 'parentStyleSheet': parentStyleSheet | |
314 }); | |
315 } | 304 } |
316 | |
317 this.styles_ = styles; | |
318 }; | 305 }; |
319 | 306 |
320 | 307 |
321 /** | 308 /** |
322 * Creates a style declaration. | 309 * Creates a style declaration. |
323 * @param {payload} payload | 310 * @param {payload} payload |
324 * @return {devtools.CSSStyleDeclaration:undefined} | 311 * @return {devtools.CSSStyleDeclaration:undefined} |
325 * @see devtools.CSSStyleDeclaration | 312 * @see devtools.CSSStyleDeclaration |
326 */ | 313 */ |
327 devtools.DomNode.prototype.makeStyle_ = function(payload) { | 314 devtools.DomNode.prototype.makeStyle_ = function(payload) { |
328 return payload && new devtools.CSSStyleDeclaration(payload); | 315 var style = new devtools.CSSStyleDeclaration(payload); |
| 316 style.nodeId_ = this.id_; |
| 317 return style; |
329 }; | 318 }; |
330 | 319 |
331 | 320 |
332 /** | 321 /** |
333 * Remove references to the style information to release | 322 * Remove references to the style information to release |
334 * resources when styles are not going to be used. | 323 * resources when styles are not going to be used. |
335 * @see setStyles_. | 324 * @see setStyles. |
336 */ | 325 */ |
337 devtools.DomNode.prototype.clearStyles = function() { | 326 devtools.DomNode.prototype.clearStyles = function() { |
338 this.styles_ = null; | 327 this.computedStyle = null; |
| 328 this.style = null; |
| 329 for (var name in this.attributesMap_) { |
| 330 this.attributesMap_[name].style = null; |
| 331 } |
| 332 this.matchedCSSRules_ = null; |
339 }; | 333 }; |
340 | 334 |
341 | 335 |
342 /** | 336 /** |
343 * Remote Dom document abstraction. | 337 * Remote Dom document abstraction. |
344 * @param {devtools.DomAgent} domAgent owner agent. | 338 * @param {devtools.DomAgent} domAgent owner agent. |
345 * @param {devtools.DomWindow} defaultView owner window. | 339 * @param {devtools.DomWindow} defaultView owner window. |
346 * @constructor. | 340 * @constructor. |
347 */ | 341 */ |
348 devtools.DomDocument = function(domAgent, defaultView) { | 342 devtools.DomDocument = function(domAgent, defaultView) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 | 437 |
444 /** | 438 /** |
445 * See usages in ScopeChainSidebarPane.js where it's called as | 439 * See usages in ScopeChainSidebarPane.js where it's called as |
446 * constructor. | 440 * constructor. |
447 */ | 441 */ |
448 devtools.DomWindow.prototype.Object = function() { | 442 devtools.DomWindow.prototype.Object = function() { |
449 }; | 443 }; |
450 | 444 |
451 | 445 |
452 /** | 446 /** |
453 * Simulates the DOM interface for styles. Must be called after | 447 * Simulates the DOM interface for styles. |
454 * node.setStyles_. | |
455 * @param {devtools.DomNode} node | 448 * @param {devtools.DomNode} node |
456 * @return {CSSStyleDescription} | 449 * @return {CSSStyleDescription} |
457 */ | 450 */ |
458 devtools.DomWindow.prototype.getComputedStyle = function(node) { | 451 devtools.DomWindow.prototype.getComputedStyle = function(node) { |
459 return node.styles_.computedStyle; | 452 return node.computedStyle_; |
460 }; | 453 }; |
461 | 454 |
462 | 455 |
463 /** | 456 /** |
464 * Simulates the DOM interface for styles. Must be called after | 457 * Simulates the DOM interface for styles. |
465 * node.setStyles_. | |
466 * @param {devtools.DomNode} nodeStyles | 458 * @param {devtools.DomNode} nodeStyles |
467 * @param {string} pseudoElement assumed to be empty string. | 459 * @param {string} pseudoElement assumed to be empty string. |
468 * @param {boolean} authorOnly assumed to be equal to authorOnly argument of | 460 * @param {boolean} authorOnly assumed to be equal to authorOnly argument of |
469 * getNodeStylesAsync. | 461 * getNodeStylesAsync. |
470 * @return {CSSStyleDescription} | 462 * @return {CSSStyleDescription} |
471 */ | 463 */ |
472 devtools.DomWindow.prototype.getMatchedCSSRules = function(node, | 464 devtools.DomWindow.prototype.getMatchedCSSRules = function(node, |
473 pseudoElement, authorOnly) { | 465 pseudoElement, authorOnly) { |
474 return node.styles_.matchedCSSRules; | 466 return node.matchedCSSRules_; |
475 }; | 467 }; |
476 | 468 |
477 | 469 |
478 /** | 470 /** |
479 * Creates DomAgent Js representation. | 471 * Creates DomAgent Js representation. |
480 * @constructor | 472 * @constructor |
481 */ | 473 */ |
482 devtools.DomAgent = function() { | 474 devtools.DomAgent = function() { |
483 RemoteDomAgent.DidGetChildNodes = | 475 RemoteDomAgent.DidGetChildNodes = |
484 devtools.Callback.processCallback; | 476 devtools.Callback.processCallback; |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
830 /** | 822 /** |
831 * Returns all properties of the given node. | 823 * Returns all properties of the given node. |
832 * @param {number} nodeId Node to get properties for. | 824 * @param {number} nodeId Node to get properties for. |
833 * @param {Array.<string>} path Path to the object. | 825 * @param {Array.<string>} path Path to the object. |
834 * @param {number} protoDepth Depth to the exact proto level. | 826 * @param {number} protoDepth Depth to the exact proto level. |
835 * @param {function(string):undefined} callback Function to call with the | 827 * @param {function(string):undefined} callback Function to call with the |
836 * result. | 828 * result. |
837 */ | 829 */ |
838 devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId, | 830 devtools.DomAgent.prototype.getNodePropertiesAsync = function(nodeId, |
839 path, protoDepth, callback) { | 831 path, protoDepth, callback) { |
840 var callbackId = devtools.Callback.wrap(callback); | 832 var mycallback = |
| 833 goog.bind(this.utilityFunctionCallbackWrapper_, this, callback); |
| 834 var callbackId = devtools.Callback.wrap(mycallback); |
841 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, | 835 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, |
842 'devtools$$getProperties', nodeId, | 836 'getProperties', nodeId, |
843 goog.json.serialize([path, protoDepth])); | 837 goog.json.serialize([path, protoDepth])); |
844 }; | 838 }; |
845 | 839 |
846 | 840 |
847 /** | 841 /** |
848 * Returns prototype chain for a given node. | 842 * Returns prototype chain for a given node. |
849 * @param {number} nodeId Node to get prototypes for. | 843 * @param {number} nodeId Node to get prototypes for. |
850 * @param {Function} callback. | 844 * @param {Function} callback. |
851 */ | 845 */ |
852 devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId, | 846 devtools.DomAgent.prototype.getNodePrototypesAsync = function(nodeId, |
853 callback) { | 847 callback) { |
854 var callbackId = devtools.Callback.wrap(callback); | 848 var mycallback = |
| 849 goog.bind(this.utilityFunctionCallbackWrapper_, this, callback); |
| 850 var callbackId = devtools.Callback.wrap(mycallback); |
855 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, | 851 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, |
856 'devtools$$getPrototypes', nodeId, ''); | 852 'getPrototypes', nodeId, '[]'); |
857 }; | 853 }; |
858 | 854 |
859 | 855 |
860 /** | 856 /** |
861 * Returns styles for given node. | 857 * Returns styles for given node. |
862 * @param {devtools.DomNode} node Node to get prototypes for. | 858 * @param {devtools.DomNode} node Node to get prototypes for. |
863 * @param {boolean} authorOnly Returns only author styles if true. | 859 * @param {boolean} authorOnly Returns only author styles if true. |
864 * @param {Function} callback. | 860 * @param {Function} callback. |
865 */ | 861 */ |
866 devtools.DomAgent.prototype.getNodeStylesAsync = function(node, | 862 devtools.DomAgent.prototype.getNodeStylesAsync = function(node, |
867 authorOnly, callback) { | 863 authorOnly, callback) { |
868 var callbackId = devtools.Callback.wrap(callback); | 864 var mycallback = |
| 865 goog.bind(this.utilityFunctionCallbackWrapper_, this, callback); |
| 866 var callbackId = devtools.Callback.wrap(mycallback); |
869 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, | 867 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, |
870 'devtools$$getStyles', | 868 'getStyles', |
871 node.id_, | 869 node.id_, |
872 goog.json.serialize(authorOnly)); | 870 goog.json.serialize([authorOnly])); |
| 871 }; |
| 872 |
| 873 |
| 874 /** |
| 875 * Toggles style with given id on/off. |
| 876 * @param {devtools.CSSStyleDeclaration} style Style to toggle. |
| 877 * @param {boolean} enabled True if style should be enabled. |
| 878 * @param {string} name Style name. |
| 879 * @param {Function} callback. |
| 880 */ |
| 881 devtools.DomAgent.prototype.toggleNodeStyleAsync = function( |
| 882 style, enabled, name, callback) { |
| 883 var mycallback = |
| 884 goog.bind(this.utilityFunctionCallbackWrapper_, this, callback); |
| 885 var callbackId = devtools.Callback.wrap(mycallback); |
| 886 RemoteToolsAgent.ExecuteUtilityFunction(callbackId, |
| 887 'toggleNodeStyle', |
| 888 style.nodeId_, |
| 889 goog.json.serialize([style.id_, enabled, name])); |
| 890 }; |
| 891 |
| 892 |
| 893 /** |
| 894 * Dumps exception if something went wrong in ExecuteUtilityFunction. |
| 895 */ |
| 896 devtools.DomAgent.prototype.utilityFunctionCallbackWrapper_ = |
| 897 function(callback, result, exception) { |
| 898 if (exception && exception.length) { |
| 899 debugPrint('Exception in ExecuteUtilityFunction styles:' + exception); |
| 900 return; |
| 901 } |
| 902 callback(result); |
873 }; | 903 }; |
874 | 904 |
875 | 905 |
876 /** | 906 /** |
877 * Represents remote CSSStyleDeclaration for using in StyleSidebarPane. | 907 * Represents remote CSSStyleDeclaration for using in StyleSidebarPane. |
878 * @param {Array<Object>} payload built by devtools$$getStyle from the injected | 908 * @param {id, Array<Object>} payload built by inject's getStyle from the |
879 * js. | 909 * injected js. |
880 * @consctuctor | 910 * @constructor |
881 */ | 911 */ |
882 devtools.CSSStyleDeclaration = function(payload) { | 912 devtools.CSSStyleDeclaration = function(payload) { |
883 this.length = payload.length; | 913 this.id_ = payload[0]; |
| 914 this.__disabledProperties = payload[1]; |
| 915 this.__disabledPropertyValues = payload[2]; |
| 916 this.__disabledPropertyPriorities = payload[3]; |
| 917 |
| 918 this.length = payload.length - 4; |
884 this.priority_ = {}; | 919 this.priority_ = {}; |
885 this.implicit_ = {}; | 920 this.implicit_ = {}; |
886 this.shorthand_ = {}; | 921 this.shorthand_ = {}; |
887 this.value_ = {}; | 922 this.value_ = {}; |
888 | 923 |
889 for (var i = 0; i < payload.length; ++i) { | 924 for (var i = 4; i < payload.length; ++i) { |
890 var p = payload[i]; | 925 var p = payload[i]; |
891 var name = p[0]; | 926 var name = p[0]; |
892 | 927 |
893 this.priority_[name] = p[1]; | 928 this.priority_[name] = p[1]; |
894 this.implicit_[name] = p[2]; | 929 this.implicit_[name] = p[2]; |
895 this.shorthand_[name] = p[3]; | 930 this.shorthand_[name] = p[3]; |
896 this.value_[name] = p[4]; | 931 this.value_[name] = p[4]; |
897 | 932 |
898 this[i] = name; | 933 this[i - 4] = name; |
899 } | 934 } |
900 }; | 935 }; |
901 | 936 |
902 | 937 |
903 /** | 938 /** |
904 * @param {string} name of a CSS property. | 939 * @param {string} name of a CSS property. |
905 * @return {string} | 940 * @return {string} |
906 */ | 941 */ |
907 devtools.CSSStyleDeclaration.prototype.getPropertyValue = function(name) { | 942 devtools.CSSStyleDeclaration.prototype.getPropertyValue = function(name) { |
908 return this.value_[name] || ''; | 943 return this.value_[name] || ''; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 function onlyTextChild() { | 979 function onlyTextChild() { |
945 if (!this.children) { | 980 if (!this.children) { |
946 return null; | 981 return null; |
947 } else if (this.children.length == 1 && | 982 } else if (this.children.length == 1 && |
948 this.children[0].nodeType == Node.TEXT_NODE) { | 983 this.children[0].nodeType == Node.TEXT_NODE) { |
949 return this.children[0]; | 984 return this.children[0]; |
950 } else { | 985 } else { |
951 return null; | 986 return null; |
952 } | 987 } |
953 } | 988 } |
OLD | NEW |