2016-08-13 37 views
1

我建立在JavaScript中自動完成,需要強調的話做一個搜索時:正則表達式的轉義字符突出

highlighting example

這工作正常,但有一個與轉義字符的問題。 當試圖突出與轉義字符的文本(例如regex &>< example),下面是發生的事情:

regex highlighting

這是怎麼回事,因爲我做了以下內容:

element.innerHTML.replace(/a/g, highlight) 

function highlight(str) { 
    return '<span class="foo"' + '>' + str + '</span>'; 
} 

innerHTML包括字&amp;,所以它是有道理的。

最後,我需要一種方法來解決,所以我想一個函數:

  • 接收aregex <br> example並返回regex &lt;br&gt; ex<span class="foo">a</span>mple
  • 接收rregex <br> example並返回<span class="foo">r</span>egex &lt;b<span class="foo">r</span>&gt; example
  • 接收<regex <br> example並返回regex <span class="foo">&lt;</span>br&gt; example

的條目可能會或可能不會包含HTML塊,看問題here(搜索<br>&

+2

如果你不想實體退換,使用'textContent'獲取內容,而'innerHTML'與跨度包括設置呢? – adeneo

+0

'textContent'具有字符轉義(即:'&'),它的正好不包括html,比如'span's,所以不起作用 – lante

+0

這看起來像是另一個例子'你不能用常規表達式的情景:http://stackoverflow.com/a/1732454/25216 –

回答

1

str.replace只返回與預期的更換一個新的字符串。原始字符串不變。

var str = 'replace me'; 
 
var str2 = str.replace(/e/g, 'E'); 
 

 
// For display only 
 
document.write('<pre>' + JSON.stringify({ 
 
    str: str, 
 
    str2: str2 
 
}, null, 2) + '</pre>');

因此代碼需要從替換回到所需元件設置返回值。

此外,innerHTML將返回轉義的文本,而不是未轉義的文本。這可能會在函數中自行轉義,但爲什麼要使用textContent呢?但是,如果要將突出顯示的文本設置爲元素,那麼通過使用innerHTML它會自動爲我們轉義文本。 :)

UPDATE:值傳遞給函數,然後設置爲元素:

注:

  • 的正則表達式也許可以做一點更穩健避免必須處理使用的特殊情況lastIndex
  • 需要對輸入進行某種保護,因爲某人c應該提供一個令人討厭的正則表達式模式。在這個例子中有一個最小保護檢查。

higlightElemById('a', 'regex &>< example', 'a'); 
 
higlightElemById('b', 'regex &>< example', '&'); 
 
higlightElemById('c', 'regex <br> example', '<'); 
 
higlightElemById('d', 'regex <br> example', 'e'); 
 
higlightElemById('e', 'regex <br> example', '[aex]'); 
 

 
function higlightElemById(id, str, match) { 
 
    var itemElem = document.getElementById(id); 
 
    // minimal regexp escape to prevent shenanigans 
 
    var safeMatch = match.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 
 
    // construct regexp to match highlight text 
 
    var regexp = new RegExp('(.*?)(' + safeMatch + ')', 'g'); 
 
    var text = ''; 
 
    var lastIndex; 
 
    var matches; 
 
    
 
    while (matches = regexp.exec(str)) { 
 
    // Escape the non-matching prefix 
 
    text += escapeHTML(matches[1]); 
 
    // Highlight the match 
 
    text += highlight(matches[2]); 
 
    // Cache the lastIndex in case no regexp at end 
 
    lastIndex = regexp.lastIndex; 
 
    } 
 

 
    if (text) { 
 
    text += escapeHTML(str.substr(lastIndex)); 
 
    } else { 
 
    text += escapeHTML(str); 
 
    } 
 

 
    itemElem.innerHTML = text; 
 
} 
 

 
function highlight(str) { 
 
    return '<span class="myHighlightClass">' + str + '</span>'; 
 
} 
 

 
function escapeHTML(html) { 
 
    this.el = this.el || document.createElement('textarea'); 
 

 
    this.el.textContent = html; 
 
    return this.el.innerHTML; 
 
}
.myHighlightClass { 
 
    text-decoration: underline; 
 
    color: red; 
 
}
<div id="a"></div> 
 
<div id="b"></div> 
 
<div id="c"></div> 
 
<div id="d"></div> 
 
<div id="e"></div>

+0

感謝您的答案,但我看到一個額外的案件不包括在內: https ://jsfiddle.net/gemxuc3e/ 我更新了問題以澄清 – lante

+0

@lante在這種情況下,您所需的輸出是什麼?將「
」轉義或不在輸入中,它是否需要在輸出元素中轉義? –

+0

查看[這裏](https://jsfiddle.net/8rd8mbm9/2/)例子中,條目可能包含也可能不包含html塊(我不能禁止用戶把html塊作爲條目)搜索'br '或'&' – lante