disable mousewheel plugin over div - javascript

I'm using the mousewheel plugin that's shown here:
https://github.com/jquery/jquery-mousewheel
And it works well for getting the page to scroll horizontally, but I want to temporarily disable that and revert to vertical scrolling when a couple specific divs pop up. I tried this:
jQuery(document).ready(function() {
jQuery('html, div.everthing').mousewheel(function(e, delta) {
this.scrollLeft -= (delta * 1);
e.preventDefault();
});
jQuery(".interests.content .child").mouseover(
function stopHorizScroll(){
var vScroll = [
jQuery(".child.books").attr("class"),
jQuery(".child.quotes").attr("class"),
jQuery(".child.humans").attr("class"),
jQuery(".child.travel").attr("class")
];
var x = "show"
if (vScroll[0].indexOf(x) !== -1) {
jQuery('html, div.everthing').mousewheel(function(e, delta) {
return false;
});
}
});
});

You've already bound the mousewheel event. return false does nothing to the event you previously bound. To do what you're trying to do, you'd need to unbind the original event, then rebind on mouseleave, or stop the propagation. I'm not sure if you can unbind/destroy the mousewheel event, and I'm not sure if e.stopPropagation() would work either.
Perhaps an easier solution would be to set a flag when someone hovers over that div, and prevent the horizontal scroll if the flag is set. For example, something like this might work:
var stopScroll = false;
jQuery('html, div.everthing').mousewheel(function(e, delta) {
if ( stopScroll ) return;
this.scrollLeft -= (delta * 1);
e.preventDefault();
});
jQuery(".interests.content .child").hover(function() {
stopScroll = true;
}, function() {
stopScroll = false;
});

Related

hammer js > how to block horizontal panning during page scroll

I've got a page where I put some horizontal slideshows, and have added panning and swipe to them. Sadly, when scrolling on mobile devices, if you scroll above the slideshows, hammer will recognize panning and leave slideshows a little panned... Not so beautiful. I'm thinking about various solutions, but the most obvious maybe would be to stop panning during scroll. Is it possible some way? Here's an extract of my current code (sorry there are methods coming from the parent class..):
if(this.options.touch_enabled){
this.hm = new Hammer(this.panels_box, {
recognizers: [
[Hammer.Swipe,{ direction: Hammer.DIRECTION_HORIZONTAL, threshold: 80 }]
,[Hammer.Pan,{ direction: Hammer.DIRECTION_HORIZONTAL, threshold: 80 }, ['swipe']]
]
,domEvents: false
});
this.hm.on('swipeleft', function(e){ if(this.options.next_condition()) this.goto('next', null, true); }.bind(this));
this.hm.on('swiperight', function(e){ if(this.options.prev_condition()) this.goto('prev', null, true); }.bind(this));
this.hm.on('panstart', function(e){ this.disable_transition(); }.bind(this));
this.hm.on('panend', function(e){ this.enable_transition(); }.bind(this));
this.hm.on('panleft', function(e){
if(!this.options.loop){ if(this.data_box.getAttribute('data-current') >= this.bounds.end) return; }
this.panels_strip.style.setProperty('--distance', e.deltaX + 'px');
}.bind(this));
this.hm.on('panright', function(e){
if(!this.options.loop){ if(this.data_box.getAttribute('data-current') <= 0) return; }
this.panels_strip.style.setProperty('--distance', e.deltaX + 'px');
}.bind(this));
}// touch
Solution for me was to check deltaY and deltaX, along with event type (since the issue was not found on desktop computers). Here an extract:
this.hm.on('panleft', function(e){ // ...and same for panright
if(e.pointerType == 'touch' && (Math.abs(e.deltaY) > Math.abs(e.deltaX))){ return false; }
// do stuff
}

jQuery .on() scroll at canvas area [duplicate]

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';
}
}
}

Trigger mousewheel event infinitely

