Daniel Daniel - 3 years ago 86
jQuery Question

How to pass currently iterated element (this) into setTimeout inside .each() function?

I'm trying to iterate through each

caption-element
inside
caption
div using
each()
function, get
captionin
,
captionout
and
delayout
attributes, next
removeClass
of that element given in
captionout
attribute (without checking if the class has been already added or not) and
addClass
to that element given in
captionin
attribute. That's easy and works perfectly.

Next I'm trying to reverse the whole process of adding and removing classes taken from
captionin
and
captionout
attributes but this time to delay it by a amount of time given in
delayout
attribute (by using
setTimeout()
function). And it doesn't work.

The whole ide is to give every iterated element it's own setTimeout delay taken from
delayout
attribute.

Every help for a complete rookie much appreciated :)

HTML:

<div class="caption">
<div id="1" class="caption-container">
<h1 class="caption-element animated" captionin="fadeInUp" captionout="bounceOut" delayout="2000">Caption 1</h1>
</div>
<div id="2" class="caption-container">
<h1 class="caption-element animated" captionin="swing" captionout="fadeOutDown" delayout="4000">Caption 2</h1>
<h1 class="caption-element animated" captionin="bounceInUp" captionout="lightSpeedOut" delayout="3000">Caption 2</h1>
</div>
<div id="3" class="caption-container">
<h1 class="caption-element animated" captionin="bounceInUp" captionout="rotateOutUpLeft" delayout="2500">Caption 3</h1>
</div>
</div>


jQuery

jQuery('.caption .caption-element').each(function () {
var captionin = jQuery(this).attr('captionin');
var captionout = jQuery(this).attr('captionout');
var delayout = jQuery(this).attr('delayout');
jQuery(this).removeClass(captionout).addClass(captionin);
setTimeout(function () {
jQuery(this).removeClass(captionin).addClass(captionout);
}, delayout, captionin, captionout);
});


PS, ask question in comment before downvoting please, thanks :)

Answer Source

Two issues.

1- Scope. this is not the same this in different functions. More about this. I solved this by capturing the JQuery(this) in a variable and use it across the code. Therefore, this won't give me surprise when I want to access the selected element $elem from somewhere else in the code.

2- I assume setTimeout needs a number as a value of time units. You are passing a string.

jQuery('.caption .caption-element').each(function() {
  var $elem = jQuery(this);


  var captionin = $elem.attr('captionin');
  var captionout = $elem.attr('captionout');
  var delayout = $elem.attr('delayout');

  console.log("Before: " + $elem.attr("class"));
  $elem.removeClass(captionout).addClass(captionin);

  setTimeout(function(captionin, captionout) {

    $elem.removeClass(captionin).addClass(captionout);
    console.log("After:" + $elem.attr("class"));

  }, Number(delayout), captionin, captionout);
});
<script src="https://code.jquery.com/jquery-2.0.3.js"></script>
<div class="caption">
  <div id="1" class="caption-container">
    <h1 class="caption-element animated" captionin="fadeInUp" captionout="bounceOut" delayout="2000">Caption 1</h1>
  </div>
  <div id="2" class="caption-container">
    <h1 class="caption-element animated" captionin="swing" captionout="fadeOutDown" delayout="4000">Caption 2</h1>
    <h1 class="caption-element animated" captionin="bounceInUp" captionout="lightSpeedOut" delayout="3000">Caption 2</h1>
  </div>
  <div id="3" class="caption-container">
    <h1 class="caption-element animated" captionin="bounceInUp" captionout="rotateOutUpLeft" delayout="2500">Caption 3</h1>
  </div>
</div>

Result:

Before: caption-element animated
Before: caption-element animated
Before: caption-element animated
Before: caption-element animated
After:caption-element animated bounceOut
After:caption-element animated rotateOutUpLeft
After:caption-element animated lightSpeedOut
After:caption-element animated fadeOutDown
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download