27

I need a jQuery filter/map/each type function to check if ALL elements satisfy a condition:

function areAllValid(inputs){
     return $.someFunction(inputs, function(input) { return input.length > 0; }); 
}

If ALL inputs have length > 0 someFunction should return true. Anything like this in jQuery?

j08691
  • 204,283
  • 31
  • 260
  • 272
parliament
  • 21,544
  • 38
  • 148
  • 238
  • 1
    I don't think jQuery has this. Underscore.js has `$.every()`. It should be simple to implement in jQuery using `$.filter`. – Barmar Mar 18 '13 at 06:20
  • Note, if you can find a way to describe your condition as a selector, then you can check the number of items in the collection `inputs.remove('[value=...]').length == 0` Something along the lines of a "value not empty selector": http://stackoverflow.com/questions/10641258/jquery-select-data-attributes-that-arent-empty – AaronLS Mar 18 '13 at 06:41
  • @Barmar, every() is exactly what I need and coincidentally have underscore as a dependency already :) . thanks – parliament Mar 18 '13 at 20:21

8 Answers8

12

The answer is YES, it has a method grep that can meet your requirement. For example:

inputs= jQuery.grep(inputs, function(input){
return input.length>0;
});
if(inputs.length>0) return true;
return false;

I don't test it, maybe it has tiny issue but should be almost like this.

OQJF
  • 1,350
  • 9
  • 12
  • From docs looks like this would work, but I didn't test either. I ended up going with Underscore.every() as I already had that as a dependency anyways and it fits the fill exactly, returning a boolean. – parliament Mar 18 '13 at 20:20
  • 10
    The problem with this is that if the second of your thousands of elements doesn't meet the requirement, it’ll still check all the following ones instead of breaking the loop and returning `false`. But it works. – bfontaine Sep 18 '14 at 09:01
11

You don't need to use jQuery to do this. You can do this in native JavaScript using Array.prototype.every, which is supported in IE 9+.

function areAllValid(inputs){
     return inputs.every(function(input) { return input.length > 0; }); 
}

If you are using EcmaScript 2015, you can tidy it up further:

var areAllValid = inputs => inputs.every(input => input.length > 0);
James Brierley
  • 4,630
  • 1
  • 20
  • 39
4

This will go through each item, AND the condition with the previous result, so that it will only return true if the condition is true for all items. You could of course replace the condition with a callback function, and do inputs.each( instead of $('input') but you may need to adjust the code a bit depending on whether inputs is a jquery object or not.

var all = true;
  $('input').each( function(index, value) { 
    all = all & ($(value).val().length > 0);
  });
return all;
AaronLS
  • 37,329
  • 20
  • 143
  • 202
0

Not exactly, but it's easy to create one:

    $.eachCondition = function (obj, conditionFunction){
        var trueCount=0;
        var falseCount=0;

        $.each(obj, function (i,v) {
          if (conditionFunction.call(this,i,v)) {
            trueCount++;
          }
          else {
            falseCount++;
          }
          });
          if (falseCount===0) {
            return true;
          }
          if (trueCount===0) {
            return false;
          }
          return undefined;
      };
      $.fn.eachCondition = function (conditionFunction) {
        return $.eachCondition(this, conditionFunction);
      };

Here is working test: http://jsbin.com/iwanof/2/

Saram
  • 1,500
  • 1
  • 18
  • 35
0

I usually use following form to get matches in JQuery

$.map($("[some selector]"), function(e) {
  return ([some matching mechanism]);
}).indexOf(false) == -1;

In your specific case it would look like this:

$.map(inputs, function(e) {
  return (e.length > 0);
}).indexOf(false) == -1;

Hope this saves you some time.

Matas Vaitkevicius
  • 58,075
  • 31
  • 238
  • 265
0

There are some minor optimization issues unaddressed by the existing answers, so I'll throw my hat in the ring with what I believe is the most readable/performant code.

Add a jQuery extension method like this which will short circuit :

/** 
* Determines whether all elements of a sequence satisfy a condition.
* @@param  {function} predicate - A function to test each element for a condition.
* @@return {boolean}  true if every element of the source sequence passes the test in the specified predicate
*/
$.fn.all = function (predicate) {
    $(this).each(function (i, el) {
        if (!predicate.call(this, i, el)) return false;
    });
    // we made it this far, we're good.
    return true;
};

Then call it like this:

var allValid = $("form :input").all(function () {
                   return $(this).valid();
                });
KyleMit
  • 30,350
  • 66
  • 462
  • 664
0

Quick little jQuery :

$(document).ready(function() {
  $('form input').keyUp(function() {
    var allValid = true;
    $.each($('form input'), function(input) { 
      allValid = input.val().length > 0 
    }
    if ( allValid )
      ...
    else
      ...
  })
});
Trip
  • 26,756
  • 46
  • 158
  • 277
0
function areAllValid(inputs){
     return Array.prototype.every.call(inputs, function(input) { return input.length > 0; }); 
}
Alex Hall
  • 34,833
  • 5
  • 57
  • 89