3

This is probably a simple question but I am stumped and just don't know where to start.

I have a PHP script (image_feed.php) that returns a URL to an image. Every time this URl is called it returns the latest image available (the image changes every couple of seconds).

What I want to happen is that when the page loads, there is an AJAX call to image_feed.php, which returns the latest url. This URl is then inserted into the HTMl replacing the appropriate image src.

After 5 seconds, I want the process to repeat, and for the image to update. However, I don't want the image to be swapped until it has finished loading, and I want to avoid a white space appearing before the new image loads.

At the moment I have the following jQuery, which simply loads the return value of image_feed.php directly into a div called #image1. image_feed.php is correctly formatted to provide a html image tag.

    $(document).ready(function(){
    var $container = $("#image1");
    $container.load('image_feed.php?CAMERA_URI=<?=$camera_uri;?>')
    var refreshId = setInterval(function()
    {
        $container.load('image_feed.php?CAMERA_URI=<?=$camera_uri;?>');
    }, 5000);

}); 

This works, but there is a problem. I get a white space the size of the image in IE and Firefox every time the image refreshes, because the image takes a while to download.

I know what I need to is for image_feed.php to return the plain URL to the image. I then use some jQuery to request this URL, pre-load it and then swap it with the existing image.

However, I'm still struggling to get anywhere. Could someone be so kind as to give me some pointers / help?

dopey
  • 496
  • 1
  • 6
  • 19

4 Answers4

3

You can. When you want to reload something, you can just append a search query, so that it refreshes the source.

For Eg., when there is a frequently changing image (say captcha) and you wanna load it again, without refreshing the browser, you can do this way:

Initial Code:

<img src="captcha.png" alt="captcha" />

Refreshed Code:

<img src="captcha.png?1" alt="captcha" />

The script used here would be just:

var d = new Date();
$('img').attr('src', $('img').attr('src') + '?_=' + d.getMilliseconds());

Hope this helps! :)

vog
  • 23,517
  • 11
  • 59
  • 75
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
  • Hi, thanks for your help. I understand how to use .attr to replace the image. However, what I am struggling with is the AJAX request to get the latest image URL and how to load that response into a variable and then feed it into the statement that swaps the image src. – dopey Jun 06 '12 at 19:16
  • @jakew009 Is the latest image URL which you are supposed to get is changing or is it a constant one? What I am asking is, all the time is it just some `image.png` or is it `eghkasdf.png` once and `sdjlhkg.png` the next time? – Praveen Kumar Purushothaman Jun 06 '12 at 19:17
  • Praveen, it changes every time. It looks something like ZHWABRKJIY_2012-06-06_20-18-24_041.jpg – dopey Jun 06 '12 at 19:19
  • Oh in that case, you can use a jQuery AJAX load to fetch the new URL. Let me put it in a different answer in few mins... :) – Praveen Kumar Purushothaman Jun 06 '12 at 19:21
  • Check it out. Hope that helps. :) – Praveen Kumar Purushothaman Jun 06 '12 at 19:28
  • @darma the user who posted the question itself has said that it is working. What's the problem? Do you have a better solution? – Praveen Kumar Purushothaman Jun 06 '12 at 19:39
  • @PraveenKumar : the problem here is to preload the next image and only display it when loading is complete, and you don't address this at all. Finbarr's answer is the good way to go. – darma Jun 06 '12 at 19:44
3
$(document).ready(function() {
    var $img = $('#image1');
    setInterval(function() {
        $.get('image_feed.php?CAMERA_URI=<?=$camera_uri;?>', function(data) {
            var $loader = $(document.createElement('img'));
            $loader.one('load', function() {
                $img.attr('src', $loader.attr('src'));
            });
            $loader.attr('src', data);
            if($loader.complete) {
                $loader.trigger('load');
            }
        });
    }, 5000);
});

Untested. Code above should load the new image in the background and then set the src attribute of the old image on load.

The event handler for load will be executed only once. The .complete check is necessary for browsers that may have cached the image to be loaded. In such cases, these browsers may or may not trigger the load event.

Finbarr
  • 31,350
  • 13
  • 63
  • 94
  • Nice answer, only in case it takes a few secs to load the image this won't work. Maybe use setTimeout (instead of setInterval) after onload, in a function that calls itself? – darma Jun 06 '12 at 19:40
  • This worked perfectly straight away! Fantastic! Now I will just have to edit it slightly so as it does not wait 5 seconds before loading the first image. Thanks! – dopey Jun 06 '12 at 19:43
  • @darma that's definitely a concern. You then have to deal with the issue of the next image never loading, but easy enough. – Finbarr Jun 06 '12 at 19:46
1

Consider, if you have to fetch the URL again from the server, for a new image URL, you can do this way:

$.ajax({
  url: 'getnewimageurl.php',
  success: function(data) {
    $('img').attr('src', data);
  }
});

The server should return only a new image name in it. For eg., the PHP code should be this way:

<?php
    $images = array("jifhdfg", "jklduou", "yuerkgh", "uirthjk", "xcjhrii");
    die($images[date('u') % count($images)] . ".png"); // Get the random milliseconds mod by length of images.
?>
Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
  • Thanks Praveen - this is what I was trying to achieve all day, its starting to make sense now. – dopey Jun 06 '12 at 19:45
0

I suggest you use jQuery 'onImagesLoad' Plugin This provides you with a callback when an image has finished loading.

When you receive new image URL from server, you create a new <img object with src="new_url_from_server" and attach 'onImagesLoad' callback to it. When your callback is called, your image has finished downloading.

Now you can just replace the 'src' attribute of old img object with new_url_from_server. Since new image is already avaiable in cache, it will not be downloaded again and will be immediately displayed!

Aletrnatively, you can hide the old image and add this new image to DOM (not required if above works correctly)

Some bare bones sample could be like this:

<!DOCTYPE html> 
<html> 
<body> 
<img id='bla' src="10.jpg" />

<script type="text/javascript" src="jquery.min.js"></script> 
<script type="text/javascript" src="jquery.onImagesLoad.js"></script> 
<script type="text/javascript"> 
    $(function(){ 
        var img = $('<div><img src="http://myserverbla/images/verybig.jpg"></img></div>');
        img.onImagesLoad({ 
                all : allImgsLoaded 
            });

        function allImgsLoaded($selector){ 
            var allLoaded = ""; //build a string of all items within the selector 
            $selector.each(function(){ 
                $('#bla').attr('src','http://myserverbla/images/verybig.jpg');
            }) 
        } 
    }); 
</script> 

</body> 
</html>
vivek.m
  • 3,213
  • 5
  • 33
  • 48
  • Thanks for your answer. I did actually play around with this plugin earlier, but was unsure how to use the callback functionality. It now makes sense - many thanks. – dopey Jun 06 '12 at 19:44