简体   繁体   中英

Get Closest Form to an Element in jQuery

I have this js/jquery script i wrote to check all checboxes with in a form. It works well but this checks all checkboxes that are on page irrespective of the form wrapper they are.

here is the function

function toggleCheck(state)
{   var checkboxes = jQuery("form input:checkbox");
if(state==true){checkboxes.prop('checked',true); }
if(state==false){ checkboxes.prop('checked',false); }
}

usage

<a id="check" href="#" onclick="javascript:toggleCheck(true);" class="btn">Select All</a>
<a id="uncheck" href="#" onclick="javascript:toggleCheck(false);" class="btn">Deselect All</a>

Note this works well but my problem is if i have

 <form action="myaction-page">//some form elements and checkboxes </form>

and

<form action="myaction-page-2">//some form elements and checkboxes </form>

and i click the check all link in form1, all checkboxes gets check including those in form2.

Is there a way to separate them without introducing form ids or names?..this is because i have used it extensively in production code and to rewrite all will be trouble.

Any Help will be greatly appreciated.

PS it is worth noting that the select all and deselect all are within both forms and both forms are on the same page.

Assuming your select/deselect links are inside the form, do:

function toggleCheck(state,elem) {
    jQuery(elem).closest("form").find("input:checkbox").prop('checked', state);
}

And change your link JS to (passing the appropriate true/false parameter):

onclick="javascript:toggleCheck(false,this);"

jsFiddle example

the .closest method will do what you want.

onclick:

onclick="toggleCheck.call(this,true);"

js:

function toggleCheck(state) {   
    var checkboxes = jQuery(this).closest("form").find("input:checkbox");
    checkboxes.prop('checked',state || false);
}

The answer is: it depends on your DOM. If your <a> elements are inside the form, you could use $.closest() :

function toggleCheck(state) {
    $(this)
        .closest("form")
        .find("input[type=checkbox]")
        .prop('checked', state);
}

I slightly altered your code to increase readability, performance (see the additional notes regarding the :checkbox selector ) and be more "jQuery"-like.

[edit] After reading the comments I rewrote the function, still on the assumption that the <a> elements are inside the <form> , this time also with a working jsFiddle :

function toggleCheck(state) {
    $(document).find(event.target)
        .closest("form")
        .find("input[type=checkbox]")
        .prop('checked', state);
}

[edit2] And for the sake of completness regarding my comment about the order of the elements ( jsFiddle ):

function toggleCheck(state) {
    var pos = $(document).find(event.target.localName + "." + event.target.className).index(event.target);
    var $form = $($(document).find("form").get(Math.floor(pos/2)));
    $form
        .find("input[type=checkbox]")
        .prop('checked', state)
}

[edit3] The last edit, I promise. This time I ignore the default callback and do my own thing :

function toggleCheck(state) {
    // either write the s tate now in a variable for
    // the next callback
}

$(document).on("click", "a.btn", function(e) {
    var $ele = $(this);
    // or do some string exploration
    var toggle = $ele.attr("onclick").indexOf("true") > -1;

    var pos = $(document).find("a.btn").index($ele);
    var $form = $($(document).find("form").get(Math.floor(pos/2)));
    $form
        .find("input[type=checkbox]")
        .prop('checked', toggle);
});

Works without having to touch anything. But I wouldn't want to use this. ;-)

You can also just apply a data-target to your anchors and eval based on the action of your form elements:

... data-target='myaction-page' ...

... checkboxes[i].form.getAttribute( 'action' ) ...

Shown in detail on this JSFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM