获取所选文本的xpath

时间:2013-04-12 08:44:44

标签: javascript browser

我正在创建一个epub书籍阅读器。显示书籍后,我想让用户在书中添加一些注释。

要显示这本书,我正在使用加载本地html文件的wpf webbrowser控件

我想通过创建上下文菜单或显示弹出窗口来操作此控件上的选定文本

我需要使用javascript函数获取所选文本的xpath

var uiWebview_xpath = "";

function uiWebview_storeSelection() 
{
    if (typeof window.getSelection != 'undefined')
     {
        var selection = window.getSelection();
        var range = selection.getRangeAt(0);//two range, absolute and relative
        if (range != null) 
        {
            uiWebview_xpath = makeXPath(range.startContainer) + '|' + range.startOffset + '|' + makeXPath(range.endContainer) + '|' + range.endOffset;
            // var x = document.getElementsByName("Hidden1");
            // x.value = uiWebview_xpath;
            return uiWebview_xpath;

        }

}

else if (typeof document.selection != "undefined") {

    if (document.selection.type == "Text") {

        html = document.selection.createRange().htmlText;

    }

    return  html;
}
}

但是我发现我没有使用这个函数的第一部分而且我得到的是第二部分返回的html,我想为这个html创建xPath

//http://home.arcor.de/martin.honnen/javascript/storingSelection1.html

function nsResolver(prefix){
    var ns = {
        'mathml' : 'http://www.w3.org/1998/Math/MathML', // for example's sake only
        'h' : 'http://www.w3.org/1999/xhtml'
    };
    return ns[prefix];
}

