The inner workings of the CSS Table Gallery

Much to my amazement, a lot of people asked how the CSS Table Gallery works. It is no rocket science, actually it is embarrassingly simple. The development environment was the latest XAMPP on a Thinkpad T40 laptop with XP professional and Homesite 5 as the editor. The imagery was done with Photoshop CS. No mouse has been harmed during the development - only the trackpointer.

Assumptions before I started developing

Here are some of the things I knew / took for granted before starting the script:

Developing backward

Knowing that I wanted to have an RSS feed, I started with an XML data file that will be used by the site and by another script to generate the feed. As there is no real XML support, I used my trusty untag() function to deal with the XML. I described what that one does in an article 3 years ago.

Thus equipped, I started with the XML file:


<?xml version="1.0" encoding="utf-8"?>
<!-- generator="Christian Heilmann and some crappy PHP" -->
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"
 xmlns:wfw="http://wellformedweb.org/CommentAPI/">
  <channel>
    <title>CSS Table gallery styles</title>
    <link>http://icant.co.uk/csstablegallery/</link>
    <description>A gallery of different styles for data tables</description>
    <copyright>Copyright 2005</copyright>
    <pubDate>Thu, 22 Sep 2005 07:40:50 +0000</pubDate>
    <item>
      <title>Plain old table</title>
      <link>0</link>
      <description>Tried and true, boring grey table with a one pixel
	  line</description>
      <author>Chris Heilmann</author>
      <authorurl>http://www.wait-till-i.com</authorurl>
      <authorcountry>UK</authorcountry>
      <cssurl>http://icant.co.uk/csstablegallery/plainold.css</cssurl>
    </item>
    <item>
      <title>Minimalist</title>
      <link>1</link>
      <description>As minimal as you can get, only lines around the body 
	  cells</description>
      <author>Chris Heilmann</author>
      <authorurl>http://www.wait-till-i.com</authorurl>
      <authorcountry>UK</authorcountry>
      <cssurl>http://icant.co.uk/csstablegallery/minimal.css</cssurl>
    </item>
  </channel>
</rss>

This is still the main driver of the site and the file I change every time a new entry is submitted. I saved it as tablestyles.xml.

The markup and the functionality

Then I created the HTML and the layout and all that Jazz, nothing really fancy here. The PHP to allow for the CSS change and the definition of the current style was next, and oh how lazy can a developer be?

# load the table styles data file

$handle = @fopen('tablestyles.xml', "r");
$contents = @fread($handle, filesize('tablestyles.xml'));
@fclose($handle);
if($handle==''){die('No styles found.');}

# grab all the items and reverse their order
$tables=untag($contents,'item',1);
$tables=array_reverse($tables);

# strip unwanted stuff from the css parameter sent via the URL
$iscss=strip_tags($_GET['css']);

# if the parameter is an integer, this will be the css id to display
# else show the first style (we reversed the array)
$l=sizeof($tables)-1;
$iscss=preg_match('/\d/',$iscss)?$iscss:$l;

# loop through all tables and compare the id with the parameter
# if they match, store the array counter as the current style
foreach($tables as $k=>$t)
{
  preg_match_all("/(\d.*)/",untag($t,'link',0),$f);
  if($f[1][0]==$iscss){$iscss=$k;break;}
}

Once I had $iscss defined, the rest was applying the style:

<link rel="StyleSheet" href="<?php echo untag($tables[$iscss],'cssurl',0);?>" 
type="text/css" />

Next was displaying the current style information:

<h3><strong>Current style:</strong> 
<a href="<?php echo untag($tables[$iscss],'cssurl',0)?>" 
title="Download this CSS example">
<?php echo untag($tables[$iscss],'title',0);?></a> 
by 
<a href="<?php echo untag($tables[$iscss],'authorurl',0)?>">
<?php echo untag($tables[$iscss],'author',0)?></a></h3>
<p><?php echo untag($tables[$iscss],'description',0);?></p>

Last but not least was the table to display, the few interesting things there was adding the "odd" row class to each second row by checking if the modulo of the array counter and 2 is 0 and testing if the author submitted a URL or not and only add the link to it when there is one.

<table summary="Submitted table designs">
  <caption>Table designs</caption>
  <thead>
    <tr>
      <th scope="col">Design Name</th>
      <th scope="col">Author</th>
      <th scope="col">Country</th>
      <th scope="col">Comment</th>
      <th scope="col">Download</th>
    </tr>
  </thead>  
  <tfoot>
    <tr>
      <th scope="row">Total</th>
      <td colspan="4"><?php echo sizeof($tables);?> designs</td>
    </tr>
  </tfoot>
  <tbody>
    <?php foreach($tables as $k=>$table){ ?>
    <tr <?php echo $k%2!=0?'class="odd"':'';?>>
      <th scope="row">
	  <a href="index.php?css=<?php echo untag($table,'link',0)?>">
	  <?php echo untag($table,'title',0)?></a></th>
      <td>
	  <?php if(untag($table,'authorurl',0)!=''){?>
	    <a href="<?php echo untag($table,'authorurl',0)?>">
	  <?}?>
	  <?php echo untag($table,'author',0)?>
	  <?php if(untag($table,'authorurl',0)!=''){?>
	    </a>
	  <?php }?>
	  </td>
      <td><?php echo untag($table,'authorcountry',0)?></td>
      <td><?php echo untag($table,'description',0)?></td>
      <td><a href="<?php echo untag($table,'cssurl',0)?>" 
	  title="Download the <?php echo untag($table,'title',0)?>
	   CSS file">Download</a></td>
    </tr>
    <?php } ?>
  </tbody>    
</table>

The last thing to do was to generate the RSS feed. This is done by stripping the XML data file of the extra data and only getting the last 5 entries:

# load the data file
$handle = @fopen('tablestyles.xml', "r");
$contents = @fread($handle, filesize('tablestyles.xml'));
@fclose($handle);
if($handle==''){die('No styles found.');}

# strip the non-RSS stuff
$contents=preg_replace("/<author>.*?<\/author>|
<authorurl>.*?<\/authorurl>|
<authorcountry>.*?<\/authorcountry>|
<cssurl>.*?<\/cssurl>/msi",'',$contents);
$con='';
# grab all items
$items=untag($contents,'item',1);
# add the last 5 items to $con
for($i=sizeof($items)-5;$i<sizeof($items);$i++)
{
  # convert the ID to a real link
  $con.='<item>'.preg_replace('/<link>/msi','<link>
  http://icant.co.uk/csstablegallery/index.php?css=',$items[$i]).'</item>';
}
# replace the old items with the five converted ones
$contents=preg_replace('/<item>.*?<\/channel>/msi',$con.'</channel>',$contents);
# set the right header and print it out
header('Content-type: text/xml', true);
echo $contents;

That was all, nothing to it really. Hopefully this answers your questions and inspires you to code as shoddy :-)