Mike L.
Mike L.

Reputation: 343

Highlight words that do not match the given string

What I'd like to do: when the user finishes typing in some text, I want this text to be tested against another string. If they don't match, I want the symbols that failed the test to be highlighted / colored red. So far I was only able to come up with the following code

let string = "The quick brown fox jumps over the lazy dog";

let input = document.querySelector(".js-textarea");

let receivedValue = "";

let checkValue = function() {
  let regex = new RegExp(string,"g");
 
  receivedValue = input.value;
  if(!regex.test(receivedValue)) {
    input.classList.add("error");
  };
}

input.addEventListener("change",checkValue);
.error {
  border: 1px solid red;
}
<div class="textarea-block">
  <textarea class="js-textarea"></textarea>
</div>

Just to see whether it is actually being tested, I color the border; but how can I get the symbols/words that don't pass the test?

Upvotes: 0

Views: 653

Answers (2)

Daniel
Daniel

Reputation: 596

The textarea element does not provide a way to apply styling to individual words so the easiest way would be to add an error message below the input element. This answer shows how that can be accomplished.

There is the hard way, though.

You can use an HTML element with the contenteditable attribute. This lets users edit the contents of the HTML element. If you give it a border and a use a white background it will look just like a textarea element.

In this example I chose to highlight with green the text that matches the string and everything else with red.

let string = "The quick brown fox jumps over the lazy dog";

let input = document.querySelector("div");

input.addEventListener("focus", () => {
  // Remove styling so as to not distract the user.
  for (let i = 0; i < input.children.length; i++) {
      input.children[i].className = "";
  }
});

input.addEventListener("blur", () => {
  // We will recreate styling tags. This is under the assumption that the
  // element will not have a lot of text.
  let value = input.textContent;
  input.textContent= "";

  let failPoint = -1;

  for (var i = 0; i < string.length && i < value.length; i++) {
      if (value[i].toLowerCase() !== string[i].toLowerCase()) {
          failPoint = i;
          break;
      }
  }

  let good = document.createElement("span");
  good.classList.add("success");
  good.textContent = value.substring(0, failPoint !== -1 ? failPoint : value.length);
  input.append(good);

  if (failPoint !== -1) {
      let bad = document.createElement("span");
      bad.classList.add("error");
      bad.textContent = value.substring(i);
      input.append(bad);
  }
});
.editable {
    border: 1px solid #ccc;
    width: 300px;
    height: 100px;
    overflow: auto;
    background: white;
    color: #020202;
    padding: 2px;
    word-break: break-all;
    font-family: sans-serif;
}

.success {
  color: green;
}

.error {
  color: red;
}
<div class="editable" contenteditable spellcheck="false"></div>

Upvotes: 0

user120242
user120242

Reputation: 15268

I just used a style red for the entire div, and then wrap matched text with a span with style black. Also added ^$ to force match whole string for the test, so the whole string has to match for it to ignore it.
You could also use '(.*?)('+string+')(.*?)' and wrap the 1st and 3rd capture groups with error spans.

I'm not sure if this is what you're looking for, but roughly guessing what you are trying to do:

let string = "The quick brown fox jumps over the lazy dog";

let input = document.querySelector(".js-textarea");

let receivedValue = "";

let checkValue = function() {
  let regex1 = new RegExp(string,"g");
  let regex = new RegExp('^'+string+'$',"g");
 
  receivedValue = input.value;
  if(!regex.test(receivedValue)) {
      document.getElementById('errorbox').innerHTML=receivedValue.replace(regex1,'<span class="matches">$&</span>');
//    input.classList.add("error");
  }
}

input.addEventListener("change",checkValue);
checkValue()
.error {
  border: 1px solid red;
}

.matches {
   color: black
}
<div class="textarea-block">
  <textarea class="js-textarea">The quick brown fox jumps over the lazy dog. Jack</textarea>
</div>

<span id="errorbox" style="color:red"></span>

Upvotes: 1

Related Questions