...

View Full Version : img.complete and DOM



C.O.D.E.N.A.M.E
02-19-2006, 02:57 AM
var imgsCompleted = {
init : function() {

var d=document, img;
if(!d.getElementById || !d.createElement)return;
img = d.body.appendChild(d.createElement("img"));
img.src = "myImage.gif?" + new Date().valueOf();
img.id = "myImg"

if (img.complete) {
// do something
d.body.removeChild(d.getElementById("myImg"));
}
}
}
function imgsCompletedLoaded() {
imgsCompleted.init();
}

window.onload = imgsCompletedLoaded;


The idea is to create images dynamically, check when img complete is true, execute code then remove img from DOM

Is this gonna work? How to do this for eg three images?

KC-Luck
02-19-2006, 06:02 AM
It's a bit more complex then that.
Here's one example on how it could be accomplished.
However, I am not removing the newly created images in this code.


<html>
<head>
<title>[object ImageLoader]</title>
<script>

function ImageLoader(src1, src2) {
this.images = [];
this.loaded = [];
this.load = function(element) {
var d = document;if (!d.createElement) return;
for (var i = 0; i < this.images.length; i++) {
var img = (element||d.body).appendChild(d.createElement("img"));
img.src = (this.baseURI || "") + this.images[i] + "?" + (new Date).valueOf();
img.id = "Image-"+ i;
img.addEventListener ?
img.addEventListner("load", this.onload, false) :
img.attachEvent("onreadystatechange", this.onchange);
img.loader = this;
img = null;
}
}
this.push = function() {
for (var i = 0; i < arguments.length; i++) {
this.images[this.images.length] = arguments[i];
}
}
this.pushCompleted = function(id) {
this.loaded[this.loaded.length] = id || true;
if (this.loaded.length == this.images.length)
(this.onComplete||new Function)(this.loaded);
}
this.onload = function(e) {
e.target.loader.pushCompleted(e.target.id);
e.target.removeEventListener("load", e.target.loader.onload, false);
e.target.loader = null;
}
this.onchange = function(e) {
var target = (e||event).srcElement;
if (/^(complete|loaded)$/i.test(target.readyState)) {
target.loader.pushCompleted(target.id);
target.detachEvent("onreadystatechange", target.loader.onchange);
target.loader = null;
}
}
if (arguments.length)
for (var i = 0; i < arguments.length; i++)
this.push(arguments[i]);
}

var loader = new ImageLoader("image1.gif", "image2.gif");
loader.baseURI = "images/";
loader.onComplete = function(loaded) {
alert(loaded.length + " images loaded successfully.");
}

window.onload = function() {
loader.load(document.body);
}

</script>
</head>
<body>

</body>
</html>

C.O.D.E.N.A.M.E
02-19-2006, 06:37 AM
I tested in Safari/Firefox and got only one error on line


img.addEventListner("load", this.onload, false) :

Error: img.addEventListner is not a function


typo I guess:

img.addEventListener("load", this.onload, false) :


retested in Moz FF 1.5.x Mac

Error:

e.target.loader has no properties

in this codeblock:

this.onload = function(e) {
e.target.loader.pushCompleted(e.target.id);
e.target.removeEventListener("load", e.target.loader.onload, false);
e.target.loader = null;
}

In Safari it worked perfect as soon the images loaded , the alert
Moz FF WIN/MAC has the e.target.loader has no properties
Opera 8.02 Mac: worked but alert showed with some seconds delay after the images loaded
IE 6 WIN loaded twice all 3 images and even duplicated one image whilst reloading, showed then the alert

Kor
02-20-2006, 11:31 AM
onload is an window/frame/iframe event only. You can not attach it to other objects (images...)

I guess that you want to check if an image is really and fully loaded. As far as I know, this is not possible with javascript.

KC-Luck
02-20-2006, 05:47 PM
My appologies, i only tested the IE, and went on luck for gecko based..
here's the fixed code.
And, yes IMAGES do fire ONLOAD event! for gecko/etc.. :)
IE does not fire it, so you look for onreadystatechange


<html>
<head>
<title>[object ImageLoader]</title>
<script>

function ImageLoader(src1, src2) {
this.images = [];
this.loaded = [];
this.load = function(element) {
var d = document;if (!d.createElement) return;
for (var i = 0; i < this.images.length; i++) {
var img = (element||d.body).appendChild(d.createElement("img"));
img.src = (this.baseURI || "") + this.images[i] + "?" + (new Date).valueOf();
img.id = "Image-"+ i;
img.addEventListener ?
img.addEventListener("load", this.onload, false) :
img.attachEvent("onreadystatechange", this.onchange);
img.loader = this;
img = null;
}
}
this.push = function() {
for (var i = 0; i < arguments.length; i++) {
this.images[this.images.length] = arguments[i];
}
}
this.pushCompleted = function(id) {
this.loaded[this.loaded.length] = id || true;
if (this.loaded.length == this.images.length)
(this.onComplete||new Function)(this.loaded);
}
this.onload = function(e) {
var target = e.currentTarget;
target.loader.pushCompleted(target.id);
target.removeEventListener("load", target.loader.onload, false);
target.loader = null;
}
this.onchange = function(e) {
var target = (e||event).srcElement;
if (/^(complete|loaded)$/i.test(target.readyState)) {
target.loader.pushCompleted(target.id);
target.detachEvent("onreadystatechange", target.loader.onchange);
target.loader = null;
}
}
if (arguments.length)
for (var i = 0; i < arguments.length; i++)
this.push(arguments[i]);
}

