jquery jquery-selectors next

jQuery encuentra los elementos siguientes/anteriores de una clase determinada pero no necesariamente hermanos



jquery-selectors next (5)

Creo que la única forma de resolver este problema es hacer una búsqueda recursiva sobre los elementos después del elemento actual. No hay una solución simple para este problema provista por jQuery. Si solo desea buscar elementos en los hermanos de su elemento principal (como es el caso en su ejemplo), no es necesario que realice una búsqueda recursiva, sino que tiene que realizar varias búsquedas.

Creé un ejemplo (en realidad, no es recursivo) que hace lo que quieres (espero). Selecciona todos los elementos después del elemento en el que se hizo clic y los pone en rojo:

<script type="text/javascript" charset="utf-8"> $(function () { $(''#click'').click(function() { var parent = $(this); alert(parent); do { $(parent).find(''.find'').css(''background-color'',''red''); parent = $(parent).parent(); } while(parent !== false); }); }); </script>

Los métodos next, prev, nextAll y prevAll son muy útiles, pero no si los elementos que intenta encontrar no están en el mismo elemento principal. Lo que quiero hacer es algo como esto:

<div> <span id="click">Hello</span> </div> <div> <p class="find">World></p> </div>

Cuando se presiona el intervalo con el click identificación, quiero hacer coincidir el siguiente elemento con la find clase, que en este caso no es un hermano del elemento en el que se hizo clic, por lo que next() o nextAll() no funcionarán.


Hoy mismo estuve trabajando en este problema, esto es lo que se me ocurrió:

/** * Find the next element matching a certain selector. Differs from next() in * that it searches outside the current element''s parent. * * @param selector The selector to search for * @param steps (optional) The number of steps to search, the default is 1 * @param scope (optional) The scope to search in, the default is document wide */ $.fn.findNext = function(selector, steps, scope) { // Steps given? Then parse to int if (steps) { steps = Math.floor(steps); } else if (steps === 0) { // Stupid case :) return this; } else { // Else, try the easy way var next = this.next(selector); if (next.length) return next; // Easy way failed, try the hard way :) steps = 1; } // Set scope to document or user-defined scope = (scope) ? $(scope) : $(document); // Find kids that match selector: used as exclusion filter var kids = this.find(selector); // Find in parent(s) hay = $(this); while(hay[0] != scope[0]) { // Move up one level hay = hay.parent(); // Select all kids of parent // - excluding kids of current element (next != inside), // - add current element (will be added in document order) var rs = hay.find(selector).not(kids).add($(this)); // Move the desired number of steps var id = rs.index(this) + steps; // Result found? then return if (id > -1 && id < rs.length) return $(rs[id]); } // Return empty result return $([]); }

Así que en tu ejemplo

<div><span id="click">hello</span></div> <div><p class="find">world></p></div>

ahora puedes encontrar y manipular el elemento ''p'' usando

$(''#click'').findNext(''.find'').html(''testing 123'');

Dudo que se desempeñe bien en grandes estructuras, pero aquí está :)


La siguiente expresión debería (¡salvo los errores de sintaxis!) Encontrar a todos los hermanos del padre que contienen un elemento p.find y luego encontrar esos elementos p.find y cambiar su color a azul.

$(this).parent().nextAll(":has(p.find)").find(".find").css(''background-color'',''blue'');

Por supuesto, si la estructura de su página es tal que p.find ocurre en un nivel de jerarquía totalmente diferente (hermano de un abuelo, por ejemplo), no funcionará.


Mi solución consistiría en ajustar su marca un poco para que el jQuery sea mucho más fácil. Si esto no es posible o no es una respuesta atractiva, ¡ignórelo!

Me gustaría envolver un envoltorio ''padre'' alrededor de lo que quieres hacer ...

<div class="find-wrapper"> <div><span id="click">hello</span></div> <div><p class="find">world></p></div> </div>

Ahora, para encontrar el find :

$(function() { $(''#click'').click(function() { var $target = $(this).closest(''.find-wrapper'').find(''.find''); // do something with $target... }); });

Esto le brinda la flexibilidad de tener cualquier tipo de marca y jerarquía que desee dentro del envoltorio que sugerí, y aún así encontrar de manera confiable su objetivo.

¡Buena suerte!


Prueba esto. Marcará su elemento, creará un conjunto de elementos que coincidan con su selector y recopilará todos los elementos del conjunto que sigue a su elemento.

$.fn.findNext = function ( selector ) { var set = $( [] ), found = false; $( this ).attr( "findNext" , "true" ); $( selector ).each( function( i , element ) { element = $( element ); if ( found == true ) set = set.add( element ) if ( element.attr("findNext") == "true" ) found = true; }) $( this ).removeAttr( "findNext" ) return set }

EDITAR

Solución mucho más simple utilizando el método de índice de Jquerys. el elemento del que se llama el método debe ser seleccionable por el mismo selector, aunque

$.fn.findNext = function( selector ){ var set = $( selector ); return set.eq( set.index( this, ) + 1 ) }

para liberar la función de esta desventaja, podríamos compareDocumentposition propios navegadores compareDocumentposition

$.fn.findNext = function ( selector ) { // if the stack is empty, return the first found element if ( this.length < 1 ) return $(s).first(); var found, that = this.get(0); $( selector ) .each( function () { var pos = that.compareDocumentPosition( this ); if ( pos === 4 || pos === 12 || pos === 20 ){ // pos === 2 || 10 || 18 for previous elements found = element; return false; } }) // using pushStack, one can now go back to the previous elements like this // $("#someid").findNext("div").remove().end().attr("id") // will now return "someid" return this.pushStack( [ found ] ); },

EDIT 2 esto es mucho más fácil usando $ .grep de jQuery. Aquí está el nuevo código

$.fn.findNextAll = function( selector ){ var that = this[ 0 ], selection = $( selector ).get(); return this.pushStack( // if there are no elements in the original selection return everything !that && selection || $.grep( selection, function( n ){ return [4,12,20].indexOf( that.compareDocumentPosition( n ) ) > -1 // if you are looking for previous elements it should be [2,10,18] }) ); } $.fn.findNext = function( selector ){ return this.pushStack( this.findNextAll( selector ).first() ); }

al comprimir nombres de variables esto se convierte en un mero dos trazadores de líneas

Edición 3 usando operaciones bitwise, esta función puede ser incluso más rápida?

$.fn.findNextAll = function( selector ){ var that = this[ 0 ], selection = $( selector ).get(); return this.pushStack( !that && selection || $.grep( selection, function(n){ return that.compareDocumentPosition(n) & (1<<2); // if you are looking for previous elements it should be & (1<<1); }) ); } $.fn.findNext = function( selector ){ return this.pushStack( this.findNextAll( selector ).first() ); }