Cumulative Voting with JQuery

W3C has its own system designed to create, answer and gather results from votes, strawpolls, registrations, etc., known as WBS; I have been developing and maintaing this system over the past six years – I’m hoping to find sometimes the time and energy to make that tool open-source, but given that this requires abstracting many of its W3C-isms, I’m not holding my breath. WBS knows a variety of types of questions that can be included in the questionnaires it creates: open comments, radio-selectable list of choices, checkboxes-selectable list of choices, timetable selector, etc. It is also (more or less weel) designed so that new types of questions can be reasonably easily added. As part of an upcoming survey for W3C Members, it was requested that WBS handles a new type of questions, to support cumulative voting.

Screenshot of Cumulative Vote in WBS, without Javascript

Adding the server-side part of that new control was relatively straightforward, thanks to WBS architecture; but given the nature of cumulative voting, it seemed more or less required to complete it with a client-side layer (read “Javascript”) to ensure a minimum level of usability. Although I started writing Javascript almost as soon as I started writing Web pages some twelve years ago, I had grown wary of doing it; I restarted coding with it lightly over the past two years, but had found it quite cumbersome to write, in particular when wanting to do it properly, that is to say with graceful degradation, events binding, proper DOM operations, etc. So I figured that if everyone is raving about these new Javascript frameworks, there may be some reason to it and that I would better pay attention – and thus started using JQuery, mostly because it happened to be already set up on the W3C site and that I hadn’t heard or read bad things about it.

Screenshot of Cumulative Vote in WBS, with Javascript layer

Sure enough, one hour and a few tutorial pages later, I had written the 30 lines of code that were needed to support what I had in mind to ease the interactions with the cumulative voting. Quite impressive! Write less, do more seems to be right on target. The usage of CSS selectors to pick the elements on which you want to act is a bliss. I did have to tweak the code a bit to improve its performance – my initial code didn’t scale well when the number of options on which to vote went up; I fixed it up by relying on event delegation, essentially reducing the number of events binding by attaching the onChange event to the container of the select elements rather than to each of them. For sake of illustration, let’s compare the code to the one I would have needed to write without using JQuery (and not mentioning cross-browsers compatibility issues) for the first couple of lines:

  • Without:
    window.addEventListener('load', function() {
  • With:
    $(document).ready(function() {
  • Without:
    // Adding a line to the list with the total displayed
    divs = document.getElementsByTagName("div");
    for(i=0;i<divs.length;i++) {
      div = divs[i];
      if (div.class=='cumulative') {
        cumulativeSelectors = div.getElementsByTagName("ul");
        for (j=0;j<cumulativeSelectors.length;j++) {
          ul = cumulativeSelectors[j];
          if (ul.class=="compare") {
            li = document.createElement("li");
            totalSpan = document.createElement("span");
            totalInput = document.createElement("input");
            remainingSpan = document.createElement("span");
            remainingInput = document.createElement("input");
            totalSpan.appendChild(document.createTextNode('Total'));
            remainingSpan.appendChild(document.createTextNode('Remaining'));
            totalSpan.class=remainingSpan.class='label';
            totalInput.disabled = remainingInput.disabled = true;
            li.appendChild(totalSpan);
            li.appendChild(document.createTextNode(':'));
            li.appendChild(totalInput);
            li.appendChild(remainingSpan);
            li.appendChild(remainingInput);
          }
        }
      }
    }
  • With:
    // Adding a line to the list with the total displayed
     $("div.cumulative ul.compare").append("<li><span class='label'>Total</span>:
     <input disabled='disabled' /> <span class='label'>
    Remaining</span> <input disabled='disabled' /></li>");

And that’s taking the less complex part of the code… I think I’m going to like coding in Javascript again! I would be curious to read the XForms equivalent of this widget – any taker? Possible improvements to my cumulative voting widget include:

  • Packaging it as a JQuery widget – this could possibly be useful to others?
  • Using sliders to give a better visual feedback
  • Annotating the controls with WAI ARIA for improved accessibility and usability

One Response to Cumulative Voting with JQuery

  1. I’m still really liking the idea of having my html snippet templates in comments rather then a hidden element someplace.Though maybe another thought, this would also be a great way for the server to leave JS some instructions on certain elements, without having to fudge hiding them in the attributes. I know I’m guilty of picking an obscure attribute on a tag, to tell JS that this is a ..whatever.. and including a short list of actions of what can be done with that object. But now, I call say anything I want to JS in the comments, and not have to worry about the classic “Oh shoot, I ran out of attributes, except the title attribute.. that’s going to look really ugly if I put it in there.”.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Before you comment here, note that your IP address is sent to Akismet, the plugin we use to mitigate spam comments.