5

Pretty simple to do with loop but I'm wondering if there's a way to see if every item in a collection matches a condition without a loop. For example:

if( $('.many-items-of-this-class').hasClass('some-other-class') ) { }

This returns true if any item in the collection returns true. Is there a way to do this sort of operation so it only returns true if all items are true?

Will
  • 5,370
  • 9
  • 35
  • 48

6 Answers6

5

You could cache the set, then run a filter against the set that tests for the other class, and compare the .length properties of both.

var many_items = $('.many-items-of-this-class');

if( many_items.length === many_items.filter('.some-other-class').length ) { }

Or shorter, but arguably more confusing, you could use a .not() filter with .length and a !.

var many_items = $('.many-items-of-this-class');

if( !many_items.not('.some-other-class').length ) { }
user113716
  • 318,772
  • 63
  • 451
  • 440
  • 1
    Touche with filter, brain-fart for a moment. -- EDIT: was thinking `map`, then using the `context`. Never occurred to me filter existed! ;p – Brad Christie Jun 09 '11 at 17:40
1

You could easily write a plugin to extend the each functionality.

(function( $ ){
   $.fn.allMustPassTest = function(test,params) {
       var allPass = true;
       $(this).each(function(){
           if(!test.apply($(this),params)){
               allPass = false;
           }
       });
       return allPass;
   };
})( jQuery );

And use as such:

var allPass = $('.many-items-of-this-class').allMustPassTest(function(){
    return $(this).hasClass('some-other-class');
});
if(allPass){
    //code to execute if all items have .some-other-class

}

Or another way:

var hasClassTest = function(clazz){
    return $(this).hasClass(clazz);
};
if($('.many-items-of-this-class').allMustPassTest(hasClassTest,['some-other-class'])){

}
joekarl
  • 2,118
  • 14
  • 23
0
var $many = $('.many-items-of-this-class');
if ( many.filter('.some-other-class').length == $many.length )
{
  // all items have the class.
}

Perhaps? Other options is to make your own Selector. e.g.

.many-items-of-this-class:and(.some-other-class)

or something.

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
  • @js1568: I'm well aware, but the impression I'm receiving is to make sure that for every `.many-items-of-this-class` item, it **must** also have `.some-other-class` applied to it (in other words, not only items with the two present) – Brad Christie Jun 09 '11 at 17:43
  • Good point, I had more of a hangup with your "and" selector. Maybe it would be better labeled as "isAlways" – js1568 Jun 09 '11 at 17:47
  • 1
    @js1568: Yea, didn't know what to call it, honestly. I think of and and think "both must match", traditional to a logic statement. Oh well, semantics :shrug: – Brad Christie Jun 09 '11 at 17:49
0

What is the goal of checking it that way? If you are performing an operation, then you can just check for both classes at once by chaining the selector:

$('.many-items-of-this-class.some-other-class').each(
    function(index, value) {
        // Do stuff here
    });
Community
  • 1
  • 1
voithos
  • 68,482
  • 12
  • 101
  • 116
  • That doesn't compare (or check) that all items with _class A_ **also** have _class B_ applied. – Brad Christie Jun 09 '11 at 17:41
  • @Brad: It doesn't have to- the jQuery selector retrieves all items which have both class A and B applied. Granted, if you need to check that all _class A_ have _class B_ applied simply for the sake of checking, then yes, this is not the best method. – voithos Jun 09 '11 at 17:45
  • 1
    And I read it as the latter task (Make sure that every items with _class A_ have a _class B_ applied to it (not only items that intersect). – Brad Christie Jun 09 '11 at 17:47
  • @Brad: Ahh, I see. I wasn't thinking of it that deeply. Very good, sir. – voithos Jun 09 '11 at 17:49
0
if( ! $('.many-items-of-this-class').is(':not(.some-other-class)') ) { }

or, if the collection is based on a selector, simply

if( $('.many-items-of-this-class:not(some-other-class)').length == 0 ) { }
Tgr
  • 27,442
  • 12
  • 81
  • 118
0
if( $('.many-items-of-this-class :not(.some-other-class)').size() == 0 ) { 
    // ...
}
Krishna K
  • 1,925
  • 1
  • 14
  • 11