Supposons que j'ai ce balisage
<h3 id="first">First</h3>
<p>Hi</p>
<p>Hello</p>
<h3 id="second">Second</h3>
<p>Bye</p>
<p>Goodbye</p>
Comment puis-je vérifier par programme si un élément, tel que l'un des p
s, est après le premier h3
et avant le second h3
avec jQuery?
J'essaie de faire quelque chose comme ça:
$(p).each(function(){
if($(this).isAfter("#first") && $(this).isBefore("#second")) {
// do stuff
}
});
La solution de Rocket fonctionne bien si sel
est un vrai sélecteur. Si vous transmettez un objet jQuery, cela ne fonctionnera pas.
Si vous voulez un plugin qui fonctionne avec les sélecteurs et les objets jQuery, utilisez plutôt ma version légèrement modifiée:
(function($) {
$.fn.isAfter = function(sel){
return this.prevAll().filter(sel).length !== 0;
};
$.fn.isBefore= function(sel){
return this.nextAll().filter(sel).length !== 0;
};
})(jQuery);
Félicitations à Rocket pour la solution originale.
Pour voir si un élément est après l'autre, vous pouvez utiliser prev()
ou prevAll()
pour obtenir le ou les éléments précédents et voir s'ils correspondent.
Et pour voir si un élément est avant un autre, vous pouvez utiliser next()
ou nextAll()
pour obtenir le ou les prochains éléments et voir s'ils correspondent.
$.fn.isAfter = function(sel){
return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
return this.nextAll(sel).length !== 0;
}
Vous pouvez utiliser la fonction index()
:
$('p').each(function(){
var index = $(this).index();
if(index > $("#first").index() && index < $("#second").index()) {
// do stuff
}
});
J'ai implémenté une fonction générale isAfter
, qui considère la profondeur et l'arborescence DOM et peut déterminer correctement si a
est après b
même s'ils se trouvent dans 2 sous-arbres différents:
<div>
<div>
<p class="first">I come first</p>
</div>
</div>
<div>
<div>
<p class="second">I come second</p>
</div>
</div>
vous pouvez le trouver dans mon dépôt GitHub . J'apprécierais vos commentaires sur le code
Voici un violon
$('p').each(function() {
previousH3 = $(this).prevAll('h3');
nextH3 = $(this).nextAll('h3');
if (previousH3.length > 0 && nextH3.length > 0) {
$(this).css('color', 'red')
}
});
La réponse:
$.fn.isAfter = function(sel){
return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
return this.nextAll(sel).length !== 0;
}
Sélectionne tous les éléments précédents ou les éléments suivants quel que soit le sélecteur (sel). J'ai donc apporté les modifications suivantes pour sélectionner les éléments en fonction de la classe:
$.fn.isAfter = function(sel){
sel = "." + sel.attr("class").replace(/ /g, ".");
return this.prevAll(sel).length !== 0;
}
$.fn.isBefore= function(sel){
sel = "." + sel.attr("class").replace(/ /g, ".");
return this.nextAll(sel).length !== 0;
}
Gardant à l'esprit la réponse de Rocket, je préfère utiliser l'approche .index()
comme suit:
$.fn.isAfter = function(sel){
return $(this).index() > $(sel).index();
};
$.fn.isBefore= function(sel){
return $(this).index() < $(sel).index();
};
Cela semble plus clair pour la lecture/compréhension et fonctionne parfaitement dans la sélection des lignes.
Les réponses précédentes fonctionnent bien SI les éléments en question sont des frères et soeurs (comme ils le sont dans la question initiale), mais une solution plus générale prendrait en compte le scénario suivant:
<div id="top">
<div>
<div>
<h3 id="first">First</h3>
<p>Hi</p>
<p>Hello</p>
</div>
</div>
<div>
<h3 id="second">Second</h3>
<p>Bye</p>
<p>Goodbye</p>
</div>
</div>
Une solution plus générale serait:
$.extend($.fn, {
isBefore: function(sel, context) {
// Get all element within the context.
var all = $(context || document).find("*");
return all.index(this[0]) < all.index($(sel));
},
isAfter: function(sel, context) {
return !this.isBefore(sel, context);
}
});
Où "contexte" est un paramètre facultatif qui limite simplement la zone de recherche de jQuery afin d'améliorer les performances. Je n'ai effectué aucun test, mais "context" n'est probablement pas nécessaire car $ ("*") semble s'exécuter qualitativement rapidement. Notez également que index () retournera -1 si l'un des éléments n'est pas dans le contexte.
$("#first").isBefore("#second");
// Gives the same result as
$("#first").isBefore("#second", "#top");
Bien entendu, tout cela suppose que par "avant" et "après", vous entendez leur ordre dans le modèle de document. Si vous êtes préoccupé par leurs positions relatives sur l’affichage, vous voudrez peut-être examiner les coordonnées d’affichage des éléments par rapport au document.