15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Google Inc.  All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Joseph Pecoraro
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met:
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1.  Redistributions of source code must retain the above copyright
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer.
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2.  Redistributions in binary form must reproduce the above copyright
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     notice, this list of conditions and the following disclaimer in the
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     documentation and/or other materials provided with the distribution.
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     its contributors may be used to endorse or promote products derived
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     from this software without specific prior written permission.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.DOMPresentationUtils = {}
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentElement)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var title = node.nodeNameInCorrectCase();
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var nameElement = document.createElement("span");
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    nameElement.textContent = title;
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parentElement.appendChild(nameElement);
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var idAttribute = node.getAttribute("id");
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (idAttribute) {
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var idElement = document.createElement("span");
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        parentElement.appendChild(idElement);
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var part = "#" + idAttribute;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        title += part;
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        idElement.appendChild(document.createTextNode(part));
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Mark the name as extra, since the ID is more important.
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        nameElement.className = "extra";
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var classAttribute = node.getAttribute("class");
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (classAttribute) {
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var classes = classAttribute.split(/\s+/);
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var foundClasses = {};
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (classes.length) {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            var classesElement = document.createElement("span");
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            classesElement.className = "extra";
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            parentElement.appendChild(classesElement);
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (var i = 0; i < classes.length; ++i) {
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var className = classes[i];
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (className && !(className in foundClasses)) {
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    var part = "." + className;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    title += part;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    classesElement.appendChild(document.createTextNode(part));
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    foundClasses[className] = true;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    parentElement.title = title;
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)/**
801e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) * @param {!Element} container
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * @param {string} nodeTitle
82926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) */
83926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)WebInspector.DOMPresentationUtils.createSpansForNodeTitle = function(container, nodeTitle)
84926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
85926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    var match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/);
86926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    container.createChild("span", "webkit-html-tag-name").textContent = match[1];
87926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (match[2])
88926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        container.createChild("span", "webkit-html-attribute-value").textContent = match[2];
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (match[3])
90926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        container.createChild("span", "webkit-html-attribute-name").textContent = match[3];
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var link = document.createElement("span");
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    link.className = "node-link";
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    link.addEventListener("click", WebInspector.domAgent.inspectElement.bind(WebInspector.domAgent, node.id), false);
100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    link.addEventListener("mouseover", WebInspector.domAgent.highlightDOMNode.bind(WebInspector.domAgent, node.id, "", undefined), false);
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    link.addEventListener("mouseout", WebInspector.domAgent.hideDOMNodeHighlight.bind(WebInspector.domAgent), false);
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return link;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.DOMPresentationUtils.linkifyNodeById = function(nodeId)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var node = WebInspector.domAgent.nodeForId(nodeId);
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!node)
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return document.createTextNode(WebInspector.UIString("<node>"));
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return WebInspector.DOMPresentationUtils.linkifyNodeReference(node);
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {string} imageURL
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * @param {boolean} showDimensions
117a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {function(!Element=)} userCallback
118a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @param {!Object=} precomputedDimensions
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WebInspector.DOMPresentationUtils.buildImagePreviewContents = function(imageURL, showDimensions, userCallback, precomputedDimensions)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var resource = WebInspector.resourceTreeModel.resourceForURL(imageURL);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resource) {
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        userCallback();
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    var imageElement = document.createElement("img");
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    imageElement.addEventListener("load", buildContent, false);
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    imageElement.addEventListener("error", errorCallback, false);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    resource.populateImageSource(imageElement);
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function errorCallback()
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Drop the event parameter when invoking userCallback.
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        userCallback();
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    function buildContent()
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var container = document.createElement("table");
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        container.className = "image-preview-container";
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var naturalWidth = precomputedDimensions ? precomputedDimensions.naturalWidth : imageElement.naturalWidth;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var naturalHeight = precomputedDimensions ? precomputedDimensions.naturalHeight : imageElement.naturalHeight;
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var offsetWidth = precomputedDimensions ? precomputedDimensions.offsetWidth : naturalWidth;
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var offsetHeight = precomputedDimensions ? precomputedDimensions.offsetHeight : naturalHeight;
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var description;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (showDimensions) {
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                description = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        container.createChild("tr").createChild("td", "image-container").appendChild(imageElement);
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (description)
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            container.createChild("tr").createChild("td").createChild("span", "description").textContent = description;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        userCallback(container);
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
16151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
16251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
16351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
16451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean=} justSelector
16551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @return {string}
16651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
16751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils.appropriateSelectorFor = function(node, justSelector)
16851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
16951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var lowerCaseName = node.localName() || node.nodeName().toLowerCase();
17051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (node.nodeType() !== Node.ELEMENT_NODE)
17151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return lowerCaseName;
17251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (lowerCaseName === "input" && node.getAttribute("type") && !node.getAttribute("id") && !node.getAttribute("class"))
17351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return lowerCaseName + "[type=\"" + node.getAttribute("type") + "\"]";
17451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
17551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return WebInspector.DOMPresentationUtils.cssPath(node, justSelector);
17651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
17751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
17851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
17951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
18051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean=} optimized
18151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @return {string}
18251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
18351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils.cssPath = function(node, optimized)
18451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
18551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (node.nodeType() !== Node.ELEMENT_NODE)
18651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return "";
18751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
18851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var steps = [];
18951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var contextNode = node;
19051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    while (contextNode) {
19151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var step = WebInspector.DOMPresentationUtils._cssPathValue(contextNode, optimized);
19251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!step)
19351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break; // Error - bail out early.
19451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        steps.push(step);
19551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (step.optimized)
19651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
19751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        contextNode = contextNode.parentNode;
19851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
19951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
20051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    steps.reverse();
20151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return steps.join(" > ");
20251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
20351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
20451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
20551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
20651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean=} optimized
207a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @return {?WebInspector.DOMNodePathStep}
20851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
20951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils._cssPathValue = function(node, optimized)
21051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
21151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (node.nodeType() !== Node.ELEMENT_NODE)
21251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return null;
21351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
21451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var id = node.getAttribute("id");
21551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (optimized) {
21651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (id)
21751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return new WebInspector.DOMNodePathStep(idSelector(id), true);
21851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var nodeNameLower = node.nodeName().toLowerCase();
21951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (nodeNameLower === "body" || nodeNameLower === "head" || nodeNameLower === "html")
22051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return new WebInspector.DOMNodePathStep(node.nodeNameInCorrectCase(), true);
22151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
22251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var nodeName = node.nodeNameInCorrectCase();
22351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
22451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (id)
22551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return new WebInspector.DOMNodePathStep(nodeName + idSelector(id), true);
22651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var parent = node.parentNode;
22751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!parent || parent.nodeType() === Node.DOCUMENT_NODE)
22851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return new WebInspector.DOMNodePathStep(nodeName, true);
22951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
23051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
231a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @param {!WebInspector.DOMNode} node
232a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)     * @return {!Array.<string>}
23351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
23451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function prefixedElementClassNames(node)
23551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
23651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var classAttribute = node.getAttribute("class");
23751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!classAttribute)
23851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return [];
23951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
24051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) {
24151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            // The prefix is required to store "__proto__" in a object-based map.
24251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return "$" + name;
24351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        });
24451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
24551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
24651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
24751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} id
24851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {string}
24951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
25051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function idSelector(id)
25151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
25251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return "#" + escapeIdentifierIfNeeded(id);
25351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
25451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
25551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
25651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} ident
25751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {string}
25851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
25951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function escapeIdentifierIfNeeded(ident)
26051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
26151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (isCSSIdentifier(ident))
26251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return ident;
26351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident);
26451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var lastIndex = ident.length - 1;
26551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return ident.replace(/./g, function(c, i) {
26651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? escapeAsciiChar(c, i === lastIndex) : c;
26751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        });
26851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
26951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
27051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
27151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} c
27251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {boolean} isLast
27351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {string}
27451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
27551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function escapeAsciiChar(c, isLast)
27651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
27751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return "\\" + toHexByte(c) + (isLast ? "" : " ");
27851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
27951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
28051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
28151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} c
28251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
28351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function toHexByte(c)
28451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
28551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var hexByte = c.charCodeAt(0).toString(16);
28651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (hexByte.length === 1)
28751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)          hexByte = "0" + hexByte;
28851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return hexByte;
28951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
29051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
29151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
29251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} c
29351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {boolean}
29451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
29551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function isCSSIdentChar(c)
29651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
29751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (/[a-zA-Z0-9_-]/.test(c))
29851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return true;
29951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return c.charCodeAt(0) >= 0xA0;
30051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
30151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
30251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
30351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @param {string} value
30451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {boolean}
30551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
30651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function isCSSIdentifier(value)
30751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
30851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return /^-?[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value);
30951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
31051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
31151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var prefixedOwnClassNamesArray = prefixedElementClassNames(node);
31251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var needsClassNames = false;
31351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var needsNthChild = false;
31451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var ownIndex = -1;
31551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var siblings = parent.children();
31651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) {
31751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var sibling = siblings[i];
31851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (sibling === node) {
31951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            ownIndex = i;
32051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            continue;
32151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
32251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (needsNthChild)
32351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            continue;
32451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (sibling.nodeNameInCorrectCase() !== nodeName)
32551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            continue;
32651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
32751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        needsClassNames = true;
32851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var ownClassNames = prefixedOwnClassNamesArray.keySet();
32951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var ownClassNameCount = 0;
33051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        for (var name in ownClassNames)
33151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            ++ownClassNameCount;
33251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (ownClassNameCount === 0) {
33351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            needsNthChild = true;
33451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            continue;
33551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
33651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var siblingClassNamesArray = prefixedElementClassNames(sibling);
33751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        for (var j = 0; j < siblingClassNamesArray.length; ++j) {
33851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            var siblingClass = siblingClassNamesArray[j];
33951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (!ownClassNames.hasOwnProperty(siblingClass))
34051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                continue;
34151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            delete ownClassNames[siblingClass];
34251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (!--ownClassNameCount) {
34351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                needsNthChild = true;
34451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                break;
34551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            }
34651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
34751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
34851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
34951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var result = nodeName;
35051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (needsNthChild) {
35151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        result += ":nth-child(" + (ownIndex + 1) + ")";
35251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    } else if (needsClassNames) {
35351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        for (var prefixedName in prefixedOwnClassNamesArray.keySet())
35451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            result += "." + escapeIdentifierIfNeeded(prefixedName.substr(1));
35551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
35651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
35751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return new WebInspector.DOMNodePathStep(result, false);
35851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
35951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
36051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
36151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
36251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean=} optimized
36351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @return {string}
36451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
36551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils.xPath = function(node, optimized)
36651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
36751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (node.nodeType() === Node.DOCUMENT_NODE)
36851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return "/";
36951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
37051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var steps = [];
37151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var contextNode = node;
37251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    while (contextNode) {
37351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var step = WebInspector.DOMPresentationUtils._xPathValue(contextNode, optimized);
37451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (!step)
37551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break; // Error - bail out early.
37651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        steps.push(step);
37751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (step.optimized)
37851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
37951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        contextNode = contextNode.parentNode;
38051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
38151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
38251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    steps.reverse();
38351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/");
38451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
38551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
38651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
38751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
38851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean=} optimized
389a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * @return {?WebInspector.DOMNodePathStep}
39051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
39151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils._xPathValue = function(node, optimized)
39251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
39351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var ownValue;
39451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var ownIndex = WebInspector.DOMPresentationUtils._xPathIndex(node);
39551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (ownIndex === -1)
39651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return null; // Error.
39751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
39851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    switch (node.nodeType()) {
39951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.ELEMENT_NODE:
40051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (optimized && node.getAttribute("id"))
40151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return new WebInspector.DOMNodePathStep("//*[@id=\"" + node.getAttribute("id") + "\"]", true);
40251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = node.localName();
40351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
40451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.ATTRIBUTE_NODE:
40551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "@" + node.nodeName();
40651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
40751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.TEXT_NODE:
40851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.CDATA_SECTION_NODE:
40951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "text()";
41051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
41151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.PROCESSING_INSTRUCTION_NODE:
41251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "processing-instruction()";
41351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
41451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.COMMENT_NODE:
41551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "comment()";
41651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
41751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    case Node.DOCUMENT_NODE:
41851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "";
41951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
42051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    default:
42151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue = "";
42251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        break;
42351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
42451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
42551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (ownIndex > 0)
42651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        ownValue += "[" + ownIndex + "]";
42751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
42851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return new WebInspector.DOMNodePathStep(ownValue, node.nodeType() === Node.DOCUMENT_NODE);
42951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)},
43051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
43151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
43251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {!WebInspector.DOMNode} node
43351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @return {number}
43451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
43551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMPresentationUtils._xPathIndex = function(node)
43651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
43751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    // Returns -1 in case of error, 0 if no siblings matching the same expression, <XPath index among the same expression-matching sibling nodes> otherwise.
43851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    function areNodesSimilar(left, right)
43951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
44051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (left === right)
44151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return true;
44251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
44351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.ELEMENT_NODE)
44451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return left.localName() === right.localName();
44551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
44651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (left.nodeType() === right.nodeType())
44751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            return true;
44851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
44951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        // XPath treats CDATA as text nodes.
45051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var leftType = left.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType();
45151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        var rightType = right.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right.nodeType();
45251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return leftType === rightType;
45351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
45451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
45551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var siblings = node.parentNode ? node.parentNode.children() : null;
45651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!siblings)
45751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return 0; // Root node - no siblings.
45851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var hasSameNamedElements;
45951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (var i = 0; i < siblings.length; ++i) {
46051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
46151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            hasSameNamedElements = true;
46251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            break;
46351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
46451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
46551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    if (!hasSameNamedElements)
46651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return 0;
46751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    var ownIndex = 1; // XPath indices start with 1.
46851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    for (var i = 0; i < siblings.length; ++i) {
46951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (areNodesSimilar(node, siblings[i])) {
47051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            if (siblings[i] === node)
47151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                return ownIndex;
47251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            ++ownIndex;
47351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        }
47451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
47551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return -1; // An error occurred: |node| not found in parent's children.
47651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
47751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
47851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)/**
47951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @constructor
48051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {string} value
48151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) * @param {boolean} optimized
48251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) */
48351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMNodePathStep = function(value, optimized)
48451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles){
48551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    this.value = value;
48651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    this.optimized = optimized || false;
48751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
48851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
48951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)WebInspector.DOMNodePathStep.prototype = {
49051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    /**
49151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     * @return {string}
49251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)     */
49351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    toString: function()
49451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
49551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        return this.value;
49651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    }
49751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)}
498