Using jQuery Cycle and ajax to dynamically create a slide show - images don't load immediately

Major Productions picture Major Productions · Aug 4, 2010 · Viewed 13.1k times · Source

I'm currently trying to make a cheap, simple slide show navigation box for a client (something along the lines of what, say, the Red Sox or Gamespot use on their sites, but far, far simpler). So far, it's actually coming along nicely, with one problem - the images don't appear upon a first visit. They only appear after the page is reloaded. I think it may be some sort of runtime issue, or perhaps a cache issue, but I'm not sure how to fix it. My code:

PHP:

if (isset($_GET['start']) && "true" === $_GET['start'])
{
    $images = array();

    if ($dir = dir('images'))
    {
        //$count = 0;

        while(false !== ($file = $dir->read()))
        {
            if (!is_dir($file) && $file !== '.' && $file !== '..' && (substr($file, -3) === 'jpg' || substr($file, -3) === 'png' || substr($file, -3) === 'gif'))
            {
                $lastModified = filemtime("{$dir->path}/$file");
                $images[$lastModified] = $file;
                //$images["image$count"] = $file;
                //++$count;
            }
        }

        echo json_encode($images);
    }
    else { echo "Could not open directory"; }
}

HTML and JavaScript:

<!doctype html>
<html lang="en-us">
    <head>
        <title>jQuery Cycle test</title>
        <script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="js/jquery.cycle.all.min.js"></script>
        <style>
            #slideshow a { margin: 0; padding: 0; color: #fff; }
        </style>
    </head>

    <body>
        <div id="slideshow">
        </div>
    </body>

    <script type="text/javascript">
        $.get('slideshow.php', {start : "true"}, function(data){
            var images = JSON.parse(data);

            for(var image in images){
                $('#slideshow').append('<a href="images/' + images[image] + '"><img src="images/' + images[image] + '" alt="" /></a>');
            }

            $('#slideshow').cycle({
                fx: 'cover',
                direction: 'right',
                timeout: 3000,
                speed: 300
            });
        });
    </script>

</html>

I think I may need to delay the timing of the cycle function, or perhaps somehow force it to 'see' the images the first time through. I'm just not sure how to do it.

Answer

Corpsekicker picture Corpsekicker · Aug 10, 2010

There are two possible reasons (or more that I am missing) that it could be loading oddly:

  1. Your call isn't encompassed in a document.ready (even though your JavaScript code is at the bottom of the page) - this might not be the issue... just a thought.

    i.e. create a function to hold your loading and do a:

    $(document).ready(function(){
        loadImages();
        startSlideShow();
    });
    
  2. The other thing could be that on the first load, the images haven't downloaded to your browser. You could do a check to see if all the images have finished loading (use a counter and isloaded on all images etc.) before you show the cycle component. This could fix it for Chrome.

Note: The built-in .each is way way faster than a "for" loop. (specially for IE and many items...)

For example:

$(newImages).each(function(){
    $('#slideshow').append($(this));
});