1

I have multiple canvas elements:

<canvas class="screen" width="250" height="250" data-json="{{json_encode($board)}}"></canvas>

In my javascript I do the following:

var canvas = document.getElementsByClassName('screen');
for (var i = 0; i < canvas.length; i++) {
    var podium = new Image();
    podium.canvas = canvas[i];
    podium.onload = function() {
        var coordinates = JSON.parse(podium.canvas.getAttribute('data-json');
        console.log(coordinates);
        //Later on I add more images or anything else based on coordinates.
    }
    podium.src = 'my_podium_image.jpg';

}

But coordinates always contains the data from the last <canvas> element in my HTML.

However if I put var coordinates = JSON.parse(podium.canvas.getAttribute('data-json'); outside onload and print the output, it prints the data-json attributes from every canvas which is correct, but in the load() function it's still logs only the last canvas' data attribute. (Multiple times, because of the for loop)

I have no idea what's going. :)

Ivanka Todorova
  • 9,533
  • 15
  • 56
  • 97

3 Answers3

3

Your problem is about Javascript Clousure How do JavaScript closures work?

when that function is executed, the value of podium is the last one that was assigned.

You should use a selfexecuted function that keeps the scope of podium

var canvas = document.getElementsByClassName('screen');
for (var i = 0; i < canvas.length; i++) {
    (function(podium) {
        podium.canvas = canvas[i];
        podium.onload = function() {
            var coordinates = JSON.parse(podium.canvas.getAttribute('data-json'));
            console.log(coordinates);
            //Later on I add more images or anything else based on coordinates.
        }
        podium.src = 'my_podium_image.jpg';
    })(new Image())

}
Community
  • 1
  • 1
Pablo Matias Gomez
  • 6,136
  • 7
  • 35
  • 70
1
var canvas = document.getElementsByClassName('screen');

for (var i = 0; i < canvas.length; i++) {
  (function(index) {
    var podium = new Image();
    podium.canvas = canvas[i];
    podium.onload = function() {
    var coordinates = JSON.parse(podium.canvas.getAttribute('data-json');
    console.log(coordinates);

    //Later on I add more images or anything else based on coordinates.
    podium.src = 'my_podium_image.jpg';
  }(i));
}
Carl Edwards
  • 12,599
  • 8
  • 53
  • 105
1

That's because "onload" event is asynchronous when it got fired your loop already reached the end

Luca
  • 66
  • 2