Slideshow Pro with PHP, CSS and JS

Well not exactly, but close enough to warrant the title I would think.

I know that I was supposed to publish another tutorial before this one, but I hacked this up last week, and thought it was cool enough to preempt the other post.  So at work the new design we just launched called for a rotating, hyperlinked slideshow, with cross-fading.

Normally it would be “To the Flash Cave!”, but I was feeling extra crotchety so I decided to basically recreate Slideshow Pro in PHP, CSS and some JS-foo.  Nothing to spectacular, but it is shiny.  Be warned, this is a very long tutorial… use at your own risk.

First, lets set some parameters

The slideshow needed to be:

  1. Dynamic
  2. Hyperlinkable on a per-image basis
  3. The images needed to be “retireable”
  4. The images needed to be “expireable”, meaning they have a date where they automatically fall out of the slideshow
  5. And non-techies needed to be able to interact with the system

My solution currently addresses points 1 - 3 directly; point 4 is just waiting for me to write a simple web form page.  Lower priority at the moment.  So lets take a look at the parts that are assembled to make up this Justice League of the web.

Hey, hey the gangs all here!

So we will of course be making use of PHP 5 and all its OOP goodnes; throw in a liberal sprinkling of prototype and script.aculo.us and finally some auto-generated CSS for spice.  Add that together, and you get this.

So lets go over the logic before we get into some code.  To maximize flexibility we are going to be storing information on each image in our slideshow in a SQL database table (for this example a MySQL DB).  We will query this table for all the images we have catalogued that aren’t retired or expired, and will use this information to generate CSS and JS to power our slideshow.

We all on the same page?  Good lets move onto the first bit of our code, the slideshow table structure.

