views:

600

answers:

6

Jquery puzzle

I've got a php script that returns the name of random jpg image from a folder. It's nice because I don't have to rename the images at all; I just drop them in the folder and the randomizer works. Right now, I call the script like this - http://mydomain.com/images/rotate.php - and on a simple web page reload, it swaps the images.

But I'd like to have it work with jQuery in that I'd like to have the image swap in a new image on an interval of ten seconds or so, and also fade them in and fade them out.

Edit 1/23/10:

This works by swapping in a spacer.gif. There might be a more elegant solution, but this works for me. Munch figured it out, by way of an idea by MidnightLightning:

function swapImage(){
  var time = new Date();
  $('#image').fadeOut(1000)
   .attr('src', 'http://mydomain.com/spacer.gif')
   .attr('src', 'http://mydomain.com/images/rotate.php?'+time.getTime())
   .fadeIn(1000);
}

var imageInterval = setInterval('swapImage()',10*1000); 

And this is rotate.php:

<?php

$folder = '.';


    $extList = array();
    $extList['gif'] = 'image/gif';
    $extList['jpg'] = 'image/jpeg';
    $extList['jpeg'] = 'image/jpeg';
    $extList['png'] = 'image/png';


$img = null;

if (substr($folder,-1) != '/') {
    $folder = $folder.'/';
}

if (isset($_GET['img'])) {
    $imageInfo = pathinfo($_GET['img']);
    if (
        isset( $extList[ strtolower( $imageInfo['extension'] ) ] ) &&
        file_exists( $folder.$imageInfo['basename'] )
    ) {
        $img = $folder.$imageInfo['basename'];
    }
} else {
    $fileList = array();
    $handle = opendir($folder);
    while ( false !== ( $file = readdir($handle) ) ) {
        $file_info = pathinfo($file);
        if (
            isset( $extList[ strtolower( $file_info['extension'] ) ] )
        ) {
            $fileList[] = $file;
        }
    }
    closedir($handle);

    if (count($fileList) > 0) {
        $imageNumber = time() % count($fileList);
        $img = $folder.$fileList[$imageNumber];
    }
}

if ($img!=null) {
    $imageInfo = pathinfo($img);
    $contentType = 'Content-type: '.$extList[ $imageInfo['extension'] ];
    header ($contentType);
    readfile($img);
} else {
    if ( function_exists('imagecreate') ) {
        header ("Content-type: image/png");
        $im = @imagecreate (100, 100)
            or die ("Cannot initialize new GD image stream");
        $background_color = imagecolorallocate ($im, 255, 255, 255);
        $text_color = imagecolorallocate ($im, 0,0,0);
        imagestring ($im, 2, 5, 5,  "IMAGE ERROR", $text_color);
        imagepng ($im);
        imagedestroy($im);
    }
}

?>
+1  A: 

Something like this might work, assuming that your PHP script simply returns the URL of the image:

$(document).ready(function(){
    window.setInterval(switchImage, 10000);

    function switchImage() {
        var rn = Math.floor(Math.random() * 100000)
        $.get('http://mydomain.com/images/rotate.php', 
              { n: rn }, 
              receiveNewImage);
    }

    function receiveNewImage(src) {
        $('#image').fadeTo(1000, 0.0, function() { switchAndFadeIn(src); } );
    }
    function switchAndFadeIn(newSrc) {
        $('#image').attr('src', newSrc).fadeTo(1000, 1.0);
    }
});

EDIT: Added random parameter.

EDIT: In your PHP, does something like this help?

