Wednesday, April 13, 2011

The Tale of 26 jQuery Click Handlers

I quickly coded up 26 distinct click handlers in jQuery for a client project that needed alphabetical sorting and display of SharePoint Discussion Forum roll-ups. The click handlers loaded an application page in a DIV tag via AJAX. I called the application page with a query string variable that passed the letter of the alphabet. It was a very simple interaction.

Because of the simplicity of copy and paste, I put together these 26 click handlers in less than a minute:

$(document).ready(function () {

    $('#a').click(function () {

        $("#alpharesults").load("/_Layouts/ClientABC/ForumPuller.aspx?alpha=a");

    })

    $('#b').click(function () {

        $("#alpharesults").load("/_Layouts/ClientABC/ForumPuller.aspx?alpha=b");

    })

   ...

    $('#z').click(function () {

        $("#alpharesults").load("/_Layouts/ClientABC/ForumPuller.aspx?alpha=z");

    })

});

The markup for these click handlers were very simple as well:

<li id="a"><a href="#">a</a></li>

<li id="b"><a href="#">b</a></li>

...

<li id="d"><a href="#">z</a></li>

After some thought I realized that I would always need 26 distinct click handlers on the DOM to account for all 26 letters of the alphabet. One click handler to account to for one letter of the alphabet and to pass that letter via query string to the application page. I was bothered by the lack of elegance in my initial proposed solution. I grabbed a club sandwich for lunch, then had a revelation.

I could redesign the markup in such a way that jQuery would magically know which letter was associated with the click:

<li class="alphabar"><a href="#">a</a></li>

<li class="alphabar"><a href="#">b</a></li>

<li class="alphabar"><a href="#">c</a></li>

...

<li class="alphabar"><a href="#">z</a></li>

Since all the letters shared the same parent class, in this case "alphabar", I created a single click handler that would roll down through all matching elements of the DOM. jQuery could then let the click handler know which letter was clicked by reading the .text() value of the clicked selector. jQuery's .text() method retrieves only the text between the tags, regardless of any obsfucated tagging like the anchor tags in my markup.

My 26-in-one click handler:

$(document).ready(function () {

    $('.alphabar').click(function () {

        var alpha = $(this).text();

        $("#alpharesults").load("/_Layouts/ClientABC/ForumPuller.aspx?alpha=" + alpha);

    })

});

I only changed a few things in my smaller "on ready" scripting:

  • I changed the selector for the click handler from an id to a class based selector. This allows all elements with the same class designation to receive their own click handler,
  • I added a variable called "alpha" to collect the clicked alphabetical letter using the magic of the $(this) selector and the .text() method,
  • And I used the "alpha" variable to pass the alphabetical letter to the application page query string.

Oddly enough 26 click handlers get built into the DOM "on ready" with both new and old methods. There must always be a one-to-one relationship between the click handlers and each letter in the alphabet. The new method made the scripting easier to manage and provided me with a sense of satisfaction. It also gave me that sense of elegance I had lost with copy and paste solution.

Thank goodness for club sandwiches!