2

我正在尝试将类添加到文档中的选定文本。问题是我不希望用户能够选择页面上的所有文本(例如使用 command+A ...)所以我想从一个范围中删除节点,但我不知道如何要做到这一点。这个页面有很多文本/嵌套的 div,所以使用添加的类来检查它是否在一个可选择的元素中会非常耗时/慢。

我做了一个小提琴来解释我想要做得更好的事情。 http://jsfiddle.net/thomasjonas/BhKFt/20/

如果您选择此示例中的所有文本,则该类将添加到所有 div。我希望它只将 css 应用于具有“是”类的 div。有没有一个不错的、非浏览器崩溃的解决方案?

提前致谢!

4

1 回答 1

2

以下内容有点笨拙且效率低下,因为它检查每个带有“yes”类的元素与选择相交。例如,您可以通过提前检查选择是否完全位于具有“yes”类的单个元素中来改进它。它使用 Rangy 专有intersection()的范围对象方法。

演示:http: //jsfiddle.net/timdown/BhKFt/23/

代码:

// getElementsByClassName implementation for browsers without it
// (IE <= 7, for example)
var getElementsByClassName =
    (typeof document.documentElement.getElementsByClassName != "undefined") ?

    function(el, cssClass) {
        return el.getElementsByClassName(cssClass);
    } :
    function(el, cssClass) {
        var allEls = el.getElementsByTagName("*");
        var elsWithClass = [];
        var classRegex = new RegExp("(?:^|\\s)" + cssClass + "(?:\\s|$)");
        for (var i = 0, len = allEls.length, el; i < len; ++i) {
            el = allEls[i];
            if (el.className && classRegex.test(el.className)) {
                elsWithClass.push(el);
            }
        }
        return elsWithClass;
    };

$(document).ready(function(){
    rangy.init();
    $(document).mouseup(function(){
        var sel = rangy.getSelection();
        var range = sel.getRangeAt(0);
        var classApplier = rangy.createCssClassApplier("tmp");

        var els = getElementsByClassName(document.body, "yes");

        // Create an array of ranges that represent the intersection of
        // the selection with each "yes" element
        var rangesWithClass = [];
        for (var i = 0, len = els.length, elRange; i < len; ++i) {
            if (range.intersectsNode(els[i])) {
                elRange = rangy.createRange();
                elRange.selectNode(els[i]);
                rangesWithClass.push(range.intersection(elRange));
                elRange.detach();
            }
        }

        // Apply the class to the ranges obtained in the last step
        for (i = 0, len = rangesWithClass.length; i < len; ++i) {
            classApplier.applyToRange(rangesWithClass[i]);
            rangesWithClass[i].detach();
        }

        sel.removeAllRanges();
    });
});

如果传入的选项对象有某种过滤选项,这可能会很有用rangy.createCssClassApplier()。我会考虑的。

于 2012-09-08T11:04:51.160 回答