3 Value Checkbox with JQuery
Monday, March 24th, 2008Few days ago I did that whole 3-value checkbox thing basing it on some script I found online. I went back and I re-implemented it using some JQuery magic. I’m not going to reiterate the whole setup here. I recommend that you check the linked post for details. You can find the JQuery-fied code below:
$(document).ready(function() { checked = '/path/to/checked.jpg'; unchecked = '/path/to/unchecked.jpg'; na = '/path/to/na.jpg'; i = 0; // replace the checkboxes with images $("form.funky_form > fieldset.funky_set :checkbox.funky_box").hide().each(function() { img = document.createElement('img'); img.className = "funky_image"; switch($(this).val()) { case "0": img.src = unchecked; $(this).attr("checked", "false"); break; case "1": img.src = checked; $(this).attr("checked", "true"); break; case "2": img.src = na; $(this).attr("checked", "true"); } // these will let us identify which image was clicked // and which checkbox does it belong to $(this).attr("id", "input" + i + "image" + i); $(img).attr("id", "" + i + "image" + i); i++; $(this).before(img); }); // add onClick functionality to the new images $(".funky_image").click(function() { // select the checkbox corresponding to the clicked img t = $("#input" + $(this).attr("id")); switch(t.val()) { case "0": $(this).attr("src", na); t.val(2).attr("checked", "true"); break; case "1": $(this).attr("src", unchecked); t.val(0).removeAttr("checked"); break; case "2": $(this).attr("src", checked); t.val(1).removeAttr("chekced"); } }); });
The major difference from the other version is that I’m much more discerning in which checkboxes get converted. The code will select only a box that is of the class funky_box and is inside a fieldset with a class of funky_set and inside a form with a class of funky_form. I’m mostly doing that to show power of JQuery - this is all specified in that very first select statement. I was trying to do something similar in the old code, but I was getting hung up on the silly DOM gotchas. JQuery makes this easy.
Also note the chaining functions. The first line after I declere i both hides all the selected check-boxes and begins the each block. Similarly, check out the second switch statement. In several places I set the value of t and change the checked attribute on the same time. It’s very expressive, and lends itself toward very compact and concise code.
Here is the HTML for the form to go with the code above (note the inclusion of the fieldset tag):
<form name="funky_form" method="POST"> <fieldset class='funky_set'> <label for="c1"> <input type="checkbox" name="c1" value="1" class="funky_box" checked> Some Important Task </label><br> <label for="c2"> <input type="checkbox" name="c2" value="1" class="funky_box" checked> Some Important Task #2 </label> </fieldset> <label for="c3"> <input type="checkbox" name="c3" value="1" class="funky_box" checked> This is a checkbox with the funky_box class outside the funky_set </label><br><br> <input type="submit" value="Submit"> </form>
How readable is this version? To me it is actually better because it’s smaller, and more compact. To someone who never worked with JQuery it might be a bit confusing at first but I think you get used to the weirdness pretty quickly. I find the selection statements much more elegant than nested loops for example, even if they might The more code I can see on my screen the better. I’m not golfing though - all the methods and most variables have meaningful names (well, except stuff like t and i but you know how it goes).
Which version do you like better?
