Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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

like image 393
jcobhams Avatar asked Oct 03 '13 20:10

jcobhams


2 Answers

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. ;-)

like image 55
nietonfir Avatar answered Sep 22 '22 09:09

nietonfir


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

like image 30
j08691 Avatar answered Sep 20 '22 09:09

j08691