Image Rotation via JavaScript, AJAX, and PHP

Download zip file with documentation

This script came about via a conjunction of a number of separate influences. It started with a question about how to have an image change on a page every so many seconds. As I'm trying to teach myself more about JavaScript and using AJAX techniques, I had this possibly silly idea of using an AJAX call to a PHP script to do the delays, since JavaScript does not have a built-in sleep or wait function per se, but mostly just because I wanted to see if it would work.

If you find this code useful and would like to encourage me to post more goodies here, you could buy me something from my wish lists at Amazon.com or at MusicDirect.com

For a demonstration of this script in action, see this simple slide-show page.

The ImageRotator class contains everything needed to set up the requisite JavaScript code in a PHP page. All you need to do is include it into your page, instantiate it, set some values to tell it things like where your images are, and call a couple methods to output the JavaScript into your page: a <script> section within the head section of your page and an "onload" attribute within the body tag. Here's a sample usage in a simple page:

<?php
require_once "ImageRotator.php";
$rotator = new ImageRotator();
// suffixes of image files to be displayed:
$rotator->setSuffixes('PNG,png');
// directory where images are located relative to the web document root:
$rotator->setImageDir('/images');
// delay in seconds between image changes:
$rotator->setDelaySeconds(8);
// HTML img element ID attribute value of image to be rotated:
$rotator->setImageId('image');
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang='en'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>
<meta name="description" content="">
<meta name="keywords" content="">
<title>Untitled</title>
<?php
// insert the JavaScript block here
echo $rotator->getHeadJs();
?>
</head>
<body <?php
// put the onload attribute here
echo $rotator->getOnloadJs();
?>>
<h1>Image Rotator Test</h1>
<p>
<img src='/images/directory.png' alt='' id='image'>
</p>
</body>
</html>

The only other thing it needs is a very short PHP file for the delay function. It should be in the same script as the PHP page displaying the images, and called "delay.php".

delay.php

<?php
/**
*  Delay for JavaScript AJAX call
*
*  Delays for the amount of time called in the URL
*/
// max out the delay at 60 seconds
$delay = min((isset($_GET['delay'])) ? abs((int)$_GET['delay']) : 8, 60);
echo $delay;
sleep($delay);
?>

And with no further ado, here is the ImageRotator class file.

ImageRotator.php

<?php
/**
*  PHP class for creating a JavaScript image rotator
*
*  Will generate the necessary JavaScript and related HTML to cause the
*  selected HTML IMG element to perodically cycle through an array of
*  images from a specific directory.
*  
*  @author Charles Reace (www.charles-reace.com)
*  @version 1.0
*/
class ImageRotator
{
   // User-modifiable variables:
   
   /**
   *  @var string path where images are located relative to web document root
   */
   var $imageDir = "images";

   /**
   *  @var string Comma-separated list of file suffixes to display
   */
   var $suffixes = " jpg,jpeg,gif,png,JPG,JPEG, GIF,PNG";
   
   /**
   *  @var integer Interval in seconds between images.
   */
   var $delaySeconds = 15;
   
   /**
   * @var string HTML ID of image element to be rotated
   */
   var $imageId = "rotate_me";
   
   /////////////////////////////////////////////////////////////////////
   // Do not modify below this line unless you know what you're doing //
   /////////////////////////////////////////////////////////////////////
   
   /**
   *  Constructor
   *
   *  Makes sure pre-defined class vars are correctly formatted
   *
   *  @return void
   */
   function ImageRotator()
   {
      $this->imageDir = trim(trim($this->imageDir), '/');
      $this->suffixes = preg_replace('/\s*,\s*/', ',', trim($this->suffixes));
      $this->delaySeconds = (int) abs($this->delaySeconds);
   }
   