CREATE TABLE `slideshow` (
`ID` bigint(20) NOT NULL auto_increment,
`url` varchar(256) NOT NULL,
`description` text NOT NULL,
`filename` varchar(256) NOT NULL,
`expiredate` date NOT NULL,
`retired` tinyint(1) NOT NULL,
KEY `ID` (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

Nothing to scary here I would say.  But just in case lets look at each field in some more detail:

  • ID: Auto-incrementing ID, for sanity purposes.
  • url: The URL we want the load if the image is clicked
  • description: For those of us who care about useability and accessability, an image description
  • filename: The filename, sans extension of the file.  This is forward thinking, to the time that we have a web interface for the non-techies to upload images for the slideshow.
  • expiredate: This allows us to specify a date for an image to fall out of hte slideshow rotation.
  • retired: So we have an image that we want to remove from the slideshow, but not delete.  This could be for an annual event, concert whatever.

For the sake of this tutorial, we will use the data set from the Asbury Site.  Next lets look at the slideshow class file.

Slideshow Framework

Currently our class will only have one function create_show() but once we start to make a web interface this class will be come much more noisy.  Since I primarily talk about WordPress here, we will assume that you will be using this on a WP powered site.  If that is not the case, you should at least know how to connect to your DB… if that isn’t the case, stop now and come back when you do.  Here is the code for our class:

<?php
// begin slideshow class
class slideshow {
function create_show() {
global $wpdb;
$today = date('Y-m-d');
$q = $wpdb->get_results( "SELECT ID, url, description, filename, expiredate, retired FROM slideshow WHERE retired = 0 AND expiredate < '$today' ORDER BY ID ASC" );
if( is_array( $q ) ) {
return $q;
} else {
return array();
}
}
} // end slideshow class

So lets step through the function.  First we find out what todays date is and set it equal to $today.  Then we perform an sql query against our slideshow table, where we look for records that are not retired (equal to 0) and that have an expiredate less than $today.

Okay so now we have our one function, lets make some use of it.  Next we’ll look at the how we programmaticaly create CSS, HTML and the JS that powers the slideshow with this function.

Creating and putting the pieces together

To make the slideshow work, we are going to need three things: generated HTML, CSS and JS.  I like to split out generated markup and scripting into thier own files, so that the static content we have can benefit from cacheing.

Here is the code for slideshow.css.php:

// begin CSS generation functions
$members = slideshow::create_show();
header('Content-Type: text/css; charset: UTF-8');
$i = 1;
$num = count( $members );
?>

<?php foreach ( $members as $picture ) {
echo "#" . 'spot-' . $i . "\n";
echo '{' . "\n";
echo ' position: absolute;' . "\n";
echo ' left: auto !important;' . "\n";
echo ' left: 7.8em;' . "\n";
echo '}' . "\n";
echo "\n";
$i++;
} // end CSS generation functions

Nothing to out of the ordinary going on here, we call our create_show() function, then loop through the results returned creating a CSS rule for each result we find.  Next we create the JS that powers the cross-fading-foo we all love so much:

// begin JS generation code
header('Content-Type: text/javascript; charset: UTF-8');
$members = slideshow::create_show();
$i = 1;
$num = count( $members );
?> var divs_to_fade = new Array(<?php foreach ( $members as $picture ) { ?><?php echo "'" . 'spot-' . $i . "'"; ?><?php $i++; ?><?php if ( $i == $num + 1 ) { echo ''; } else { echo ', '; };
}
?>);

var i = 0;

// the number of milliseconds between swaps. Default is five seconds.
var wait = 5000;

// the function that performs the fade
function swapFade() {
Effect.Fade(divs_to_fade[i], { duration:1, from:1.0, to:0.0 });
i++;
if (i == <?php echo $num; ?>) i = 0;
Effect.Appear(divs_to_fade[i], { duration:1, from:0.0, to:1.0 });
 }

// the onload event handler that starts the fading.
function startSlideShow() {
setInterval('swapFade()',wait);
}
<?php // end JS generation code ?>

Again, very straightforward. Some of you might have noticed that we queried for all of the fields in the table in each of these examples, but didn’t actually use the information.  We could have created another function, that only returned the ID for example, and used it when creating the CSS and JS.

I decided it was silly to have two functions, but if you want to go that way, by all means do.  It makes no difference to me.  Next we need to create some HTML.  I have this in a template file (slideshow.php) that I load via our nifty theme system.

When using WordPress you could place this code in the index template, or the header template wrapped in if ( is_home() ) if you wanted it to only show up on the root of your site.  Here is the code to generate the markup for the slideshow:

<?php
// begin HTML generation functions
$members = slideshow::create_show();
$i = 1;
foreach ( $members as $picture ) {
?> <div id="spot-<?php echo $i; ?>"<?php if ( $i == 1 ) { echo ''; } else { echo ' style="display:none"'; } $i++; ?>> <a href="<?php echo $picture->url; ?>" title="<?php echo $picture->description; ?>"><img src="theme/default/images/spots/<?php echo $picture->filename; ?>.jpg" alt="<?php echo $picture->description; ?>" /></a> </div><?php } // end HTML generation functions ?>

When run succesfully this code will give you something like this:

<div id="spot-1"> <a href="/url1/" title="URL and Image 1"><img src="/wp-content/themes/default/images/image1.jpg" alt="URL and Image 1" /></a> </div> <div id="spot-2" style="display:none"> <a href="/url2/" title="URL and Image 2"><img src="/wp-content/themes/default/images/image2.jpg" alt="URL and Image 2" /></a> </div> <div id="spot-3" style="display:none"> <a href="/url3/" title="URL and Image 3"><img src="/wp-content/themes/default/images/image3.jpg" alt="URL and Image 3" /></a> </div> <div id="spot-4" style="display:none"> <a href="/url4/" title="URL and Image 4"><img src="/wp-content/themes/default/images/image4.jpg" alt="URL and Image 4" /></a> </div> <div id="spot-5" style="display:none"> <a href="/url5/" title="URL and Image 5"><img src="/wp-content/themes/default/images/image5.jpg" alt="URL and Image 5" /></a> </div>

So that is it, you have the core of functionality that can be found in SlideShow Pro, for free throught the clever use of PHP, CSS and JS.  Now, let me say that I don’t have any problem with Todd’s product.  It is pretty amazing and very affordable, I just didn’t want to use Flash for this when there was a much more interesting method that could be employed.

Again to see this in action, just load the Asbury College Homepage and be amazed by the fadey goodness.

As always, questions and comments are welcome in the, uh… comments section.

  1. personal avatar Arthus Erea
    Stroll on over and visit Arthus Erea
    March 1, 2007

    Very nice; I tried doing something like this a while back and ended up just going back to Flash. Of course, I didn’t know about script.aculo.us then. Flickr should use this on the front page!

  2. personal avatar tom
    Stroll on over and visit tom
    March 1, 2007

    nice tutorial derek, when thing would be always that easy :)
    arthus, that was my first thought too, flickr should use this too. not exactly this handmade script, but a feature with a slideshow would be nice

    is this available as a plugin?

  3. personal avatar Chris J. Davis
    Stroll on over and visit Chris J. Davis
    March 1, 2007

    Thanks for the comments guys. I should think that Flickr will use soemthing like this when they can, since they have been moving away from dependency on flash.

    And Tom, I am using Derek’s theme for this month but this is my site (Chris J. Davis), not Derek’s. And no, it isn’t available as a plugin. I am not sure I will be rolling it up intp one.

  4. personal avatar Nathan Smith
    Stroll on over and visit Nathan Smith
    March 1, 2007

    Very nice writeup, and nicely done on Asbury.edu as well. You’re cleanin’ up that on-horse town. :)

    Also, hadn’t mentioned it before, so I will do so here: I’m really diggin your new site design. It’s very Jeff-Croft-esque, but with enough CJD flavah to make it feel unique. Might I suggest a little show/hide JS action on the tags though? It’s sort of overwhelming. Anyway, I’m just complaining needlessly. Don’t mind me.

  5. personal avatar Nathan Smith
    Stroll on over and visit Nathan Smith
    March 1, 2007

    Update: I just realized it’s a skin. Please disregard my previous nit-picky-ness (nit-picky-ness spelled wrong intentionally).

  6. personal avatar tom
    Stroll on over and visit tom
    March 1, 2007

    forgive me 100000 times, im sorry :)

  7. personal avatar Andy
    Stroll on over and visit Andy
    March 1, 2007

    Chris-

    Thanks - onload=”startSlideShow();” did the trick - I must be going mental!

    I am running it all in PHP4 so I guess it should work - I just stripped out the OO for now - all should still work though.

    Thanks again!
    -Andy

  8. personal avatar CJGraphix
    Stroll on over and visit CJGraphix
    March 22, 2007

    Thanks so much for this. I found it extremely helpful. While I ended up modifying some portions of the code to suit my personal needs I never would have gotten there if it wasn’t for this tutorial.

  9. personal avatar Vidar
    Stroll on over and visit Vidar
    October 25, 2007

    Oh wow, look at it go. It’s awesome.

    P.S: freenode is filtering me out, I miss you guys a lot!

  10. personal avatar murray
    Stroll on over and visit murray
    February 16, 2008

    Say, can I email you a question about CSS inside PHP?

    Thanks

    Murray

  11. personal avatar lockemonda
    Stroll on over and visit lockemonda
    April 8, 2008

    Hi:
    I’m going to ask what is probably a stupid question. I usually work in Dreamweaver. What kind of document do I set up to start creating the slideshow? Should I choose a Javascript document? Or a PHP document?
    Thanks!

  12. personal avatar Don
    Stroll on over and visit Don
    June 4, 2008

    First, I really like this slideshow. I already inputed the older version you had of this on the site I’m currently testing with.

    I’m trying to use this new one you have up as the site currently has both jquery and prototype running and that’s 2 big scripts and now that you have this version using prototype I look forward to simplifying things. I’m stuck though as I’m unsure about some of the JS code. Also asbury appears to still use the old version you posted (though I may be wrong) so I’m not sure how to judge the new coding you have here against that other than visually.

    The site is already connected to the mysql DB so I’m not so worried there. I guess its more I’m not sure how the rest of it has changed from the previous version.

    I will admit that I haven’t used the php xx generate code function yet because I’m unclear as to how that actually works.

    Any help would be great.

Pingbacks & Trackbacks

  1. Secret Weapon Notes: Volume Unlucky 13 at Secret Weapon Labs » [...] Lastly, Chris J. Davis has a great writeup on hacking and mashing together Slideshow Pro, CSS, and JS. It’s definitely worth the read. Plus, he’s [...]
  2.   Slideshow Pro with PHP, CSS and JS by Blogging Pro » [...] Well, Chris has gone and created a method of replacing flash when it comes to making a slideshow with transition effects. It is a beautiful example of what can be done with PHP, CSS and some JavaScript (I still hate JavaScript no matter how popular its becoming again). So at work the new design we just launched called for a rotating, hyperlinked slideshow, with cross-fading. [...]

Leave a Reply