2011-12-14 20 views
5

Tôi đang cố gắng viết một plugin nổi bật và muốn giữ lại định dạng HTML. Có thể bỏ qua tất cả các ký tự giữa < và> trong chuỗi khi thực hiện thay thế bằng javascript?Thay thế các từ trong một chuỗi, nhưng bỏ qua HTML

Sử dụng sau đây là một ví dụ:

var string = "Lorem ipsum dolor span sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit."; 

Tôi muốn để có thể đạt được như sau (thay thế 'dolor' với 'foo'):

var string = "Lorem ipsum FOO span sit amet, consectetuer <span class='dolor'>FOO</span> adipiscing elit."; 

Hoặc có lẽ ngay cả điều này (thay thế 'span' bằng 'BAR'):

var string = "Lorem ipsum dolor BAR sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit."; 

Tôi đến rất gần để tìm câu trả lời được đưa ra bởi người đánh bạc ở đây: Can you ignore HTML in a string while doing a Replace with jQuery? nhưng, vì một lý do nào đó, tôi không thể nhận được câu trả lời được chấp nhận để làm việc.

Tôi hoàn toàn mới để regex, vì vậy bất kỳ trợ giúp nào cũng sẽ được đánh giá cao.

+1

http://stackoverflow.com/questions/2289552/jquery-can-you-ignore-html- in-string-while-doing-a-replace – ggzone

+0

Jon, cố gắng phân tích cú pháp html với regex nổi tiếng là khó khăn. http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 – graphicdivine

+2

Bạn nên phân tích cú pháp HTML và sau đó lặp lại đệ quy trên mỗi nút văn bản. –

Trả lời

6

Phân tích cú pháp HTML bằng trình phân tích cú pháp tích hợp của trình duyệt qua innerHTML theo sau là quá trình duyệt DOM là cách hợp lý để thực hiện việc này. Dưới đây là một câu trả lời một cách lỏng lẻo dựa trên this answer:

Live Demo: http://jsfiddle.net/FwGuq/1/

Code:

// Reusable generic function 
function traverseElement(el, regex, textReplacerFunc) { 
    // script and style elements are left alone 
    if (!/^(script|style)$/.test(el.tagName)) { 
     var child = el.lastChild; 
     while (child) { 
      if (child.nodeType == 1) { 
       traverseElement(child, regex, textReplacerFunc); 
      } else if (child.nodeType == 3) { 
       textReplacerFunc(child, regex); 
      } 
      child = child.previousSibling; 
     } 
    } 
} 

// This function does the replacing for every matched piece of text 
// and can be customized to do what you like 
function textReplacerFunc(textNode, regex, text) { 
    textNode.data = textNode.data.replace(regex, "FOO"); 
} 

// The main function 
function replaceWords(html, words) { 
    var container = document.createElement("div"); 
    container.innerHTML = html; 

    // Replace the words one at a time to ensure each one gets matched 
    for (var i = 0, len = words.length; i < len; ++i) { 
     traverseElement(container, new RegExp(words[i], "g"), textReplacerFunc); 
    } 
    return container.innerHTML; 
} 


var html = "Lorem ipsum dolor span sit amet, consectetuer <span class='dolor'>dolor</span> adipiscing elit."; 
alert(replaceWords(html, ["dolor"])); 
+0

Cảm ơn câu trả lời tuyệt vời như vậy, Tim. Nhiều đánh giá cao! – Jon

+0

Đây là một giải pháp rất tốt, nhưng khi bạn cố gắng bao gồm các thẻ HTML trong văn bản thay thế, chúng sẽ được thoát. Ví dụ: bolding chuỗi tìm kiếm sẽ dẫn đến < chuỗi > – Hawkee

+0

@Hawkee: Có. Việc cho phép HTML trong chuỗi tìm kiếm hoàn toàn thay đổi vấn đề. –

1

giải pháp này làm việc với perl, và cũng nên làm việc với Javascript vì nó là tương thích với ECMA 262:

s,\bdolor\b(?=[^"'][^>]*>),FOO,g

Về cơ bản, thay thế nếu từ được theo sau bởi tất cả mọi thứ mà không phải là một trích dẫn, tiếp bởi tất cả mọi thứ mà không phải là đóng cửa > và đóng cửa > chính nó.

+0

Mặc dù tôi tiếc là không thể lấy ví dụ của bạn để làm việc, cảm ơn tất cả cho câu trả lời của bạn, fge. – Jon

Các vấn đề liên quan