1

我正在创建一个 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!='未定义'”

4

1 回答 1

0

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

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

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

这是我的代码:

    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;
    }
    }
于 2013-05-14T10:37:54.603 回答