2013-05-21 38 views
18

文本節點我有一個小的文本節點:插入HTML與JavaScript的

var node 

而且我想環繞的「笑」每一次出現的跨度。

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

它它打印出"<span>lol<span>"當我想"lol"作爲一個span元素。

+0

? –

+0

@ArunPJohny文本節點如何做呢 – alt

+0

@ JacksonGariety - 您需要用新的DOM span元素和文本節點替換文本節點,或者修改其父元素的innerHTML屬性。走了,發佈你的嘗試。 – RobG

回答

3

您可能需要node是父節點,這樣你可以使用innerHTML:

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

這裏node.childNodes[0]指的是實際文本節點,node是它包含的元素。

+6

被警告替換包含節點的innerHTML對於可能通過腳本添加事件偵聽器的子節點具有破壞性。 – ccjuju

+0

這不適合我(Chrome 50);沒有視覺上的變化。我可以在控制檯中看到'node.innerHTML'已經改變,但UI沒有改變。此外,'node.parentNode.innerHTML'不包含新的更改。 – Jeff

15

下面的文章給你的代碼與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. 在分割之間插入一個span元素。
13

Andreas Josas提出的答案相當不錯。但是,當搜索詞出現在同一個文本節點中幾次時,代碼有幾個錯誤。下面是修復了這些bug的解決方案,另外插入了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標籤來代替,改變創造元素是「一「而不是」span「,添加一行以將href屬性添加到標籤,並將」a「添加到excludeElements列表中,以便鏈接不會在鏈接內創建。

+1

我添加了修復'regex.lastIndex = 0'來重新使用正則表達式。看到http://stackoverflow.com/questions/1520800/why-regexp-with-global-flag-in-javascript-give-wrong-results – Jeff

2

不是說這是一個更好的答案,但我張貼我所做的完整性。在我的情況中,我已經查找或確定了需要在特定#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); 
在這種情況下,你將不得不repace與HTML內容
+0

謝謝你,這是我的最佳答案 – romuleald