Me sorprende que no haya ningún código de libro de cocina listo que enumere o busque a lo largo del eje anterior en un DOM con javascript de la forma en que XPath puede hacerlo. Y, por supuesto, el siguiente eje también.
El problema de ejemplo es: tengo un nodo de texto y quiero encontrar el nodo de texto anterior.
Obviamente el precedenteSibling es insuficiente, porque podría no haber ninguno, o podría ser un elemento.
Lo he implementado varias veces por mí mismo, pero soy demasiado perezoso para tratar de encontrar mi código. En cambio, prefiero hacerlo de nuevo. Pero también les gusta comparar notas, y les sorprende que nadie parezca preguntarle al respecto, ni presumir de las suyas.
Así que aquí hay una firma de función con algunos garabatos iniciales:
Node.prototype.findPrevious function(foundPr = x => x, giveUpPr = () => false) { node = this; while(true) { let previousSibling = node.previousSibling; if(!previousSibling) // no previousSibling means we need to go up while(true) { const parent = node.parentNode; previousSibling = parent.previousSibling; if(parent.previousSibling) break; node = parent; if(!node || giveUpPr(node)) return null; } // now we have the nearest previous sibling (or we gave up already) node = previousSibling; // but we aren't done, we have to go down now // now finally we have the last previous item while(true) { let lastChild = node.lastChild; if(!lastChild) break; node = lastChild; } // now our node is the deepest lastChild that doesn't have any more children // now only can we check our found predicate: if(foundPr(node)) return node; // and if not we go to the beginning } };Supongo que acabo de escribir el código en lugar de explicar lo que haría. Y lo bueno es que la misma lógica funciona al revés para findNext:
Node.prototype.findNext = function(foundPr = x => x, giveUpPr = () => false) { let node = this; while(true) { let nextSibling = node.nextSibling; if(!nextSibling) // no nextSibling means we need to go up while(true) { const parent = node.parentNode; nextSibling = parent.nextSibling; if(nextSibling) break; node = parent; if(!node || giveUpPr(node)) return null; } // now we have the nearest next sibling (or we gave up already) node = nextSibling; // but we aren't done, we have to go down now // now finally we have the first next item while(true) { let firstChild = node.firstChild; if(!firstChild) break; node = firstChild; } // now our node is the deepest firstChild that doesn't have any more children // now only can we check our found predicate: if(foundPr(node)) return node; // and if not we go to the beginning trying the nextSibling } };¿Pero no hay ya alguna solución integrada?