2

ドキュメントで選択したテキストにクラスを追加しようとしています。問題は、ユーザーがページ上のすべてのテキストを選択できるようにしたくないことです (たとえば、コマンド + A を使用して...)。したがって、範囲からノードを削除したいのですが、方法がわかりませんそれをするために。このページには多くのテキスト/ネストされた div があるため、追加されたクラスを使用して選択可能な要素にあるかどうかを確認すると、非常に時間がかかり/遅くなります。

もう少しうまくやろうとしていることを説明するためにフィドルを作りました。 http://jsfiddle.net/thomasjonas/BhKFt/20/

この例ですべてのテキストを選択すると、クラスがすべての div に追加されます。「はい」クラスのdivにのみcssを適用したい。これに対する、ブラウザがクラッシュしない優れた解決策はありますか?

前もって感謝します!

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();
    });
});

に渡されたoptionsオブジェクトに何らかのフィルタリングオプションがあると便利な場合がありますrangy.createCssClassApplier()。考えてみます。

于 2012-09-08T11:04:51.160 に答える