regexp highlight search matching numbers

Tags: , ,



I’ve got a script from a friend, and tried to modified it. So that it highlights a string of numbers in a div.

The problem is, that the output of the highlighted text becomes the regexp. Any solutions, what I’m doing wrong?

var list = document.getElementsByClassName("message__content")
var search_word = RegExp(/9756[0-9]{8}/);

var contents = []


for(var i = 0; i < list.length; i++){
var contents = list[i].textContent.split(search_word)


var elem = '<span class="highlight">'+search_word+'</span>'
list[i].innerHTML = contents.join(elem)
}

https://jsfiddle.net/rrggrr/kgd4swha/6/

Answer

Here’s a simple way of doing it:

Use a string#replace using /(9756[0-9]{8})/g as the regex to capture the value (don’t forget the g to indicate that it’s a global regex so it’ll run for every match in the input string), then a replace of '<span class="highlight">$1</span>' to use the first capture group and apply the markup.

var list = document.getElementsByClassName("message__content")

for (var i = 0; i < list.length; i++) {
  list[i].innerHTML = list[i].textContent.replace(
    /(9756[0-9]{8})/g,
    '<span class="highlight">$1</span>')
}
.highlight {
  color: blue;
}
<div class="message__content">
  Lorem ipsum dolor sit amet, 975600000000 (random quis) adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore 975611111111 . Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
  aute irure dolor in 975622222222 in voluptate velit esse cillum dolore eu fugiat nulla pariatur. (random quis) 975633333333 sint occaecat (random quis) cupidatat non proident, sunt in culpa qui officia des (random quis) nt mollit anim id est laborum.
</div>

As a note, the problem in the original post is that the string#split function doesn’t actually save the text that was removed as part of the split, so if you wanted to go that route, you’d have to use string#matchAll on the side, and then map over the indexes to put everything together properly.

I took a look at doing this originally before I realized that string#replace is a cleaner solution in this instance.


From a comment, here’s a way to conditionally set button classes based on if a regex matches.

If the goal is to check if every number in the text matches the regex, then we can use a regex replace for /d+/g with a function as the replacement value so that we can do the regex#test within the replacement.

If you want to limit the numbers that get checked, you could modify the /d+/g to change what are being replaced.

var list = document.getElementsByClassName("message__content")

for (var i = 0; i < list.length; i++) {
  let text = list[i].textContent;
      // Make the regex have boundary characters to ensure that it's checking against the whole number, rather than a part
  const regex = /b9756[0-9]{8}b/;
  list[i].innerHTML = text.replace(
    // Replace all number sequences in the text
    /d+/g,
    // Replace by checking if the replacement text matches the regex to determine color
    (match) => `<button class="${regex.test(match)}">${match}</button>`
  )
}
.highlight {
  color: blue;
}

.true {
  background-color: green;
}

.false {
  background-color: red;
}
<div class="message__content">
  Lorem ipsum dolor sit amet, 975600000000 (random quis) adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore 975611111111 . Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis
  aute irure dolor in 975622222222 in voluptate velit esse cillum dolore eu fugiat nulla pariatur. (random quis) 975633333333 sint occaecat (random quis) cupidatat non proident, sunt in culpa qui officia des (random quis) nt mollit anim id est laborum.
  975600000000, 9756000000009, 097560000000, 9756000
</div>

Another possibility intead of checking every number is to split on a value and then map over the resulting values. I’m just including this as it’s helpful for something that’s simple to split.

var list = document.getElementsByClassName("message__content")

for (var i = 0; i < list.length; i++) {
  // split by ', ' as that is what is separating between values
  const values = list[i].textContent.split(', ');
  // Make the regex have boundary characters to ensure that it's checking against the whole number, rather than a part
  const regex = /b9756[0-9]{8}b/;
  list[i].innerHTML = values.map((value) => {
    // Loop over the split values and create buttons based on if the regex is a match against the string
    return `<button class="${regex.test(value)}">${value}</button>`
  }).join(', ');
}
.true {
  background-color: green;
}

.false {
  background-color: red;
}
<div class="message__content">
  975600000000, 9756000000009, 097560000000, 9756000
</div>


Source: stackoverflow