header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Expires data in the past
Tom Bartel
Also seems like this should work fine, but it doesn't. Nothing shows. Not even with a URL of a static image instead of the URL of the php script. Thanks for your help; I can't think of what else to try...
songdogtech
Don't you even get an error? Are you using Firebug for debugging? Is the AJAX request actually executed? Does it return the expected kind of value?
Tom Bartel
Yup, should have offered more details; up too late. This morning it works somewhat; junk characters in my header. It fades in and out one image, and Firebug shows the Get request firing.Must have something with the returned URL of the image? Now I realize that URL of the image is always the same - http://mydomain.com/images/rotate.php - but the image is different. When I go to ttp://mydomain.com/images/rotate.php directy in my browser, I get a different image each (non-jQuery) reload. So that's something that must make a difference that I didn't realize at first... Thanks for the help.
songdogtech
How about a little upvote then? ;-)
Tom Bartel
Just guessing with my limted jQuery knowedge: do we need a full ajax call to pull the image rather than `$.get`, since the image url stays the same even though the image will be different from the php script?
songdogtech
I'm not quite sure what you mean by "full AJAX call", in my opinion `$.get` qualifies as an AJAX call. Maybe the result of the request is cached by the browser. Try either appending a random number as parameter (see edit) or set an according "expires" header in your PHP script.
Tom Bartel
The random parameter doesn't make a difference. I was thinking of something like this (once again, with my limited jQuery knowledge, but I am learning quite a bit here):`$.ajax({ type: "GET", url: "http://mydomain.com/images/rotate.php", cache: false, success: function(data){; //not correct here }});`
songdogtech
See my edit of the answer, hope this finally helps. It seems like the `cache: false` parameter does more or less what I suggested in that it appends a current timestamp to the URL and thus makes the URL unique to prevent the browser from caching the response.
Tom Bartel
This is turning into an epic :) Firebug shows the get request firing OK, and html shows the raw source of the image file. I have image caching disabled in htacces to no effect....
songdogtech
+2  A: 

Since your php script is returning the source of the new image, you might be best to avoid using load() and use a simple ajax call that swaps the image's source.

var img=$('#image');//cache the element

function refreshNotification(){
  $.ajax({
    url: 'http://mydomain.com/images/rotate.php',
    success: function(src){
      img.attr({src: src});
    }
  });
}

setInterval(refreshNotification, 10000);
czarchaic
Seems like this should work fine, but it doesn't. Nothing shows. Not even with a URL of a static image instead of the URL of the php script. Thanks for your help; I can't think of what else to try...
songdogtech
make sure to test it using `www.mydomain.com` there is something about the script that complains ... or try to eliminate the domain pare and use `images/rotate.php` instead use `\` to replace the `http://mydomain.com/` that is if you are on a deeper directory... and you might need to
Val
This seems like it should be an easy fix. What exactly is being returned from the ajax call? Is it just the source of an image or an `<img>` tag? Once the swap has been made, what does firebug say is the src of the affected image?
czarchaic
This is turning into an epic :) Firebug shows the get request firing OK, and html shows the raw source of the image file....
songdogtech
Why/how would this work? If I'm reading this right, you're assigning part of the response contents - which is of content type 'image' - to the src attribute, which should be a string URL... ?
LeguRi
A: 
$("#image").each(function({
$(this).fadeOut(function() { 

$(this).attr("src", "http://mydomain.com/images/image.jpg"); 
$(this).load(function() { $(this).fadeIn(); }); // this should be on the bottom....
}); 
})

Check each function on JQEach

I have updated the script i think it should work because you are waiting for an image to load, but it doesn't have a source... check this out > <img onerror="alert('there was an error') />" if you get the error it means that the source doesn't exist. btw you should not use the #image if you are planning to use multiple images as there can be one unique id on your html otherwise you will get conflicts

hope this helps

Val
Seems like this should work fine, but it doesn't. Nothing shows. Not even with a URL of a static image instead of the URL of the php script. Thanks for your help; I can't think of what else to try...
songdogtech
Still can't get this to work, and it doesn't throw the error, either. Am using only one #image. How does this time itself for the fadein/out interval?
songdogtech
`$(this).fadeOut(1000,function() { `speed parameter is before the call back ...http://docs.jquery.com/Effects/fadeOut, therefore you will get an error
Val
+4  A: 

The downside I see to doing it like this is that there will be a load period for the new image and the animation may be a little quirky because of it. It may be beneficial to have two parts to that file where a path is returned if a $_GET value is equal to one thing, and the image is returned if that $_GET value is not set or it equals something else. That way you could preload a series of images and there would be a smoother animation between images.

Having said that, it seems to me that something like this should work.

$(document).ready(function(){
   function swapImage(){
      var time = new Date();
      $('#image').fadeOut(1000)
       .attr('src', 'http://mydomain.com/images/rotate.php?'+time.getTime())
       .fadeIn(1000);
   }

   var imageInterval = setInterval('swapImage()',10*1000); 
});

The time makes it so the browser think it's getting a new image.

Spacer.gif

To do this with a black spacer, I'd recommend wrapping your image in a div and giving the div a #000 background color to match the spacer:

#image-wrap{background-color:#000;}

It would make it so the image actually faded to black, rather than fading to your current background color, changing to black, and fading back in. The js would be very similar to the above:

function swapImage(){
  var time = new Date();
  $('#image').fadeOut(1000)
   .attr('src', 'http://mydomain.com/spacer.gif')
   .attr('src', 'http://mydomain.com/images/rotate.php?'+time.getTime())
   .fadeIn(1000);
}

var imageInterval = setInterval('swapImage()',10*1000); 

Keeping the time in there probably isn't necessary, but hey, it's another safe-guard against the browser caching the "image".

munch
The random numbers or time stamps on the URL make no difference....
songdogtech
I'm thinking this method has merit; if you try stripping out the `fadeOut`/`fadeIn` animations and try just swapping the source every 10 seconds with a URL with constantly-changing suffixes, does firebug show that the image is actually reloading? Maybe instead of going directly from rotate.php to rotate.php, try "unloading" it first by going from rotate.php to spacer.gif to rotate.php?
MidnightLightning
That's a good idea for a spacer.gif. What would be the code for that? A black spacer gif might be a nice transistion: fade out color to black, fade in color and could solve the problem of calling a new image from rotate.php each time without having to use some sort of timestamp.
songdogtech
This works! The key must be getting around some sort of image caching, even though I have caching disabled in .htaccess. MidnightLightning, I'll see if I can get you some points, too, for the idea.
songdogtech
A: 

Your setup is missing the step of telling jQuery not to cache the AJAX request. There's a 'cache' parameter that can be added to an AJAX call to force it to grab a new copy:

$.ajax({
  url: 'http://mydomain.com/images/rotate.php',
  cache: false,
  success: function(src){
    img.attr({src: src});
  }
});
MidnightLightning
Firebug shows this firing off Get requests, but the image isn't shown, only the raw code of the image. It does rotate the image, but the image doesn't display, only source.
songdogtech
Oh yes; this won't work, since AJAX is getting the DATA of the image, which is the result of the AJAX call, not the URL of the image, which is what I was pushing into the 'src' attribute (round peg, square hole; would never work, regardless of a random change). Given some time to think on it, I think Munch's idea of not using AJAX, but using a random suffix might be the way to go, if refined.
MidnightLightning
+1  A: 

How about defining the swapImage() function outside of the $(document).ready() block?

<script type="text/javascript" scr="path/to/jquery.js"></script>
<script type="text/javascript">
function swapImage(){
    var time = new Date();
    $('#rotate').fadeOut(1000)
     .attr('src', 'rotate.php?'+time.getTime())
     .fadeIn(1000);
}
$(document).ready(function(){
  var imageInterval = setInterval('swapImage()',5000);
});
</script>

<img src="rotate.php" id="rotate" />
robertbasic
This almost gets it.... Firebug shows the script firing fine and I get the first image fine, then the subsequent images aren't there, but I do get the missing image "?" (which fades in and out) and which is more than before. Reason for the missing image is the image URL in Firebug has the time appended, i.e. rotate.php1264184509211 But removing the time stamp doesn't work either. Firebug shows the reloading happening, but with just rotate.php as the URL, and nothing happens.
songdogtech
if it's rotate.php1234567890 that should be rotate.php?1234567890
robertbasic
The "?" in the URL doesn't make a difference....
songdogtech
it should make a difference, cause without the "?", the server is looking for a file called rotate.php1234567890, but with the "?" it's looking for rotate.php and passing a parameter via $_GET. For me this example works just fine... What version of jQuery do you use? Are the paths set correctly?
robertbasic
Latest version of jQuery, and the paths are right....
songdogtech