XPath Tester

  • /*
     * @title XPath Tester
     * @description my bookmarklet
     * @include http://*
     * @license MIT License
     * @require 
     */
    
    // XPathFinder.js
    //  by motormean <motormean@s58.xrea.com>
    // ver 0.1
    var XPathFinder = {
        findBar: null,
        finderInput: null,
        alwaysUseAsContext: null,
        lastXPathQuery: null,
        lastFoundNode: null,
        foundNodes: null,
        nodeIndex: 0,
        ignoredNodes: null,
        contextNode: null,
        init: function() {
            XPathFinder.findBar = document.createElement('div');
            with(XPathFinder.findBar) {
                setAttribute('id', 'XPathFinder-findBar');
                style.fontSize = 'smaller';
                style.backgroundColor = 'infobackground';
                style.position = 'fixed';
                style.top = '0';
                style.left = '0';
                style.margin = '0';
                style.width = '100%';
                style.borderBottom = '2px solid';
                style.padding = '2px';
                style.zIndex = "23455";
                style.overflow = "auto";
                innerHTML = '<input type="text" id="XPathFinder-input" style="width: 40%;" onkeydown="XPathFinder.checkKey(event);"><button onclick="XPathFinder.findNext();">XPath Search</button> <input type="checkbox" id="XPathFinder-always"><label for="XPathFinder-always">always</label></input> <button onclick="XPathFinder.setContextNode();">use the found node as context node</button>';
                addEventListener('click', function(aEvent) {
                    if (aEvent.target.id == 'XPathFinder-findBar') XPathFinder.closeFindBar();
                }, true);
            }
            document.body.appendChild(XPathFinder.findBar);
            XPathFinder.finderInput = document.getElementById('XPathFinder-input');
            XPathFinder.alwaysUseAsContext = document.getElementById('XPathFinder-always');
            XPathFinder.finderInput.focus();
    
        },
        startFind: function(aQuery) {
            try {
                XPathFinder.foundNodes =
                document.evaluate(
                aQuery, XPathFinder.contextNode || document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            }
            catch (e) {
                return false;
            }
            XPathFinder.nodeIndex = 0;
            XPathFinder.lastXPathQuery = aQuery;
            XPathFinder.ignoredNodes = new Object();
            return true;
        },
        findNext: function() {
            if (XPathFinder.lastFoundNode) XPathFinder.toggleHighlight(XPathFinder.lastFoundNode);
            if (XPathFinder.alwaysUseAsContext.checked) XPathFinder.setContextNode();
            if (!XPathFinder.foundNodes || XPathFinder.lastXPathQuery != XPathFinder.finderInput.value) if (!XPathFinder.startFind(XPathFinder.finderInput.value)) return;
            var found = XPathFinder.foundNodes.snapshotItem(XPathFinder.nodeIndex);
            while (XPathFinder.checkComponent(XPathFinder.nodeIndex++)) {
                if (XPathFinder.ignoredNodes.length == XPathFinder.foundNodes.snapshotLength) return;
                if (XPathFinder.nodeIndex > XPathFinder.foundNodes.snapshotLength - 1) XPathFinder.nodeIndex = 0;
                found = XPathFinder.foundNodes.snapshotItem(XPathFinder.nodeIndex);
            }
            XPathFinder.toggleHighlight(XPathFinder.lastFoundNode = found);
            XPathFinder.scrollTo(found);
            if (XPathFinder.nodeIndex > XPathFinder.foundNodes.snapshotLength - 1) XPathFinder.nodeIndex = 0;
        },
        setContextNode: function() {
            XPathFinder.contextNode = XPathFinder.lastFoundNode;
            XPathFinder.startFind(XPathFinder.finderInput.value);
        },
        scrollTo: function(aNode) {
            var left = 0;
            var top = 0;
            while (aNode) {
                left += aNode.offsetLeft;
                top += aNode.offsetTop;
                aNode = aNode.offsetParent;
            }
            window.scrollTo(left, top - XPathFinder.findBar.offsetHeight - 10);
        },
        checkKey: function(aEvent) {
            if (aEvent.keyCode == 13 || aEvent.keyCode == 114) XPathFinder.findNext();
            else if (aEvent.keyCode == 27) XPathFinder.closeFindBar();
        },
        closeFindBar: function(aEvent) {
            XPathFinder.toggleHighlight(XPathFinder.lastFoundNode);
            document.body.removeChild(XPathFinder.findBar);
        },
        toggleHighlight: function(aElement) {
            if (!aElement || !aElement.style) return;
            if (aElement.__XPathFinder_SavedBackgroundColor != undefined) {
                aElement.style.backgroundColor = aElement.__XPathFinder_SavedBackgroundColor;
                delete aElement.__XPathFinder_SavedBackgroundColor;
            }
            else {
                aElement.__XPathFinder_SavedBackgroundColor = aElement.style.backgroundColor;
                aElement.style.backgroundColor = 'yellow';
            }
        },
        checkComponent: function(aIndex) {
            if (XPathFinder.ignoredNodes[aIndex]) return true;
            var aNode = XPathFinder.foundNodes.snapshotItem(aIndex);
            for (; aNode && aNode != document.body; aNode = aNode.parentNode) {
                if (aNode.id == 'XPathFinder-findBar') {
                    XPathFinder.ignoredNodes[aIndex] = aNode;
                    return true;
                }
            }
            return false;
        }
    };
    XPathFinder.init();
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2010/08/11 17:33:57 - 2010-08-11