1

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;
    });

Not very well versed in jquery but i'm stumbled because I have this code which works for hiding them first

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

      $('.newest_full' + i).hide();

      i = i + 1;
    });
Michael Bragt
  • 21
  • 1
  • 6
  • What does your HTML look like? – user1032531 Sep 29 '15 at 23:37
  • possible duplicate of [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – JJJ Sep 29 '15 at 23:37
  • Well the html i a big foreach loop, think it's to much to copy here, but basically im pulling post from a database.... And I want to have two different styled DIVS, where one is hidden and one is visible and then use the handler to show/hide them... Im giving the divs unique identifier adding by a $count php variable So something like:
    Etc.
    – Michael Bragt Sep 29 '15 at 23:45

3 Answers3

2

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();
  });
});
Andrew Shepherd
  • 44,254
  • 30
  • 139
  • 205
  • Okay, thx alot... Not so much into jquery yet.... But is index a default used index for a each() loop? – Michael Bragt Sep 30 '15 at 00:07
  • @MichaelBragt - Not sure I understand your question. `index` will be the zero based index of the iteration:it will be 0 for the first item, 1 for the second, 2 for the third and so on. http://api.jquery.com/each/ – Andrew Shepherd Sep 30 '15 at 00:17
0

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.

Titus Popovici
  • 149
  • 2
  • 11
  • Ahh okay, so my function to hide all the divs works because is not for a handler? but actually to hide them 'while' the HTML is generated? – Michael Bragt Sep 29 '15 at 23:54
0

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.

Ivan De Paz Centeno
  • 3,595
  • 1
  • 18
  • 20