Image attributes of uncached image

Discussion in 'Web Design and Development' started by angelwatt, Feb 19, 2008.

  1. angelwatt Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #1
    On a recent little project I've come across something interesting and frustrating. Say you have the following code inside a script tag within the head tag.
    Code:
    var a = document.createElement('img');
    a.setAttribute('src', 'image.png');
    alert(a.width);
    The first time the page loads it will alert 0, but if you reload the page it'll give you the correct width of that image. I've also tried the alternative technique below.
    Code:
    var a = new Image();
    a.src = 'image3.png';
    alert(a.width);
    I get the same results. This gets quite frustrating when you're centering the image on the screen and getting zero widths and heights for the image as you can imagine. So far the only way I've been able to get the images to center without a reload is to do getElementById on it a "moment" later and adjust the style attributes (using the now accessible width/height) of the image at that point.

    Though I have a working solution (at least I think it is), I was curious if other people had thoughts on the subject and maybe better solutions they'd like to share. PHP handles this stuff nicely, but prefer not to do an AJAX call. I want pure JavaScript with maybe a hint of CSS if need be.
     
  2. bootedbear macrumors 6502

    bootedbear

    Joined:
    Sep 13, 2004
    Location:
    Austin, TX
    #2
    Until the browser downloads the image, it's not going to know the image width. Is there a previous page where you can reference the image invisibly so that the browser has a chance to cache it prior to reaching your page?
     
  3. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #3
    Well it happens all on the same page. I'm creating my own version of lightbox essentially. I'm still going through their code to see how they get around it, though it seems they're using a similar technique as I am, but they animate the appearance of the image so it caches along the way.
     
  4. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #4
    To show one solution (that I'm not very satisfied with since it requires a delay):
    Code:
    var a = document.createElement('img');
    a.setAttribute('src', 'image.png');  // starts to put image in cache
    setTimeout('alertWidth()', 400); // 400 millisecond delay
    function alertWidth() { alert(a.width); }
    So setting the attribute to the file does start to put the image into cache, but apparently it needs a little time before the images attributes become available. The specific time needed depends on the connection speed between the browser and the server. I had been using 100 ms, which worked fine from home where my server is at, but from work that doesn't seem to be a long enough delay so going to increase it to probably 400 ms.

    Still though, I'd like to hear other people's thoughts and if they have different solutions.
     
  5. SrWebDeveloper macrumors 68000

    SrWebDeveloper

    Joined:
    Dec 7, 2007
    Location:
    Alexandria, VA, USA
    #5
    Please try this possible solution:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <title>Test</title>
    
    <script language="javascript" type="text/javascript">
    <!--//
    function MakeVisible() {
    	var imgobj=document.getElementById('mypic');
    	var divobj=document.getElementById('mydiv');
    	divobj.style.visibility="visible";
    	alert(imgobj.width);
    }
    //-->
    </script>
    
    </head>
    
    <body onload="MakeVisible()">
    
    	<div id="mydiv" style="display: none">
    		<img src="whatever.png" alt="Blah blah...." id="mypic"  />
    	</div>
    
    </body>
    </html>
    

    What I did was wrap a div around the image, assigned id's to both, set only the div hidden. The body onLoad calls a simple function that creates objects for the div and image, setting the div visible and then alerting the image size as in your example.

    I included the complete HTML page to show you placement of things and what doctype I was using. If this works for you I'm sure you can streamline and tweak.

    Please let me know, I tried it in FF and MSIE making sure to dump my cache before testing.

    -Jim
     
  6. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #6
    Well, not quite what I was after Jim. First, a small note, I think you meant for the style of the div to be visibility: hidden rather than display: hidden since display doesn't have a hidden value. Small point though.

    By having the img tag in the HTML from the beginning, the browser is already caching the image, even if the style is set to hidden (from my understanding). In my situation (which I didn't explain well in the beginning so sorry about that), the only img tags in the HTML is for the thumbnails, not the full size image, which is why it's not cached.

    I have updated my JavaScript to use a longer delay before displaying the image after creating the img element. If someone wants to check it out to see if it works for you, you can find my web site through my profile and it's in the Artwork section of my site (I'd rather not post direct links). If it centers first try let me know, and also if it doesn't. The delay isn't too horrible.
     
  7. SrWebDeveloper macrumors 68000

    SrWebDeveloper

    Joined:
    Dec 7, 2007
    Location:
    Alexandria, VA, USA
    #7
    Please note the "display" attribute is now set to "none", thanks! Sounds like you've found your solution, enjoy!

    -jim
     
  8. CoreWeb macrumors 6502

    Joined:
    Mar 2, 2007
    Location:
    Edge of reason
    #8
    I made a solution to this once. My page would often not know what image would be displayed until it was displayed, and I had to measure it before the display took place. I therefore created the image object in either an invisible area (using methods such as display:none, visibility:hidden, opacity/filter:alpha 0, left:-500px, etc), and then waited for the image to load.

    When an image finishes loading, it triggers some events. The most important are: onabort, onerror, onload. By handling these events, you can detect when the image has finished loading.

    Example: (I have not tested this specific example, but this is how it works)
    Code:
    var a = document.createElement('img');
    //insert the handlers BEFORE the src is set
    a.onabort = imageError;
    a.onerror = imageError;
    a.onload = imageLoaded;
    
    a.setAttribute('src', 'image.png');
    
    function imageError(){
        alert("Oops: A problem occurred while displaying the image");
    }
    function imageLoaded(){
        alert(a.width);
    }
    
    Once the image has finished loading, finding values such as dimensions work fine.
     
  9. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #9
    Thanks CoreWeb. I tested your code you posted and it did alert the correct width, and that was without placing the image (hidden or otherwise) into the document.

    I had been using the onload in an earlier version, but for whatever reason had taken it out (kept running into browser issues here and there). I'll try to get it back into my code and see what happens. I'll be sure to post back my results.
     
  10. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #10
  11. CoreWeb macrumors 6502

    Joined:
    Mar 2, 2007
    Location:
    Edge of reason
    #11
    I'm glad you found that helpful. I think at one time I was using onload along with a interval check for IE (there is some way, I forgot how, to detect whether an image has loaded), but for some reason I determined that it was unnecessary in my latest javascript library.

    I notice that you are letting the image load while it is visible; it may look nicer if you delayed displaying it until it had completely loaded. Just a suggestion.
     
  12. angelwatt thread starter Moderator emeritus

    angelwatt

    Joined:
    Aug 16, 2005
    Location:
    USA
    #12
    Yeah that's one of the little bugs I've got going on. I tried to hide it until after it was loaded, but for some reason IE and Opera had issues with that. It would work for the first click, but if you tried to review it, the image wouldn't reappear. It's very odd. If only Firefox and Safari were the only browsers I would have had this done a while ago. I think it's because IE and Opera don't start preloading the image until after the image is thrown on the screen. Maybe I could try a peek-a-boo tactic to fool it :)
     

Share This Page