Hi all,

here' the code

$(document).ready(function(){

	$("ul li ul").hide();

	$("li:has(ul)").click(function(){
		$this = $(this);
		if ($this.siblings().find('ul:visible').size()!=0)
		{
			$this.siblings().find('ul:visible').slideUp(1000, function(){
			$this.find('ul:hidden').slideDown(500);
			});
		} else {
			$this.find('ul:hidden').slideDown(500);
		}

	});

	$("li:has(ul:hidden)").mousedown(function(){
		$(this).css("background-color","#869094");
	}).mouseup(function(){
		$(this).css("background-color","#7793ae");
	});

	$("li > ul > li").mousedown(function(){
		$(this).css("background-color","#a5ccef");
	}).mouseup(function(){
		$(this).css("background-color","#d9ebf1");
	});
});

The problem is the li:has(ul:hidden) part - line 19. The event triggers regardless of whether the ul is hidden or has been 'slid down' i.e. visible.

Interestingly if I change it to li:has(ul:visible) it never triggers.

I have tried

("li > ul:hidden").parent("li"), but get the same effect.

Can anyone point out what i'm doing wrong?

Many thanks

Dani AI

Generated

The symptom you described comes from when the selector is evaluated, not from :hidden/:visible being wrong. already confirmed the visibility test inside the click handler runs correctly; the problem is that the mousedown binding was attached to the static set of elements matched at bind time. Those handlers stay attached even after the child UL is slid down, so the mousedown still fires.

Two simple fixes:

  • Use event delegation so the selector is matched at event time (modern jQuery: use .on). This makes the :has(ul:hidden) match re-evaluate when the event occurs.
$(document).on('mousedown', 'li:has(ul:hidden)', function() {
  // handler runs only when the child UL is currently hidden
});
  • Or bind to the broader set and check state inside the handler. That is version-safe and explicit:
$('li:has(ul)').on('mousedown', function() {
  if ($(this).children('ul').is(':hidden')) {
    // only run for hidden child ULs
  }
});

Notes and best practice: older jQuery (<1.7) uses .delegate/.live for delegation; use .on for current versions. Relying on heavy selectors repeatedly can be slower—an efficient pattern is to add/remove a simple class (for example open) in your slide callbacks and test that class instead of complex selectors. See the jQuery docs for details on delegated events, :has, and :hidden / :visible: .on, :has selector, :hidden selector.

Recommended Answers

All 2 Replies

You have correctly set the UL to hidden/visible accordingly?

The 'if' statement runs okay and that is based on wether the UL is hidden or visible.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.