Friday, September 12, 2008

The joys of debugging

Looking at other people's code can be enlightening. I've been looking for an excuse to try out Benjamin Keen's smartlist plugin for jQuery for a while now. (The jQuery website was recently redesigned and is even more awesome now.)

One of the most important questions a potential student may hope to answer on our website is “Can I get the degree I want?” Actually, it's probably a bit more abstract than that. I know when I evaluate schools, from my own time at a community college to my undergrad days to my current graduate program, I care less about the degree than I do about the topics covered and the skills developed. I care about the topics because if I'm going to devote a couple years of my life to a program, I want to make sure it will hold my interest. The skills are important because ultimately that's what gives me an edge in my chosen job market. I doubt anyone surfs over to our website specifically looking for a degree in biotechnology, but s/he may have an interest in chemistry and biology already and may be considering a career path where such a degree offers a competitive edge.

In it's simplest form, this question could be written as “What do you have to offer me?” (The only question more important than this one is probably “How much will it cost me?”) Each student evaluates that question through criteria specific to his or her needs, wants, and experiences. The form of this evaluation follows traditional models of interpersonal communication (that is, a spoken conversation) more so than print materials. We really need a new model for a new communications medium, but I'll leave that for this generation's Peirce or McLuhan or Leary. (No, really. Leary wrote and lectured on cyberspace and virtual reality after the whole LSD thing blew over.) In the mean time, the idea of a conversation fits better than the idea of a book or newspaper article.

If you've taken a look at the smarlists demo you may see where I'm going with this.

The ability to tag (or flag, as Ben calls it) the items in a smartlist can foster the sort of back and forth communication that the web thrives on. This is something that will need a lot of testing, of course, because the initial set of tags may not fit the words in the minds of our students. There's also a careful line to walk between providing enough tags to make the ability to sort through the data useful vs. introducing a new flavor of information overload. It's very experimental, but I think it can be done right and I think it can be a great help to our students, both current and potential.

So yesterday I actually started building this new application for the redesigned site (still only available via IP from on campus, I'll link it here once we publicly release the beta). The first thing I notice is the demo uses a table. I furrow my brow, thinking a table isn't necessarily the best way to approach this as far as semantics go. I look a bit closer and realize the plugin is written in such a way to allow me to use any html tags I want. I just need to apply the right classes to those elements so the script knows what everything means. Ideally, I'd like to use a definition list. But that would require me to wrap each <dt> / <dd> set in a <div> since the script expects the list of tags (or flags) to be a child element of (that is, contained completely inside) the element defined as an “item”. I don't think a <dl> likes being filled with block level elements like <div>s between itself and its children. I could do a definition list per item, but that seems like over kill. Eventually, I settled on an unordered list with a few paragraph tags inside the list items and appropriate classes scattered throughout.

I build enough of the list that I feel it's testable. In hindsight, I should have built the smallest possible test case, something like 3 items and 4 tags. Everything worked fine as long as you clicked links. Pagination worked. Filtering by clicking on the tags worked. Resetting the list by choosing the default option on the drop down list also worked. Selecting a tag from the drop down resulted in all items being hidden. Strangely, the pagination still worked. In other words, if the list is showing 10 items per page, and you select a tag with 25 items, you get the links for 3 pages just like you should. But all 3 pages are blank. I run in to this particular error around lunch time yesterday. I pour over the code for about 3 hours looking for differences between my local, broken code and the functioning code published with the demo. It appears to be exactly the same, and it should be, I downloaded from the source, right?

Eventually, I check the jQuery code on the demo. That's version 1.2.3. I'm running 1.2.6 (actually just one revision removed, 1.2.4 and 1.2.5 were skipped for various reasons). I ran into a similar problem with a plug in when 1.2.3 was new. Back then I found a page in the documentation that explained exactly what functions were changed and how. That made it very easy to discover a couple of functions were being called that were no longer available. I replaced those 2 functions with the new single function that supersedes them in the new version and was back up and running in less than an hour. This time around, I the documentation on the changes (short version, full version) between versions was less helpful. :(

But at least now I know it's a problem due to changes in the most recent version of jQuery. Now I feel justified in contacting the author directly. I use the form on Ben's site to contact him, explaining what I've found so far so at least he knows I tried to fix the problem myself, and ask if he has put any work into updating the plugin that just haven't been published to the site yet. I go back to troubleshooting for about half an hour before I bother checking for a reply. Turns out that was a mistake because he replied almost immediately. He said I was the 3rd person to write him on the same issue and it seems to be a change to the inArray() function but he hasn't tracked down the exact nature yet.

I start to reply talking about how that doesn't seem to make sense because I had just read over that bit of code in the half hour since I first wrote him and the inArray() function is called the same way no matter which event triggers the action. Since it works fine when clicking a link but fails when selecting from the drop down menu, the problem has to be related to the triggering event. But the only place I can find where that makes a difference is the way a specific variable is set. I checked the state of that variable after it's set using either method and it contains the proper value. These are the thoughts going through my head as I begin to type my reply, but I don't quite make it that far. If you've got any experience debugging JavaScript or any other loosely typed language you may have figured this out already too.

The problem was the variable was a number when set by the click event, and a string when set from the drop down menu. The default value worked because it's a string rather than an index number.

You know what? I just realized that the fix I made last night introduces a new bug. I was just casting the value via the Number() function, but that screws up the default string value. Crap. So the full fix is an if statement checking for the default value and casting if it's not found. I'm off to make that change and then hopefully I'll be done.

Look for updated code to hit Ben's site in the not too distant future. :)

No comments: