2
* Copyright (C) 2011 Google Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above
12
* copyright notice, this list of conditions and the following disclaimer
13
* in the documentation and/or other materials provided with the
16
* THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17
* āAS ISā AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20
* OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
var nodeParentPairs = [];
31
// Script entry point.
33
function prepareWebKitXMLViewer(noStyleMessage)
35
var html = createHTMLElement('html');
36
var head = createHTMLElement('head');
37
html.appendChild(head);
38
var style = createHTMLElement('style');
39
style.id = 'xml-viewer-style';
40
head.appendChild(style);
41
var body = createHTMLElement('body');
42
html.appendChild(body);
43
var sourceXML = createHTMLElement('div');
44
sourceXML.id = 'webkit-xml-viewer-source-xml';
45
body.appendChild(sourceXML);
48
while (child = document.firstChild) {
49
document.removeChild(child);
50
if (child.nodeType != Node.DOCUMENT_TYPE_NODE)
51
sourceXML.appendChild(child);
53
document.appendChild(html);
55
var header = createHTMLElement('div');
56
body.appendChild(header);
57
header.classList.add('header');
58
var headerSpan = createHTMLElement('span');
59
header.appendChild(headerSpan);
60
headerSpan.textContent = noStyleMessage;
61
header.appendChild(createHTMLElement('br'));
63
var tree = createHTMLElement('div');
64
body.appendChild(tree);
65
tree.classList.add('pretty-print');
67
window.onload = sourceXMLLoaded;
70
function sourceXMLLoaded()
72
var sourceXML = document.getElementById('webkit-xml-viewer-source-xml');
74
return; // Stop if some XML tree extension is already processing this document
75
//var style = document.head.firstChild;
76
//document.head.removeChild(style);
77
//document.head.appendChild(style);
78
var root = document.getElementById('tree');
80
for (var child = sourceXML.firstChild; child; child = child.nextSibling)
81
nodeParentPairs.push({parentElement: root, node: child});
83
for (var i = 0; i < nodeParentPairs.length; i++)
84
processNode(nodeParentPairs[i].parentElement, nodeParentPairs[i].node);
89
if (typeof(onAfterWebkitXMLViewerLoaded) == 'function')
90
onAfterWebkitXMLViewerLoaded();
95
function processNode(parentElement, node)
97
if (!processNode.processorsMap) {
98
processNode.processorsMap = {};
99
processNode.processorsMap[Node.PROCESSING_INSTRUCTION_NODE] = processProcessingInstruction;
100
processNode.processorsMap[Node.ELEMENT_NODE] = processElement;
101
processNode.processorsMap[Node.COMMENT_NODE] = processComment;
102
processNode.processorsMap[Node.TEXT_NODE] = processText;
103
processNode.processorsMap[Node.CDATA_SECTION_NODE] = processCDATA;
105
if (processNode.processorsMap[node.nodeType])
106
processNode.processorsMap[node.nodeType].call(this, parentElement, node);
109
function processElement(parentElement, node)
111
if (!node.firstChild)
112
processEmptyElement(parentElement, node);
114
var child = node.firstChild;
115
if (child.nodeType == Node.TEXT_NODE && isShort(child.nodeValue) && !child.nextSibling)
116
processShortTextOnlyElement(parentElement, node);
118
processComplexElement(parentElement, node);
122
function processEmptyElement(parentElement, node)
124
var line = createLine();
125
line.appendChild(createTag(node, false, true));
126
parentElement.appendChild(line);
129
function processShortTextOnlyElement(parentElement, node)
131
var line = createLine();
132
line.appendChild(createTag(node, false, false));
133
for (var child = node.firstChild; child; child = child.nextSibling)
134
line.appendChild(createText(child.nodeValue));
135
line.appendChild(createTag(node, true, false));
136
parentElement.appendChild(line);
139
function processComplexElement(parentElement, node)
141
var collapsible = createCollapsible();
143
collapsible.expanded.start.appendChild(createTag(node, false, false));
144
for (var child = node.firstChild; child; child = child.nextSibling)
145
nodeParentPairs.push({parentElement: collapsible.expanded.content, node: child});
146
collapsible.expanded.end.appendChild(createTag(node, true, false));
148
collapsible.collapsed.content.appendChild(createTag(node, false, false));
149
collapsible.collapsed.content.appendChild(createText('...'));
150
collapsible.collapsed.content.appendChild(createTag(node, true, false));
151
parentElement.appendChild(collapsible);
154
function processComment(parentElement, node)
156
if (isShort(node.nodeValue)) {
157
var line = createLine();
158
line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
159
parentElement.appendChild(line);
161
var collapsible = createCollapsible();
163
collapsible.expanded.start.appendChild(createComment('<!--'));
164
collapsible.expanded.content.appendChild(createComment(node.nodeValue));
165
collapsible.expanded.end.appendChild(createComment('-->'));
167
collapsible.collapsed.content.appendChild(createComment('<!--'));
168
collapsible.collapsed.content.appendChild(createComment('...'));
169
collapsible.collapsed.content.appendChild(createComment('-->'));
170
parentElement.appendChild(collapsible);
174
function processCDATA(parentElement, node)
176
if (isShort(node.nodeValue)) {
177
var line = createLine();
178
line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>'));
179
parentElement.appendChild(line);
181
var collapsible = createCollapsible();
183
collapsible.expanded.start.appendChild(createText('<![CDATA['));
184
collapsible.expanded.content.appendChild(createText(node.nodeValue));
185
collapsible.expanded.end.appendChild(createText(']]>'));
187
collapsible.collapsed.content.appendChild(createText('<![CDATA['));
188
collapsible.collapsed.content.appendChild(createText('...'));
189
collapsible.collapsed.content.appendChild(createText(']]>'));
190
parentElement.appendChild(collapsible);
194
function processProcessingInstruction(parentElement, node)
196
if (isShort(node.nodeValue)) {
197
var line = createLine();
198
line.appendChild(createComment('<?' + node.nodeName + ' ' + node.nodeValue + '?>'));
199
parentElement.appendChild(line);
201
var collapsible = createCollapsible();
203
collapsible.expanded.start.appendChild(createComment('<?' + node.nodeName));
204
collapsible.expanded.content.appendChild(createComment(node.nodeValue));
205
collapsible.expanded.end.appendChild(createComment('?>'));
207
collapsible.collapsed.content.appendChild(createComment('<?' + node.nodeName));
208
collapsible.collapsed.content.appendChild(createComment('...'));
209
collapsible.collapsed.content.appendChild(createComment('?>'));
210
parentElement.appendChild(collapsible);
214
function processText(parentElement, node)
216
parentElement.appendChild(createText(node.nodeValue));
223
return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
226
function isShort(value)
228
return trim(value).length <= 50;
233
function createHTMLElement(elementName)
235
return document.createElementNS('http://www.w3.org/1999/xhtml', elementName)
238
function createCollapsible()
240
var collapsible = createHTMLElement('div');
241
collapsible.classList.add('collapsible');
242
collapsible.expanded = createHTMLElement('div');
243
collapsible.expanded.classList.add('expanded');
244
collapsible.appendChild(collapsible.expanded);
246
collapsible.expanded.start = createLine();
247
collapsible.expanded.start.appendChild(createCollapseButton());
248
collapsible.expanded.appendChild(collapsible.expanded.start);
250
collapsible.expanded.content = createHTMLElement('div');
251
collapsible.expanded.content.classList.add('collapsible-content');
252
collapsible.expanded.appendChild(collapsible.expanded.content);
254
collapsible.expanded.end = createLine();
255
collapsible.expanded.appendChild(collapsible.expanded.end);
257
collapsible.collapsed = createHTMLElement('div');
258
collapsible.collapsed.classList.add('collapsed');
259
collapsible.collapsed.classList.add('hidden');
260
collapsible.appendChild(collapsible.collapsed);
261
collapsible.collapsed.content = createLine();
262
collapsible.collapsed.content.appendChild(createExpandButton());
263
collapsible.collapsed.appendChild(collapsible.collapsed.content);
268
function createButton()
270
var button = createHTMLElement('span');
271
button.classList.add('button');
275
function createCollapseButton(str)
277
var button = createButton();
278
button.classList.add('collapse-button');
282
function createExpandButton(str)
284
var button = createButton();
285
button.classList.add('expand-button');
289
function createComment(commentString)
291
var comment = createHTMLElement('span');
292
comment.classList.add('comment');
293
comment.classList.add('webkit-html-comment');
294
comment.textContent = commentString;
298
function createText(value)
300
var text = createHTMLElement('span');
301
text.textContent = trim(value);
302
text.classList.add('text');
306
function createLine()
308
var line = createHTMLElement('div');
309
line.classList.add('line');
313
function createTag(node, isClosing, isEmpty)
315
var tag = createHTMLElement('span');
316
tag.classList.add('webkit-html-tag');
318
var stringBeforeAttrs = '<';
320
stringBeforeAttrs += '/';
321
stringBeforeAttrs += node.nodeName;
322
var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
323
tag.appendChild(textBeforeAttrs);
326
for (var i = 0; i < node.attributes.length; i++)
327
tag.appendChild(createAttribute(node.attributes[i]));
330
var stringAfterAttrs = '';
332
stringAfterAttrs += '/';
333
stringAfterAttrs += '>';
334
var textAfterAttrs = document.createTextNode(stringAfterAttrs);
335
tag.appendChild(textAfterAttrs);
340
function createAttribute(attributeNode)
342
var attribute = createHTMLElement('span');
343
attribute.classList.add('webkit-html-attribute');
345
var attributeName = createHTMLElement('span');
346
attributeName.classList.add('webkit-html-attribute-name');
347
attributeName.textContent = attributeNode.name;
349
var textBefore = document.createTextNode(' ');
350
var textBetween = document.createTextNode('="');
352
var attributeValue = createHTMLElement('span');
353
attributeValue.classList.add('webkit-html-attribute-value');
354
attributeValue.textContent = attributeNode.value;
356
var textAfter = document.createTextNode('"');
358
attribute.appendChild(textBefore);
359
attribute.appendChild(attributeName);
360
attribute.appendChild(textBetween);
361
attribute.appendChild(attributeValue);
362
attribute.appendChild(textAfter);
368
function drawArrows()
370
var ctx = document.getCSSCanvasContext("2d", "arrowRight", 10, 11);
372
ctx.fillStyle = "rgb(90,90,90)";
381
var ctx = document.getCSSCanvasContext("2d", "arrowDown", 10, 10);
383
ctx.fillStyle = "rgb(90,90,90)";
393
function expandFunction(sectionId)
397
document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
398
document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
402
function collapseFunction(sectionId)
406
document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
407
document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
411
function initButtons()
413
var sections = document.querySelectorAll('.collapsible');
414
for (var i = 0; i < sections.length; i++) {
415
var sectionId = 'collapsible' + i;
416
sections[i].id = sectionId;
418
var expandedPart = sections[i].querySelector('#' + sectionId + ' > .expanded');
419
var collapseButton = expandedPart.querySelector('.collapse-button');
420
collapseButton.onclick = collapseFunction(sectionId);
421
collapseButton.onmousedown = handleButtonMouseDown;
423
var collapsedPart = sections[i].querySelector('#' + sectionId + ' > .collapsed');
424
var expandButton = collapsedPart.querySelector('.expand-button');
425
expandButton.onclick = expandFunction(sectionId);
426
expandButton.onmousedown = handleButtonMouseDown;
431
function handleButtonMouseDown(e)
433
// To prevent selection on double click