0

I've been working with CoffeScript and JQuery. I need to create a simple animation.

I tried using delay and I didn't understand it at all, so I read a question before:

Link from this page

So I decided to use queues; the main problem is that just the last element of the animation is considereded although the queue has more elements inside.

I Hope you could help me :), You can find the codes below.

All the elements inside the queue (CoffeScript).

    for proc in listaDeProcesos
    id = proc.id
    nombre = proc.nombre
    idFinal = "#{id}#{nombre}"
    tiempo = parseInt(proc.tejecucion)
    $("#animacion").queue('chain',(next)->
            $("##{idFinal}").fadeOut(tiempo,->
                    next()
                )
        )

The dequeue function call:

        $("#animacion").dequeue('chain')
Community
  • 1
  • 1
Juan Reséndiz
  • 97
  • 1
  • 1
  • 11
  • May be your indentation is somehow messed up so the loop is exhausted and the rest of the code is using only the last value of `proc` (outside of the loop). – jdb Mar 29 '13 at 19:39
  • I don't get it. I've solve it using an auxiliar queue and adding the effects individually. Thanks I'll read my code again, the indentation is a headache sometimes. – Juan Reséndiz Mar 29 '13 at 19:49

2 Answers2

1

Congratulations! Butting your head against this is a rite of passage for all JavaScript (or CoffeeScript) developers. You were bound to run into it eventually. The explanation is twofold:

  • JavaScript (and CoffeeScript) variables are function scoped, not block scoped
  • Closures

Basically, each iteration creates a function with a reference to the variable idFinal, not the value of idFinal at that iteration through the loop. So when later iterations change idFinal, it changes it for all the functions that you've created. See here for a simpler example of the behavior:

JavaScript closure inside loops – simple practical example

One way to get around this in CoffeeScript is to introduce a new scope with the do construct:

for {id, nombre, tejecucion} in listaDeProcesos
  do (idFinal = "#{id}#{nombre}", tiempo = parseInt(tejecucion)) ->
    $("#animacion").queue 'chain', (next) ->
      $("##{idFinal}").fadeOut tiempo, next
Community
  • 1
  • 1
Ian Henry
  • 22,255
  • 4
  • 50
  • 61
  • Wow it seems I have a lot of things to learn about JS and CoffeeScript, I've solved the problem using other method, thanks anyway I'll check the link your giving in order to improve myself :) – Juan Reséndiz Mar 29 '13 at 19:57
0

I found an alternative solution, in case someone else has the same problem I write the code below, Thanks anyway :)

All the code is in coffeescript.

Animated Element class

class animatedElement
constructor: (@element,@time) ->
showInfo: ->
    alert ("#{@element} >> #{@time}")

Iteration of what you want to animate:

for proc in listaDeProcesos
    id = proc.id
    nombre = proc.nombre
    idFinal = "#{id}#{nombre}"
    tiempo = parseInt(proc.tejecucion)
    elemento = new animatedElement($("##{idFinal}"),tiempo)
    queue.push(elemento)

Auxiliar function

showAnimation = ()->
if (queue.length > 0)
    tiempo = queue[0].time
    (queue.shift().element).fadeOut(tiempo, showAnimation)

And finally you just need to call

showAnimation()

I hope it could be useful for someone else :)

Juan Reséndiz
  • 97
  • 1
  • 1
  • 11