\ b元字符无法正常工作

时间:2016-03-14 23:51:02

标签: javascript html regex

我知道这段代码有效,而且它现在已经停止工作了。我正在研究一个人的荧光笔工具,但如果我输入一个单词然后输入mark,它会突出显示实际的标记元素。这是我的代码:

function Search (tagC) {
var notes = document.getElementsByClassName("NoteOp");
for (var i = 0; i < notes.length; i++) {
var n = notes[i];
var tagOut = tagC
var tagFront = tagOut.slice(0, -9);
var tagLast = tagOut.slice(-9);
n.innerHTML = n.innerHTML.replace(new RegExp("\\b(" + tagFront + ")\\b", "gim"), "<mark class=" + tagLast + ">$1</mark>");
if(window.Bold === "Yes") {
    $("mark").css("font-weight", "bold");
}
}
}

tagFront是搜索词,而tagLast是一个总是有9个字母的类。在编码中看到的任何问题?

tagC的一个例子是:

testYelColBox

...我正在搜索的文字如下:

<div id="NoteHolder">
<p class="NoteOp">This is a test paragraph uses to TeSt filters.</p>
<p class="NoteOp">Random words, I need to see if it will mess up mark</p>
</div>

主要问题:即使我的代码有\b元字符选择器,为什么我的代码会标记HTML元素?

1 个答案:

答案 0 :(得分:1)

你的问题似乎是这样的:

如果您首先突出显示一个单词,它就能正常工作。但是现在你的HTML有<mark>个标签,所以如果现在你第二次用搜索词&#34;标记&#34; 进行搜索,那么这个标签会得到一个嵌套标记,这是不希望的,使您的HTML无效。

为什么会发生这种情况

\b转义匹配搜索字符串中字符序列从字母数字字符切换到非字母数字字符的任何位置,反之亦然。这意味着\b也会与< <mark ...>之后的位置匹配,并且位于k之后的位置(由于后面的空格)。

解决方案

通过仅将其应用于文本节点而不是HTML元素来进行受控替换。为此,您需要遍历节点,检查其类型,以及何时它们是文本节点,执行替换。由于替换涉及插入HTML元素,您实际上应该将该文本节点拆分为之前的内容,标记元素以及之后的内容。

这是执行所有这些操作的代码:

&#13;
&#13;
function clear() {
    var notes = document.getElementsByClassName("NoteOp");
    for (var i = 0; i < notes.length; i++) {
        var n = notes[i];
        // Remove all opening/closing mark tags
        n.innerHTML = n.innerHTML.replace(/<\/?mark.*?>/gm, "");
    }
}

function highlight(tagC) {
    // Sanity check
    if (tagC.length <= 9) return; // ignore wrong input
    var notes = document.getElementsByClassName("NoteOp");
    // Split into parts before entering loop:
    var tagFront = tagC.slice(0, -9);
    var tagLast = tagC.slice(-9);
    // Escape tagFront characters that could conflict with regex syntax:
    tagLast = tagLast.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
    var regex = new RegExp("\\b(" + tagFront + ")\\b", "gim");
    // Create a template of the highlight that can be cloned
    var mark = document.createElement('mark');
    mark.setAttribute('class', tagLast);
    // Loop over notes
    for (var i = 0; i < notes.length; i++) {
        // Create a span that will have the contents after replacements
        var span = document.createElement('span');
        // Go through all child nodes of this note
        var nodes = notes[i].childNodes;
        for (var j = 0; j < nodes.length; j++) {
            var node = nodes[j];
            if (node.nodeType === 3) {
                // Only if text node, perform replacement
                parts = node.textContent.split(regex);
                // As regex has capture group, also the split expression is a part
                for (var k = 0; k < parts.length; k++) {
                    // Add this part 
                    if (k % 2) {
                        // Add highlighted text
                        mark.textContent = parts[k];
                        span.appendChild(mark.cloneNode(true));
                    } else { 
                        // Add text part that did not match as such
                        span.appendChild(document.createTextNode(parts[k]));
                    }
                }
            } else {
                // Non-text nodes are just copied as they are
                span.appendChild(node.cloneNode(true));
            }
        }
        // Replace note contents with new contents
        notes[i].innerHTML = span.innerHTML;
    }
    // Setting style for CSS class should happen outside of the loop
    $("mark").css("font-weight", window.Bold === "Yes" ? "bold": "normal");
}

// I/O 
var inp = document.querySelector('#inp');
var btnMark = document.querySelector('#mark');
var btnClear = document.querySelector('#clear');

btnMark.onclick = function () {
    highlight(inp.value + 'YelColBox');
}
btnClear.onclick = clear;
&#13;
Type text to be highlighted and press Mark:<br>
<input id="inp" value="">
<button id="mark">Mark</button>
<button id="clear">Clear</button>

<div id="NoteHolder">
<p class="NoteOp">This is a test paragraph uses to TeSt filters.</p>
<p class="NoteOp">Random words, I need to see if it will mess up mark</p>
</div>
&#13;
&#13;
&#13;