Jquery Closest and Parents Not Working with Input and Nested Divs

2.6k Views Asked by At

I have hidden Divs with ".display-link" classes that are two levels up from an input box. When an input (checkbox) is clicked, it should display the hidden link in the parent's previous sibling's wrapper.

Or another way to say it is, when an input checkbox is clicked it should find the previous div with the class .display-link and show() that.

I am having trouble traversing the elements to reach this div with this class. It should only display the one, previous div.

<!DOCTYPE HTML>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>

$(document).ready(function(){

$(".display-link").hide();//hide all links

$('input').click (function ()
    {
    $(this).closest(".display-link").show();//doesn't work
    $(this).closest("div.display-link").show();//doesn't work
    myInput = $(this);
    $(myInput).closest(".display-link").show();//doesn't work
    $(myInput).parents(".display-link").show();//doesn't work
    $(myInput).prevUntil(".display-link").show();//doesn't work
    });
});
</script>
</head>

<body>
<div class="accordion-button">First Heading
  <div class="display-link">LINK</div>
</div>
<div class="collapsible">
  <div class="input-row">
    <input id="checkbox01" name="checkbox01" type="checkbox" value="value01"  />
    <label for="checkbox01" >Name 1</label>
  </div>
  <div class="input-row">
    <input id="checkbox02" name="checkbox02" type="checkbox" value="value02"  />
    <label for="checkbox02" >Name 2</label>
  </div>
</div>
<div class="accordion-button">Second Heading
  <div class="display-link">LINK</div>
</div>
<div class="collapsible">
  <div class="input-row">
    <input id="checkbox03" name="checkbox03" type="checkbox" value="value03"  />
    <label for="checkbox03" >Name 3</label>
  </div>
</div>
</body>
</html>

I need to go out of the collapsible div and into the accordion-button div down to the display-link div.

4

There are 4 best solutions below

0
On BEST ANSWER
$('input').on('click', function () {
    $(this).parents('.collapsible').prev('.accordion-button').children('.display-link').show();
});

Here is a demo: http://jsfiddle.net/hazvX/

This finds the parent .collapsible element, finds the previous .accordion-button element, then selects it's child .display-link element.

Your HTML shows that there are two .display-link elements and three inputs. If you want the inputs to find the first possible (previous) .display-link elements you can use .prevAll() in place of .prev():

$('input').on('click', function () {
    $(this).parents('.collapsible').prevAll('.accordion-button').eq(0).children('.display-link').show();
});

Here is a demo: http://jsfiddle.net/hazvX/1/

Notice I also added .eq(0) after the .prevAll() function to only get the first returned element (since there can be multiple).

Note that .on() is new in jQuery 1.7 and in this case is the same thing as .bind().

2
On

Since the .display-link element you want to display is not a sibling or an ancestor of the checkbox you can't do this in one step. First go up to the .collapsible element which is a sibling of .accordion-button, then get the previous element, which is .accordion-button itself, and then find the .display-link element within that:

$(":checkbox").click(function() {
    $(this).closest(".collapsible").prev().find("display-link").show();
});

The closest method only looks at ancestor elements, as does parents. The prevUntil method only looks at preceding siblings.

Note that the above will only work if your structure stays as it is in the question. If you add elements in places that would affect the above code you will have to modify it accordingly. You could make it a bit more robust if you think the DOM may change:

$(this).closest(".collapsible").prevAll(".accordion-button:first").find(".display-link").show();
1
On

Parents, closest won't work because it isn't in the same path.

Can you give them an ID, or put them in another container: http://jsfiddle.net/Cq9Cw/

2
On

Another solution I'll throw in here, is if each input had a corresponding display-link then you could use the index

http://jsfiddle.net/7TaqC/

Now of course in your example there are 3 inputs and only 2 links, however I don't know if this is because this is just a small snippet of your code

$(".display-link").hide();//hide all links

$('input').click (function (e)
{
   $this = $(this);
var index = $('input').index($this);
$('.display-link').eq(index).show();

});