Creating a virtual card catalog

Ever get nostalgic for the old card catalog?

I was lurking on #code4lib and someone dropped a link to some fabulous old catalog cards. That reminded me of an idea Eli Neiburger had to make a flash-based card catalog that you could flip through. Never one to let a good idea sit, I decided to work on a variation that would allow visitors to AADL’s catalog a chance to get their hands on a “virtual card catalog”.

Thanks to some handy photoshopping by Eric Klooster, I had some really great card-stock to work with. These have some real character! Here’s one:

Using PHP’s great GD front-end, I threw together an interface to view the cards and a little database that will allow users to add some marginalia. Of course, you can view the cards with or without the comments. Here’s a one with the comments disabled:

The background stock randomly rotates, as well as the handwriting font, so you can get some really neat-looking, unique cards:

Adding a little graffiti is just a matter of typing it in:

An unlimited number of comments can be added for each “position” on the card. They are simply randomly picked from the database and drawn on the image dynamically at render time.

Users can access these via the hitlist now, and soon via the item record itself. Also, I’m working on a way for registered users to save cards in a “personal card catalog”. That way, if they see card they like, they can revisit it later.

I’m sure the layout on these cards is far from orthodox, but they’re still kinda fun. Take a look and play around. Who says the OPAC can’t be fun?

[update 1/20/2006 2:15 PM]

I’ve added the ability for registered users to “collect” cards in their own personal card catalog. Users will then be able to go to their catalog and view the cards they saved (It saves the card exactly how it was. That is, it preserves the same background, fonts, etc). Per Ed’s request, users can also email their cards to friends and co-workers with an optional note.

This is a sample card with the “Add this card to your collection” link:

And this is what the Personal Card Catalog looks like. Notice that each card is thumb-nailed–even the comments:

Obviously, I need to do a little work on the personal card catalog, allowing users to filter, sort, search, etc. But this is a start.

[/update]

RESTful output from AADL catalog

After a somewhat restful day… (groan)

In an effort to make the AADL catalog a little more accessible to developers, I’ve written a little bit of middleware that generates REST output from the catalog. Yes, we currently have RSS feeds directly from the catalog, but they are not suited for true development. REST output will allow developers to freely access both hitlist data and bibliographical data without having to do any funky scraping, parsing, or wand-waving.

Please take a look, hack away, try to break it, whatever. Beta testers are always welcome!

Here are the details:

If you were to do a keyword search for “Harry Potter” on our catalog, you would see the URI looking like this:

http://www.aadl.org/cat/seek/search/X?Harry%20Potter&searchscope=26&m=&SORT=D

That, of course, is the hitlist. You want RESTful output. So change the URI to:

http://www.aadl.org/cat/rest/search/X?Harry%20Potter&searchscope=26&m=&SORT=D

Basically, you are just changing “seek” to “rest”. The base URI for the REST interface is http://www.aadl.org/cat/rest/ but going there without a query won’t get you much. Anyway, the output from the preceding looks like:

<?xml version="1.0"?>
<p:Records xmlns:p="http://www.aadl.org"
           xmlns:xlink="http://www.w3.org/1999/xlink">
	<Record id = "1249810" xlink:href="http://www.aadl.org/cat/rest/record/1249810"/>
	<Record id = "1251743" xlink:href="http://www.aadl.org/cat/rest/record/1251743"/>
	<Record id = "1239167" xlink:href="http://www.aadl.org/cat/rest/record/1239167"/>
	<Record id = "1260602" xlink:href="http://www.aadl.org/cat/rest/record/1260602"/>
	<Record id = "1249532" xlink:href="http://www.aadl.org/cat/rest/record/1249532"/>
	<Record id = "1249531" xlink:href="http://www.aadl.org/cat/rest/record/1249531"/>
	<Record id = "1230466" xlink:href="http://www.aadl.org/cat/rest/record/1230466"/>
	<Record id = "1258774" xlink:href="http://www.aadl.org/cat/rest/record/1258774"/>
	<Record id = "1237981" xlink:href="http://www.aadl.org/cat/rest/record/1237981"/>
	<Record id = "1224899" xlink:href="http://www.aadl.org/cat/rest/record/1224899"/>
	<Record id = "1236034" xlink:href="http://www.aadl.org/cat/rest/record/1236034"/>
	<Record id = "1228878" xlink:href="http://www.aadl.org/cat/rest/record/1228878"/>
</p:Records>

