So basically I'm developing a website where the scroll event's default is prevented and instead each scroll takes you down or up to the next "section". This works really well on PC and some phones but on iOS the scrolling just becomes this jumbled up mess and quite frankly I'm out of ideas.
The scroll API for mobile I'm using is jquery touchSwipe
https://github.com/mattbryson/TouchSwipe-Jquery-Plugin
And the following code is the function that is supposed to do all the work.
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
$(window).swipe({
swipe:function(event, direction, distance, duration, fingerCount, fingerData) {
if (scrolling == false && direction === "down") {
scrolling = true;
scrollSection = Math.round($(window).scrollTop()/window.innerHeight);
scrollTo_(event,sections[scrollSection-1]);
setTimeout(function() {
scrolling = false;
}, 1000);
}
else if (scrolling == false && direction === "up") {
scrolling = true;
scrollSection = Math.round($(window).scrollTop()/window.innerHeight);
scrollTo_(event,sections[scrollSection+1]);
setTimeout(function() {
scrolling = false;
}, 1000);
}
}
});
}
If you have any questions by all means let me know and I will update this question.
Have you tried with this?
In my web app last days I've worked on Jquery UI slider, that's didn't worked for mobiles, so after attaching that it get's worked.
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'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;
});
I am trying to detect user scroll, if to left and to right then trigger and do something.
But if user use trackpad scroll to top or to bottom then it will accidentally scroll to left or to right.
I think, may be not just check timer define per scroll also need to check if user scroll distance smaller than 20, we can differentiate that as accidentally and don't do anything.
I can't find the way check if user scroll distance, the element is not be scrollable so can't use scrollTop scrollLeft....
Any idea?
var scroll_timer;
$('img').bind('mousewheel', function(e) {
if (e.originalEvent.wheelDeltaX < 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
// console.log('right');
}, 200);
} else if (e.originalEvent.wheelDeltaX > 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
// console.log('left');
}, 200);
}
});
Here is my JSFiddle
It looks like you can use e.originalEvent.wheelDeltaX to get scroll distance values. You could then use e.originalEvent.wheelDeltaY to see if the user is scrolling vertically more than horizontally and trigger stuff after that is true.
Here's a demo that works by testing if the value of scrolling Y is less that scrolling X and then allowing you to trigger if it's left or right after that. Seems to do the trick on my mac trackpad
var scroll_timer;
$('img').bind('mousewheel', function(e) {
if((Math.abs(e.originalEvent.wheelDeltaX) > Math.abs(e.originalEvent.wheelDeltaY)))
{
if (e.originalEvent.wheelDeltaX < 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
console.log('right');
}, 200);
} else if (e.originalEvent.wheelDeltaX > 0) {
clearTimeout(scroll_timer);
scroll_timer = setTimeout(function() {
// .. do something
console.log('left');
}, 200);
}
}
});
http://jsfiddle.net/andyface/5CfgT/
Now that Bootstrap 3 is out, what is the recommended option for enabling touch? As before, there aren't many touch events in the bootstrap.js, though it is supposed to be a mobile first framework.
The last thing I've found on github suggests using fastclick.js, but that was before the v3.0 release.
My recommendation is to use Bootstrap alongside JQuery mobile, TouchSwipe, or Hammer.js . An example of a bootstrap touch carousel can be found here.
Start working on another fully working Touch Carousel on GitHub. This also includes drag events...
Despite I believe bootstrap is a joke of a css framework (especially due to no multileveled navigation), I would probably agree with others to go with some different carousel if you have a choice.
From my experience JQuery mobile will work rather smoothly but my site was not built alongside jquery mobile and the css belonging to it really messed the things up.
<script>
$(document).ready(function() {
$('.carouselresp').carousel({'data-interval': 6000, 'data-pause': "hover"});
var clicking = false;
var currentMousePos = 0;
var newMousePos = 0;
$('.carouselresp img').on('mousedown', function(event) {
clicking = true;
currentMousePos = event.pageX;
});
$('.carouselresp img').on('touchstart', function(event) {
clicking = true;
var touchstart = event.originalEvent.touches[0];
currentMousePos = touchstart.pageX;
});
$(document).on('mouseup', function(event) {
clicking = false;
});
$('.carouselresp img').on('touchend', function(event) {
clicking = false;
});
$(document).on('mousemove', function(event) {
if (!clicking) {
return;
}else {
if (event.pageX < currentMousePos) {
if ((currentMousePos - event.pageX) > 50) {
$('.carouselresp').carousel('next');
clicking = false;
}
} else {
if ((event.pageX - currentMousePos) > 50) {
$('.carouselresp').carousel('prev');
clicking = false;
}
}
}
});
$('.carouselresp img').on('touchmove', function(event) {
var touch = event.originalEvent.touches[0];
if (!clicking) {
return;
}else {
if (touch.pageX < currentMousePos) {
if ((currentMousePos - touch.pageX) > 50) {
$('.carouselresp').carousel('next');
clicking = false;
}
} else {
if ((touch.pageX - currentMousePos) > 50) {
$('.carouselresp').carousel('prev');
clicking = false;
}
}
}
event.preventDefault();
});
});
</script>
It works fine for me on android and iphone too, plus I am allowing the move event in browsers with no touch support.
I hope it helped.
TomHre