2013-05-21 1 views
18

와 텍스트 노드에 좀 텍스트 노드있어 :삽입 HTML 자바 스크립트

var node 

을 그리고 난 "LOL"의 모든 발생 주위에 범위를 포장합니다. 내가 스팬 요소로 "lol" 할 때

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

그것은 그것 "<span>lol<span>" 출력합니다.

+0

이 경우 텍스트 노드를 html 콘텐츠로 다시 채워야합니다. –

+0

@ArunPJohny 어떻게해야합니까? – alt

+0

@ JacksonGariety - 텍스트 노드를 새 DOM span 요소 및 텍스트 노드로 바꾸거나 부모의 innerHTML 속성을 수정해야합니다. 가자. 시도해라. – RobG

답변

3

당신은 부모 노드로 node을해야 할 수도 있습니다, 당신은 단지 innerHTML을 사용할 수 있습니다 그 방법 : 여기 node.childNodes[0]

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

실제 텍스트 노드를 참조하고 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. 스플릿 사이에 스팬 요소를 삽입하십시오.
13

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 "을 추가하고 태그에 href 속성을 추가하는 행을 추가하고 excludeElements 목록에 'a'를 추가하여 링크가 링크 내부에서 작성되지 않도록하십시오.

+1

재사용 할 때 regex를 재설정하기 위해'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); 
+0

감사합니다. 저에게 가장 좋은 답변이었습니다. – romuleald