0

I have small application in Famo.us framework. I have added four images in mainContext with draggable modifier using four loop. I want fire an event when user drag the event for that I have added following code.

var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var Transform = require('famous/core/Transform');
var MouseSync = require("famous/inputs/MouseSync");
var StateModifier = require('famous/modifiers/StateModifier');
var Draggable = require("famous/modifiers/Draggable");
var ImageSurface    = require('famous/surfaces/ImageSurface');
var Transitionable = require("famous/transitions/Transitionable");
var SnapTransition = require("famous/transitions/SnapTransition");
Transitionable.registerMethod('snap', SnapTransition);
// create the main context
var mainContext = Engine.createContext();
var mouseSync = new MouseSync();

var isPlus;
var isFirst = true;

var oldValues = [];
var mySurfaces=[];
var draggables = [];
var myModifiers= [];

var images = [
    ['img/svelteMan.png', -0.4375 * window.innerWidth, -1.5 * window.innerWidth], 
    ['img/swimmer.png', 0 * window.innerWidth, -0.96875 * window.innerWidth], 
    ['img/soccerPlayer.png', -0.21875 * window.innerWidth, -0.984375 * window.innerWidth], 
    ['img/breakDancer.png', 0 * window.innerWidth, -0.6875 * window.innerWidth]
];

for(var i=0;i<images.length;i++) {
    var mySurface = new ImageSurface({ });
    mySurface.setContent(images[i][0]);

    var myModifier = new StateModifier({
        origin: [0.5, 0.5]
    }); 

    var draggable = new Draggable({ });
    mySurface.pipe(draggable);
    mySurfaces.push(mySurface);     
    myModifiers.push(myModifier);
    draggables.push(draggable);

    mainContext.add(draggables[i]).add(myModifiers[i]).add(mySurfaces[i]);

    var oldValue =0;
    oldValues.push(oldValue);
}

ActivateEvent();
function ActivateEvent(){
    for(var i=0;i<images.length;i++) {  
        draggables[i].on('update', function (data) {
            MakeMove(i);
        }); 
    }
};

function MakeMove(i) {
    //alert(i);
    if (oldValues[i] > draggables[i].getPosition()[0]) {
        myModifiers[i].setTransform(Transform.rotateZ(-0.1));
    } else {
        myModifiers[i].setTransform(Transform.rotateZ(0.1));
    }
    oldValues[i] = draggables[i].getPosition()[0];      
}

I have added onUpdate event of Draggable as following :

for(var i=0;i<images.length;i++) {  
    draggables[i].on('update', function (data) {
        MakeMove(i);
    }); 
}

But I am getting error saying draggables[i] is not defined

If I want to call an event of Third image on draggable then how to call event? How to register an events when surfaces added in for loop?

Thanks

Cerbrus
  • 70,800
  • 18
  • 132
  • 147
ghanshyam.mirani
  • 3,075
  • 11
  • 45
  • 85
  • Is that `for` loop in your last code block in the same file as the rest of your code? – Cerbrus Jun 03 '14 at 07:09
  • @Barmar: That's not the issue, here. The error is about `draggables[i]` being undefined, which has nothing to do with that _"infamous Loop issue"_ So, this mark as duplicate is incorrect. – Cerbrus Jun 03 '14 at 07:21
  • Thanks, misunderstood the question. – Barmar Jun 03 '14 at 07:23
  • 1
    What line is the error happening on? Is it `draggables[i].on(...)` or is it `if (oldValues[i] > draggables[i].getPosition()[0])`. If it's the latter, then it IS the infamous Loop issue. – Barmar Jun 03 '14 at 07:26
  • ya i am getting an error on draggables[i].on(...) – ghanshyam.mirani Jun 03 '14 at 07:29
  • @ghanshyam.mirani: Can you answer the question in my first comment, please? – Cerbrus Jun 03 '14 at 07:30
  • @Cerbrus yes for loop is in code first code block. – ghanshyam.mirani Jun 03 '14 at 07:34
  • @ghanshyam.mirani, before you start the loop, what is the output of `console.log(draggables);`? Does this array have any element at that point? – rdleal Jun 03 '14 at 07:39
  • @ghanshyam.mirani As @rbyte asked, it's important to know if the second snippet of for loop is the same one from the `ActiveEvent` function (I assume it is). The other assumption is that the first code block is all in one file and it's the ONLY code in that file. The worry is that draggables might have a scoping issue or have been changed somewhere (if we're not seeing all the code) before the `ActiveEvent` runs. I've tried simplifying in this [jsbin](http://jsbin.com/gipaz/1/edit) but I only get `draggables[i] is undefined` inside the `MakeMove` function. – David Atchley Jun 03 '14 at 07:54

2 Answers2

0

Add a closure:

var cl = function(n) {
    return function(data){
        MakeMove(n);
    };
};

for(var i=0;i<images.length;i++)
{   
    draggables[i].on('update', cl(i)); 
}

Hope it helps.

rdleal
  • 987
  • 5
  • 15
  • How does this fix the fact that `draggables[i] is not defined`? – Cerbrus Jun 03 '14 at 07:07
  • I suspect this will fix the OP's problem. The problem is that the original code is calling `MakeMove(i)`, and `i` is too high because it's the last value of `i` in the `for` loop. – Barmar Jun 03 '14 at 07:29
  • @Barmer closure will work fine in this case as it will store current context not the last value. same type of Fiddle example(http://jsfiddle.net/f65AZ/)[http://jsfiddle.net/f65AZ/] – Akhlesh Jun 03 '14 at 07:33
  • @Barmar, yes. This is why I didn't update the answer yet. As the OP didn't specify the line of the error, I (maybe wrongly) assumed it was inside the `MakeMove`. – rdleal Jun 03 '14 at 07:34
0

You have a closure problem. Take a look of this:

var draggables = [];
for(i=0;i<10;i++) {
    var draggable = new Draggable({ });
    draggables.push(draggable);
}

ActivateEvent();

function ActivateEvent(){

    for(var i=0;i<10;i++) {  
       setTimeout(function() {
           MakeMove(i);         
       }(i),0);        //<----- notice the (i), this how you can send the correct loop for     MakeMove function, without that (i) the anonymous function scope breaks the loop 
     }
}

function MakeMove(i) {
 console.log(draggables[i]); //==> this outputs the draggables
}

Maybe you can try this:

draggables[i].on('update', function (data) {
    MakeMove(i);
}(i));      <----- now the loop is send to makeMove