I am working on an application and I need to track the mouse wheel movement but my functions are not working as I expect in Internet Explorer. It works in all other browsers but not IE, any ideas on what I am doing wrong?
JS...
var request = true;
var onMouseWheelSpin = function(event) {
if(request === true){
request = false;
var nDelta = 0;
if (!event) { event = window.event; }
// cross-bowser handling of eventdata to boil-down delta (+1 or -1)
if ( event.wheelDelta ) { // IE and Opera
nDelta= event.wheelDelta;
if ( window.opera ) { // Opera has the values reversed
nDelta= -nDelta;
}
}
else if (event.detail) { // Mozilla FireFox
nDelta= -event.detail;
}
if (nDelta > 0) {
zoomFun( 1, event );
}
if (nDelta < 0) {
zoomFun( -1, event );
}
if ( event.preventDefault ) { // Mozilla FireFox
event.preventDefault();
}
event.returnValue = false; // cancel default action
}
}
var zoomFun = function(delta,e) {
if(delta > 0){ // zoom in
alert("In");
}else{ // zoom out
alert("Out");
}
request = true;
}
var setupMouseWheel = function(){
// for mouse scrolling in Firefox
var elem = document.getElementById("zoom");
if (elem.addEventListener) { // all browsers except IE before version 9
// Internet Explorer, Opera, Google Chrome and Safari
elem.addEventListener ("mousewheel", onMouseWheelSpin, false);
// Firefox
elem.addEventListener ("DOMMouseScroll", onMouseWheelSpin, false);
}else{
if (elem.attachEvent) { // IE before version 9
elem.attachEvent ("onmousewheel", onMouseWheelSpin);
}
}
}
I am calling the setupMouseWheel function onload in the body aka
<body onload="setupMouseWheel();">
Thanks for the help!
To listen to the mouse wheel, it's best to listen to DOMMouseScroll, mousewheel and wheel. The last one is IE, and is the only one you're not listening for.
I'll also point out that jQuery has a shortcut for binding multiple events:
$(elem).on("DOMMouseScroll mousewheel wheel", onMouseWheelSpin);
update: noticed that though you tagged this as jQuery, you're not actually using it. To do this without jQuery, just carry on as you are but add a wheel event listener like the others.
I finally found a great cross browser approach here for anyone who has a similar issue
https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel
Related
I believe that EDGE recently changed its behaviour and when used on a Desktop, non touch device, now reports values > 0 for navigator.maxTouchPoints
This breaks the following JS-Code we use to detect touch-devices:
function is_touch_device() {
var touch = false;
if ( window.PointerEvent && ('maxTouchPoints' in navigator) ) {
// if Pointer Events are supported, just check maxTouchPoints
if (navigator.maxTouchPoints > 0) {
touch = true;
}
} else {
// no Pointer Events...
if ( window.matchMedia && window.matchMedia("(any-pointer:coarse)").matches ) {
// check for any-pointer:coarse which mostly means touchscreen
touch = true;
} else if ( window.TouchEvent || ('ontouchstart' in window) ) {
// last resort - check for exposed touch events API / event handler
touch = true;
}
}
return touch;
}
Does anyone know of a reliable way to detect (in JS) if MS Edge is used on a touch device? I haven't been able to find anything.
I know Edge is almost dead, but for the time being, i have to support it.
Thanks!
You could use the following code to check whether it is a touch device.
<script type="text/javascript">
if ("ontouchstart" in document.documentElement) {
document.write("your device is a touch screen device.");
}
else {
document.write("your device is NOT a touch device");
}
</script>
Is there a way to get the mouse wheel events (not talking about scroll events) in jQuery?
$(document).ready(function(){
$('#foo').bind('mousewheel', function(e){
if(e.originalEvent.wheelDelta /120 > 0) {
console.log('scrolling up !');
}
else{
console.log('scrolling down !');
}
});
});
Binding to both mousewheel and DOMMouseScroll ended up working really well for me:
$(window).bind('mousewheel DOMMouseScroll', function(event){
if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
// scroll up
}
else {
// scroll down
}
});
This method is working in IE9+, Chrome 33, and Firefox 27.
Edit - Mar 2016
I decided to revisit this issue since it's been a while. The MDN page for the scroll event has a great way of retrieving the scroll position that makes use of requestAnimationFrame, which is highly preferable to my previous detection method. I modified their code to provide better compatibility in addition to scroll direction and position:
(function() {
var supportOffset = window.pageYOffset !== undefined,
lastKnownPos = 0,
ticking = false,
scrollDir,
currYPos;
function doSomething(scrollPos, scrollDir) {
// Your code goes here...
console.log('scroll pos: ' + scrollPos + ' | scroll dir: ' + scrollDir);
}
window.addEventListener('wheel', function(e) {
currYPos = supportOffset ? window.pageYOffset : document.body.scrollTop;
scrollDir = lastKnownPos > currYPos ? 'up' : 'down';
lastKnownPos = currYPos;
if (!ticking) {
window.requestAnimationFrame(function() {
doSomething(lastKnownPos, scrollDir);
ticking = false;
});
}
ticking = true;
});
})();
See the Pen Vanilla JS Scroll Tracking by Jesse Dupuy (#blindside85) on CodePen.
This code is currently working in Chrome v50, Firefox v44, Safari v9, and IE9+
References:
https://developer.mozilla.org/en-US/docs/Web/Events/scroll
https://developer.mozilla.org/en-US/docs/Web/Events/wheel
As of now in 2017, you can just write
$(window).on('wheel', function(event){
// deltaY obviously records vertical scroll, deltaX and deltaZ exist too.
// this condition makes sure it's vertical scrolling that happened
if(event.originalEvent.deltaY !== 0){
if(event.originalEvent.deltaY < 0){
// wheeled up
}
else {
// wheeled down
}
}
});
Works with current Firefox 51, Chrome 56, IE9+
There's a plugin that detects up/down mouse wheel and velocity over a region.
Answers talking about "mousewheel" event are refering to a deprecated event. The standard event is simply "wheel". See https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel
This worked for me:)
//Firefox
$('#elem').bind('DOMMouseScroll', function(e){
if(e.originalEvent.detail > 0) {
//scroll down
console.log('Down');
}else {
//scroll up
console.log('Up');
}
//prevent page fom scrolling
return false;
});
//IE, Opera, Safari
$('#elem').bind('mousewheel', function(e){
if(e.originalEvent.wheelDelta < 0) {
//scroll down
console.log('Down');
}else {
//scroll up
console.log('Up');
}
//prevent page fom scrolling
return false;
});
from stackoverflow
Here is a vanilla solution. Can be used in jQuery if the event passed to the function is event.originalEvent which jQuery makes available as property of the jQuery event. Or if inside the callback function under we add before first line: event = event.originalEvent;.
This code normalizes the wheel speed/amount and is positive for what would be a forward scroll in a typical mouse, and negative in a backward mouse wheel movement.
Demo: http://jsfiddle.net/BXhzD/
var wheel = document.getElementById('wheel');
function report(ammout) {
wheel.innerHTML = 'wheel ammout: ' + ammout;
}
function callback(event) {
var normalized;
if (event.wheelDelta) {
normalized = (event.wheelDelta % 120 - 0) == -0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
} else {
var rawAmmount = event.deltaY ? event.deltaY : event.detail;
normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
}
report(normalized);
}
var event = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
window.addEventListener(event, callback);
There is also a plugin for jQuery, which is more verbose in the code and some extra sugar: https://github.com/brandonaaron/jquery-mousewheel
This is working in each IE, Firefox and Chrome's latest versions.
$(document).ready(function(){
$('#whole').bind('DOMMouseScroll mousewheel', function(e){
if(e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
alert("up");
}
else{
alert("down");
}
});
});
I was stuck in this issue today and found this code is working fine for me
$('#content').on('mousewheel', function(event) {
//console.log(event.deltaX, event.deltaY, event.deltaFactor);
if(event.deltaY > 0) {
console.log('scroll up');
} else {
console.log('scroll down');
}
});
use this code
knob.bind('mousewheel', function(e){
if(e.originalEvent.wheelDelta < 0) {
moveKnob('down');
} else {
moveKnob('up');
}
return false;
});
The plugin that #DarinDimitrov posted, jquery-mousewheel, is broken with jQuery 3+. It would be more advisable to use jquery-wheel which works with jQuery 3+.
If you don't want to go the jQuery route, MDN highly cautions using the mousewheel event as it's nonstandard and unsupported in many places. It instead says that you should use the wheel event as you get much more specificity over exactly what the values you're getting mean. It's supported by most major browsers.
my combination looks like this. it fades out and fades in on each scroll down/up. otherwise you have to scroll up to the header, for fading the header in.
var header = $("#header");
$('#content-container').bind('mousewheel', function(e){
if(e.originalEvent.wheelDelta > 0) {
if (header.data('faded')) {
header.data('faded', 0).stop(true).fadeTo(800, 1);
}
}
else{
if (!header.data('faded')) header.data('faded', 1).stop(true).fadeTo(800, 0);
}
});
the above one is not optimized for touch/mobile, I think this one does it better for all mobile:
var iScrollPos = 0;
var header = $("#header");
$('#content-container').scroll(function () {
var iCurScrollPos = $(this).scrollTop();
if (iCurScrollPos > iScrollPos) {
if (!header.data('faded')) header.data('faded', 1).stop(true).fadeTo(800, 0);
} else {
//Scrolling Up
if (header.data('faded')) {
header.data('faded', 0).stop(true).fadeTo(800, 1);
}
}
iScrollPos = iCurScrollPos;
});
If using mentioned jquery mousewheel plugin, then what about to use the 2nd argument of event handler function - delta:
$('#my-element').on('mousewheel', function(event, delta) {
if(delta > 0) {
console.log('scroll up');
}
else {
console.log('scroll down');
}
});
I think many key things are a bit all over the place and I needed to read all the answers to make my code work as I wanted, so I will post my findings in just one place:
You should use "wheel" event over the other deprecated or browser specific events.
Many people here is getting something wrong: the opposite of x>0 is x<=0 and the opposite of x<0 is x>=0, many of the answers in here will trigger scrolling down or up incorrectly when x=0 (horizontal scrolling).
Someone was asking how to put sensitivity on it, for this you can use setTimeout() with like 50 ms of delay that changes some helper flag isWaiting=false and you protect yourself with if(isWaiting) then don't do anything. When it fires you manually change isWaiting=true and just below this line you start the setTimeout again who will later change isWaiting=false after 50 ms.
I got same problem recently where
$(window).mousewheel was returning undefined
What I did was $(window).on('mousewheel', function() {});
Further to process it I am using:
function (event) {
var direction = null,
key;
if (event.type === 'mousewheel') {
if (yourFunctionForGetMouseWheelDirection(event) > 0) {
direction = 'up';
} else {
direction = 'down';
}
}
}
I have a few event listener and it works in all browsers except mousewheel in Firefox (in Chrome and other it works perfect). It should zoom in and zoom out when I scrolling. It's JSC3D library. Code is below
// setup input handlers.
// compatibility for touch devices is taken into account
var self = this;
if(!JSC3D.PlatformInfo.isTouchDevice) {
this.canvas.addEventListener('mousedown', function(e){self.mouseDownHandler(e);}, false);
this.canvas.addEventListener('mouseup', function(e){self.mouseUpHandler(e);}, false);
this.canvas.addEventListener('mousemove', function(e){self.mouseMoveHandler(e);}, false);
//this.canvas.addEventListener('mousewheel', function(e){self.mouseWheelHandler(e);}, false);
this.canvas.addEventListener(JSC3D.PlatformInfo.browser == 'firefox' ? 'DOMMouseScroll' : 'mousewheel',
function(e){self.mouseWheelHandler(e);}, false);
document.addEventListener('keydown', function(e){self.keyDownHandler(e);}, false);
document.addEventListener('keyup', function(e){self.keyUpHandler(e);}, false);
}
else if(JSC3D.Hammer) {
JSC3D.Hammer(this.canvas).on('touch release hold drag pinch', function(e){self.gestureHandler(e);});
}
else {
this.canvas.addEventListener('touchstart', function(e){self.touchStartHandler(e);}, false);
this.canvas.addEventListener('touchend', function(e){self.touchEndHandler(e);}, false);
this.canvas.addEventListener('touchmove', function(e){self.touchMoveHandler(e);}, false);
}
And function JSC3D.Viewer.prototype.mouseWheelHandler:
JSC3D.Viewer.prototype.mouseWheelHandler = function(e) {
if(!this.isLoaded)
return;
if(this.onmousewheel) {
var info = this.pick(e.clientX, e.clientY);
this.onmousewheel(info.canvasX, info.canvasY, e.button, info.depth, info.mesh);
}
e.preventDefault();
e.stopPropagation();
if(!this.isDefaultInputHandlerEnabled)
return;
this.zoomFactor *= (JSC3D.PlatformInfo.browser == 'firefox' ? -e.detail : e.wheelDelta) < 0 ? 1.1 : 0.91;
this.update();
};
Anyone?
The most respect for jsc3d, but rather than sniffing browser agent, i would better go with feature detection for this, something like:
if(!JSC3D.PlatformInfo.isTouchDevice) {
...
this.canvas.addEventListener('onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll', function(e){self.mouseWheelHandler(e);});
...
}
EDIT:
...and with the same logic, also remove the check for 'firefox' in :
JSC3D.Viewer.prototype.mouseWheelHandler = function(e) {
...
this.zoomFactor *= (e.deltaY ? e.deltaY : e.wheelDelta ? e.wheelDelta : e.detail) < 0 ? 1.1 : 0.91;
...
};
then, you should get your handler:
function OnViewerMouseWheeel(canvasX, canvasY, button, depth, mesh) {
...
}
viewer.onmousewheel=OnViewerMouseWheeel;
Tested in latest FF, 'onwheel' in document is returning true.
Please, let me know if this solves the issue.
if (this.addEventListener) {
// IE9, Chrome, Safari, Opera
this.addEventListener("mousewheel", MouseWheelHandler, false);
// Firefox
this.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else this.attachEvent("onmousewheel", MouseWheelHandler);
Firefox uses the DOMMouseScroll event rather than mousewheel
Hi i'm building a webapp. To remove the onclick delay i found this script on
http://cubiq.org/remove-onclick-delay-on-webkit-for-iphone
The code is bascically-
function NoClickDelay(el) {
this.element = el;
if( 'ontouchstart' in window ){
console.log("===================touch supported :P")
this.element.addEventListener('touchstart', this.handleEvent, false);
}
}
NoClickDelay.prototype = {
handleEvent: function(e) {
switch(e.type) {
case 'touchstart': this.onTouchStart(e); break;
case 'touchmove': this.onTouchMove(e); break;
case 'touchend': this.onTouchEnd(e); break;
}
},
onTouchStart: function(e) {
//e.preventDefault(); //removed to let the page scroll
this.moved = false;
this.element.addEventListener('touchmove', this, false);
this.element.addEventListener('touchend', this, false);
},
onTouchMove: function(e) {
this.moved = true;
},
onTouchEnd: function(e) {
this.element.removeEventListener('touchmove', this, false);
this.element.removeEventListener('touchend', this, false);
if( !this.moved ) {
// Place your code here or use the click simulation below
var theTarget = document.elementFromPoint(e.changedTouches[0].clientX, e.changedTouches[0].clientY);
if(theTarget.nodeType == 3) theTarget = theTarget.parentNode;
var theEvent = document.createEvent('MouseEvents');
theEvent.initEvent('click', true, true);
theTarget.dispatchEvent(theEvent);
}
}
};
My question is that this works on iphone/ipad but not on Android. What prevents it from working in android and what can i do to achieve a similar behavior in android and other devices??? please help.
We had the same problem and solved it with a slightly different approche.
We were able to fix it for iPhone and Android. Clicks will be fired immediately and the delayed events will be ignored. Maybe you can use it:
https://github.com/cargomedia/jquery.touchToClick
In your link there is someone commented about Android solution (I haven't try it):
Android has same problem with laggy onClicks. Your demo doesn’t work on Android, unless I comment out window.Touch below, so I believe that DOM property is only visible on iOS.
function NoClickDelay(el) {
this.element = el;
// if (window.Touch) not available on android
this.element.addEventListener(‘touchstart’, this, false);
}
With the above change Android gets non-laggy touch event!
touchToClick or fastclick does not work in my case.
I had a lot of code at onclick events, and I'm using Tappy actually:
onClick event in android webview too slow
<meta name="viewport" content="width=device-width, user-scalable=no">
This disables double-tap zooming, so browser does not wait to detect double-tap. No need to bother with tap events. Sadly, it works only in recent browsers.
Is it possible to track what script or what line of code, that ex. set a width on an element?
//KennethBL
On IE you can use the onpropertychanged event to fire an event when the width element is fired.
On IE 9, Chrome and FF you can use the DOMAttrModified:
var elm = document.getElementById ("targetElemntId");
if (elm.addEventListener) { // all browsers except IE before version 9
elm.addEventListener ('DOMAttrModified', checkProperty, false); //FF, Opera, IE
}
if (elm.attachEvent) { // IE & Opera
elm.attachEvent ('onpropertychange', checkProperty); // IE
}
function checkProperty(event) {
var name = event.attrName ? event.attrName : event.propertyName;
if(name == "width") {
alert("width changed");
}
}
Don't know how you would achieve this on chrome though.