jQuery

Hi all,

I’m super new to jquery and am trying to get a few hidden div’s to slide down when a link is clicked and then contract when a close link inside that div is clicked.

So far i have been able to get at least one of the hidden links to appear using the slidetoggle feature. I’m not sure how to go about making the close link inside it function though.

At the moment I was trying to get multiple links to toggle open and closed but all that is happening is that the same hidden div is opening and closing when different links are clicked. I believe this has something to do with how I defined the click trigger?

can anyone help me with this, show me how i would be able to use the slidetoggle feature and have a close link inside that hidden div work properly?

here is my test site: slidetoggle test

basically what i have on the test site is this: slidetoggle test


   1. $(document).ready(function(){
   2. //Expand & Close Toolbox Panel
   3. $(".toolbox").click(function(){
   4. $("#popup-toolbox").slideToggle("slow");
   5. $(this).toggleClass("active"); return false;

I was told I needed to additionally remove the toggleclass but if i do that then none of the slide toggling works.

How would I add to that to make the close link work?

Should I even be using slidetoggle?

Additionally, if I wanted to set the positioning of where the box dropped down is the only way to do that in css or can i accomplish that in the jquery code?

I appreciate any help with this or suggestions.

What you are trying to do is fairly easy but needs some planning. Lets go one step at a time. Here is the html part.


<ul id="panelnav">
       <li><a href="#login" title="Login">Login</a></li>
       <li><a href="#client" title="Client Area">Client Area</a></li>
</ul>
<div id="login" class="panel">
       <p>This is login panel</p>
</div>
<div id="client" class="panel">
       <p>This is Client Area</p>
</div>

Each panel has a class and an id. Class for targeting all of them and id to target them individually.

Inorder to expand we will need the height of the panels. So following code collects the heights of the panels, stores them and sets their heights to zero.


$panels = $('div.panel');
for (i=0; i<$panels.length; i++){
           ht = $panels.eq(i).height();
           $panels.eq(i).data('height', ht).height(0);
}

Close button inside panel

The close buttons inside the panels they all do the same which is to collapse their parent div which can be setup as follows.


$('div.panel a.close').click(function(){
       $(this).parent().animate({
                height: 0
       }, 800);
       return false;
});

Buttons outside panels

Now when the user clicks the links outside the script needs to know which panel to open. We can use the attributes to store that data. Since these links do not have real links we can use the href attribute to store data as shown in markup. Now the script to open and close panels from the panelnav links.

Inorder to know if the panel is already open we will use ‘open’ class to store that information.


$('#panelnav a').click(function(){
       var id = $(this).attr('href');
       var ht = $(id).data('height');
       $(id).animate({
                height: ht
       }, 800).addClass('open');
       $('div.panel.open').animate({
                height: 0
       }, 800).removeClass('open');
       return false;
});

That should do it. Let me know if you have any questions.

Hi Semantic,

Thanks so much for your response I’ve asked this question on a few forums and you were the only person that offered an answer and one that seems easy to understand! I will give your suggestions a test here right away and will definitely let you know if I have any other questions.

Was I way off base with my slidetoggle since I don’t see anything like what I had in your example?

Thanks for taking the time to help a newbie like me!

Glad to hear that it was easy to understand. Thats the hard part. You can use slideToggle too. I just happen to use animate instead. The advantage of this method is the ability to control the height if necessary.

Hi Semantic,

I thought I understood your explination but maybe I’m not as clever as I thought. -__-;; lol

I tried to implement it here: Test 2

But nothing happens.

Thanks for your patience in helping a newbie like me I really appreciate it.

Its not working because your selectors are not pointing at the right elements.

The links inside mininav have href’s such as #client but the actual id is #popup-client. So the selector is null which ends up doing nothing.

For the close buttons inside panels the class close is given to a div holding the a element so again the selector is null.

I would recommend getting firefox with firebug. This combo is great for debugging. Once the addon is installed turn it on by clicking the icon which will open a panel in the browser. You can start debugging by making sure your selectors are returning elements you are after. For example if you are trying to collect all div’s with a class popup you use $(‘div.popup’). To check if things went well use the following code…


console.log($('div.popup'));

If it failed you would see ‘’ in the log window. If it worked as planned you would see [div.popup, div.popup, div.popup …].

hmm… maybe I need to review selectors and such as I can’t for the life of me get this to work. even if I copy your html and javascript examples and start from scratch it’s not dropping anything down.

i do have firefox firebug and i have been going over it this weekend trying to figure out what i’m doing wrong.

Try this. The html…


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title></title>
	<meta http-equiv="content-language" content="en-us" />
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<link href="css/styles.css" rel="stylesheet" media="screen" type="text/css" />
	<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
	<script type="text/javascript" src="js/custom.js"></script>
</head>

<body>

<ul id="nav">
	<li><a href="#login">CMS Login</a></li>
	<li><a href="#client">Client Area</a></li>
	<li><a href="#career" >Careers</a></li>
	<li><a href="#awards">Awards</a></li>
	<li><a href="#toolbox">Toolbox</a></li>
</ul>

<div id="login" class="popup">
	<a class="close" href="#" title="close">Close</a>
	<h2>Login Panel</h2>
	<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
	<p>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).</p>
</div>

<div id="client" class="popup">
	<a class="close" href="#" title="close">Close</a>
	<h2>Client Information</h2>
	<p>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.</p>
</div>

<div id="toolbox" class="popup">
	<a class="close" href="#" title="close">Close</a>
	<h2>Toolbox</h2>
	<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
	<p>It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).</p>
	<p>Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.</p>
</div>

</body>
</html>

The css…


* {
	margin: 0;
	padding: 0;
	font-size: 100&#37;;
}

body	{
	color: #fff;
	padding: 10px;
	font: 75% Arial;
	background: #000;
}

#nav li	{
	float: left;
	list-style: none;
	margin-right: 2px;
}

#nav a, #nav a:visited	{
	color: #fff;
	float: left;
	outline: none;
	display: block;
	padding: 5px 10px;
	text-decoration: none;
}
#nav a:hover	{
	color: #000;
	background: #fff;
}
#nav a.active, #nav a.active:visited, #nav a.active:hover	{
	color: #fff;
	background: #300;
}

div.popup	{
	clear: both;
	width: 800px;
	padding: 0 10px;
	background: #300;
	overflow: hidden;
}
div.popup a.close, div.popup a.close:visited	{
	color: #000;
	float: right;
	display: block;
	background: #fff;
	padding: 5px 10px;
	text-decoration: none;
}
div.popup a.close:hover	{
	color: #000;
	background: #ccc;
}

div.popup h2	{
	padding: 10px 0 15px 0;
}
div.popup p	{
	line-height: 1.5;
	padding-bottom: 15px;
}

and finally the script…


$(function(){

//	Collect heights and collapse panels

	$panels = $('div.popup');
	for (i=0; i<$panels.length; i++){
		ht = $panels.eq(i).height();
		$panels.eq(i).data('height', ht).height(0);
	}

//	Click handler for menu links

	$('#nav a').click(function(){

		if ($(this).hasClass('active')){	//	Do nothing if the selected panel is already open
			return false;					//	the presence of active class indicates the panel
		}									//	is already open

		$('#nav a').removeClass('active');	//	Deactivate the active button if any

		var name = $(this).addClass('active').attr('href');	//	Get the name of the panel to open
															//	and set the corresponding button to
															//	active state

		var ht = $(name).data('height');	//	Collect height of the panel to open

		$('div.popup.open').removeClass('open').animate({	//	Collapse any open panels
			height: 0
		}, 800);

		$(name).addClass('open').animate({	//	Open selected panel
			height: ht
		}, 800);
		return false;
	});

//	Click handler for close buttons

	$('div.popup a.close').click(function(){
		$obj = $(this).parent().removeClass('open').animate({	//	Remove 'open' class, collapse the
			height: 0											//	panel and set the nav button to
		}, 800, function(){										//	normal state
			$('#nav a').removeClass('active');
		});
		return false;
	});

});

thank you so much semantic. i really appreciate your time and help. the example you just posted does work. seeing it in action and going over the code has helped me understand this.

i’m curious though, in your js script you have div.popup same in your css. is there a reason that you include the div before your class? can you just put .popup?

You are welcome. Yes there is a benefit to using div.popup instead of .popup. When you target a class the DOM tree is traversed to collect the elements that have the class. So if .popup is used every element is analyzed. If div.popup is used only div’s are analyzed. So it cuts down on the processing time making the rendering quicker. The increased efficiency can be observed in both css and javascript.

oh, i see! thanks again. the reason i asked is because i generate my stylesheets in dreamweaver and I had never seen it done like div.class but that explination makes sense