Selecting multiple divs in jQuery?

Hello!

I’m new to jQuery and I’m not sure how to make simple show/hide system:


<div id="One"><p>Some text</p></div>
<div id="nav"><a href="#" class="toggle">Toggle</a></div>

<div id="Two"><p>Some text again.</p></div>
<div id="nav"><a href="#" class="toggle">Toggle</a></div>

<div id="Three"><p>Some text and again.</p></div>
<div id="nav"><a href="#" class="toggle">Toggle</a></div>

etc.

I want to toggle the div above clicked link (and I don’t mean parent, but the previous div named One, or Two, or Three etc.).

My code so far, it hides ALWAYS the very first div, not the one above. I’ve tried “prev()” and “this”, but I’m not sure how to use them exactly in this case.


(...)
    $('.toggle').click(
    function()
    {      
    $('#nav').prev().toggle()
});
(...)

Well, actually I was digging a few hours and then realized that I simplified example and mine link is in not only in a div but also in a paragraph!

So had to use parent().parent().toggle() (btw is there a shorter way of describing grand-grandparents etc.?).

Sorry for that and thanks for the solution!

About putting scripts in body part - well, great advice. I guess everyone puts $cripts in the head section because… other people do the same! I was never thinking about that…

Are you sure there’s absolutely no difference between $(document).ready in head and a script at the end of the document without this line? If yes, then I’m going to put my scripts at the end, because more functions = less clarity.

If I’m reading the response correctly, it looks like Matt misinterpreted what “.parent” did and wanted to ask a follow up question before actually trying it. It doesn’t look like it failed.

Actually, you touch on a really good question that I’ve never heard an answer to though…

In the “bad old days” before jQuery, I learned progressive enhancement and we had this same issue as well. I was trained to cope with this situation by placing the script elements not in the head tag, but at the end of the document right before the closing body tag. That way all the DOM elements you were working with were rendered on the page.

Now jQuery gives you the option insert your scripts in the head element and to wrap all your function calls in $(document).ready(…whatever code you want executed…); However, it seems silly to me to wrap EVERY function you want to run inside of this code.

Doesn’t it make more sense to build your script without having to summon everything from inside a $(document).ready(…) call, and place the script element at the end of the file instead? Is $(document).ready doing something else besides waiting for the page to render? From what I can tell from the non-minified file, it doesn’t look like it. Or is there some advantage to calling the script from the head element that I don’t know about? I haven’t noticed any problems in all the years I’ve used progressive enhancement and my files have always tested out fine in IE, FF, O and S.

Aaaww, it was so lame, I was trying to figure out why so many people using jQuery is making this mistake with multipe IDs on one page and I made it also, shameful, sorry!

Actually, your code doesn’t work also:


$('.toggle').click(
    function()
    {      
    $(this).parent().prev().toggle()
});

Because as far as I understand it closes previous LINK (<a>) (as soon as “this” is an <a> with class .toggle, right?).

Logically it should be $(this).prev(div).toggle() but it seems to easy and doesn’t work as well.

:slight_smile: I hate it when I lose track of stuff like that. Glad you got it worked out. And that is the simplest way I know of, but I’m not exactly a ninja yet, so see if someone else knows a short cut.

I’m in the middle of a big C# project at the moment, but I want to test that out more when I’m finished. I’m also hoping to hear some feedback from other developers. I have a three years of OOP experience, but I’ve been out of JS for almost that whole time and am hoping to hear some opinions. I’m of the exact same feeling as you (more functions = less clarity) and that’s what I’d really prefer to do.

I just tried the following and that works as you want it to:


<body>
    <div id="One"><p>Some text</p></div>
		<div class="nav"><a href="#" class="toggle">Toggle</a></div>

		<div id="Two"><p>Some text again.</p></div>
		<div class="nav"><a href="#" class="toggle">Toggle</a></div>

		<div id="Three"><p>Some text and again.</p></div>
		<div class="nav"><a href="#" class="toggle">Toggle</a></div>
		<script type="text/javascript">
			$('.toggle').click(	function() {
				$(this).parent().prev().toggle();
			});
		</script>
  </body>

What it does is, when you click an element with class “toggle” (in you case the <a> elements) :

  1. find its parent, which is the div containing the a
  2. find the element before that, which is the div before the div that contains the <a>
  3. toggle that element

Are you sure you put the script in the right place? You should either but it just before </body> like I did, or in the head, but then you need to make it

$(document).ready( function() {
 $('.toggle').click(	function() {
   $(this).parent().prev().toggle();
 });
});

To make sure it only fires when the DOM is ready. If you just put it in the head, the .toggle elements are not in the DOM yet, so the code has nothing to do.

It should be


function() {
  $(this).parent().prev().toggle();
}

That being said, an ID can only be used once in a page, you used the ID nav at least 3 times. You should make it a class:


<div id="One"><p>Some text</p></div>
<div class="nav"><a href="#" class="toggle">Toggle</a></div>
 
<div id="Two"><p>Some text again.</p></div>
<div class="nav"><a href="#" class="toggle">Toggle</a></div>
 
<div id="Three"><p>Some text and again.</p></div>
<div class="nav"><a href="#" class="toggle">Toggle</a></div> 

And of course also change #nav to .nav in your stylesheet(s) :slight_smile: