For the record, I'm not too great at Java yet, I'm just starting out with it. Currently, I'm working on a small personal project that randomly displays images from a folder for 5 seconds before transitioning to another one. I'd like to add as many images as possible, but once I make an array of over 100+ objects, managing it, as well as the files, becomes quite a chore, especially if I want to start rearranging files or add/remove some.
I've already had to start renaming the files to sequential numbers to get the random cycling to work, which has been a chore in it's own, so I was curious if there was a way to at least shorten the array and have it cycle through the files. Or maybe there's an easier solution that doesn't require the array at all since the files are named sequentially with numbers.
This is what the code looks like so far:
var delay=5000 //set delay in miliseconds
var curindex=0
var randomimages=new Array()
randomimages[0]="1.png"
randomimages[1]="2.jpg"
randomimages[2]="3.png"
randomimages[3]="4.png"
randomimages[4]="5.png"
randomimages[5]="6.png"
randomimages[6]="7.png"
randomimages[7]="8.jpg"
randomimages[8]="9.png"
randomimages[9]="10.png"
// Cut out the 100 extra lines
// Continues like this for multiple lines and variates between PNG and JPG images
randomimages[103]="104.jpg"
var preload=new Array()
for (n=0;n<randomimages.length;n++)
{
preload[n]=new Image()
preload[n].src=randomimages[n]
}
document.write('<div><img name="defaultimage" src="'+randomimages[Math.floor(Math.random()*(randomimages.length))]+'"></div>')
function rotateimage()
{
if (curindex==(tempindex=Math.floor(Math.random()*(randomimages.length)))){
curindex=curindex==0? 1 : curindex-1
}
else
curindex=tempindex
document.images.defaultimage.src=randomimages[curindex]
}
setInterval("rotateimage()",delay)
Any help is appreciated.
Try this code:
var delay = 5000, //set delay in miliseconds
count = 104,
curindex = Math.floor(Math.random() * count),
preload = [],
img;
for (var n = 1; n <= count; n++) {
img = new Image();
img.src = n + '.png';
preload.push(img);
}
document.write('<div><img name="defaultimage" src="' + (curindex + 1) + '.png"></div>')
function rotateimage() {
var tempindex = Math.floor(Math.random() * count);
if (curindex === tempindex) {
curindex = (curindex === 0 ? 1 : curindex - 1);
} else {
curindex = tempindex;
}
document.images.defaultimage.src = (curindex + 1) + '.png';
}
setInterval("rotateimage()", delay);
There's no need to have an array like you said.
Related
I have a JSON file which stores an array of picture URLs. I want to rotate through these links, changing the background of a div every 4 seconds.
I'm having no trouble accessing the JSON file or changing the background of the div. However, I can't seem to figure out how to restart at the beginning of the array after every picture has been shown.
How should I approach this problem?
$.getJSON(json, function (data) {
var arr = $.map(data, function (el) { return el; })
, i = 0;
var changeObj = function() {
i++;
var url = 'url("' + arr[i].url + '")';
$this.css({
backgroundImage: url
});
};
setInterval(changeObj, 4000);
});
Here's a demo
Let's assume your have already parsed your JSON into an array of URLs called myPictureArray and you have written a function called swapInNewPicture, which takes a URL of an image as its argument. (I'm not going to write these functions for you.)
var rotatePictures = function (arr) {
var length = arr.length
, i = 0;
setInterval(function () {
i = (i + 1) % length;
swapInNewPicture(arr[i]);
}, 4000)
}
Now, all you have to do is call rotatePictures(myPictureArray) after you finish parsing your JSON.
Use the modulus operation so it wraps around when it reaches the end of the array. Replace:
i++;
with:
i = (i + 1) % arr.length;
This is basically equivalent to:
i++;
if (i == arr.length) {
i = 0;
}
BTW, you can simplify the setInterval call to:
setInterval(changeObj, 4000);
I have the current JavaScript problem. I have four divisions next to each other on my website that constantly rotate images on a 10 seconds interval. I need these intervals to keep rotating images at the current interval but start 5 seconds apart from each other in order to obtain a nice waterfall effect. How can I accomplish this using JavaScript?
image of how it looks on my websites' header
This is an example of the code I am currently using to display a single division and handle the rotation of the images.
<div class = "TestRotator">
<img src="http://bushveld.info/wp-content/uploads/2013/07/image1.png" alt="rotating" width="100" height="232" id="rotator">
<script type="text/javascript">
(function () {
var rotator = document.getElementById('rotator'); // change to match image ID
var imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/';
var delayInSeconds = 5;
// set number of seconds delay
// list image names
var images = ['image2.png', 'image3.png', 'image4.png'];
var num = 0;
var changeImage = function () {
var len = images.length;
rotator.src = imageDir + images[num++];
if (num == len) {
num = 0;
}
};
setInterval(changeImage, delayInSeconds * 1000);
})();
</script>
</div>
I've fiddled it a lot! (I changed it big time.)
chenged setInterval() with setTimeout() and many others.
Is this what you wanted?
PS: state holds the 1st image to which the imgs change. and the difference in the timeout (200 milliseconds is in order to just to make some difference in between them, yuo can change it to a round number if you want to).
If I've understood your question correctly, you need something like this:
window.onload = function () {
var // Customable parameters
imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/',
interval = 2, // Interval between "flushes" in seconds. Must be > speed * maxScreens
speed = 0.1, // "Flush" speed in seconds
maxScreens = 4, // amount of used image tags
images = 4, // amount of image sources, can be > maxScreens
dir = 1, // 1 = from left to right, -1 = from right to left
// Program
flush,
target = (dir > 0) ? 1 : maxScreens,
targetOrigo = target,
changeImage = function() {
var img = document.getElementById('rotator' + target),
id = parseInt(img.src.substr(img.src.length - 5, 1), 10) - dir;
if (id < 1) {
id = images;
}
if (id > images) {
id = 1;
}
img.src = imageDir + 'image' + id + '.png';
if (target !== maxScreens - targetOrigo + 1) {
target += dir;
setTimeout(changeImage, speed * 1000);
} else {
target = targetOrigo;
setTimeout(runRotation, interval * 1000);
}
return;
},
runRotation = function () {
setTimeout(changeImage, speed * 1000);
};
setTimeout(runRotation, 1000);
}
A live demo at jsFiddle
Notice, that I've put the function at window.onload, looks better when all the images are already loaded, before the rotation starts.
The snippet doesn't use setInterval() at all, instead it's based on nested setTimeout()s. This way you can avoid a mess, which you might get (depends on used browser), if user visits at other tab and then comes back to your site.
You can play with interval, "flush" speed, number of images you have on the rotation and even how many different images you like to use (max. = 9). You can also switch the direction of the rotation.
If you want to avoid two similar images to be shown at the same time, you can add image5.png to your image folder, and set images = 5.
Also version using an image source array available.
Thanx alot for the input. I solved this issue by adapting the code in this manner...
(function() {
var rotator3 = document.getElementById('rotator3'); // change to match image ID
var imageDir = 'http://bushveld.info/wp-content/uploads/2013/07/';
// set number of seconds delay
// list image names
var images = ['image2.png', 'image3.png', 'image4.png', 'image1.png'];
// don't change below this line
var num = 0;
var changeImage = function()
{
var len = images.length;
rotator3.src = imageDir + images[num++];
if (num == len)
{
num = 0;
}
};
function SwImg() {
var rotate = setInterval(changeImage, 20000);
}
setTimeout(SwImg,15000);
})();
This tweak basically creates an initial delay of 5++ seconds at each division with the standard 20 seconds delay interval between switches, rotating each image in each division 5 seconds after the other. Here is a link to the website , will be done end of this week. Thanks again for the input, really awesome and creative ways of solving this issue!
Cheers
okay so i want if my counter reaches the maximum count, it starts over, with the default counter number which is 0 here is my code:
var picCount = 0; // global
var maxCount = 4;
//Pictures, to add more then 4 pics, add var picFive = "link to image here", var picSix ="bla", you get it.. add in picArray ,picFive and ,picSix
//To change the time delay, change it at the body onload and on the setTimeout
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray = [picOne, picTwo, picThree, picFour]
//
// gets next picture in array
function nextPic() { // check if adding 1 exceeds number of pics in array
if (picCount.length < maxCount.length) {
picCount = (picCount + 1 < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
} else {
picCount = (picCount - maxCount < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
}
}
okay so i hope you guys can help me with this..
That's a lot of messy code.
My fix for an implementation would probably look something like this:
var currentPic = 0;
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray= [picOne,picTwo,picThree,picFour]
function nextPic() {
if (currentPic < picArray.length) {currentPic++;}
else {currentPic = 0;}
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
// repeat this every 10 seconds.
setTimeout('nextPic()',10 * 1000)//setTimeout is here
}
Despite many other issues which I am sure are present in your code, I believe this line is the cause of your particular problem addressed in the question:
if (picCount.length < maxCount.length) {
maxCount and picCount are just numbers. They do not have a length property. Change it to this:
if (picCount < maxCount) {
var currentPic = 0;
var picArray= ["http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg",
"http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png",
"http://www.mupload.nl/img/rl6zeofbb.png",
"http://www.mupload.nl/img/rl6zeofbb.png"];
function nextPic() {
(currentPic < picArray.length) ? currentPic++ : currentPic = 0;
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
}
setTimeout('nextPic()',10 * 1000);
I made a few changes that make your code cleaner.
Some tips:
No need to store your image URLs in vars before putting them in the array. Just initialize your array with them.
Don't repeat yourself. Whenever you find yourself using the exact same code in multiple places, you probably need to rethink how you are approaching the problem.
Look up the "ternary operator". In my opinion it makes simple conditional statements easier to read.
No need to use maxCount - the max count will be the length of your picArray.
Although not usually required, try to end all statements with a semicolon.
Don't mind the elitist attitude some people have, but at the same time, try to research as much as you can before asking a question.
How to set interval or may be timeout through the array, to produce effects for the element every 2 sec for example the 1-st idea is to programm something like this:
for (photoKey in arrBigPhotoes) {
setInterval(function() {
// alert(arrBigPhotoes[photoKey]);
document.getElementById("big_photo").src='/upload/images/'+arrBigPhotoes[photoKey];
}, 2000);
}
But it didn't work properly. May be someone can help me with this task I'll be extremely glad.
I'm also have a jQuery - the resolution may be through this library, but without any plug-ins.
Thanks.
Try something like this -
var photos = ['1.jpg', '2.jpg', '3.jpg'];
var photo_index = 0;
function switchPhoto() {
photo_index = (photo_index + 1) % photos.length;
document.getElementById('big_photo').setAttribute('src', '/upload/images/' + photos[photo_index]);
}
setInterval(switchPhoto, 2000);
You should probably put this inside some kind of document ready event handler
I would suggest you pre-load the images you are trying to display. If the user is on a slow connection, your approach would fail.
var images = new Array();
var counter = 0;
var image = document.createElement("img");
image.onload = function() {
counter++;
};
image.src = <url>;
images.push(image);
The counter is there so that you can determine when all images are properly loaded. Let's say you have six images, then, in your "intervaled" function, you would immediately return if counter < 6.
Your "switcher" function could look this way
var i = 0;
setInterval(function() {
if (counter < 6) return;
i = (i+1) % images.length;
document.getElementById("big_photo").src = images[i].src;
}, 2000);
I have to process loads of images. First, I need to check if the size of the image is greater than 50x60 and appropriately increasing the counter of bad images.
The problem I have is that the speed of n.width / n.height on Internet Explorer 8 is extremely low. I checked n.offsetWidth, n.clientWidth but they are all the same speed-wise. I cannot use n.style.width though, because this value is not always set on the <img /> tags that I'm interested in.
Consider following code:
Javascript
var Test = {
processImages: function () {
var fS = new Date().getTime();
var minimagew = 50,
minimageh = 60;
var imgs = document.getElementsByTagName('img');
var len = imgs.length,
isBad = 0,
i = len;
while (i--) {
var n = imgs[i];
var imgW = n.width;
var imgH = n.height;
if (imgW < minimagew || imgH < minimageh) {
isBad++;
}
}
var fE = new Date().getTime();
var fD = (fE - fS);
console.info('Processed ' + imgs.length + ' images in '
+ fD + 'ms. ' + isBad + ' were marked as bad.');
}
};
HTML
<img src="http://nsidc.org/images/logo_nasa_42x35.gif" />
[snip 9998 images]
<img src="http://nsidc.org/images/logo_nasa_42x35.gif" />
Code produces following output parsing 10k images (3 different Ctrl+F5s)
FF: Processed 10000 images in 115ms. 10000 were marked as bad.
FF: Processed 10000 images in 99ms. 10000 were marked as bad.
FF: Processed 10000 images in 87ms. 10000 were marked as bad.
IE8: Processed 10000 images in 206ms. 10000 were marked as bad.
IE8: Processed 10000 images in 204ms. 10000 were marked as bad.
IE8: Processed 10000 images in 208ms. 10000 were marked as bad.
As you can see the code in FF 3.6 is twice faster than the code executed in IE8.
To prove that the issue is really related to the speed of browser dimension property, if I change: n.width and n.height to constants, so we'll have:
var imgW = 43;
var imgH = 29;
I get following results:
FF: Processed 10000 images in 38ms. 10000 were marked as bad.
FF: Processed 10000 images in 34ms. 10000 were marked as bad.
FF: Processed 10000 images in 33ms. 10000 were marked as bad.
IE8: Processed 10000 images in 18ms. 10000 were marked as bad.
IE8: Processed 10000 images in 22ms. 10000 were marked as bad.
IE8: Processed 10000 images in 17ms. 10000 were marked as bad.
That's right! When we skip <img /> dimension check (call to node.width / node.clientWidth etc), IE8 actually performs better than Firefox.
Do you have any ideas why does it take so long for IE to check the size of the image and eventually how to improve the performance of this check?
Well your code is pretty basic. The only thing you can optimize is how you check dimensions:
if (n.width < minimagew || n.height < minimageh) {
isBad++;
}
In this way if the width of an image is wrong, the height won't be accessed. It will make your code 1.5-2x faster for images with bad width.
But my guess is that you don't actually need 10 000 images as part of your website. In this case you can do your check on Image objects instead of <img> elements.
loop {
var img = new Image();
img.src = "http://nsidc.org/images/logo_nasa_42x35.gif";
}
This will make your code 2x faster in IE 8 and 10x faster in FF.
Making these changes gave the following improvements on my computer (demo):
FF: 200 ms -> 7 ms
IE: 80 ms -> 20 ms
In other words you ask why browser A takes longer time than browser B to do exactly the same ting.
Well, they DO NOT do the same thing. You write in your script what you want to happen, and the browser of your choice tries it's best to makes that happen, but you have little or no control over how it does it.
The browsers are written by different teams with different philosophies of how to do things. Your 20-something-line-script could require 10000 cpu-cycles in browser A and 50000 in browser B depending on how the code of the browser is written and the inner workings of the browser.
To give a detailed answer why IE8 is slower compared to FF in this case one has to look under the hood whats going on. Since the source code for IE8 isn't publicly available we can't look there and I'm not aware if there is any documentation that is detailed enough to tell what's going on.
Instead I give you an example of how two different philosophies of how to do things greatly effects the time to produce the same end result. Note: This is an example and any resemblance with the real world is purely coincidental.
What to do:
get the dimensions of an image.
Team A:
Load file from specified source
decode image into memory
return width and height of the image
Nothing wrong with that, is it? It does return the width and height of the image. Can team be do it better?
Team B:
Load the first 1024 bytes of file into memory
Detect image format
is it jpeg? get header FFC0, save width and height
is it png? locate header, save width and height
is it gif? locate header, save width and height
return width and height of the image
Their code also returns the width and height of the image, but they do it in a different way that is several magnitudes times faster than the code that team A wrote: Only the beginning of the file is loaded into memory, and the dimensions is taken from the header without decoding the image. It saves bandwidth, memory and time.
So, which one is the best? The code from Team A or Team B? Think of that for a moment while both teams run their code against 100 000 images.... It might take a wh... oh, team B is already finished! They say that 10% of the images was smaller than 50x60 pixels, and that they couldn't open 3 of them. How about team A then? Looks like we have to wait a while... a cup of coffee maybe?
[10 minutes later]
I guess that you think team B wrote the best code, am I right or am I right?
Team A says 8% of the images was smaller than 50x60 pixels. Strange, that wasn't what team B said. Team A also says that they couldn't get the dimension of 20% of the images because those files where corrupted. That's something that team B didn't say anything about...
So which code did you think was the best?
I apologize for linguistic errors, English isn't my native language.
Well this is most likely not what you're looking for, but I though I'd post it in case it helps someone else. Since there's no way to improve the speed of the browser's basic functionality, you can prevent the loop from freezing the browser while it is executing. You can do this by performing your loop in chunks and initiate the next chunk using setTimeout with a time of 0. This basically allows the browser to repaint, and perform other actions before it calls the next chunk. Here's a modified version of your script:
var Test = {
processImages: function() {
var fS = new Date().getTime();
var minimagew = 50,
minimageh = 60,
stepSize = 1000;
var imgs = document.getElementsByTagName('img');
var len = imgs.length,
isBad = 0,
i = len,
stopAt = len;
var doStep = function() {
stopAt -= stepSize;
while (i >= stopAt && i--) {
var n = imgs[i];
var imgW = n.width;
var imgH = n.height;
if (imgW < minimagew || imgH < minimageh) {
isBad++;
}
}
if (i > 0)
setTimeout(doStep, 0);
else {
var fE = new Date().getTime();
var fD = (fE - fS);
console.info('Processed ' + imgs.length + ' images in '
+ fD + 'ms. ' + isBad + ' were marked as bad.');
}
}
doStep();
}
};
Of course this makes the total execution time longer, but maybe you can use it so that your page is usable while it is working.
I was very interested in your question but unfortunately I didn't really get anywhere in optimizing your code. I was able to trim off about 30 to 40 ms on the IE execution (this is obviously dependent on the power of your physical machine). But I tried just about everything
Things I tried instead of [element].width.
[element].getBoundingClientRect() - basically this returns height and width in one
document.elementFromPoint(x, y) - I though by using offsetLeft + 50 and offsetTop + 60 I could determine if the element at that point was different than the current element, meaning that it was a "bad" image.
In the end this is what I came up with to trim just a bit off the time (30 to 40 ms).
Note: the best time I got in IE 8 was 171ms
Edited - I modified the code below to include your way, my way and using Jquery. Test it out.
<html>
<script src="http://code.jquery.com/jquery-1.4.2.js" type="text/javascript"></script>
<script type="text/javascript">
var TestYourWay = {
processImages: function () {
var fS = new Date().getTime();
var minimagew = 50,
minimageh = 60;
var imgs = document.getElementsByTagName('img');
var len = imgs.length,
isBad = 0,
i = len;
while (i--) {
var n = imgs[i];
var imgW = n.width;
var imgH = n.height;
if (imgW < minimagew || imgH < minimageh) {
isBad++;
}
}
var fE = new Date().getTime();
var fD = (fE - fS);
alert('Processed ' + imgs.length + ' images in '
+ fD + 'ms. ' + isBad + ' were marked as bad.');
}
};
var TestMyWay = {
processImages: function () {
var fS = new Date(),
imgs = document.getElementsByTagName('img'),
isBad = 0;
for (var i = 0, img; img = imgs[i]; i++) {
if (img.width < 50 || img.height < 60) {
isBad++;
}
}
var fD = new Date() - fS;
alert('Processed ' + i + ' images in ' + fD + 'ms. ' + isBad + ' were marked as bad.');
}
};
var TestJquery = {
processImages: function () {
var fS = new Date(),
imgs = $('img'),
isBad = 0;
imgs.each(function () {
if (this.width < 50 || this.height < 60) {
isBad++;
}
});
var fD = new Date() - fS;
alert('Processed ' + imgs.length + ' images in ' + fD + 'ms. ' + isBad + ' were marked as bad.');
}
};
</script>
<body>
<button onclick="javascript:TestYourWay.processImages();" id="yourWay">Your Way</button>
<button onclick="javascript:TestMyWay.processImages();" id="myWay">My Way</button>
<button onclick="javascript:TestJquery.processImages();" id="myWay">jQuery Way</button>
<img src="http://nsidc.org/images/logo_nasa_42x35.gif" />
<!--Copy This image tag 10000 times -->
</body>
</html>
Other things of Note:
The JavaScript engine in IE 8 is not as fast a FireFox 3.6+, Safari or Chrome. Opera has made improvements to their scripting engine but still not as fast as FF, Safari or Chrome. However Opera does out preform IE 8 in some things but is sluggish in others. Also of Note IE 9 is due out late this year or early next year and they have made improvements to the JavaScript Engine. You can see some Statistics on what I am saying here.
https://spreadsheets.google.com/pub?key=0AuWerG7Xqt-8dHBuU2pGMncwTENNNGlvNzFtaE5uX0E&hl=en&output=html
I haven't tested this on IE but, what you could do is remove the variable declarations from the loop, even though they're not that expensive (CPU-wise) they can spare a few CPU cycles when they're removed from a loop, also you can go ahead and skip the imgW and imgH assignments and access the objects properties directly, cause this can save one object de-referencing since the other part of the logic check in the if statement wouldn't have to be executed for the images with faulty widths;
var Test = {
processImages: function () {
var fS = new Date().getTime();
var minimagew = 50,
minimageh = 60;
var imgs = document.getElementsByTagName('img');
var len = imgs.length,
isBad = 0,
i = len;
/* this is the only part updated */
while (i--) {
if (imgs[i].width < minimagew || imgs[i].height < minimageh) {
isBad++;
}
}
/* ... 'till here */
var fE = new Date().getTime();
var fD = (fE - fS);
console.info('Updated: Processed ' + imgs.length + ' images in '
+ fD + 'ms. ' + isBad + ' were marked as bad.');
}
,processImagesOriginal: function () { // for comparisson
var fS = new Date().getTime();
var minimagew = 50,
minimageh = 60;
var imgs = document.getElementsByTagName('img');
var len = imgs.length,
isBad = 0,
i = len;
while (i--) {
var n = imgs[i];
var imgW = n.width;
var imgH = n.height;
if (imgW < minimagew || imgH < minimageh) {
isBad++;
}
}
var fE = new Date().getTime();
var fD = (fE - fS);
console.info('Original: Processed ' + imgs.length + ' images in '
+ fD + 'ms. ' + isBad + ' were marked as bad.');
}
};
//Original: Processed 10000 images in ~38ms. 10000 were marked as bad.
//Updated: Processed 10000 images in ~23ms. 10000 were marked as bad.
Access an layout attribute of an element on screen (or under document.body) may invoke layout overhead (lock, reflow, ...etc) even if you do read-only access in IE.
I didn't test but you can try something like this.
var done=i;
while (i--) {
var img=new Image();
img.onload=function(){
if (this.width < minimagew || this.height < minimageh) {
isBad++;
}
if(done--==0){ onComplete(); }
};
img.onerror=function(){ done--; }
img.src=imgs[i].src;
}
Don't use long loop! which make GUI slow
EDIT: document.getElementsByTagName is slower then you expected. It does not return a static array but a dynamic object which reflect changes(if any). You can try to copy elements in an array, which may reduce performance drop by interference when other DOM API.