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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/xml/DocumentXMLTreeViewer.idl ('k') | Source/core/xml/XMLTreeViewer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/xml/DocumentXMLTreeViewer.js
diff --git a/Source/core/xml/DocumentXMLTreeViewer.js b/Source/core/xml/DocumentXMLTreeViewer.js
new file mode 100644
index 0000000000000000000000000000000000000000..dfc1787ded5bd80c291fcb5248ffbd636eb06635
--- /dev/null
+++ b/Source/core/xml/DocumentXMLTreeViewer.js
@@ -0,0 +1,466 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+"use strict";
+
+installClass("Document", function(DocumentPrototype) {
+ // FIXME: The stylesheet should be defined in a separate css file
+ var styleSheet = [
+ "div.header {",
+ " border-bottom: 2px solid black;",
+ " padding-bottom: 5px;",
+ " margin: 10px;",
+ "}",
+ "",
+ "div.collapsible > div.hidden {",
+ " display:none;",
+ "}",
+ "",
+ ".pretty-print {",
+ " margin-top: 1em;",
+ " margin-left: 20px;",
+ " font-family: monospace;",
+ " font-size: 13px;",
+ "}",
+ "",
+ "#webkit-xml-viewer-source-xml {",
+ " display: none;",
+ "}",
+ "",
+ ".collapsible-content {",
+ " margin-left: 1em;",
+ "}",
+ ".comment {",
+ " white-space: pre;",
+ "}",
+ "",
+ ".button {",
+ " -webkit-user-select: none;",
+ " cursor: pointer;",
+ " display: inline-block;",
+ " margin-left: -10px;",
+ " width: 10px;",
+ " background-repeat: no-repeat;",
+ " background-position: left top;",
+ " vertical-align: bottom;",
+ "}",
+ "",
+ ".collapse-button {",
+ " background-image: -webkit-canvas(arrowDown);",
+ " height: 10px;",
+ "}",
+ "",
+ ".expand-button {",
+ " background-image: -webkit-canvas(arrowRight);",
+ " height: 11px;",
+ "}"].join('');
+ var nodeParentPairs = [];
+ var tree;
+
+ function prepareWebKitXMLViewer(noStyleMessage)
+ {
+ var html = createHTMLElement('html');
+ var head = createHTMLElement('head');
+ html.appendChild(head);
+ var style = createHTMLElement('style');
+ style.id = 'xml-viewer-style';
+ style.appendChild(document.createTextNode(styleSheet));
+ head.appendChild(style);
+ var body = createHTMLElement('body');
+ html.appendChild(body);
+ var sourceXML = createHTMLElement('div');
+ sourceXML.id = 'webkit-xml-viewer-source-xml';
+ body.appendChild(sourceXML);
+
+ var child;
+ while (child = document.firstChild) {
+ document.removeChild(child);
+ if (child.nodeType != Node.DOCUMENT_TYPE_NODE)
+ sourceXML.appendChild(child);
+ }
+ document.appendChild(html);
+
+ var header = createHTMLElement('div');
+ body.appendChild(header);
+ header.classList.add('header');
+ var headerSpan = createHTMLElement('span');
+ header.appendChild(headerSpan);
+ headerSpan.textContent = noStyleMessage;
+ header.appendChild(createHTMLElement('br'));
+
+ tree = createHTMLElement('div');
+ body.appendChild(tree);
+ tree.classList.add('pretty-print');
+ window.onload = sourceXMLLoaded;
+ }
+
+ function sourceXMLLoaded()
+ {
+ var sourceXML = document.getElementById('webkit-xml-viewer-source-xml');
+ if (!sourceXML)
+ return; // Stop if some XML tree extension is already processing this document
+
+ for (var child = sourceXML.firstChild; child; child = child.nextSibling)
+ nodeParentPairs.push({parentElement: tree, node: child});
+
+ for (var i = 0; i < nodeParentPairs.length; i++)
+ processNode(nodeParentPairs[i].parentElement, nodeParentPairs[i].node);
+
+ drawArrows();
+ initButtons();
+
+ return false;
+ }
+
+ // Tree processing.
+
+ function processNode(parentElement, node)
+ {
+ var map = processNode.processorsMap;
+ if (!map) {
+ map = {};
+ processNode.processorsMap = map;
+ map[Node.PROCESSING_INSTRUCTION_NODE] = processProcessingInstruction;
+ map[Node.ELEMENT_NODE] = processElement;
+ map[Node.COMMENT_NODE] = processComment;
+ map[Node.TEXT_NODE] = processText;
+ map[Node.CDATA_SECTION_NODE] = processCDATA;
+ }
+ if (processNode.processorsMap[node.nodeType])
+ processNode.processorsMap[node.nodeType].call(this, parentElement, node);
+ }
+
+ function processElement(parentElement, node)
+ {
+ if (!node.firstChild)
+ processEmptyElement(parentElement, node);
+ else {
+ var child = node.firstChild;
+ if (child.nodeType == Node.TEXT_NODE && isShort(child.nodeValue) && !child.nextSibling)
+ processShortTextOnlyElement(parentElement, node);
+ else
+ processComplexElement(parentElement, node);
+ }
+ }
+
+ function processEmptyElement(parentElement, node)
+ {
+ var line = createLine();
+ line.appendChild(createTag(node, false, true));
+ parentElement.appendChild(line);
+ }
+
+ function processShortTextOnlyElement(parentElement, node)
+ {
+ var line = createLine();
+ line.appendChild(createTag(node, false, false));
+ for (var child = node.firstChild; child; child = child.nextSibling)
+ line.appendChild(createText(child.nodeValue));
+ line.appendChild(createTag(node, true, false));
+ parentElement.appendChild(line);
+ }
+
+ function processComplexElement(parentElement, node)
+ {
+ var collapsible = createCollapsible();
+
+ collapsible.expanded.start.appendChild(createTag(node, false, false));
+ for (var child = node.firstChild; child; child = child.nextSibling)
+ nodeParentPairs.push({parentElement: collapsible.expanded.content, node: child});
+ collapsible.expanded.end.appendChild(createTag(node, true, false));
+
+ collapsible.collapsed.content.appendChild(createTag(node, false, false));
+ collapsible.collapsed.content.appendChild(createText('...'));
+ collapsible.collapsed.content.appendChild(createTag(node, true, false));
+ parentElement.appendChild(collapsible);
+ }
+
+ function processComment(parentElement, node)
+ {
+ if (isShort(node.nodeValue)) {
+ var line = createLine();
+ line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
+ parentElement.appendChild(line);
+ } else {
+ var collapsible = createCollapsible();
+
+ collapsible.expanded.start.appendChild(createComment('<!--'));
+ collapsible.expanded.content.appendChild(createComment(node.nodeValue));
+ collapsible.expanded.end.appendChild(createComment('-->'));
+
+ collapsible.collapsed.content.appendChild(createComment('<!--'));
+ collapsible.collapsed.content.appendChild(createComment('...'));
+ collapsible.collapsed.content.appendChild(createComment('-->'));
+ parentElement.appendChild(collapsible);
+ }
+ }
+
+ function processCDATA(parentElement, node)
+ {
+ if (isShort(node.nodeValue)) {
+ var line = createLine();
+ line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>'));
+ parentElement.appendChild(line);
+ } else {
+ var collapsible = createCollapsible();
+
+ collapsible.expanded.start.appendChild(createText('<![CDATA['));
+ collapsible.expanded.content.appendChild(createText(node.nodeValue));
+ collapsible.expanded.end.appendChild(createText(']]>'));
+
+ collapsible.collapsed.content.appendChild(createText('<![CDATA['));
+ collapsible.collapsed.content.appendChild(createText('...'));
+ collapsible.collapsed.content.appendChild(createText(']]>'));
+ parentElement.appendChild(collapsible);
+ }
+ }
+
+ function processProcessingInstruction(parentElement, node)
+ {
+ if (isShort(node.nodeValue)) {
+ var line = createLine();
+ line.appendChild(createComment('<?' + node.nodeName + ' ' + node.nodeValue + '?>'));
+ parentElement.appendChild(line);
+ } else {
+ var collapsible = createCollapsible();
+
+ collapsible.expanded.start.appendChild(createComment('<?' + node.nodeName));
+ collapsible.expanded.content.appendChild(createComment(node.nodeValue));
+ collapsible.expanded.end.appendChild(createComment('?>'));
+
+ collapsible.collapsed.content.appendChild(createComment('<?' + node.nodeName));
+ collapsible.collapsed.content.appendChild(createComment('...'));
+ collapsible.collapsed.content.appendChild(createComment('?>'));
+ parentElement.appendChild(collapsible);
+ }
+ }
+
+ function processText(parentElement, node)
+ {
+ parentElement.appendChild(createText(node.nodeValue));
+ }
+
+ // Processing utils.
+
+ function trim(value)
+ {
+ return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+ }
+
+ function isShort(value)
+ {
+ return trim(value).length <= 50;
+ }
+
+ // Tree rendering.
+
+ function createHTMLElement(elementName)
+ {
+ return document.createElementNS('http://www.w3.org/1999/xhtml', elementName)
+ }
+
+ function createCollapsible()
+ {
+ var collapsible = createHTMLElement('div');
+ collapsible.classList.add('collapsible');
+ collapsible.expanded = createHTMLElement('div');
+ collapsible.expanded.classList.add('expanded');
+ collapsible.appendChild(collapsible.expanded);
+
+ collapsible.expanded.start = createLine();
+ collapsible.expanded.start.appendChild(createCollapseButton());
+ collapsible.expanded.appendChild(collapsible.expanded.start);
+
+ collapsible.expanded.content = createHTMLElement('div');
+ collapsible.expanded.content.classList.add('collapsible-content');
+ collapsible.expanded.appendChild(collapsible.expanded.content);
+
+ collapsible.expanded.end = createLine();
+ collapsible.expanded.appendChild(collapsible.expanded.end);
+
+ collapsible.collapsed = createHTMLElement('div');
+ collapsible.collapsed.classList.add('collapsed');
+ collapsible.collapsed.classList.add('hidden');
+ collapsible.appendChild(collapsible.collapsed);
+ collapsible.collapsed.content = createLine();
+ collapsible.collapsed.content.appendChild(createExpandButton());
+ collapsible.collapsed.appendChild(collapsible.collapsed.content);
+
+ return collapsible;
+ }
+
+ function createButton()
+ {
+ var button = createHTMLElement('span');
+ button.classList.add('button');
+ return button;
+ }
+
+ function createCollapseButton(str)
+ {
+ var button = createButton();
+ button.classList.add('collapse-button');
+ return button;
+ }
+
+ function createExpandButton(str)
+ {
+ var button = createButton();
+ button.classList.add('expand-button');
+ return button;
+ }
+
+ function createComment(commentString)
+ {
+ var comment = createHTMLElement('span');
+ comment.classList.add('comment');
+ comment.classList.add('webkit-html-comment');
+ comment.textContent = commentString;
+ return comment;
+ }
+
+ function createText(value)
+ {
+ var text = createHTMLElement('span');
+ text.textContent = trim(value);
+ text.classList.add('text');
+ return text;
+ }
+
+ function createLine()
+ {
+ var line = createHTMLElement('div');
+ line.classList.add('line');
+ return line;
+ }
+
+ function createTag(node, isClosing, isEmpty)
+ {
+ var tag = createHTMLElement('span');
+ tag.classList.add('webkit-html-tag');
+
+ var stringBeforeAttrs = '<';
+ if (isClosing)
+ stringBeforeAttrs += '/';
+ stringBeforeAttrs += node.nodeName;
+ var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
+ tag.appendChild(textBeforeAttrs);
+
+ if (!isClosing) {
+ for (var i = 0; i < node.attributes.length; i++)
+ tag.appendChild(createAttribute(node.attributes[i]));
+ }
+
+ var stringAfterAttrs = '';
+ if (isEmpty)
+ stringAfterAttrs += '/';
+ stringAfterAttrs += '>';
+ var textAfterAttrs = document.createTextNode(stringAfterAttrs);
+ tag.appendChild(textAfterAttrs);
+
+ return tag;
+ }
+
+ function createAttribute(attributeNode)
+ {
+ var attribute = createHTMLElement('span');
+ attribute.classList.add('webkit-html-attribute');
+
+ var attributeName = createHTMLElement('span');
+ attributeName.classList.add('webkit-html-attribute-name');
+ attributeName.textContent = attributeNode.name;
+
+ var textBefore = document.createTextNode(' ');
+ var textBetween = document.createTextNode('="');
+
+ var attributeValue = createHTMLElement('span');
+ attributeValue.classList.add('webkit-html-attribute-value');
+ attributeValue.textContent = attributeNode.value;
+
+ var textAfter = document.createTextNode('"');
+
+ attribute.appendChild(textBefore);
+ attribute.appendChild(attributeName);
+ attribute.appendChild(textBetween);
+ attribute.appendChild(attributeValue);
+ attribute.appendChild(textAfter);
+ return attribute;
+ }
+
+ // Tree behaviour.
+
+ function drawArrows()
+ {
+ var ctx = document.getCSSCanvasContext("2d", "arrowRight", 10, 11);
+
+ ctx.fillStyle = "rgb(90,90,90)";
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(0, 8);
+ ctx.lineTo(7, 4);
+ ctx.lineTo(0, 0);
+ ctx.fill();
+ ctx.closePath();
+
+ var ctx = document.getCSSCanvasContext("2d", "arrowDown", 10, 10);
+
+ ctx.fillStyle = "rgb(90,90,90)";
+ ctx.beginPath();
+ ctx.moveTo(0, 0);
+ ctx.lineTo(8, 0);
+ ctx.lineTo(4, 7);
+ ctx.lineTo(0, 0);
+ ctx.fill();
+ ctx.closePath();
+ }
+
+ function expandFunction(sectionId)
+ {
+ return function()
+ {
+ document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
+ document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
+ };
+ }
+
+ function collapseFunction(sectionId)
+ {
+ return function()
+ {
+ document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
+ document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
+ };
+ }
+
+ function initButtons()
+ {
+ var sections = document.querySelectorAll('.collapsible');
+ for (var i = 0; i < sections.length; i++) {
+ var sectionId = 'collapsible' + i;
+ sections[i].id = sectionId;
+
+ var expandedPart = sections[i].querySelector('#' + sectionId + ' > .expanded');
+ var collapseButton = expandedPart.querySelector('.collapse-button');
+ collapseButton.onclick = collapseFunction(sectionId);
+ collapseButton.onmousedown = handleButtonMouseDown;
+
+ var collapsedPart = sections[i].querySelector('#' + sectionId + ' > .collapsed');
+ var expandButton = collapsedPart.querySelector('.expand-button');
+ expandButton.onclick = expandFunction(sectionId);
+ expandButton.onmousedown = handleButtonMouseDown;
+ }
+
+ }
+
+ function handleButtonMouseDown(e)
+ {
+ // To prevent selection on double click
+ e.preventDefault();
+ }
+
+ DocumentPrototype.transformDocumentToTreeView = function(noStyleMessage) {
+ prepareWebKitXMLViewer(noStyleMessage);
+ }
+});
+
« no previous file with comments | « Source/core/xml/DocumentXMLTreeViewer.idl ('k') | Source/core/xml/XMLTreeViewer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698