Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at NCDevCon 2011 (Raleigh, NC) with: Jaana Gilbert and Brenda Priest

The Beauty Of The jQuery Each() Method

By Ben Nadel on

The jQuery library provides a method, Each(), which will loop through each element of the target jQuery object:

  • // Loop over each hottie.
  • $( "#girls a.hottie" ).each(
  •  
  • // For each hottie, run this code. The "indIndex" is the
  • // loop iteration index on the current element.
  • function( intIndex ){
  •  
  • // Bind the onclick event to simply alert the
  • // iteration index value.
  • $( this ).bind (
  • "click",
  • function(){
  • alert( "Hottie index: " + intIndex );
  • }
  • );
  •  
  • }
  •  
  • );

While there is nothing revolutionary going on here (although the "Bind" method is freakin' sweet-ass-sweet unto itself), the beauty of the Each() method is that it creates a separate function scope for each loop iteration. For anyone who has tried to do a standard FOR-Loop in which each iteration tries to dynamically set some object value, you probably have run into situation where all values post-loop are the same. This has to do with when the variable is being bound.

By creating a separate function scope for each loop iteration, you basically eliminate all the "unexpected" variable binding behavior. Sweet! It seems every time I step back and look at what jQuery is doing for me, it's simply stripping away more and more headache time.

Tweet This Provocative thoughts by @BenNadel - The Beauty Of The jQuery Each() Method Thanks my man — you rock the party that rocks the body!



Reader Comments

Yes indeed, each() rules. If you get excited about this kind of stuff, you may want to take a look at Ruby on Rails if you haven't already done so. You'll get excited about a lot of things. For one, the Ruby language alone has some very powerful features that are quite unique and that allow for very elegant code. I really like ColdFusion, but I think RoR brings a lot to the table and it costs nothing (OK, I know, our time is valuable) to give it a try and see something different. And if you decide to do so, please be sure to let us all know what you thought!

Thomas,

Thanks for the heads up. To date, I have not looked into Ruby on Rails. However, I have heard a lot of good things about it. When I start to look into it, I am sure I will have a lot to say ;)

Wow. Thank you. I'm fairly new to js/jquery and this really helps me with logically thinking/looking at what I need. Plus it really helps me in a current project.

Oh my, you just saved me what I'm sure would have been a few more hours of searching. The each() function is great but I couldn't find any documentation anywhere regarding getting an index from it until here. So thank you. I like jQuery but IE doesn't play nice.

hey

I want to use each() to manipulate all the checkboxes that match.

my head and the wall are both bloody now, i seem to need to use this.checked i.o. $(this)
typeof($(this)) yields 'object object'

anyone care to enlighten me?

$('.myclass').each(
function ( intindex ){
this.checked =chkbox.checked ;
}
);

does work. (thanks alot for that btw). Just trying to understand why it works, lol.

how does my function know what this is? i have lots of user myths building up in my head....

thanks again

@greg,

When jQuery executes the function that you pass to the each() method, it executes it in the context of given object such that "this" is explicitly pointed to the given object. This is what the call() and apply() methods do in Javascript.

Most likely, they do something like this:

for (i = 0 ; i < this.size() ; i++){
. . . . yourCallback.call( this[ i ], i, this[ i ] );
}

The first argument of the call() method is the this/context of the executing function (yourCallback). Any subsequent arguments (i, this[ i ]) are the actual arguments passed to the method.

@ABCD

That would require that us programmers actually talk to girls, which (*adjusts glasses*) is simply ridiculous.

In seriousness, thanks for the write-up, Ben.

@Lewis,

I think the problem is that you are calling each() on your P tags. What you want to do is get the collection of P tag and then get the text() on the entire set.

var text = $( ".... p" ).text();

This will return the text aggregation of all the paragraphs found in the set. This way, you don't have to loop over the 2 paragraphs, which is why you are getting two read more links.

Wow! now i understand "each()"!! i've had read a lot about it, but using "common names"....but it was hard to understand.

