Reputation: 3517
I want to run a function when someone scrolls down on an element. Something like this:
$('div').scrollDown(function(){ alert('down') });
$('div').scrollUp(function(){ alert('up') });
But those functions don't exist. Is there a solution to this problem? Awwwards seem to be able to do it (logo in navbar changes depending on scroll direction). Unfortunately, the source code is compressed, so no luck there.
Upvotes: 64
Views: 167925
Reputation: 583
You can use this simple plugin to add scrollUp
and scrollDown
to your jQuery
https://github.com/phpust/JQueryScrollDetector
var lastScrollTop = 0;
var action = "stopped";
var timeout = 100;
// Scroll end detector:
$.fn.scrollEnd = function(callback, timeout) {
$(this).scroll(function(){
// get current scroll top
var st = $(this).scrollTop();
var $this = $(this);
// fix for page loads
if (lastScrollTop !=0 )
{
// if it's scroll up
if (st < lastScrollTop){
action = "scrollUp";
}
// else if it's scroll down
else if (st > lastScrollTop){
action = "scrollDown";
}
}
// set the current scroll as last scroll top
lastScrollTop = st;
// check if scrollTimeout is set then clear it
if ($this.data('scrollTimeout')) {
clearTimeout($this.data('scrollTimeout'));
}
// wait until timeout done to overwrite scrolls output
$this.data('scrollTimeout', setTimeout(callback,timeout));
});
};
$(window).scrollEnd(function(){
if(action!="stopped"){
//call the event listener attached to obj.
$(document).trigger(action);
}
}, timeout);
Upvotes: 0
Reputation: 5205
This one deserves an update - nowadays we have the wheel
event :
$(function() {
$(window).on('wheel', function(e) {
var delta = e.originalEvent.deltaY;
if (delta > 0) $('body').text('down');
else $('body').text('up');
return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
font-size: 22px;
text-align: center;
color: white;
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Support has been pretty good on modern browsers for quite a while already :
https://developer.mozilla.org/en-US/docs/Web/Events/wheel
If deeper browser support is required, probably best to use mousewheel.js instead of messing about :
https://plugins.jquery.com/mousewheel/
$(function() {
$(window).mousewheel(function(turn, delta) {
if (delta > 0) $('body').text('up');
else $('body').text('down');
return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
font-size: 22px;
text-align: center;
color: white;
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
Upvotes: 48
Reputation: 4520
There could be 3 solution from this posting and other stackoverflow article.
Solution 1
var lastScrollTop = 0;
$(window).on('scroll', function() {
st = $(this).scrollTop();
if(st < lastScrollTop) {
console.log('up 1');
}
else {
console.log('down 1');
}
lastScrollTop = st;
});
Solution 2
$('body').on('DOMMouseScroll', function(e){
if(e.originalEvent.detail < 0) {
console.log('up 2');
}
else {
console.log('down 2');
}
});
Solution 3
$('body').on('mousewheel', function(e){
if(e.originalEvent.wheelDelta > 0) {
console.log('up 3');
}
else {
console.log('down 3');
}
});
I couldn't tested it on Safari
chrome 42 (Win 7)
Firefox 37 (Win 7)
IE 11 (Win 8)
IE 10 (Win 7)
IE 9 (Win 7)
IE 8 (Win 7)
I checked that side effect from IE 11 and IE 8 is come from
if else
statement. So, I replaced it withif else if
statement as following.
From the multi browser test, I decided to use Solution 3 for common browsers and Solution 1 for firefox and IE 11.
I referred this answer to detect IE 11.
// Detect IE version
var iev=0;
var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
var trident = !!navigator.userAgent.match(/Trident\/7.0/);
var rv=navigator.userAgent.indexOf("rv:11.0");
if (ieold) iev=new Number(RegExp.$1);
if (navigator.appVersion.indexOf("MSIE 10") != -1) iev=10;
if (trident&&rv!=-1) iev=11;
// Firefox or IE 11
if(typeof InstallTrigger !== 'undefined' || iev == 11) {
var lastScrollTop = 0;
$(window).on('scroll', function() {
st = $(this).scrollTop();
if(st < lastScrollTop) {
console.log('Up');
}
else if(st > lastScrollTop) {
console.log('Down');
}
lastScrollTop = st;
});
}
// Other browsers
else {
$('body').on('mousewheel', function(e){
if(e.originalEvent.wheelDelta > 0) {
console.log('Up');
}
else if(e.originalEvent.wheelDelta < 0) {
console.log('Down');
}
});
}
Upvotes: 24
Reputation: 4347
Following example will listen to MOUSE scroll only, no touch nor trackpad scrolls.
It uses jQuery.on() (As of jQuery 1.7, the .on() method is the preferred method for attaching event handlers to a document).
$('#elem').on( 'DOMMouseScroll mousewheel', function ( event ) {
if( event.originalEvent.detail > 0 || event.originalEvent.wheelDelta < 0 ) { //alternative options for wheelData: wheelDeltaX & wheelDeltaY
//scroll down
console.log('Down');
} else {
//scroll up
console.log('Up');
}
//prevent page fom scrolling
return false;
});
Works on all browsers.
fiddle: http://jsfiddle.net/honk1/gWnNv/7/
Upvotes: 51
Reputation: 1801
var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
$(document).bind(mousewheelevt,
function(e)
{
var evt = window.event || e //equalize event object
evt = evt.originalEvent ? evt.originalEvent : evt; //convert to originalEvent if possible
var delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta //check for detail first, because it is used by Opera and FF
if(delta > 0)
{
scrollup();
}
else
{
scrolldown();
}
}
);
Upvotes: 0
Reputation: 3517
I managed to figure it out in the end, so if anyone is looking for the answer:
//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;
});
Upvotes: 108
Reputation: 14872
Here is a sample showing an easy way to do it. The script is:
$(function() {
var _t = $("#container").scrollTop();
$("#container").scroll(function() {
var _n = $("#container").scrollTop();
if (_n > _t) {
$("#target").text("Down");
} else {
$("#target").text("Up");
}
_t = _n;
});
});
The #container
is your div id
. The #target
is just to see it working. Change to what you want when up or when down.
EDIT
The OP didn't say before, but since he's using a div with overflow: hidden
, scrolling doesn't occur, then the script to detect the scroll is the least of it. Well, how to detect something that does not happen?!
So, the OP himself posted the link with what he wants, so why not use that library? http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js.
The call is just:
$(function() {
$(".scrollable").scrollable({ vertical: true, mousewheel: true });
});
Upvotes: 1
Reputation: 77966
$(function(){
var _top = $(window).scrollTop();
var _direction;
$(window).scroll(function(){
var _cur_top = $(window).scrollTop();
if(_top < _cur_top)
{
_direction = 'down';
}
else
{
_direction = 'up';
}
_top = _cur_top;
console.log(_direction);
});
});
Demo: http://jsfiddle.net/AlienWebguy/Bka6F/
Upvotes: 12