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

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: 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 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 if (typeof(onAfterWebkitXMLViewerLoaded) == 'function')
114 onAfterWebkitXMLViewerLoaded();
115 }
116
117 // Tree processing.
118
119 function processNode(parentElement, node)
120 {
121 if (!processNode.processorsMap) {
122 processNode.processorsMap = {};
123 processNode.processorsMap[Node.PROCESSING_INSTRUCTION_NODE] = proces sProcessingInstruction;
124 processNode.processorsMap[Node.ELEMENT_NODE] = processElement;
125 processNode.processorsMap[Node.COMMENT_NODE] = processComment;
126 processNode.processorsMap[Node.TEXT_NODE] = processText;
127 processNode.processorsMap[Node.CDATA_SECTION_NODE] = processCDATA;
128 }
129 if (processNode.processorsMap[node.nodeType])
130 processNode.processorsMap[node.nodeType].call(this, parentElement, n ode);
131 }
132
133 function processElement(parentElement, node)
134 {
135 if (!node.firstChild)
136 processEmptyElement(parentElement, node);
137 else {
138 var child = node.firstChild;
139 if (child.nodeType == Node.TEXT_NODE && isShort(child.nodeValue) && !child.nextSibling)
140 processShortTextOnlyElement(parentElement, node);
141 else
142 processComplexElement(parentElement, node);
143 }
144 }
145
146 function processEmptyElement(parentElement, node)
147 {
148 var line = createLine();
149 line.appendChild(createTag(node, false, true));
150 parentElement.appendChild(line);
151 }
152
153 function processShortTextOnlyElement(parentElement, node)
154 {
155 var line = createLine();
156 line.appendChild(createTag(node, false, false));
157 for (var child = node.firstChild; child; child = child.nextSibling)
158 line.appendChild(createText(child.nodeValue));
159 line.appendChild(createTag(node, true, false));
160 parentElement.appendChild(line);
161 }
162
163 function processComplexElement(parentElement, node)
164 {
165 var collapsible = createCollapsible();
166
167 collapsible.expanded.start.appendChild(createTag(node, false, false));
168 for (var child = node.firstChild; child; child = child.nextSibling)
169 nodeParentPairs.push({parentElement: collapsible.expanded.content, n ode: child});
170 collapsible.expanded.end.appendChild(createTag(node, true, false));
171
172 collapsible.collapsed.content.appendChild(createTag(node, false, false)) ;
173 collapsible.collapsed.content.appendChild(createText('...'));
174 collapsible.collapsed.content.appendChild(createTag(node, true, false));
175 parentElement.appendChild(collapsible);
176 }
177
178 function processComment(parentElement, node)
179 {
180 if (isShort(node.nodeValue)) {
181 var line = createLine();
182 line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
183 parentElement.appendChild(line);
184 } else {
185 var collapsible = createCollapsible();
186
187 collapsible.expanded.start.appendChild(createComment('<!--'));
188 collapsible.expanded.content.appendChild(createComment(node.nodeValu e));
189 collapsible.expanded.end.appendChild(createComment('-->'));
190
191 collapsible.collapsed.content.appendChild(createComment('<!--'));
192 collapsible.collapsed.content.appendChild(createComment('...'));
193 collapsible.collapsed.content.appendChild(createComment('-->'));
194 parentElement.appendChild(collapsible);
195 }
196 }
197
198 function processCDATA(parentElement, node)
199 {
200 if (isShort(node.nodeValue)) {
201 var line = createLine();
202 line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>')) ;
203 parentElement.appendChild(line);
204 } else {
205 var collapsible = createCollapsible();
206
207 collapsible.expanded.start.appendChild(createText('<![CDATA['));
208 collapsible.expanded.content.appendChild(createText(node.nodeValue)) ;
209 collapsible.expanded.end.appendChild(createText(']]>'));
210
211 collapsible.collapsed.content.appendChild(createText('<![CDATA['));
212 collapsible.collapsed.content.appendChild(createText('...'));
213 collapsible.collapsed.content.appendChild(createText(']]>'));
214 parentElement.appendChild(collapsible);
215 }
216 }
217
218 function processProcessingInstruction(parentElement, node)
219 {
220 if (isShort(node.nodeValue)) {
221 var line = createLine();
222 line.appendChild(createComment('<?' + node.nodeName + ' ' + node.nod eValue + '?>'));
223 parentElement.appendChild(line);
224 } else {
225 var collapsible = createCollapsible();
226
227 collapsible.expanded.start.appendChild(createComment('<?' + node.nod eName));
228 collapsible.expanded.content.appendChild(createComment(node.nodeValu e));
229 collapsible.expanded.end.appendChild(createComment('?>'));
230
231 collapsible.collapsed.content.appendChild(createComment('<?' + node. nodeName));
232 collapsible.collapsed.content.appendChild(createComment('...'));
233 collapsible.collapsed.content.appendChild(createComment('?>'));
234 parentElement.appendChild(collapsible);
235 }
236 }
237
238 function processText(parentElement, node)
239 {
240 parentElement.appendChild(createText(node.nodeValue));
241 }
242
243 // Processing utils.
244
245 function trim(value)
246 {
247 return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
248 }
249
250 function isShort(value)
251 {
252 return trim(value).length <= 50;
253 }
254
255 // Tree rendering.
256
257 function createHTMLElement(elementName)
258 {
259 return document.createElementNS('http://www.w3.org/1999/xhtml', elementN ame)
260 }
261
262 function createCollapsible()
263 {
264 var collapsible = createHTMLElement('div');
265 collapsible.classList.add('collapsible');
266 collapsible.expanded = createHTMLElement('div');
267 collapsible.expanded.classList.add('expanded');
268 collapsible.appendChild(collapsible.expanded);
269
270 collapsible.expanded.start = createLine();
271 collapsible.expanded.start.appendChild(createCollapseButton());
272 collapsible.expanded.appendChild(collapsible.expanded.start);
273
274 collapsible.expanded.content = createHTMLElement('div');
275 collapsible.expanded.content.classList.add('collapsible-content');
276 collapsible.expanded.appendChild(collapsible.expanded.content);
277
278 collapsible.expanded.end = createLine();
279 collapsible.expanded.appendChild(collapsible.expanded.end);
280
281 collapsible.collapsed = createHTMLElement('div');
282 collapsible.collapsed.classList.add('collapsed');
283 collapsible.collapsed.classList.add('hidden');
284 collapsible.appendChild(collapsible.collapsed);
285 collapsible.collapsed.content = createLine();
286 collapsible.collapsed.content.appendChild(createExpandButton());
287 collapsible.collapsed.appendChild(collapsible.collapsed.content);
288
289 return collapsible;
290 }
291
292 function createButton()
293 {
294 var button = createHTMLElement('span');
295 button.classList.add('button');
296 return button;
297 }
298
299 function createCollapseButton(str)
300 {
301 var button = createButton();
302 button.classList.add('collapse-button');
303 return button;
304 }
305
306 function createExpandButton(str)
307 {
308 var button = createButton();
309 button.classList.add('expand-button');
310 return button;
311 }
312
313 function createComment(commentString)
314 {
315 var comment = createHTMLElement('span');
316 comment.classList.add('comment');
317 comment.classList.add('webkit-html-comment');
318 comment.textContent = commentString;
319 return comment;
320 }
321
322 function createText(value)
323 {
324 var text = createHTMLElement('span');
325 text.textContent = trim(value);
326 text.classList.add('text');
327 return text;
328 }
329
330 function createLine()
331 {
332 var line = createHTMLElement('div');
333 line.classList.add('line');
334 return line;
335 }
336
337 function createTag(node, isClosing, isEmpty)
338 {
339 var tag = createHTMLElement('span');
340 tag.classList.add('webkit-html-tag');
341
342 var stringBeforeAttrs = '<';
343 if (isClosing)
344 stringBeforeAttrs += '/';
345 stringBeforeAttrs += node.nodeName;
346 var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
347 tag.appendChild(textBeforeAttrs);
348
349 if (!isClosing) {
350 for (var i = 0; i < node.attributes.length; i++)
351 tag.appendChild(createAttribute(node.attributes[i]));
352 }
353
354 var stringAfterAttrs = '';
355 if (isEmpty)
356 stringAfterAttrs += '/';
357 stringAfterAttrs += '>';
358 var textAfterAttrs = document.createTextNode(stringAfterAttrs);
359 tag.appendChild(textAfterAttrs);
360
361 return tag;
362 }
363
364 function createAttribute(attributeNode)
365 {
366 var attribute = createHTMLElement('span');
367 attribute.classList.add('webkit-html-attribute');
368
369 var attributeName = createHTMLElement('span');
370 attributeName.classList.add('webkit-html-attribute-name');
371 attributeName.textContent = attributeNode.name;
372
373 var textBefore = document.createTextNode(' ');
374 var textBetween = document.createTextNode('="');
375
376 var attributeValue = createHTMLElement('span');
377 attributeValue.classList.add('webkit-html-attribute-value');
378 attributeValue.textContent = attributeNode.value;
379
380 var textAfter = document.createTextNode('"');
381
382 attribute.appendChild(textBefore);
383 attribute.appendChild(attributeName);
384 attribute.appendChild(textBetween);
385 attribute.appendChild(attributeValue);
386 attribute.appendChild(textAfter);
387 return attribute;
388 }
389
390 // Tree behaviour.
391
392 function drawArrows()
393 {
394 var ctx = document.getCSSCanvasContext("2d", "arrowRight", 10, 11);
395
396 ctx.fillStyle = "rgb(90,90,90)";
397 ctx.beginPath();
398 ctx.moveTo(0, 0);
399 ctx.lineTo(0, 8);
400 ctx.lineTo(7, 4);
401 ctx.lineTo(0, 0);
402 ctx.fill();
403 ctx.closePath();
404
405 var ctx = document.getCSSCanvasContext("2d", "arrowDown", 10, 10);
406
407 ctx.fillStyle = "rgb(90,90,90)";
408 ctx.beginPath();
409 ctx.moveTo(0, 0);
410 ctx.lineTo(8, 0);
411 ctx.lineTo(4, 7);
412 ctx.lineTo(0, 0);
413 ctx.fill();
414 ctx.closePath();
415 }
416
417 function expandFunction(sectionId)
418 {
419 return function()
420 {
421 document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
422 document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
423 };
424 }
425
426 function collapseFunction(sectionId)
427 {
428 return function()
429 {
430 document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
431 document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
432 };
433 }
434
435 function initButtons()
436 {
437 var sections = document.querySelectorAll('.collapsible');
438 for (var i = 0; i < sections.length; i++) {
439 var sectionId = 'collapsible' + i;
440 sections[i].id = sectionId;
441
442 var expandedPart = sections[i].querySelector('#' + sectionId + ' > . expanded');
443 var collapseButton = expandedPart.querySelector('.collapse-button');
444 collapseButton.onclick = collapseFunction(sectionId);
445 collapseButton.onmousedown = handleButtonMouseDown;
446
447 var collapsedPart = sections[i].querySelector('#' + sectionId + ' > .collapsed');
448 var expandButton = collapsedPart.querySelector('.expand-button');
449 expandButton.onclick = expandFunction(sectionId);
450 expandButton.onmousedown = handleButtonMouseDown;
451 }
452
453 }
454
455 function handleButtonMouseDown(e)
456 {
457 // To prevent selection on double click
458 e.preventDefault();
459 }
460
461 DocumentPrototype.transformDocumentToTreeView = function() {
462 prepareWebKitXMLViewer("This XML file does not appear to have any style information associated with it. The document tree is shown below.");
463 }
464 });
465
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698