views:

144

answers:

1

Hi, I am creating a page that allows users access to a certain section of my website if they click 8 out of 25 checkboxes in the right sequence.

First of all thanks to Reigel for the code, its way better than what I initialy started with.

My question is, can the javascript code I have be optimized. For instance, the clearforms function, or anything else. I am a noob, just started to work with javascript 3 days ago, so any advice is appreciated.

My code is as follows:

<body onLoad="clearForms()" onUnload="clearForms()">

 <p>&nbsp;</p>
 <p>&nbsp;</p>
 <p>&nbsp;</p>
 <p>&nbsp;</p>

<form id="form1" name="form1" method="post" action="check_combination.php">
<table width="200" border="1" align="center">

<tr>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="1" /></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="2"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="3"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="4"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="5"/></td>
</tr>

<tr>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="6"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="7"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="8"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="9"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="10"/></td>
</tr>

<tr>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="11"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="12"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="13"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="14"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="15"/></td>
</tr>

<tr>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="16"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="17"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="18"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="19"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="20"/></td>
</tr>

<tr>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="21"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="22"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="23"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="24"/></td>
 <td width="20" align="center" valign="middle"><input name="checkbox" type="checkbox" value="25"/></td>
</tr>

<tr>
 <td height="23" colspan="5" align="center" valign="middle" class="label"></td>
</tr>

<tr>
 <td height="28" colspan="5" align="center" valign="middle"><input type="button" value="Test length" id="test" /></td>
</tr>

<tr>
 <td height="28" colspan="5" align="center" valign="middle"><input type="submit" name="button" id="button" value="Submit" /></td>
</tr>

<tr>
 <td height="28" colspan="5" align="center" valign="middle"><input type="button" name="button" id="button2" value="Test hidden input value" /></td>
</tr>

</table>

<input name="result" type="hidden" id="result" />

</form>

</body>

And the javascript:

function clearForms() {
    var i;
    for (i = 0; (i < document.forms.length); i++) {
       document.forms[i].reset();
    $(':checkbox[name=checkbox]:disabled').attr('disabled', false);
    }
}


//initial checkCount of zero
var checkCount = 0;

//maximum number of allowed checked boxes
var maxChecks = 8;

$(document).ready(function() {

    $(':checkbox[name=checkbox]').click(function() {

        //update checkCount
        checkCount = $(':checked').length;

        if (checkCount >= maxChecks) {
            //alert('you may only choose up to ' + maxChecks + ' options');
            $(':checkbox[name=checkbox]').not(':checked').attr('disabled', true);
        } else {
            $(':checkbox[name=checkbox]:disabled').attr('disabled', false);
        }

        if (this.checked) {
            $("td.label").append('<label>' + this.value + ' </label>');
        } else {
            $("td.label").find(':contains(' + this.value + ')').remove();
        }

        $('input[name="result"]').val($("td.label").text());

    });


    $("#test").click(function() {
        alert($(':checked').length)
    });

    $('#button2').click(function() {
        alert($('input[name="result"]').val());
    });

});

And this is the modified javascript per advice of Peter Ajtai (Thanks Again! To Peter, and Reigel the person who took the original code I had and rewrote it entirely to shorten it.)

function clearForms() {
    var i;
    for (i = 0; (i < document.forms.length); i++) {
       document.forms[i].reset();
    $(':checkbox[name=checkbox]:disabled').attr('disabled', false);

    }
}


//initial checkCount of zero
var checkCount = 0;

//maximum number of allowed checked boxes
var maxChecks = 8;

$(document).ready(function() {

clearForms();

var $nameCheckbox = $('input:checkbox[name=checkbox]');

    $nameCheckbox.click(function() {

        //update checkCount
        checkCount = $('input:checked').length;

        if (checkCount >= maxChecks) {
            //alert('you may only choose up to ' + maxChecks + ' options');
            $nameCheckbox.not(':checked').attr('disabled', true);
        } else {
            $nameCheckbox.filter(':disabled').attr('disabled', false);
        }

        if (this.checked) {
            $("td.label").append('<label>' + this.value + ' </label>');
        } else {
            $("td.label").find(':contains(' + this.value + ')').remove();
        }

        $('input[name="result"]').val($("td.label").text());

    });


    $("#test").click(function() {
        alert($('input:checked').length)
    });

    $('#button2').click(function() {
        alert($('input[name="result"]').val());
    });

});
+3  A: 

One thing that jumped out at me...

To speed things up use:

$('input:checkbox[name=checkbox]')

instead of

$(':checkbox[name=checkbox]')

This is because the first version look for checkboxes only among the input elements, the second version looks for checkboxes over all elements.

Take a look at this speed comparison Nick Craver created to demonstrate the above for this answer.

Do this wherever possible, so use $('input:checked').

Also, there are several jQuery objects you create multiple times.

For example you use, $(':checkbox[name=checkbox]') many times. Each time you recreate the same jQuery object, so do:

var $nameCheckbox = $('input:checkbox[name=checkbox]');
$nameCheckbox.click(function() {
    ...
       $nameCheckbox.not(':checked').attr('disabled', true);
    } else {
       $nameCheckbox.filter(':disabled').attr('disabled', false);
    ...

Finally semantically, it makes more sense to remove the inline javascript, so replace:

<body onLoad="clearForms()" onUnload="clearForms()">

with

<body>

and put clearForm() inside the jQuery doc ready. The jQuery doc ready will fire before window.onload since onload has to wait for all images, etc to load. jQuery doc ready fires when the DOM is ready. You can also make use of window.onunload, but I don't quite understand why that's necessary.

$(document).ready(function() {
    clearForms();
Peter Ajtai
Thank you for looking at this, it is much appreciated.
James
@James - You're welcome ;) I added one more thing about removing the inline JS and add `clearForms()` into doc ready which should fire a little before `onload` if you have any images and such on the page.
Peter Ajtai
So for example would something like this be correct? $('input:checkbox[name=checkbox]').not('input:checked').attr('disabled', true);
James
@James - In that case,`$('input:checkbox[name=checkbox]')` is a set of all `input` checkboxes with the name `checkbox`, so it is redundant to write `.not('input:checked')`. Instead write `.not(':checked')`......... In fact that's the example I wrote in my code above: `$nameCheckbox.not(':checked').attr('disabled', true);` which because of what `$nameCheckbox` is defined as is: `$('input:checkbox[name=checkbox]').not(':checked').attr('disabled', true);`
Peter Ajtai
Gotcha, Thanks for your help :) Thats exactly what I was wondering, whether or not 'input:checked' was necessary. Im going to implement the changes to the clearforms funtion as well. Can I post the code once I think it meets your advice and have you take one last look at it?
James
I think I have edited to meet your advice, I had to add to jfiddle because the code is too long for a message. here is the link: http://jsfiddle.net/xSsrC/2/
James
@James - That looks pretty good. I notice you didn't include a [ `window.onunload = clearForms;` ](https://developer.mozilla.org/en/DOM/window.onunload) - But I'm not sure what function that served any way.
Peter Ajtai
I skimmed right over that section about window.onunload, was trying to modify quickly to get advice on mods. It seems to be clearing just fine though. When I first started, I had a problem with FireFox holding onto disabled checkboxes when reloading page, but it seems to be cleared up. Adding this code: $(':checkbox[name=checkbox]:disabled').attr('disabled', false);, to ClearForms() is the only thing that worked to clear disabled checkboxes onload, resetting the form wouldnt quite do the trick.
James