9

要素内の複数の強調表示されたテキスト用の jquery プラグインを探しています。まさにそのための非常に人気のあるプラグインを見つけました: http://bartaz.github.com/sandbox.js/jquery.highlight.htmlと他の多くのプラグイン。

それらは正常に機能しますが、以前に強調表示されたテキストと重なるテキストを強調表示したい場合は機能しません。

複数の強調表示されたテキストをサポートし、重なったテキストを正しく強調表示する jquery または javascript プラグインを知っている人はいますか?

4

1 に答える 1

15

いくつかの小さな調整を追加すれば、見つけたハイライタープラグインですべてを行うことができます. 図として、今日の午後にすぐにまとめた実際の例をフィドルするために投稿しました:http://jsfiddle.net/4bwgA/

ここでは、プラグイン (OP が参照する) が既に実行しているすべてのことをステップバイステップで説明し、最後に重複する強調表示された領域の解決策を示します。

蛍光ペンの機能は、適用する単語の周りにタグを付けることです。だからあなたが持っているなら

   <p>Who is the quick brown fox?</p>

そして、「茶色」という単語を強調表示しました

   $("p").highlight("brown");

あなたが得る

   <p>Who is the quick <span class="highlight">brown</span> fox?</p>

そして追加コマンド

   $("p").highlight("brown fox");

何も見つかりません。これは、茶色の周りにタグが付けられたため、文字列にこの部分文字列がなくなったためです。

オーバーラップについてだけであれば、解決策は簡単です。パッケージは、新しい強調表示の前に適用できる強調表示解除機能を提供します

   $("p").unhighlight().highlight("brown fox");

そして得る

   <p>Who is the quick <span class="highlight">brown fox</span>?</p>

今のところ、これはエキサイティングなことではありません。しかし、一度に「茶色」を強調表示し、次に「キツネ」を強調表示した場合はどうなるでしょうか。これを取得します

   <p>Who is the quick <span class="highlight">brown</span> <span class="highlight">fox</span>?</p>

次に、隣接する強調表示された領域を結合します。これは、次のような追加の関数を使用して実行できます。

    function mergenode(node) {
        var parent1 = node.contents();
        parent1.each(function (i) {
            if (i > 0 && this.nodeType !== 1 && //if text node
                this.data.search(/^\s*$/g) === 0 && //consisting only of hyphens or blanks
                parent1[i - 1].nodeName === "SPAN" && //bordering to SPAN elements
                parent1[i + 1].nodeName === "SPAN" && 
                parent1[i - 1].className === "highlight" && //of class highlight
                parent1[i + 1].className === "highlight") {
                    selected1.push(parent1[i - 1]
                        .textContent.concat(this.data, parent1[i + 1].textContent));
            }
            else if (this.nodeType === 1 && 
                this.nodeName === "SPAN" && 
                parent1[i + 1].nodeName === "SPAN" && 
                this.className === "highlight" && 
                parent1[i + 1].className === "highlight") {
                    selected1.push(this.textContent.concat(parent1[i + 1].textContent));
            }
        });
        $(node).unhighlight().highlight(selected1);
    }

これにより、隣接するすべてのスパンがクラス ハイライトとマージされます (これは一般的なハイライター タグ用に記述されていますが、カスタム タグ用の nodeName と className の 2 つの追加引数で簡単に拡張できます)。結果は次のようになります

    <p>Who is the quick <span class="highlight">brown fox</span>?</p>

これまでのところすべて順調です。しかし、検索文字列が重複しているとどうなるでしょうか?!!! 最初に...オーバーラップを処理する最善の方法は、クリアされたテキストでオーバーラップしている文字列をチェックする前に、古い選択を選択解除することです。このためには、前の選択を覚えておく必要があります。これは、たとえば、selected1追加の選択ごとに追加される値を取得する配列 (私は it と呼びます) に保存できます。

実行ごとに、最終的な選択 (すべてマージ) がselected1配列に保存されるため、将来のマージとオーバーラップに使用できます。

では、ハイライターは文字列の配列をどのように処理するのでしょうか? 関数に渡された順序でそれぞれにハイライト関数を適用します。そのため、2 つの文字列が完全に重なっている場合は、選択文字列の配列を並べ替えて、最初に長い文字列を強調表示するだけで対処できます。例えば

    $("p").highlight(["brown fox","brown"]);

ハイライトするだけ

    <p>Who is the quick <span class="highlight">brown fox</span>?</p>

配列は、このようなもので長さでソートできます

    words = words.sort(function (str1, str2) {
        return (str1.length < str2.length) ? 1 : 0;
    });

完全に重なり合うハイライトと隣接するハイライトが処理されます。ここで、部分的に重複する文字列を確実に取得する必要があります。ここで、2 つの文字列のオーバーラップを比較する関数を作成しました...これを行う方法は他にもありますが、この回答で示したいのは、ほとんどの場合、強調表示を目的の方法で取得するために必要な一連の手順です。したい =)

この関数は 2 つの文字列を取り、重複しているかどうかを確認し、重複している場合はそれらを結合し、結合された新しい文字列を配列に保存toselectし、最後に元の配列に追加しwordsます。いくつかの役に立たない組み合わせがあるかもしれませんが、それは害にはなりません - それらは最後には表示されません.

    function overlap(a, b) {
        var l = b.length,
            m = a.length;
        for (var j = 1; j < l; j++) {
            if (a.indexOf(b.substr(l - j)) === 0) {
                toselect.push(b.concat(a.substr(j)));
            } else if (a.substr(m - j).indexOf(b.substr(0, j)) === 0) {
                toselect.push(a.concat(b.substr(j)));
            }
        }
    }

words次に、この関数を配列内の可能なすべての要素のペアに適用します。これをループで繰り返すこともできましたが、少し興奮してこれを行いました

    $.each(arr, function (i) {
        $.each(arr.slice(i + 1), function (i, v) {
            overlap(arr[i], v);
        });
    });

ここでtoselect、重複する可能性のあるすべての文字列が連結された新しい配列を元の配列に追加する必要がありますwords

これで、必要なすべての部品が揃ったので、それらを組み立てることができます。新しい文字列または文字列の配列を強調表示するたびに、次の手順を実行します。

  1. 現在強調表示されているすべての強調表示を解除します (強調表示されたものはすべてselected1配列に含まれます)。
  2. 新しい文字列または文字列の配列が配列に入りwordsます
  3. selected1に追加words
  4. 部分的に重複する文字列のペアをすべて結合しwords、新しい結合文字列を追加しますwords(overlap配列全体を反復処理する関数とそのラッパーを使用 -overdiagフィドルの例)
  5. 文字列の長さで並べ替えwords、最長の文字列が最初に来るようにする
  6. のすべての文字列を強調表示しますwords
  7. 強調表示されたすべての隣接する文字列をマージします (mergenode関数を使用)
  8. 強調表示された文字列の最終的なセットは、selected1

今日の午後、これをすばやくまとめたので、アイデアの完全な実装ではありませんが、機能します =) コードを蛍光ペン スクリプトに追加し、http://jsfiddleで再生できるように jsfiddle の簡単な例に追加しました.net/4bwgA/ . ボタンがあるので、すべての異なるステップを押して、その動作を確認できます。

于 2013-03-03T03:44:02.400 に答える