Mousewheel event in modern browsers
Clean and simple:
window.addEventListener("wheel", event => console.info(event.deltaY));
Browsers may return different values for the delta (for instance, Chrome returns +120
(scroll up) or -120
(scroll down). A nice trick to normalize it is to extract its sign, effectively converting it to +1
/-1
:window.addEventListener("wheel", event => {
const delta = Math.sign(event.deltaY);
console.info(delta);
});
Reference: MDN. mousewheel event is not triggering in firefox browser
Firefox doesn't recognize "mousewheel" as of version 3. You should use "DOMMouseScroll" instead for firefox.
check this: http://www.javascriptkit.com/javatutors/onmousewheel.shtml
mousewheel,wheel and DOMMouseScroll in JavaScript
I would suggest that all three of them be used at the same time to cover all browsers.
Notes:
In versions of Firefox where both the
wheel
andDOMMouseScroll
events are supported, we need a way to instruct the browser to execute onlywheel
and not both. Something like the following:if ("onwheel" in window) ...
The above check though, in the case of
IE9
andIE10
will fail, because even though these browsers support thewheel
event, they don't have theonwheel
attribute in DOM elements. To counter that we can use a flag as shown later on.I believe the number returned by
e.deltaY
,e.wheelDelta
ande.detail
is not useful other than helping us determine the direction of the scroll, so in the solution below-1
and1
will be returned.
/* The flag that determines whether the wheel event is supported. */var supportsWheel = false;
/* The function that will run when the events are triggered. */function DoSomething (e) { /* Check whether the wheel event is supported. */ if (e.type == "wheel") supportsWheel = true; else if (supportsWheel) return;
/* Determine the direction of the scroll (< 0 → up, > 0 → down). */ var delta = ((e.deltaY || -e.wheelDelta || e.detail) >> 10) || 1;
/* ... */ console.log(delta);}
/* Add the event listeners for each event. */document.addEventListener('wheel', DoSomething);document.addEventListener('mousewheel', DoSomething);document.addEventListener('DOMMouseScroll', DoSomething);
Normalizing mousewheel speed across browsers
Edit September 2014
Given that:
- Different versions of the same browser on OS X have yielded different values in the past, and may do so in the future, and that
- Using the trackpad on OS X yields very similar effects to using a mouse wheel, yet gives very different event values, and yet the device difference cannot be detected by JS
var handleScroll = function(evt){
if (!evt) evt = event;
var direction = (evt.detail<0 || evt.wheelDelta>0) ? 1 : -1;
// Use the value as you will
};
someEl.addEventListener('DOMMouseScroll',handleScroll,false); // for Firefox
someEl.addEventListener('mousewheel', handleScroll,false); // for everyone else
Original attempt to be correct follows.
Here is my first attempt at a script to normalize the values. It has two flaws on OS X: Firefox on OS X will produce values 1/3 what they should be, and Chrome on OS X will produce values 1/40 what they should be.
// Returns +1 for a single wheel roll 'up', -1 for a single roll 'down'
var wheelDistance = function(evt){
if (!evt) evt = event;
var w=evt.wheelDelta, d=evt.detail;
if (d){
if (w) return w/d/40*d>0?1:-1; // Opera
else return -d/3; // Firefox; TODO: do not /3 for OS X
} else return w/120; // IE/Safari/Chrome TODO: /3 for Chrome OS X
};
You can test out this code on your own browser here: http://phrogz.net/JS/wheeldelta.htmlSuggestions for detecting and improving the behavior on Firefox and Chrome on OS X are welcome.
Edit: One suggestion from @Tom is to simply count each event call as a single move, using the sign of the distance to adjust it. This will not give great results under smooth/accelerated scrolling on OS X, nor handle perfectly cases when the mouse wheel is moved very fast (e.g. wheelDelta
is 240), but these happen infrequently. This code is now the recommended technique shown at the top of this answer, for the reasons described there.
Vimeo iFrame Stealing Mouse Wheel Event on Firefox
This is basically by design. Your code should be completely unaware of what the user does inside an IFRAME (especially one from a different origin like YouTube - this is a part of the web's security architecture, as mandated by the Same Origin Policy.)
Now, even in the cross-origin case browsers can choose to let scrolling affect the frame's ancestor if the frame itself doesn't scroll. This scrolling should happen without any events firing on the top document - see Chrome's behaviour if you scroll to the bottom of this IFRAME and keep scrolling:
http://jsfiddle.net/8cj0dofx/1/
HTML:
<iframe src="data:text/html,<body style='background:grey;height:550px'>Hello" seamless></iframe>
<div style="height:100px">Hello</div>
JS:document.addEventListener('DOMMouseScroll', function(e){
document.getElementsByTagName('div')[0].firstChild.data += ' ' + e.type
});
document.addEventListener('mousewheel', function(e){
document.getElementsByTagName('div')[0].firstChild.data += ' ' + e.type
});
What you'll see is that when you have scrolled to the end of the IFRAME, the main document will scroll but no events will fire until the mouse is above the parent document. MouseWheel in Chrome and Firefox
Fix for no MouseWheel in a Flex app when wmode="opaque" (it actually works in IE, just not Firefox or Chrome, probably not Safari or Opera either). This also fixes the different MouseWheel scroller rates between Firefox and everything else.
Add this JavaScript to your wrapper:
.
if(window.addEventListener) {
var eventType = (navigator.userAgent.indexOf('Firefox') !=-1) ? "DOMMouseScroll" : "mousewheel";
window.addEventListener(eventType, handleWheel, false);
}
function handleWheel(event) {
var app = document.getElementById("YOUR_APPLICATION");
var edelta = (navigator.userAgent.indexOf('Firefox') !=-1) ? -event.detail : event.wheelDelta/40;
var o = {x: event.screenX, y: event.screenY,
delta: edelta,
ctrlKey: event.ctrlKey, altKey: event.altKey,
shiftKey: event.shiftKey}
app.handleWheel(o);
}
And drop this support class into your main MXML file (Declarations for Flex4):.
package {
import flash.display.InteractiveObject;
import flash.display.Shape;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import flash.geom.Point;
import mx.core.FlexGlobals;
import mx.core.UIComponent;
import mx.events.FlexEvent;
public class MouseWheelSupport {
//--------------------------------------
// Constructor
//--------------------------------------
public function MouseWheelSupport() {
FlexGlobals.topLevelApplication.addEventListener(FlexEvent.APPLICATION_COMPLETE, attachMouseWheelHandler);
}
//------------------------------------------------------------------------------
//
// Functions
//
//------------------------------------------------------------------------------
//--------------------------------------
// Private
//--------------------------------------
private function attachMouseWheelHandler(event : FlexEvent) : void {
ExternalInterface.addCallback("handleWheel", handleWheel);
}
private function handleWheel(event : Object) : void {
var obj : InteractiveObject = null;
var applicationStage : Stage = FlexGlobals.topLevelApplication.stage as Stage;
var mousePoint : Point = new Point(applicationStage.mouseX, applicationStage.mouseY);
var objects : Array = applicationStage.getObjectsUnderPoint(mousePoint);
for (var i : int = objects.length - 1; i >= 0; i--) {
if (objects[i] is InteractiveObject) {
obj = objects[i] as InteractiveObject;
break;
}
else {
if (objects[i] is Shape && (objects[i] as Shape).parent) {
obj = (objects[i] as Shape).parent;
break;
}
}
}
if (obj) {
var mEvent : MouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, true, false,
mousePoint.x, mousePoint.y, obj,
event.ctrlKey, event.altKey, event.shiftKey,
false, Number(event.delta));
obj.dispatchEvent(mEvent);
}
}
}
}
JavaScript example:. <script type="text/javascript">
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
var swfVersionStr = "10.1.0";
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
var xiSwfUrlStr = "playerProductInstall.swf";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "#ffffff";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
params.wmode = "opaque";
var attributes = {};
attributes.id = "YOURAPP";
attributes.name = "YOURAPP";
attributes.align = "middle";
if(window.addEventListener) {
var eventType = (navigator.userAgent.indexOf('Firefox') !=-1) ? "DOMMouseScroll" : "mousewheel";
window.addEventListener(eventType, handleWheel, false);
}
function handleWheel(event) {
var app = document.getElementById("YOURAPP");
var edelta = (navigator.userAgent.indexOf('Firefox') !=-1) ? -event.detail : event.wheelDelta/40;
var o = {x: event.screenX, y: event.screenY,
delta: edelta,
ctrlKey: event.ctrlKey, altKey: event.altKey,
shiftKey: event.shiftKey}
app.handleWheel(o);
}
swfobject.embedSWF(
"YOURAPP.swf", "flashContent",
"100%", "100%",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
</script>
Related Topics
Subject VS Behaviorsubject VS Replaysubject in Angular
How to Getting Browser Current Locale Preference Using JavaScript
How to Use Local Storage in Angular
How to Reset the Scale/Zoom of a Web App on an Orientation Change on the Iphone
Where Should I Initialize Pg-Promise
Why Does This Foreach Return Undefined When Using a Return Statement
How to Create a Stopwatch Using JavaScript
Why Is There a 'Null' Value in JavaScript
What's "This" in JavaScript Onclick
Angularjs "Controller As" or "$Scope"
Objects Are Not Valid as a React Child (Found: [Object Promise])
Is Localstorage.Getitem('Item') Better Than Localstorage.Item or Localstorage['Item']
JavaScript Regular Expression to Check for Ip Addresses
How to Execute a Function on Pressing the Enter Key in an <Input> Field