0

I have a border 9x9, with lines, columns and squares, like a sudoku border and I want to animate it but I had a few problems when there was multiple animations at same time, so I decided to animate one array of elements each time, for that I putted them in an array and want to animate it one by one but I'm having some issues. There is a piece of my code:

var col,
        row,
        square,
        arr = [];

    col = checkColumn(cell);
    row = checkRow(cell);
    square = checkSquare(cell);

    if(row != null){
        arr.push(row);
    }

    if(col != null){
        arr.push(col);
    }

    if(square != null){
        arr.push(square)
    }

    if(arr.length !=0){
        arr.each(function(){
            enlight($(this));
        });
    }

So, at the moment I can't use arr.each because it says arr isnt a function, If I change arr to:

arr ={}

I can't use .push to add the elements, is there an solution to animate them one by one? Thank you in advance for the help!

The enlight does this:

function enlight(cells){
    var delayTime=0;
    cells.each(function(){
        $(this).parent().delay(delayTime).animate({
            "background-color" : "#ffa500"

        }, 500).delay(100)
            .animate({
                "background-color" : "#ffffff"
            });
        delayTime+=100;
    })

}

So, I want to sent an array each time (row, col and square) to animate one by one not all at same time.

Some HTML:

<div class="board">
      <div class="row">
        <div class="cell">
            <input type="number"  data-column="0" data-line="0">
        </div>
        <div class="cell">
            <input type="number"  data-column="1" data-line="0">
        </div>
        <div class="cell">
            <input type="number"  data-column="2" data-line="0">
        </div>
        <div class="cell">
            <input type="number"  data-column="3" data-line="0">
        </div>
        (more cells 81 in total)
