【问题标题】:Make a text Highlight using javascript使用 javascript 突出显示文本
【发布时间】:2013-04-07 02:06:03
【问题描述】:

我想在给定的段落中加粗一个单词。这是一个javascript代码。

        var hlWord = "idm";
        var nregex = new RegExp(hlWord,"gi");
        var div = document.getElementById("SR").innerHTML;
        var rword = div.replace(nregex,"<b>"+hlWord+"</b>");
        document.getElementById("SR").innerHTML = rword;  

这是一个 HTML 代码。

<div id="SR">
Download here free idm.
<a href="http://www.anywebsite.com/idm">click here to download</a>
</div>  

这很好用,让所有 idm 加粗,但这里有一个问题,它也会改变 喜欢这个的网址

<a href="http://www.anywebsite.com/<b>idm</b>">click here to download</a>  

这不是一个有效的url。这是这段代码使url损坏的问题。 请告诉我如何避免这种情况。
谢谢...

【问题讨论】:

  • 我不知道你的例子有多深,但对于你发布的例子,你可以使用var nregex = /idm/i;

标签: javascript html regex


【解决方案1】:

您可以使用this thread 中的方法遍历所有文本节点,更改它们并用新的粗体替换它们。

var hlWord = "idm";
var nregex = new RegExp(hlWord,"gi");

var sr = document.getElementById('SR');

function escape_html(html) {
    return html.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

(function findTextNodes(current) {
    // make a shadow copy of the child nodes.
    var current_children = Array.prototype.slice.call(current.childNodes);
    for(var i = 0; i < current_children.length; i++) {
        var child = current.childNodes[i];
        // text node
        if(child.nodeType == 3) {
            var value = escape_html(child.nodeValue);
            var html = value.replace(nregex, '<b>' + hlWord + '</b>');
            if (html != value) {
                var node = document.createElement('div');
                node.innerHTML = html;
                // make a shadow copy of the child nodes.
                var childNodes = Array.prototype.slice.call(node.childNodes);
                // replace the plain text node with the bold segments
                for (var j = 0; j < childNodes.length; j++) {
                    var c = childNodes[j];
                    current.insertBefore(c, child);
                }
                current.removeChild(child);
            }
        }
        else {
            findTextNodes(child);
        }
    }
})(sr);

查看jsFiddle的代码示例。

更新

  • Passerby 指出innerHTML 应谨慎使用。处理前转义文本 nodeValue。

【讨论】:

  • 虽然很少见,但有些文字具有HTML代码的意义,所以直接修改innerHTML可能会导致意想不到的结果:jsfiddle.net/r9Qrr/3
  • 如果要使用别人的代码,至少参考一下:stackoverflow.com/questions/3963872/…
  • @Passerby 你是对的。在处理替换之前需要对文本 nodeValue 进行转义。
  • @lan 我没有引用那个线程。我搜索了 text node traversal 并找到了另一个线程,该线程之前发布过您列出的线程,并且我第一次在第一段中附加了链接 this thread发布我的答案。
  • @ArieShaw 我不这么认为,您的代码与我找到并提供的代码几乎完全相同。而且您在第一次发布答案时从未包含任何内容-我可以看到您的编辑历史记录,并且我记得您的原始答案。在我说了什么之前没有添加任何内容。不管怎样,没关系,你做了一个很好的解决方案
【解决方案2】:

经过一些尝试和失败后,我制作了一个工作演示,它可能比您想象的要复杂:

http://jsfiddle.net/4VKNk/

var cache=[];
var reg=/idm/gi;
var id=function(ID){return document.getElementById(ID);}
function walkElement(ele){
    if(ele.childNodes.length>0){
        for(var i=0;i<ele.childNodes.length;i++){
            walkElement(ele.childNodes[i]);
        }
    }else if(ele.nodeType==3){//text node
        if(reg.test(ele.nodeValue)){
            cache.push(ele);
        }
    }
}
id("test").onclick=function(){
    cache=[];
    walkElement(id("SR"));
    while(cache.length>0){
        var ele=cache.shift();
        var val=ele.nodeValue;
        var pnt=ele.parentNode;
        var nextSibling=ele.nextSibling;
        var i=0;
        var r,tmp;
        pnt.removeChild(ele);
        while(r=reg.exec(val)){
            tmp=document.createTextNode(val.substring(i,r.index));
            if(nextSibling){
                pnt.insertBefore(tmp,nextSibling);
                tmp=document.createElement("strong");
                tmp.appendChild(document.createTextNode("idm"));
                pnt.insertBefore(tmp,nextSibling);
            }else{
                pnt.appendChild(tmp);
                tmp=document.createElement("strong");
                tmp.appendChild(document.createTextNode("idm"));
                pnt.appendChild(tmp);
            }
            i=reg.lastIndex;
        }
        if(i<val.length-1){
            tmp=document.createTextNode(val.substring(i,val.length));
            if(nextSibling){
                pnt.insertBefore(tmp,nextSibling);
            }else{
                pnt.appendChild(tmp);
            }
        }
    }
};

我采用了 DOM 操作的方法。

解释:

  1. 遍历目标元素下的整个 DOM 树,并缓存所有 TEXT_NODE (nodeType==3);
  2. 使用RegExp.exec()方法获取每个匹配的索引;
  3. 找到匹配项时,添加回它之前的文本,然后添加包含匹配项的突出显示元素 (&lt;strong&gt;);继续这一步;
  4. 如果我们还有文字,请将其添加回来。

之所以需要先缓存TEXT_NODE,是因为如果直接在walkElement修改,会改变其父级的childNodes.length,从而中断进程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 2013-05-28
    • 2011-09-08
    • 2011-02-21
    • 2014-03-12
    • 2021-12-01
    相关资源
    最近更新 更多