function makeXPath (node, currentPath) {
    /* this should suffice in HTML documents for selectable nodes, XML with namespaces needs more code */
    currentPath = currentPath || '';
    switch (node.nodeType) {
        case 3:
        case 4:
            return makeXPath(node.parentNode, 'text()[' + (document.evaluate('preceding-sibling::text()', node, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']');
        case 1:
            return makeXPath(node.parentNode, node.tagName + '[' + (document.evaluate('preceding-sibling::' + 'h:' + node.tagName, node, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']' + (currentPath ? '/' + currentPath : ''));
        case 9:
            return '/' + currentPath;
        default:
            return '';
    }
}  

我是编程的初学者,我正在寻找指示和帮助,我也想知道webbrowser控件的版本是否会影响我得到的结果 “document.selection!=”undefined“和”window.getSelection!='undefined'“

之间的区别是什么?

1 个答案:

答案 0 :(得分:0)

我曾经遇到过这个问题。您所要做的就是添加IE浏览器无法识别的功能。

  1. 首先,您必须使用ierange来提供对象范围而不是TextRange

  2. 使用wgxpath为您提供重要功能,即document.evaluate

  3. 这是我的代码:

        function fixIERangeObject(range, win) { //Only for IE8 and below.
            win = win || window;
    
            if (!range) return null;
            if (!range.startContainer && win.document.selection) { //IE8 and below
    
                var _findTextNode = function (parentElement, text) {
                    //Iterate through all the child text nodes and check for matches
                    //As we go through each text node keep removing the text value (substring) from the beginning of the text variable.
                    var container = null, offset = -1;
                    for (var node = parentElement.firstChild; node; node = node.nextSibling) {
                        if (node.nodeType == 3) {//Text node
                            var find = node.nodeValue;
                            var pos = text.indexOf(find);
                            if (pos == 0 && text != find) { //text==find is a special case
                                text = text.substring(find.length);
                            } else {
                                container = node;
                                offset = text.length - 1; //Offset to the last character of text. text[text.length-1] will give the last character.
                                break;
                            }
                        }
                    }
                    //Debug Message
                    //alert(container.nodeValue);
                    return { node: container, offset: offset }; //nodeInfo
                }
    
                var rangeCopy1 = range.duplicate(), rangeCopy2 = range.duplicate(); //Create a copy
                var rangeObj1 = range.duplicate(), rangeObj2 = range.duplicate(); //More copies :P
    
                rangeCopy1.collapse(true); //Go to beginning of the selection
                rangeCopy1.moveEnd('character', 1); //Select only the first character
                rangeCopy2.collapse(false); //Go to the end of the selection
                rangeCopy2.moveStart('character', -1); //Select only the last character
    
                //Debug Message
                // alert(rangeCopy1.text); //Should be the first character of the selection
                var parentElement1 = rangeCopy1.parentElement(), parentElement2 = rangeCopy2.parentElement();
    
    
                rangeObj1.moveToElementText(parentElement1); //Select all text of parentElement
                rangeObj1.setEndPoint('EndToEnd', rangeCopy1); //Set end point to the first character of the 'real' selection
                rangeObj2.moveToElementText(parentElement2);
                rangeObj2.setEndPoint('EndToEnd', rangeCopy2); //Set end point to the last character of the 'real' selection
    
                var text1 = rangeObj1.text; //Now we get all text from parentElement's first character upto the real selection's first character    
                var text2 = rangeObj2.text; //Here we get all text from parentElement's first character upto the real selection's last character
    
                var nodeInfo1 = _findTextNode(parentElement1, text1);
                var nodeInfo2 = _findTextNode(parentElement2, text2);
    
                //Finally we are here
                range.startContainer = nodeInfo1.node;
                range.startOffset = nodeInfo1.offset;
                range.endContainer = nodeInfo2.node;
                range.endOffset = nodeInfo2.offset + 1; //End offset comes 1 position after the last character of selection.
            }
            return range;
        }
    
        function getRangeObject(win) { //Gets the first range object
            win = win || window;
            if (win.getSelection) { // Firefox/Chrome/Safari/Opera/IE9
                try {
                    return win.getSelection().getRangeAt(0); //W3C DOM Range Object
                } catch (e) { /*If no text is selected an exception might be thrown*/ }
            }
            else if (win.document.selection) { // IE8
                var range = win.document.selection.createRange(); //Microsoft TextRange Object
                return fixIERangeObject(range, win);
            }
            return null;
        }
    
            function nsResolver(prefix) {
                var ns = {
                    'mathml': 'http://www.w3.org/1998/Math/MathML', // for example's sake only
                    'h': 'http://www.w3.org/1999/xhtml'
                };
                return ns[prefix];
            }
    
            function makeXPath(node, currentPath) {
                /* this should suffice in HTML documents for selectable nodes, XML with namespaces needs more code */
                currentPath = currentPath || '';
                switch (node.nodeType) {
                    case 3:
                    case 4:
                        return makeXPath(node.parentNode, 'text()[' + (document.evaluate('preceding-sibling::text()', node, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']');
                    case 1:
                        return makeXPath(node.parentNode, node.tagName + '[' + (document.evaluate('preceding-sibling::' + 'h:' + node.tagName, node, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength + 1) + ']' + (currentPath ? '/' + currentPath : ''));
                    case 9:
                        return '/' + currentPath;
                    default:
                        return '';
                }
            }
    
             var uiWebview_xpath = "";
    
        function uiWebview_storeSelection() {
    
        if (typeof window.getSelection != 'undefined') {
        wgxpath.install(window);
        var selection = window.getSelection();
        var range = selection.getRangeAt(0); //two range, absolute and relative
        if (range != null) {
        uiWebview_xpath = makeXPath(range.startContainer) + '|' + range.startOffset + '|' + makeXPath(range.endContainer) + '|' + range.endOffset;
        alert(uiWebview_xpath);
        return uiWebview_xpath;
    
        }
    
        }
    
        else if (typeof document.selection != "undefined") {
            wgxpath.install();
            var range = getRangeObject();
            if (range != null) {
                uiWebview_xpath = makeXPath(range.startContainer) + '|' + range.startOffset + '|' + makeXPath(range.endContainer) + '|' + range.endOffset;
                alert("D"+uiWebview_xpath);
                return uiWebview_xpath;
    
            }
    
    
    //        if (document.selection.type == "Text") {
    
    //            html = document.selection.createRange().htmlText;
    
    //            alert(html);
    
    
    
    //        }
    
            return "elsif\n:" + "html\n:" + html;
        }
        }