25

私は小さなテキストノードを持っています:

var node

そして、"lol" が出現するたびにスパンをラップしたいと思います。

node.nodeValue = node.nodeValue.replace(/lol/, "<span>lol</span>")

"<span>lol<span>"必要なときに"lol"スパン要素として出力します。

4

5 に答える 5

20

Andreas Josas が提示した答えは非常に優れています。ただし、検索用語が同じテキスト ノードに複数回出現する場合、コードにはいくつかのバグがありました。これらのバグが修正されたソリューションを次に示します。さらに、使用と理解を容易にするために挿入が matchText に組み込まれています。これで、新しいタグのみがコールバックで構築され、return によって matchText に戻されます。

バグ修正を含む更新された matchText 関数:

var matchText = function(node, regex, callback, excludeElements) { 

    excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
    var child = node.firstChild;

    while (child) {
        switch (child.nodeType) {
        case 1:
            if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1)
                break;
            matchText(child, regex, callback, excludeElements);
            break;
        case 3:
            var bk = 0;
            child.data.replace(regex, function(all) {
                var args = [].slice.call(arguments),
                    offset = args[args.length - 2],
                    newTextNode = child.splitText(offset+bk), tag;
                bk -= child.data.length + all.length;

                newTextNode.data = newTextNode.data.substr(all.length);
                tag = callback.apply(window, [child].concat(args));
                child.parentNode.insertBefore(tag, newTextNode);
                child = newTextNode;
            });
            regex.lastIndex = 0;
            break;
        }

        child = child.nextSibling;
    }

    return node;
};

使用法:

matchText(document.getElementsByTagName("article")[0], new RegExp("\\b" + searchTerm + "\\b", "g"), function(node, match, offset) {
    var span = document.createElement("span");
    span.className = "search-term";
    span.textContent = match;
    return span;
});

span タグの代わりにアンカー (リンク) タグを挿入する場合は、create 要素を「span」ではなく「a」に変更し、href 属性をタグに追加する行を追加し、excludeElements に「a」を追加します。リンク内にリンクが作成されないようにします。

于 2015-03-27T13:23:41.300 に答える
17

次の記事では、テキストを HTML 要素に置き換えるコードを示します。

http://blog.alexanderdickson.com/javascript-replaceing-text

記事から:

var matchText = function(node, regex, callback, excludeElements) { 

    excludeElements || (excludeElements = ['script', 'style', 'iframe', 'canvas']);
    var child = node.firstChild;

    do {
        switch (child.nodeType) {
        case 1:
            if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1) {
                continue;
            }
            matchText(child, regex, callback, excludeElements);
            break;
        case 3:
           child.data.replace(regex, function(all) {
                var args = [].slice.call(arguments),
                    offset = args[args.length - 2],
                    newTextNode = child.splitText(offset);

                newTextNode.data = newTextNode.data.substr(all.length);
                callback.apply(window, [child].concat(args));
                child = newTextNode;
            });
            break;
        }
    } while (child = child.nextSibling);

    return node;
}

使用法:

matchText(document.getElementsByTagName("article")[0], new RegExp("\\b" + searchTerm + "\\b", "g"), function(node, match, offset) {
    var span = document.createElement("span");
    span.className = "search-term";
    span.textContent = match;
    node.parentNode.insertBefore(span, node.nextSibling); 
});

そして説明:

基本的に、それを行う正しい方法は…</p>

  1. すべてのテキスト ノードを反復処理します。
  2. テキスト ノードで部分文字列を検索します。
  3. オフセットで分割します。
  4. 分割の間にスパン要素を挿入します。
于 2013-05-21T05:06:28.453 に答える