0

I have 4 css classes that are named a particular way : test-class-0, test-class-1, test-class-2, test-class-3 so that I can register custom click handlers programmatically.

Here is my attempt:

for(var i = 0; i < 4; i++) {
  $('.test-class-'+i).on('click', function(e){ alert(i); });
}

Full demo:

for (var i = 0; i < 4; i++) {
  $('.test-class-' + i).on('click', function(e) {
    alert(i);
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test-class-0">TEST 1</div>
<div class="test-class-1">TEST 2</div>
<div class="test-class-2">TEST 3</div>
<div class="test-class-3">TEST 4</div>

The events get registered, however, the handler will always use the latest value of i, which is 4, when I would like the value of i on the time of handler registration, so I get alert(0), alert(1), alert(2), and alert(3) when I click on test-class-0, 1, 2, 3 respectively.

Is there a way I can lock down the value of i within the function when the click handler is registered?

Goran Stoyanov
  • 2,311
  • 1
  • 21
  • 31
hofan41
  • 1,438
  • 1
  • 11
  • 25

4 Answers4

4

for (var i = 0; i < 4; i++) {
  $('.test-class-' + i).on('click', {
    i: i
  }, function(e) {
    alert(e.data.i);
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test-class-0">TEST 1</div>
<div class="test-class-1">TEST 2</div>
<div class="test-class-2">TEST 3</div>
<div class="test-class-3">TEST 4</div>
Goran Stoyanov
  • 2,311
  • 1
  • 21
  • 31
Rich Tier
  • 9,021
  • 10
  • 48
  • 71
1

Alternatively, you might use only one event handler, and resolve the class index at runtime:

$('[class*="test-class-"').on('click', function() {
  var i = $(this).attr("class").replace("test-class-", "");
  alert(i);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test-class-0">TEST 1</div>
<div class="test-class-1">TEST 2</div>
<div class="test-class-2">TEST 3</div>
<div class="test-class-3">TEST 4</div>
Goran Stoyanov
  • 2,311
  • 1
  • 21
  • 31
LcSalazar
  • 16,524
  • 3
  • 37
  • 69
0

Use a closure:

for(var i = 0; i < 4; i++) {
  (function( i ) {
     $('.test-class-'+i).on('click', function(e){ alert(i); });
  })( i )
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test-class-0">TEST 1</div>
<div class="test-class-1">TEST 2</div>
<div class="test-class-2">TEST 3</div>
<div class="test-class-3">TEST 4</div>
PeterKA
  • 24,158
  • 5
  • 26
  • 48
0

You can try using this instead of the for:

$('*[class*="test-class-"]').each(function(i) {
  $(this).on('click', function() {
    alert(i + 1)
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="test-class-0">TEST 1</div>
<div class="test-class-1">TEST 2</div>
<div class="test-class-2">TEST 3</div>
<div class="test-class-3">TEST 4</div>
Goran Stoyanov
  • 2,311
  • 1
  • 21
  • 31
carlosherrera
  • 177
  • 2
  • 11