Aller au contenu

Objet passé en référence


Sujets conseillés

Posté

Bonsoir à tous,

il y a quelque chose que je ne comprends pas sur la façon dont Javascript traite les objets passés dans les fonctions et je ne trouve pas de doc...

J'ai plusieurs fonctions qui font ça en gros :

function fonc_1(obj){

fonc_2(obj);

}

function fonc_2(obj){

setTimeout("alert(obj.src); obj.src = 'truc.jpg'", 5);

}

Donc si ma première image de la page est machin.jpg et que je fais

fonc1(document.images[0]);

j'obtiens le message "machin.jpg" et machin.jpg est transformé en truc.jpg au bout de 5 secondes. Tout va bien.

Par contre, si pendant l'intervalle des 5 secondes j'ai le malheur d'appeler la fonction de nouveau (par exemple fonc1(document.images[1])), au bout des 5 secondes j'obtiens le message "machin.jpg" mais machin.jpg n'est plus transformé en truc.jpg.

Tout se passe comme si l'objet et ses propriétés étaient bien définis au moment de l'éxécution du Timeout, mais que le Javacript s'était emmêlé les pinceaux et ne retrouve plus l'objet dans la page. J'ai tenté des tas de choses pendant 24h, je n'en peux plus là... Merci !

Posté

Hello,

on peut voir la source entière dans une page ? c'est plus facile pour utiliser un débogueur (et te répondre) qu'un fragment de code.

D'instinct comme ça je n'ai qu'une question, à quoi sert fonc_1 ? ^^

Posté

Bonsoir SStephane et merci,

ma fonction 1 (--> details) regarde si telle balise img existe déjà dans la page. Si ce n'est pas le cas, elle la crée et appelle la fonction 2 (--> qz_grayscale_test) en la lui passant en argument :

		var dzidx = 1;
function details(creation_id){

logo = document.getElementById("im_"+creation_id);

if(!logo){

di = document.getElementById("demoimg_");
di.innerHTML += "<img id=\"im_\"+creation_id+"" src=\"image_"+creation_id+".jpg\"/>";

logo = document.getElementById("im_"+creation_id);
qz_grayscale_test(logo);
}

//put the current logo on top of the others
logo.style.zIndex = dzidx;
dzidx++;

}

Remarque: j'ai un peu simplifié les trucs pas importants, j'espère ne pas avoir laissé de petite incohérence

La deuxième fonction regarde juste si l'image correspond à une valeur enregistrée dans un cookie et la passe à une troisième fonction si c'est le cas :

		function qz_grayscale_test(obj){
//see into the cookie if the logo should be black and white
gs = obj.src;
if(gs){
gs = gs.replace(/.*\\/images\\/([a-z]+)\\/[0-9]+\\/([0-9]+)\\/logo.jpg$/g, "$1:$2");

gs = gs.split(":");
if(gs[0]=="quiz") gs[0]=1;
if(gs[0]=="test") gs[0]=2;
if(gs[0]=="poll") gs[0]=3;
gt = qz_cookie_read("qzci_"+gs[0]);
if(gt) {
gt = gt.split(":");
for(gti in gt){
//if we find it the cookie values
if(gt[gti] === gs[1]){
qz_grayscale(obj);
}
}
}
}
}

la fonction 3 (--> qz_grayscale) crée un double de l'image et passe le relais à la fonction 4 (sous Firefox) qui s'exécutera quand ce double sera chargé (.onload) :

		//transform a picture into a black & white version (grayscaling)
function qz_grayscale(oImg){

if(!oImg.grayscaled){

oImg.grayscaled = true;

if(IE){
oImg.style.filter = "progid:DXImageTransform.Microsoft.BasicImage(grayScale=1)";
}
else{
oImg.cloneImg = new Image;
oImg.cloneImg.onload = function(){ qz_grayscale2(oImg); };
oImg.cloneImg.src = oImg.src;
}
}
}

