Skip to content
Advertisement

How to avoid affecting HTML tags in childNodes during innerHTML string.replace()?

I am aiming to replace each word in a document P tags with a span element. While the below code does the trick well for the first case, the following ones overlap, and start to destroy the HTML structure of our P tag completely. See image for unwanted output

Wondering if my approach is a wrong one, or would need some sorcery to only effect the innerHTML between the tags?

const runBionic = (node: ChildNode, paragraph: HTMLElement):HTMLElement => {
if (node.textContent === null) return paragraph;
const originalWords:string[] = node.textContent.split(" ");
const filteredWords: string[] = originalWords.filter(word => word!=="" && word !== "n");
console.log("Filtered words: ", filteredWords);
//replace each word with a span element
filteredWords.forEach(word => {
    const modifiedWord = `<span style='font-weight: bold;'>${word}</span>`;
    console.log("REPLACING ", word, "WITH ", modifiedWord);
    paragraph.innerHTML = paragraph.innerHTML.replaceAll(word,modifiedWord);
});
return paragraph;};

Aiming to eventually build a chrome extension that highlights the first 1/2 of the characters of any word on any page. This will help dyslexic people read the web faster. Attaching a link to the whole repo on github for context.

Advertisement

Answer

Okay, so I ended up with replacing the whole TextNode with a new span element instead. This way I can prepare the whole element and append it to its parent. Works perfectly, no regex needed….

const replaceNode = (node: ChildNode)=>{
if (node.textContent === null) return node;
const newChild = document.createElement("span");
const words: string[] = node.textContent.split(" ").filter(word => word!=="" && word !== "n");
const HTMLstring: string = spannify(words);
newChild.innerHTML = HTMLstring;
return newChild;};

const spannify = (words : string[]) : string=>{
let HTMLstring = "";
words.forEach(word =>{
    const span = `<span> ${word} </span>`;
    HTMLstring += span;
});
return HTMLstring;};
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement