422
422

Reputation: 5770

Validate multiple checkboxes, minimum one required

We are creating a advertising form, and our jQuery coder is in Syria, and unfortunately caught up in the ugliness there.

So whilst he at present cannot assist with some code he made for us, I have an issue I think could be solved quite easily.

We have a stepped form, you know: Complete step 1, move on to step 2 etc etc. On step 4, we have multiple checkboxes, that we require a user to check at least ONE.

If they check ONE they can proceed to the next step.. if they don't click any we show an error message.

So this is our js:

(function($) {
$.fn.formToWizard = function(options) {
    options = $.extend({  
        submitButton: "" 
    }, options); 

    var element = this;

    var steps = $(element).find("fieldset");
    var count = steps.size();
    var submmitButtonName = "#" + options.submitButton;
    $(submmitButtonName).hide();

    // 2
    $(element).before("<ul id='steps'></ul>");

    steps.each(function(i) {
        $(this).wrap("<div id='step" + i + "'></div>");
        $(this).append("<p id='step" + i + "commands'></p>");

        // 2
        var name = $(this).find("legend").html();
        $("#steps").append("<li id='stepDesc" + i + "'>Step " + (i + 1) + "<span>" + name + "</span></li>");

        if (i == 0) {
            createNextButton(i);
            selectStep(i);
        }
        else if (i == count - 1) {
            $("#step" + i).hide();
            createPrevButton(i);
        }
        else {
            $("#step" + i).hide();
            createPrevButton(i);
            createNextButton(i);
        }
    });

    function createPrevButton(i) {
        var stepName = "step" + i;
        $("#" + stepName + "commands").append("<a href='javascript:;' id='" + stepName + "Prev' class='purple button'>Back</a>&nbsp;");

        $("#" + stepName + "Prev").bind("click", function(e) {
            $("#" + stepName).hide();

            if($(this).attr('id') == "step4Prev" && $('li#stepDesc3 del').legnth > 0){
                i--;
            }
            $("#step" + (i - 1)).show();
            $(submmitButtonName).hide();
            selectStep(i - 1);
        });
    }

    function createNextButton(i) {
        var stepName = "step" + i;
        $("#" + stepName + "commands").append("<a href='javascript:;' id='" + stepName + "Next' class='purple button'>Next</a>");

        $("#" + stepName + "Next").bind("click", function(e) {
            var div = $('div#'+ stepName);
            $(div).find('.field_help').remove();
            if( $(div).find('input:text[value=""]').length > 0 ||
                $(div).find('input:checkbox:not(:checked)').length > 0 ||
                $(div).find('select option:first-child:selected').length > 0 ||
                $(div).find('textarea').val() == ""
                ){
                    $(div).prepend('<p class="field_help"> Please complete all fields before moving to next step</p>');
                    return false;
                }
            if($(this).attr('id') == "step2Next" ){
                if($(div).find('select[name="type"]').val() == "land"){
                    i++;
                    $('li#stepDesc3').html('<del>'+$('li#stepDesc3').html()+'</del>');
                }else{
                    if($('li#stepDesc3 del').legnth > 0){
                        $('li#stepDesc3').html($('li#stepDesc3 del').html());
                    }
                }
            }

            $("#" + stepName).hide();
            $("#step" + (i + 1)).show();
            if (i + 2 == count)
                $(submmitButtonName).show();
            selectStep(i + 1);
        });
    }

    function selectStep(i) {
        $("#steps li").removeClass("current");
        $("#stepDesc" + i).addClass("current");
    }

}
})(jQuery);

And this is the form area for the checkboxes:

<div class="master-container">
                <div class="lefthandblock">
                    <div class="sort left">
                        <span id="checkbox3Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="heating" id="checkbox3" /></span><p class="labeller">Heating</p>
                        <span id="checkbox4Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="aircon" id="checkbox4" /></span><p class="labeller">Air Conditioning</p>
                        <span id="checkbox5Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="ensuite" id="checkbox5" /></span><p class="labeller">Master En-suite</p>
                        <span id="checkbox6Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="builtins" id="checkbox6" /></span><p class="labeller">Built in Robes</p>
                        <span id="checkbox7Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="newkitchen" id="checkbox7" /></span><p class="labeller">New Kitchen</p>
                        <span id="checkbox8Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="rumpus" id="checkbox8" /></span><p class="labeller">Rumpus / Family Room</p>
                        <span id="checkbox9Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="intspa" id="checkbox9" /></span><p class="labeller">Inside spa</p>
                        <span id="checkbox10Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="media" id="checkbox10" /></span><p class="labeller">Media Room</p>
                    </div>  
                </div>
                <!--//left hand-->
                <!--right hand-->
                <div class="righthandblock">
                    <div class="sort left">
                        <span id="checkbox11Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="fans" id="checkbox11" /></span><p class="labeller">Ceiling Fans</p>
                        <span id="checkbox12Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="highceilings" id="checkbox12" /></span><p class="labeller">High Ceilings</p>
                        <span id="checkbox13Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="insulated" id="checkbox13" /></span><p class="labeller">Insulated</p>
                        <span id="checkbox14Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="phase" id="checkbox14" /></span><p class="labeller">3 Phase Power</p>
                        <span id="checkbox15Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="internet" id="checkbox15" /></span><p class="labeller">Broadband / Internet</p>
                        <span id="checkbox16Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="floor" id="checkbox16" /></span><p class="labeller">Polished Floors</p>
                        <span id="checkbox17Wrap" class="styledCheckboxWrap"><input type="checkbox" class="styledCheckbox" onclick="setCheckboxDisplay(this)" name="internal[]" value="granny" id="checkbox17" /></span><p class="labeller">Granny Flat</p>
                    </div>  
                </div>
            </div>

The issue is that at present the javascript will only validate if the user ticks every single checkbox.

Perhaps it's obvious perhaps it isn't, but I cannot figure it out.

ADDED:

with checkbox ticked this is the html.

<span id="checkbox4Wrap" class="styledCheckboxWrap wrapChecked">
<input id="checkbox4" class="styledCheckbox" type="checkbox" value="aircon" name="internal[]" onclick="setCheckboxDisplay(this)">
</span>

if we untick this is the html.

<span id="checkbox4Wrap" class="styledCheckboxWrap">
<input id="checkbox4" class="styledCheckbox" type="checkbox" value="aircon" name="internal[]" onclick="setCheckboxDisplay(this)">
</span>

Upvotes: 1

Views: 4308

Answers (2)

Dave Newton
Dave Newton

Reputation: 160321

$(div).find('input:checkbox:not(:checked)').length > 0

This line says "if I have any checkboxes not checked", so the behavior you're seeing is what I'd expect. Don't you want to count the number of checked boxes and make sure it's > 0?

Upvotes: 3

Alex Peattie
Alex Peattie

Reputation: 27697

Try something like this:

if($("input[name='internal[]']:checked").length > 0)) {
  alert("At least 1 checkbox checked!");
}

Upvotes: 2

Related Questions