I have tried to do some research already and haven't found anything, but If I've missed the answer, please tell me. Basically I have multiple elements with multiple classes each, but the combinations are unique. I want to select a certain combination of classes, but not other elements that have this elements in combination with others.
I would like to know if this selector exists in jQuery or if there is some other way to accomplish what I am explaining. See the example below:
<div class="a b c"></div>
<div class="a b c d"></div>
<div class="a b c d">/div>
When trying to log only the element with the classes a b c
, I tried using:
$('.a.b.c').each( function() {
console.log($(this));
}
the output is:
[ <div class="a b c">...</div> ,
<div class="a b c d">...</div ,
<div class="a b c d">...</div> ]
I am looking for the output to be:
[ <div class="a b c">...</div> ]
Any guidance is appreciated. Thanks!
You could use the CSS3 :not()
pseudo class to negate the .d
class: (example)
$('.a.b.c:not(.d)').each( function() {
console.log($(this));
});
jQuery also has a .not()
method: (example)
$('.a.b.c').not('.d').each( function() {
console.log($(this));
});
You could also use the attribute selector: (example)
[class="a b c"]
Note that the order always has to be a b c
. Just throwing that out there as an option.
I don't believe you can do this with straight CSS selectors, short of using :not to enumerate every other class you wish to exclude or some real gymnastics with [class=]. However, what you can do is select all elements with the .a.b.c classes, and then filter out any elements that have more than three elements in their class list:
var $abcDivs = $('.a.b.c').filter(function(i, $elem){
return $elem.attr("class").split(' ').length == 3;
})
More generally:
function exactClass(classList) {
return $(classList.join('.')).filter(function(i, $elem){
return $elem.attr("class").split(' ').length == classList.length;
});
}
I've been looking for something similar a while ago, but I was not able to guess what classes I do not need (as they were appended dynamically). So, instead of excluding unwanted classes with not()
, I made this to match elements with only classes I know of.
var classes = ['a','c','b'];
$('.'+classes.join('.')).each( function(){
var cl = $(this).attr('class');
for(var i in classes) {
cl = cl.split(classes[i]).join('');
}
if(cl.replace(/\s+/, '') === ''){
$(this).addClass('blah');
}
});
.blah{
font-size:30px;
color : red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a b c d">Foo</div>
<div class="c b a">Bar</div>
<div class=" a b c">Hello</div>
<div class=" a b">World</div>
JSFiddle . As a method:
function el(c){
var a = [];
$('.'+c.join('.')).each(function(){
var k = $(this).attr('class');
for(var i in c) k=k.split(c[i]).join('');
if(k.replace(/\s+/,'')==='') a.push(this);
});
return a;
}
// usage:
$(el(['a','c','b'])).addClass('blah');