737

Is there a way in jQuery to loop through or assign to an array all of the classes that are assigned to an element?

ex.

<div class="Lorem ipsum dolor_spec sit amet">Hello World!</div>

I will be looking for a "special" class as in "dolor_spec" above. I know that I could use hasClass() but the actual class name may not necessarily be known at the time.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Buggabill
  • 13,726
  • 4
  • 42
  • 47
  • If you don't know the class name at the time, preventing you from using hasClass(), how do you intend to know which one in the array it is? – doomspork Aug 04 '09 at 13:05
  • I am designing a form where I am doing some preliminary validation with jQuery. I am appending the id of the input element to the class list of the error div if one is generated. I am then making it possible to click on the error div to focus the errant input element. This script is going to be used for more than one form. I therefore do not want to hard-code the ids in the script. – Buggabill Aug 04 '09 at 13:10
  • 1
    Right, I understand why you wouldn't want to hardcode. But if you take a moment to look over redsquare's example you'll see you've got to hardcode 'someClass' into the if block. Either way you could achieve this with a variable. – doomspork Aug 04 '09 at 13:31
  • Rather than using the class attribute, you could have an error list variable inside your namespace which contained DOM references to the elements with errors. Thus eliminating the need to pull the attribute list each time, iterate it, find the DOM element, and focus it. – doomspork Aug 04 '09 at 13:33

16 Answers16

787

You can use document.getElementById('divId').className.split(/\s+/); to get you an array of class names.

Then you can iterate and find the one you want.

var classList = document.getElementById('divId').className.split(/\s+/);
for (var i = 0; i < classList.length; i++) {
    if (classList[i] === 'someClass') {
        //do something
    }
}

jQuery does not really help you here...

var classList = $('#divId').attr('class').split(/\s+/);
$.each(classList, function(index, item) {
    if (item === 'someClass') {
        //do something
    }
});

You can use

if ($('#divId').hasClass('someClass')) {
    //do something
}
Community
  • 1
  • 1
redsquare
  • 78,161
  • 20
  • 151
  • 159
337

Why has no one simply listed.

$(element).attr("class").split(/\s+/);

EDIT: Split on /\s+/ instead of ' ' to fix @MarkAmery's objection. (Thanks @YashaOlatoto.)

Bob Stein
  • 16,271
  • 10
  • 88
  • 101
Dreamr OKelly
  • 3,544
  • 1
  • 14
  • 3
  • 7
    That is part of the accepted answer... I needed all the classes that were applied to an element. – Buggabill Apr 17 '12 at 12:26
  • Haha, true! I wanted just this. It returns a string of classes separated by spaces, so maybe if you want to pick up one of them you can split the string by space and get an array to pick up a class from – Rahul Dole Aug 06 '13 at 13:18
  • 56
    Because it's wrong! Classes can be separated by any kind of whitespace (e.g. you can wrap a long class attribute in your HTML onto multiple lines), but this answer fails to account for that. Try pasting `$('
    ').attr("class").split(' ')` into your browser console (there's a tab character in there); you'll get `["foo", "bar baz"]` instead of the correct class list of `["foo", "bar", "baz"]`.
    – Mark Amery Dec 17 '14 at 23:27
  • 2
    @MarkAmery is right. If you would have a `class="foo bar"`, you would end up with an array with empty string elements. – Jacob van Lingen Sep 22 '15 at 14:03
  • @JacobvanLingen Is it possible to have lots of spaces between classes in modern browsers? – Philip Feb 25 '16 at 12:37
169

On supporting browsers, you can use DOM elements' classList property.

$(element)[0].classList

It is an array-like object listing all of the classes the element has.

If you need to support old browser versions that don't support the classList property, the linked MDN page also includes a shim for it - although even the shim won't work on Internet Explorer versions below IE 8.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Pehmolelu
  • 3,534
  • 2
  • 26
  • 31
  • 1
    @Marco Sulla: this has indeed a shortcoming other than support on obsolete software. `.classList` is not a true array, and such methods as `.indexOf(⋯)` don’t work on it. It is only an “array-like object”, whereas `.className.split(/\s+/).indexOf(⋯)` (from the accepted answer) works. – Incnis Mrsi Jan 28 '20 at 13:20
  • 3
    You can easily convert any iterable to an `Array` using `[...iterable]` or `Array.from(iterable)` – Marco Sulla Jan 28 '20 at 16:57
142

Here is a jQuery plugin which will return an array of all the classes the matched element(s) have

;!(function ($) {
    $.fn.classes = function (callback) {
        var classes = [];
        $.each(this, function (i, v) {
            var splitClassName = v.className.split(/\s+/);
            for (var j = 0; j < splitClassName.length; j++) {
                var className = splitClassName[j];
                if (-1 === classes.indexOf(className)) {
                    classes.push(className);
                }
            }
        });
        if ('function' === typeof callback) {
            for (var i in classes) {
                callback(classes[i]);
            }
        }
        return classes;
    };
})(jQuery);

Use it like

$('div').classes();

In your case returns

["Lorem", "ipsum", "dolor_spec", "sit", "amet"]

