jQuery hasClass() - check for more than one class
With:
if(element开发者_JAVA百科.hasClass("class"))
I can check for one class, but is there an easy way to check whether "element" has any of many classes?
I am using:
if(element.hasClass("class") || element.hasClass("class") ... )
Which isn't too bad, but I am thinking of something like:
if(element.hasClass("class", "class2")
Which unfortunately doesn't work.
Is there something like that?
element.is('.class1, .class2')
works, but it's 35% slower than
element.hasClass('class1') || element.hasClass('class2')
See also this jsbench.me test.
How about:
element.is('.class1, .class2')
$.fn.extend({
hasClasses: function (selectors) {
var self = this;
for (var i in selectors) {
if ($(self).hasClass(selectors[i]))
return true;
}
return false;
}
});
$('#element').hasClasses(['class1', 'class2', 'class3']);
This should do it, simple and easy.
filter() is another option
Reduce the set of matched elements to those that match the selector or pass the function's test.
$(selector).filter('.class1, .class2'); //Filter elements: class1 OR class2
$(selector).filter('.class1.class2'); // Filter elements: class1 AND class2
How about this?
if (element.hasClass("class1 class2")
here's an answer that does follow the syntax of
$(element).hasAnyOfClasses("class1","class2","class3")
(function($){
$.fn.hasAnyOfClasses = function(){
for(var i= 0, il=arguments.length; i<il; i++){
if($self.hasClass(arguments[i])) return true;
}
return false;
}
})(jQuery);
it's not the fastest, but its unambiguous and the solution i prefer. bench: http://jsperf.com/hasclasstest/10
What about:
if ($('.class.class2.class3').length) {
//...
}
jQuery
if( ['class', 'class2'].some(c => [...element[0].classList].includes(c)) )
Vanilla JS
if( ['class', 'class2'].some(c => [...element.classList].includes(c)) )
What about this,
$.fn.extend({
hasClasses: function( selector ) {
var classNamesRegex = new RegExp("( " + selector.replace(/ +/g,"").replace(/,/g, " | ") + " )"),
rclass = /[\n\t\r]/g,
i = 0,
l = this.length;
for ( ; i < l; i++ ) {
if ( this[i].nodeType === 1 && classNamesRegex.test((" " + this[i].className + " ").replace(rclass, " "))) {
return true;
}
}
return false;
}
});
Easy to use,
if ( $("selector").hasClasses("class1, class2, class3") ) {
//Yes It does
}
And It seems to be faster, http://jsperf.com/hasclasstest/7
This is quite old, but hear me out on this one.
$.fn.extend({
hasClasses: function (selectors) {
// Setup
const _id = $(this).attr('id'); // Preserve existing id
const uuid = generateUUID(); // Create new id for query
$(this).attr('id', uuid); // Apply new id to element
// Query to find if element has any of the classes
const res = selectors.some(cls => !!$(`${uuid}.${cls}`).length);
// Rollback on id
if (!_id) $(this).removeAttr("id"); // No Id to begin with
else $(this).attr('id', _id); // Preserve old id
// Done
return res;
}
})
Instead of trying to find a match between one of the classes in selectors
and one of the element's classes we simply apply a temporary id
(uuid) to the element and query to find if there exists some element with that temporary id
and any of the classes listed in selectors
.
This inspired by Kalel Wade's and Simon Arnold's solution but with a minor improvement to performance (benchmarked on jsbench.me).
Note
JSBENCH doesn't allow saving over a limit of a certain amount of characters or words. I had some trouble with the async fetching of random words, so you can get random words manually and use the bench that way.
EDIT:
I just noticed that for my implementation of this I am relying on the id
with async calls. I might cause an issue if I need to query the element by id the same time that hasClasses
changes the id
.
To circumvent this we can just add a unique uuid
attribute (literally just the uuid
).
Here is the correction:
$.fn.extend({
hasClasses: function (selectors) {
// Setup
const uuid = generateUUID(); // Create new uuid to query later
$(this).attr(uuid, ""); // Apply uuid to element for query
// Query to find if element has any of the classes
const res = selectors.some(cls => !!$(`[${uuid}].${cls}`).length);
// Remove the uuid attribute
$(this).removeAttr(uuid);
// Done
return res;
}
})
We could still use an the elements' id
if it has one instead of adding an attribute
.
I'm not sure if querying id
s is faster or not. I referenced this, but by the looks of it there isn't much of a hit with modern browsers. Could still implement using the id
if it exists instead of an attribute
.
use default js match() function:
if( element.attr('class') !== undefined && element.attr('class').match(/class1|class2|class3|class4|class5/) ) {
console.log("match");
}
to use variables in regexp, use this:
var reg = new RegExp(variable, 'g');
$(this).match(reg);
by the way, this is the fastest way: http://jsperf.com/hasclass-vs-is-stackoverflow/22
You can do this way:
if($(selector).filter('.class1, .class2').length){
// Or logic
}
if($(selector).filter('.class1.class2').length){
// And logic
}
This worked for me:
$('.class1[class~="class2"]').append('something');
Works for me:
if ( $("element").hasClass( "class1") || $("element").hasClass("class2") ) {
//do something here
}
精彩评论