KarelRuzicka
KarelRuzicka

Reputation: 471

How to make function queue executions in jS

I use jQuery to smoothen up hiding and showing of the boxes. For example if you click to hide one box, it will hide all of the boxes but only the ones that should not be hidden will then reappear.

With showing it was a little bit harder. The box that was supposed to show was showing before the others finished disappearing. So I added a setTimeout function with time limit of 400ms (default fade in/out time in JQuery).

Now the code runs fine except for one little thing. If you click on all the buttons rapidly the boxes will queue up to disappear. That's how it should be. However if you repeat the process (rapidly click all the button backwards to make all the buttons reappear) it will glitch out.

I replicated the process on video here: https://ctrlv.tv/video/2020/04/09/13/Ij9u.webm . - You can see that the disappearing looks smooth but the reappearing looks terrible.

I think this might be happening because of the setTimeout function.

Is there any way to go around this?

function showhide(num) {
  if ($("#box" + num).css('display') == 'none') {
    $(".box").fadeOut();
    
    setTimeout(function() {
      $("#box" + num).removeClass("hidden");
      $(".box:not(.hidden)").fadeIn();
    }, 400);
  } else {
    $(".box").fadeOut();
    $("#box" + num).addClass("hidden");
    $(".box:not(.hidden)").fadeIn();
  }
}
html {
  width: 340px;
  border-style: solid;
}

.box {
  width: 100px;
  height: 100px;
  float: left;
}

#box1 { background-color: red; }
#box2 { background-color: blue; }
#box3 { background-color: green; }
#box4 { background-color: yellow; }
#box5 { background-color: orange; }
#box6 { background-color: purple; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<b>Hide/Show</b><br>

<button onclick="showhide(1)">Box 1</button>
<button onclick="showhide(2)">Box 2</button>
<button onclick="showhide(3)">Box 3</button>
<button onclick="showhide(4)">Box 4</button>
<button onclick="showhide(5)">Box 5</button>
<button onclick="showhide(6)">Box 6</button><br><br>

<div id="box1" class="box"></div>
<div id="box2" class="box"></div>
<div id="box3" class="box"></div>
<div id="box4" class="box"></div>
<div id="box5" class="box"></div>
<div id="box6" class="box"></div>

jsFiddle

Upvotes: 1

Views: 36

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337646

The issue is because you rely on the .hidden class not existing on the elements for the fade to work. As soon as you remove that class the element re-appears.

You can make the logic more effective, and simpler, by surrounding the .box elements with a container which you can fade in/out. In the callback of that fade you can then hide/show the relevant box before fading the visible ones back in again. Try this:

let $container = $('#box-container');

$('button').on('click', function() {
  var $target = $($(this).data('target'));
  
  $container.fadeOut(() => {
    $target.toggleClass("hidden");
    $container.fadeIn();
  });
});
html {
  width: 340px;
  border-style: solid;
}

.box {
  width: 100px;
  height: 100px;
  float: left;
}

.hidden { display: none; }

#box1 { background-color: red; }
#box2 { background-color: blue; }
#box3 { background-color: green; }
#box4 { background-color: yellow; }
#box5 { background-color: orange; }
#box6 { background-color: purple; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<b>Hide/Show</b><br>

<button data-target="#box1">Box 1</button>
<button data-target="#box2">Box 2</button>
<button data-target="#box3">Box 3</button>
<button data-target="#box4">Box 4</button>
<button data-target="#box5">Box 5</button>
<button data-target="#box6">Box 6</button><br><br>

<div id="box-container">
  <div id="box1" class="box"></div>
  <div id="box2" class="box"></div>
  <div id="box3" class="box"></div>
  <div id="box4" class="box"></div>
  <div id="box5" class="box"></div>
  <div id="box6" class="box"></div>
</div>

Also note the use of unobtrusive event handlers. Inline onX attributes are no longer good practice and should be avoided where possible.

Upvotes: 1

Related Questions