9

我正在为一个元素中的多个突出显示的文本寻找一个 jquery 插件。我找到了一个非常流行的插件:http: //bartaz.github.com/sandbox.js/jquery.highlight.html以及许多其他插件。

它们工作正常,但如果我想突出显示与先前突出显示的文本重叠的文本 - 它不起作用。

有谁知道支持多个突出显示的文本并正确突出重叠文本的 jquery 或 javascript 插件?

4

1 回答 1

15

如果您添加一些小调整,您可以使用找到的荧光笔插件完成所有操作。作为一个插图,我发布了一个我今天下午快速整理的工作示例:http: //jsfiddle.net/4bwgA/

在这里,我将逐步介绍插件(OP 所指)已经完成的所有事情,最后给出重叠突出区域的解决方案。

荧光笔的作用是在您应用它的单词周围放置一个标签。所以如果你有

   <p>Who is the quick brown fox?</p>

你突出显示了“棕色”这个词

   $("p").highlight("brown");

你得到

   <p>Who is the quick <span class="highlight">brown</span> fox?</p>

和一个额外的命令

   $("p").highlight("brown fox");

不会找到任何东西,因为字符串不再有这个子字符串,因为它现在有棕色周围的标签。

因此,如果只是重叠......解决方案很简单。该软件包提供了取消突出显示的功能,您可以在新的突出显示之前应用该功能

   $("p").unhighlight().highlight("brown fox");

并得到

   <p>Who is the quick <span class="highlight">brown fox</span>?</p>

到目前为止,这并没有什么令人兴奋的。但是,如果我们一次性突出显示“棕色”,然后在下一个突出显示“狐狸”。我们得到这个

   <p>Who is the quick <span class="highlight">brown</span> <span class="highlight">fox</span>?</p>

然后我们要加入相邻的高亮区域。这可以通过一个附加函数来完成,它执行如下操作:

    function mergenode(node) {
        var parent1 = node.contents();
        parent1.each(function (i) {
            if (i > 0 && this.nodeType !== 1 && //if text node
                this.data.search(/^\s*$/g) === 0 && //consisting only of hyphens or blanks
                parent1[i - 1].nodeName === "SPAN" && //bordering to SPAN elements
                parent1[i + 1].nodeName === "SPAN" && 
                parent1[i - 1].className === "highlight" && //of class highlight
                parent1[i + 1].className === "highlight") {
                    selected1.push(parent1[i - 1]
                        .textContent.concat(this.data, parent1[i + 1].textContent));
            }
            else if (this.nodeType === 1 && 
                this.nodeName === "SPAN" && 
                parent1[i + 1].nodeName === "SPAN" && 
                this.className === "highlight" && 
                parent1[i + 1].className === "highlight") {
                    selected1.push(this.textContent.concat(parent1[i + 1].textContent));
            }
        });
        $(node).unhighlight().highlight(selected1);
    }

这会将所有相邻跨度与类高亮合并(这只是为通用荧光笔标签编写的,但可以很容易地使用 nodeName 和 className 的两个额外参数进行扩展,用于自定义标签)。结果将如下所示

    <p>Who is the quick <span class="highlight">brown fox</span>?</p>

到目前为止一切都很好。但是如果我们的搜索字符串重叠怎么办?!!!首先......与重叠最好的办法是在检查清除文本上的重叠字符串之前取消选择旧选择。为此,我们需要记住之前的选择,例如,可以将其保存在一个数组(我称之为它selected1)中,该数组在每次额外选择时都会添加一个值。

每次运行时,最终选择(全部合并)都会保存到selected1数组中,以便将来用于合并和重叠。

现在,荧光笔如何处理字符串数组?它按照它们被传递给函数的顺序将高亮函数应用于它们中的每一个。因此,如果两个字符串完全重叠,我们可以通过对选择字符串数组进行排序并首先突出显示较长的字符串来处理它。例如

    $("p").highlight(["brown fox","brown"]);

只会突出显示

    <p>Who is the quick <span class="highlight">brown fox</span>?</p>

数组可以按长度排序,如下所示

    words = words.sort(function (str1, str2) {
        return (str1.length < str2.length) ? 1 : 0;
    });

现在处理完全重叠和相邻的高光。现在我们必须确保我们得到部分重叠的字符串。在这里,我编写了一个比较两个字符串是否重叠的函数......还有其他方法可以做到这一点,但我想在这个答案中展示的主要是您需要执行的一系列步骤,以便以您的方式突出显示想要 =)

此函数接受两个字符串,检查它们是否重叠,如果重叠,则将它们组合起来并将新组合的字符串保存到一个数组中,toselect最后附加到原始words数组中。可能有一些无用的组合,但它不会受到伤害 - 它们不会在最后显示。

    function overlap(a, b) {
        var l = b.length,
            m = a.length;
        for (var j = 1; j < l; j++) {
            if (a.indexOf(b.substr(l - j)) === 0) {
                toselect.push(b.concat(a.substr(j)));
            } else if (a.substr(m - j).indexOf(b.substr(0, j)) === 0) {
                toselect.push(a.concat(b.substr(j)));
            }
        }
    }

现在我们想将此函数应用于words数组中所有可能的元素对。我们可以用循环来迭代它,但我有点兴奋并做了这个

    $.each(arr, function (i) {
        $.each(arr.slice(i + 1), function (i, v) {
            overlap(arr[i], v);
        });
    });

现在我们只需要将新toselect数组(其中所有可能的重叠字符串都已连接)附加到原始words数组。

所以现在我们有了我们需要的所有部件,我们可以把它们放在一起。每次我们想要突出显示一个新字符串或字符串数​​组时,我们都会执行以下步骤:

  1. 取消突出显示当前突出显示的所有内容(突出显示的任何内容都将在selected1数组中)。
  2. 我们的新字符串或字符串数​​组进入words数组
  3. 附加selected1words
  4. 合并所有部分重叠的字符串对words并将新的合并字符串添加到words(使用overlap函数及其遍历整个数组的包装器 -overdiag在小提琴示例中)
  5. words字符串长度排序,所以最长的字符串会排在第一位
  6. 突出显示所有字符串words
  7. 合并所有相邻的高亮字符串(使用mergenode函数)
  8. 最后一组突出显示的字符串保存到selected1

我今天下午很快把它放在一起,所以它不是这个想法的完美实现,但它有效 =) 我将我的代码添加到荧光笔脚本中,并将它们添加到 jsfiddle 上的一个简单示例中,供您使用http://jsfiddle .net/4bwgA/。有一些按钮,因此您可以按下所有不同的步骤并查看它们的作用。

于 2013-03-03T03:44:02.400 回答