Quelle serait la meilleure façon d'obtenir toutes les divs qui ont une classe qui commence par une input
? En d'autres termes, a
et b
devraient être retournés à partir de ce qui est ci-dessous, mais pas c
.
<div id="a" class="input1 foo"></div> <div id="b" class="foo input2"></div> <div id="c" class="xinput3 foo"></div>
La façon ostensible, qui a été étonnamment acceptée ici , est de faire $("div[class^='input']");
Mais bien sûr, ça manque b
. Et bien sûr $("div[class*='input']");
Donnera un faux positif sur c
.
Le meilleur que j'ai pu trouver était cette monstruosité
function getAllInputDivs() { return $("div").filter(function (i, currentDiv) { return $.grep($(currentDiv).attr("class").split(" "), function (val) { return val.substr(0, "input".length) === "input"; }).length > 0; }); }
Y at-il un moyen plus propre? Voici un violon de travail de ce qui précède
Vous pouvez créer votre propre expression dans jQuery
$.expr[':'].hasClassStartingWithInput = function(obj){ return (/\binput/).test(obj.className); };
Et vous pouvez récupérer ces div avec
$('div:hasClassStartingWithInput');
Un exemple JsFiddle: http://jsfiddle.net/7zFD6/
Edit: vous pouvez également utiliser un paramètre (sans coder en dur le nom de la classe dans l'identifiant de la fonction) de cette manière
$.expr[':'].hasClassStartingWith = function(el, i, selector) { var re = new RegExp("\\b" + selector[3]); return re.test(el.className); }
Nouvel exemple sur http://jsfiddle.net/pMepk/1/
Voici un moyen …
function getAllInputDivs() { return $("div").filter(function () { return /(?:^|\s)input/.test(this.className); }); }
Ou rendez-vous plus polyvalent …
function classStartsWith( tag, s ) { var re = new RegExp('(?:^|\\s)' + s); return $(tag || '*').filter(function () { return re.test(this.className); }); }
Ou prenez l'approche indexOf
si vous n'aimez pas regex …
function classStartsWith( tag, s ) { return $(tag || '*').filter(function () { return this.className.indexOf(s)===0 || this.className.indexOf(' ' + s)>-1; }); }
Bien que vous devriez savoir qu'il ne teste pas les caractères de l'onglet, seulement les caractères de l'espace, donc il pourrait échouer si un onglet était utilisé à la place d'un espace.
En revenant aux versions regex, vous pouvez améliorer l'efficacité en ajoutant la chaîne recherchée au sélecteur.
Ensuite, il teste seulement un sous-ensemble de divs.
function getAllInputDivs() { return $("div[class*='input']").filter(function () { return /(?:^|\s)input/.test(this.className); }); }
Avec le .filter()
appliqué à ces divs que vous connaissez, vous avez quelque chose dans la classe, la performance s'améliorera.
Ou la version polyvalente ressemblerait à ceci:
function classStartsWith( tag, s ) { var re = new RegExp('(?:^|\\s)' + s); return $((tag || '*') + '[class*="' + s + '"]').filter(function () { return re.test(this.className); }); }
C'est ma solution pour le problème:
(function($) { $.fn.hasClassStartsWith = function(klass) { var _return = []; for(var i = 0; i < this.length; i++){ if((' ' + $(this[i]).attr('class')).indexOf(klass) != -1) _return.push(this[i]); } return _return; } })(jQuery);
Utilisez-le comme suit:
var divs = $('div').hasClassStartsWith("my_class_prefix");
Cela fonctionne aussi pour le cas où quelqu'un crée une classe avec un point au milieu.