12daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch/*
22daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Copyright (C) 2011 Google Inc. All rights reserved.
32daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
42daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * Redistribution and use in source and binary forms, with or without
52daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * modification, are permitted provided that the following conditions are
62daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * met:
72daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
82daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 1. Redistributions of source code must retain the above copyright
92daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * notice, this list of conditions and the following disclaimer.
102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * 2. Redistributions in binary form must reproduce the above
122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * copyright notice, this list of conditions and the following disclaimer
132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * in the documentation and/or other materials provided with the
142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * distribution.
152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch *
162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch */
282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvar nodeParentPairs = [];
302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Script entry point.
322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction prepareWebKitXMLViewer(noStyleMessage)
342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var html = createHTMLElement('html');
362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var head = createHTMLElement('head');
372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    html.appendChild(head);
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var style = createHTMLElement('style');
392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    style.id = 'xml-viewer-style';
402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    head.appendChild(style);
412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var body = createHTMLElement('body');
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    html.appendChild(body);
432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var sourceXML = createHTMLElement('div');
442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    sourceXML.id = 'webkit-xml-viewer-source-xml';
452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    body.appendChild(sourceXML);
462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var child;
482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    while (child = document.firstChild) {
492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        document.removeChild(child);
502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (child.nodeType != Node.DOCUMENT_TYPE_NODE)
512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            sourceXML.appendChild(child);
522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    document.appendChild(html);
542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var header = createHTMLElement('div');
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    body.appendChild(header);
572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    header.classList.add('header');
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var headerSpan = createHTMLElement('span');
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    header.appendChild(headerSpan);
602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    headerSpan.textContent = noStyleMessage;
612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    header.appendChild(createHTMLElement('br'));
622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var tree = createHTMLElement('div');
642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    body.appendChild(tree);
652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    tree.classList.add('pretty-print');
662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    tree.id = 'tree';
672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    window.onload = sourceXMLLoaded;
682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction sourceXMLLoaded()
712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var sourceXML = document.getElementById('webkit-xml-viewer-source-xml');
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!sourceXML)
742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return; // Stop if some XML tree extension is already processing this document
752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    //var style = document.head.firstChild;
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    //document.head.removeChild(style);
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    //document.head.appendChild(style);
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var root = document.getElementById('tree');
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (var child = sourceXML.firstChild; child; child = child.nextSibling)
812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        nodeParentPairs.push({parentElement: root, node: child});
822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (var i = 0; i < nodeParentPairs.length; i++)
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode(nodeParentPairs[i].parentElement, nodeParentPairs[i].node);
852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    drawArrows();
872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    initButtons();
882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (typeof(onAfterWebkitXMLViewerLoaded) == 'function')
902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch      onAfterWebkitXMLViewerLoaded();
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Tree processing.
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processNode(parentElement, node)
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!processNode.processorsMap) {
982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap = {};
992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[Node.PROCESSING_INSTRUCTION_NODE] = processProcessingInstruction;
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[Node.ELEMENT_NODE] = processElement;
1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[Node.COMMENT_NODE] = processComment;
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[Node.TEXT_NODE] = processText;
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[Node.CDATA_SECTION_NODE] = processCDATA;
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (processNode.processorsMap[node.nodeType])
1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processNode.processorsMap[node.nodeType].call(this, parentElement, node);
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processElement(parentElement, node)
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!node.firstChild)
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        processEmptyElement(parentElement, node);
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    else {
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var child = node.firstChild;
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (child.nodeType == Node.TEXT_NODE && isShort(child.nodeValue) && !child.nextSibling)
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            processShortTextOnlyElement(parentElement, node);
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        else
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            processComplexElement(parentElement, node);
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processEmptyElement(parentElement, node)
1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var line = createLine();
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    line.appendChild(createTag(node, false, true));
1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    parentElement.appendChild(line);
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processShortTextOnlyElement(parentElement, node)
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var line = createLine();
1322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    line.appendChild(createTag(node, false, false));
1332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (var child = node.firstChild; child; child = child.nextSibling)
1342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        line.appendChild(createText(child.nodeValue));
1352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    line.appendChild(createTag(node, true, false));
1362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    parentElement.appendChild(line);
1372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processComplexElement(parentElement, node)
1402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var collapsible = createCollapsible();
1422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.start.appendChild(createTag(node, false, false));
1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (var child = node.firstChild; child; child = child.nextSibling)
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        nodeParentPairs.push({parentElement: collapsible.expanded.content, node: child});
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.end.appendChild(createTag(node, true, false));
1472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.content.appendChild(createTag(node, false, false));
1492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.content.appendChild(createText('...'));
1502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.content.appendChild(createTag(node, true, false));
1512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    parentElement.appendChild(collapsible);
1522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processComment(parentElement, node)
1552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isShort(node.nodeValue)) {
1572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var line = createLine();
1582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        line.appendChild(createComment('<!-- ' + node.nodeValue + ' -->'));
1592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(line);
1602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
1612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var collapsible = createCollapsible();
1622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.start.appendChild(createComment('<!--'));
1642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.content.appendChild(createComment(node.nodeValue));
1652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.end.appendChild(createComment('-->'));
1662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('<!--'));
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('...'));
1692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('-->'));
1702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(collapsible);
1712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processCDATA(parentElement, node)
1752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isShort(node.nodeValue)) {
1772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var line = createLine();
1782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        line.appendChild(createText('<![CDATA[ ' + node.nodeValue + ' ]]>'));
1792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(line);
1802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
1812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var collapsible = createCollapsible();
1822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.start.appendChild(createText('<![CDATA['));
1842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.content.appendChild(createText(node.nodeValue));
1852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.end.appendChild(createText(']]>'));
1862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createText('<![CDATA['));
1882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createText('...'));
1892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createText(']]>'));
1902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(collapsible);
1912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
1922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processProcessingInstruction(parentElement, node)
1952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isShort(node.nodeValue)) {
1972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var line = createLine();
1982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        line.appendChild(createComment('<?' + node.nodeName + ' ' + node.nodeValue + '?>'));
1992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(line);
2002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    } else {
2012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var collapsible = createCollapsible();
2022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.start.appendChild(createComment('<?' + node.nodeName));
2042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.content.appendChild(createComment(node.nodeValue));
2052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.expanded.end.appendChild(createComment('?>'));
2062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('<?' + node.nodeName));
2082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('...'));
2092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapsible.collapsed.content.appendChild(createComment('?>'));
2102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        parentElement.appendChild(collapsible);
2112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
2122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction processText(parentElement, node)
2152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    parentElement.appendChild(createText(node.nodeValue));
2172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Processing utils.
2202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction trim(value)
2222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return value.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
2242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction isShort(value)
2272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return trim(value).length <= 50;
2292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Tree rendering.
2322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createHTMLElement(elementName)
2342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return document.createElementNS('http://www.w3.org/1999/xhtml', elementName)
2362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createCollapsible()
2392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var collapsible = createHTMLElement('div');
2412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.classList.add('collapsible');
2422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded = createHTMLElement('div');
2432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.classList.add('expanded');
2442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.appendChild(collapsible.expanded);
2452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.start = createLine();
2472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.start.appendChild(createCollapseButton());
2482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.appendChild(collapsible.expanded.start);
2492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.content = createHTMLElement('div');
2512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.content.classList.add('collapsible-content');
2522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.appendChild(collapsible.expanded.content);
2532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.end = createLine();
2552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.expanded.appendChild(collapsible.expanded.end);
2562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed = createHTMLElement('div');
2582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.classList.add('collapsed');
2592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.classList.add('hidden');
2602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.appendChild(collapsible.collapsed);
2612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.content = createLine();
2622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.content.appendChild(createExpandButton());
2632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    collapsible.collapsed.appendChild(collapsible.collapsed.content);
2642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return collapsible;
2662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createButton()
2692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var button = createHTMLElement('span');
2712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    button.classList.add('button');
2722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return button;
2732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createCollapseButton(str)
2762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var button = createButton();
2782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    button.classList.add('collapse-button');
2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return button;
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createExpandButton(str)
2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var button = createButton();
2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    button.classList.add('expand-button');
2862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return button;
2872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createComment(commentString)
2902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var comment = createHTMLElement('span');
2922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    comment.classList.add('webkit-html-comment');
2932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    comment.textContent = commentString;
2942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return comment;
2952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
2962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
2972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createText(value)
2982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
2992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var text = createHTMLElement('span');
3002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    text.textContent = trim(value);
3012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    text.classList.add('text');
3022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return text;
3032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createLine()
3062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var line = createHTMLElement('div');
3082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    line.classList.add('line');
3092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return line;
3102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createTag(node, isClosing, isEmpty)
3132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var tag = createHTMLElement('span');
3152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    tag.classList.add('webkit-html-tag');
3162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var stringBeforeAttrs = '<';
3182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isClosing)
3192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stringBeforeAttrs += '/';
3202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    stringBeforeAttrs += node.nodeName;
3212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var textBeforeAttrs = document.createTextNode(stringBeforeAttrs);
3222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    tag.appendChild(textBeforeAttrs);
3232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!isClosing) {
3252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        for (var i = 0; i < node.attributes.length; i++)
3262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            tag.appendChild(createAttribute(node.attributes[i]));
3272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
3282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var stringAfterAttrs = '';
3302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (isEmpty)
3312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        stringAfterAttrs += '/';
3322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    stringAfterAttrs += '>';
3332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var textAfterAttrs = document.createTextNode(stringAfterAttrs);
3342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    tag.appendChild(textAfterAttrs);
3352daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3362daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return tag;
3372daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3392daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction createAttribute(attributeNode)
3402daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3412daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var attribute = createHTMLElement('span');
3422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.classList.add('webkit-html-attribute');
3432daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var attributeName = createHTMLElement('span');
3452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attributeName.classList.add('webkit-html-attribute-name');
3462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attributeName.textContent = attributeNode.name;
3472daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3482daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var textBefore = document.createTextNode(' ');
3492daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var textBetween = document.createTextNode('="');
3502daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var attributeValue = createHTMLElement('span');
3522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attributeValue.classList.add('webkit-html-attribute-value');
3532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attributeValue.textContent = attributeNode.value;
3542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3552daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var textAfter = document.createTextNode('"');
3562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.appendChild(textBefore);
3582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.appendChild(attributeName);
3592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.appendChild(textBetween);
3602daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.appendChild(attributeValue);
3612daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    attribute.appendChild(textAfter);
3622daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return attribute;
3632daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3642daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Tree behaviour.
3662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3672daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction drawArrows()
3682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var ctx = document.getCSSCanvasContext("2d", "arrowRight", 10, 11);
3702daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3712daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.fillStyle = "rgb(90,90,90)";
3722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.beginPath();
3732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.moveTo(0, 0);
3742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(0, 8);
3752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(7, 4);
3762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(0, 0);
3772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.fill();
3782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.closePath();
3792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var ctx = document.getCSSCanvasContext("2d", "arrowDown", 10, 10);
3812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.fillStyle = "rgb(90,90,90)";
3832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.beginPath();
3842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.moveTo(0, 0);
3852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(8, 0);
3862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(4, 7);
3872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.lineTo(0, 0);
3882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.fill();
3892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ctx.closePath();
3902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
3912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
3922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction expandFunction(sectionId)
3932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
3942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return function()
3952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
3962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded';
3972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed hidden';
3982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    };
3992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction collapseFunction(sectionId)
4022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return function()
4042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    {
4052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        document.querySelector('#' + sectionId + ' > .expanded').className = 'expanded hidden';
4062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        document.querySelector('#' + sectionId + ' > .collapsed').className = 'collapsed';
4072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    };
4082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction initButtons()
4112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    var sections = document.querySelectorAll('.collapsible');
4132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    for (var i = 0; i < sections.length; i++) {
4142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var sectionId = 'collapsible' + i;
4152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        sections[i].id = sectionId;
4162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var expandedPart = sections[i].querySelector('#' + sectionId + ' > .expanded');
4182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var collapseButton = expandedPart.querySelector('.collapse-button');
4192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapseButton.onclick = collapseFunction(sectionId);
4202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        collapseButton.onmousedown = handleButtonMouseDown;
4212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var collapsedPart = sections[i].querySelector('#' + sectionId + ' > .collapsed');
4232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        var expandButton = collapsedPart.querySelector('.expand-button');
4242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        expandButton.onclick = expandFunction(sectionId);
4252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        expandButton.onmousedown = handleButtonMouseDown;
4262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
4272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
4292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
4302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochfunction handleButtonMouseDown(e)
4312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
4322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch   // To prevent selection on double click
4332daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch   e.preventDefault();
4342daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
435