   /**
   *  setter for the $imageDir parameter
   *
   *  @param string $dir directory path relative to web document root
   *  @return boolean TRUE on success, else FALSE and generates user_warning
   */
   function setImageDir($dir)
   {
      $dir = trim(trim($dir), '/');
      if(!is_dir($_SERVER['DOCUMENT_ROOT'].'/'.$dir))
      {
         user_error("'$dir' is not a directory or is not readable.");
         return(FALSE);
      }
      if(!is_readable($_SERVER['DOCUMENT_ROOT'].'/'.$dir))
      {
         user_error("'$dir' is not readable.");
         return(FALSE);
      }
      $this->imageDir = $dir;
      return(TRUE);
   }
   
   /**
   *  setter for the $suffixes parameter
   *
   *  @param string $suffixes comma-separated list of file suffixes
   *  @return boolean Always returns TRUE
   */
   function setSuffixes($suffixes)
   {
      $this->suffixes = preg_replace('/\s*,\s*/', ',', trim($suffixes));
      return(TRUE);
   }
   
   /**
   *  setter for the $delaySeconds parameter
   *
   *  @param integer $delay delay in seconds
   *  @return boolean Always returns TRUE
   */
   function setDelaySeconds($delay)
   {
      $this->delaySeconds = (int) abs($delay);
      return(TRUE);
   }
   
   /**
   *  setter for the $imageId parameter
   *  @param string $id HTML ID
   *  @return boolean Always returns true
   */
   function setImageId($id)
   {
      $this->imageId = trim($id);
      return(TRUE);
   }
   
   /**
   *  get an array of image pathnames
   *
   *  @return array array of file pathnames relative to web document root
   */
   function getImageArray()
   {
      $images = array();
      $cwd = getcwd();
      chdir($_SERVER['DOCUMENT_ROOT']);
      $images = glob($this->imageDir.'/*.{'.$this->suffixes.'}', GLOB_BRACE);
      chdir($cwd); // back to original directory
      return($images);
   }
   
   /**
   *  get the JavaScript text for the head section
   *
   *  @return string A javascript element and code to be inserted within the
   *  head section of a [X]HTML page
   */
   function getHeadJs()
   {
      $images = $this->getImageArray();
      if(!count($images))
      {
         return(FALSE);
      }
      $js = <<<EOD
<script type="text/javascript">
/*
*  AJAX function to provide delay functionality
*/
function ajaxFunction(ix, id, url)
{
   /* usual stuff to create xmlHttp object */
   var xmlHttp;
   try
   {
      // Firefox, Opera 8.0+, Safari
      xmlHttp=new XMLHttpRequest();
   }
   catch (e)
   {
      // Internet Explorer
      try
      {
      xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
      }
      catch (e)
      {
         try
         {
            xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
         }
         catch (e)
         {
            alert("Could not display some data as your browser does not support AJAX.");
            return false;
         }
      }
   }
   /* when data received, call image update function */
   xmlHttp.onreadystatechange=function()
   {
      if(xmlHttp.readyState==4)
      {
         changeImage(ix, id, url);
      }
   }

   /* Send request */
   xmlHttp.open("GET",url,true);
   xmlHttp.send(null);
}

/*
*  Change the image src value
*/
function changeImage(ix, id, url)
{
   var images = new Array([<IMAGES>]);
   if(images.length == 0)
   {
      return false;
   }
   if(ix >= images.length)
   {
      ix = 0;
   }
   document.getElementById(id).src = '/' + images[ix];
   ix = ix + 1;
   ajaxFunction(ix, id, url);
}
</script>
EOD;
      $js = str_replace('[<IMAGES>]', "'".implode("','", $images)."'", $js);
      return($js);
   }
   
   /**
   *  get the JavaScript for the body tag onload attribute
   *
   *  @return string the onload string, including the "onload=" part
   */
   function getOnloadJs()
   {
      $url = dirname($_SERVER['SCRIPT_NAME']) . '/delay.php?delay=' .
             $this->delaySeconds;
      return("onload='changeImage(0, \"{$this->imageId}\", \"$url\");'");
   }
}

Download zip file with documentation