利用JavaScript在HTML页面搜索并高亮匹配的文本

网页中内容比较多的话,有时候需要通过搜索快速查找特定的文本。当然,这可以通过浏览器的搜索功能实现,但是,象Anki的复习界面这样的场景,并没有搜索功能,我们就需要自己在网页上提供一个搜索框来实现。

下面先用原生JavaScript实现一个。基本思路是,用户在input中输入文字后,在页面上进行查找,找到匹配的内容,就用一个class属性为包含高亮格式的css类名的span标签包裹起来。代码如下:

<!DOCTYPE html>
<html lang="zh">
<head>
   <meta charset="utf-8">
   <title>原生js搜索并高亮文本</title>
   <style>
      /* 用于高亮显示的css类 */
      .highlight {
         background-color: yellow;
         font-weight: bold;
      }
   </style>
</head>
<body>
<div style="width:30%;text-indent: 2em;color:red;">
   这个搜索用的是在innerHTML中搜索文本,因此,如果文本中包含html标签会导致搜索失败。
   在innerText中搜索文本,可以排除html标签的影响,但高亮后可能破坏原有的文档标签结构。</div>
   <pre>
      下面的代码显示两行文本,参见灰色底纹处:
      &lt;div class="content"&gt;
      &lt;p&gt;我爱北京&lt;span&gt;天安&lt;i&gt;门&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
      天安门上太阳升
   &lt;/div&gt;
   </pre>
   <div class="content" style="background-color: #ccc;width:20%;">
      <p>我爱北京<span>天安<i>门</i></span></p>
      天安门上太阳升
   </div>
      <input type="text" id="searchInput" placeholder="输入搜索文本..." oninput="highlightText()"/>
   <script>
      function highlightText() {
         const searchInput = document.getElementById('searchInput');
         const searchValue = searchInput.value.trim();
         const contentElement = document.querySelector('.content');
         const content = contentElement.innerHTML;

         if (searchValue !== '') {
            //先清除原有的高亮,即将用于高亮的<span>标签删除但保留原有内容
            let highlightedContent = content.replace(
                  new RegExp('<span class="highlight">(.*)</span>', 'gi'),
                  '$1'
            );
            //高亮,即将需要高亮的内容用类名为包含高亮格式的css类span标签包裹起来
            highlightedContent = highlightedContent.replace(
                  new RegExp(searchValue, 'gi'),
                  '<span class="highlight">$&</span>'
            );
            contentElement.innerHTML = highlightedContent;
         } else {
            //清除高亮
            let highlightedContent = content.replace(
                  new RegExp('<span class="highlight">(.*)</span>', 'gi'),
                  '$1'
            );
         }
      }
   </script>
</body>
</html>

上面的代码显示的网页大致如下:

在搜索框输入文字,例如“天安”,两处天安均会高亮显示,如下:

再多输入一个“门”,这时候上面的天安门不高亮显示了,只有下面的天安门高亮显示:

这就是网页上部文字说明的意思。上一行的天安与门字中间多了个html标签<i>,导致匹配失败。所以要用原生JavaScript来实现高亮,还要想法消除可能存在的HTML标签的影响。这里涉及到的算法稍微有点复杂的,实现方法可参考利用原生JavaScript实现匹配搜索结果的网页内容高亮。此外,jquery有个mark.js库,用来干这个事完全是小儿科,而且健壮性兼容性都有保障。以上面的页面为例,只需要将input元素的oniput事件删除,将原有的原生JavaScript代码删除,引入jquery和mark库(我这里是下载到本地了,也可以用CDN方式引用),然后增加数行代码即可完成。参见如下代码:

   <input type="text" id="searchInput" placeholder="输入搜索文本..."/>
   <script src="jquery.min.js" ></script>
   <script src="jquery.mark.es6.js"></script>
   <script>
      $(function() {
          $("#searchInput").on("input.highlight", function() {
              // 获取指定搜索的字符串
              var searchTerm = $(this).val();
              // 将解析中匹配的文本高亮
              $(".content").unmark().mark(searchTerm,
                  {
                     "acrossElements": true,
                     "separateWordSearch": false,
                     "className":"highlight",
                  }
              );
          }).trigger("input.highlight");
      });
   </script>

用这个库,html标签就不影响文本的匹配了,参见下图:

将这个功能应用到Anki中,要能够离线使用,需要将上面两个JavaScript库下载下来,复制到“%APPDATA%/anki2”中的Anki登录用户名下的“collection.media”文件夹中,为防止被Anki当作未使用资源删除,应该将JavaScript库文件名修改为以英文状态的下划线开头。然后将最后那个代码片段复制到Anki卡片模板中的适当位置(注意JavaScript库的名称前加上下划线),修改一下相关的jquery选择符及相关类名就行了。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yivifu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值