最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do you pinpoint a word or a selection in the entire document? - Stack Overflow

programmeradmin0浏览0评论

I am trying to highlight a part of the text on my website. This highlighted text will be saved for the specific user in a database and when the document is opened again it will show the previously highlighted text. I assumed I would be using javascript to highlight the text but I cannot seem to find a way to pinpoint where the word is that I am highlighting.

function getSelText()
{
    var txt = '';
     if (window.getSelection)
    {
        txt = window.getSelection();
             }
    else if (document.getSelection)
    {
        txt = document.getSelection();
            }
    else if (document.selection)
    {
        txt = document.selection.createRange().text;
            }
    else return "";
    return txt;
}

I am using that to get the selection but I cannot figure out where the selection is in the text. The biggest annoyance is when I have duplicates within the line or text so if I were to use search then I would find the first instance and not the one I was looking for.

So the question is : How do you pinpoint a word or a selection in the entire document?

I am trying to highlight a part of the text on my website. This highlighted text will be saved for the specific user in a database and when the document is opened again it will show the previously highlighted text. I assumed I would be using javascript to highlight the text but I cannot seem to find a way to pinpoint where the word is that I am highlighting.

function getSelText()
{
    var txt = '';
     if (window.getSelection)
    {
        txt = window.getSelection();
             }
    else if (document.getSelection)
    {
        txt = document.getSelection();
            }
    else if (document.selection)
    {
        txt = document.selection.createRange().text;
            }
    else return "";
    return txt;
}

I am using that to get the selection but I cannot figure out where the selection is in the text. The biggest annoyance is when I have duplicates within the line or text so if I were to use search then I would find the first instance and not the one I was looking for.

So the question is : How do you pinpoint a word or a selection in the entire document?

Share Improve this question edited Mar 7, 2011 at 9:13 Greg 21.9k17 gold badges88 silver badges109 bronze badges asked Mar 7, 2011 at 2:35 vmanvman 3211 gold badge4 silver badges11 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 4

You can use my Rangy library and its selection serialization module for this. Rangy's core provides a consistent Selection and Range API for all browsers and the serializer module builds on this by converting each selection boundary into a path through the document. See the linked documentation for more details.

This certainly isn't a trivial task, since you're faced with the two major problems of locating the text in the current document, and then being able to find it again on a subsequent page load. The problem is further plicated if the content of your page is subject to change, since you can't even rely on the relative position of the text to stay the same.

You may want to consider whether or not this is the best approach for whatever you're trying to acplish given the effort required, but here's something that might get you started in the right direction:

function getSelection() {
    var selection, position;

    if (window.getSelection) {
        selection = window.getSelection();

        if (selection && !selection.isCollapsed) {
            position = {
                'offset': selection.anchorOffset,
                'length': selection.toString().length,
                // We're assuming this will be a text node
                'node': selection.anchorNode.parentNode
            };
        }
    } else if (document.selection) {
        selection = document.selection.createRange();

        if (selection && selection.text.length) {
            var text = selection.parentElement().innerText,
                range = document.body.createTextRange(),
                last = 0, index = -1;

            range.moveToElementText(selection.parentElement());

            // Figure out which instance of the selected text in the overall
            // text is the correct one by walking through the occurrences
            while ((index = text.indexOf(selection.text, ++index)) !== -1) {
                range.moveStart('character', index - last);
                last = index;

                if (selection.offsetLeft == range.offsetLeft && selection.offsetTop == range.offsetTop) {
                    break;
                }
            }

            position = {
                'offset': index,
                'length': selection.text.length,
                'node': selection.parentElement()
            };
        }
    }

    return position;
}

As well as a method to select the text again:

function setSelection(position) {
    if (!position || !position.node) {
        return;
    }

    var selection, range, element;

    if (document.createRange) {
        element = position.node.childNodes[0];
        range = document.createRange();
        range.setStart(element, position.offset);
        range.setEnd(element, position.offset + position.length);
        selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(range);
    } else if (document.body.createTextRange) {
        range = document.body.createTextRange();
        range.moveToElementText(position.node);
        range.collapse(true);
        range.move('character', position.offset);
        range.moveEnd('character', position.length);
        range.select();
    }
}

This code makes the rather naïve assumption that the selected text all resides in the same DOM element. Chances are high that if a user is selecting arbitrary text this won't be the case.

Given that the Selection object accounts for this with the anchorNode and focusNode properties, you could try and work around this, though dealing with the TextRange object in Internet Explorer might prove to be a bit more problematic.

There's also the problem of how to keep track of the position.node value across page requests. In my jsFiddle sample, I've used a slightly modified version of a selector-generating jQuery function to generate a selector string that can be saved and used to reselect the correct node later on. Note that the process is relatively trivial, so you could easily do it without jQuery – it just happened to save some effort in this case.

Of course if you're changing the DOM between visits, this approach will likely be fairly unstable. If you aren't though, I feel like it's probably one of the more reliable options.

createRange creates a textRange object. It has all kinds of useful information:

            var range = document.selection.createRange();

            var left = range.boundingLeft;
            var top = range.boundingTop;
发布评论

评论列表(0)

  1. 暂无评论