Home > Software design >  Highlight matched text instead of the whole the text
Highlight matched text instead of the whole the text

Time:01-08

I have a function, getTextNodes, that searches text nodes recursively. Then I use a addHighlight function to highlight the text with <mark> tags:

const buttonEl = `<button>
  <span>
    Icon
  </span>
  Text
</button>
`;

document.body.innerHTML = buttonEl;

const foundButtonEl = document.querySelector("button");
const elements = [];

elements.push(foundButtonEl);

addHighlight(elements, "T");

function addHighlight(elements, text) {
  elements.forEach((element, index) => {
    const textNodes = getTextNodes(document.body);
    const matchingNode = textNodes.find(node => node.textContent.includes(text));

    const markElement = document.createElement('mark');
    markElement.innerHTML = matchingNode.textContent;
    matchingNode.replaceWith(markElement);
  });
}

function getTextNodes(node) {
  let textNodes = [];

  if (node.nodeType === Node.TEXT_NODE) {
    textNodes.push(node);
  }

  node.childNodes.forEach(childNode => {
    textNodes.push(...getTextNodes(childNode));
  });

  return textNodes;
}

The problem is that addHighlight is highlighing the whole text (in the example, Text), instead of the matched text (in the example, T).

How to change this code so that only the matched text is highlighted (text)?

CodePudding user response:

The problem is that the node you match is the element of which the innerContent contains the string you want to highlight.

What you should do instead of :

markElement.innerHTML = matchingNode.textContent;
matchingNode.replaceWith(markElement);

is probably something like

markElement.innerHTML = text;
matchingNode.replaceTextWithHTML(text, markElement);

replaceTextWithHTML is a fictive function :)

CodePudding user response:

matchingNode is the whole node so you're replacing everything. If you want to match just part of it, you need to iterate though the textnode and find the index positions of the substring that you're searching for.

Start by splitting the node into an array

matchingNode.split("")

Then find the index positions, insert markElement at that position, and go from there.

  • Related