PHPhil
PHPhil

Reputation: 1540

Multiple setTimeout and clearTimeout intervering each other

I'm trying to accomplish the following. I have multiple forms with a button. When I click on that button, I want it to change color and text for 2 second. When clicked again within that timeframe it resets and the rotation will start over.

So far my codes work as expected, However, when I click on the button of another form within these 2 seconds the rotation stops because timerId is cleared by clearTimeout.

Look at my example, when you click ‘order1’ and within 2 second you click ‘order2’ then ‘order1’doesn’t change back to its original state. Is there a way to let other forms not interfere with each other?

var timerId, delay = 2000;

$(".product-form").submit(function(e){
 
var button = $(this).find('button[type=submit]'),
  order = button.find("span:eq(0)"),
  added = button.find("span:eq(1)");

  clearTimeout(timerId);
  added.hide();
  order.hide();
  button.addClass("green");
  added.slideDown("slow");

  timerId = setTimeout(function() {
    added.hide();
    order.show();
    button.removeClass("green");
  }, delay); 
  e.preventDefault();
});
form {
  float: left;
  padding: 10px;
}

.hide {
  display: none
}

#button {
  width: 200px;
  height: 40px;
  border: none;
  background: orange;
}

.green {
  background: green !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order1</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>
 
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order2</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order2</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

Upvotes: 3

Views: 65

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

Your code uses just a single timerId for all buttons, so that's why they're stepping on each other. You could store the timerId on the button instead, see *** lines:

var delay = 2000; // *** No timerId here

$(".product-form").submit(function(e) {
  var $this = $(this),                               // ***
      timerId = $this.data("timerId"),               // ***
      button = $this.find('button[type=submit]'),    // ***
      order = button.find("span:eq(0)"),
      added = button.find("span:eq(1)");

  clearTimeout(timerId);
  added.hide();
  order.hide();
  button.addClass("green");
  added.slideDown("slow");

  $this.data("timerId", setTimeout(function() {      // ***
    added.hide();
    order.show();
    button.removeClass("green");
  }, delay));                                        // ***
  e.preventDefault();
});
form {
  float: left;
  padding: 10px;
}

.hide {
  display: none
}

#button {
  width: 200px;
  height: 40px;
  border: none;
  background: orange;
}

.green {
  background: green !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order1</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>
 
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order2</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order2</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

Upvotes: 1

Rounin
Rounin

Reputation: 29453

You need to make only 3 simple changes:

  1. Make timerId an array;
  2. Remove the clearTimeout statement;
  3. Since timerId is now an array, use timerId[timerId.length] = setTimeout(function() {

Working Example:

var timerId = [];
var delay = 2000;

$(".product-form").submit(function(e){
 
var button = $(this).find('button[type=submit]'),
  order = button.find("span:eq(0)"),
  added = button.find("span:eq(1)");

  added.hide();
  order.hide();
  button.addClass("green");
  added.slideDown("slow");

  timerId[timerId.length] = setTimeout(function() {
    added.hide();
    order.show();
    button.removeClass("green");
  }, delay); 
  e.preventDefault();
});
form {
  float: left;
  padding: 10px;
}

.hide {
  display: none
}

#button {
  width: 200px;
  height: 40px;
  border: none;
  background: orange;
}

.green {
  background: green !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order1</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>
 
<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order2</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

<form class="product-form" action="#cart" method="post">
  <button id="button" type="submit">
    <span>Order3</span>
    <span class="hide">&#10003; Added</span>
  </button>
</form>

Upvotes: 0

Related Questions