搜索div时突出显示结果

时间:2017-06-01 10:01:06

标签: javascript jquery

我有这样的div设置:

<input id="search">

<div class="entry">
  <div class="title">hello world test 123</div>
  <div class="description">lorem ipsum test test1 testing</div>
</div>

<div class="entry">
  <div class="title">attack on titan</div>
  <div class="description">fullmetal alchemist</div>
</div>

我允许用户使用以下内容搜索div:

jQuery(document).ready(function() {
    jQuery("#search").on("keyup click input", function () {
        var val = jQuery(this).val();
        if (val.length) {
            jQuery(".entry").hide().filter(function () {
                return jQuery('.title, .description',this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
            }).show();
        }
        else {
            jQuery(".entry").show();
        }
    });
});

效果很好,请尝试jsFiddle

我的问题是,如何突出搜索字词?例如,如果用户搜索test,我想将文本test包装到<span>标记中。

编辑:请注意,我知道如何搜索/替换文本,但我似乎无法使用我的搜索功能使其正常工作。

3 个答案:

答案 0 :(得分:2)

尝试使用contains(text)代替filter()。最初隐藏所有div。然后只显示包含div的文本。并使用{{将span元素应用于子元素中的匹配字母3}}

在正则表达式中忽略区分大小写的匹配ig,并为contains添加不区分大小写的代码

已更新已修复儿童的.title, .description

jQuery(document).ready(function() {
  jQuery("#search").on("input", function() {
    var val = jQuery(this).val()
    jQuery(".entry").hide()
    jQuery(".entry:contains(" + val + ")").show()
    jQuery(".entry").each(function() {
      if ($(this).find(".title, .description:contains(" + val + ")")) {
        $(this).find(".title, .description:contains(" + val + ")").html(function() {
          return $(this).text().replace(new RegExp('('+val+')', 'ig'), '<span>$1</span>')
        })
      }
    })
  });

})
jQuery.expr[':'].contains = function(a, i, m) {
  return jQuery(a).text().toUpperCase()
      .indexOf(m[3].toUpperCase()) >= 0;
};
.entry {
  background: #fff;
  margin-bottom: 10px;
  width: 300px;
}

span {
  color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">

<div class="entry">
  <div class="title">hello world test 123</div>
  <div class="description">lorem ipsum test test1 testing</div>
</div>

<div class="entry">
  <div class="title">Attack on titan</div>
  <div class="description">fullmetal alchemist</div>
</div>
<div class="entry">
<div>
  <div class="title">For nested element on titan</div>
  <div>
  <div class="description">fullmetal alchemist nested</div>
  </div>
  </div>
</div>

答案 1 :(得分:2)

试试这个:

&#13;
&#13;
document.getElementById('search').onkeyup = userInput;
document.getElementById('search').onclick = userInput;
document.getElementById('search').oninput = userInput;
var allEntries = document.querySelectorAll('.entry');

function userInput () {
    var val = this.value;
    for (var i = 0; i < allEntries.length; i++) {
        var entryElement    = allEntries[i];
        var title           = entryElement.querySelector('.title');
        var description     = entryElement.querySelector('.description');
        var noHtmlSearchStr = '';
        if (title)       noHtmlSearchStr +=       title.innerText;
        if (description) noHtmlSearchStr += description.innerText;
        if (noHtmlSearchStr.length > 0) {
            if (noHtmlSearchStr.toLowerCase().indexOf(val.toLowerCase()) != -1) {
                // Remove existing <b> tags.
                var regexp1 = new RegExp('(<b>|<\/b>)', 'gi');
                if (title)             title.innerHTML =       title.innerHTML.replace(regexp1, '');
                if (description) description.innerHTML = description.innerHTML.replace(regexp1, '');

                if (val.length > 3) {
                    var regexp2 = new RegExp('(' + val + ')(?!>)', 'gi');
                    if (title)             title.innerHTML =       title.innerHTML.replace(regexp2, '<b>$1</b>');
                    if (description) description.innerHTML = description.innerHTML.replace(regexp2, '<b>$1</b>');
                }
                entryElement.style.display = 'block';
            } else {
                entryElement.style.display = 'none';
            }
        }
    }
}
&#13;
.entry {
    background: #fff;
    margin-bottom: 10px;
    width: 300px;
}
&#13;
<input id="search">

<div class="entry">
    <div class="title">hello world test 123</div>
    <div class="description">div lorem <span>ipsum</span> test <div>test1</div> testing span</div>
</div>

<div class="entry">
    <div class="title">attack on titan</div>
    <div class="description">fullmetal alchemist</div>
</div>

<div class="entry"></div>

<div class="entry">
    <div class="title">attack on titan</div>
</div>

<div class="entry">
    <div class="description">Let's not go to Camelot, 'tis a silly place</div>
</div>
&#13;
&#13;
&#13;

JS代码

的说明
  1. 将所有事件绑定到userInput()函数。
  2. 获取.entry类的所有元素,并将其存储在allEntries
  3. 获取用户的输入并存储在val
  4. 遍历allEntries
  5. titledescription获取要搜索的文字并存储在noHtmlSearchStr
  6. 如果valnoHtmlSearchStr的某些部分匹配,则显示entryElement,否则将其隐藏。
  7. <b>title移除description代码。
  8. 如果用户搜索的长度(val)超过三个字符,请突出显示文字上的匹配项,否则请勿突出显示任何内容。

答案 2 :(得分:2)

优化解决方案

在评论中讨论了所有问题并尝试优化解决方案以使其不会出现最终错误之后,我重构了代码并对其进行了优化:

&#13;
&#13;
$(document).ready(function() {
  $("#search").on("keyup click input", function() {
    var val = jQuery(this).val();
    var regExp = new RegExp(val, 'ig');
    var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
    if (val.length) {
      $(".entry").hide().filter(function() {
        var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
        if (val.length > 3) {
          $('.title, .description', this).each(function(k, v) {
            if ($(v).text().match(regExp)) {
              $(v).html($(v).text().replace(regExp, '<span class="highlight">$&</span>'));
            } else {
              $(v).html($(v).text().replace(reg, '$&'));
            }
          });
        } else {
          $('.title, .description', this).each(function(k, v) {
            $(v).html($(v).text().replace(reg, '$&'));
          });
        }
        return found;
      }).show();
    } else {
      $('.title, .description').each(function(k, v) {
        $(v).html($(v).text().replace(reg, '$&'));
      });
      $(".entry").show();
    }
  });
});
&#13;
.highlight {
  background-color: blue
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">

<div class="entry">
  <div class="title">hello world test 123</div>
  <div class="description">lorem ipsum test test1 testing</div>
</div>

<div class="entry">
  <div class="title">attack on titan</div>
  <div class="description">fullmetal alchemist</div>
</div>
&#13;
&#13;
&#13;

它遍历元素并使用带有匹配组的RegExp,如果迭代元素内容与正则表达式匹配,则将匹配的文本替换为包含在span中的相同内容,否则只需将内容设置为其原始形式。

原始答案

这是你应该怎么做的:

    var val = jQuery(this).val();
    if (val.length) {
      $(".entry").hide().filter(function() {
        var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
        var regExp = new RegExp(val, 'ig');
        $('.title, .description', this).each(function(k, v) {
          if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
            var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
            $(v).html(newHTML);
          }
        });
        return found;
      }).show();
    } else {
      $(".entry").show();
    }

您需要遍历元素并使用带有匹配组的RegExp,如果此元素内容与您的Regex匹配,请将匹配的文本替换为包含在范围内的相同内容。

<强>演示:

这是一个有效的演示:

&#13;
&#13;
$(document).ready(function() {
  $("#search").on("keyup click input", function() {
      var val = jQuery(this).val();
      if (val.length) {
        $(".entry").hide().filter(function() {
            var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
            var regExp = new RegExp(val, 'ig');
              $('.title, .description', this).each(function(k, v) {
                if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
                  var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
                  $(v).html(newHTML);
                }
              });
          return found;
        }).show();
    } else {
      $('.title, .description').each(function(k, v) {
        var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
        var newHTML = $(v).text().replace(reg, '$&');
        $(v).html(newHTML);
      });
      $(".entry").show();
    }
  });
});
&#13;
.highlight {
  background-color: blue
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">

<div class="entry">
  <div class="title">hello world test 123</div>
  <div class="description">lorem ipsum test test1 testing</div>
</div>

<div class="entry">
  <div class="title">attack on titan</div>
  <div class="description">fullmetal alchemist</div>
</div>
&#13;
&#13;
&#13;

修改

这是一个仅在输入超过2个字母时突出显示句子的演示:

&#13;
&#13;
$(document).ready(function() {
  $("#search").on("keyup click input", function() {
    var val = jQuery(this).val();
    if (val.length) {
      $(".entry").hide().filter(function() {
        var found = $('.title, .description', this).text().toLowerCase().indexOf(val.toLowerCase()) != -1;
        var regExp = new RegExp(val, 'ig');
        if (val.length > 2) {
          $('.title, .description', this).each(function(k, v) {
            if ($(v).text().toLowerCase().indexOf(val.toLowerCase()) != -1) {
              var newHTML = $(v).text().replace(regExp, '<span class="highlight">$&</span>');
              $(v).html(newHTML);
            }
          });
        } else {
          $('.title, .description').each(function(k, v) {
            var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
            var newHTML = $(v).text().replace(reg, '$&');
            $(v).html(newHTML);
          });
        }
        return found;
      }).show();
    } else {
      $('.title, .description').each(function(k, v) {
        var reg = new RegExp('<span class="highlight">(.+)<\/span>', 'ig');
        var newHTML = $(v).text().replace(reg, '$&');
        $(v).html(newHTML);
      });
      $(".entry").show();
    }
  });
});
&#13;
.highlight {
  background-color: blue
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="search">

<div class="entry">
  <div class="title">hello world test 123</div>
  <div class="description">lorem ipsum test test1 testing</div>
</div>

<div class="entry">
  <div class="title">attack on titan</div>
  <div class="description">fullmetal alchemist</div>
</div>
&#13;
&#13;
&#13;