I want my mousewheel event to trigger every time I scroll my mouse up. Can you help me? Because it only fires once. Please see my code below.
$('#foo').bind('mousewheel', function(e){
if(e.originalEvent.wheelDelta /120 > 0) {
$("#room").trigger("click");
foo = true;
mousewheel = true;
}
else{
alert('down');
}
The mousewheel event was non-standard and now depreciated, use the vanilla wheel event instead,
document.getElementById('foo').addEventListener('wheel', function (e) {
if (e.deltaY / 120 > 0) {
$("#room").trigger("click");
foo = true;
mousewheel = true;
} else {
alert('down');
}
});
See the code in the compatibility section if you need to support legacy
Example proving it fires multiple times (use console)
document.body.addEventListener('wheel', console.dir.bind(console));

Eliminate Recursion on Events Triggered Inside Mousewheel Event

I'm working on a project that's using a sort of dummy pagination. The body is set to overflow: hidden and currently the only way to navigate the pages is by physically clicking on either links in the nav pane, or on sroll-down/scroll-up buttons. Here's an idea of the events that are triggered when those elements are physically clicked:
var links = $('#topnav, .top-mid a'), l = links.length - 1;
var id = 0;
$('.scrollDown, .scrollUp, .top-mid a, body.home #topnav').click(function (e) {
e.preventDefault();
var $this = $(this);
if ($this.is('.scrollDown') && id < l) id++;
if ($this.is('.scrollUp') && id > 0) id--;
if ($this.is('#topnav, .top-mid a')) id = links.index(this);
// Body is animated down or up and elements are
// shown or hidden depending on what was clicked and
// and what the var id is currently equal to
});
The idea is to trigger exactly ONE click of the scroll button on a mousewheel event. So something close to as simple as this, but that actually works:
$(window).on('mousewheel', function(e){ // I realize this will not work in FF
var evt = e.originalEvent.wheelDelta;
console.log(evt);
// Scrolling Down
if (evt < 0) {
$('.scrollDown').click(); // This fires recursively as long as wheelDelta !== 0
}
});
How can I either force wheelDelta to only increment or decrement by one, or, barring that, how can I eliminate the recursion on the click event?
I've been at this for a while, and read lots of posts and haven't been able to crack it. I've also tried fullPage.js, but it's rather heavy and doesn't really suit my project for other various reasons.
I finally solved this, and of course it turned out to be quite simple. It was a matter of toggling a boolean value inside the click() event, but only after all the animations had taken place. Like this:
var scrolled = false;
$(window).on('mousewheel', function(e){
var evt = e.originalEvent.wheelDelta;
// Scrolling Down - Only fire the click event if it hasn't already fired
if (evt < 0 && !scrolled) {
$('.scrollDown').click();
// Scrolling Up
} else if (evt > 0 && !scrolled) {
$('.scrollUp').click();
}
});
// Toggle the scrolled variable inside the original click event
$('.scrollDown, .scrollUp').click(function (e) {
e.preventDefault();
var $this = $(this);
if ($this.is('.scrollDown') && id < l) {
id++;
scrolled = true;
setTimeout(function(){
scrolled = false;
}, 1500);
}
if ($this.is('.scrollUp') && id > 0) {
id--;
scrolled = true;
setTimeout(function(){
scrolled = false;
}, 1500);
}
// Other events here
// The timeout has to be set high enough to assure
// that the mousewheel event is finished
});

Catch scrolling event on overflow:hidden element

Any insights on how to catch a scrolling event on a element that has overflow:hidden? I would like to scroll in a column without showing a scrollbar to the user.
This is actually a somewhat indepth process. What I do is set global flags when users mouse enters and leaves the element that you want to scroll. Then, on the mousewheel event for the body I check to see if the MOUSE_OVER flag is true, then stop propagation of the event. This is so the main body doesnt scroll in case your entire page has overflow.
Note that with overflow hidden, the default scrolling ability is lost so you must create it yourself. To do this you can set a mousewheel listener on your div in question and use the event.wheelDelta property to check whether the user is scrolling up or down. This value is different according to browser, but it is generally negative if scrolling down and positive if scrolling up. You can then change position of your div accordingly.
This code is hacked up quickly but it would essentially look like this...
var MOUSE_OVER = false;
$('body').bind('mousewheel', function(e){
if(MOUSE_OVER){
if(e.preventDefault) { e.preventDefault(); }
e.returnValue = false;
return false;
}
});
$('#myDiv').mouseenter(function(){ MOUSE_OVER=true; });
$('#myDiv').mouseleave(function(){ MOUSE_OVER=false; });
$('#myDiv').bind('mousewheel', function(e){
var delta = e.wheelDelta;
if(delta > 0){
//go up
}
else{
//go down
}
});
I use overflow:scroll, but also Absolutely position a div over the scroll bar in order to hide it.
$("body").css("overflow", "hidden")
$(document).bind('mousewheel', function(evt) {
var delta = evt.originalEvent.wheelDelta
console.log(delta)
})
works for me. adapted from How do I get the wheelDelta property?
I edited #anson s answer to Vanilla Javascript since it may be useful for others. Also note that "mousewheel" event is deprecated. So my code uses "wheel" instead. Next to that I added arrow functions for practical access the to "this".
fixScrollBehavior(elem) {
elem.addEventListener('scroll', (e) => {
console.log('scrolling');
});
let MOUSE_OVER = false;
elem.addEventListener('wheel', (e) => {
if (MOUSE_OVER) {
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
return false;
}
});
elem.addEventListener('mouseenter', () => {
MOUSE_OVER = true;
});
elem.addEventListener('mouseleave', () => {
MOUSE_OVER = false;
});
elem.addEventListener('wheel', (e) => {
let delta = e.wheelDelta;
if (delta > 0) {
//go up
} else {
//go down
}
});
}
Note that this does not fix the mobile touch-"scroll"s.
$("div").on('wheel', function (e) {
if (e.originalEvent.deltaY < 0) {
console.log("Scroll up");
} else {
console.log("Scroll down");
}
});
This did the trick for me.
JSFiddle
StackFiddle:
$("div").on('wheel', function(e) {
if (e.originalEvent.deltaY < 0) {
console.log("Scroll up");
} else {
console.log("Scroll down");
}
});
div {
height: 50px;
width: 300px;
background-color: black;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
I am late, but I think I have a better answer.
Style your container as overflow: overlay, this will free up space of scrollbar, then style scrollbar or hide it or make its handle height/width 0,
Then you should get scroll events also.
Note : styling the scrollbar is not supported in all web browsers.

Categories