0

I'm using event delegation in the pagination for my website. When you click the < or > buttons it moves the page up or down. The problem is that if you don't release the mouse button, in a split-second it will keep repeating the click handler.

How can I make it so that this event only occurs once per-click? Here's my code:

$(document).on('mousedown', '#prev', function(event) {
    // Page is the value of the URL parameter 'page'
    if (page != 1) {
        page--;
        var state = {
          "thisIsOnPopState": true
        };
        history.replaceState(state, "a", "?page=" + page + "");
    }
    // Refresh is a custom function that loads new items on the page
    refresh();
});
Sanjeev Singh
  • 3,976
  • 3
  • 33
  • 38
mightyspaj3
  • 471
  • 1
  • 8
  • 22
  • try changing `mousedown` to `click` – Wesley Smith Apr 28 '15 at 02:08
  • I did previously, it doesn't change anything – mightyspaj3 Apr 28 '15 at 02:10
  • 2
    Are you sure you dont have some other code bound to the element? – Wesley Smith Apr 28 '15 at 02:12
  • 1
    I mean to say, a "click" handler will only fire once per click of the mouse, if you changed it to "click" and your function is getting called repeatedly, you must have some other handler attached to that element or are somehow calling that function repeatedly from elsewhere in your code, a click handler could not do that – Wesley Smith Apr 28 '15 at 02:20
  • 2
    It sounds like the element is bound twice (as DelightedD0D said). Try doing `('#prev').off('click')` before binding -- and yeah you should really be doing `click` for this behavior, not `mousedown`. I would also bind it directly to `#prev` (not `document`), as you're currently listening to the entire document. – Benny Schmidt Apr 28 '15 at 02:21
  • 2
    can you add a alert just before `$(document).on('mouse` and see how many times it is getting called – Arun P Johny Apr 28 '15 at 02:40
  • replace your current handler with the following code and open the console when you run it. What gets printed in the console when you click the element one time? `var i =0; $(document).on('click', '#prev', function(event) { console.log('number of times function has been called: '+i); i++; });` – Wesley Smith Apr 28 '15 at 06:40
  • it just says this repeatedly `number of times function has been called: 1 filters.js:100 number of times function has been called: 0` – mightyspaj3 Apr 28 '15 at 06:44

3 Answers3

1

You should use "click" event instead of "mousedown" unless you have a unavoidable reason. But "mousedown" or "touchstart" event occurs when a user start pressing the mouse button or screen and it will not be fired until you release the button and press it again.

So I assume you are using a chattering mouse or mouses which has macro software. change event into "click" and see if it works and in the case "click" event is not gonna solve the issue,try using another mouse.

FYI,underscore methods _.throttle or _.debounce might help to support chattering mouses.

throttle_.throttle(function, wait, [options])

Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with.


debounce_.debounce(function, wait, [immediate])

Creates and returns a new debounced version of the passed function which will postpone its execution until after wait milliseconds have elapsed since the last time it was invoked. Useful for implementing behavior that should only happen after the input has stopped arriving. For example: rendering a preview of a Markdown comment, recalculating a layout after the window has stopped being resized, and so on.

http://underscorejs.org/

suish
  • 3,253
  • 1
  • 15
  • 34
  • I tried using click, it doesn't make a difference. Also I'm using a $70 gaming mouse, so it isn't the mouse lol, and even if it was you shouldn't expect your users to have good mice either. – mightyspaj3 Apr 28 '15 at 02:18
0

If you want to use a "delegated" event handler rather than a "direct" event handler to bubble up the event, try to use a more specific target selector than $(document) like $('.some-class') where some-class is the class name directly above the #prev element.

I would also use either the mouseup or click events instead to avoid the mousedown event firing while the mouse click is held down.

According to the API:

The majority of browser events bubble, or propagate, from the deepest, innermost element (the event target) in the document where they occur all the way up to the body and the document element.

Try this:

// delegated "click" listener using a more specific target selector
$('.some-class').on('click', '#prev', function(event) {})

You may want to check your HTML to see if you are using #prev multiple times. Usually, just creating the listener on the target ID element should work fine.

// direct "click" listener on an ID element
$('#prev').on('click', function(event) {})
boombox
  • 2,396
  • 2
  • 11
  • 15
0

I haven't found the answer to this question, but I have found a solution that fixes the problem. What I have done is added a conditional that only allows the click event to occur once-per-click:

var i = 0;

$(document).on('click', '#prev', function(event) {
    if (page != 1 && i === 0) {
        page--;
        var state = {
          "thisIsOnPopState": true
        };
        history.replaceState(state, "a", "?page=" + page + "");
        i = 1;
        refresh();
    }
});

// Resets 'i' for the next click
$(document).on('mouseup', function() {
    i = 0;
});
mightyspaj3
  • 471
  • 1
  • 8
  • 22
  • While this may seem to solve your problem. Your are really doing yourself a huge disservice. The fact is, your code and the solutions offered should all work just as expected. If your code is not working in your application, it is because you have made a mistake either in the code itself, the logic of your application, or some other code in the application that is inadvertently affecting this functionality. You should really figure out where that is and address it now. A band-aid now might come back to bite you in the rear later when once your app is more complicated. – Wesley Smith Apr 28 '15 at 06:47