-1

I'm trying to simplify my code using while loop but the value can't seem to attach. Here is an example

  var x=1;
  while(x <= 20){
    $('.analytics' + x).click(function(event){
        analytics(x);
    });
    x++
  }

  var analytics = function(num){
    alert(num);
  };

Everytime I click a button containing a class analytics1-5 it returns a value of 20 when I expect it to be 1,2,3,4,5 . I have a vague idea that I'm passing 20 to the function analytics since the while loop already ended when I click a button. Can someone explain this to me ?

Chris W.
  • 22,835
  • 3
  • 60
  • 94
Gilbert Mendoza
  • 405
  • 1
  • 7
  • 16

5 Answers5

2

Edit: I got a little overzealous with my edits on your question. I apologize if I threw off other people who answered.

You're running into a scope/binding problem. It's been so long since I've dealt with < ES6 that I really struggled to remember how to solve it. I've updated my answer to have one possible solution.

This SO kind of covers it better than I did: Javascript infamous Loop issue?

$(document).ready(function() {
  for (var i=1; i<=5; i++) {
      $('.analytics' + i).click(function(event) {
        analytics($(this).index());
      });
  }

  function analytics(num) {
    console.log(num);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="analytics1">A1</div>
<div class="analytics2">A2</div>
<div class="analytics3">A3</div>
<div class="analytics4">A4</div>

Original irrelevant answer:

Ugh, you are multiple binding. You have bound 20 click events to that piece of DOM. Once you click you are only seeing the last one.

The loop doesn't wait for you to click. You can confirm this by putting console.log(x); inside the loop and hit F12 to see that all 20 events have bound before you click.

Matt
  • 5,315
  • 1
  • 30
  • 57
  • 1
    That expression of disgust though. – cs95 Jun 29 '17 at 04:30
  • Them: "Why is this ajax method firing 40 times?!" Me: "Because every time you change tabs you are rebinding it." – Matt Jun 29 '17 at 04:36
  • You shouldn't edit someone's original question to that extent, rolled it back, sorry amigo. :) – Chris W. Jun 29 '17 at 04:40
  • No worries I just figured you threw your edits in the wrong post instead of your own edit, cheers – Chris W. Jun 29 '17 at 04:42
  • oh wait I thought it did this but guess something off w8 – Gilbert Mendoza Jun 29 '17 at 05:24
  • What's happening? – Matt Jun 29 '17 at 05:27
  • basically what I want to happen is when a class containing analytics10 is clicked then it will alert 10. in the snippet its all analytics1 but it prints different values. – Gilbert Mendoza Jun 29 '17 at 05:31
  • You should see A1, A2, A3, A4 and each should print the equivalent number. Not sure what you mean when you say all analytics 1. – Matt Jun 29 '17 at 05:33
  • the class, i'm talking about the class – Gilbert Mendoza Jun 29 '17 at 05:35
  • Oops, how about now? – Matt Jun 29 '17 at 05:36
  • not relevant. can you add another line in that
    A5
    . this should print 10 right
    – Gilbert Mendoza Jun 29 '17 at 05:37
  • No. It will print 5 because it's the 5th item. Now that I see what you're looking for there's probably an easier way to do this. I don't even think you need the loop. I don't have time to create another answer tonight, but if you ultimately want to assign some number to each div and then alert that number, put class="analytics" on all of them and use data-id="xyz" for the values. Then you can have a single click event for analytics and output the data-id of the specific item that was clicked. – Matt Jun 29 '17 at 05:40
  • solved it by navigating the link that you provided. thank you – Gilbert Mendoza Jun 29 '17 at 05:41
1

You're basically telling it that once it's clicked, count to 21 and execute the function, 20 times.

I think what you mean to do just takes a quick tweak in the logic;

var x=1;
$('.analytics').click(function(event){
  while(x <= 20){   
      console.log(x);    
    x++
  }
 });
button {
  padding: 1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="analytics">Something to Click to Count to 20</button>

Wherein the example I just slapped a console.log in there for example but you could execute your method instead. Hope this helps, cheers.

Chris W.
  • 22,835
  • 3
  • 60
  • 94
  • I actually need the analytics to be inside the while loop, because the name of the classes that ill be using is analytics1 analytics2 ... – Gilbert Mendoza Jun 29 '17 at 05:20
1

Try this one:

      var x = 1;
    $(document).on('click','.analytics',function(){
      while(x <= 20){
        analytics(x);
            x++;
  }
    });
    function analytics(num){
        alert(num);
      };
Mohammed Shiyas
  • 63
  • 1
  • 11
1

New answer based on previous comments on previous answer.

$(document).ready(function() {
  $('.analytics').on('click', function(event) {
    analytics($(this).data("id"));
  });

  function analytics(num) {
    console.log(num);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="analytics" data-id=1>A1 id1</div>
<div class="analytics" data-id=2>A2 id2</div>
<div class="analytics" data-id=42>A3 id42</div>
<div class="analytics" data-id=17>A4 id17</div>

In case anyone finds this question in the future.

ES6 solves this problem by allowing you to use let.

$(document).ready(function() {
  for (let i = 1; i <= 5; i++) {
    $('.analytics' + i).click(function(event) {
      analytics(i);
    });
  }

  function analytics(num) {
    console.log(num);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="analytics1">A1</div>
<div class="analytics2">A2</div>
<div class="analytics3">A3</div>
<div class="analytic4s">A4</div>
Matt
  • 5,315
  • 1
  • 30
  • 57
0

This does the trick for me

  for (var i=1; i<=20; i++) {

    function clickHandler(num) {    
        $(".analytics" + i).click (function(event){
            analytics(num);
        })
    }
    clickHandler(i);

  }

thanks for the link @mkaatman

Gilbert Mendoza
  • 405
  • 1
  • 7
  • 16