Getting functions to execute at the right time (queued or concurrently)

221 Views Asked by At

I have written a little script that randomly shuffles a series of divs - this works as expected (or hoped).

My problem is in the implementation. I want the divs to fade out, to be shuffled and to fade in again. What I have found is that the function moveBox() executes concurrently with any animation. I have tried calling the it as a callback function to all the elements (fadeOut, delay and fadeIn) in the animation, but always with the same effect - the shuffling and redistribution of the divs happens during the animation, and is therefore visible.

I have a solution (var ts=timeOut...) which makes the shuffle happen while the divs are hidden, but I am not convinced that this is the best solution.

I would like to know how to control the order of execution of functions and whether they should execute concurrently or in sequence. My code :

<style>
    .tester{
        float:left;
        width:100px;
        height:100px;
        margin:5px;
        }
    .tester p{text-align:center;
        margin-top:20px;
    }
    .one{background-color:red;}
    .two{background-color:yellow;}
    .three{background-color:teal;}
    .four{background-color:blue;}
    .five{background-color:green;}
    .six{background-color:silver;}
</style>

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    jQuery(document).ready(function(){
        var anibase=jQuery(".tester").length;
        jQuery(".tester").fadeOut(1000);
        function moveBox(){
            function shuffle(){
                for (i = 0; i <= (anibase - 2); i++) {
                    mover = Math.floor(Math.random() * (anibase - i));
                    if (mover != 0) {
                        mover = mover + i;
                        jQuery(".tester:eq(" + mover + ")").insertBefore(".tester:eq(" + i + ")");
                    };
                };
            };
            jQuery(".tester").fadeOut(1500).delay(500).fadeIn(1500);
            var ts = setTimeout(shuffle,1500);
            var t=setTimeout(moveBox,5000);
        };
        moveBox();
    });

</script>
<body>
    <div class="tester one">
        <p>box 1</p>
    </div>
    <div class="tester two">
        <p>box 2</p>
    </div>
    <div class="tester three">
        <p>box 3</p>
    </div>
    <div class="tester four">
        <p>box 4</p>
    </div>
    <div class="tester five">
        <p>box 5</p>
    </div>
    <div class="tester six">
        <p>box 6</p>
    </div>
</body>

thanks in advance

1

There are 1 best solutions below

5
On BEST ANSWER

JQuery has the ability to nest functions, effectively controlling the order of execution.

First off although it is valid to nest functions in Javascript in this case it is not necessary, consider the following code:

<script type="text/javascript">

  jQuery(document).ready(function(){
    moveBox();  //call the function that will do the work and then setTimeout
  });



  function moveBox(){
    jQuery(".tester").fadeOut("slow",function(){
      shuffle();
      $(this).fadeIn("slow");
      return;
    });
    var t=setTimeout(moveBox,5000);
  }

  function shuffle(){
    var anibase=jQuery(".tester").length;
    for (i = 0; i <= (anibase - 2); i++) {
      mover = Math.floor(Math.random() * (anibase - i));
      if (mover != 0) {
        mover = mover + i;
        jQuery(".tester:eq(" + mover + ")").insertBefore(".tester:eq(" + i + ")");
      }
    }
  }
</script>

The important part here to look at is this:

jQuery(".tester").fadeOut("slow",function(){
  shuffle();
  $(this).fadeIn("slow");
  return;
});

This will instruct jQuery to

  1. Fade Out the .tester element
  2. When the fade out is complete execute shuffle()
  3. Then fade the elements back in

You can see further examples of this in the fadeOut documentation, some of the examples show chained events

Also by keeping your function definitions separate it makes it much easier to read.