Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

79
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!