Why does this jquery each() loop doesn't operate on unique classes

I'm trying to make a jquery function work on classes with a unique identifier.. But it seems like it isn't adding the var to the element... How do I do this

My code is this...

    var x = 1;
    $('.newest_posts').each(function() {

      $('.showFull' + x).on('click', function(e) {
        $('.newest_small' + x).hide(); // hide image preview on delete click
        $('.newest_full' + x).show(); // hide image delete link on click
        e.preventDefault();
      });

      x = x + 1;
    });

Answers


You have to ask the question: what does x equal when the click handler is called? It will not be equal to the x value when you registered the handler, but be equal to the value of x after the loop has completed.

Assuming nothing else modified it, it will be equal to $(.newestPosts).length() + 2.

Here is the quick fix for the problem:

var x = 1;
$('.newest_posts').each(function() {
  var xCopy = x;
  $('.showFull' + xCopy).on('click', function(e) {
    $('.newest_small' + xCopy).hide(); // hide image preview on delete click
    $('.newest_full' + xCopy).show(); // hide image delete link on click
    e.preventDefault();
  });

  x = x + 1;
});

It creates a new variable inside the scope of the handling function.

An even better fix is to dispense with the outer x and use the first parameter of the each handler, which will be the index.

$('.newest_posts').each(function(index) {
  var x = index + 1;
  $('.showFull' + x).on('click', function(e) {
    $('.newest_small' + x).hide(); // hide image preview on delete click
    $('.newest_full' + x).show(); // hide image delete link on click
    e.preventDefault();
  });
});

You must first understand that javascript is asynchronous, and that code doesn't run the way you'd expect it to run in a synchronous programming language.

The each loop runs when the page loads, incrementing the x variable, whereas the function you passed as a parameter to the 'click' event only runs when the actual element is clicked on the page. At that point, the value of your x is going to be the same as the number of posts that you have.

You could do it like this:

var x = 1;
$('.newest_posts').each(function() {

  $('.showFull' + x).on('click', function(e) {
    var thisElementsIndex = $(this).attr("class").split(' ').filter(function(el){
       return el.indexOf('showFull') != -1
    })[0].replace('showFull', '');
    $('.newest_small' + thisElementsIndex ).hide(); // hide image preview on delete click
    $('.newest_full' + thisElementsIndex ).show(); // hide image delete link on click
    e.preventDefault();
  });

  x = x + 1;
});

What happens here is, the 'each' iteration using the x variable makes sure that all of your classes trigger that callback when you click on them. In the callback, you retrieve the value for x from the class name and pass it to the hide/show selectors.


You can also use the data() method to store its index in order to use it inside the element's onclick function:

var x = 1;
$('.newest_posts').each(function() {

  $('.showFull' + x).data('index', x);
  $('.showFull' + x).on('click', function(e) {
    var index = $(this).data('index');
    $('.newest_small' + index).hide(); // hide image preview on delete click
    $('.newest_full' + index).show(); // hide image delete link on click
    e.preventDefault();
  });

  x = x + 1;
});

This have the advantage that maps each iteration index to its corresponding element, allowing other functions to benefit from it; also you don't have to care about the value of x, whose scope is out of the function.


Need Your Help

unhandled microsoft .net framework exception in w3wp.exe

c# .net workflowservice

I am writing a console application which uses a workflow service.

Parsing C# code to evaluate expressions (basically, implementing Intellisense)

c# parsing intellisense lexer

I'm trying to evaluate C# code as it gets typed, think of it as if I'm trying to write an IDE.