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

81
Vistas
Busque nodos DOM y devuelva el padre si algún descendiente contiene una coincidencia

Digamos que tengo lo siguiente:

 <div className="container"> <div id="one" class="item"> <div></div> <div></div> <div> <span>foo</span> </div> </div> <div id="two" class="item"> <div></div> <div></div> <div> <div>foo</div> </div> </div> <div id="three" class="item"> <span>foo</span> <div></div> <div> <span></span> </div> </div> <div id="four" class="item"> <span></span> <div></div> <div> <div> <span>foo</span> </div> </div> </div> </div>

Quiero devolver todos los elementos que contienen un lapso con contenido de texto "foo" en cualquier lugar dentro de ellos. En el ejemplo anterior, esperaría que se devolvieran 1, 2 y 4.

He escrito un método recursivo pero estoy tropezando en alguna parte, pienso en cómo estoy manejando el retorno. Esto actualmente devuelve todos los artículos.

 const hasFoo = (el) => { const isSpan = el.tagName?.toLowerCase() === "span"; const isMatch = el.innerText?.toLowerCase() === "foo"; if (isSpan && isMatch) { return true; } else if (el.children?.length) { const nodes = [...el.children]; return nodes.forEach(node => hasFoo(node)); } else { return false; } }; const container = document.getElementsByClassName("container")[0]; const nodes = [...container.children]; const filtered = nodes.filter(node => hasFoo(node));
about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

Un par de problemas.

className no es una alternativa válida para el atributo de clase. Por eso, document.getElementsByClassName("container") devuelve una matriz vacía.

return nodes.forEach(node => hasFoo(node)) SIEMPRE devolverá undefined . Según MDN ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach )

forEach() ejecuta la función callbackFn una vez para cada elemento de la matriz; a diferencia de map() o reduce(), siempre devuelve el valor indefinido y no se puede encadenar.

Use un bucle for en su lugar

 const hasFoo = (el) => { const isSpan = el.tagName?.toLowerCase() === "span"; const isMatch = el.innerText?.toLowerCase() === "foo"; if (isSpan && isMatch) { return true; } const nodes = [...el.children]; for (let i = 0; i < nodes.length; i++) { if (hasFoo(nodes[i])) return true; } return false; }
about 4 years ago · Juan Pablo Isaza Denunciar

0

Otros han señalado los problemas con className y su forEach . Pero para una mejor experiencia que un bucle explícito, use Array.prototype.some , así:

 const hasFoo = (el) => (el .tagName ?.toLowerCase() === "span" && el .textContent ?.toLowerCase() === "foo") || [...el .children ?? []] .some (hasFoo) const foos = [... document .querySelectorAll (".container > *")] .filter (hasFoo) foos .forEach (div => div .classList .add ('hasFoo'))
 div {border: 1px solid #ccc; margin: .125em; padding: .125em;} span {border: 1px solid #000; padding: .125em;} div.hasFoo {background-color: yellow; border: 2px dotted #00f;}
 <div class="container"><div id="one" class="item"><div></div><div></div><div><span>foo</span></div></div><div id="two" class="item"><div></div><div></div><div><div>foo</div></div></div><div id="three" class="item"><span>foo</span><div></div><div><span></span></div></div><div id="four" class="item"><span></span><div></div><div><div><span>foo</span></div></div></div></div>

Aquí marcamos todos los <div> s con un borde claro, todos los <span> s con uno más oscuro y resaltamos todos los elementos secundarios de .container que tienen un foo -span con un fondo amarillo y un borde punteado.

about 4 years ago · Juan Pablo Isaza Denunciar

0

No es recursivo, pero prefiero devolver una matriz filtrada de items según la condición/requisito.

 const items = Array.from(document.querySelectorAll('.item')); const itemsWithFooSpans = items.filter(item => { let hasFoo = false; const spans = item.querySelectorAll('span'); spans.forEach(span => { console.log('span: ', span); if (span && span.textContent && span.textContent === 'foo') { hasFoo = true; } }); return hasFoo; });
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