CaffGeek
CaffGeek

Reputation: 22054

jQuery select elements with multiple classes

I need to select all elements that contain multiple classes. The class names don't matter, I just need to select any elements with two or more.

What would the jQuery selector for that look like?

Upvotes: 3

Views: 850

Answers (5)

bfavaretto
bfavaretto

Reputation: 71908

It works just like regular CSS

$('.class1.class2') // will select elements with both classes

Upvotes: 0

Blender
Blender

Reputation: 298066

This should select all elements with more than two classes.

$('*').filter(function() {
  return this.className.trim().split(/\s+/).length > 1;
}).foo('bar');

Upvotes: 8

Brad Christie
Brad Christie

Reputation: 101594

A different understanding leads me to a better solution (my apologies for jumping to a conclusion):

Demo

(function($){
    $.expr[':'].classes = function(o,i,m,s){
        var c = o.className.match(/\s*(.*)\s*/)[0].split(/\s+/).length;

        // Hard [fixed] limit
        // :classes(N)
        if (/^\d+$/.test(m[3])) {
            var n = parseInt(m[3], 10);
            return o.className.split(/\s+/).length == n;
        }

        // Expression:
        // :classes(>N)    :classes(>=N)
        // :classes(>N)    :classes(<=N)
        else if (/^[<>]=?\d+$/.test(m[3])) {
            var e = m[3].match(/^[><]=?/)[0],
                n = m[3].match(/\d+$/)[0];
            switch (e){
                case '<':
                    return c < n;
                case '<=':
                    return c <= n;
                case '>':
                    return c > n;
                case '>=':
                    return c >= n;
            }
        }

        // Range
        // :classes(4-6)
        else if (/^\d+\-\d+$/.test(m[3])) {
            var ln = parseInt(m[3].match(/^(\d+)/)[0], 10),
                hn = parseInt(m[3].match(/(\d+)$/)[0], 10);
            return ln <= c && c <= hn;
        }

        // all else fails
        return false;
    };
})(jQuery);

Updated Added a bit more flexibility with regards to the argument you can supply. Now you have the following options (replacing N & M with numbers):

  • :classes(N)
    Finds elements with exactly N classes
  • :classes(<=N)
    Finds elements with N or fewer classes
  • :classes(<N)
    Finds elements with fewer than N classes
  • :classes(>=N)
    Finds elements with N or more classes
  • :classes(>N)
    Finds elements with more than N classes
  • :classes(N-M)
    Finds elements whose class count falls between N and M

Upvotes: 2

maxedison
maxedison

Reputation: 17553

The following code will first select all elements with a space in the class attribute. We could just do $('*') as Blender suggests, but that's less efficient because it initially selects ALL elements on the page, rather than just those that are viable candidates (i.e., have a space in the class name).

It also takes into consideration those cases where there is just one class, but the class attribute has a space in it (this is done by using jQuery's $.trim() method on the class attribute prior to splitting it). Blender's doesn't solve this kind of situation.

$(function(){
    var div = $('div[class*=" "]').filter(function(){
        var clsArray = $.trim(this.className.split(' ');
        return clsArray.length > 1;
    });
    div.css('background','yellow');
});

Live example: http://jsfiddle.net/udBZy/3/

Upvotes: 1

Elliot Nelson
Elliot Nelson

Reputation: 11557

$('[class*=" "]')

Returns all tags with a space in the class attribute.

Upvotes: 3

Related Questions