最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Highlight only matching text within a string (JQueryJavascript) - Stack Overflow

programmeradmin10浏览0评论

I'm trying to highlight only matching text within a string at any point.

I have an input box which filters the results. Originally this worked fine to highlight the FIRST character, but the remit has changed to highlight the text within a string at any position.

Fiddle: Highlight matching text

It filters perfectly as it should, but highlights letters starting at the front, not the matching ones. I tried to use indexOf valThis to sort it out but I was probably doing it wrong.

Any help or pointers would be really appreciated.

$('#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();
    }
});

});

I'm trying to highlight only matching text within a string at any point.

I have an input box which filters the results. Originally this worked fine to highlight the FIRST character, but the remit has changed to highlight the text within a string at any position.

Fiddle: Highlight matching text

It filters perfectly as it should, but highlights letters starting at the front, not the matching ones. I tried to use indexOf valThis to sort it out but I was probably doing it wrong.

Any help or pointers would be really appreciated.

$('#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();
    }
});

});
Share Improve this question asked Apr 10, 2017 at 16:11 sidestealsidesteal 672 silver badges5 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 5

The line

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

says "take length characters from the beginning of the string." You want to start with the first matching character, so you need to know where that is. So you want String#indexOf, not String#includes.

You also want to save the original text so you can pare against that, not against the text updated by the previous filter operation:

// 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, snippet:

// 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./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>

Try this. It does non-destructive copying

$('#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();
        }
    });

});
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./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>

I guess you need to use a bination of indexOf, RegEx and substring to find and highlight the position of the word in each string.

See Fiddle here: https://jsfiddle/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();
    }
  });
});

You would not want to hardcode your substring position at 0, as this will always begin at the start of the string regardless.

Instead, you need to use indexOf, which will return the starting position. You can then use that in the substring to find the starting point that you want to replace. Note that indexOf will return -1 if not found, hence the if statement.

Where to end though? Well, this will e in as a bination of the start position we already have + the string length you just typed.

NOTE: For my own convenience, I used some es2015 features like const and template literals, but you can't use es2015, simply run it through Babel, or manually replace these parts with var and string concatenation respectively.

Hope this makes sense?

e.g. ES5 safe:

$('#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();
    }
  });
});
发布评论

评论列表(0)

  1. 暂无评论