2010-01-19 5 views
16

Il m'a surpris que Sizzle (le moteur de sélection utilise jQuery) est livré avec un sélecteur :nth-child() intégré, mais il manque un sélecteur :nth-of-type().: nth-of-type() dans jQuery/Sizzle?

Pour illustrer la différence entre :nth-child() et :nth-of-type() et pour illustrer le problème, pensez 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> 

Depuis Sizzle utilise les querySelector() et querySelectorAll() navigateur natif méthodes si ceux-ci sont présents (par exemple dans les navigateurs qui mettent déjà en œuvre le Selectors API), des choses comme $('body p:nth-child'); vont bien sûr fonctionner. Cela ne fonctionnera pas dans les anciens navigateurs, car Sizzle n'a pas de méthode de secours pour ce sélecteur.

Est-il possible d'ajouter facilement le sélecteur :nth-of-type() à Sizzle, ou de l'implémenter dans jQuery (en utilisant the built-in :nth-child() selector, peut-être)? Un custom selector with parameters serait bien.

+2

Je ne suis pas sûr, mais je ne veux pas que $ ('p: pair') 'vous donne ce que vous cherchez? Vous avez déjà le sélecteur ('p'), vous avez juste besoin de le filtrer. – Kobi

+1

@Kobi: Ce n'est pas si simple. Le sélecteur 'p: nth-child (2n)' correspondrait à chaque deuxième paragraphe * de chaque élément parent *. S'il y a deux DIVs, les deux contenant trois paragraphes, les paragraphes suivants (dans l'ordre DOM) seront comparés par 'p: nth-child (2n)': # 2, # 5. Voir? Il ne s'agit pas seulement d'obtenir chaque «P» dans le document, puis de le filtrer à chaque * mn * ème élément. Oui, '$ ('p: even')' est un alias pour '$ ('p: nth-child (2n)')', mais pas pour '$ ('p: nth-of-type (2n) ') '. En outre, j'utilise '2n' dans cet exemple, mais bien sûr d'autres variations devraient aussi être possibles. –

+0

Got it, et supprimé ma réponse. – Kobi

Répondre

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 - (vérifier dans IE ou renommer le sélecteur)

Vous pouvez bien sûr ajouter même & étrange aussi:

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

+1

Cool! C'est ce que je cherchais; une solution courte, intelligente et concise. Comme vous le savez, ': odd' et': even' sont déjà pris en charge dans jQuery, mais pas dans le ': nième de type (impair)'/': nième de type (même)' forme, mais il est agréable de les avoir là aussi pour l'amour de l'exhaustivité. –

+0

Mise à jour: pour encore plus sélecteurs, voir https://github.com/keithclark/JQuery-Extended-Selectors –

+1

Nice, mais je voulais juste avertir les autres de cette solution en supposant toujours une périodicité (n). Je veux dire, filtre comme ': nième de type (2n)' et ': nième de type (2)' sera le même (lorsque celui-ci ne devrait être le 2ème élément, au lieu de tous les même éléments) . –

1

Je ne peux pas prétendre savoir comment nth-of-type est implémenté, mais jQuery fournit un mécanisme par lequel vous pouvez créer votre propre sélecteur personnalisé.

Les offres de question suivante avec des filtres personnalisés, et peut fournir un aperçu utile pour vous

What useful custom jQuery selectors have you written?

+0

Oui, je suis conscient de cela ... Je devrais probablement ajouter cela à mon poste. –

4

le plugin jQuery moreSelectors a le soutien pour nième de type (et bien d'autres sélecteurs). Je suggère soit d'utiliser cela, ou simplement implémenter un simple plugin qui implémente uniquement les sélecteurs précis dont vous avez besoin. Vous devriez pouvoir copier-coller le code à partir de là.

Joyeux hacking!

Questions connexes