This is the HTML I’m working with:
<ul id="categories">
<li><a href="#cargo">Cargo Trailers</a></li>
<div class="dropdown">
<ul>
<li><a href="#utility">Utility Trailers</a></li>
</ul>
</div>
</ul>
I have written a jQuery script to hide the dropdown div. The dropdown div appears the first time the click event is fired. Once the li in the dropdown div is selected and switches places with the first li in the #categories ul, clicking on the li will not bring up the dropdown div.
Here is the jQuery:
jQuery(document).ready(function($) {
// hide the dropdown div
$('#categories > div').hide();
/*
Click the drop down arrow function
*/
var $listHeader = $('#categories > li');
$listHeader.click(function() {
if ( $('#categories > div:hidden') ) {
//show the drop down
$('#categories > div').show();
} else {
//hide the drop down
$('#categories > div').hide();
}
});
/*
Click a list-item in the drop down function
*/
$('#categories > div a').click(function() {
/* actions to change the title to the newly selected item */
// hide the ul
$('#categories > div').hide();
// move the clicked item to the header
$(this).prependTo('#categories > li');
// move the previous title to the dropdown and sort
$('#categories > li > a:eq(1)').prependTo('#categories > div > ul > li:empty');
// Reset the listHeader variable
$listHeader = $('#categories > li');
// cancel default browser action
return false;
});
});
this
$('#categories > div:hidden')will always return jQuery object (which evaluates to true), even if there are no elements matching selector. Use jQuery’s.toggle()instead ofif...else:here’s an example to play with
Update in response to your comment: Updated example – http://jsfiddle.net/Etkjr/1/
You are correct, event handlers are unbound on DOM change. To prevent, that you would need to use 2 jQuery functions:
.live()and.delegate. Both of them monitor DOM changes and rebind events to selectors when the DOM is changed.You want click on a first li to expand dropdown menu – use
this way clicking on a first li will trigger your handler, even if your
liwas just now moved to first position.This is an example of
.delegate(). This means that when someone clicks element matching.dropdown ainside the#categoriesthis handler will be called.Here you can use
.live()instead, but.delegatemakes more sense. Instead of assigning (copying) event handler to all matching elements, wedelegateall clicks to a single event handler.I also updated “moving” code. Interesting side effect here, is that you don’t need to
.hide()dropdown inside the second handler. You see, when you click on a link inside dropdown, the link gets moved into first position..live()detects that and assigns aclick()handler to the link you just clicked. But event is still propagating, so after your second handler is finished, event bubbles up toli, and$('.li').live('click', ...)executes, hiding your dropdown div.Hope this makes sense.