João Silva
  • 531
  • 4
  • 21
  • 40
  • Animate what, it's an array and a number of unspecified functions? – adeneo Oct 24 '16 at 17:28
  • col, row and square are arrays of 9 cells each, the enlight function works well but I just want to pass here one of them at a time. – João Silva Oct 24 '16 at 17:29
  • You are passing them one at a time, but the animation is probably async, so you have to wait for something, but as that code isn't posted, there's no way to know what to wait for, or for how long ? – adeneo Oct 24 '16 at 17:31
  • My problem here isn't, the problem is with the var arr, if I let it arr = [] I cant use the function arr.each(). If I make it arr = {} I can't use the function .push() – João Silva Oct 24 '16 at 17:33
  • It sounds like this question is more about iterating over an array, is that right? Are you asking "how can I do `something` to each element of an array"? – alexanderbird Oct 24 '16 at 17:36
  • Yes but one at a time – João Silva Oct 24 '16 at 17:41
  • `arr.forEach( enlight )` – adeneo Oct 24 '16 at 17:48
  • @adeneo using that they will go almost all at same time, I want to do it one at once, just want to move to the next array after the previous finished his animation – João Silva Oct 24 '16 at 17:51
  • And again, **you can not** do that unless you know what's animating, how long it takes, when it happens etc. and you haven't showed us that. – adeneo Oct 24 '16 at 17:52
  • @adeneo I added enlight function, I send him an array of 9 cells, I just want to animate the next array after this one finish his job, not before. – João Silva Oct 24 '16 at 17:55
  • Something more like this -> https://jsfiddle.net/h8ge7s89/1/ – adeneo Oct 24 '16 at 17:58
  • @adeneo with that I get "cannot read property 'then' of undefined" but the first element animate. – João Silva Oct 24 '16 at 18:02
  • Oh, more like this then *(and it's a general idea, not neccessarely production code)* -> https://jsfiddle.net/h8ge7s89/3/ <- edited this – adeneo Oct 24 '16 at 18:06
  • @adeneo after that it doesnt move one for the next elements of the array, so it animate the row but doesnt move to the line or square. – João Silva Oct 24 '16 at 18:11
  • https://jsfiddle.net/h8ge7s89/5/ – adeneo Oct 24 '16 at 18:25
  • 1
    Maybe I'm just complicating this for you, here's another example -> https://jsfiddle.net/h8ge7s89/6/ – adeneo Oct 24 '16 at 18:46
  • My problem isnt animate 1 array of cells, I'm trying to animate 1 array each time, for exemple, I have 1 array with 3 arrays of cells each, row (9 cells), column (9 cells) and a square (9 cells), so I kinda have a matrix, but I want to animate 1 array each time, first row, then column then the square. just to prevent overlapping of animations when there is a row/column with a square... – João Silva Oct 24 '16 at 18:50

2 Answers2

1

so I decided to animate one array of elements each time, for that I putted them in an array and want to animate it one by one

You can use .queue(), .promise(), .then(), $.map() to animate elements in sequential order.

// set queue name for `.row` element to `"enlighten"` iterate `.row` elements
$({}).queue("enlighten", $.map($(".row"), function(el, index) {
  // return a function to push to `"enlighten"` queue
  return function(next) {
    // set queue name for `.cell input` elements to `"cells"`
    // iterate `input` elements within `.cell` elements
    $({}).queue("cells", $.map($(".cell > input", el), function(cell) {
      // return a function to push to `"cells"` queue
      return function(_next) {
        // animate `.cell input` elements
        $(cell).delay(100).animate({
            "background-color" : "#ffa500"
        }, 500).delay(100) 
        .animate({
          "background-color" : "#ffffff"
        })
        // when current `.cell input` element animation completes
        // call `_next` function in `"cells"` queue
        .promise().then(_next)           
      }
    // call first function in `"cells"` queue
    // when all `"cells"` queue functions have been called
    // call `next` function in `"enlighten"` queue
    })).dequeue("cells").promise("cells").then(next)
  }
// call first function in `"enlighten"` queue
})).dequeue("enlighten").promise("enlighten")
// do stuff when all functions in `"enlighten"` and `"cells"`
// queues have been called
.then(function() {
  console.log("all animations complete")
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script   src="http://code.jquery.com/ui/1.12.1/jquery-ui.min.js"   integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="   crossorigin="anonymous"></script>
first board
<div class="board">
  first row
  <div class="row">
    <div class="cell">
      <input type="number" data-column="0" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="1" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="2" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="3" data-line="0">
    </div>
  </div>
</div>
<br>
second board
<div class="board">
  second row
  <div class="row">
    <div class="cell">
      <input type="number" data-column="0" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="1" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="2" data-line="0">
    </div>
    <div class="cell">
      <input type="number" data-column="3" data-line="0">
    </div>
  </div>
</div>
guest271314
  • 1
  • 15
  • 104
  • 177
  • Can I use queue with the $each? like Martin posted? – João Silva Oct 24 '16 at 17:40
  • Yes, you can use `$.each()` or `$.map()`, see [Execute function queue in javascript](http://stackoverflow.com/questions/32028368/execute-function-queue-in-javascript/) , [Want to repeat animation on div for infinity times in jQuery?](http://stackoverflow.com/questions/40068359/want-to-repeat-animation-on-div-for-infinity-times-in-jquery/) – guest271314 Oct 24 '16 at 17:44
  • @JoãoSilva Note, you can also wrap an array in `jQuery()` to iterate the array with `.each()`, e.g., `$([10,20,30]).each(function(index, element) {console.log(element)})` – guest271314 Oct 24 '16 at 17:49
  • You should be able to use `$(arr).each(function(){ enlight($(this)); });` , possibly `$(cells).each()` with you existing `javascript` – guest271314 Oct 24 '16 at 17:57
  • Yes, but with that the 2nd element start animating before the first finish his animation... I needed it to be one by one. – João Silva Oct 24 '16 at 17:58
  • Then use `.queue()`. Can you include `html` at Question? – guest271314 Oct 24 '16 at 18:00
  • html added, I was trying but I didnt figured out how to wrap it with each function – João Silva Oct 24 '16 at 18:06
  • @JoãoSilva See updated post. Are you trying to animate `.cell` elements in sequential order? Are you using `jQuery UI` to animate `background-color`? – guest271314 Oct 24 '16 at 18:17
  • Can you add some comments to the code? I'm not understanding all of it, anyway, should I change the each with this? – João Silva Oct 24 '16 at 18:26
  • Well, I guess its almost what I wanted, but you did it for cells, but my enlight animate the cells one by one, what I want is to animate the arrays one by one, for exemple, I have 1 column and 1 square to animate, when I call them its animating the cells of the column 1 by 1 and the square too but there can be overlapping of animations, since the array of column and square aren't queueing. So, my enlight does that cell animation, I just need to place a order in the each so after the first element is done, to go to the next one. – João Silva Oct 24 '16 at 18:46
  • @JoãoSilva Not certain what you mean? You do not want to animate each `input` element of each `.cell` element? But, animate the entire `.row` element at a single animation? Then animate the next `.row` element when previous `.row` animation completes? Can you create a stacksnippet, jsfiddle http://jsfiddle.net or plnkr http://plnkr.co of your current implementation? – guest271314 Oct 24 '16 at 18:50
  • My function enlight animate 1 array of 9 cells, cell by cell, but my problem here is that I want to animate rows, columns and squares both with 9 cells. The problem is to animate multiple arrays. I need something that wait my function enlight finish with the last cell before move on to the next array. – João Silva Oct 24 '16 at 18:53
  • @JoãoSilva _" I need something that wait my function enlight finish with the last cell before move on to the next array."_ That is what `javascript` at Question achieves. There are two `.board` elements which contain `.row` child elements at `html` at stacksnippets. The second `.row .cell` elements are not animated until the first `.row .cell` animations have all completed. See updated post. – guest271314 Oct 24 '16 at 18:57
  • https://jsfiddle.net/0pmawcvu/ there is a piece of the html but jsfiddle isnt putting the border right... I'm going to take a printscreen of the border so you can understand better – João Silva Oct 24 '16 at 19:01
  • @JoãoSilva You have not included jQuery at jsfiddle. Note also that `.animate()` does not animate colors by default. Where are `checkColumn`, `checkRow`, `checkCell` defined? – guest271314 Oct 24 '16 at 19:03
  • I will check it, there is an image of the border http://imgur.com/a/gkA6e – João Silva Oct 24 '16 at 19:06
  • @JoãoSilva How is border related to Question? Which portion of `javascript` at stacksnippets does not return expected result? – guest271314 Oct 24 '16 at 19:07
  • I updated with the checkRow method... because in jsfiddle It isnt showing the border as it should so there arent squares or rows... just columns – João Silva Oct 24 '16 at 19:08
  • `HTML_LINE` is not defined. Not sure how formatting the `html` is related to original Question? – guest271314 Oct 24 '16 at 19:10
  • `checkColumn` and `checkSquare` are still not defined. – guest271314 Oct 24 '16 at 19:13
  • they are similar, they get an array and return an array in case of all values have been set in that row or square or return null otherwise, the question here is how to make a each for an array with 3 arrays use a function one at a time. – João Silva Oct 24 '16 at 19:19
  • _"the question here is how to make a each for an array with 3 arrays use a function one at a time."_ This is what `.queue(queueName).promise(queueName)` implements. Use `.promise(queueName).then(function)` pattern to call next functions in sequential order when `queueName` functions have all been called. – guest271314 Oct 24 '16 at 19:21
  • So, since it's just one function I could do something like this: if(arr.length !=0){ jQuery.each(arr,function(){ enlight($(this)).promise('test').done(); }).queue('test'); but If I can I have to return something from enlight, right? – João Silva Oct 24 '16 at 19:30
  • Something like that. You cannot chain `.queue()` to `.done()`, though you can call `.queue()` within `.done(function() {// do stuff using .queue()})`. `enlight($(this)).promise('test')` may be ok, though you would still need to `return` the jQuery promise from `enlight` representing the completion of all `cell` animations. You could `return cell.promise()` from `enlight`. `"test"` `queueName` should also be previously defined. Will try to put together a jsfiddle using that pattern. Ah, `.queue()` is chained to `enlight()` call – guest271314 Oct 24 '16 at 19:37
  • I can't chain queue() to enlight it gives a TypeError: queue is not a function – João Silva Oct 24 '16 at 19:46
  • 1
    This awnser is a litle bit overkill for this simple problem – Martin Godzina Oct 24 '16 at 19:59
  • @MartinGodzina What do you mean? – guest271314 Oct 24 '16 at 20:08
  • @JoãoSilva Alternatively, using `$.when.apply()` within `enlight` without adjusting `500` at `duration` of `.animate()` http://plnkr.co/edit/KbeStjyXP16qZ9ReCeAa?p=preview at version 2 – guest271314 Oct 24 '16 at 20:51
  • I see... So, there no otherway to wait for a function to finish inside a each loop, right? – João Silva Oct 24 '16 at 21:07
  • `$.map()` and `$.each()` should return similar result. `$.map()` returns an array. Why do you need to use `$.each()`? Does either plnkr return render effect? – guest271314 Oct 24 '16 at 21:12
  • It worked! but what does apply($, $.map(.. means? the first '$' – João Silva Oct 24 '16 at 21:20
  • @JoãoSilva See [How do you work with an array of jQuery Deferreds?](http://stackoverflow.com/questions/4878887/how-do-you-work-with-an-array-of-jquery-deferreds/) – guest271314 Oct 25 '16 at 04:37
1

The Array type in Javascript does not contain an each function but Jquery does so.

jQuery.each( array, callback )

With this in mind the solution is to use the Jquery each function:

if(arr.length !=0){
    $each(arr,function(){
        enlight($(this));
    });
}

Edit:

You can get more detailed information how to use the JQuery.each function at the officiel docs: http://api.jquery.com/jquery.each/

Martin Godzina
  • 1,470
  • 11
  • 17
  • Can I use queue or another function to wait for enligh finish with the first element before jumping to the next one? – João Silva Oct 24 '16 at 17:41
  • Yes you can. There is allready a nice source at stackoverflow: http://stackoverflow.com/questions/5202403/how-to-add-pause-between-each-iteration-of-jquery-each – Martin Godzina Oct 24 '16 at 17:44
  • But with setTimeout I need to have a timer, that is what im trying to run out... there isnt possible to do a done in each interactionor something? – João Silva Oct 24 '16 at 17:47
  • 1
    You're missing a period – adeneo Oct 24 '16 at 17:47