Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: Source/devtools/front_end/elements/ElementsTreeOutline.js

Issue 701153002: DevTools: [Elements] Highlight DOM updates (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Refactored UpdateInfo fill-in and their use when building titles Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
4 * Copyright (C) 2009 Joseph Pecoraro 4 * Copyright (C) 2009 Joseph Pecoraro
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 9 *
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
(...skipping 1035 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 "html", "head", "body" 1046 "html", "head", "body"
1047 ].keySet(); 1047 ].keySet();
1048 1048
1049 /** @enum {number} */ 1049 /** @enum {number} */
1050 WebInspector.ElementsTreeElement.ChildrenDisplayMode = { 1050 WebInspector.ElementsTreeElement.ChildrenDisplayMode = {
1051 NoChildren: 0, 1051 NoChildren: 0,
1052 InlineText: 1, 1052 InlineText: 1,
1053 HasChildren: 2 1053 HasChildren: 2
1054 } 1054 }
1055 1055
1056 /**
1057 * @param {!WebInspector.ElementsTreeElement} treeElement
1058 */
1059 WebInspector.ElementsTreeElement.animateOnDOMUpdate = function(treeElement)
1060 {
1061 var tagName = treeElement.listItemElement.querySelector(".webkit-html-tag-na me");
1062 WebInspector.runCSSAnimationOnce(tagName || treeElement.listItemElement, "do m-update-highlight");
1063 }
1064
1056 WebInspector.ElementsTreeElement.prototype = { 1065 WebInspector.ElementsTreeElement.prototype = {
1057 /** 1066 /**
1058 * @return {!WebInspector.DOMNode} 1067 * @return {!WebInspector.DOMNode}
1059 */ 1068 */
1060 node: function() 1069 node: function()
1061 { 1070 {
1062 return this._node; 1071 return this._node;
1063 }, 1072 },
1064 1073
1065 /** 1074 /**
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 moveChild: function(child, targetIndex) 1298 moveChild: function(child, targetIndex)
1290 { 1299 {
1291 var wasSelected = child.selected; 1300 var wasSelected = child.selected;
1292 this.removeChild(child); 1301 this.removeChild(child);
1293 this.insertChild(child, targetIndex); 1302 this.insertChild(child, targetIndex);
1294 if (wasSelected) 1303 if (wasSelected)
1295 child.select(); 1304 child.select();
1296 }, 1305 },
1297 1306
1298 /** 1307 /**
1308 * @param {!WebInspector.DOMNode=} node
1309 * @return {!WebInspector.ElementsTreeUpdater.UpdateInfo|undefined}
1310 */
1311 _updateInfo: function(node)
1312 {
1313 if (!WebInspector.settings.highlightDOMUpdates.get())
1314 return undefined;
1315 var effectiveNode = node || this._node;
1316 var updater = this.treeOutline._elementsTreeUpdater;
1317 return updater._recentlyModifiedNodes.get(effectiveNode) || updater._rec entlyModifiedParentNodes.get(effectiveNode);
1318 },
1319
1320 /**
1299 * @param {boolean} fullRefresh 1321 * @param {boolean} fullRefresh
1300 * @param {?Array.<!WebInspector.DOMNode>} children 1322 * @param {?Array.<!WebInspector.DOMNode>} children
1301 */ 1323 */
1302 _updateChildren: function(fullRefresh, children) 1324 _updateChildren: function(fullRefresh, children)
1303 { 1325 {
1304 if (!children || this._updateChildrenInProgress || !this.treeOutline._vi sible) 1326 if (!children || this._updateChildrenInProgress || !this.treeOutline._vi sible)
1305 return; 1327 return;
1306 1328
1307 this._updateChildrenInProgress = true; 1329 this._updateChildrenInProgress = true;
1308 var selectedNode = this.treeOutline.selectedDOMNode(); 1330 var selectedNode = this.treeOutline.selectedDOMNode();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1341 var elementToSelect; 1363 var elementToSelect;
1342 var visibleChildren = this._visibleChildren(); 1364 var visibleChildren = this._visibleChildren();
1343 for (var i = 0; i < visibleChildren.length && i < this.expandedChildrenL imit; ++i) { 1365 for (var i = 0; i < visibleChildren.length && i < this.expandedChildrenL imit; ++i) {
1344 var child = visibleChildren[i]; 1366 var child = visibleChildren[i];
1345 if (existingTreeElements.has(child)) { 1367 if (existingTreeElements.has(child)) {
1346 // If an existing element was found, just move it. 1368 // If an existing element was found, just move it.
1347 this.moveChild(existingTreeElements.get(child), i); 1369 this.moveChild(existingTreeElements.get(child), i);
1348 } else { 1370 } else {
1349 // No existing element found, insert a new element. 1371 // No existing element found, insert a new element.
1350 var newElement = this.insertChildElement(child, i); 1372 var newElement = this.insertChildElement(child, i);
1373 var updateRecord = this._updateInfo();
1374 if (updateRecord)
1375 WebInspector.ElementsTreeElement.animateOnDOMUpdate(newEleme nt);
1351 if (child === selectedNode) 1376 if (child === selectedNode)
1352 elementToSelect = newElement; 1377 elementToSelect = newElement;
1353 // If a node was inserted in the middle of existing list dynamic ally we might need to increase the limit. 1378 // If a node was inserted in the middle of existing list dynamic ally we might need to increase the limit.
1354 if (this.expandedChildCount > this.expandedChildrenLimit) 1379 if (this.expandedChildCount > this.expandedChildrenLimit)
1355 this.expandedChildrenLimit++; 1380 this.expandedChildrenLimit++;
1356 } 1381 }
1357 } 1382 }
1358 1383
1359 this.updateTitle(); 1384 this.updateTitle(false);
pfeldman 2014/11/10 15:38:20 revert
apavlov 2014/11/10 16:07:37 Done.
1360 this._adjustCollapsedRange(); 1385 this._adjustCollapsedRange();
1361 1386
1362 if (this._node.nodeType() === Node.ELEMENT_NODE && this._hasChildTreeEle ments()) 1387 if (this._node.nodeType() === Node.ELEMENT_NODE && this._hasChildTreeEle ments())
1363 this.insertChildElement(this._node, this.children.length, true); 1388 this.insertChildElement(this._node, this.children.length, true);
1364 1389
1365 // We want to restore the original selection and tree scroll position af ter a full refresh, if possible. 1390 // We want to restore the original selection and tree scroll position af ter a full refresh, if possible.
1366 if (fullRefresh && elementToSelect) { 1391 if (fullRefresh && elementToSelect) {
1367 elementToSelect.select(); 1392 elementToSelect.select();
1368 if (treeOutlineContainerElement && originalScrollTop <= treeOutlineC ontainerElement.scrollHeight) 1393 if (treeOutlineContainerElement && originalScrollTop <= treeOutlineC ontainerElement.scrollHeight)
1369 treeOutlineContainerElement.scrollTop = originalScrollTop; 1394 treeOutlineContainerElement.scrollTop = originalScrollTop;
(...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 2172
2148 // Remaining cases are single line non-expanded elements with a closing 2173 // Remaining cases are single line non-expanded elements with a closing
2149 // tag, or HTML elements without a closing tag (such as <br>). Return 2174 // tag, or HTML elements without a closing tag (such as <br>). Return
2150 // null in the case where there isn't a closing tag. 2175 // null in the case where there isn't a closing tag.
2151 var tags = this.listItemElement.getElementsByClassName("webkit-html-tag" ); 2176 var tags = this.listItemElement.getElementsByClassName("webkit-html-tag" );
2152 return (tags.length === 1 ? null : tags[tags.length-1]); 2177 return (tags.length === 1 ? null : tags[tags.length-1]);
2153 }, 2178 },
2154 2179
2155 /** 2180 /**
2156 * @param {boolean=} onlySearchQueryChanged 2181 * @param {boolean=} onlySearchQueryChanged
2182 * @param {!WebInspector.ElementsTreeUpdater.UpdateInfo=} updates
2157 */ 2183 */
2158 updateTitle: function(onlySearchQueryChanged) 2184 updateTitle: function(onlySearchQueryChanged, updates)
pfeldman 2014/11/10 15:38:20 revert
apavlov 2014/11/10 16:07:37 Done.
2159 { 2185 {
2160 // If we are editing, return early to prevent canceling the edit. 2186 // If we are editing, return early to prevent canceling the edit.
2161 // After editing is committed updateTitle will be called. 2187 // After editing is committed updateTitle will be called.
2162 if (this._editing) 2188 if (this._editing)
2163 return; 2189 return;
2164 2190
2165 if (onlySearchQueryChanged) { 2191 if (onlySearchQueryChanged) {
2166 if (this._highlightResult) 2192 if (this._highlightResult)
2167 this._updateSearchHighlight(false); 2193 this._updateSearchHighlight(false);
2168 } else { 2194 } else {
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 var hasText = (forceValue || value.length > 0); 2304 var hasText = (forceValue || value.length > 0);
2279 var attrSpanElement = parentElement.createChild("span", "webkit-html-att ribute"); 2305 var attrSpanElement = parentElement.createChild("span", "webkit-html-att ribute");
2280 var attrNameElement = attrSpanElement.createChild("span", "webkit-html-a ttribute-name"); 2306 var attrNameElement = attrSpanElement.createChild("span", "webkit-html-a ttribute-name");
2281 attrNameElement.textContent = name; 2307 attrNameElement.textContent = name;
2282 2308
2283 if (hasText) 2309 if (hasText)
2284 attrSpanElement.createTextChild("=\u200B\""); 2310 attrSpanElement.createTextChild("=\u200B\"");
2285 2311
2286 var attrValueElement = attrSpanElement.createChild("span", "webkit-html- attribute-value"); 2312 var attrValueElement = attrSpanElement.createChild("span", "webkit-html- attribute-value");
2287 2313
2314 var updates = this._updateInfo();
2315 if (updates && updates.isAttributeModified(name))
2316 WebInspector.runCSSAnimationOnce(hasText ? attrValueElement : attrNa meElement, "dom-update-highlight");
2317
2288 /** 2318 /**
2289 * @this {WebInspector.ElementsTreeElement} 2319 * @this {WebInspector.ElementsTreeElement}
2290 * @param {string} value 2320 * @param {string} value
2291 * @return {!Element} 2321 * @return {!Element}
2292 */ 2322 */
2293 function linkifyValue(value) 2323 function linkifyValue(value)
2294 { 2324 {
2295 var rewrittenHref = node.resolveURL(value); 2325 var rewrittenHref = node.resolveURL(value);
2296 if (rewrittenHref === null) { 2326 if (rewrittenHref === null) {
2297 var span = createElement("span"); 2327 var span = createElement("span");
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2349 _buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeE lement, linkify) 2379 _buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeE lement, linkify)
2350 { 2380 {
2351 var node = this._node; 2381 var node = this._node;
2352 var classes = [ "webkit-html-tag" ]; 2382 var classes = [ "webkit-html-tag" ];
2353 if (isClosingTag && isDistinctTreeElement) 2383 if (isClosingTag && isDistinctTreeElement)
2354 classes.push("close"); 2384 classes.push("close");
2355 var tagElement = parentElement.createChild("span", classes.join(" ")); 2385 var tagElement = parentElement.createChild("span", classes.join(" "));
2356 tagElement.createTextChild("<"); 2386 tagElement.createTextChild("<");
2357 var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name"); 2387 var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name");
2358 tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName; 2388 tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName;
2359 if (!isClosingTag && node.hasAttributes()) { 2389 if (!isClosingTag) {
2360 var attributes = node.attributes(); 2390 if (node.hasAttributes()) {
2361 for (var i = 0; i < attributes.length; ++i) { 2391 var attributes = node.attributes();
2362 var attr = attributes[i]; 2392 for (var i = 0; i < attributes.length; ++i) {
2363 tagElement.createTextChild(" "); 2393 var attr = attributes[i];
2364 this._buildAttributeDOM(tagElement, attr.name, attr.value, false , node, linkify); 2394 tagElement.createTextChild(" ");
2395 this._buildAttributeDOM(tagElement, attr.name, attr.value, f alse, node, linkify);
2396 }
2365 } 2397 }
2398 var hasUpdates;
2399 var updates = this._updateInfo();
2400 if (updates) {
2401 hasUpdates |= updates.hasRemovedAttributes();
2402 var hasInlineText = this._childrenDisplayMode === WebInspector.E lementsTreeElement.ChildrenDisplayMode.InlineText;
2403
2404 hasUpdates |= (!hasInlineText || this.expanded) && updates.hasCh angedChildren();
2405
2406 // Highlight the tag name, as the inserted node is not visible ( either child of a collapsed tree element or empty inline text).
2407 hasUpdates |= !this.expanded && updates.hasInsertedNodes() && (! hasInlineText || this._node.firstChild.nodeValue().length === 0);
2408
2409 // Highlight the tag name, as the inline text node value has bee n cleared.
2410 // The respective empty node will be highlighted, but the highli ght will not be visible to the user.
2411 hasUpdates |= hasInlineText && (updates.isCharDataModified() || updates.hasChangedChildren()) && this._node.firstChild.nodeValue().length === 0;
2412 }
2413 if (hasUpdates)
2414 WebInspector.runCSSAnimationOnce(tagNameElement, "dom-update-hig hlight");
2366 } 2415 }
2416
2367 tagElement.createTextChild(">"); 2417 tagElement.createTextChild(">");
2368 parentElement.createTextChild("\u200B"); 2418 parentElement.createTextChild("\u200B");
2369 }, 2419 },
2370 2420
2371 /** 2421 /**
2372 * @param {string} text 2422 * @param {string} text
2373 * @return {!{text: string, entityRanges: !Array.<!WebInspector.SourceRange> }} 2423 * @return {!{text: string, entityRanges: !Array.<!WebInspector.SourceRange> }}
2374 */ 2424 */
2375 _convertWhitespaceToEntities: function(text) 2425 _convertWhitespaceToEntities: function(text)
2376 { 2426 {
2377 var result = ""; 2427 var result = "";
2378 var resultLength = 0;
2379 var lastIndexAfterEntity = 0; 2428 var lastIndexAfterEntity = 0;
2380 var entityRanges = []; 2429 var entityRanges = [];
2381 var charToEntity = WebInspector.ElementsTreeOutline.MappedCharToEntity; 2430 var charToEntity = WebInspector.ElementsTreeOutline.MappedCharToEntity;
2382 for (var i = 0, size = text.length; i < size; ++i) { 2431 for (var i = 0, size = text.length; i < size; ++i) {
2383 var char = text.charAt(i); 2432 var char = text.charAt(i);
2384 if (charToEntity[char]) { 2433 if (charToEntity[char]) {
2385 result += text.substring(lastIndexAfterEntity, i); 2434 result += text.substring(lastIndexAfterEntity, i);
2386 var entityValue = "&" + charToEntity[char] + ";"; 2435 var entityValue = "&" + charToEntity[char] + ";";
2387 entityRanges.push({offset: result.length, length: entityValue.le ngth}); 2436 entityRanges.push({offset: result.length, length: entityValue.le ngth});
2388 result += entityValue; 2437 result += entityValue;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
2435 break; 2484 break;
2436 2485
2437 case WebInspector.ElementsTreeElement.ChildrenDisplayMode.Inline Text: 2486 case WebInspector.ElementsTreeElement.ChildrenDisplayMode.Inline Text:
2438 var textNodeElement = info.titleDOM.createChild("span", "web kit-html-text-node"); 2487 var textNodeElement = info.titleDOM.createChild("span", "web kit-html-text-node");
2439 var result = this._convertWhitespaceToEntities(node.firstChi ld.nodeValue()); 2488 var result = this._convertWhitespaceToEntities(node.firstChi ld.nodeValue());
2440 textNodeElement.textContent = result.text; 2489 textNodeElement.textContent = result.text;
2441 WebInspector.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value"); 2490 WebInspector.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value");
2442 info.titleDOM.createTextChild("\u200B"); 2491 info.titleDOM.createTextChild("\u200B");
2443 info.hasChildren = false; 2492 info.hasChildren = false;
2444 this._buildTagDOM(info.titleDOM, tagName, true, false); 2493 this._buildTagDOM(info.titleDOM, tagName, true, false);
2494 var updates = this._updateInfo();
2495 if (updates && (updates.hasInsertedNodes() || updates.hasCha ngedChildren()))
2496 WebInspector.runCSSAnimationOnce(textNodeElement, "dom-u pdate-highlight");
2497 updates = this._updateInfo(this._node.firstChild);
2498 if (updates && updates.isCharDataModified())
2499 WebInspector.runCSSAnimationOnce(textNodeElement, "dom-u pdate-highlight");
2445 break; 2500 break;
2446 2501
2447 case WebInspector.ElementsTreeElement.ChildrenDisplayMode.NoChil dren: 2502 case WebInspector.ElementsTreeElement.ChildrenDisplayMode.NoChil dren:
2448 if (this.treeOutline.isXMLMimeType || !WebInspector.Elements TreeElement.ForbiddenClosingTagElements[tagName]) 2503 if (this.treeOutline.isXMLMimeType || !WebInspector.Elements TreeElement.ForbiddenClosingTagElements[tagName])
2449 this._buildTagDOM(info.titleDOM, tagName, true, false); 2504 this._buildTagDOM(info.titleDOM, tagName, true, false);
2450 break; 2505 break;
2451 } 2506 }
2452 break; 2507 break;
2453 2508
2454 case Node.TEXT_NODE: 2509 case Node.TEXT_NODE:
2455 if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") { 2510 if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
2456 var newNode = info.titleDOM.createChild("span", "webkit-html -text-node webkit-html-js-node"); 2511 var newNode = info.titleDOM.createChild("span", "webkit-html -text-node webkit-html-js-node");
2457 newNode.textContent = node.nodeValue(); 2512 newNode.textContent = node.nodeValue();
2458 2513
2459 var javascriptSyntaxHighlighter = new WebInspector.DOMSyntax Highlighter("text/javascript", true); 2514 var javascriptSyntaxHighlighter = new WebInspector.DOMSyntax Highlighter("text/javascript", true);
2460 javascriptSyntaxHighlighter.syntaxHighlightNode(newNode); 2515 javascriptSyntaxHighlighter.syntaxHighlightNode(newNode);
2461 } else if (node.parentNode && node.parentNode.nodeName().toLower Case() === "style") { 2516 } else if (node.parentNode && node.parentNode.nodeName().toLower Case() === "style") {
2462 var newNode = info.titleDOM.createChild("span", "webkit-html -text-node webkit-html-css-node"); 2517 var newNode = info.titleDOM.createChild("span", "webkit-html -text-node webkit-html-css-node");
2463 newNode.textContent = node.nodeValue(); 2518 newNode.textContent = node.nodeValue();
2464 2519
2465 var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlig hter("text/css", true); 2520 var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlig hter("text/css", true);
2466 cssSyntaxHighlighter.syntaxHighlightNode(newNode); 2521 cssSyntaxHighlighter.syntaxHighlightNode(newNode);
2467 } else { 2522 } else {
2468 info.titleDOM.createTextChild("\""); 2523 info.titleDOM.createTextChild("\"");
2469 var textNodeElement = info.titleDOM.createChild("span", "web kit-html-text-node"); 2524 var textNodeElement = info.titleDOM.createChild("span", "web kit-html-text-node");
2470 var result = this._convertWhitespaceToEntities(node.nodeValu e()); 2525 var result = this._convertWhitespaceToEntities(node.nodeValu e());
2471 textNodeElement.textContent = result.text; 2526 textNodeElement.textContent = result.text;
2472 WebInspector.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value"); 2527 WebInspector.highlightRangesWithStyleClass(textNodeElement, result.entityRanges, "webkit-html-entity-value");
2473 info.titleDOM.createTextChild("\""); 2528 info.titleDOM.createTextChild("\"");
2529 var updates = this._updateInfo();
2530 if (updates && updates.isCharDataModified())
2531 WebInspector.runCSSAnimationOnce(textNodeElement, "dom-u pdate-highlight");
2474 } 2532 }
2475 break; 2533 break;
2476 2534
2477 case Node.COMMENT_NODE: 2535 case Node.COMMENT_NODE:
2478 var commentElement = info.titleDOM.createChild("span", "webkit-h tml-comment"); 2536 var commentElement = info.titleDOM.createChild("span", "webkit-h tml-comment");
2479 commentElement.createTextChild("<!--" + node.nodeValue() + "-->" ); 2537 commentElement.createTextChild("<!--" + node.nodeValue() + "-->" );
2480 break; 2538 break;
2481 2539
2482 case Node.DOCUMENT_TYPE_NODE: 2540 case Node.DOCUMENT_TYPE_NODE:
2483 var docTypeElement = info.titleDOM.createChild("span", "webkit-h tml-doctype"); 2541 var docTypeElement = info.titleDOM.createChild("span", "webkit-h tml-doctype");
2484 docTypeElement.createTextChild("<!DOCTYPE " + node.nodeName()); 2542 docTypeElement.createTextChild("<!DOCTYPE " + node.nodeName());
2485 if (node.publicId) { 2543 if (node.publicId) {
2486 docTypeElement.createTextChild(" PUBLIC \"" + node.publicId + "\""); 2544 docTypeElement.createTextChild(" PUBLIC \"" + node.publicId + "\"");
2487 if (node.systemId) 2545 if (node.systemId)
2488 docTypeElement.createTextChild(" \"" + node.systemId + " \""); 2546 docTypeElement.createTextChild(" \"" + node.systemId + " \"");
2489 } else if (node.systemId) 2547 } else if (node.systemId)
2490 docTypeElement.createTextChild(" SYSTEM \"" + node.systemId + "\""); 2548 docTypeElement.createTextChild(" SYSTEM \"" + node.systemId + "\"");
2491 2549
2492 if (node.internalSubset) 2550 if (node.internalSubset)
2493 docTypeElement.createTextChild(" [" + node.internalSubset + "]"); 2551 docTypeElement.createTextChild(" [" + node.internalSubset + "]");
2494 2552
2495 docTypeElement.createTextChild(">"); 2553 docTypeElement.createTextChild(">");
2496 break; 2554 break;
2497 2555
2498 case Node.CDATA_SECTION_NODE: 2556 case Node.CDATA_SECTION_NODE:
2499 var cdataElement = info.titleDOM.createChild("span", "webkit-htm l-text-node"); 2557 var cdataElement = info.titleDOM.createChild("span", "webkit-htm l-text-node");
2500 cdataElement.createTextChild("<![CDATA[" + node.nodeValue() + "] ]>"); 2558 cdataElement.createTextChild("<![CDATA[" + node.nodeValue() + "] ]>");
2501 break; 2559 break;
2560
2502 case Node.DOCUMENT_FRAGMENT_NODE: 2561 case Node.DOCUMENT_FRAGMENT_NODE:
2503 var fragmentElement = info.titleDOM.createChild("span", "webkit- html-fragment"); 2562 var fragmentElement = info.titleDOM.createChild("span", "webkit- html-fragment");
2504 if (node.isInShadowTree()) { 2563 if (node.isInShadowTree()) {
2505 var shadowRootType = node.shadowRootType(); 2564 var shadowRootType = node.shadowRootType();
2506 if (shadowRootType) { 2565 if (shadowRootType) {
2507 info.shadowRoot = true; 2566 info.shadowRoot = true;
2508 fragmentElement.classList.add("shadow-root"); 2567 fragmentElement.classList.add("shadow-root");
2509 } 2568 }
2510 } 2569 }
2511 fragmentElement.textContent = node.nodeNameInCorrectCase().colla pseWhitespace(); 2570 fragmentElement.textContent = node.nodeNameInCorrectCase().colla pseWhitespace();
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2740 2799
2741 /** 2800 /**
2742 * @constructor 2801 * @constructor
2743 * @param {!WebInspector.DOMModel} domModel 2802 * @param {!WebInspector.DOMModel} domModel
2744 * @param {!WebInspector.ElementsTreeOutline} treeOutline 2803 * @param {!WebInspector.ElementsTreeOutline} treeOutline
2745 */ 2804 */
2746 WebInspector.ElementsTreeUpdater = function(domModel, treeOutline) 2805 WebInspector.ElementsTreeUpdater = function(domModel, treeOutline)
2747 { 2806 {
2748 domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._n odeInserted, this); 2807 domModel.addEventListener(WebInspector.DOMModel.Events.NodeInserted, this._n odeInserted, this);
2749 domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._no deRemoved, this); 2808 domModel.addEventListener(WebInspector.DOMModel.Events.NodeRemoved, this._no deRemoved, this);
2750 domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._a ttributesUpdated, this); 2809 domModel.addEventListener(WebInspector.DOMModel.Events.AttrModified, this._a ttributeModified, this);
2751 domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._at tributesUpdated, this); 2810 domModel.addEventListener(WebInspector.DOMModel.Events.AttrRemoved, this._at tributeRemoved, this);
2752 domModel.addEventListener(WebInspector.DOMModel.Events.CharacterDataModified , this._characterDataModified, this); 2811 domModel.addEventListener(WebInspector.DOMModel.Events.CharacterDataModified , this._characterDataModified, this);
2753 domModel.addEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this ._documentUpdated, this); 2812 domModel.addEventListener(WebInspector.DOMModel.Events.DocumentUpdated, this ._documentUpdated, this);
2754 domModel.addEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated , this._childNodeCountUpdated, this); 2813 domModel.addEventListener(WebInspector.DOMModel.Events.ChildNodeCountUpdated , this._childNodeCountUpdated, this);
2755 2814
2756 this._domModel = domModel; 2815 this._domModel = domModel;
2757 this._treeOutline = treeOutline; 2816 this._treeOutline = treeOutline;
2758 /** @type {!Set.<!WebInspector.DOMNode>} */ 2817 /** @type {!Map.<!WebInspector.DOMNode, !WebInspector.ElementsTreeUpdater.Up dateInfo>} */
2759 this._recentlyModifiedNodes = new Set(); 2818 this._recentlyModifiedNodes = new Map();
2760 /** @type {!Set.<!WebInspector.DOMNode>} */ 2819 /** @type {!Map.<!WebInspector.DOMNode, !WebInspector.ElementsTreeUpdater.Up dateInfo>} */
2761 this._recentlyModifiedParentNodes = new Set(); 2820 this._recentlyModifiedParentNodes = new Map();
2762 } 2821 }
2763 2822
2764 WebInspector.ElementsTreeUpdater.prototype = { 2823 WebInspector.ElementsTreeUpdater.prototype = {
2765 dispose: function() 2824 dispose: function()
2766 { 2825 {
2767 this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeInse rted, this._nodeInserted, this); 2826 this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeInse rted, this._nodeInserted, this);
2768 this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeRemo ved, this._nodeRemoved, this); 2827 this._domModel.removeEventListener(WebInspector.DOMModel.Events.NodeRemo ved, this._nodeRemoved, this);
2769 this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModi fied, this._attributesUpdated, this); 2828 this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrModi fied, this._attributeModified, this);
2770 this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemo ved, this._attributesUpdated, this); 2829 this._domModel.removeEventListener(WebInspector.DOMModel.Events.AttrRemo ved, this._attributeRemoved, this);
2771 this._domModel.removeEventListener(WebInspector.DOMModel.Events.Characte rDataModified, this._characterDataModified, this); 2830 this._domModel.removeEventListener(WebInspector.DOMModel.Events.Characte rDataModified, this._characterDataModified, this);
2772 this._domModel.removeEventListener(WebInspector.DOMModel.Events.Document Updated, this._documentUpdated, this); 2831 this._domModel.removeEventListener(WebInspector.DOMModel.Events.Document Updated, this._documentUpdated, this);
2773 this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNod eCountUpdated, this._childNodeCountUpdated, this); 2832 this._domModel.removeEventListener(WebInspector.DOMModel.Events.ChildNod eCountUpdated, this._childNodeCountUpdated, this);
2774 }, 2833 },
2775 2834
2776 /** 2835 /**
2777 * @param {?WebInspector.DOMNode} parentNode 2836 * @param {?WebInspector.DOMNode} parentNode
2778 */ 2837 */
2779 _parentNodeModified: function(parentNode) 2838 _parentNodeModified: function(parentNode)
pfeldman 2014/11/10 15:38:20 annotate
apavlov 2014/11/10 16:07:37 Done.
2780 { 2839 {
2781 if (!parentNode) 2840 if (!parentNode)
2782 return; 2841 return;
2783 this._recentlyModifiedParentNodes.add(parentNode); 2842
2843 var record = this._recentlyModifiedParentNodes.get(parentNode);
2844 if (!record) {
2845 record = new WebInspector.ElementsTreeUpdater.UpdateInfo();
2846 this._recentlyModifiedParentNodes.set(parentNode, record);
2847 }
2784 2848
2785 var treeElement = this._treeOutline.findTreeElement(parentNode); 2849 var treeElement = this._treeOutline.findTreeElement(parentNode);
2786 if (treeElement) { 2850 if (treeElement) {
2787 var oldDisplayMode = treeElement._childrenDisplayMode; 2851 var oldDisplayMode = treeElement._childrenDisplayMode;
2788 treeElement._updateChildrenDisplayMode(); 2852 treeElement._updateChildrenDisplayMode();
2789 if (treeElement._childrenDisplayMode !== oldDisplayMode) 2853 if (treeElement._childrenDisplayMode !== oldDisplayMode)
2790 this._nodeModified(parentNode); 2854 this._nodeModified(parentNode).childrenModified();
2791 } 2855 }
2792 2856
2793 if (this._treeOutline._visible) 2857 if (this._treeOutline._visible)
2794 this._updateModifiedNodesSoon(); 2858 this._updateModifiedNodesSoon();
2859
2860 return record;
2795 }, 2861 },
2796 2862
2797 /** 2863 /**
2798 * @param {!WebInspector.DOMNode} node 2864 * @param {!WebInspector.DOMNode} node
2799 */ 2865 */
2800 _nodeModified: function(node) 2866 _nodeModified: function(node)
pfeldman 2014/11/10 15:38:20 annotate
apavlov 2014/11/10 16:07:37 Done.
2801 { 2867 {
2802 this._recentlyModifiedNodes.add(node);
2803 if (this._treeOutline._visible) 2868 if (this._treeOutline._visible)
2804 this._updateModifiedNodesSoon(); 2869 this._updateModifiedNodesSoon();
2870 var record = this._recentlyModifiedNodes.get(node);
2871 if (!record) {
2872 record = new WebInspector.ElementsTreeUpdater.UpdateInfo();
2873 this._recentlyModifiedNodes.set(node, record);
2874 }
2875 return record;
2805 }, 2876 },
2806 2877
2807 /** 2878 /**
2808 * @param {!WebInspector.Event} event 2879 * @param {!WebInspector.Event} event
2809 */ 2880 */
2810 _documentUpdated: function(event) 2881 _documentUpdated: function(event)
2811 { 2882 {
2812 var inspectedRootDocument = event.data; 2883 var inspectedRootDocument = event.data;
2813 2884
2814 this._reset(); 2885 this._reset();
2815 2886
2816 if (!inspectedRootDocument) 2887 if (!inspectedRootDocument)
2817 return; 2888 return;
2818 2889
2819 this._treeOutline.rootDOMNode = inspectedRootDocument; 2890 this._treeOutline.rootDOMNode = inspectedRootDocument;
2820 }, 2891 },
2821 2892
2822 /** 2893 /**
2823 * @param {!WebInspector.Event} event 2894 * @param {!WebInspector.Event} event
2824 */ 2895 */
2825 _attributesUpdated: function(event) 2896 _attributeModified: function(event)
2826 { 2897 {
2827 var node = /** @type {!WebInspector.DOMNode} */ (event.data.node); 2898 var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
2828 this._nodeModified(node); 2899 this._nodeModified(node).attributeModified(event.data.name);
2829 }, 2900 },
2830 2901
2831 /** 2902 /**
2903 * @param {!WebInspector.Event} event
2904 */
2905 _attributeRemoved: function(event)
2906 {
2907 var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
2908 this._nodeModified(node).attributeRemoved(event.data.name);
2909 },
2910
2911 /**
2832 * @param {!WebInspector.Event} event 2912 * @param {!WebInspector.Event} event
2833 */ 2913 */
2834 _characterDataModified: function(event) 2914 _characterDataModified: function(event)
2835 { 2915 {
2836 var node = /** @type {!WebInspector.DOMNode} */ (event.data); 2916 var node = /** @type {!WebInspector.DOMNode} */ (event.data);
2837 this._parentNodeModified(node.parentNode); 2917 this._parentNodeModified(node.parentNode).charDataModified();
2838 this._nodeModified(node); 2918 this._nodeModified(node).charDataModified();
2839 }, 2919 },
2840 2920
2841 /** 2921 /**
2842 * @param {!WebInspector.Event} event 2922 * @param {!WebInspector.Event} event
2843 */ 2923 */
2844 _nodeInserted: function(event) 2924 _nodeInserted: function(event)
2845 { 2925 {
2846 var node = /** @type {!WebInspector.DOMNode} */ (event.data); 2926 var node = /** @type {!WebInspector.DOMNode} */ (event.data);
2847 this._parentNodeModified(node.parentNode); 2927 this._parentNodeModified(node.parentNode).nodeInserted(node);
2848 }, 2928 },
2849 2929
2850 /** 2930 /**
2851 * @param {!WebInspector.Event} event 2931 * @param {!WebInspector.Event} event
2852 */ 2932 */
2853 _nodeRemoved: function(event) 2933 _nodeRemoved: function(event)
2854 { 2934 {
2855 var node = /** @type {!WebInspector.DOMNode} */ (event.data.node); 2935 var node = /** @type {!WebInspector.DOMNode} */ (event.data.node);
2856 var parentNode = /** @type {!WebInspector.DOMNode} */ (event.data.parent ); 2936 var parentNode = /** @type {!WebInspector.DOMNode} */ (event.data.parent );
2857 this._treeOutline._resetClipboardIfNeeded(node); 2937 this._treeOutline._resetClipboardIfNeeded(node);
2858 this._parentNodeModified(parentNode); 2938 this._parentNodeModified(parentNode).childrenModified();
2859 }, 2939 },
2860 2940
2861 /** 2941 /**
2862 * @param {!WebInspector.Event} event 2942 * @param {!WebInspector.Event} event
2863 */ 2943 */
2864 _childNodeCountUpdated: function(event) 2944 _childNodeCountUpdated: function(event)
2865 { 2945 {
2866 var node = /** @type {!WebInspector.DOMNode} */ (event.data); 2946 var node = /** @type {!WebInspector.DOMNode} */ (event.data);
2867 this._parentNodeModified(node); 2947 this._parentNodeModified(node);
2868 }, 2948 },
2869 2949
2870 _updateModifiedNodesSoon: function() 2950 _updateModifiedNodesSoon: function()
2871 { 2951 {
2872 if (this._updateModifiedNodesTimeout) 2952 if (this._updateModifiedNodesTimeout)
2873 return; 2953 return;
2874 this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes. bind(this), 50); 2954 this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes. bind(this), 50);
2875 }, 2955 },
2876 2956
2877 _updateModifiedNodes: function() 2957 _updateModifiedNodes: function()
2878 { 2958 {
2879 if (this._updateModifiedNodesTimeout) { 2959 if (this._updateModifiedNodesTimeout) {
2880 clearTimeout(this._updateModifiedNodesTimeout); 2960 clearTimeout(this._updateModifiedNodesTimeout);
2881 delete this._updateModifiedNodesTimeout; 2961 delete this._updateModifiedNodesTimeout;
2882 } 2962 }
2883 2963
2884 var updatedNodes = this._recentlyModifiedNodes.valuesArray().concat(this ._recentlyModifiedParentNodes.valuesArray()); 2964 var updatedNodes = this._recentlyModifiedNodes.keysArray().concat(this._ recentlyModifiedParentNodes.keysArray());
2885 var hidePanelWhileUpdating = updatedNodes.length > 10; 2965 var hidePanelWhileUpdating = updatedNodes.length > 10;
2886 if (hidePanelWhileUpdating) { 2966 if (hidePanelWhileUpdating) {
2887 var treeOutlineContainerElement = this._treeOutline.element.parentNo de; 2967 var treeOutlineContainerElement = this._treeOutline.element.parentNo de;
2888 var originalScrollTop = treeOutlineContainerElement ? treeOutlineCon tainerElement.scrollTop : 0; 2968 var originalScrollTop = treeOutlineContainerElement ? treeOutlineCon tainerElement.scrollTop : 0;
2889 this._treeOutline._element.classList.add("hidden"); 2969 this._treeOutline._element.classList.add("hidden");
2890 } 2970 }
2891 2971
2892 if (this._treeOutline._rootDOMNode && this._recentlyModifiedParentNodes. has(this._treeOutline._rootDOMNode)) { 2972 if (this._treeOutline._rootDOMNode && this._recentlyModifiedParentNodes. has(this._treeOutline._rootDOMNode)) {
2893 // Document's children have changed, perform total update. 2973 // Document's children have changed, perform total update.
2894 this._treeOutline.update(); 2974 this._treeOutline.update();
2895 } else { 2975 } else {
2896 var nodes = this._recentlyModifiedNodes.valuesArray(); 2976 var nodes = this._recentlyModifiedNodes.keysArray();
vsevik 2014/11/10 16:00:51 Let's switch to for-of while you are here.
apavlov 2014/11/10 16:07:37 Done.
2897 for (var i = 0, size = nodes.length; i < size; ++i) { 2977 for (var i = 0, size = nodes.length; i < size; ++i) {
2898 var nodeItem = this._treeOutline.findTreeElement(nodes[i]); 2978 var nodeItem = this._treeOutline.findTreeElement(nodes[i]);
2899 if (nodeItem) 2979 if (nodeItem)
2900 nodeItem.updateTitle(); 2980 nodeItem.updateTitle(false);
2901 } 2981 }
2902 2982
2903 var parentNodes = this._recentlyModifiedParentNodes.valuesArray(); 2983 var parentNodes = this._recentlyModifiedParentNodes.keysArray();
vsevik 2014/11/10 16:00:51 Let's switch to for-of while you are here.
apavlov 2014/11/10 16:07:37 Done.
2904 for (var i = 0, size = parentNodes.length; i < size; ++i) { 2984 for (var i = 0, size = parentNodes.length; i < size; ++i) {
2905 var parentNodeItem = this._treeOutline.findTreeElement(parentNod es[i]); 2985 var parentNodeItem = this._treeOutline.findTreeElement(parentNod es[i]);
2906 if (parentNodeItem && parentNodeItem.populated) 2986 if (parentNodeItem && parentNodeItem.populated)
2907 parentNodeItem.updateChildren(); 2987 parentNodeItem.updateChildren(false);
2908 } 2988 }
2909 } 2989 }
2910 2990
2911 if (hidePanelWhileUpdating) { 2991 if (hidePanelWhileUpdating) {
2912 this._treeOutline._element.classList.remove("hidden"); 2992 this._treeOutline._element.classList.remove("hidden");
2913 if (originalScrollTop) 2993 if (originalScrollTop)
2914 treeOutlineContainerElement.scrollTop = originalScrollTop; 2994 treeOutlineContainerElement.scrollTop = originalScrollTop;
2915 this._treeOutline.updateSelection(); 2995 this._treeOutline.updateSelection();
2916 } 2996 }
2917 this._recentlyModifiedNodes.clear(); 2997 this._recentlyModifiedNodes.clear();
2918 this._recentlyModifiedParentNodes.clear(); 2998 this._recentlyModifiedParentNodes.clear();
2919 this._treeOutline._fireElementsTreeUpdated(updatedNodes); 2999 this._treeOutline._fireElementsTreeUpdated(updatedNodes);
2920 }, 3000 },
2921 3001
2922 _reset: function() 3002 _reset: function()
2923 { 3003 {
2924 this._treeOutline.rootDOMNode = null; 3004 this._treeOutline.rootDOMNode = null;
2925 this._treeOutline.selectDOMNode(null, false); 3005 this._treeOutline.selectDOMNode(null, false);
2926 this._domModel.hideDOMNodeHighlight(); 3006 this._domModel.hideDOMNodeHighlight();
2927 this._recentlyModifiedNodes.clear(); 3007 this._recentlyModifiedNodes.clear();
2928 this._recentlyModifiedParentNodes.clear(); 3008 this._recentlyModifiedParentNodes.clear();
2929 delete this._treeOutline._clipboardNodeData; 3009 delete this._treeOutline._clipboardNodeData;
2930 } 3010 }
2931 } 3011 }
2932 3012
2933 /** 3013 /**
2934 * @constructor 3014 * @constructor
3015 */
3016 WebInspector.ElementsTreeUpdater.UpdateInfo = function()
3017 {
3018 this._removedAttributeCount = 0;
pfeldman 2014/11/10 15:38:20 Can we use this._removedAttributes size?
apavlov 2014/11/10 16:07:37 Done.
3019 }
3020
3021 WebInspector.ElementsTreeUpdater.UpdateInfo.prototype = {
3022 /**
3023 * @param {string} attrName
3024 */
3025 attributeModified: function(attrName)
3026 {
3027 if (this._removedAttributes && this._removedAttributes.has(attrName)) {
3028 this._removedAttributes.delete(attrName);
3029 --this._removedAttributeCount;
3030 }
3031 if (!this._modifiedAttributes)
3032 this._modifiedAttributes = /** @type {!Set.<string>} */ (new Set());
3033 this._modifiedAttributes.add(attrName);
3034 },
3035
3036 /**
3037 * @param {string} attrName
3038 */
3039 attributeRemoved: function(attrName)
3040 {
3041 if (this._modifiedAttributes && this._modifiedAttributes.has(attrName))
3042 this._modifiedAttributes.delete(attrName);
3043 if (!this._removedAttributes)
3044 this._removedAttributes = /** @type {!Set.<string>} */ (new Set());
3045 this._removedAttributes.add(attrName);
3046 ++this._removedAttributeCount;
3047 },
3048
3049 /**
3050 * @param {!WebInspector.DOMNode} node
3051 */
3052 nodeInserted: function(node)
3053 {
3054 if (!this._insertedNodes)
3055 this._insertedNodes = /** @type {!Set.<!WebInspector.DOMNode>} */ (n ew Set());
3056 this._insertedNodes.add(/** @type {!WebInspector.DOMNode} */ (node));
3057 },
3058
3059 charDataModified: function()
3060 {
3061 this._charDataModified = true;
3062 },
3063
3064 childrenModified: function()
3065 {
3066 this._hasChangedChildren = true;
3067 },
3068
3069 /**
3070 * @param {string} attributeName
3071 * @return {boolean}
3072 */
3073 isAttributeModified: function(attributeName)
3074 {
3075 return this._modifiedAttributes && this._modifiedAttributes.has(attribut eName);
3076 },
3077
3078 /**
3079 * @return {boolean}
3080 */
3081 hasRemovedAttributes: function()
3082 {
3083 return !!this._removedAttributeCount;
3084 },
3085
3086 /**
3087 * @return {boolean}
3088 */
3089 hasInsertedNodes: function()
3090 {
3091 return !!this._insertedNodes && !!this._insertedNodes.size;
3092 },
3093
3094 /**
3095 * @return {boolean}
3096 */
3097 isCharDataModified: function()
3098 {
3099 return !!this._charDataModified;
3100 },
3101
3102 /**
3103 * @return {boolean}
3104 */
3105 isNodeInserted: function(node)
3106 {
3107 return !!this._insertedNodes && this._insertedNodes.has(node);
3108 },
3109
3110 /**
3111 * @return {boolean}
3112 */
3113 hasChangedChildren: function()
3114 {
3115 return !!this._hasChangedChildren;
3116 }
3117 }
3118
3119 /**
3120 * @enum {number}
3121 */
3122 WebInspector.ElementsTreeUpdater.UpdateInfo.ChangeType = {
pfeldman 2014/11/10 15:38:20 remove
apavlov 2014/11/10 16:07:37 Done.
3123 NoChange: 0,
3124 AttrModified: 1,
3125 AttrRemoved: 2,
3126 ChildrenModified: 3,
3127 NodeInserted: 4
3128 }
3129
3130 /**
3131 * @constructor
2935 * @implements {WebInspector.Renderer} 3132 * @implements {WebInspector.Renderer}
2936 */ 3133 */
2937 WebInspector.ElementsTreeOutline.Renderer = function() 3134 WebInspector.ElementsTreeOutline.Renderer = function()
2938 { 3135 {
2939 } 3136 }
2940 3137
2941 WebInspector.ElementsTreeOutline.Renderer.prototype = { 3138 WebInspector.ElementsTreeOutline.Renderer.prototype = {
2942 /** 3139 /**
2943 * @param {!Object} object 3140 * @param {!Object} object
2944 * @return {!Promise.<!Element>} 3141 * @return {!Promise.<!Element>}
(...skipping 30 matching lines...) Expand all
2975 treeOutline.rootDOMNode = node; 3172 treeOutline.rootDOMNode = node;
2976 if (!treeOutline.children[0].hasChildren) 3173 if (!treeOutline.children[0].hasChildren)
2977 treeOutline._element.classList.add("single-node"); 3174 treeOutline._element.classList.add("single-node");
2978 treeOutline.setVisible(true); 3175 treeOutline.setVisible(true);
2979 treeOutline.element.treeElementForTest = treeOutline.children[0] ; 3176 treeOutline.element.treeElementForTest = treeOutline.children[0] ;
2980 resolve(treeOutline.element); 3177 resolve(treeOutline.element);
2981 } 3178 }
2982 } 3179 }
2983 } 3180 }
2984 } 3181 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/common/Settings.js ('k') | Source/devtools/front_end/elements/elementsTreeOutline.css » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698