That’s useful to get the hitlist of records for that search. Obviously, those URI’s above denote the corresponding records in REST format. The first one (http://www.aadl.org/cat/rest/record/1249810) looks like:

<?xml version="1.0"?>
<p:Record xmlns:p="http://www.aadl.org"
          xmlns:xlink="http://www.w3.org/1999/xlink">
	<callnum>823 Bu</callnum>
	<author>Burkart, Gina, 1971-</author>
	<fulltitle>A parent's guide to Harry Potter / Gina Burkart</fulltitle>
	<title>A parent's guide to Harry Potter </title>
	<pubinfo>Downers Grove, Ill. : InterVarsity Press, c2005</pubinfo>
	<desc>112 p</desc>
	<bibliography>Includes bibliographical references</bibliography>
	<contents>The Harry hype -- More than a story -- The modern fairy tale -- Discussing fantasy with children -- Morals, not magic -- The real issues in Harry Potter -- Dealing with traumatic experiences -- Facing fears -- Battling bullies -- Delving into diversity -- Hiding hurts -- Letting go of anger -- Getting help -- Choosing good over evil -- The power of love -- Facing spiritual battles</contents>
	<isbn>0830832882</isbn>
	<price>$11.00</price>
	<lang>eng</lang>
	<copies>0</copies>
	<catdate>08-16-2005</catdate>
	<mattype>a</mattype>
	<avail>No copies available</avail>
	<recordlink xlink:href="http://www.aadl.org/cat/seek/record=1249810"/>
</p:Record>

This data would be very easily accessible using something like PHP’s simpleXML. I think one of my next little side projects will be to write a class that accesses this and make it available for download here. Enjoy!

III XMLOPAC 1.8 Update

iii-xmlopac-1.8.tar.gz

I’ve fixed a problem in the xmlopac class that would sometimes return key fields such as author or title as “GarbageData”. The problem basically stems from the fact that PHP doesn’t have an extensive enough set of html_special_chars to handle what’s being thrown at it from Innovative. You’ll find that 1.8 will return better results overall now. Be sure to grab it.

III Bib # to ASIN to Cover Art

azImgSrc-1.0.tar.gz

I’ve written a PHP script that takes a III Bib # and, using amazon’s REST interface, it tries it’s darnedest to find the ASIN for that item. It will then store that Bib#-ASIN pair in a database. After that, it will cache the small, medium and large cover images associated with that ASIN in another database table and display whichever one you want.

This script requires the latest version of the III-XMLOPAC class (1.6), PEAR::DB, MySQL (of course) and PHP5 (or PHP4 with SimpleXML). In addition to that, you’ll need to have your own Amazon Dev token, etc.

Essentially, I wanted a way to get more cover art into the catalog. If you currently use Syndetics, you’ll know that you almost never get any cover art for CDs and DVDs. My solution was to write this. Just to warn you, though, this script will not return ASINs and cover art for all the items in your collection. Far from it. There is about a 30% hit-rate. I could easily get that higher, but then accuracy drops off, and I want 100% accuracy.

So, I plan on working with this script, massaging the search to figure out ways to get that 30% up. Please feel free to hack away at it yourselves too, but bear in mind, that I’m looking for accuracy above all else. If you’re really interested in how I’m determining an accurate hit, take a look at the code. Basically, I’m doing an initial search, then I match the UPC number on the amazon record to the stdnum info from the Bib record. Doing it this way, I haven’t seen a wrong match yet.

Incidentally, here is a hit list with images from this script:

To use it, you’d basically do something like this:

<?php
 
$bibnum = "123456";
echo  '<img src="/azImgSrc.php?bnum=' . $bibnum . '">';
 
?>

As a side bonus, you’ll have a nice table with Bib#-to-ASIN data. You can even manually add data to that table to ensure your favorite records have images associated with them.

III-XMLOPAC class update 1.6

[update] iii-xmlopac-1.7.tar.gz [/update]

I really love that Casey keeps adding functionality to the III XMLOPAC class. I've incorporated his latest function that grabs alternate ISBN numbers from OCLC's xISBN service into 1.6.

Because of his function, however, I've changed the way get_opac_data() is called. The change is completely backward compatible, so don't worry about anything breaking after you upgrade. The new prototype looks like this:

<?php
$bibinfo = get_opac_data($bibnum, $extend = NULL);
 
// Of course, you can just call it like this:
$bibinfo = get_opac_data($bibnum);
?>

Essentially, Casey's function will only be called if $extend is TRUE (or some value). I've implemented it this way because this class gets some heavy use and I don't want it polling OCLC every time I grab a bib record. I envision the $extend flag to be used in cases where external web services are queried. By default, those features will be disabled.

Also, in 1.6, I've fixed a pretty bad bug that would often times return an invalid ISBN. I've broken that bad ISBN number off into the "stdnum" key instead.

If you're using this class, you definitely should upgrade to 1.6.

[update]
Actually, grab version 1.7. I didn't add a test to make sure a record has an ISBN before it's shunted to Casey's function. As such, you might get a PHP warning depending on your error report settings. Nothing major, just an annoyance, 1.7 fixes that.
[/update]