How to detect user mouse wheel scroll distance? - javascript

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/

Related

Vertical sliders scroll

I have a problem with a code which I've copied from http://jsfiddle.net/NGj7F/ I placed this code in my HTML file between and I have put every section between
//Set each section's height equals to the window height
$('section').height($(window).height());
/*set the class 'active' to the first element
this will serve as our indicator*/
$('section').first().addClass('active');
/* handle the mousewheel event together with
DOMMouseScroll to work on cross browser */
$(document).on('mousewheel DOMMouseScroll', function (e) {
e.preventDefault();//prevent the default mousewheel scrolling
var active = $('section.active');
//get the delta to determine the mousewheel scrol UP and DOWN
var delta = e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1;
//if the delta value is negative, the user is scrolling down
if (delta < 0) {
//mousewheel down handler
next = active.next();
//check if the next section exist and animate the anchoring
if (next.length) {
/*setTimeout is here to prevent the scrolling animation
to jump to the topmost or bottom when
the user scrolled very fast.*/
var timer = setTimeout(function () {
/* animate the scrollTop by passing
the elements offset top value */
$('body, html').animate({
scrollTop: next.offset().top
}, 'slow');
// move the indicator 'active' class
next.addClass('active')
.siblings().removeClass('active');
clearTimeout(timer);
}, 800);
}
} else {
//mousewheel up handler
/*similar logic to the mousewheel down handler
except that we are animate the anchoring
to the previous sibling element*/
prev = active.prev();
if (prev.length) {
var timer = setTimeout(function () {
$('body, html').animate({
scrollTop: prev.offset().top
}, 'slow');
prev.addClass('active')
.siblings().removeClass('active');
clearTimeout(timer);
}, 800);
}
}
});
It works as I want on my website with the exception that every time I arrive at the last section and scroll down again, after that it doesn't work anymore. The same happens when I try to scroll from the first section up. Why does it stop working? Please help!!! And can someone help me to introduce also the up and down arrows to this function? Thanks!!!!!

Slider with touch function

I have created a simple slider. I want it also for smartphones and not only for desktops. So in this case it should be possible to let it slide when you move your finger from left to right or from right to left. For now it only works when you click on buttons.
I have no idea how to start with it. How can I do this?
var i = 0;
$('.next').bind('click', function() {
if (i < 4) {
$('li').animate({'left': '-=600px'}, 300).delay(600);
i++;
}
console.log($('li:first').position().left);
console.log(i);
});
$('.back').bind('click', function() {
if (i > 0) {
if ($('li:first').position().left < 0) {
$('li').animate({'left': '+=600px'}, 300).delay(600);
i--;
}
}
console.log(i);
});
https://jsfiddle.net/6t1wx95f/11/
PS: It should work without using a plugin.
I updated your fiddle: https://jsfiddle.net/6t1wx95f/13/
Tested in chrome (in responsive view to have the touch events working). Credit goes to this answer.
Basically, you just need to use touchstart and touchmove events. When you touchmove you just take your X position and compare it to where it was when touch-started.
See the touch events docs. It's all in vanilla javascript so you won't have to include any plugin.
// Set up events
var slider = document.getElementsByClassName('slider')[0];
slider.addEventListener('touchstart', handleTouchStart, false);
slider.addEventListener('touchmove', handleTouchMove, false);
..and
if ( xDiff > 0 ) {
/* left swipe */
slideRight();
} else {
/* right swipe */
slideLeft();
}

disable mousewheel plugin over div

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

Check if Cursor is hovering over the top X amount of pixel?

