JQuery - open closed indicators - Novice to Ninja book

This question comes from the book: JQuery: Novice to Ninja
Chapter 5: 03_open_closed_indicators.
(see zipped my files.)

This seems simple, but I’m totally lost with my logic.
(1) I’ve filtered the first item to be open when the page is loaded.
(2) When the first panel is open, the cooresponding open / close indicator (which is simply one small image) points the wrong way, or acts improperly.

My Question
What code am i missing that would handle the open/closed arrows appropriately if the first item was open on load?

My js code

$(document).ready(function(){
				   
$( '#menu > li > ul' ) 
	.click(function( e ){
		e.stopPropagation();
	})
.filter(':not(:first)')
.hide();

  $('#menu > li').toggle(function(){
	  $(this)
      .css('background-position', 'right -20px')
      .find('ul').slideDown();
  }, function(){
  	$( this )
      .css('background-position', 'right top')
      .find('ul').slideUp();
  });
});

I’ve messed around with the code for way too long and can’t figure it out. Any help appreciated.

Also,(not essential) how easy is it to add an expand / collapse all buttons? Though I have some ideas as to how to approach this.

PhilipToop, I really appreciate the reply! I’ll give it a try and let you know.

Brandon

To get the arrow to appear right you need to set the background-position correctly.

My first thought was to modify the first statement to hide everything and then show the first time.

	$( "#menu > li > ul" ).click(function( e ){
									e.stopPropagation();
				}).hide()
				.first().parent().css('background-position', 'right -20px')
				.find("ul").slideDown();

This gives the right initial effect but the title needs to be clicked twice to close it the first time. That is toggle assumes it is closed.

An alternative approach is to set up a class “openmenu” which has a style

.openmenu {
	background-position : right -20px;
}

This can then act as a toggle indicator.

	$( "#menu > li > ul" ).click(function( e ){
									e.stopPropagation();
				}).hide()
				.first().parent().addClass("openmenu")
				.find("ul").slideDown();

	$("#menu > li").click( function(evt) {
					if ($(this).hasClass("openmenu")) {
						$(this).removeClass("openmenu");
						$(this).find("ul").slideUp();
					} else {
						$(this).addClass("openmenu");
						$(this).find("ul").slideDown();
					}
					evt.preventDefault();
		});

Hi again. Very close. I have understood your comments and attempted to apply the solution, which for the most part worked! :slight_smile: The double click (via toggle) has been corrected. However, the following code will now not substitute the correct arrow positioning (Stays in down position, as if not recognizing the open menu class, which has been added to my css):


	$( "#menu > li > ul" ).click(function( e ){
									e.stopPropagation();
				}).hide()
				.first().parent().addClass("openmenu")
				.find("ul").slideDown();
 
	$("#menu > li").click( function(evt) {
					if ($(this).hasClass("openmenu")) {
						$(this).removeClass("openmenu");
						$(this).find("ul").slideUp();
					} else {
						$(this).addClass("openmenu");
						$(this).find("ul").slideDown();
					}
					evt.preventDefault();
		});

Very weird.
I tried using the .css(‘background-position’, ‘right -20px’) throughout your example code instead using the “openmenu” class.

If you change the style so that it is

<style type="text/css">
#menu .openmenu {
	background-position: right -20px;
}

it should solve the problem. the style #menu li in menu.css was taking precedence. By adding the #menu before the .openmenu we can change that.

It worked! Sorry for all the questions but I was determined to (with some assistance) do this properly without a plugin. Thanks again, I am encouraged to keep moving forward!