With this example: "girls.hottie", was so really easy to understand hehehehe

thanks!

@A GEEK GIRL: hehehe

Hi, quick question: I'm using each() and I'd like to use the index as part of a selector, as in

$(".input").each(function (i) {

inputVal = $(this).getValue();

if (inputVal==null||inputVal =="") {

$(this).addClass('alertInputEmpty');

$('.fieldAlert').get(i).html('Please enter a valid path');

...

I can't for the life of me figure out how to get that last line to work. Any help would be greatly appreciated!

Thanks!

Dude, the choice of variable names is quite sexist, I hope your lady clients don't ever see this, as many will be quite put off (as I am)

@ A Lady

If anything it's an honor to your gender. It's a way of saying we worship you. I understand that since you're a woman you can't understand this, but it doesn't make it not true.

Hey, Ben! Thanks for the great article and don't worry about what "A Lady" says about it being sexist because it's not. Sometimes it's good to make the examples more fun as long as the content isn't blatantly offensive (some examples: swearing, referencing certain body parts, or adult images)..... This way your readers don't get into trouble at work when they look for a simple code example or want to check their syntax.

(That's just my humble opinion.)

Did you have to call:
$( this ).bind (
"click",
function(){
alert( "Hottie index: " + intIndex );
}
);

Couldn't you just call:
$( this ).click (
function(){
alert( "Hottie index: " + intIndex );
}
);

@Amy,

I appreciate your feedback :) Exactly, I'm just trying to keep the learning fun.

@Kristopher,

Yes, you can certainly use the event-name short hands; in fact, that's what I often use these days. If you want to define the event handler with additional data, however, you still need to use the bind method:

$( .. ).bind( "click", eventData, function(){} );

Other than that, though, there is zero downside to the short hand notations.

It was very useful but I wonder what to do in case you are not interested in all elements, but for example all minus 5 last?

@Marta,

You can start to limit the collection using the various selectors and filtering methods. For example, if you have 10 items in the child node collection, you could use the pseudo-selector :lt()

$( "span:lt(5)" )

My problem is that I work with an xml document which is weather data for a specific place.

<time period='2'> </ time>
<time period='3'> </ time>

<time period='0'> </ time>
<time period='1'> </ time>
<time period='2'> </ time>
<time period='3'> </ time>

<time period='0'> </ time>
<time period='1'> </ time>
<time period='2'> </ time>
<time period='3'> </ time>

Each <time/> equivalent to 6 hours of each day. As time 0-3 = 24h. When I take home my xml document, there are more days than I would like to in the form of </ time> nodes(3-1/day), and each xml document does not begin with period = 0, in the event period 0 has expired, there's just time = 1 and so on. So the solution you gave me does not help as much as all the combinations between 20 and 16 may be possible. I have now sat and figured the problem for several days, would need a kick in the butt to move forward in my project.
There is an example of the xml document I work with so it is perhaps easier to understand what I'm about woolly.
http://www.yr.no/sted/Sverige/Kalmar/Borgholm/forecast.xml

Excuse me for my English.

Best Regards Marta

@Marta,

Are you saying that the XML you are working with has bad data? I apologize, but I am not completely sure what you are asking. Are you trying to do this with jQuery? Or are you parsing the XML with some other language?

I'm using each to do some validation on a form. My each loop returns the correct info on my test box, but "this" is bound to the entire array on my production box.

Here is my code:

function validateForm () {
var validForm = true;
$(".required").each(
function(){
if ($(this).val().length == 0) {
validForm = false;
$(this).css("background-color","#ff0000");
}
}
)
return validForm;
}

If I set a breakpoint and look at $(this) in the middle function, it will return an array not just a single element.

Any thoughts?

Thanks in advanced!

@Eric,

That is really odd. I cannot think of what would be causing that. Are you sure you have the same version of jQuery on development and production? Of course, core jQuery shouldn't be messing that up in any version, unless it was altered.

Is it possible that you have a plugin on the production server that is not on DEV that is perhaps overriding the core each() method?

@Ben Nadel, Thanks for the quick reply. The jquery version caught my eye and I started looking at other modules I have on this page (I am using the DotNetNuke Content Management System.) I saw a reference to scriptaculous for a photo gallery module. So I moved my code to another page and VIOLA!

Free $.each Tip :-)

I was about to write about a problem I had with a fast outer javascript loop with an $.ajax call in the middle and the inherent problem that comes with that. You have 1 ajax call that only updates the last item in the javascript list.

BUT! If you have your outer javascript list in an array, you can use the $.each to give the inner $.ajax time to finish:

var some_array = {
'abc': '123',
'def': '456'
};

Instead of:
for (i=0;i<some_array.length;i++) {
$.ajax({
... whatever
});
}

You CAN have:

$.each(some_arrray, function (key,value) {
$.ajax({
... whatever
});
});

Solved my problem!!!

@Robbie,

Sounds good. The each() method really solves a lot of problems. Sometimes, I think I overuse it, and I actually drop back down into the for() loop when I need to break out of a the loop. But, if I don't need to break, it's really really nice.

Hi I have a question..

I'm working with the following set up:

<form>
<div>
<input>
<input>
<input>
<input>
...
</div>
<div>
<input>
<input>
<input>
<input>
...
</div>
<div>
<input>
<input>
<input>
<input>
...
</div>
</form>

Now the case is the following.
Everytime someone changes any of the input fields in a div, a loop must be activated to check if all input fields in that particular div are not-empty. This is what I have so far:

$("#groepA :input").change( function() {
$(this).each( function() {
if ( $(this).val() != '' ) {$("#expandA").addClass("succes"); }
else { $("#expandA").removeClass("succes"); }
});
});

It's just doing exactly what it needs to do... Whenever any of the inputfields change.. only if you change the first or last field something happens ( the change of class )..

I just can't figure out what the problem is.. ehm... help? anyone?

Oh and by the way.. the following didn't work either..

$("#groepA :input").each( function() {
$(this).change( function() {
if ( $(this).val() != '' ) {$("#expandA").addClass("succes"); }
else { $("#expandA").removeClass("succes"); }
});
});

@Jorik,

I am not sure you are actually looping over anything. Although your initial collection might contain multiple INPUT elements, when your change() event fires, the THIS value at the time will be pointing to the actual INPUT that triggered the change ... I don't think it will be the original collection.

As such, $(this).each() within the change event handler is simply looping over the single input that triggered the event.

I suppose the second piece of script I just posted is looping through every input element in '#groepA', but it is just not doing the right thing.
The second script just checks if a input element has been changed, if yes, check the value, if it is empty, remove class, otherwise, add class.

That's where my problem is I believe. Because I need to check every input element in '#groepA' before adding/removing the class...

@Jorik,

I am not sure I understand what you are trying to do. Every time someone changes a given input, you need to check every other input in order to see if a message can be removed?

The set up:

< form >
< div id="groepA" >
< a class="expandA" > Groep A < /a >
< input field >
< input field >
< input field >
< input field >
< /div >
etc.. for 'groepB' , 'groepC' etc..
< /form >

< script >
$("#groepA :input").each( function() {
$(this).change( function() {
if ( $(this).val() != '' ) {$("#expandA").addClass("succes"); }
else { $("#expandA").removeClass("succes"); }
});
});
</ script >

No everytime someone changes the value (input) of a input field the other remaining input fields in the div '#groepA' only need to be checked on being empty.
If one or more of them are empty, remove the class 'succes' from '#expandA', if every input field is set, add class 'succes' tot '#expandA'.

Right now, the script check the value of a single input field and then adds or removes the class from '#expandA'. After checking one input field, it checks the next the same way..

I need the script first to check every input field, if empty or not, and if they are all set, the add class 'succes' to '#expandA'

Is this a more clear explanation.. BTW, I appologies for any mistakes in my English..

@Jorik,

Ok, I think I see what you're talking about now. For something like, it might be most helpful to get and keep a reference to the inputs before you do anything.

// Get object references.
var container = $("#expandA");
var inputs = container.find(":input");

// Bind inputs change events.
inputs.change(function(){

// Check to see if any inputs are empty.
if (inputs.filter("[value = '']").size()){
container.removeClass( "success" );
} else {
container.addClass( "success" );
}

});

Here, when the change event is triggered, we filter the existing input collection down to inputs that have an empty value. If ANY of the inputs are empty, the size() call will be a Truthy and the Success class will be removed.

NOTE: I did not actually run this.

@Ben Nadel,

Thanks a lot for your help, The script you posted worked like a charm.. just what I needed! Thanks again!

@Jorik,

My pleasure. When in doubt, get (and cache) references to the values you are going to be working with. I find that this often helps me think through the problem if for no other reason, it makes me more mindful of the situation.

Hello, I have some code using jQuery which works really well in Firefox and Chrome, but IE does not, it does not even access to the second each... here is the code:

$(".additive").each(function(){
alert('found an additive question');
var atLeastOne = false;
var scoreTotal = 0;
$(this+":input:checkbox").each(function(){
alert('checking checkbox state'); //IE is not getting here!!! Firefox and chrome does the work OK, but I don't know how to make this work on IE
if($(this).attr('checked')){
atLeastOne = true;
scoreTotal += parseInt($(this).attr('value'));
}
});
if(atLeastOne){
totalAdditiveAnswered ++;
alert('at least one selected');
}else{
alert('none selected');
}
userScore+=scoreTotal;
});

Anyone can help me with this?

@Marco,

My guess is that this line is causing a problem:

$(this+":input:checkbox")

Within the each() loop, "this" refers to the current DOM element in the iteration. It looks like you are trying to cast it to a string automatically. I am surprised this worked in other browsers.

If I think I see what you're doing, you're trying to find input/checkboxes contained within the current element? If so, try doing this:

$(":checkbox", this)

This approach uses the "this" as the context for the select, ":checkbox". I think that's what you want. Also, you don't need both the :checkbox and the :input pseudo selector - checkbox will always be an input.

Hello Ben,

Actually, that fixed the problem, it now works on IE.

I haven't noticed I did a mistake whileusing:

$(this+":input:checkbox")

Now it seems to be weird that it even worked!

Any way, using your suggestion:
$(":checkbox", this)

Did the trick!, thanks a lot!

This may be a bit novice, but I'm completely stumped.

Here's my setup:

I have a collection of divs with the same id. I'd like for each one of the divs to fadeOut whenever someone clicks on it, however, it only does so for the first. Here's the code I'm using:

HTML:

<div class = "success" id = "printmsg">
This is an example success message.
</div>

<div class = "error" id = "printmsg">
This is an example error message.
</div>

<div class = "notice" id = "printmsg">
This is an example notice message.
</div>

<div class = "message" id = "printmsg">
This is an example message... message.
</div>

jQuery:

$('#printmsg').each(function() {
$(this).click(function(){
$(this).fadeOut("500");
});
});

Any thoughts?

@A Lady

You can only speak for yourself. I'm a girl and it doesn't bother me at all. In fact, I find it amusing.

The humor in the code examples is one of the reasons I like Ben's site.

This site keep coming up in my searches for a current project and while the examples are clear & well presented, the very frequent use of girls throughout the site as humorous code examples rapidly becomes off-putting and gross.

Humour objectifying females (har har) can be funny in very occasional doses, but you might want to reign it in a bit, as after a while it begins to come off as extraordinarily creepy & exclusionary.

@Alexandru,

I like to keep it fun... but sometimes it rubs people the wrong way (see @Principessa's comment above).

Can't for the life of me figure out how to use each in the following situation... If I don't pass in deluserlist as parameter, all is good.

var delUserClicker = $('#deleteUser');
var delUserList = $('#profile_list li a');

function myFunction(delUserClicker,delUserList) {
delUserClicker.toggle(function(){
$(this).text('Done');
delUserList.each(function(i){
$(this).wait((i+1.25)*50).animate({
width: '69.5%'
},100,'swing');
});
}, function(){
$(this).text('Edit');
delUserList.each(function(i){
$(this).wait((i+1.25)*50).animate({
width: '100%'
},100,'swing');
});
});
}

Hello....can someone help me with a problem, which has been haunting me for weeks? I have an array of ids and I go through this array with an each loop. For each item in the array I want to fire a click() method that will select the corresponding radio button. Like this:

$.each(confArray, function(index, id) {
$('#' + id).click();
});

Where "confArray" is the array containing the id integer.
I´ve tried this with IE and it works fine, but with Firefox and Chrome it seems to only work for the last id of the array and all others are ignored. I don´t know what I´m doing wrong.

Help with this would be greatly appreciated. Thank you very much!

I am trying to use a button to select all rows in a datatable using jquery. I have a button with the id "selectall" and a table with the id "gtable" what i would like to achieve is all of the rows get a "row-highlight" css class added when the button is clicked. It seems like a foreach type problem but i am getting stuck with the jquery syntax.
here is a slice of the code that i have at the moment

  • $('#groups tr')
  • .click(function(event) {
  • $(this).toggleClass('row_selected');
  • });
  •  
  • $('#selectall')
  • .click(function(event){
  • for(var i in $('#groups tr')) i.removeClass('row_selected').addClass('row_selected');
  • });

i am sure that there is a simple fix for this, but i can't figure it out. Doesn't help that i am working in 36C and around 90% humidity...

OK, some perseverance and good luck helped me here. I am making headway with my problem. I also made a slight mistake when placing my original comment (above) the id of my table is "groups"

so here is my semi-working function to select/deselect all rows from my table.

  • $('#selectall')
  • .click(function(event){
  • $('#groups tr').each(function(index){
  • if (!$(this).hasClass('row_selected')) {
  • $(this).addClass('row_selected');
  • } else {
  • $(this).removeClass('row_selected');
  • }
  • });
  • });

The logic is not quite right at the moment, but I am making progress.
And there are no syntax errors.

This works fine if there are no rows currently selected, but I need to adjust it slightly to meet my needs.

  • $("#submit_btn").click(function(){
  • // when the button is clicked
  • // options are the inputs
  • $.each($(".options"),function(i,e){
  • // loop through all the items
  • var check = e.value;
  • if(check == '')
  • {
  • $(this).addClass("check");
  • $("form").submit(function () { return false; });
  • }else{
  • $(this).removeClass("check");
  • $("form").submit(function () { return true; });
  • }
  • });
  • });

so, this works except it submits the form even if there is blank inputs.... know how i can fix that?

please note that when you select using class name please add type of the element
like
$('input .text')
for faster than
$('.text')
cuz you tell jquery to search only on inputs
not all element

thanks

How do you skip the first element in the collection?

I am trying to recreate an accordion in Kevin Yank's Javascript course using jQuery. I need the title link to have a click event and I need all other links in the fold to have focus events. If the title gets both events, it expands and then quickly collapses, so I believe I need to skip the title link when binding the focus event listener.

With a javascript for-loop I would start with var i=1, but I am lost as to how to skip the first indexed element the each() or $.each();

Sorry if this is too simple, I have just begun studying jQuery after learning the fundamentals of Javascript at SitePoint/Learnable.

Thanks Ben! Even though most of your blog is over my head - I have been coming back for the past 2 years!

Ha! I think I figured it out from your reply to Marta above. I am now using the not(). It works now but is there a better way? I tried the pseudo-selector :gt(), but I couldn't get that to work.

var Accordion =
{

init: function()
{
var accordions = $("ul.accordion");
var folds = accordions.children();

$(folds).each(function(index)
{
Accordion.collapse(folds);
var foldLinks = $(this).find('a');
var foldTitleLink = $(foldLinks).eq(0);
$(foldTitleLink).bind("click", Accordion.clickListener);
$(foldLinks).not(foldLinks[0]).bind("focus", Accordion.focusListener);
})
},

collapse: function(fold) ...
collapseAll: function(accordion)...
expand: function(fold) ...
clickListener: function(event)...
focusListener: function(event)...
};

Accordion.init();

Thanks!

Ben, first off, thanks, this was the snippet I was searching for.

@geekgirl, a lady and 'princess' - or the white-knight trolls posting them - you are stupid. Talking about one gender isn't automatically sexist. You are ridiculous. Saying you like women, or that "girl is hot" isn't sexist. Fuck me. It would take a leather bound tome of severe proportions to fully explain the levels of failure in understand how the world works.

@Ben, thanks for not being one of those idiot guys who uses a male-specific pronoun in an example or even a non-specific one, gets a comment saying it is sexist and write an 11 paragraph note at the top of the post apologizing and then updating it.

@Amy

Thanks for being an educated voice around here! I am glad the pigswill internet fauxminism hasn't messed with the singular individualism of all people!

Cheers

i try to get this to loop, but can't, need some help

$('document').ready(function()
{

$('#acceptForm').ajaxForm( {
target: '#memberslinkup',
success: function() {
$('#requestlinkUP_accept').slideUp('fast');
$('#requestlinkUP_burn').slideUp('fast');
$('#requestlinkUP_text').slideUp('fast');
}
});

Hi,I am facing one problem in jquery,

I want to display a popup div on a click of an image. that image is inside a <td> of a table.I am iterating that table.and the values are coming from database for every record.
i have written jquery functions for creating popup.

My problem is whenever i am clicking on any image to get the popup, i am always getting the popup with the data of the first record.

whereas, i am expecting whenever i will be clicking on an image to get the popup i should get the data for that image which i am clicking on.

whenever i click on "mybutton" it always searches for the div with popup name "Popup"
which it gets in the first row itself. so i am always getting data for the first row inside my popup window. which is incorrect.
I want appropriate data for corresponding row.

Please help it is really urgent.

@Ben,

In the following example, would the "i" refer to the position of the "tr" being iterated via "each"?. Thanks!! Funny site! It keeps me from falling asleep!

--------------------------------------

  • jQuery("tr#guys").each(function(i, tr) {
  •  
  • var description = jQuery("#condoms", tr).text();
  • var name = jQuery("#name", tr).text();
  • if(description == "refuses"){
  • console_log("watch out for " + name + " at position number i: " + i);
  • }
  • else {
  • console_log("gotta love " + name + " at position number i: " + i + "!");
  • }
  • });

My code

showHide: function (event) {
var type=event.data.divName;
console.log('inside the function for ' + type);
}

var quickShow = currentPage.find('a#quick_show');
if(quickShow){
if(quickShow.length > 0) {
quickShow.each(currentClass,function(indx,containerRow){
console.log('Element '+containerRow.name + ' ' + indx);
currentPage.find('a '+containerRow.name).click({divName: 'show'+containerRow.name }
,function(event){
console.log('trying to call ');
showHide();
});
});
}

}

not able to access the showHide() from inside the call back method

Please help

my html code :
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="nss.js"></script>
</head>
<body>
a rel="nss"></a>
a rel="nss"></a>
a rel="nss"></a>
a rel="nss"></a>
</body>
</html>
=======================================
My javascript code !
(function( $ ) {

$.fn.nss = function( ) {

var q = this.index(this)
console.log(q)
};

}( jQuery ))

// console.log(q) = -1

@Greg,

Hey - I'm trying to accomplish the same thing as you are. I dynamically create checkboxes based on an event and then I grab the user's data which corresponds to the checkboxes. What I want to do is check the checkboxes that match the user's data since the values will vary from event to event and user to user.

That's sounds like what you were doing? If so, can you help me out with the code? I've been banging my head on this for days.

Basically, I need to look through each UserCarType and if one or more numbers match the values of CarType then check those checkboxes. I can't seem to get this to work. These are numeric values so they have to be an exact match, i.e. 1 can not match 10 so the indexOf doesn't work for this.