I have a client with a large product catalog in PDF format, which is close to 20MB to download. While this is fine for some of their customers, they wanted to give people the ability to only download what they needed, as well as the ability to sort of “flip” through it without having to wait on page loading.
While there are some very fancy ways to do this (Flash, etc.), I thought I’d offer up a simpler solution that I could implement in a timely, cost-effective manner by leveraging PHP, PEAR (the php extension library), and good ol’ MySQL.
Here’s an existing version of the company’s full catalog. They’ve had much success with this, so they asked me to do another for one of their smaller divisions, and I’m going to walk you through the process. Basically, we’re going to create a PDF catalog which will have a left-side navigation for the various sections. When a section is clicked, it will pull up a list of thumb-nailed pages linked to their corresponding PDF file, like so:

What You’ll Need
Of course, you’ll need a server running PHP 4 or later, a MySQL database, and PEAR’s Pager and HTML_AJAX modules. You should also be comfy with PHP, databases, and working at the command line (ssh, moving around directories, etc.).
The easiest way to install these PEAR packages is via the command line, which often requires root access to your server. Some hosting companies may have these, or at least a few, PEAR packages installed. But most shared hosts do not have these particular packages. You can ask them to do it for you, or, you can try these instructions for installing PEAR on a shared host, which I’ve gotten to work, although it can be tricky. (If you’re starting a new website, I highly recommend getting a dedicated server or at least a virtual server so you can have root access.)
To see what you have installed, login to your server via ssh, and type “pear list” at the command line.
Project Database Structure
So we’re going to create two new tables in our database. One will hold our categories, and the other will hold the pages. The client usually sends me a giant spreadsheet, and lucky for me, they take the time to create the jpg thumbnails and separate out the pdf files that will be linked from each thumbnail. Even so, I still have to massage the data a bit in Excel, so it looks something like this:

The name field is the name of the page (which will be linked along with the thumbnail), the cat_id is the category id (see screen shot » ), the start and end columns are the page numbers, thumb is the thumbnail image, and pdf is the corresponding pdf file. This will model our database column for column - the only difference is that the database will also have an auto-incremented “id” field as its primary key. I’m going to export this to a csv file, and import it using phpMyAdmin (tip: add an empty “id” column to your Excel/csv file, which will auto-populate the ‘id’ database field).
Now, in the categories table, you may wonder why I have a sort field - why not just sort by id? Clients have a habit of changing their minds about stuff - so this is purely precautionary. If this client changes the order of the catalog at some point, all I need to do it modify the sort column in the database, and never touch a line of code.
In the same directory as the code goes in, I create a “pdf” folder and a “pics” folder to hold the thumbnails and PDFs.
The PHP Code
So now we have all of our data imported, and we’re ready to build the actual catalog. I split it up into 3 files:
- index.php - the page that will display the data to the end user
- master-ajax.php - the page that contains our sql queries, and generates the HTML
- server.php - this just sets up the AJAX server, which will dynamically generate each category of the catalog, without having to reload the page
The last 2 of these files will be included in index.php. Because of this, I keep all these files in the same directory so I don’t have to fuss with include paths. Let’s work our way backwards.
server.php
All this page does is setup our AJAX server, then it listens for requests:
<?php
include 'HTML/AJAX/Server.php';
$server = new HTML_AJAX_Server();
$server->handleRequest();
?>
master-ajax.php
This page does all the heavy lifting for us. It performs our database lookups, performs paginations with PEAR Pager, and populates a data array that will hold our AJAX-i-fied HTML. It’s the longest file here, so I just dumped it into a text file. I did my best to comment it well.
index.php
I’m not going to bother with the entire page, only the part that displays our AJAX data:
<div id="catalog">
<script type="text/javascript" src="server.php?client=all"></script>
<div id="target" style="margin: 0; padding: 0;">
<p style="margin: 0; padding: 0;">
Please hold while the catalog pages are loaded...
</p>
</div>
<script type="text/javascript"> HTML_AJAX.replace('target', 'master-ajax.php');</script>
</div>
All this does is embed some JavaScript, which sets up our AJAX server and calls our master-ajax.php page to populate the data. If the end user’s connection is slow, it will display a message to sit tight while the data is being retrieved.
And there you have it! You can see the working example here.
Drawbacks
There are a couple drawbacks to this approach. For one, search engines will not be able to read this data. In general, search engines can’t read any data embedded in JavaScript. If it could, I’m sure we’d see a lot more of this type of stuff. However, the website that I used this on does have a full version of its catalog in PDF format, which the search engines can read, and it also has a ton of other information about its products in addition to this nifty little AJAX catalog. The goal here was to please the end-user, not the search engines. However, it pays to be up front with your client about this stuff.
The other drawback is that no matter what page of the AJAX catalog is being viewed, the URL is always the same. This prevents people from bookmarking and emailing a specific part of the catalog.
So there you have it - please feel free to let me know if anything is overly confusing, or any errata - cheers!
Leave a comment