Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

274
Vistas
RegEx/JS: Wrap innerHTML text elements in span including nested HTML elements

Given the innerHTML of an element, I'm trying to wrap each word in a span, and if the word is already wrapped, wrap the element.

e.g. Such that Here is a paragraph <span class="red">which</span> <div id="typed-effect">might</div> have nested elements

Becomes <span>Here</span> <span>is</span> <span>a</span> <span>paragraph</span> <span class="red">which</span> <span><div id="typed-effect">might</div></span> <span>have </span> <span>nested</span> <span>elements</span>

The components I have are:

  1. Extract the innerHTML and wrap in spans:
function wrapElementText(elementSelector) {
   const element = document.querySelector(elementSelector);
   const rawHTML = element.innerHTML;
   // Do magic to create list
   element.innerHTML = "";
   list.forEach((i, item) => {
     if (!item.contains(`<span`)) {
        element.innerHTML += `<span class="wrapped-text">${item}</span>`
      }
   }
};
  1. My best attempt is this ((\<.*?\>)|((\s?).*?(\s))) but it's returning e.g. <div id="typed-effect"> and might</div> as seperate groups when it should be one group <div id="typed-effect">might</div>.

Thanks so much in advance!

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Ok so i came up with these solutions:

  1. the regex approach(not recommended but what you asked for):
function wrapElementTextRegexp(elementSelector) {
    const element = document.querySelector(elementSelector);
    const chunks = element.innerHTML.match(/[a-zA-Z]+|(<[a-z][^>]+>.+<\/[^>]+>)/g);
    element.innerHTML = "";
    for(const chunk of chunks) {
        element.innerHTML += !chunk.startsWith('<span')
            ? `<span class="wrapped-text">${chunk}</span>`
            : chunk
    }
}

Here, the regexp is searching for a whole text or for a html tag pattern(simplified), in case it finds something that is not a span it wraps it in a span, otherwise it just return the original span

  1. the childNodes approach(imo better):
function wrapElementTextNodes(elementSelector) {
    const element = document.querySelector(elementSelector);
    const parsedInnerHTML = [...element.childNodes]
        .map(node => node instanceof HTMLElement
            ? node instanceof HTMLSpanElement
                ? node.outerHTML
                : `<span class="wrapped-text">${node.outerHTML}</span>`
            : node.textContent
                  .trim()
                  .split(/\s+/)
                  .map(word => `<span class="wrapped-text">${word}</span>`))
        .flat()
        .filter(chunk => !chunk.match(/><\//g))
        .join('')
  element.innerHTML = parsedInnerHTML;
}

Here we have access to the instances and we don't have to split the innerHTML since we're using childNodes, in the example i mapped the nodes by checking if the node was an actual HTMLElement and if yes if it was a HTMLSpanElement. After the first map i used a filter to remove from the array every empty node generated after the map(filtering out nodes like <span class="wrapped-text"></span>) and finally i join() the elements.

IMPORTANT NOTE wrapping a <div> element inside a <p> it's a bad practice, javascript won't recognize any childNode after the div(included) so for example if you have

<p>
    some
    <div>bad</div>
    example
</p>

the div and the node example will be omitted in element.innerHTML that, in this case, will return some. So make sure you correct your markup

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda