All in all, I’ve been pretty unhelpful in the coordination of Code4Lib 2006. Those that know me know I’m not terribly organized and horribly forgetful, so I knew it wasn’t in anybody’s best interest for me to commit to much. With that, I felt it best if I was involved with the proposal submission/vetting process.
Early in the organizing process, the “organizing group” (committee is far too strong a term) set up a Backpack page to keep up with all of our tasks and documents. It worked pretty well. I liked the idea of a centrally located “document” that was editable by several users (the “proposal submission group” was made up of myself, Jeremy Frumkin and Dan Chudnov (on a non-committal basis)), so I used another Backpack page to compile the submissions. I am glad that I did this; I would never have been able to keep up with them, otherwise.
As we got closer to the submission deadline, it dawned on me that I needed to set up the voting mechanism quickly (we had decided to allow any potential attendees vote on the program they wanted to see). Roy Tennant had toyed with the voting module in drupal (since that’s what code4lib.org runs), but it wasn’t quite what I had pictured.
What I wanted was:
- A page where the user could see all the proposals at once
- A simple up or down vote
- A way to tally how many “yea” votes the user has cast (since we were allowing them to cast 11 votes)
- A way for the user to revise their votes
- An auditing system
- Something to tally the votes for me
So I made my own. One nice side effect to having compiled all of the submissions in Backpack was that it was very easy to screenscrape. All of the “notes” are contained in divs that have the class “note”. The id attribute contains a unique id for that note and the titles are contained in an H3 within that div. Perfect for scraping.
The first thing I did was set up a simple MySQL database that contained three tables: voters, proposals and votes. Voters probably wasn’t necessary, but I had this original plan to “register to vote” within code4lib.org and then the voting mechanism would “review your registration”. It wound up being much less sophisticated. So, basically “voters” was two fields, drupal user name and id.
“Proposals” was also just two fields: id and title, and the intention was that this would get scraped from the Backpack page (the id being the unique “note” id). “Votes” was just a joining table between voters and proposals.
Next, I made a bookmarklet that rewrote the Backpack page to have a bunch of forms with submit buttons on them within the “note” divs. There’s a lot of wasted space in Backpack, so I inserted an Iframe under the Backpack logo in the right column to tally the user’s votes. The bookmarklet was pretty simple and can be found here.
Next, I wrote a PHP script that set in the Iframe and tallied the votes. When the user posted a vote, it would check to see if the proposal had already been added to the proposals table (if not, it would add it) and add the user’s vote to the “votes” table. It would output all that they had already voted for and let them know how many votes they had left. It would also create links next to each submitted vote for the user to remove a cast vote.
The last step was making a node in Drupal that create made a bookmarklet link that included the user’s username (the user needed to be logged in to vote). This step, sadly, took me the longest because I had no idea how to get the username in Drupal. It turns out you can “global” the $user variable and have access to all its attributes.
Lastly, I created a handful of webservices to keep a running tally of which proposals had enough votes to “win”, a list of registered voters and how many votes they had cast, and (when more reshuffling the schedule allowed 3 more presentations to be accepted) a list of all proposals and their vote counts.
For throwing something together at the last minute, it worked ok. There is one user that doesn’t have a username (no clue who that is or why it happened) and Ed Corrado doesn’t appear in the registered voters output because his “voting cookie” was set before I cleared out all of the “test votes” (I think).
All in all, a fun little hack.