2010-01-19 14 views
16

Mi ha sorpreso il fatto che Sizzle (il motore di selezione utilizzato da jQuery) sia dotato di un selettore :nth-child() integrato, ma manca di un selettore :nth-of-type().: nth-of-type() in jQuery/Sizzle?

Per illustrare la differenza tra :nth-child() e :nth-of-type() e per illustrare il problema, si consideri the following HTML document:

<!doctype html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <title>:nth-of-type() in Sizzle/jQuery?</title> 
    <style> 
    body p:nth-of-type(2n) { background: red; } 
    </style> 
</head> 
<body> 
    <p>The following CSS is applied to this document:</p> 
    <pre>body p:nth-of-type(2n) { background: red; }</pre> 
    <p>This is paragraph #1.</p> 
    <p>This is paragraph #2. (Should be matched.)</p> 
    <p>This is paragraph #3.</p> 
    <p>This is paragraph #4. (Should be matched.)</p> 
    <div>This is not a paragraph, but a <code>div</code>.</div> 
    <p>This is paragraph #5.</p> 
    <p>This is paragraph #6. (Should be matched.)</p> 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
    <script> 
    $(function() { 
    // The following should give every second paragraph (those that had red backgrounds already after the CSS was applied) an orange background. 
    // $('body p:nth-of-type(2n)').css('background', 'orange'); 
    }); 
    </script> 
</body> 
</html> 

Dal Sizzle utilizza il browser nativo querySelector() e querySelectorAll() metodi se questi sono presenti (ad esempio nei browser che già implementare il Selectors API), cose come $('body p:nth-child'); funzioneranno ovviamente. Tuttavia, non funzionerà con i browser più vecchi, perché Sizzle non ha alcun metodo di fallback per questo selettore.

È possibile aggiungere facilmente il selettore :nth-of-type() a Sizzle o implementarlo in jQuery (utilizzando the built-in :nth-child() selector, forse)? A custom selector with parameters sarebbe bello.

+2

Non sicuro, ma non '$ ('p: even')' ti dà quello che stai cercando? Hai già il selettore ('p'), quindi devi solo filtrarlo. – Kobi

+1

@Kobi: non è così facile. Il selettore 'p: nth-child (2n)' corrisponde a ogni secondo paragrafo * in ogni elemento genitore *. Se ci sono due DIV, entrambi contenenti tre paragrafi, i seguenti paragrafi (in ordine DOM) verrebbero abbinati a 'p: nth-child (2n)': # 2, # 5. Vedere? Non si tratta solo di ottenere ogni 'P' nel documento e quindi di filtrarlo in ogni * mn * th elemento. Sì, '$ ('p: even')' è un alias per '$ ('p: nth-child (2n)')', ma non per '$ ('p: nth-of-type (2n) ') '. Inoltre, sto usando '2n' in questo esempio, ma ovviamente anche altre varianti dovrebbero essere possibili. –

+0

Capito e cancellato la mia risposta. – Kobi

risposta

14
/** 
* Return true to include current element 
* Return false to exclude current element 
*/ 
$.expr[':']['nth-of-type'] = function(elem, i, match) { 
    if (match[3].indexOf("n") === -1) return i + 1 == match[3]; 
    var parts = match[3].split("+"); 
    return (i + 1 - (parts[1] || 0)) % parseInt(parts[0], 10) === 0; 
}; 

Test case - (verifica in IE o rinominare il selettore)

Ovviamente si può aggiungere anche & dispari troppo:

match[3] = match[3] == "even" ? "2n" : match[3] == "odd" ? "2n+1" : match[3]; 

+1

Fantastico! Questo è quello che stavo cercando; una soluzione breve, intelligente, concisa. Come sapete, ': odd' e': even' sono già supportati in jQuery, non solo nella forma ': nth-of-type (dispari)'/': nth-of-type (even)', ma è bello averli anche lì per motivi di completezza. Aggiornamento –

+0

: per un numero ancora maggiore di selettori, vedere https://github.com/keithclark/JQuery-Extended-Selectors –

+1

Bello, ma volevo solo avvisare gli altri di questa soluzione assumendo sempre una periodicità (n). Voglio dire, filtro come ': nth-of-type (2n)' e ': nth-of-type (2)' sarà lo stesso (quando quest'ultimo dovrebbe essere solo il 2 ° elemento, invece di tutti gli elementi pari) . –

1

Non posso fingere di sapere come viene implementato l'nth-of-type, ma jQuery fornisce un meccanismo tramite il quale è possibile creare il proprio selettore personalizzato.

i seguenti questione riguarda selettori personalizzati, e possono fornire una visione utile a voi

What useful custom jQuery selectors have you written?

+0

Sì, ne sono a conoscenza ... Probabilmente dovrei aggiungerlo al mio post. –

4

il plugin jQuery moreSelectors ha il supporto per nth-of-type (e molti altri selettori). Suggerisco di usarlo o semplicemente di implementare un semplice plugin che implementa solo i selettori esatti di cui hai bisogno. Dovresti essere in grado di copiare e incollare il codice da lì.

Happy hacking!