Sara
Sara

Reputation: 489

Home made javascript gallery bug

I've tried to make a photo gallery by myself in Javascript, here is my code:

var images =    [   
                "BAN46",
                "BASTIONE"
                ];

var legendes =  [   
                "exemple \"avec des\" guillemets",
                "legende2"
                ];


var path = '/galerie/';
var nbr = images.length;
var galerie = document.getElementById('sous_galerie');
var bloc_image = document.getElementById('bloc_image');
var nouvelle_image;

for(var i = 0; i < nbr; i++) {
    nouvelle_image = document.createElement('img');
    nouvelle_image.src = path + 'vignettes/' + images[i] + '-vignette.jpg';
    nouvelle_image.alt = images[i];
    nouvelle_image.setAttribute('onclick', 'zoom(' + i + ')');
    galerie.appendChild(nouvelle_image);
}

function zoom(i) {
    var image = document.createElement('img');  
    image.src = path + images[i] + '.jpg';
    image.alt = images[i];
    image.id = images[i];
    image.setAttribute('onclick', 'dispose(' + i + ')');

    var paragraphe = document.createElement('p');
    paragraphe.innerHTML = legendes[i];
    paragraphe.id = legendes[i];

    var ratio = image.height / image.width; 
    if(image.height >= 750) {
        image.height = '750';
        image.width = image.height / ratio;
    }

    image.style.marginTop = 0 - image.height / 2 + 'px';
    image.style.marginLeft = 0 - image.width / 2 + 'px';

    paragraphe.style.width = image.width + 'px';
    paragraphe.style.marginTop = (image.height + 20) / 2 + 'px';
    paragraphe.style.marginLeft = 0 - image.width / 2 + 'px';

    bloc_image.style.width = '100%';
    bloc_image.style.height = '100%';

    bloc_image.appendChild(image);
    bloc_image.appendChild(paragraphe);
}

function dispose(i) {
    bloc_image.removeChild(document.getElementById(images[i]));
    bloc_image.removeChild(document.getElementById(legendes[i]));
    bloc_image.style.width = '0';
    bloc_image.style.height = '0';
}

(sorry the code is in french. If you need comment or precision about the code, don't hesitate to ask me =) )

My problem is, when I click on the vignette, it displays the right image but considers that its width and height are 0px, so the image is correctly displayed but moved south-east because of

image.style.marginTop = 0 - image.height / 2 + 'px';
image.style.marginLeft = 0 - image.width / 2 + 'px';

Moreover, the caption is also moved over the picture. But, when I update the page and retry, this time the picture is correctly displayed and right in the middle, because its width and height values are correct.

It seems that the browser displays the image and caption before loading its properties, and I don't know how to correct this "bug".

Upvotes: 0

Views: 59

Answers (1)

bfavaretto
bfavaretto

Reputation: 71938

You have to wait for the image to finish loading before you can access the dimensions:

function zoom(i) {
    var image = document.createElement('img');  
    image.src = path + images[i] + '.jpg';
    image.alt = images[i];
    image.id = images[i];
    image.setAttribute('onclick', 'dispose(' + i + ')');
    image.onload = function() {
        var paragraphe = document.createElement('p');
        paragraphe.innerHTML = legendes[i];
        paragraphe.id = legendes[i];

        var ratio = image.height / image.width; 
        if(image.height >= 750) {
            image.height = '750';
            image.width = image.height / ratio;
        }

        image.style.marginTop = 0 - image.height / 2 + 'px';
        image.style.marginLeft = 0 - image.width / 2 + 'px';

        paragraphe.style.width = image.width + 'px';
        paragraphe.style.marginTop = (image.height + 20) / 2 + 'px';
        paragraphe.style.marginLeft = 0 - image.width / 2 + 'px';

        bloc_image.style.width = '100%';
        bloc_image.style.height = '100%';

        bloc_image.appendChild(image);
        bloc_image.appendChild(paragraphe);
    }
}

Also, it's good practice to use actual event handlers, instead of creating attributes. For example, replace this:

image.setAttribute('onclick', 'dispose(' + i + ')');

with:

image.onclick = function() {
    dispose(i);
};

(Or use addEventListener, with a proper fallback to attachEvent so it works on oldIE).

When you're inside the for loops, it will need a more complicated syntax (why?). So replace:

nouvelle_image.setAttribute('onclick', 'zoom(' + i + ')');

with:

nouvelle_image.onclick = (function(index){
    return function() {
        zoom(index)
    }
}(i));

Upvotes: 1

Related Questions