You can also pass a function to the method to be called on each class

$('div').classes(
    function(c) {
        // do something with each class
    }
);

Here is a jsFiddle I set up to demonstrate and test http://jsfiddle.net/GD8Qn/8/

Minified Javascript

;!function(e){e.fn.classes=function(t){var n=[];e.each(this,function(e,t){var r=t.className.split(/\s+/);for(var i in r){var s=r[i];if(-1===n.indexOf(s)){n.push(s)}}});if("function"===typeof t){for(var r in n){t(n[r])}}return n}}(jQuery);
Haroldo_OK
  • 6,612
  • 3
  • 43
  • 80
Will
  • 7,225
  • 2
  • 23
  • 14
107

You should try this one:

$("selector").prop("classList")

It returns a list of all current classes of the element.

P.Petkov
  • 1,569
  • 1
  • 12
  • 20
  • 6
    Well I don't know. But this is the proper way to get property from DOM element. And "classList" is such property that gives you an array of css classes applied to the element. – P.Petkov May 09 '16 at 21:14
  • @RozzA Maybe it wasn't available back then? But I'd say this is the most appropriate method as of now, unless you don't use jQuery, where a simple `.classList` is the solution - you just need to pay attention to inconsistencies and/or missing browser support.. – Dennis98 Sep 01 '16 at 14:58
  • @Dennis98 good call, I forget sometimes how rapidly new features have come out recently. I've also done plain js `.classList` it works quite well in modern browsers – RozzA Sep 05 '16 at 07:01
  • 3
    Note that the `classList` property doesn't work on IE 10/11 for SVG elements (though it works for HTML elements). See https://developer.mozilla.org/en-US/docs/Web/API/Element/classList – Métoule Jul 19 '17 at 09:51
  • @Métoule also .prop('classList') may [not work in IE9](https://caniuse.com/#feat=classlist) for HTML elements. – Bob Stein Jan 27 '18 at 22:19
17
var classList = $(element).attr('class').split(/\s+/);
$(classList).each(function(index){

     //do something

});
Fiona - myaccessible.website
  • 14,481
  • 16
  • 82
  • 117
Carlisle
  • 171
  • 1
  • 2
8
$('div').attr('class').split(' ').each(function(cls){ console.log(cls);})
alexche8
  • 1,270
  • 3
  • 19
  • 26
  • 2
    This is a horrible abuse of `.map`; use `.each` if you don't need `.map`'s return value. Splitting on spaces rather than any whitespace is also broken - see my comment on http://stackoverflow.com/a/10159062/1709587. Even if none of these points were true, this adds nothing new to the page. -1! – Mark Amery Dec 17 '14 at 23:54
7

Update:

As @Ryan Leonard pointed out correctly, my answer doesn't really fix the point I made my self... You need to both trim and remove double spaces with (for example) string.replace(/ +/g, " ").. Or you could split the el.className and then remove empty values with (for example) arr.filter(Boolean).

const classes = element.className.split(' ').filter(Boolean);

or more modern

const classes = element.classList;

Old:

With all the given answers, you should never forget to user .trim() (or $.trim())

Because classes gets added and removed, it can happen that there are multiple spaces between class string.. e.g. 'class1 class2       class3'..

This would turn into ['class1', 'class2','','','', 'class3']..

When you use trim, all multiple spaces get removed..

DutchKevv
  • 1,659
  • 2
  • 22
  • 39
  • 2
    This is incorrect (and not an answer). Both String.trim() and $.trim() remove all leading and trailing whitespace, and leave the rest of the string alone. https://jsconsole.com/?%22%20%20a%20%20b%20%20%22.trim() – Ryan Leonard Oct 24 '16 at 16:10
  • Did you even had a look at the answers? All the native JS solutions did not check for leading and trailing whitespaces, thus giving a faulty class list, as there would be empty classes in the array.. jQuery does the same internally with trim when it reads the classes – DutchKevv Oct 24 '16 at 18:20
  • 2
    I did see the other answers, and agree that whitespace should be removed between class names. I was pointing out that a) this should be a comment on the other solutions, as it isn't a complete answer b) .trim() does *not* remove multiple spaces to achieve what you need. – Ryan Leonard Oct 24 '16 at 19:01
  • 1
    You are totally correct indeed... Sorry for my to-quick comment.. It doesn't remove the spaces in between... s.trim().replace(/ +/g, " ") or something would be needed to remove all multiple spaces in between classes.. Next to that, el.classList is almost widely supported, fixing it all I suppose.. – DutchKevv Nov 19 '17 at 00:42
  • 1
    no problem at all. Happily upvoted, `.classList` is a much cleaner approach! – Ryan Leonard Nov 25 '17 at 04:27
3

Might this can help you too. I have used this function to get classes of childern element..

function getClickClicked(){
    var clickedElement=null;
    var classes = null;<--- this is array
    ELEMENT.on("click",function(e){//<-- where element can div,p span, or any id also a class
        clickedElement = $(e.target);
        classes = clickedElement.attr("class").split(" ");
        for(var i = 0; i<classes.length;i++){
            console.log(classes[i]);
        }
        e.preventDefault();
    });
}

