Styphon
Styphon

Reputation: 10447

Why is event undefined when using a.click

I am trying to create a basic megamenu for my site but I'm having problems with the menu opening and closing on one click. This is a basic version of the HTML:

<ul class="menu">
    <li class="dropdown-toggle">
        <a href="#">Toggle Dropdown</a>
        <ul class="dropdown-wrap">
            <ul class="column">
                <li><a href="#">Link 1</a></li>
                <li><a href="#">Link 2</a></li>
                <li><a href="#">Link 3</a></li>
            </ul>
            <ul class="column">
                <li><a href="#">Link 4</a></li>
                <li><a href="#">Link 5</a></li>
                <li><a href="#">Link 6</a></li>
            </ul>
        </ul>
    </li>
</ul>

And this is a basic version of the JavaScript:

$menu = $('ul.menu');
$menu.find('li.dropdown-toggle').children('a').click(function(event) {
    var $wrap = $(this).siblings('.dropdown-wrap');
    if ($wrap.hasClass('open')) {
        closeDropdown($wrap);
    } else {
        openDropdown($wrap);
    }
    event.preventDefault().stopPropagation();
});
$('html').click(function() {
    console.log('HTML FIRED');
    if ($('.dropdown-wrap.open').length > 0) {
        closeDropdown($('.dropdown-wrap.open'));
    }
});

function closeDropdown($wrap) {
    $wrap.removeClass('open');
    console.log('Close');
}
function openDropdown($wrap) {
    $wrap.addClass('open');
    console.log('Open');
}

The problem is I'm getting an event is undefined error when running stopPropagation.

Uncaught TypeError: Cannot read property 'stopPropagation' of undefined

This is a jsfiddle of the error in action: http://jsfiddle.net/styphon/0go9ukky/

My questions are why is event undefined in this case? And if event is undefined why doesn't event.preventDefault() throw the same error? How can I get this working?

None of the search results have explained this behaviour so far and I can't understand why event is undefined.

Upvotes: 1

Views: 6103

Answers (2)

Magus
Magus

Reputation: 15104

event is defined. But preventDefault does not return the event. So you have to do it in two lines:

event.preventDefault();
event.stopPropagation();

Upvotes: 2

Tushar
Tushar

Reputation: 87203

You cannot chain methods from event object, ex: stopPropagation with preventDefault.

Code From jQuery Source:

preventDefault: function () {
    var e = this.originalEvent;

    this.isDefaultPrevented = returnTrue;

    if (e && e.preventDefault) {
        e.preventDefault();
    }
},

As you can see that preventDefault does not return anything explicitly, so by default undefined is returned.

And you'll get error

Uncaught TypeError: Cannot read property 'stopPropagation' of undefined

To solve the issue use

event.preventDefault();
event.stopPropagation();

You can also use return false; as alternative to the two methods.

Upvotes: 1

Related Questions