Dado el HTML interno de un elemento, estoy tratando de envolver cada palabra en un lapso, y si la palabra ya está envuelta, envuelva el elemento.
por ejemplo, tal que Here is a paragraph <span class="red">which</span> <div id="typed-effect">might</div> have nested elements
Se convierte <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>
Los componentes que tengo son:
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>` } } };((\<.*?\>)|((\s?).*?(\s))) pero está regresando, por ejemplo, <div id="typed-effect"> y might</div> como grupos separados cuando debería ser un grupo <div id="typed-effect">might</div> .Muchas gracias de antemano!
Ok, entonces se me ocurrieron estas soluciones:
function wrapElementTextRegexp(elementSelector) { const element = document.querySelector(elementSelector); const chunks = element.innerHTML.match(/[a-zA-Z]+|(<[az][^>]+>.+<\/[^>]+>)/g); element.innerHTML = ""; for(const chunk of chunks) { element.innerHTML += !chunk.startsWith('<span') ? `<span class="wrapped-text">${chunk}</span>` : chunk } }Aquí, la expresión regular está buscando un texto completo o un patrón de etiqueta html (simplificado), en caso de que encuentre algo que no sea un lapso, lo envuelve en un lapso, de lo contrario, simplemente devuelve el lapso original
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; } Aquí tenemos acceso a las instancias y no tenemos que dividir el HTML interno ya que estamos usando childNodes, en el ejemplo map los nodos comprobando si el nodo era un HTMLElement real y, en caso afirmativo, si era un HTMLSpanElement. Después del primer mapa, utilicé un filter para eliminar de la matriz todos los nodos vacíos generados después del mapa (filtrando nodos como <span class="wrapped-text"></span> ) y finalmente join() los elementos.
NOTA IMPORTANTE envolver un elemento <div> dentro de un <p> es una mala práctica, javascript no reconocerá ningún childNode después del div (incluido), por ejemplo, si tiene
<p> some <div>bad</div> example </p> el div y el example de nodo se omitirán en element.innerHTML que, en este caso, devolverá some . Así que asegúrese de corregir su marcado