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,964
  • 16
  • 66
  • 103

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,614
  • 7
  • 38
  • 72
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
  • 13,826
  • 11
  • 57
  • 119
1

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

Luca
  • 66
  • 2