Is it possible to use Javascript/jQuery to check to see if your cursor is hovering over the top 20 pixels or so of the webpage?
Example:
Similar to how the exit bar works on windows 8. You have to hover at
the top of the screen for a second or so for the close minimize
options to appear.
I wondered if this is possible to replicate purely with Javascript/jQuery, to then allow a jQuery.fadeIn() or jQuery.slideDown() to take place.
Hopefully it's possible!
Sure, with a mouse event and checking if e.pageY is less than 20px, you're mouse is in the top 20 pixels etc.
var isOnTop = false;
$(window).on('mousemove', function(e) {
isOnTop = e.pageY < 20;
});
I'll add a few examples, keeping the mouse still at the top for a second will trigger the event
$(window).on('mousemove', function(e) {
clearTimeout($(this).data('timer'));
if ( e.pageY < 20 ) {
$(this).data('timer',
setTimeout(function() {
$('#top').slideDown()
}, 1000)
);
}
});
$('#top').on('mouseleave', function() {
$(this).slideUp();
});
FIDDLE
Any movement at the top requires a little more code, and another variable to keep from removing the timer
$(window).on('mousemove', function(e) {
if ( e.pageY < 20 ) {
if ( ! $(this).data('isSet') ) {
$(this).data('timer',
setTimeout(function() {
$('#top').slideDown()
$(this).data('isSet', false);
}, 1000)
).data('isSet', true);
}
} else {
clearTimeout($(this).data('timer'));
$(this).data('isSet', false);
}
});
$('#top').on('mouseleave', function() {
$(this).slideUp();
});
FIDDLE
You should add a mousemove listener to body. Also, you should create a boolean flag (variable or .data(). In that listener you check if the mouse is in the top x px of the page, and set the flag to that boolean value.
If the flag changed by that operation, either
setTimeout for showing something, if the flag changed to true.
clearTimeout said timeout and hide the thing of shown, if the flag changed to false.
I believe you'll be able to implement this based on my answer. I'll be happy to give more instructions, but I'm not going to give you copypastible JS code.
Pseudocode:
flag = false
when mouse moved over page {
if mouse y < value and flag = false {
flag = true
show after 1 second
}
if mouse y > value and flag = true {
flag = false
cancel showing
hide if shown
}
}

How to prevent duplicate events when scroll in jQuery?

I have 4 divs like;
<div class="diva">diva</div>
<div class="divb">divb</div>
<div class="divc">divc</div>
<div class="divd">divd</div>
They are 400px wide and high. I want to alert a when div b scrolls to top of page, and did using scroll function and scrollTop method. Each time when scroll, it check if scrollTop() if lager than 400, and alert a. But if I don't click the on the ok button of alert window, if I continue scrolling, multiple alerts will come, and I have to close them all.
But I just want one alert, and even if I continue scrolling, I want no more alerts. Also if the scrollTop is below 400px, I want to alert b (here also, I don't want repeats). If I got alert a, and if I scroll in opposite direction, and if scrollTop becomes below 400px, I want alert b, no problem for that.
Here is the fiddle.
please add this script on your file JS and try this script:
$(document).ready(function() {
$(window).scroll(function(){
var xx = $(document).scrollTop();
if(xx > jQuery(".divb").height()){
alert("a");
}else{
alert("b");
}
});
});
You are popping alerts on a 'scroll' event which happens every time you scroll..
if this is just a debugging annoyance, what you can do is use console.log('a') instead - example
If you wanted the actual function to run once for each time you reach it you can do this:
var a = false;
$(window).scroll(function(){
var xx = $(document).scrollTop();
if(xx > 400){
if (!a) {
alert("a");
a = true;
}
}else{
if (a) {
alert("b");
a = false;
}
}
});
fiddle for this example
The easiest way to avoid any confusion would be to keep state of scroll actions.
Demo: http://jsfiddle.net/abhitalks/uwUvC/1/
var last = 0, // last scroll-top to determine scroll direction
scrolledUp = false, // to cache state of scroll up
scrolledDown = false; // to cache state of scroll down
$(window).scroll(function (event) {
var current = $(this).scrollTop();
if (current > last) { // if scrolled down
if (current > 400 && !scrolledDown) { // check position and state
alert("A");
scrolledDown = true; // reset scroll down state
}
} else { // if scrolled up
if (current < 400 && scrolledDown && !scrolledUp) {
alert("B");
scrolledUp = true; // reset scroll up state
}
}
last = current; // keep current position to check direction
});
This way you are sure about when you are scrolling up and when you are scrolling down. Keep state of scroll in respective variables and check them.
The alerts fire only once in each direction.

Categories