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

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

Powered by Google App Engine
This is Rietveld 408576698