1

This answer gives a helpful explication of how to add a "link" (really, an event that redirects to a URL) to a particular object rather than to all objects on the canvas:

How to add URL to an image in Fabric.js?

However, when placed inside a loop that generates multiple objects, it only links to the last object created's value.

Here's an example:

for (var p = 0; p<2; p++) {
  var object = new fabric.Circle({ radius: 10, top: 10 + 20 * p, left: 10 });
  object.on('selected', function() {
    window.location.href = "mylink" + "/" + p;
  })
  canvas.add(object);
}

This will have both objects linking to "mylink/1", when what I want is for the first object to link to "mylink/0" and the second to link to "mylink/1".

My Javascript skills are stuck in 1999, but this looks like a lazy loading problem to me. How do I force the object created from each loop to have its own function?

Community
  • 1
  • 1
Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235

1 Answers1

2

It does appear to be about lazy evaluation/closures.

Using this beautiful answer (Javascript: Creating Functions in a For Loop), I was able to craft a solution. Posting here in the hopes it will be useful to others. See the linked answer for why it works.

  var fxnArr = [];
  for( var p = 0; p < rows.length; p++ ) {
    fxnArr[fxnArr.length] = (function(val) { return function(){  
        window.location.href = "mylink" + "/" + val; 
    } })(p);
  }
  for (var p = 0; p<2; p++) {
    var object = new fabric.Circle({ radius: 10, top: 10 + 20 * p, left: 10 });
    object.on('selected', fxnArr[p] );
    canvas.add(object);
  }
Community
  • 1
  • 1
Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • 1
    an easier solution is to use `let p` rather than `var p` - run it through a transpiler for internet exploder and voilà – Jaromanda X Dec 21 '16 at 02:35
  • 1
    @JaromandaX - Yep. These days when ES6 is supported just about everywhere, using `let` is the way to go. As [this Mozilla Hacks post](https://hacks.mozilla.org/2015/07/es6-in-depth-let-and-const/) explains: "Loops of the form `for (let x...)` create a fresh binding for `x` in each iteration." – Ted Hopp Dec 21 '16 at 02:54