pour finir, la fonction 4 calcule la version noir et blanc du double et doit la mettre dans l'attribut src de l'image d'origine :

		function qz_grayscale2(oImg){

var canvas = document.createElement("canvas");
var canvasContext = canvas.getContext("2d");

imgW = oImg.cloneImg.width;
imgH = oImg.cloneImg.height;
canvas.width = imgW;
canvas.height = imgH;

canvasContext.drawImage(oImg.cloneImg, 0, 0);
var imgPixels = canvasContext.getImageData(0, 0, imgW, imgH);

for(y = 0; y < imgPixels.height; y++){
for(x = 0; x < imgPixels.width; x++){
i = (y * 4) * imgPixels.width + x * 4;
avg = (imgPixels.data[i] + imgPixels.data[i + 1] + imgPixels.data[i + 2]) / 3;
imgPixels.data[i] = avg;
imgPixels.data[i + 1] = avg;
imgPixels.data[i + 2] = avg;
}
}

canvasContext.putImageData(imgPixels, 0, 0, 0, 0, imgPixels.width, imgPixels.height);
oImg.src = canvas.toDataURL();
}

Mais je répète que ça foire **uniquement** quand les fonctions sont re-appelées avant que le onload qui déclenche la 4ème fonction se déclenche. Le timeout que j'ai évoqué avant m'a permis d'agrandir le délai avant l'éxécution de ce onload et constater que c'était bien ce laps de temps qui pose problème.

Dernière chose : dans la 4ème fonction, la preuve qu'il connait l'objet sans pouvoir y accéder directement (uniquement quand les fonctions ont été rappelées) pour lui assigner une nouvelle src, c'est que si je remplace ceci :

oImg.src = canvas.toDataURL();

par cela :

document.getElementById(oImg.id).src = canvas.toDataURL();

là ça fonctionne bien !

Même un alert(oImg.src) dans la 4è fonction me renvoie toujours la valeur actuelle de src (donc ça marche pour "lire") alors que oImg.src = canvas.toDataURL() juste après ne fonctionne pas (donc ça foire pour "écrire").

Alors soit vous me dites que je n'ai pas tout compris au fonctionnement des objets dans les fonctions, soit vous me dites que c'est une histoire de fous et je vous fais une URL pour tester par vous-mêmes :)

Posté

En fait je voulais dire une page en ligne, que je puisse répondre rapidement (si j'en suis capable ;)), le débogueur me permettrait de poser des points arrêt pour parcourir les objets et tout le reste, ça reste très abstrait. Je te fais donc une réponse rapide sans examiner plus le truc.

oImg.cloneImg.onload = function(){      qz_grayscale2(oImg); };

Cette manière de procéder est foireuse, car le oImg passe à moitiée et je trouve ça déjà surprenant, car elle n'est pas sensé passer dans un langage objet normal, onload attend un délégué. Le fait de le déclarer directement (la partie : function(){ qz_grayscale2(oImg); };) devrait créer normalement un nouveau contexte, je trouverai ça logique, d'ailleurs en Java, je pense que tu te fais sanctionner.

Je veux bien une url, j'ai une bonne idée d'où vient ton souci.

Posté

Bonsoir !

Voilà je n'ai pas eu le temps de la faire aujourd'hui mais ça y est :


/>http://quizity.com/webhub/test.html

Si tu appuies sur le bouton 2 avant que l'image 1 soit en noir et blanc, ça l'empêchera de fonctionner.

Merci !

Posté


function details(creation_id){

logo = document.getElementById(creation_id);

if(!logo){

src = "./image/"+creation_id+".jpg";

var img = document.createElement('IMG');
img.setAttribute('id',creation_id);
img.setAttribute('src',src);

di = document.getElementById("demoimg");
di.appendChild(img);

var logo = document.getElementById(creation_id);
//test the creation to know if it has been played and if the logo should be grayscaled
qz_grayscale_test(logo);
}
}

Tu comprendras aisément ton erreur :)

Par ailleurs je comprends mal ta manière de faire à certains endroits :P

Posté

Extraordinaire ! on dirait que tu as trouvé sans forcer en plus, bravo !

Je ne sais pas comment te remercier :D je vais devoir faire des modifs dans plusieurs de mes pages pour m'adapter à ce que tu as trouvé :)

Je ne sais pas ce que tu trouves bizarre, j'ai essayé de rester simple et logique pourtant ? :)

Si c'est le fait de cloner l'image qui te trouble, en fait je fais ça pour avoir la véritable taille de l'image et non celle qui lui est donnée par CSS (offsetheight me renvoie aussi cette taille CSS).

Merci encore!

Posté

Je veux dire que tu as beaucoup de variables globales qui sont en fait locales, la fonction 2 (dont je ne me souviens plus le nom, ne sert effectivement à rien).

Sinon pour trouver rapidement, je n'ai pas grand mérite, dis merci à firebug :)

Posté

Ha mais ça c'est parce que j'ai simplifié le code, toutes ces choses ont une utilité en réalité ;)

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...