2011-06-29 10 views
5

Questa è una variazione su una domanda posta tante volte. Dato qualsiasi elemento, voglio essere in grado di trovare qualsiasi altro elemento dopo di esso nell'intero documento. Può essere un fratello ma potrebbe anche essere qualsiasi altro elemento che si verifica in seguito. Ad esempio, dato il seguente markup,Elemento successivo in * intero * documento dopo un determinato elemento

<div> 
    <p>Hello</p> 
    <div> 
     <p>Foo</p> 
     <p class="bar">Bar</p> 
     <p>rawr!</p> 
    </div> 
    <p>bop</p> 
    <input/> 
    <div> 
     <p>Another</p> 
     <div> 
      <span>something</span> 
      <p>deep!</p> 
     </div> 
    </div> 
</div> 
<p>last</p> 

Per il bene di questa descrizione, diciamo la funzione sto cercando è chiamato $.fn.nextInDocument. Se ho chiamato:

$('.bar').nextInDocument('p'); // <p>rawr</p> 
$('.bar').nextInDocument('p').nextInDocument('p'); // <p>bop</p> 

Proseguendo, si otterrebbe <p>Another</p>, quindi <p>deep!</p> e infine <p>last</p>.

Esiste qualcosa del genere? Non mi interessa se si tratta di un selettore o di una funzione. Ho solo bisogno della funzionalità.

EDIT Aggiornato la struttura DOM per renderlo una domanda più stimolante e ancora più chiara per quello che sto cercando.

risposta

2

ne dici di questo? È una soluzione generica che utilizza i metodi DOM per attraversare a turno i nodi e testa ciascuno contro il selettore jQuery.

jsFiddle: http://jsfiddle.net/PsEdZ/3/

(function($) { 
    function nextNode(node, omitChildren) { 
     var sibling, parentNode; 
     if (!omitChildren && node.hasChildNodes()) { 
      return node.firstChild; 
     } else { 
      sibling = node.nextSibling; 
      if (sibling) { 
       return sibling; 
      } else { 
       parentNode = node.parentNode; 
       return parentNode ? nextNode(parentNode, true) : null; 
      } 
     } 
    } 

    $.fn.nextInDocument = function(selector) { 
     var node = this[0], $node; 
     while ((node = nextNode(node))) { 
      $node = $(node); 
      if ($node.is(selector)) { 
       return $node; 
      } 
     } 
     return null; 
    } 
})(jQuery); 
+0

sembra che funzioni. testare alcune situazioni difficili ora ... – Jeff

+0

questo ha resistito a tutto ciò che ho buttato su di esso finora. Mi chiedo quanto bene funzioni, ho pensato fin da ora che non ho intenzione di correre su pagine troppo grandi. grazie mille! – Jeff

+0

@Jeff: Probabilmente potrebbe essere ottimizzato: ad esempio, immagino che valutare il selettore per ogni nodo sia causa di possibili problemi di prestazioni. Suggerirei solo di preoccuparmene se causa un collo di bottiglia. –

1

Questo dovrebbe funzionare. Non proprio sicuro che sia utile, anche se ...

;(function ($) 
{ 
    $.fn.nextInDocument = function (s) 
    { 
     var self = this, 
      next; 
     do 
     { 
      next = self.nextAll(s).first(); 
      self = self.parent(); 
     } 
     while (self.length && !next.length); 

     return next; 
    }; 
})(jQuery); 

Demo: http://jsfiddle.net/mattball/HAFn8/

+0

@ Matt sfera ha alcuni problemi che vanno in elementi figlio dopo un elemento corrente, anche se non sono sicuro se fosse anche dopo la funzionalità del genere: http://jsfiddle.net/niklasvh/HAFn8/3/ – Niklas

+0

Grazie per averlo indicato. Una carenza evidente, renderà sicuramente le cose più complicate se necessario. Avrà bisogno di un algoritmo di attraversamento dell'albero migliore. –

+0

Non sono abbastanza sicuro di come funzioni, ma sembra promettente. L'ho messo in un violino e non c'è modo di abbinare un selettore. In altre parole '$ ('. Bar'). NextInDocument ('p') == $ ('. Bar'). NextInDocument ('div') == '

rawr!

'. – Jeff

1
(function(jQuery) { 
jQuery.fn.extend({ 
    nextInDocument: function(a) { 
     if (jQuery(this).next(a).length === 0) { 
      //console.log($(this).parent().nextInDocument('p')); 
      jQuery(this).parent().nextInDocument(a); 
     } 
     else 
      return jQuery(this).next(a); 
    } 
}); 
})(jQuery); 
+0

grazie Boopathi. Non sono sicuro che mi manchi qualcosa. Ho messo questo in un violino e la tua funzione ha restituito l'elemento originale per ogni chiamata, ad esempio '$ ('. bar ') .nextInDocument (' div ') ==

rawr

'. http://jsfiddle.net/jeffrod/nHeGU/ – Jeff

+0

scusate per il fatto che ... corretto .. verificarlo .. ha un altro bug minore. migliorare ... –

+0

im ottenere nulla indietro da questo.non sembra funzionare ancora – Jeff

0

prendere un'occhiata al mio codice:

HTML

<div> 
    <p>Hello</p> 
    <div> 
     <p>Foo</p> 
     <p>Fooooo</p> 
     <p class="bar">Bar</p> 
     <p>rawr!</p> 
    </div> 
    <p>bop</p> 
    <input/> 
    <div> 
     <p>Another</p> 
    </div> 
</div> 
<p>last</p> 

<a class="show" href="#">!!!</a> 

JS

$(function() { 
    i = 0; 
    start = 0; 
    $('p').each(function() { 
     if ($(this).hasClass('bar')) { 
      start = i; 
     } 
     i++; 
    }); 
    $('a.show').click(function(){ 
     alert($('p').eq(start+4).text()); 
    }); 
}); 

http://jsfiddle.net/mV8pm/

cambiamento start+X e si otterrà il prossimo tag 'p'

+0

grazie.questo sembra che sia strettamente accoppiato al markup che ho dato nella demo, ma ho bisogno di qualcosa che può funzionare "per qualsiasi elemento" e afferra "qualsiasi elem dopo di lui ". non penso che questo sarebbe quel flessibile – Jeff

+0

scommetto che lo proverò :) provalo su diversi DOM. tutto ciò di cui hai bisogno è mettere questo codice nella funzione JQ. a proposito, tag dell'elemento start (selezionato per classe) e tag che stai cercando dopo dovrebbe essere lo stesso (ad esempio 'p'). – bravedick

1

Ecco una versione POJS:

function nextInDocument(el, tagName) { 
    var node, nodes = document.getElementsByTagName('*'); 
    var start = false; 
    tagName = tagName.toLowerCase(); 

    for (var i=0, iLen=nodes.length; i<iLen; i++) { 
    node = nodes[i]; 
    if (!start) { 
     if (node == el) start = true; 
    } else { 
     if (node.tagName.toLowerCase() == tagName) { 
     return node; 
     } 
    } 
    } 
} 
+0

bella soluzione per plain old js. Grazie. jquery può fare uso di selettori più complicati anche se ciò rende alcuni altri frammenti più interessanti per la mia particolare situazione. – Jeff

+0

Fai attenzione a questo approccio, potresti riscontrare problemi di prestazioni se rendi i selettori troppo complessi. Prendi in considerazione l'utilizzo delle classi, in modo che l'elemento successivo sia più facile da trovare. – RobG

+0

buon punto. mal considerato che se le prestazioni diventano un problema. – Jeff

Problemi correlati