In your case you want doler_ipsum class u can do like this now calsses[2];.

Phoenix
  • 467
  • 1
  • 11
  • 23
3

For getting the list of classes applied to element we can use

$('#elementID').prop('classList')

For adding or removing any classes we can follow as below.

$('#elementID').prop('classList').add('yourClassName')
$('#elementID').prop('classList').remove('yourClassName')

And for simply checking if the class is present or not we can use hasClass

Mantra
  • 316
  • 3
  • 16
  • does not answer the question – Aurovrata Oct 25 '21 at 15:06
  • @Aurovrata $('#elementID').prop('classList') was for getting the List of classes of the element and further, .add and .remove methods for doing changes to the list of classes. Isn't the question asking how to get class list in JQuery? – Mantra Oct 29 '21 at 10:46
  • Indeed, the question specifically asks how to get the classlist so as to loop through it, nothing mentioned about adding or removing classes. Furthermore, you answer fails to explain what it does. Please consider improving it. – Aurovrata Nov 02 '21 at 07:29
  • @Aurovrata: Thanks, I have improved the answer, please feel free to improve it further as per the requirement. – Mantra Dec 29 '21 at 06:56
2

Try This. This will get you the names of all the classes from all the elements of document.

$(document).ready(function() {
var currentHtml="";
$('*').each(function() {
    if ($(this).hasClass('') === false) {
        var class_name = $(this).attr('class');
        if (class_name.match(/\s/g)){
            var newClasses= class_name.split(' ');
            for (var i = 0; i <= newClasses.length - 1; i++) {
                if (currentHtml.indexOf(newClasses[i]) <0) {
                    currentHtml += "."+newClasses[i]+"<br>{<br><br>}<br>"
                }
            }
        }
        else
        {
            if (currentHtml.indexOf(class_name) <0) {
                currentHtml += "."+class_name+"<br>{<br><br>}<br>"
            }
        }
    }
    else
    {
        console.log("none");
    }
});
$("#Test").html(currentHtml);

});

Here is the working example: https://jsfiddle.net/raju_sumit/2xu1ujoy/3/

Sumit Raju
  • 175
  • 5
2

Thanks for this - I was having a similar issue, as I'm trying to programatically relate objects will hierarchical class names, even though those names might not necessarily be known to my script.

In my script, I want an <a> tag to turn help text on/off by giving the <a> tag [some_class] plus the class of toggle, and then giving it's help text the class of [some_class]_toggle. This code is successfully finding the related elements using jQuery:

$("a.toggle").toggle(function(){toggleHelp($(this), false);}, function(){toggleHelp($(this), true);});

function toggleHelp(obj, mode){
    var classList = obj.attr('class').split(/\s+/);
    $.each( classList, function(index, item){
    if (item.indexOf("_toggle") > 0) {
       var targetClass = "." + item.replace("_toggle", "");
       if(mode===false){$(targetClass).removeClass("off");}
       else{$(targetClass).addClass("off");}
    }
    });
} 
Alan L.
  • 370
  • 3
  • 6
1

I had a similar issue, for an element of type image. I needed to check whether the element was of a certain class. First I tried with:

$('<img>').hasClass("nameOfMyClass"); 

but I got a nice "this function is not available for this element".

Then I inspected my element on the DOM explorer and I saw a very nice attribute that I could use: className. It contained the names of all the classes of my element separated by blank spaces.

$('img').className // it contains "class1 class2 class3"

Once you get this, just split the string as usual.

In my case this worked:

var listOfClassesOfMyElement= $('img').className.split(" ");

I am assuming this would work with other kinds of elements (besides img).

Hope it helps.

eva
  • 59
  • 3
-1

javascript provides a classList attribute for a node element in dom. Simply using

  element.classList

will return a object of form

  DOMTokenList {0: "class1", 1: "class2", 2: "class3", length: 3, item: function, contains: function, add: function, remove: function…}

The object has functions like contains, add, remove which you can use

Anuj J
  • 123
  • 2
  • 7
-3

The question is what Jquery is designed to do.

$('.dolor_spec').each(function(){ //do stuff

And why has no one given .find() as an answer?

$('div').find('.dolor_spec').each(function(){
  ..
});

There is also classList for non-IE browsers:

if element.classList.contains("dolor_spec") {  //do stuff
john k
  • 6,268
  • 4
  • 55
  • 59
  • 3
    -​1; among other problems, your first two code snippets are unrelated to the question asked and your final snippet is a syntax error. – Mark Amery Dec 17 '14 at 23:58
-3

A bit late, but using the extend() function lets you call "hasClass()" on any element, e.g.:
var hasClass = $('#divId').hasClass('someClass');

(function($) {
$.extend({
    hasClass: new function(className) {
        var classAttr = $J(this).attr('class');
        if (classAttr != null && classAttr != undefined) {
            var classList = classAttr.split(/\s+/);
            for(var ix = 0, len = classList.length;ix < len;ix++) {
                if (className === classList[ix]) {
                    return true;
                }
            }
        }
        return false;
    }
}); })(jQuery);
gesellix
  • 3,024
  • 28
  • 31