| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 | |
| 5 /** | 4 /** |
| 6 * @constructor | |
| 7 * @extends {WebInspector.Widget} | |
| 8 * @implements {WebInspector.Searchable} | 5 * @implements {WebInspector.Searchable} |
| 9 * @param {!Document} parsedXML | 6 * @unrestricted |
| 10 */ | 7 */ |
| 11 WebInspector.XMLView = function(parsedXML) | 8 WebInspector.XMLView = class extends WebInspector.Widget { |
| 12 { | 9 /** |
| 13 WebInspector.Widget.call(this, true); | 10 * @param {!Document} parsedXML |
| 14 this.registerRequiredCSS("network/xmlView.css"); | 11 */ |
| 15 this.contentElement.classList.add("shadow-xml-view", "source-code"); | 12 constructor(parsedXML) { |
| 13 super(true); |
| 14 this.registerRequiredCSS('network/xmlView.css'); |
| 15 this.contentElement.classList.add('shadow-xml-view', 'source-code'); |
| 16 this._treeOutline = new TreeOutlineInShadow(); | 16 this._treeOutline = new TreeOutlineInShadow(); |
| 17 this._treeOutline.registerRequiredCSS("network/xmlTree.css"); | 17 this._treeOutline.registerRequiredCSS('network/xmlTree.css'); |
| 18 this.contentElement.appendChild(this._treeOutline.element); | 18 this.contentElement.appendChild(this._treeOutline.element); |
| 19 | 19 |
| 20 /** @type {?WebInspector.SearchableView} */ | 20 /** @type {?WebInspector.SearchableView} */ |
| 21 this._searchableView; | 21 this._searchableView; |
| 22 /** @type {number} */ | 22 /** @type {number} */ |
| 23 this._currentSearchFocusIndex = 0; | 23 this._currentSearchFocusIndex = 0; |
| 24 /** @type {!Array.<!TreeElement>} */ | 24 /** @type {!Array.<!TreeElement>} */ |
| 25 this._currentSearchTreeElements = []; | 25 this._currentSearchTreeElements = []; |
| 26 /** @type {?WebInspector.SearchableView.SearchConfig} */ | 26 /** @type {?WebInspector.SearchableView.SearchConfig} */ |
| 27 this._searchConfig; | 27 this._searchConfig; |
| 28 | 28 |
| 29 WebInspector.XMLView.Node.populate(this._treeOutline, parsedXML, this); | 29 WebInspector.XMLView.Node.populate(this._treeOutline, parsedXML, this); |
| 30 }; | 30 } |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * @param {!Document} parsedXML | 33 * @param {!Document} parsedXML |
| 34 * @return {!WebInspector.SearchableView} | 34 * @return {!WebInspector.SearchableView} |
| 35 */ | 35 */ |
| 36 WebInspector.XMLView.createSearchableView = function(parsedXML) | 36 static createSearchableView(parsedXML) { |
| 37 { | |
| 38 var xmlView = new WebInspector.XMLView(parsedXML); | 37 var xmlView = new WebInspector.XMLView(parsedXML); |
| 39 var searchableView = new WebInspector.SearchableView(xmlView); | 38 var searchableView = new WebInspector.SearchableView(xmlView); |
| 40 searchableView.setPlaceholder(WebInspector.UIString("Find")); | 39 searchableView.setPlaceholder(WebInspector.UIString('Find')); |
| 41 xmlView._searchableView = searchableView; | 40 xmlView._searchableView = searchableView; |
| 42 xmlView.show(searchableView.element); | 41 xmlView.show(searchableView.element); |
| 43 xmlView.contentElement.setAttribute("tabIndex", 0); | 42 xmlView.contentElement.setAttribute('tabIndex', 0); |
| 44 return searchableView; | 43 return searchableView; |
| 45 }; | 44 } |
| 46 | 45 |
| 47 /** | 46 /** |
| 48 * @param {string} text | 47 * @param {string} text |
| 49 * @param {string} mimeType | 48 * @param {string} mimeType |
| 50 * @return {?Document} | 49 * @return {?Document} |
| 51 */ | 50 */ |
| 52 WebInspector.XMLView.parseXML = function(text, mimeType) | 51 static parseXML(text, mimeType) { |
| 53 { | |
| 54 var parsedXML; | 52 var parsedXML; |
| 55 try { | 53 try { |
| 56 parsedXML = (new DOMParser()).parseFromString(text, mimeType); | 54 parsedXML = (new DOMParser()).parseFromString(text, mimeType); |
| 57 } catch (e) { | 55 } catch (e) { |
| 58 return null; | 56 return null; |
| 59 } | 57 } |
| 60 if (parsedXML.body) | 58 if (parsedXML.body) |
| 61 return null; | 59 return null; |
| 62 return parsedXML; | 60 return parsedXML; |
| 61 } |
| 62 |
| 63 /** |
| 64 * @param {number} index |
| 65 * @param {boolean} shouldJump |
| 66 */ |
| 67 _jumpToMatch(index, shouldJump) { |
| 68 if (!this._searchConfig) |
| 69 return; |
| 70 var regex = this._searchConfig.toSearchRegex(true); |
| 71 var previousFocusElement = this._currentSearchTreeElements[this._currentSear
chFocusIndex]; |
| 72 if (previousFocusElement) |
| 73 previousFocusElement.setSearchRegex(regex); |
| 74 |
| 75 var newFocusElement = this._currentSearchTreeElements[index]; |
| 76 if (newFocusElement) { |
| 77 this._updateSearchIndex(index); |
| 78 if (shouldJump) |
| 79 newFocusElement.reveal(true); |
| 80 newFocusElement.setSearchRegex(regex, WebInspector.highlightedCurrentSearc
hResultClassName); |
| 81 } else { |
| 82 this._updateSearchIndex(0); |
| 83 } |
| 84 } |
| 85 |
| 86 /** |
| 87 * @param {number} count |
| 88 */ |
| 89 _updateSearchCount(count) { |
| 90 if (!this._searchableView) |
| 91 return; |
| 92 this._searchableView.updateSearchMatchesCount(count); |
| 93 } |
| 94 |
| 95 /** |
| 96 * @param {number} index |
| 97 */ |
| 98 _updateSearchIndex(index) { |
| 99 this._currentSearchFocusIndex = index; |
| 100 if (!this._searchableView) |
| 101 return; |
| 102 this._searchableView.updateCurrentMatchIndex(index); |
| 103 } |
| 104 |
| 105 /** |
| 106 * @param {boolean} shouldJump |
| 107 * @param {boolean=} jumpBackwards |
| 108 */ |
| 109 _innerPerformSearch(shouldJump, jumpBackwards) { |
| 110 if (!this._searchConfig) |
| 111 return; |
| 112 var newIndex = this._currentSearchFocusIndex; |
| 113 var previousSearchFocusElement = this._currentSearchTreeElements[newIndex]; |
| 114 this._innerSearchCanceled(); |
| 115 this._currentSearchTreeElements = []; |
| 116 var regex = this._searchConfig.toSearchRegex(true); |
| 117 |
| 118 for (var element = this._treeOutline.rootElement(); element; element = eleme
nt.traverseNextTreeElement(false)) { |
| 119 if (!(element instanceof WebInspector.XMLView.Node)) |
| 120 continue; |
| 121 var hasMatch = element.setSearchRegex(regex); |
| 122 if (hasMatch) |
| 123 this._currentSearchTreeElements.push(element); |
| 124 if (previousSearchFocusElement === element) { |
| 125 var currentIndex = this._currentSearchTreeElements.length - 1; |
| 126 if (hasMatch || jumpBackwards) |
| 127 newIndex = currentIndex; |
| 128 else |
| 129 newIndex = currentIndex + 1; |
| 130 } |
| 131 } |
| 132 this._updateSearchCount(this._currentSearchTreeElements.length); |
| 133 |
| 134 if (!this._currentSearchTreeElements.length) { |
| 135 this._updateSearchIndex(0); |
| 136 return; |
| 137 } |
| 138 newIndex = mod(newIndex, this._currentSearchTreeElements.length); |
| 139 |
| 140 this._jumpToMatch(newIndex, shouldJump); |
| 141 } |
| 142 |
| 143 _innerSearchCanceled() { |
| 144 for (var element = this._treeOutline.rootElement(); element; element = eleme
nt.traverseNextTreeElement(false)) { |
| 145 if (!(element instanceof WebInspector.XMLView.Node)) |
| 146 continue; |
| 147 element.revertHighlightChanges(); |
| 148 } |
| 149 this._updateSearchCount(0); |
| 150 this._updateSearchIndex(0); |
| 151 } |
| 152 |
| 153 /** |
| 154 * @override |
| 155 */ |
| 156 searchCanceled() { |
| 157 this._searchConfig = null; |
| 158 this._currentSearchTreeElements = []; |
| 159 this._innerSearchCanceled(); |
| 160 } |
| 161 |
| 162 /** |
| 163 * @override |
| 164 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig |
| 165 * @param {boolean} shouldJump |
| 166 * @param {boolean=} jumpBackwards |
| 167 */ |
| 168 performSearch(searchConfig, shouldJump, jumpBackwards) { |
| 169 this._searchConfig = searchConfig; |
| 170 this._innerPerformSearch(shouldJump, jumpBackwards); |
| 171 } |
| 172 |
| 173 /** |
| 174 * @override |
| 175 */ |
| 176 jumpToNextSearchResult() { |
| 177 if (!this._currentSearchTreeElements.length) |
| 178 return; |
| 179 |
| 180 var newIndex = mod(this._currentSearchFocusIndex + 1, this._currentSearchTre
eElements.length); |
| 181 this._jumpToMatch(newIndex, true); |
| 182 } |
| 183 |
| 184 /** |
| 185 * @override |
| 186 */ |
| 187 jumpToPreviousSearchResult() { |
| 188 if (!this._currentSearchTreeElements.length) |
| 189 return; |
| 190 |
| 191 var newIndex = mod(this._currentSearchFocusIndex - 1, this._currentSearchTre
eElements.length); |
| 192 this._jumpToMatch(newIndex, true); |
| 193 } |
| 194 |
| 195 /** |
| 196 * @override |
| 197 * @return {boolean} |
| 198 */ |
| 199 supportsCaseSensitiveSearch() { |
| 200 return true; |
| 201 } |
| 202 |
| 203 /** |
| 204 * @override |
| 205 * @return {boolean} |
| 206 */ |
| 207 supportsRegexSearch() { |
| 208 return true; |
| 209 } |
| 63 }; | 210 }; |
| 64 | 211 |
| 65 WebInspector.XMLView.prototype = { | |
| 66 /** | |
| 67 * @param {number} index | |
| 68 * @param {boolean} shouldJump | |
| 69 */ | |
| 70 _jumpToMatch: function(index, shouldJump) | |
| 71 { | |
| 72 if (!this._searchConfig) | |
| 73 return; | |
| 74 var regex = this._searchConfig.toSearchRegex(true); | |
| 75 var previousFocusElement = this._currentSearchTreeElements[this._current
SearchFocusIndex]; | |
| 76 if (previousFocusElement) | |
| 77 previousFocusElement.setSearchRegex(regex); | |
| 78 | |
| 79 var newFocusElement = this._currentSearchTreeElements[index]; | |
| 80 if (newFocusElement) { | |
| 81 this._updateSearchIndex(index); | |
| 82 if (shouldJump) | |
| 83 newFocusElement.reveal(true); | |
| 84 newFocusElement.setSearchRegex(regex, WebInspector.highlightedCurren
tSearchResultClassName); | |
| 85 } else { | |
| 86 this._updateSearchIndex(0); | |
| 87 } | |
| 88 }, | |
| 89 | |
| 90 /** | |
| 91 * @param {number} count | |
| 92 */ | |
| 93 _updateSearchCount: function(count) | |
| 94 { | |
| 95 if (!this._searchableView) | |
| 96 return; | |
| 97 this._searchableView.updateSearchMatchesCount(count); | |
| 98 }, | |
| 99 | |
| 100 /** | |
| 101 * @param {number} index | |
| 102 */ | |
| 103 _updateSearchIndex: function(index) | |
| 104 { | |
| 105 this._currentSearchFocusIndex = index; | |
| 106 if (!this._searchableView) | |
| 107 return; | |
| 108 this._searchableView.updateCurrentMatchIndex(index); | |
| 109 }, | |
| 110 | |
| 111 /** | |
| 112 * @param {boolean} shouldJump | |
| 113 * @param {boolean=} jumpBackwards | |
| 114 */ | |
| 115 _innerPerformSearch: function(shouldJump, jumpBackwards) | |
| 116 { | |
| 117 if (!this._searchConfig) | |
| 118 return; | |
| 119 var newIndex = this._currentSearchFocusIndex; | |
| 120 var previousSearchFocusElement = this._currentSearchTreeElements[newInde
x]; | |
| 121 this._innerSearchCanceled(); | |
| 122 this._currentSearchTreeElements = []; | |
| 123 var regex = this._searchConfig.toSearchRegex(true); | |
| 124 | |
| 125 for (var element = this._treeOutline.rootElement(); element; element = e
lement.traverseNextTreeElement(false)) { | |
| 126 if (!(element instanceof WebInspector.XMLView.Node)) | |
| 127 continue; | |
| 128 var hasMatch = element.setSearchRegex(regex); | |
| 129 if (hasMatch) | |
| 130 this._currentSearchTreeElements.push(element); | |
| 131 if (previousSearchFocusElement === element) { | |
| 132 var currentIndex = this._currentSearchTreeElements.length - 1; | |
| 133 if (hasMatch || jumpBackwards) | |
| 134 newIndex = currentIndex; | |
| 135 else | |
| 136 newIndex = currentIndex + 1; | |
| 137 } | |
| 138 } | |
| 139 this._updateSearchCount(this._currentSearchTreeElements.length); | |
| 140 | |
| 141 if (!this._currentSearchTreeElements.length) { | |
| 142 this._updateSearchIndex(0); | |
| 143 return; | |
| 144 } | |
| 145 newIndex = mod(newIndex, this._currentSearchTreeElements.length); | |
| 146 | |
| 147 this._jumpToMatch(newIndex, shouldJump); | |
| 148 }, | |
| 149 | |
| 150 _innerSearchCanceled: function() | |
| 151 { | |
| 152 for (var element = this._treeOutline.rootElement(); element; element = e
lement.traverseNextTreeElement(false)) { | |
| 153 if (!(element instanceof WebInspector.XMLView.Node)) | |
| 154 continue; | |
| 155 element.revertHighlightChanges(); | |
| 156 } | |
| 157 this._updateSearchCount(0); | |
| 158 this._updateSearchIndex(0); | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * @override | |
| 163 */ | |
| 164 searchCanceled: function() | |
| 165 { | |
| 166 this._searchConfig = null; | |
| 167 this._currentSearchTreeElements = []; | |
| 168 this._innerSearchCanceled(); | |
| 169 }, | |
| 170 | |
| 171 /** | |
| 172 * @override | |
| 173 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig | |
| 174 * @param {boolean} shouldJump | |
| 175 * @param {boolean=} jumpBackwards | |
| 176 */ | |
| 177 performSearch: function(searchConfig, shouldJump, jumpBackwards) | |
| 178 { | |
| 179 this._searchConfig = searchConfig; | |
| 180 this._innerPerformSearch(shouldJump, jumpBackwards); | |
| 181 }, | |
| 182 | |
| 183 /** | |
| 184 * @override | |
| 185 */ | |
| 186 jumpToNextSearchResult: function() | |
| 187 { | |
| 188 if (!this._currentSearchTreeElements.length) | |
| 189 return; | |
| 190 | |
| 191 var newIndex = mod(this._currentSearchFocusIndex + 1, this._currentSearc
hTreeElements.length); | |
| 192 this._jumpToMatch(newIndex, true); | |
| 193 }, | |
| 194 | |
| 195 /** | |
| 196 * @override | |
| 197 */ | |
| 198 jumpToPreviousSearchResult: function() | |
| 199 { | |
| 200 if (!this._currentSearchTreeElements.length) | |
| 201 return; | |
| 202 | |
| 203 var newIndex = mod(this._currentSearchFocusIndex - 1, this._currentSearc
hTreeElements.length); | |
| 204 this._jumpToMatch(newIndex, true); | |
| 205 }, | |
| 206 | |
| 207 /** | |
| 208 * @override | |
| 209 * @return {boolean} | |
| 210 */ | |
| 211 supportsCaseSensitiveSearch: function() | |
| 212 { | |
| 213 return true; | |
| 214 }, | |
| 215 | |
| 216 /** | |
| 217 * @override | |
| 218 * @return {boolean} | |
| 219 */ | |
| 220 supportsRegexSearch: function() | |
| 221 { | |
| 222 return true; | |
| 223 }, | |
| 224 | |
| 225 __proto__: WebInspector.Widget.prototype | |
| 226 }; | |
| 227 | 212 |
| 228 /** | 213 /** |
| 229 * @constructor | 214 * @unrestricted |
| 230 * @extends {TreeElement} | |
| 231 * @param {!Node} node | |
| 232 * @param {boolean} closeTag | |
| 233 * @param {!WebInspector.XMLView} xmlView | |
| 234 */ | 215 */ |
| 235 WebInspector.XMLView.Node = function(node, closeTag, xmlView) | 216 WebInspector.XMLView.Node = class extends TreeElement { |
| 236 { | 217 /** |
| 237 TreeElement.call(this, "", !closeTag && !!node.childElementCount); | 218 * @param {!Node} node |
| 219 * @param {boolean} closeTag |
| 220 * @param {!WebInspector.XMLView} xmlView |
| 221 */ |
| 222 constructor(node, closeTag, xmlView) { |
| 223 super('', !closeTag && !!node.childElementCount); |
| 238 this._node = node; | 224 this._node = node; |
| 239 this._closeTag = closeTag; | 225 this._closeTag = closeTag; |
| 240 this.selectable = false; | 226 this.selectable = false; |
| 241 /** @type {!Array.<!Object>} */ | 227 /** @type {!Array.<!Object>} */ |
| 242 this._highlightChanges = []; | 228 this._highlightChanges = []; |
| 243 this._xmlView = xmlView; | 229 this._xmlView = xmlView; |
| 244 this._updateTitle(); | 230 this._updateTitle(); |
| 231 } |
| 232 |
| 233 /** |
| 234 * @param {!TreeOutline|!TreeElement} root |
| 235 * @param {!Node} xmlNode |
| 236 * @param {!WebInspector.XMLView} xmlView |
| 237 */ |
| 238 static populate(root, xmlNode, xmlView) { |
| 239 var node = xmlNode.firstChild; |
| 240 while (node) { |
| 241 var currentNode = node; |
| 242 node = node.nextSibling; |
| 243 var nodeType = currentNode.nodeType; |
| 244 // ignore empty TEXT |
| 245 if (nodeType === 3 && currentNode.nodeValue.match(/\s+/)) |
| 246 continue; |
| 247 // ignore ATTRIBUTE, ENTITY_REFERENCE, ENTITY, DOCUMENT, DOCUMENT_TYPE, DO
CUMENT_FRAGMENT, NOTATION |
| 248 if ((nodeType !== 1) && (nodeType !== 3) && (nodeType !== 4) && (nodeType
!== 7) && (nodeType !== 8)) |
| 249 continue; |
| 250 root.appendChild(new WebInspector.XMLView.Node(currentNode, false, xmlView
)); |
| 251 } |
| 252 } |
| 253 |
| 254 /** |
| 255 * @param {?RegExp} regex |
| 256 * @param {string=} additionalCssClassName |
| 257 * @return {boolean} |
| 258 */ |
| 259 setSearchRegex(regex, additionalCssClassName) { |
| 260 this.revertHighlightChanges(); |
| 261 if (!regex) |
| 262 return false; |
| 263 if (this._closeTag && this.parent && !this.parent.expanded) |
| 264 return false; |
| 265 regex.lastIndex = 0; |
| 266 var cssClasses = WebInspector.highlightedSearchResultClassName; |
| 267 if (additionalCssClassName) |
| 268 cssClasses += ' ' + additionalCssClassName; |
| 269 var content = this.listItemElement.textContent.replace(/\xA0/g, ' '); |
| 270 var match = regex.exec(content); |
| 271 var ranges = []; |
| 272 while (match) { |
| 273 ranges.push(new WebInspector.SourceRange(match.index, match[0].length)); |
| 274 match = regex.exec(content); |
| 275 } |
| 276 if (ranges.length) |
| 277 WebInspector.highlightRangesWithStyleClass(this.listItemElement, ranges, c
ssClasses, this._highlightChanges); |
| 278 return !!this._highlightChanges.length; |
| 279 } |
| 280 |
| 281 revertHighlightChanges() { |
| 282 WebInspector.revertDomChanges(this._highlightChanges); |
| 283 this._highlightChanges = []; |
| 284 } |
| 285 |
| 286 _updateTitle() { |
| 287 var node = this._node; |
| 288 switch (node.nodeType) { |
| 289 case 1: // ELEMENT |
| 290 var tag = node.tagName; |
| 291 if (this._closeTag) { |
| 292 this._setTitle(['</' + tag + '>', 'shadow-xml-view-tag']); |
| 293 return; |
| 294 } |
| 295 var titleItems = ['<' + tag, 'shadow-xml-view-tag']; |
| 296 var attributes = node.attributes; |
| 297 for (var i = 0; i < attributes.length; ++i) { |
| 298 var attributeNode = attributes.item(i); |
| 299 titleItems.push( |
| 300 '\u00a0', 'shadow-xml-view-tag', attributeNode.name, 'shadow-xml-v
iew-attribute-name', '="', |
| 301 'shadow-xml-view-tag', attributeNode.value, 'shadow-xml-view-attri
bute-value', '"', |
| 302 'shadow-xml-view-tag'); |
| 303 } |
| 304 if (!this.expanded) { |
| 305 if (node.childElementCount) { |
| 306 titleItems.push( |
| 307 '>', 'shadow-xml-view-tag', '\u2026', 'shadow-xml-view-comment',
'</' + tag, 'shadow-xml-view-tag'); |
| 308 } else if (this._node.textContent) { |
| 309 titleItems.push( |
| 310 '>', 'shadow-xml-view-tag', node.textContent, 'shadow-xml-view-t
ext', '</' + tag, |
| 311 'shadow-xml-view-tag'); |
| 312 } else { |
| 313 titleItems.push(' /', 'shadow-xml-view-tag'); |
| 314 } |
| 315 } |
| 316 titleItems.push('>', 'shadow-xml-view-tag'); |
| 317 this._setTitle(titleItems); |
| 318 return; |
| 319 case 3: // TEXT |
| 320 this._setTitle([node.nodeValue, 'shadow-xml-view-text']); |
| 321 return; |
| 322 case 4: // CDATA |
| 323 this._setTitle([ |
| 324 '<![CDATA[', 'shadow-xml-view-cdata', node.nodeValue, 'shadow-xml-view
-text', ']]>', 'shadow-xml-view-cdata' |
| 325 ]); |
| 326 return; |
| 327 case 7: // PROCESSING_INSTRUCTION |
| 328 this._setTitle(['<?' + node.nodeName + ' ' + node.nodeValue + '?>', 'sha
dow-xml-view-processing-instruction']); |
| 329 return; |
| 330 case 8: // COMMENT |
| 331 this._setTitle(['<!--' + node.nodeValue + '-->', 'shadow-xml-view-commen
t']); |
| 332 return; |
| 333 } |
| 334 } |
| 335 |
| 336 /** |
| 337 * @param {!Array.<string>} items |
| 338 */ |
| 339 _setTitle(items) { |
| 340 var titleFragment = createDocumentFragment(); |
| 341 for (var i = 0; i < items.length; i += 2) |
| 342 titleFragment.createChild('span', items[i + 1]).textContent = items[i]; |
| 343 this.title = titleFragment; |
| 344 this._xmlView._innerPerformSearch(false, false); |
| 345 } |
| 346 |
| 347 /** |
| 348 * @override |
| 349 */ |
| 350 onattach() { |
| 351 this.listItemElement.classList.toggle('shadow-xml-view-close-tag', this._clo
seTag); |
| 352 } |
| 353 |
| 354 /** |
| 355 * @override |
| 356 */ |
| 357 onexpand() { |
| 358 this._updateTitle(); |
| 359 } |
| 360 |
| 361 /** |
| 362 * @override |
| 363 */ |
| 364 oncollapse() { |
| 365 this._updateTitle(); |
| 366 } |
| 367 |
| 368 /** |
| 369 * @override |
| 370 */ |
| 371 onpopulate() { |
| 372 WebInspector.XMLView.Node.populate(this, this._node, this._xmlView); |
| 373 this.appendChild(new WebInspector.XMLView.Node(this._node, true, this._xmlVi
ew)); |
| 374 } |
| 245 }; | 375 }; |
| 246 | 376 |
| 247 /** | |
| 248 * @param {!TreeOutline|!TreeElement} root | |
| 249 * @param {!Node} xmlNode | |
| 250 * @param {!WebInspector.XMLView} xmlView | |
| 251 */ | |
| 252 WebInspector.XMLView.Node.populate = function(root, xmlNode, xmlView) | |
| 253 { | |
| 254 var node = xmlNode.firstChild; | |
| 255 while (node) { | |
| 256 var currentNode = node; | |
| 257 node = node.nextSibling; | |
| 258 var nodeType = currentNode.nodeType; | |
| 259 // ignore empty TEXT | |
| 260 if (nodeType === 3 && currentNode.nodeValue.match(/\s+/)) | |
| 261 continue; | |
| 262 // ignore ATTRIBUTE, ENTITY_REFERENCE, ENTITY, DOCUMENT, DOCUMENT_TYPE,
DOCUMENT_FRAGMENT, NOTATION | |
| 263 if ((nodeType !== 1) && (nodeType !== 3) && (nodeType !== 4) && (nodeTyp
e !== 7) && (nodeType !== 8)) | |
| 264 continue; | |
| 265 root.appendChild(new WebInspector.XMLView.Node(currentNode, false, xmlVi
ew)); | |
| 266 } | |
| 267 }; | |
| 268 | 377 |
| 269 WebInspector.XMLView.Node.prototype = { | |
| 270 /** | |
| 271 * @param {?RegExp} regex | |
| 272 * @param {string=} additionalCssClassName | |
| 273 * @return {boolean} | |
| 274 */ | |
| 275 setSearchRegex: function(regex, additionalCssClassName) | |
| 276 { | |
| 277 this.revertHighlightChanges(); | |
| 278 if (!regex) | |
| 279 return false; | |
| 280 if (this._closeTag && this.parent && !this.parent.expanded) | |
| 281 return false; | |
| 282 regex.lastIndex = 0; | |
| 283 var cssClasses = WebInspector.highlightedSearchResultClassName; | |
| 284 if (additionalCssClassName) | |
| 285 cssClasses += " " + additionalCssClassName; | |
| 286 var content = this.listItemElement.textContent.replace(/\xA0/g, " "); | |
| 287 var match = regex.exec(content); | |
| 288 var ranges = []; | |
| 289 while (match) { | |
| 290 ranges.push(new WebInspector.SourceRange(match.index, match[0].lengt
h)); | |
| 291 match = regex.exec(content); | |
| 292 } | |
| 293 if (ranges.length) | |
| 294 WebInspector.highlightRangesWithStyleClass(this.listItemElement, ran
ges, cssClasses, this._highlightChanges); | |
| 295 return !!this._highlightChanges.length; | |
| 296 }, | |
| 297 | |
| 298 revertHighlightChanges: function() | |
| 299 { | |
| 300 WebInspector.revertDomChanges(this._highlightChanges); | |
| 301 this._highlightChanges = []; | |
| 302 }, | |
| 303 | |
| 304 _updateTitle: function() | |
| 305 { | |
| 306 var node = this._node; | |
| 307 switch (node.nodeType) { | |
| 308 case 1: // ELEMENT | |
| 309 var tag = node.tagName; | |
| 310 if (this._closeTag) { | |
| 311 this._setTitle(["</" + tag + ">", "shadow-xml-view-tag"]); | |
| 312 return; | |
| 313 } | |
| 314 var titleItems = ["<" + tag, "shadow-xml-view-tag"]; | |
| 315 var attributes = node.attributes; | |
| 316 for (var i = 0; i < attributes.length; ++i) { | |
| 317 var attributeNode = attributes.item(i); | |
| 318 titleItems.push( | |
| 319 "\u00a0", "shadow-xml-view-tag", | |
| 320 attributeNode.name, "shadow-xml-view-attribute-name", | |
| 321 "=\"", "shadow-xml-view-tag", | |
| 322 attributeNode.value, "shadow-xml-view-attribute-value", | |
| 323 "\"", "shadow-xml-view-tag"); | |
| 324 } | |
| 325 if (!this.expanded) { | |
| 326 if (node.childElementCount) { | |
| 327 titleItems.push( | |
| 328 ">", "shadow-xml-view-tag", | |
| 329 "\u2026", "shadow-xml-view-comment", | |
| 330 "</" + tag, "shadow-xml-view-tag"); | |
| 331 } else if (this._node.textContent) { | |
| 332 titleItems.push( | |
| 333 ">", "shadow-xml-view-tag", | |
| 334 node.textContent, "shadow-xml-view-text", | |
| 335 "</" + tag, "shadow-xml-view-tag"); | |
| 336 } else { | |
| 337 titleItems.push(" /", "shadow-xml-view-tag"); | |
| 338 } | |
| 339 } | |
| 340 titleItems.push(">", "shadow-xml-view-tag"); | |
| 341 this._setTitle(titleItems); | |
| 342 return; | |
| 343 case 3: // TEXT | |
| 344 this._setTitle([node.nodeValue, "shadow-xml-view-text"]); | |
| 345 return; | |
| 346 case 4: // CDATA | |
| 347 this._setTitle([ | |
| 348 "<![CDATA[", "shadow-xml-view-cdata", | |
| 349 node.nodeValue, "shadow-xml-view-text", | |
| 350 "]]>", "shadow-xml-view-cdata"]); | |
| 351 return; | |
| 352 case 7: // PROCESSING_INSTRUCTION | |
| 353 this._setTitle(["<?" + node.nodeName + " " + node.nodeValue + "?>",
"shadow-xml-view-processing-instruction"]); | |
| 354 return; | |
| 355 case 8: // COMMENT | |
| 356 this._setTitle(["<!--" + node.nodeValue + "-->", "shadow-xml-view-co
mment"]); | |
| 357 return; | |
| 358 } | |
| 359 }, | |
| 360 | |
| 361 /** | |
| 362 * @param {!Array.<string>} items | |
| 363 */ | |
| 364 _setTitle: function(items) | |
| 365 { | |
| 366 var titleFragment = createDocumentFragment(); | |
| 367 for (var i = 0; i < items.length; i += 2) | |
| 368 titleFragment.createChild("span", items[i + 1]).textContent = items[
i]; | |
| 369 this.title = titleFragment; | |
| 370 this._xmlView._innerPerformSearch(false, false); | |
| 371 }, | |
| 372 | |
| 373 onattach: function() | |
| 374 { | |
| 375 this.listItemElement.classList.toggle("shadow-xml-view-close-tag", this.
_closeTag); | |
| 376 }, | |
| 377 | |
| 378 onexpand: function() | |
| 379 { | |
| 380 this._updateTitle(); | |
| 381 }, | |
| 382 | |
| 383 oncollapse: function() | |
| 384 { | |
| 385 this._updateTitle(); | |
| 386 }, | |
| 387 | |
| 388 onpopulate: function() | |
| 389 { | |
| 390 WebInspector.XMLView.Node.populate(this, this._node, this._xmlView); | |
| 391 this.appendChild(new WebInspector.XMLView.Node(this._node, true, this._x
mlView)); | |
| 392 }, | |
| 393 | |
| 394 __proto__: TreeElement.prototype | |
| 395 }; | |
| OLD | NEW |