MillerMedia
MillerMedia

Reputation: 3671

Attach Click Event to HTML after Menu Click

I've got a dropdown menu on a site I'm working on that has different classes added to it when it is activated. It's built into a WordPress theme so I'm having to build a workaround on it for iPad landscape mode. The site navigation displays the same as desktop when on landscape so I need to create some touch events to mimic the behavior.

The first thing I'm having to do is to deactivate the link on the first click and then reactivate it if it's clicked again. This works fine.

if ('ontouchstart' in document.documentElement) {
    $('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
        e.preventDefault();
        $('li.clicked_link').on('click', function(){
            var this_link = $(this).find('> a').attr('href');
            document.location.href=this_link;
        });

        $(this).parent().addClass('clicked_link');
    });
}

The problem is that when you click on the li.sub-menu it adds a class of sub-hover onto it which activates a dropdown menu. It's a CSS/jQuery dropdown menu so it's based on the presence of that sub-hover class. It works fine when I first click but I then want to remove that class when you click outside of it. It deactivates it if I click another link in the dropdown but I'd like to bind a click event to the html or body elements so if you click anywhere outside of it, it will remove the sub-hover class, thus removing the dropdown.

I tried to do this:

if ('ontouchstart' in document.documentElement) {
    $('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
        e.preventDefault();
        $('li.clicked_link').on('click', function(){
            var this_link = $(this).find('> a').attr('href');
            document.location.href=this_link;
        });

        $(this).parent().addClass('clicked_link');

        $('html').on('click',function(){
            $('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
        });
    });
}

It doesn't work though because it seems to fire the first click function and then immediately fire the html click function. I tried to use bind as well but the same thing happened. I also tried it outside of the initial click function but, as you can guess, it fires the two click events simultaneously which doesn't work.

How do I get it to bind but not fire the click event only after the initial click event takes place?

Upvotes: 0

Views: 1145

Answers (1)

T J
T J

Reputation: 43166

This is not a direct fix for the problem, but something that might help you fix the problem (Too long for a comment).

  • You are binding click handlers inside another click handler without unbinding the previous ones, So everytime you click a matching <li> new click handlers are being added to <html> and other matching elements. I strongly believe you're not doing it on purpose and isn't aware of it.

  • Leaving that, You're trying to bind a click for .clicked_link using

    $('li.clicked_link').on('click', function(){
    

    This code looks for matching elements currently present in DOM, and probably finds no matching elements since you're actually adding the class clicked_link after it.

    You actually need to delegate this handler to check for matching elements in future.

  • The events are bubbled up till the root element, in other words: you if you click an anchor, starting from the anchor, all the parents till html will receive a click event, which you can prevent using e.stopPropagation();.

Ideally you're code should look something like this:

if ('ontouchstart' in document.documentElement) {

   $('#masthead nav ul > li:has(.sub-menu) a').click(function(e){
       e.preventDefault();
       $(this).parent().addClass('clicked_link');
    });

    $(document).on('click','li.clicked_link', function(){
        var this_link = $(this).find('> a').attr('href');
        document.location.href=this_link;
    });

    $('html').on('click',function(){
        $('#masthead nav ul > li:has(.sub-menu)').removeClass('sub-hover').removeClass('clicked_link');
    });
}

(Can't go any further with the currently available info. Minimal code such as respective html structure or a demo would be helpful)

Upvotes: 1

Related Questions