var loader = new ImageLoader("image1.gif", "imag2.gif");
loader.baseURI = "images/";
loader.onComplete = function(loaded) {
alert(loaded.length + " images loaded successfully.");
}

window.onload = function() {
loader.load(document.body);
}

</script>
</head>
<body>

</body>
</html>

changed e.target => e.currentTarget
and fixed the typo of addEventListener

C.O.D.E.N.A.M.E
02-20-2006, 08:22 PM
thanks, will continue testing.

IE actually seemed to load twice the images strange if considering they are not hard-coded in the HTML, they get appended through DOM ?? So removing the images from the DOM seems necessary after checking DOM or add maybe for IE 6 WIN a el.style.visibility = hidden ?

I have in one script that waits for an image to really have loaded to execute a script, in this case could we use this too?


myFunctionToBeExecuted = function(){
// check if has loaded allready, and if so, abandon it.
if( this.hasloaded ) { return; }
// if not, mark it as having allready run
this.hasloaded = true;

// rest of function
}

// this works for IE to check images have loaded
document.getElementById('myImage').hasloaded = false;
document.getElementById('myImage').onload = myFunctionToBeExecuted;

if(document.getElementById('myImage').complete) {
document.getElementById('myImage').onload();
}

felgall
02-20-2006, 09:34 PM
An onload event handler is only associated with images in some browsers. Only the window has that event for all browsers.

Also depending on the browser where the image can't be loaded img.complete will either be set true once the browser gives up trying to load the image or will never be set true.

KC-Luck
02-20-2006, 11:07 PM
I guess this fellow doesn't have it right either?
http://www.panoramio.com/blog/onload-event/
just one of quick google scans :)

so with the direct .onload function method =


<html>
<head>
<title>ImageLoader 2</title>
<script>

function ImageLoader() {
this.all = [];
this.loaded = [];
this.test = function(src) {
if (this.all.length == this.loaded.length)
(this.onComplete||new Function)(this.loaded);
}
this.push = function() {
for (var i = 0; i < arguments.length; i++)
this.all[this.all.length] = arguments[i];
}
this.load = function(element, baseURI) {
for (var i = 0; i < this.all.length; i++) {
var img = document.createElement("img");
img.onload = function(e) {
if (this.loader) {
this.loader.loaded[this.loader.loaded.length] = this.src;
this.loader.test();
this.loader = null;
}
}
img.loader = this;
img.src = (baseURI||"") + this.all[i];
(element||document.body).appendChild(img);
}
}
}

var loader = new ImageLoader();
loader.push("image1.gif", "image2.gif");
loader.onComplete = function(loaded) {
alert(loaded.length +" images loaded.");
}

onload = function() {
loader.load(document.body, "images/");
}

</script>
</head>
<body>

</body>
</html>

KC-Luck
02-20-2006, 11:52 PM
Or, for the greatly twisted, you could use the following code:


<html>
<head>
<title>Loader</title>
<script src="Loader.js"></script>
<script>

var scriptLoader = new Loader("script");
scriptLoader.push("script1.js", "script2.js");
scriptLoader.onComplete = function(loaded) {
alert(loaded.length + " scripts loaded successfully.");
}

var imageLoader1 = new Loader("img");
imageLoader1.push("image1.gif", "image2.gif");
imageLoader1.onComplete = function(loaded) {
alert(loaded.length + " images loaded successfully.");
}

var imageLoader2 = new Loader("img", {
all: ["image1.gif", "image2.gif"],
onComplete: function(loaded) {
alert(loaded.length + " images also loaded successfully.");
}
});


onload = function() {
var body = document.getElementsByTagName("body").item(0);
var head = document.getElementsByTagName("head").item(0);
scriptLoader.load(head, "scripts/");
imageLoader1.load(body, "images/");
imageLoader2.load(body, "images/");
}

</script>
</head>
<body>
</body>
</html>

with this generic Loader object.


function Loader(tag, instance) {
this.all = [];
this.loaded = [];
this.tag = (tag||"img");
this.test = function(element) {
this.loaded[this.loaded.length] = element.src;
if (this.all.length == this.loaded.length)
(this.onComplete||new Function)(this.loaded);
}
this.push = function() {
for (var i = 0; i < arguments.length; i++)
this.all[this.all.length] = arguments[i];
}
this.load = function(element, baseURI) {
for (var i = 0; i < this.all.length; i++) {
var node = document.createElement(this.tag);
node.onreadystatechange = function(e) {
if (this.loader && this.readyState == "complete") {
this.loader.test(this);
this.loader = null;
}
}
node.onload = function(e) {
if (this.loader) {
this.loader.test(this);
this.loader = null;
}
}
node.loader = this;
node.src = (baseURI||"") + this.all[i];
(element||document.body).appendChild(node);
}
}
if (instance)
for (var property in instance)
this[property] = instance[property];
}

Please try out on various browsers, and let me know?
Already tested fine on:
IE 6.0 XP SP2
Firefox 1.5.0.0

Thanks.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum