使用JavaScript将HTML插入文本节点

时间:2013-05-21 04:55:51

标签: javascript dom textnode

我有一个小文本节点:

var node

我想围绕“lol”的每次出现包围一段距离。

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

当我希望"<span>lol<span>"作为span元素时,它打印出"lol"

5 个答案:

答案 0 :(得分:19)

Andreas Josas提出的答案非常好。但是,当搜索项在同一文本节点中出现多次时,代码有几个错误。这是解决了这些错误的解决方案,另外插入因素被考虑到matchText中以便于使用和理解。现在,只有新标记在回调中构造,并通过返回传递给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标签,请将创建元素更改为&#34; a&#34;而不是&#34; span&#34;,添加一行以将href属性添加到标记,并添加&#39; a&#39;到excludeElements列表,这样就不会在链接中创建链接。

答案 1 :(得分:17)

以下文章为您提供了使用HTML元素替换文本的代码:

http://blog.alexanderdickson.com/javascript-replacing-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); 
});

并解释:

  

基本上,正确的做法是......

     
      
  1. 遍历所有文本节点。
  2.   
  3. 在文本节点中查找子字符串。
  4.   
  5. 将其拆分为偏移量。
  6.   
  7. 在分割之间插入一个span元素。
  8.   

答案 2 :(得分:5)

不是说这是一个更好的答案,但我发布了我为完整性所做的事情。在我的情况下,我已经查找或确定了我需要在特定的#text节点中突出显示的文本的偏移量。这也澄清了这些步骤。

//node is a #text node, startIndex is the beginning location of the text to highlight, and endIndex is the index of the character just after the text to highlight     

var parentNode = node.parentNode;

// break the node text into 3 parts: part1 - before the selected text, part2- the text to highlight, and part3 - the text after the highlight
var s = node.nodeValue;

// get the text before the highlight
var part1 = s.substring(0, startIndex);

// get the text that will be highlighted
var part2 = s.substring(startIndex, endIndex);

// get the part after the highlight
var part3 = s.substring(endIndex);

// replace the text node with the new nodes
var textNode = document.createTextNode(part1);
parentNode.replaceChild(textNode, node);

// create a span node and add it to the parent immediately after the first text node
var spanNode = document.createElement("span");
spanNode.className = "HighlightedText";
parentNode.insertBefore(spanNode, textNode.nextSibling);

// create a text node for the highlighted text and add it to the span node
textNode = document.createTextNode(part2);
spanNode.appendChild(textNode);

// create a text node for the text after the highlight and add it after the span node
textNode = document.createTextNode(part3);
parentNode.insertBefore(textNode, spanNode.nextSibling);

答案 3 :(得分:4)

您可能需要node作为父节点,这样您就可以使用innerHTML:

node.innerHTML=node.childNodes[0].nodeValue.replace(/lol/, "<span>lol</span>");

此处node.childNodes[0]表示实际的文本节点,node是其包含的元素。

答案 4 :(得分:0)

对于那些现在正在寻找这个问题的人,最新的答案是:

select p66.language_string_text_id, p66.language_string, p66.language_id
FROM project66.languagestrings p66 
WHERE p66.language_string_text_id NOT IN 
(SELECT wh.language_string_text_id FROM wisehouse.languagestrings wh) 
GROUP BY p66.language_string_text_id, p66.language_id

想法是使用

function textNodeInnerHTML(textNode,innerHTML) { var div = document.createElement('div'); textNode.parentNode.insertBefore(div,textNode); div.insertAdjacentHTML('afterend',innerHTML); div.remove(); textNode.remove(); } 之前插入一个新创建的html元素(让我们说var div = document.createElement('div');)。
textNode

,然后使用:

textNode.parentNode.insertBefore(div,textNode);

然后使用以下命令删除div.insertAdjacentHTML( 'afterend', textNode.data.replace(/lol/g,`<span style="color : red">lol</span>`) ) textNode

div

textNode.remove(); div.remove(); 不会像insertAdjacentHTML那样破坏事件监听器。

如果要查找属于innerHTML后代的所有文本节点,请使用:

elm