突出显示字符串中的匹配文本(JQuery / Javascript)

时间:2017-04-10 16:11:00

标签: javascript jquery

我试图在任何一点只突出显示字符串中的匹配文本。

我有一个过滤结果的输入框。最初这可以很好地突出第一个字符,但是在任何位置都可以更改为突出显示字符串中的文本。

小提琴:Highlight matching text

过滤完美无缺,但突出显示从前面开始的字母,而不是匹配的字母。我尝试使用indexOf valThis对其进行排序,但我可能做错了。

任何帮助或指示都会非常感激。

$('#box').keyup(function () {

var valThis = this.value.toLowerCase();
var length  = this.value.length;

$('.objType').each(function () {
    var text  = $(this).text(),
        textL = text.toLowerCase(),
        //n = textL.indexOf(valThis);
     var htmlR = '<b>' + text.substr(0, length) + '</b>' + text.substr(length);

    if(textL.includes(valThis))
    {
      $(this).html(htmlR).show()
    }
    else
    {
        $(this).hide();
    }
});

});

3 个答案:

答案 0 :(得分:3)

该行

var htmlR = '<b>' + text.substr(0, length) + '</b>' + text.substr(length);

说“从字符串的开头拿走length个字符。”您希望从第一个匹配的字符开始,因此您需要知道它在哪里。所以你想要String#indexOf,而不是String#includes

您还希望保存原始文本,以便与之进行比较,而不是与之前过滤操作更新的文本进行比较:

// Grab the original text
$(".objType").each(function() {               // ***
    $(this).data("original", $(this).text()); // ***
})                                            // ***
$('#box').keyup(function() {
  var valThis = this.value.toLowerCase();
  var length = this.value.length;

  $('.objType').each(function() {
    var text = $(this).data("original"),      // ***
      textL = text.toLowerCase(),
      index = textL.indexOf(valThis);         // ***

    if (index !== -1) {
      var htmlR = text.substr(0, index) + '<b>' + text.substr(index, length) + '</b>' + text.substr(index + length); // ***
      $(this).html(htmlR).show()
    } else {
      $(this).hide();
    }
  });
});

Updated Fiddle,摘录:

// Grab the original text
$(".objType").each(function() {               // ***
	$(this).data("original", $(this).text()); // ***
})                                            // ***
$('#box').keyup(function() {
  var valThis = this.value.toLowerCase();
  var length = this.value.length;

  $('.objType').each(function() {
    var text = $(this).data("original"),      // ***
      textL = text.toLowerCase(),
      index = textL.indexOf(valThis);         // ***

    if (index !== -1) {
      var htmlR = text.substr(0, index) + '<b>' + text.substr(index, length) + '</b>' + text.substr(index + length); // ***
      $(this).html(htmlR).show()
    } else {
      $(this).hide();
    }
  });
});
input[type="text"] {
  width: 50%;
  font-size: 110%;
  margin: 10px;
  padding: 5px;
  float: left;
  clear: left;
}

span {
  float: left;
  clear: left;
  margin: 10px 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input placeholder="Filter results" id="box" type="text" />

<span class="objType" id="item1">Accepted Event Relation</span>
<span class="objType" id="item2">Case Status Value</span>
<span class="objType" id="item3">External Data Source</span>
<span class="objType" id="item4">Navigation Link Set</span>

答案 1 :(得分:1)

试试这个。 它进行非破坏性复制

&#13;
&#13;
$('#box').keyup(function () {
    var valThis = this.value.toLowerCase(),
        length  = this.value.length;

    $('.objType').each(function () {
        var text  = $(this).text(),
            textL = text.toLowerCase(),
            textStart = textL.indexOf(valThis),
            textEnd = textStart+valThis.length;
            //n = textL.indexOf(valThis);
         var htmlR = text.substring(0,textStart)+'<b>' + text.substring(textStart,textEnd) + '</b>' + text.substring(textStart+length);
        
        if(textStart!=-1) {
          $("#"+this.id+"r").html(htmlR).show()
        	$(this).hide();
        }
        else {
         $("#"+this.id+"r").empty();
        	$(this).hide();
        }
    });

});
&#13;
input[type="text"] { 
    width: 50%;
    font-size: 110%;
    margin:10px;
    padding: 5px;
    float:left;
    clear:left;
}
span{
  float:left;
  clear:left;
  margin:10px 10px;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input placeholder="Filter results" id="box" type="text" />

<span class="objType" id="item1">Accepted Event Relation</span><span id="item1r"></span>
<span class="objType" id="item2">Case Status Value</span><span id="item2r"></span>
<span class="objType" id="item3">External Data Source</span><span id="item3r"></span>
<span class="objType" id="item4">Navigation Link Set</span><span id="item4r"></span>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

我猜你需要使用indexOfRegExsubstring的组合来查找并突出显示每个字符串中单词的位置。

见小提琴: https://jsfiddle.net/sxk7qj40/

$('#box').keyup(function () {
  const valThis = this.value;
  const length  = this.value.length;

  $('.objType').each(function () {
    const text  = $(this).text();
    const textL = text.toLowerCase();
    const position = textL.indexOf(valThis.toLowerCase());

    if (position !== -1) {
      const matches = text.substring(position, (valThis.length + position));
      const regex = new RegExp(matches, 'ig');
      const highlighted = text.replace(regex, `<mark>${matches}</mark>`);

      $(this).html(highlighted).show();
    } else {
      $(this).text(text);
      $(this).hide();
    }
  });
});

您不希望将substring位置硬编码为0,因为无论如何,这始终始于字符串的开头。

相反,您需要使用indexOf,这将返回起始位置。然后,您可以在子字符串中使用它来查找要replace的起点。请注意,indexOf如果找不到则会返回-1,因此会if声明。

虽然在哪里结束?好吧,这将作为我们已经拥有的起始位置+您刚输入的字符串长度的组合。

  

注意:为了方便起见,我使用了一些 es2015 功能,例如const和模板文字,但是你不能使用 es2015 ,只需通过Babel运行,   或者用var和string连接手动替换这些部分   分别

希望这有道理吗?

e.g。 ES5安全:

$('#box').keyup(function () {
  var valThis = this.value;
  var length  = this.value.length;

  $('.objType').each(function () {
    var text  = $(this).text();
    var textL = text.toLowerCase();
    var position = textL.indexOf(valThis.toLowerCase());

    if (position !== -1) {
      var matches = text.substring(position, (valThis.length + position));
      var regex = new RegExp(matches, 'ig');
      var highlighted = text.replace(regex, '<mark>' + matches + '</mark>');

      $(this).html(highlighted).show();
    } else {
      $(this).text(text);
      $(this).hide();
    }
  });
});