Monkeying With JavaScript
It’s funny really, one of my main reasons for switching to a Rails-based blogging platform way back when was to become more familiar with web technologies. As it turned out I never really did much of that, but since switching back to Wordpress I’ve been tinkering away madly, and astute observers may have noticed the results on this site.
Of course I have no real idea what I am doing. Despite having zero knowledge of PHP or JavaScript, for some reason I feel no reluctance towards sitting down at a keyboard and bashing away until I produce either Macbeth or a better website. The entire site is stored in a Bazaar repository, and that makes reverting bad changes especially easy, and I’ll attempt to blog further about that sometime.
For now let me just point out a seemingly small change to the site. The dates of the posts and comments are now displayed in a more human-friendly manner such as “3 days ago” or “20 minutes later”. This was a feature of Typo that I liked enough to port to my Mephisto theme, and which (I thought) would be fairly simple to get into Wordpress.
It wasn’t. Read on for the war story.
The Prototype Version
John Wang describes how it is implemented in Typo. Basically it’s a bit of JavaScript that is run when the page loads. It looks for dates, which are delimited by the abbr
tag and have a pre-defined CSS class. The script iterates over each of these and converts them into a friendly date. The abbr
tag is handy because it allows you to specify the full date and time in the title
attribute, which you can see when you hover over the date with your mouse.
One of the challenges with using JavaScript in this way is to ensure that you register event handlers in a manner that works with other JavaScript on the page, as well as across browsers. The Prototype library helps out immensely here, and for actually locating the abbr
tags.
One of the nice features of Wordpress is that it manages dependencies on third-party JavaScript libraries, on behalf of the plugins. So as long as your plugin/theme uses the wp_enqueue_script
function, Wordpress will find a copy of the requested library and insert your script correctly into the HTML output. You call it simply from the theme’s functions.php
file like this:
add_action( 'wp_print_scripts', 'depo_theme_add_javascript' ); function depo_theme_add_javascript() { wp_enqueue_script('friendly_dates', get_bloginfo('stylesheet_directory') . '/javascript/friendly_dates.js', array('jquery')); }
So at this point, I had the friendly date script originally from Typo, registered correctly with Wordpress and, it worked. Sort of. Specifically: when I had some of my Wordpress plugins disabled.
Prototype vs jQuery
Besides Prototype there are also other JavaScript libraries that people use, and they don’t always play nicely together. For example, jQuery is quite popular, and seems to be used by at least two of the wordpress plugins I have installed. Which meant that I could use my date script or the plugins, but not both.
Now jQuery (at least) is supposed to play nice with other libraries if you use the noConflict
method. Unfortunately I couldn’t get it to work. I even resorted to asking my first question on Stack Overflow. This seemed to stump the experts too; the best answer was basically “switch to jQuery”.
So that’s what I did.
The jQuery Version
jQuery is a quite unusual library. It reminds me a little bit of XSLT, in that you declare a pattern of matching items in the DOM tree, and for each of those, some actions which affect the output. You might even say the similarity is quite ironic, given that XSLT is the browser’s other scripting language.
By chance I came across yet another pretty date JavaScript from Zach Leatherman (but with ancestry tracing back to jQuery author John Resig). This allowed me to perform the article date transformations almost trivially:
jQuery(document).ready(function() { jQuery("abbr.published").humane_dates(); });
Nice. But what about the comment dates? These require two dates, both the comment date but also the date of the article to which it belongs. The former is easy enough, but there was no easy DOM path from the comment to its article meta data. If it was XSLT I could have come up with an XPath expression, but jQuery is unfortunately not that powerful (yet?).
So I settled for a bit of a hack. For each comment, I inserted the article date as a hidden field in the HTML as a sibling to the date abbr
, where it can be easily retrieved by a jQuery method.
It’s not an ideal solution of course, and part of me wants to (at least) put the article date in a local cache variable where it doesn’t need to looked up all the time. But another part of me just wants to get it working so that I can start the process of blogging about how I got it working…
Publish and Be Damned
Anyway here’s the code. I’ll find a better place for it if I make any other mods, or if there is any interest in it.
Lessons Learned
I’m not even sure there are many here. Perhaps:
- Don’t mix JavaScript libraries.
- Learn jQuery. It’s powerful.
- C++ is easy compared to diagnosing JavaScript bugs (ok maybe not)
10 Comments