javascript用户选择突出显示 [英] javascript user selection highlighting

查看:118
本文介绍了javascript用户选择突出显示的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用javascript来突出显示用户点击某个奇怪突出显示按钮时所选择的文本(如< span style =background-color:yellow>突出显示的文字< / span> )。它只需要与WebKit或Firefox一起使用,但它似乎几乎不可能,因为它必须在以下情况下工作:

I'm trying to find a way with javascript to highlight the text the user selects when they click some odd highlight button (as in <span style="background-color:yellow">highlighted text</span>). It only has to work with either WebKit or Firefox, but it seems to be well nigh impossible because it has to work in the following cases:

<p>this is text</p>
<p>I eat food</p>

当用户在浏览器中选择is text到I eat时(不能)只是把它放在那里)。

When the user selects from "is text" through "I eat" in the browser (can't just put a span there).

和这种情况:

<span><span>this is text</span>middle text<span>this is text</span></span>

当用户在浏览器中选择is text到this is时(即使你可以在选区中的每个元素周围包装你的高光跨度,我希望你看到你试图让中间文字突出显示。)

When the user selects from "is text" to "this is" in the browser (even though you can wrap your highlight spans around each element in the selection, I'd like to see you try to get that middle text highlighted).

这个问题似乎没有在任何地方都可以解决,坦率地说我怀疑它是否可能。

This problem doesn't seem to be solved anywhere, frankly I doubt it's possible.

如果你能从选择中得到的范围作为一个完整的html字符串可能是可能的解析然后替换,但据我所知,你不能得到一个范围的原始html ..可惜。

It would be possible if you could get the Range that you get from the selection as a string complete with html which could be parsed and then replaced, but as far as I can tell you can't get the raw html of a Range.. pity.

推荐答案

这个答案对你来说可能要晚了几年,但是我遇到了类似的问题并且想在这里记录,因为它是google上的第一个。

This answer is probably a few years too late for you, but I faced a similar problem and wanted to document it here, since it is the first hit on google.

重申一下,问题是你想从用户选择中捕获Range对象并用样式div包围它,如下所示:

To reiterate, the problem is that you would like to just capture the Range object from the User Selection and surround it with a styled div, like so:

function highlightSelection() {
    var userSelection = window.getSelection().getRangeAt(0);
    highlightRange(userSelection);

}

function highlightRange(range) {
    var newNode = document.createElement("div");
    newNode.setAttribute(
       "style",
       "background-color: yellow; display: inline;"
    );
    range.surroundContents(newNode);
}

但正如原始父母所述,这是不安全的。如果选择不跨越元素边界,它将起作用,但如果用户选择创建的范围是跨越HTML标记边界的不安全范围,它将抛出DOM错误。

But as Original Parent states, this is unsafe. It will work if the selection does not cross element boundaries, but it will throw a DOM eror if the Range created by the User Selection is an unsafe range which crosses the boundaries of HTML tags.

解决方案是生成一个较小的Range对象数组,这些对象都没有单独穿过元素屏障,但它们共同覆盖选定的范围由用户。这些安全范围中的每一个都可以如上突出显示。

The solution is to produce an array of smaller Range objects, none of which individually crosses an element barrier, but which collectively cover the Range selected by the user. Each of these safe Ranges can be highlighted as above.

function getSafeRanges(dangerous) {
    var a = dangerous.commonAncestorContainer;
    // Starts -- Work inward from the start, selecting the largest safe range
    var s = new Array(0), rs = new Array(0);
    if (dangerous.startContainer != a)
        for(var i = dangerous.startContainer; i != a; i = i.parentNode)
            s.push(i)
    ;
    if (0 < s.length) for(var i = 0; i < s.length; i++) {
        var xs = document.createRange();
        if (i) {
            xs.setStartAfter(s[i-1]);
            xs.setEndAfter(s[i].lastChild);
        }
        else {
            xs.setStart(s[i], dangerous.startOffset);
            xs.setEndAfter(
                (s[i].nodeType == Node.TEXT_NODE)
                ? s[i] : s[i].lastChild
            );
        }
        rs.push(xs);
    }

    // Ends -- basically the same code reversed
    var e = new Array(0), re = new Array(0);
    if (dangerous.endContainer != a)
        for(var i = dangerous.endContainer; i != a; i = i.parentNode)
            e.push(i)
    ;
    if (0 < e.length) for(var i = 0; i < e.length; i++) {
        var xe = document.createRange();
        if (i) {
            xe.setStartBefore(e[i].firstChild);
            xe.setEndBefore(e[i-1]);
        }
        else {
            xe.setStartBefore(
                (e[i].nodeType == Node.TEXT_NODE)
                ? e[i] : e[i].firstChild
            );
            xe.setEnd(e[i], dangerous.endOffset);
        }
        re.unshift(xe);
    }

    // Middle -- the uncaptured middle
    if ((0 < s.length) && (0 < e.length)) {
        var xm = document.createRange();
        xm.setStartAfter(s[s.length - 1]);
        xm.setEndBefore(e[e.length - 1]);
    }
    else {
        return [dangerous];
    }

    // Concat
    rs.push(xm);
    response = rs.concat(re);    

    // Send to Console
    return response;
}

然后可以(似乎)突出显示用户选择修改后的代码:

It is then possible to (appear to) highlight the User Selection, with this modified code:

function highlightSelection() {
    var userSelection = window.getSelection().getRangeAt(0);
    var safeRanges = getSafeRanges(userSelection);
    for (var i = 0; i < safeRanges.length; i++) {
        highlightRange(safeRanges[i]);
    }
}






请注意,您可能需要一些更高级的CSS来使用户可以看起来很好的许多不同的元素。我希望最终这会帮助互联网上的其他一些疲惫的灵魂!


Note that you'' probably need some fancier CSS to make the many disparate elements a user could look nice together. I hope that eventually this helps some other weary soul on the internet!

这篇关于javascript用户选择突出显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