【问题标题】:JQuery/JavaScript plugin for highlighting text用于突出显示文本的 JQuery/JavaScript 插件
【发布时间】:2012-08-18 11:30:54
【问题描述】:

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

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

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

【问题讨论】:

  • 你的意思是双高亮元素的颜色应该添加到自身(看起来更暗)?
  • 我的意思是新的选择应该突出显示文本,即使这个文本是旧选择的一部分
  • 因此您搜索字符串“quick brown fox”,它以(假设)黄色突出显示。然后您搜索“狐狸”并选择绿色。你想让'狐狸'是绿色还是黄绿色?您搜索“o”并选择红色。棕色的“o”是红色还是橙色?狐狸中的“o”是红色还是病态的棕色? (显然,我需要复习色彩理论)。这是你的+50,所以我认为你应该准确地说出你想要什么。哦,还有 +1,整洁的插件。
  • 既然是我的“+50”,我会插话。首先,这一切都不必包括搜索。如果我有一个字符串,说“The quick brown fox”,并且最初突出显示“the quick”,然后我去突出显示“quick brown fox”,我希望两个突出显示的部分合并为一个突出显示的部分,所以突出显示“快速棕色狐狸”。
  • 只需使用jquery.mark

标签: javascript jquery


【解决方案1】:

如果您添加一些小调整,您可以使用找到的highlighter plugin 完成所有操作。 作为一个插图,我发布了一个我今天下午快速整理的工作示例: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);
    }

这会将所有相邻的 span 与 class highlight 合并(这只是为一般的 highlighter 标签编写的,但可以很容易地使用 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. selected1 附加到words
  4. words 中组合所有部分重叠的字符串对,并将新组合的字符串添加到words(使用overlap 函数及其遍历整个数组的包装器——小提琴示例中的overdiag
  5. 按字符串长度对words 进行排序,因此最长的字符串会排在最前面
  6. 突出显示words 中的所有字符串
  7. 合并所有相邻的高亮字符串(使用mergenode函数)
  8. 最后一组突出显示的字符串保存到selected1

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

【讨论】:

  • 欢迎来到 Stack Overflow!谢谢你的帖子!请不要在您的帖子中使用签名/标语。您的用户框算作您的签名,您可以使用您的个人资料发布您喜欢的任何关于您自己的信息。 FAQ on signatures/taglines
  • @AndrewBarber 谢谢,我确实阅读了常见问题解答,但后来对写作感到非常兴奋 =) 我不会再这样做了。
  • 干得好,现在您只需将其打包成一个独立的漂亮插件,抽象 unhighlight 调用,以便在您调用 highlight 时自动发生,并确保实际的外部 unhighlight 调用删除其“内存” ,因为您希望能够永久删除所有突出显示的内容。但除此之外,这可能在不诉诸魔法的情况下尽可能好。
  • @Mirek 你好!如果这个答案对您根本没有帮助,我只是在浏览我的旧答案并且正在徘徊?或者如果有其他原因你不接受它。 - 我知道它没有提供开箱即用插件的列表 - 但如果您仍然需要它,您可以随意使用我的解决方案并根据需要修改它们以进行生产 =) 干杯!
猜你喜欢
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 2012-03-28
  • 2011-11-22
  • 2013-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多