JQuery – a classe qui commence avec

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.