开发者

jQuery click event fires the first time, but not the second

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>
 开发者_Go百科   </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 of if...else:

$('#categories > div').toggle();

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

$('#categories li:first').live('click', function() {})

this way clicking on a first li will trigger your handler, even if your li was just now moved to first position.

$('#categories').delegate('.dropdown a', 'click', functon(evt) {})

This is an example of .delegate(). This means that when someone clicks element matching .dropdown a inside the #categories this handler will be called.

Here you can use .live() instead, but .delegate makes more sense. Instead of assigning (copying) event handler to all matching elements, we delegate all 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 a click() handler to the link you just clicked. But event is still propagating, so after your second handler is finished, event bubbles up to li, and $('.li').live('click', ...) executes, hiding your dropdown div.

Hope this makes sense.


It could be your if statement needs .length on it, giving:

If ( $('selector').length > 0 ) // show the drop down

Your current if statement doesn't check whether the object exists. Selectors return an empty collection of elements, not null, if they don't match anything.


Maybe prependTo removes the click event handler. Execute the initialization again. If that indeed works, you can choose to use the jQuery.live() function instead of jQuery.click() to bind the click events.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