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

Side by Side Diff: Source/core/xml/DocumentXMLTreeViewer.js

Issue 479753003: Transform XML tree viewer to blink-in-js implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Patch for landing! Created 6 years, 3 months 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 "use strict";
6
7 installClass("Document", function(DocumentPrototype) {
8 // FIXME: The stylesheet should be defined in a separate css file
9 var styleSheet = [
10 "div.header {",
11 " border-bottom: 2px solid black;",
12 " padding-bottom: 5px;",
13 " margin: 10px;",
14 "}",
15 "",
16 "div.collapsible > div.hidden {",
17 " display:none;",
18 "}",
19 "",
20 ".pretty-print {",
21 " margin-top: 1em;",
22 " margin-left: 20px;",
23 " font-family: monospace;",
24 " font-size: 13px;",
25 "}",
26 "",
27 "#webkit-xml-viewer-source-xml {",
28 " display: none;",
29 "}",
30 "",
31 ".collapsible-content {",
32 " margin-left: 1em;",
33 "}",
34 ".comment {",
35 " white-space: pre;",
36 "}",
37 "",
38 ".button {",
39 " -webkit-user-select: none;",
40 " cursor: pointer;",
41 " display: inline-block;",
42 " margin-left: -10px;",
43 " width: 10px;",
44 " background-repeat: no-repeat;",
45 " background-position: left top;",
46 " vertical-align: bottom;",
47 "}",
48 "",
49 ".collapse-button {",
50 " background-image: -webkit-canvas(arrowDown);",
51 " height: 10px;",
52 "}",
53 "",
54 ".expand-button {",
55 " background-image: -webkit-canvas(arrowRight);",
56 " height: 11px;",
57 "}"].join('');
58 var nodeParentPairs = [];
59 var tree;
60
61 function prepareWebKitXMLViewer(noStyleMessage)
62 {
63 var html = createHTMLElement('html');
64 var head = createHTMLElement('head');
65 html.appendChild(head);
66 var style = createHTMLElement('style');
67 style.id = 'xml-viewer-style';
68 style.appendChild(document.createTextNode(styleSheet));
69 head.appendChild(style);
70 var body = createHTMLElement('body');
71 html.appendChild(body);
72 var sourceXML = createHTMLElement('div');
73 sourceXML.id = 'webkit-xml-viewer-source-xml';
74 body.appendChild(sourceXML);
75
76 var child;
77 while (child = document.firstChild) {
78 document.removeChild(child);
79 if (child.nodeType != Node.DOCUMENT_TYPE_NODE)
80 sourceXML.appendChild(child);
81 }
82 document.appendChild(html);
83
84 var header = createHTMLElement('div');
85 body.appendChild(header);
86 header.classList.add('header');
87 var headerSpan = createHTMLElement('span');
88 header.appendChild(headerSpan);
89 headerSpan.textContent = noStyleMessage;
90 header.appendChild(createHTMLElement('br'));
91
92 tree = createHTMLElement('div');
93 body.appendChild(tree);
94 tree.classList.add('pretty-print');
95 window.onload = sourceXMLLoaded;
96 }
97
98 function sourceXMLLoaded()
99 {
100 var sourceXML = document.getElementById('webkit-xml-viewer-source-xml');
101 if (!sourceXML)
102 return; // Stop if some XML tree extension is already processing thi s document
103
104 for (var child = sourceXML.firstChild; child; child = child.nextSibling)
105 nodeParentPairs.push({parentElement: tree, node: child});
106
107 for (var i = 0; i < nodeParentPairs.length; i++)
108 processNode(nodeParentPairs[i].parentElement, nodeParentPairs[i].nod e);
109
110 drawArrows();
111 initButtons();
112
113 return false;
114 }
115
116 // Tree processing.
117
118 function processNode(parentElement, node)
119 {
120 if (!processNode.processorsMap) {
121 processNode.processorsMap = {};
PhistucK 2014/09/02 07:36:45 Perhaps cache processNode.processorsMap instead of
122 processNode.processorsMap[Node.PROCESSING_INSTRUCTION_NODE] = proces sProcessingInstruction;
123 processNode.processorsMap[Node.ELEMENT_NODE] = processElement;
124 processNode.processorsMap[Node.COMMENT_NODE] = processComment;
125 processNode.processorsMap[Node.TEXT_NODE] = processText;
126 processNode.processorsMap[Node.CDATA_SECTION_NODE] = processCDATA;
127 }
128 if (processNode.processorsMap[node.nodeType])
129 processNode.processorsMap[node.nodeType].call(this, parentElement, n ode);
130 }
131
132 function processElement(parentElement, node)
133 {
134 if (!node.firstChild)
135 processEmptyElement(parentElement, node);
136 else {
137 var child = node.firstChild;
138 if (child.nodeType == Node.TEXT_NODE && isShort(child.nodeValue) && !child.nextSibling)
139 processShortTextOnlyElement(parentElement, node);
140 else
141 processComplexElement(parentElement, node);
142 }
143 }
144
145 function processEmptyElement(parentElement, node)
146 {
147 var line = createLine();
148 line.appendChild(createTag(node, false, true));
149 parentElement.appendChild(line);
150 }
151
152 function processShortTextOnlyElement(parentElement, node)
153 {
154 var line = createLine();
155 line.appendChild(createTag(node, false, false));
156 for (var child = node.firstChild; child; child = child.nextSibling)
157 line.appendChild(createText(child.nodeValue));
158 line.appendChild(createTag(node, true, false));
159 parentElement.appendChild(line);
160 }
161
162 function processComplexElement(parentElement, node)
163 {
164 var collapsible = createCollapsible();
165
166 collapsible.expanded.start.appendChild(createTag(node, false, false));
PhistucK 2014/09/02 07:36:45 Same here.
167 for (var child = node.firstChild; child; child = child.nextSibling)
168 nodeParentPairs.push({parentElement: collapsible.expanded.content, n ode: child});
169 collapsible.expanded.end.appendChild(createTag(node, true, false));
170
171 collapsible.collapsed.content.appendChild(createTag(node, false, false)) ;
PhistucK 2014/09/02 07:36:45 Same here.
172 collapsible.collapsed.content.appendChild(createText('...'));
173 collapsible.collapsed.content.appendChild(createTag(node, true, false));
174 parentElement.appendChild(collapsible);
175 }
176
177 function processComment(parentElement, node)
178 {
179 if (isShort(node.nodeValue)) {
180 var line = createLine();
181 line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
182 parentElement.appendChild(line);
183 } else {
184 var collapsible = createCollapsible();
185
186 collapsible.expanded.start.appendChild(createComment('<!--'));
187 collapsible.expanded.content.appendChild(createComment(node.nodeValu e));
188 collapsible.expanded.end.appendChild(createComment('-->'));
189
190 collapsible.collapsed.content.appendChild(createComment('<!--'));
191 collapsible.collapsed.content.appendChild(createComment('...'));
192 collapsible.collapsed.content.appendChild(createComment('-->'));
193 parentElement.appendChild(collapsible);
194 }
195 }
196
197 function processCDATA(parentElement, node)
198 {
199 if (isShort(node.nodeValue)) {
200 var line = createLine();
201 line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>')) ;
202 parentElement.appendChild(line);
203 } else {
204 var collapsible = createCollapsible();
205
206 collapsible.expanded.start.appendChild(createText('<![CDATA['));
207 collapsible.expanded.content.appendChild(createText(node.nodeValue)) ;
208 collapsible.expanded.end.appendChild(createText(']]>'));
209
210 collapsible.collapsed.content.appendChild(createText('<![CDATA['));
211 collapsible.collapsed.content.appendChild(createText('...'));
212 collapsible.collapsed.content.appendChild(createText(']]>'));
213 parentElement.appendChild(collapsible);
214 }
215 }
216
217 function processProcessingInstruction(parentElement, node)
218 {
219 if (isShort(node.nodeValue)) {
220 var line = createLine();
221 line.appendChild(createComment('<?' + node.nodeName + ' ' + node.nod eValue + '?>'));
222 parentElement.appendChild(line);
223 } else {
224 var collapsible = createCollapsible();
225
226 collapsible.expanded.start.appendChild(createComment('<?' + node.nod eName));
227 collapsible.expanded.content.appendChild(createComment(node.nodeValu e));
228 collapsible.expanded.end.appendChild(createComment('?>'));
229
230 collapsible.collapsed.content.appendChild(createComment('<?' + node. nodeName));
231 collapsible.collapsed.content.appendChild(createComment('...'));
232 collapsible.collapsed.content.appendChild(createComment('?>'));
233 parentElement.appendChild(collapsible);
234 }
235 }
236
237 function processText(parentElement, node)
238 {
239 parentElement.appendChild(createText(node.nodeValue));
240 }
241
242 // Processing utils.
243
244 function trim(value)
245 {
246 return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
247 }
248
249 function isShort(value)
250 {
251 return trim(value).length <= 50;
252 }
253
254 // Tree rendering.
255
256 function createHTMLElement(elementName)
257 {
258 return document.createElementNS('http://www.w3.org/1999/xhtml', elementN ame)
259 }
260
261 function createCollapsible()
262 {
263 var collapsible = createHTMLElement('div');
264 collapsible.classList.add('collapsible');
265 collapsible.expanded = createHTMLElement('div');
266 collapsible.expanded.classList.add('expanded');
267 collapsible.appendChild(collapsible.expanded);
268
269 collapsible.expanded.start = createLine();
270 collapsible.expanded.start.appendChild(createCollapseButton());
271 collapsible.expanded.appendChild(collapsible.expanded.start);
272
273 collapsible.expanded.content = createHTMLElement('div');
274 collapsible.expanded.content.classList.add('collapsible-content');
275 collapsible.expanded.appendChild(collapsible.expanded.content);
276
277 collapsible.expanded.end = createLine();
278 collapsible.expanded.appendChild(collapsible.expanded.end);
279
280 collapsible.collapsed = createHTMLElement('div');
281 collapsible.collapsed.classList.add('collapsed');
282 collapsible.collapsed.classList.add('hidden');
283 collapsible.appendChild(collapsible.collapsed);
284 collapsible.collapsed.content = createLine();
285 collapsible.collapsed.content.appendChild(createExpandButton());
286 collapsible.collapsed.appendChild(collapsible.collapsed.content);
287
288 return collapsible;
289 }
290
291 function createButton()
292 {
293 var button = createHTMLElement('span');
294 button.classList.add('button');
295 return button;
296 }
297
298 function createCollapseButton(str)
299 {
300 var button = createButton();
301 button.classList.add('collapse-button');
302 return button;
303 }
304
305 function createExpandButton(str)
306 {
307 var button = createButton();
308 button.classList.add('expand-button');
309 return button;
310 }
311
312 function createComment(commentString)
313 {
314 var comment = createHTMLElement('span');
315 comment.classList.add('comment');
316 comment.classList.add('webkit-html-comment');
317 comment.textContent = commentString;
318 return comment;
319 }
320
321 function createText(value)
322 {
323 var text = createHTMLElement('span');
324 text.textContent = trim(value);
325 text.classList.add('text');
326 return text;
327 }
328
329 function createLine()
330 {
331 var line = createHTMLElement('div');
332 line.classList.add('line');
333 return line;
334 }
335
336 function createTag(node, isClosing, isEmpty)
337 {
338 var tag = createHTMLElement('span');
339 tag.classList.add('webkit-html-tag');
340
341 var stringBeforeAttrs = '<';
342 if (isClosing)
343 stringBeforeAttrs += '/';
344 stringBeforeAttrs += node.nodeName;
345 var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
346 tag.appendChild(textBeforeAttrs);
347
348 if (!isClosing) {
349 for (var i = 0; i < node.attributes.length; i++)
350 tag.appendChild(createAttribute(node.attributes[i]));
351 }
352
353 var stringAfterAttrs = '';
354 if (isEmpty)
355 stringAfterAttrs += '/';
356 stringAfterAttrs += '>';
357 var textAfterAttrs = document.createTextNode(stringAfterAttrs);
358 tag.appendChild(textAfterAttrs);
359
360 return tag;
361 }
362
363 function createAttribute(attributeNode)
364 {
365 var attribute = createHTMLElement('span');
366 attribute.classList.add('webkit-html-attribute');
367
368 var attributeName = createHTMLElement('span');
369 attributeName.classList.add('webkit-html-attribute-name');
370 attributeName.textContent = attributeNode.name;
371
372 var textBefore = document.createTextNode(' ');
373 var textBetween = document.createTextNode('="');
374
375 var attributeValue = createHTMLElement('span');
376 attributeValue.classList.add('webkit-html-attribute-value');
377 attributeValue.textContent = attributeNode.value;
378
379 var textAfter = document.createTextNode('"');
380
381 attribute.appendChild(textBefore);
382 attribute.appendChild(attributeName);
383 attribute.appendChild(textBetween);
384 attribute.appendChild(attributeValue);
385 attribute.appendChild(textAfter);
386 return attribute;
387 }
388
389 // Tree behaviour.
390
391 function drawArrows()
392 {
393 var ctx = document.getCSSCanvasContext("2d", "arrowRight", 10, 11);
394
395 ctx.fillStyle = "rgb(90,90,90)";
396 ctx.beginPath();
397 ctx.moveTo(0, 0);
398 ctx.lineTo(0, 8);
399 ctx.lineTo(7, 4);
400 ctx.lineTo(0, 0);
401 ctx.fill();
402 ctx.closePath();
403
404 var ctx = document.getCSSCanvasContext("2d", "arrowDown", 10, 10);
405
406 ctx.fillStyle = "rgb(90,90,90)";
407 ctx.beginPath();
408 ctx.moveTo(0, 0);
409 ctx.lineTo(8, 0);
410 ctx.lineTo(4, 7);
411 ctx.lineTo(0, 0);
412 ctx.fill();
413 ctx.closePath();
414 }
415
416 function expandFunction(sectionId)
417 {
418 return function()
419 {
420 document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
421 document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
422 };
423 }
424
425 function collapseFunction(sectionId)
426 {
427 return function()
428 {
429 document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
430 document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
431 };
432 }
433
434 function initButtons()
435 {
436 var sections = document.querySelectorAll('.collapsible');
437 for (var i = 0; i < sections.length; i++) {
438 var sectionId = 'collapsible' + i;
439 sections[i].id = sectionId;
440
441 var expandedPart = sections[i].querySelector('#' + sectionId + ' > . expanded');
442 var collapseButton = expandedPart.querySelector('.collapse-button');
443 collapseButton.onclick = collapseFunction(sectionId);
444 collapseButton.onmousedown = handleButtonMouseDown;
445
446 var collapsedPart = sections[i].querySelector('#' + sectionId + ' > .collapsed');
447 var expandButton = collapsedPart.querySelector('.expand-button');
448 expandButton.onclick = expandFunction(sectionId);
449 expandButton.onmousedown = handleButtonMouseDown;
450 }
451
452 }
453
454 function handleButtonMouseDown(e)
455 {
456 // To prevent selection on double click
457 e.preventDefault();
458 }
459
460 DocumentPrototype.transformDocumentToTreeView = function() {
461 prepareWebKitXMLViewer("This XML file does not appear to have any style information associated with it. The document tree is shown below.");
462 }
463 });
464
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698