如何使用HTML标记包装文本但排除某些HTML标记内的文本

时间:2015-05-29 11:37:56

标签: javascript

我正在创建一些功能来突出显示页面上的文字。这将围绕给定单词包裹span标签。我已经完成了这项任务,但会解释一下。

代码的工作方式是在页面首次加载时获取innerHTML,并将其存储在内存中(因此我有原始内容的副本)。

然后我获取innerHTML的副本(称为copyInnerHtml) - 然后我在copyInnerHtml上找到搜索词,并用<span id="find-iteration">包装它们(其中迭代是一个唯一的数字,例如find-0,find- 1,find-2 etc)标签并用copyInnerHtml替换页面内容。然后,当用户重新点击搜索按钮时,我首先将页面恢复为原始的innerHTML内容,然后如上继续。这很好用。

如何查找文本(网站副本)中仅用作HTML元素/属性中的值的单词和注释单词。

示例,请考虑以下代码

 <div class="search">This is the search box</div>

现在,我想搜索单词&#34; 搜索&#34;。问题是,它会发现它两次。

不使用正则表达式,只使用JavaScript(请不要使用jQuery),如何检测字符串是否是HTML标记的一部分?

JSFIDDLE 应该让我更加清楚

现在,您希望注意小提琴中的以下一行

<p class="changeMe">&nbsp;</p><p>&nbsp;</p>

请将此更新为

<p class="find">&nbsp;</p><p>&nbsp;</p>

你会看到代码中断。这就是我的意思,当我搜索一个单词时(在JSFIDDLE的情况下,单词&#39; find&#39;)然后我只想通过网站副本进行搜索。

1 个答案:

答案 0 :(得分:1)

如您所知,您必须处理整个(或部分)DOM。 执行此操作时,您必须将每个tagName与您不想处理的黑名单进行交叉检查。

以下是一个关于如何在vanilla javascript中完成此操作的小例子:

var excludeElements = ['script', 'style', 'a', 'form', 'iframe', 'canvas'];

var markText = function(textToHighlight) {

    walk(document.body, textToHighlight, function(node, match, offset) {
        var abbrevNode = document.createElement("span");
        abbrevNode.appendChild(document.createTextNode(textToHighlight));
        abbrevNode.className="someClass";
    });

}

var walk = function(node, textToHighlight, callback) { 


    var child = node.firstChild;

    while (child) {
        switch (child.nodeType) {
        case 1:
            if (excludeElements.indexOf(child.tagName.toLowerCase()) > -1)
                break;
            walk(child, textToHighlight, callback);
            break;
        case 3:
            var bk = 0;
            child.data.replace(textToHighlight, 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;
            });
            break;
        }
        child = child.nextSibling;
    }

    return node;
};