image.onload in Firefox

J

jon

Hello,
I've had long standing code that runs in IE, that I'm testing with
firefox unsuccessfully now. The problem seems to be that images that I
dynamically create don't fire their onload event in firefox. The
onload method I assign is never being called. Any ideas why firefox
isn't calling this, or what I can do for a workaround?

Below is approxiatemate code of what I'm doing...


function addImage(obj,isTrue){
alert('add');
alert(obj.id);
// do stuff
}


function main(){
var imageObj = new Array();
var image_src = '/images/someKnownImage.jpg';
var somethingIsTrue = true;

imageObj[imageObj.length] = new Image();
imageObj[imageObj.length-1].id = id;
if(somethingIsTrue){
imageObj[imageObj.length-1].onload = function() {
addImage(this,'true'); }
} else {
imageObj[imageObj.length-1].onload = function() {
addImage(this,'false'); }
}
imageObj[imageObj.length-1].src = image_src;

}
 
R

RobG

jon said:
Hello,
I've had long standing code that runs in IE, that I'm testing with
firefox unsuccessfully now. The problem seems to be that images that I
dynamically create don't fire their onload event in firefox. The
onload method I assign is never being called. Any ideas why firefox
isn't calling this

According to the HTML 4 specification, img elements don't have an
onload attribute.

<URL:http://www.w3.org/TR/html4/struct/objects.html#edef-IMG>


However IE, Opera and Firefox at least seem to have implemented it.

or what I can do for a workaround?

Below is approxiatemate code of what I'm doing...

Your code runs fine for me - check Firefox's JavaScript console.
function addImage(obj,isTrue){
alert('add');
alert(obj.id);

You don't assign an ID, so the above alerts 'undefined' in Firefox and
throws an error in IE.

// do stuff
}


function main(){
var imageObj = new Array();
var image_src = '/images/someKnownImage.jpg';
var somethingIsTrue = true;

imageObj[imageObj.length] = new Image();

Why continually get imageObj.length? It's probably best to use a var
to store the object temporarily, then assign it to the array at the
end.

imageObj[imageObj.length-1].id = id;

You don't assign a value to id, so nothing sensible is assigned to the
value of the image object.

Here's my cleaned-up version, maybe the error will become apparent:

function addImage(obj, isTrue){
alert('add');
alert('id: ' + obj.id
+ '\nisTrue: ' + isTrue );
}

function main(){
var imageObj = new Array();
var image_src = 'a.gif';
var somethingIsTrue = true;
var id = 'blah';

var img = new Image();
img.id = id;
img.onload = (function(bool){
return function(){addImage(this, bool);}
})(somethingIsTrue);
img.src = image_src;
imageObj[imgObj.length] = img;
}

main();
 
P

Pete

function main(){
var imageObj = new Array();
var image_src = 'a.gif';
var somethingIsTrue = true;
var id = 'blah';

var img = new Image();
img.id = id;
img.onload = (function(bool){
return function(){addImage(this, bool);}
})(somethingIsTrue);
img.src = image_src;
imageObj[imgObj.length] = img;
}

Be careful using inline functions. If at any time you need to delete
the image, the image will delete fine, but the browser won't free up
the memory. Bascially the inline function has a reference to the parent
function and the parent function has a reference to the inline
function. So when you try to removeChild() or delete() the memory won't
be freed.

You'll better off not using inline functions at all as good practice.
It can lead to all sorts of nasty memory leaks if you are building any
systems that use lots of dom manipulation.

But I digress :)
 
R

Richard Cornford

Pete said:
function main(){
var imageObj = new Array();
var image_src = 'a.gif';
var somethingIsTrue = true;
var id = 'blah';

var img = new Image();
img.id = id;
img.onload = (function(bool){
return function(){addImage(this, bool);}
})(somethingIsTrue);
img.src = image_src;
imageObj[imgObj.length] = img;
}

Be careful using inline functions. If at any time you need
to delete the image,

Javascript has no mechanism for deleting the image, it has automatic
garbage collection.
the image will delete fine, but the browser won't
free up the memory.

A strange definition of 'delete'.
Bascially the inline function has a reference to the
parent function and the parent function has a reference
to the inline function.

The parent function does not have a reference to the inner function, it
being anonymous. IE's circular reference issue is provoked here by the
Variable object of the outer function still having a reference to the
Image object itself (as its - img - variable). The circle is outer
Variable.img -> Image, Image,onload -> inner function, inner
function.[[Scope]] -> outer Variable. That circle can be broken by
ending the outer function with - imageObj = img = null; -, but IE may
take the assignment of an - id - to the image as an excuse to add a
property to the global object with the name of the - id - and referring
to the Image, forming a second circular reference through the global
object.
So when you try to removeChild() or delete() the memory
won't be freed.

Which environments provide a - delete - function/method? And how would
it be used with javascript where - delete - (being an operator) cannot
be an Identifier name?
You'll better off not using inline functions at all as
good practice.

That would be paranoid and self-destructive. Once the memory leak issue
in IE is understood, along with the mechanism of closures in javascript,
action can be taken to avoid and mitigate the issue.
It can lead to all sorts of nasty memory leaks if you are
building any systems that use lots of dom manipulation.

In this code there is no evidence of any DOM manipulation happening at
all. However, inner function's are nowhere near the only means of
provoking memory leaks in IE. Any chain of references that is circular
and includes a DOM/ActiveX object will hinder the garbage collection of
the objects involved.

For example, an action as apparently simple as defining an element in
the HTML with an ID attribute and an intrinsic event handing attribute
may be enough. As IE will turn the intrinsic event attribute code into a
function that is referred to by a property of the element, IE will use
the ID attribute to create a property of the global object of the global
object which refers to the element, and the global object is referred to
by the internal [[Scope]] property of all functions the circle is:
Element.onevent -> event handler function, event handler
function.[[Scope]] -> global object, global object[id] -> Element.

It is short sighted to think that the issue may be avoided by a blanket
ban on the use of inner functions (particularly as event handlers).

Richard.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top