I try to make a mousewheel event script, but getting some issues since I'm using an Apple Magic Mouse and its continue-on-scroll function.
I want to do this http://jsfiddle.net/Sg8JQ/ (from jQuery Tools Scrollable with Mousewheel - scroll ONE position and stop, using http://brandonaaron.net/code/mousewheel/demos), but I want a short animation (like 250ms) when scrolling to boxes, AND ability to go throught multiple boxes when scrolling multiple times during one animation. (If I scroll, animation start scrolling to second box, but if I scroll again, I want to go to the third one, and if I scroll two times, to the forth, etc.)
I first thought stopPropagation
/ preventDefault
/ return false;
could "stop" the mousewheel velocity (and the var delta) – so I can count the number of new scroll events (maybe with a timer) –, but none of them does.
Ideas?
EDIT : If you try to scroll in Google Calendars with these mouses, several calendars are switched, not only one. It seems they can't fix that neither.
EDIT 2 : I thought unbind mousewheel and bind it again after could stop the mousewheel listener (and don't listen to the end of inertia). It did not.
EDIT 3 : tried to work out with Dates (thanks to this post), not optimal but better than nothing http://jsfiddle.net/eZ6KE/
Best way is to use a timeout and check inside the listener if the timeout is still active:
var timeout = null;
var speed = 100; //ms
var canScroll = true;
$(element).on('DOMMouseScroll mousewheel wheel', function(event) {
// Timeout active? do nothing
if (timeout !== null) {
event.preventDefault();
return false;
}
// Get scroll delta, check for the different kind of event indexes regarding delta/scrolls
var delta = event.originalEvent.detail ? event.originalEvent.detail * (-120) : (
event.originalEvent.wheelDelta ? event.originalEvent.wheelDelta : (
event.originalEvent.deltaY ? (event.originalEvent.deltaY * 1) * (-120) : 0
));
// Get direction
var scrollDown = delta < 0;
// This is where you do something with scrolling and reset the timeout
// If the container can be scrolling, be sure to prevent the default mouse action
// otherwise the parent container can scroll too
if (canScroll) {
timeout = setTimeout(function(){timeout = null;}, speed);
event.preventDefault();
return false;
}
// Container couldn't scroll, so let the parent scroll
return true;
});
You can apply this to any scrollable element and in my case, I used the jQuery tools scrollable library but ended up heavily customizing it to improve browser support as well as adding in custom functionality specific to my use case.
One thing you want to be careful of is ensuring that the timeout is sufficiently long enough to prevent multiple events from triggering seamlessly. My solution is effective only if you want to control the scrolling speed of elements and how many should be scrolled at once. If you add console.log(event)
to the top of the listener function and scroll using a continuous scrolling peripheral, you will see many mousewheel events being triggered.
Annoyingly the Firefox scroll DOMMouseScroll does not trigger on magic mouse or continuous scroll devices, but for normal scroll devices that have a scroll and stop through the clicking cycle of the mouse wheel.