Thursday, April 24, 2008

Kudos to Scriblio and thoughts

Scriblio is a fantastic Wordpress module that makes it easy to build a discovery layer over your regular library catalog (or to make a completely new one). It is completely free and built by folks how care about libraries and users: Casey Bisson, Lichen Rancourt and Jessamyn West.

It seems to me that there are different people hacking away at OPACs--trying to mine & mash them and teach them new tricks. Efforts like Scriblio, LibraryThing for Libraries, John Blyberg's Drupal-based, Library Elf, and more.

I think we can reach some sort of synergy if we, at lease, share some code =)

Just counting the different implementations for "getting stuff out of a Millennium WebOpac record", I can count 3 (Scriblio's,'s and mine)... and they´re all PHP. And I can tell you I didn't use code from any of them (at the time I started I think Scriblio only had MARC import capabilities. Darn!)

With the Berkeley Accord, there might also be some standards, to boot. =)

Wednesday, April 23, 2008

Drupal Millennium module screenshots

Below are pics of the admin portion of the module; for a live demo you can try our implementation at

These are the general settings for the Drupal Millennium module, from where you can jumpstart your Next-Generation Library Catalog =)

Here's where you can manually queue items for import:

Apologies: Please download Millennium module v.1.2

I messed up; I did not thoroughly test version 1.1 of the module. However, you can now download 1.2 which also has some added niceties (thanks, roblivian!)

Drupal Millennium Integration now at 1.1

Added: Ajax loading of holdings information. Check it out.

Wednesday, April 16, 2008

Using ajax to load parts of a page in Drupal

I wanted to load some time-consuming content into Drupal nodes in the Millennium module, but didn't want the whole page to suffer for it. It looked rather hard at first, but I came across some code that made it clearer for me.

You will be putting funcionality in a module, so you'll need to know how to write a Drupal modules first.

First, you will need a DIV in your final page's HTML that will be updated via Ajax. It can be result of your module adding stuff to a node via the nodeapi hook, for example. I tagged mine like this:
<div class="millennium holdings load" id="nid-12345"> Text before loading goes here. </div>   
Also, you will need a backend portion that outputs HTML.

Now, remember your node or page can be listed along with others! (For example in search results showing teasers, Views, or the standard front page view in Drupal which shows teasers for all new published + promoted pages). So we will have to deal with multiple DIVs appearing from different pages, and write JS to deal with ALL of those.

You will have to write some JS to modify this div; I placed mine in the module's directory as millennium.js
// The following is Javascript

// Call millenniumUpdateNext() when page first loads.

* Looks for first div element with class "load" and updates it depending on its
id attribute. (DIVs should already have an id="nid-XXXX" attribute, where XXXX
* is the node's id.

function millenniumUpdateNext() {
// Get the first div element with the classes we are looking for
var div = $("div.load").get(0);
if (! div) return;
var id =;
if (! id || id.substr(0,4) != "nid-" ) return;

// Get the node id from the id attribute
var nid = id.substr(4); //nid-123456 --> 123456

* URL to get information from. If you go here in your browser you get plain HTML
* depending on the nid argument. This URL is defined in the module under
* millennium_menu()

var url = "/millennium_ajax?nid=" + nid;

// Show 'loading' message.
div.innerHTML = 'Loading...';

// Activate the ajax fetch from url. When done function(data) will get executed.
$.get(url, function(data) {
$("#"+id).hide(); // Hide
$("#"+id).html(data); // Replace 'loading' message with fetched HTML
$("#"+id).slideDown("slow"); // Un-hide it
// Now, "unmark" it so millenniumUpdateNext() skips this element
millenniumUpdateNext(); // Start over for another element
Back in your module, you should implement two things to handle the ajax calls: an item in the _menu hook, and the handler function itself.

First, the item in the menu hook:
function millennium_menu($may_cache) {
// cached menu items here...
if(! $may_cache) {
$items[] = array(
'path' => 'millennium_ajax',
'callback' => 'millennium_ajax_handler',
'type' => MENU_CALLBACK,
'access' => true
// ... more stuff
return ($items);
And now the handler function itself
* This function is the one that takes a long time to run...
* This is the whole point; to not delay the whole page load waiting for this
* to be put inline with all the other page elements.
function millennium_ajax_handler() {
$nid = intval($_GET['nid']);
$output = "<h2>You called
millennium_ajax with argument nid = $nid</h2>";
echo $output;
Now, you have the server-side code, and you have the client Javascript code, now you just need to tell Drupal to add the Ajax-able bits to nodes, and also load in the Javascript. Let's do this.

First, to output some custom portions into existing nodes, you use [modulename]_nodeapi(), like this:
function millennium_nodeapi(&$node, $op, $teaser, $page) {
switch($op) {
case 'view':
// Load JS file in an orderly fashion.
drupal_add_js( drupal_get_path('module','millennium') . '/millennium.js');
// You can also load a custom CSS file here with drupal_add_css()...

// Add the custom content
$node->content['millennium_whatever'] = array(
'#value' => "<div class='millennium load' id='nid-". $node->nid ."'>This will be updated sometime after the page finishes loading.</div>\n",
'#weight' => 0,
This will add a DIV inside every node, with the classes millennium and load, and also an id attribute of nid-xxxxx

That's it! See how it shows on my test site showcasing the Millennium module.

Friday, April 11, 2008

Beta release of Millennium integration module

I am proud to announce the newest version of the Millennium integration module, which crawls a Millennium WebOpac and converts MARC into Biblio nodes, adds taxonomy terms, and can show holdings information in real-time.

Check it out here:

For a demo, go to

Communicate with your ILS via SIP2 in PHP

That's a mouthful of acronyms right there =)

cap60552 posted some code over at Google Code that lets you communicate via SIP2 with your library system. Badly needed, very welcome!

Thanks amyq! Via: