PDA

View Full Version : download image first then apply fadein



ggalan
10-02-2010, 01:52 AM
i have some jquery which loads an image then applies a fade


<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
var img = new Image();
$(img).load(function () {
$(this).hide();
$('#divContent').append(this);
$(this).fadeIn();
}).attr('src', 'images/main.jpg');
});
</script>
</head>
<body>
<div id="divContent"></div>
</body>
</html>

however i am trying to apply this to multiple images through a loop, but unsuccessful. can anyone lend a hand


<html>
<head>
<style>
#divContent ul li{display:block;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {

var oBox = document.getElementById("divContent");
var aKids = oBox.getElementsByTagName("li");

var img = new Image();

for (var iKid = 0; iKid < aKids.length; iKid++)
{

$(img).load(function () {
$(this).hide();
$('#divContent').append(this);
$(this).fadeIn();
}).attr('src', aKids[iKid]);
}


});
</script>
</head>
<body>
<div id="divContent">
<ul>
<li><img src="images/main.jpg" width="512" height="384" /></li>
<li><img src="images/main2.jpg" width="512" height="384" /></li>
<li><img src="images/main3.jpg" width="512" height="384" /></li>
</ul>
</div>
</body>
</html>

jscheuer1
10-02-2010, 03:31 AM
There could be other problems. But there is no:



var oBox = document.getElementById("nav");

jscheuer1
10-02-2010, 05:27 AM
Not sure exactly what you're going for, but I played around with this quite a bit and came up with this:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
#divContent ul li {
list-style-type: none;
margin: 0;
padding: 0;
}
#divContent ul li img {
display: block;
width: 140px;
height: 225px;
}
</style>
<!--[if lt IE 8]>
<style type="text/css">
#divContent ul li {
margin-top: -4px;
}
</style>
<![endif]-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script>
document.write('\n<style>\n' +
'#divContent ul li {\n' +
' display: none;\n' +
'}\n' +
'</style>\n');
jQuery(function($){

var oBox = $('#divContent'), aKids = oBox.find('li'), fadeRate = 1000, inc = 1000, ctr = aKids.size();

aKids.each(function(){
var img = new Image(), li = $(this);
$(img).load(function(){
if(!--ctr){
aKids.each(function(){
$(this).fadeIn(fadeRate += inc);
});
}
}).attr('src', li.find('img').first().attr('src'));
});
});
</script>
</head>
<body>
<div id="divContent">
<ul>
<li><img src="photo1.jpg" alt=""></li>
<li><img src="photo2.jpg" alt=""></li>
<li><img src="photo3.jpg" alt=""></li>
</ul>
</div>
</body>
</html>

It's valid HTML 5 and corrects for IE 7 and less getting li's wrong (a good reason not to use them). The larger images are changed to ones I had handy. Change 'em back to test it out. Width and height of the images are set in style. Degrades well when no script available.

Demo:

http://home.comcast.net/~jscheuer1/side/files/jq_fadein_ims.htm

ggalan
10-02-2010, 02:19 PM
thanks!! will try it out
can i ask why you did this?


document.write('\n<style>\n' +
'#divContent ul li {\n' +
' display: none;\n' +
'}\n' +
'</style>\n');

instead of placing this in the html?

jscheuer1
10-02-2010, 03:06 PM
If it's in the HTML, even folks with javascript disabled/unavailable will be affected. This way only those with javascript will have the li elements display: none. With javascript they are later faded in. Without, one would never see them, except that by doing it this way, they will still be seen, just not faded in.

That's what I meant by:


Degrades well when no script available.

ggalan
10-03-2010, 12:40 AM
very cool!
right now, the code downloads all the images in the loop then applys the fade but
can you have it so that as soon as each of the individual image gets downloaded then it fades in?
so that the user doesnt have to wait for the entire batch but rather each individual to load then fade in

jscheuer1
10-03-2010, 02:26 AM
Yes. That invites disorder though. If your images are large in byte size, that might be preferable to having to wait for them all.

Most browsers will download 3 images synchronously. So you generally won't notice much of a difference unless they are competing with other page resources or they are of greatly differing bytes size, in which case things could look a bit disorderly.

Images for the web should be optimized for smallest byte size. If your images are, as I say - there shouldn't be much of a difference.

Here's the modified script (essentially the same with a stripped out section and one less variable):


document.write('\n<style>\n#divContent ul li {\n\tdisplay: none;\n}\n</style>\n');
jQuery(function($){

var oBox = $('#divContent'), aKids = oBox.find('li'), fadeRate = 1000, inc = 1000;

aKids.each(function(){
var img = new Image(), li = $(this);
$(img).load(function(){
li.fadeIn(fadeRate += inc);
}).attr('src', li.find('img').first().attr('src'));
});
});

Note: I condensed the document.write() style to a one liner. But it's the same as before.

Here's an even more condensed version:


document.write('\n<style>\n#divContent ul li {\n\tdisplay: none;\n}\n</style>\n');
jQuery(function($){

var fadeRate = 1000, inc = 1000;

$('#divContent li').each(function(){
var li = $(this);
$(new Image()).load(function(){
li.fadeIn(fadeRate += inc);
}).attr('src', li.find('img').attr('src'));
});
});

ggalan
10-03-2010, 02:36 AM
awesome! i will study your code. thank you so much :D

ggalan
10-03-2010, 03:27 AM
Yes. That invites disorder though. If your images are large in byte size


right now the code hides the li element so then the images are not structured, the quickest load appears in box 1 then as the larger images get loaded in it pushes the loaded boxes over for position 1. can this code somehow keep the order structure while performing the same load?

jscheuer1
10-03-2010, 12:30 PM
Which order structure? The one established by the load times, or the one established by the order in which the images appear in the HTML code?

If the former:


document.write('\n<style>\n#divContent ul li {\n\tdisplay: none;\n}\n</style>\n');
jQuery(function($){

var fadeRate = 1000, inc = 1000, ul = $('#divContent ul');

$('#divContent li').each(function(){
var li = $(this);
$(new Image()).load(function(){
ul.append(li.fadeIn(fadeRate += inc));
}).attr('src', li.find('img').attr('src'));
});
});

If the latter, I think that would require (in addition to script changes) abandoning the ul/li bit and using all div elements.

ggalan
10-03-2010, 02:56 PM
If the latter, I think that would require (in addition to script changes) abandoning the ul/li bit and using all div elements.


i see, thank you for all the examples. i will make an attempt at the "latter" and post my results.

jscheuer1
10-03-2010, 03:28 PM
Well, I was thinking it might be the former because that's what the original was attempting. If the latter, you would need container divisions for each division that would hold the images (this could be worked out various ways and the ul/li original layout could be preserved, but that would make it more complicated*). These containers would each be set (hard coded) to the dimensions of the image each contains or will contain (depending upon how you code it). That requires knowing the dimensions of each image before the browser does (hence the hard coding of the dimensions) and would result in gaps (blank spots) in the layout until all had loaded and begun fading in. But the layout wouldn't change as things happened, and the original hard coded order of things could be maintained.

I may take a stab at my own version of doing it this way.

*More about ul/li - in IE less than 8 the layout of the li element contains an elusive offset value that corresponds to nothing in style and that isn't accessible via javascript. My layout assumed one image per line. Used this way that offset could be guessed and I did so. If you are laying out a different way, it may be different, and/or need to be applied differently. The good thing about the div element is that it has no such offset in IE < 8 and by default no padding or margin in any browser. So it can be laid out however you like without having to worry about those parts (offset, margin, padding).

ggalan
10-03-2010, 03:59 PM
i see. so the css would need to have exact placement for each of the boxes?
right now they all just "float:left"



<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
#divContent{width:800px;}
#divContent div.items {float:left; margin: 0; padding: 0; list-style-type:none;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script>
jQuery(function($){

$('#divContent div.items').each(function(){
var oItems = $(this).hide();
$(new Image()).load(function(){
oItems.fadeIn(400);
}).attr('src', oItems.find('img').attr('src'));
});

});
</script>
</head>
<body>
<div id="divContent">
<div class="items"><img src="images/main.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/main2.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/main3.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/Footballhighimpact.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/Footballhighimpact_tmb.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/Marvingaye.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/Marvingaye_tmb.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrest2.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrest2_tmb.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrest3.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrest3_tmb.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrests.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoCrests_tmb.jpg" width="100" height="100" /></div>
<div class="items"><img src="images/MatoGH.jpg" width="100" height="100" /></div>
</div>
</body>
</html>

jscheuer1
10-03-2010, 04:15 PM
Yes. I was just working on this and came up with:


<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
#divContent {
overflow: hidden;
}
#divContent .containers {
width: 140px;
height: 225px;
float: left;
}
#divContent img {
display: block;
width: 140px;
height: 225px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script>
document.write('\n<style>\n#divContent .containers div {\n\tdisplay: none;\n}\n</style>\n');
jQuery(function($){

var fadeRate = 1000, inc = 1000;

$('#divContent .containers').each(function(){
var c = $(this);
$(new Image()).load(function(){
c.find('div').fadeIn(fadeRate += inc);
}).attr('src', c.find('img').attr('src'));
});
});
</script>
</head>
<body>
Some content above
<div id="divContent">
<div class="containers">
<div><img src="photo1.jpg" alt=""></div>
</div>
<div class="containers">
<div><img src="photo2.jpg" alt=""></div>
</div>
<div class="containers">
<div><img src="photo3.jpg" alt=""></div>
</div>
</div><!--[if lt IE 7]><br style="clear: left;"><![endif]-->
Some content below
</body>
</html>

By setting the dimensions and other styles of the images and their .containers containers, layout and the display value of the images is unaffected when you make the image's immediate containers (the inner nested div's with no class or id) display none. This happens in my version via the document.write() style. In your version by the hide(). But the effect is the same - display: none;. In your version though, since there is no layout height or width to those div's or their content when display is none and nothing around them with layout width and height to compensate, the layout space is not preserved. Things will still push around as the images load and begin fading in. Also, waiting for DOM ready to hide() them may not be quick enough to avoid flicker during page load. With such a simple markup, probably yes. But if this becomes part of a large and complex page, perhaps not.

ggalan
10-03-2010, 04:36 PM
thank you again for bouncing back so many ideas, will study and compare all of these posts!!
so if you didnt make the .containers containers div's and kept them ul li, you couldnt achieved the same result with a class in the li element?

jscheuer1
10-03-2010, 07:45 PM
As I said:


. . . the ul/li original layout could be preserved, but that would make it more complicated* . . .

. . . *More about ul/li - in IE less than 8 the layout of the li element contains an elusive offset value that corresponds to nothing in style and that isn't accessible via javascript. My layout assumed one image per line. Used this way that offset could be guessed and I did so. If you are laying out a different way, it may be different, and/or need to be applied differently. The good thing about the div element is that it has no such offset in IE < 8 and by default no padding or margin in any browser. So it can be laid out however you like without having to worry about those parts (offset, margin, padding).