3

I am having trouble with multiple clicks being registered in jQuery when only one element has been clicked. I have read some other threads on Stack Overflow to try and work it out but I reckon it is the code I have written. The HTML code is not valid, but that is caused by some HTML 5 and the use of YouTube embed code. Nothing that affects the click.

The jQuery, triggered on document.ready

function setupHorzNav(portalWidth) {
    $('.next, .prev').each(function() {
        $(this).click(function(e) {
            var target = $(this).attr('href');
            initiateScroll(target);
            console.log("click!");
            e.stopPropagation();
            e.preventDefault();
            return false;
        });
    });

    function initiateScroll(target) {
        var position = $(target).offset();
        $('html, body').animate({
            scrollLeft: position.left
        }, 500);
    }
}

Example HTML

<nav class="prev-next">
    <a href="#countdown-wrapper" class="prev">Prev</a>
    <a href="#signup-wrapper" class="next">Next</a>
</nav>

In Firefox one click can log a "Click!" 16 times! Chrome only sees one, but both browsers have shown problems with the above code.

Have I written the code wrongly or is there a bug?

-- Some extra info ------------------------------------------

setupHorzNav is called by another function in my code. I have tested this and have confirmed it is only called once on initial load.

if ( portalWidth >= 1248 ) {
    wrapperWidth = newWidth * 4;
    setupHorzNav(newWidth);
}
else
{
    wrapperWidth = '100%';
}

There are mutiple instances of nav 'prev-next'. All target different anchors. All are within the same html page.

<nav class="prev-next">
    <a href="#video-wrapper" class="prev">Prev</a>
</nav>
9
  • 2
    Can you post where you're calling setupHorzNav from and the code surrounding <nav class="prev-next">? Commented Feb 13, 2013 at 14:48
  • 1
    Well just a few suggestions. You don't need to use each in this scenario, just use: $('.next, .prev').click(function (e) { //... });. And you don't need to use all three of e.stopPropagation();, e.preventDefault(); and return false;. return false; automatically does the preventDefault and stopPropagation. Those are useful if you only want to do one of them, or want to execute it sooner than return false because of possible problems in your code Commented Feb 13, 2013 at 14:48
  • Also, it is better to define your event handler function outside a loop (such as each in your case), to make sure you do not have multiple instances of the same function in memory. Commented Feb 13, 2013 at 14:50
  • 3
    I believe chrome also shows 16 logs but as a digit in front of the line. Commented Feb 13, 2013 at 14:53
  • 1
    Put a console.log right at the start of your setupHorzNav function and check how many times it is getting called. Commented Feb 13, 2013 at 14:55

4 Answers 4

8

Try unbinding the click event like this

$(this).unbind('click').click(function (e) {    
});
Sign up to request clarification or add additional context in comments.

Comments

5

You don't need .each() for binding event handlers. Try this instead:

$('.next, .prev').click(function(e){
        var target = $(this).attr('href');
        initiateScroll(target);
        console.log("click!");
        e.stopPropagation();
        e.preventDefault();
        return false;
});

EDIT: I think it is the way you are attaching the event handler from within the setupHorzNav function that is causing it. Change it to attach it only once from say, $(document).ready() or something.

I have managed to get the situation of multiple event handlers by attaching the event handlers from a function that gets called from event handler. The effect is that the number of click event handlers keeps increasing geometrically with each click.

This is the code: (and the jsfiddle demo)

function setupNav() {
    $('.next, .prev').each(function () {
        $(this).click(function (e) {
            setupNav();
            var target = $(this).attr('href');
            console.log("click!");
            e.stopPropagation();
            e.preventDefault();
            return false;
        });
    });
}

setupNav();

See how calling the setupNav() function from the click event handler adds multiple eventhandlers (and the click log message) on successive clicks

2 Comments

Wouldn't change/help/fix anything, this is the same as if each were used. each is just unnecessary in this situation, as you've pointed out, but wouldn't help if changed
I have used the first example code you have added. It works now. I can confirm in FF and Chrome that clicks are triggered as expected. There are no weird scroll issues now. Brilliant! Thank you.
3

Since it is not clear from your question whether you are calling the binding function multiple times, a quick and dirty fix would be:

$('.next, .prev').unbind('click').click(function() {
    ...
});

What you are doing here is unbinding any previously bound event handlers for click and binding afresh.

Comments

1

Are there no other click bindings elsewhere?

Are you loading the page with ajax?

You could also try this:

$('.next, .prev').click(function (e) {
    var target = $(this).attr('href');
    initiateScroll(target);
    console.log("click!");
    e.stopPropagation();
    e.preventDefault();
    return false;
});

1 Comment

There are click bindings elsewhere but on unrelated items, triggered by seperate functions. The page is not loaded via ajax.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.