How to count mouse wheel scroll in jquery - javascript

How to count mouse scroll in jquery/javascript?
Like initial value 0 and scroll down ++1 and scroll up --1.
And not be -1. Must be positive.
If i scroll 2 times down then value will be 2 and then scroll one time up then value be 1.

$(document).ready(function(){
var scrollPos = 0;
var Counter = 0;
$(window).scroll(function(){
var scrollPosCur = $(this).scrollTop();
if (scrollPosCur > scrollPos) {
Counter -= 1;
} else {
Counter += 1;
}
scrollPos = scrollPosCur;
});
});
The code compares the position of a scrollbar. scrollPos shows how many pixels you moved the scrollbar downwards and is initialized with a value of 0, as it starts at the top.
When you scroll the page, scrollPosCur will first save the current Position of the scrollbar. After that we compare how the value changed :
If the current value is bigger than the saved one, it indicates that the scrollbar has been moved downwards, so your Counter is incremented by 1.
Analogous to that, we decrement the Counter by 1 when scrollPosCur is smaller than scrollPos.
In order to keep the code working, we save the current value to compare against for future scroll Events.

Here is a possible solution for your question
var scrollCount = 0,
latestScrollTop = 0,
doc = document.documentElement,
top = 0;
// Bind window scroll event
$(window).bind('scroll', function (e) {
top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
if (latestScrollTop < top) {
// Scroll down, increment value
scrollCount += 1;
} else {
// Scroll up, decrement value
scrollCount -= 1;
}
// Store latest scroll position for next position calculation
latestScrollTop = top;
});

scrollcount=0;
$(document).ready(function(){
$("div").scroll(function(){
$("span").text(scrollcount+=1);
});
});

$(window).scroll(function () {
if ($(this).scrollTop() > 100) {
$('.scrollToTop').fadeIn();
} else {
$('.scrollToTop').fadeOut();
}
});
//Click event to scroll to top
$('.scrollToTop').click(function () {
$('html, body').animate({ scrollTop: 0 }, 800);
return false;
});

Related

OnMouseScroll increment a variable JS

I want to make a JS function.
It will work like this :
If I use my Mouse Wheel to Scroll Down so my variable will decrement. And if I use my Mouse Wheel to Scroll Up my variable will increment
I want to put that in a Condition with a max and min number.
I will send you a screenshot of my website and you will understand
So like you see, I need to make it work without scrollbar. I've only one page in 100vh.
I've make something very bad but you will understand the idea
https://jsfiddle.net/tuzycreo/
i= 1;
if (i>0 && i<5) {
//if(MouseScrollUp)
//i++;
document.querySelector('.number').innerHTML = i;
//else if(MouseScrollDown)
//i--;
// document.querySelector('.number').innerHTML = number;
}
Thanks you guys !
You can try like this,
var scrollCount = 0,
latestScrollTop = 0,
doc = document.documentElement,
top = 0;
// Bind window scroll event
$(window).bind('scroll', function (e) {
top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
if (latestScrollTop < top) {
// Scroll down, increment value
scrollCount += 1;
} else {
// Scroll up, decrement value
scrollCount -= 1;
}
// Store latest scroll position for next position calculation
latestScrollTop = top;
});
I make something that is working for me
https://jsfiddle.net/u93c9eth/2/
var scrollCount = 1;
window.addEventListener('mousewheel', function(e){
if(e.wheelDelta<0 && scrollCount<5){
scrollCount++;
}
else if(e.wheelDelta>0 && scrollCount>1){
scrollCount--;
}
document.querySelector('.number').innerHTML = scrollCount;
});

Is it possible to determine where a scroll will end up using javascript? If so, how?

I have a situation where, for example, if a user's scroll will result in a 1000 px change in scrollTop I'd like to know ahead of time.
The perfect example is iCalendar's control over a user's scroll. No matter how hard you scroll in the iCalendar application, the farthest you can scroll is to the next or previous month.
I currently have a very hackish solution to limit scroll behavior, which only takes into account where the user's scroll currently is.
MyConstructor.prototype._stopScroll = function(){
//Cache the previous scroll position and set a flag that will control
//whether or not we stop the scroll
var previous = this._container.scrollTop;
var flag = true;
//Add an event listener that stops the scroll if the flag is set to true
this._container.addEventListener('scroll', function stop(){
if(flag) {
this._container.scrollTop = previous;
}
}.bind(this), false);
//Return a function that has access to the stop function and can remove it
//as an event listener
return function(){
setTimeout(function(){
flag = false;
this._container.removeEventListener('scroll', stop, false);
}.bind(this), 0);
}.bind(this);
};
This approach works, and will stop a scroll in progress, but it is not smooth and I'd love to know if there's a better way to accomplish this.
The key to this question is can I know ahead of time where a scroll will end up. Thanks!!!
Edit: Just found the following project on github:
https://github.com/jquery/jquery-mousewheel
I tried the demo and it's able to report my touchpad and mouse scroll speed. Also it able to stop scrolling without any position fixed hacks :D
I'll have a look in the next few days and see if I can write anything that reports scroll speed, direction, velocity, device etc. Hopefully I'm able to make some jquery plugin that can override all scrolling interaction.
I'll update this post when I've got more info on this subject.
It's impossible to predict where a mouse scroll will end up.
A touchscreen/touchpad swipe on the other hand has a certain speed that will slow down after the user stopped swiping, like a car that got a push and starts slowing down afterwards.
Sadly every browser/os/driver/touchscreen/touchpad/etc has it's own implementation for that slowing down part so we can't predict that.
But we can of course write our own implementation.
We got 3 implementations that could be made:
A. Direction
B. Direction and speed
C. Direction, speed and velocity
iCalender probably uses implementation A.
Implementation A:
Outputs scroll direction to console, user is able to scroll +/- 1px
before the direction is detected.
Demo on JSFiddle
Demo with animation on JSFiddle
(function iDirection() {
var preventLoop = true;
var currentScroll = scrollTop();
function scroll() {
if(preventLoop) {
//Get new scroll position
var newScroll = scrollTop();
//Stop scrolling
preventLoop = false;
freeze(newScroll);
//Check direction
if(newScroll > currentScroll) {
console.log("scrolling down");
//scroll down animation here
} else {
console.log("scrolling up");
//scroll up animation here
}
/*
Time in milliseconds the scrolling is disabled,
in most cases this is equal to the time the animation takes
*/
setTimeout(function() {
//Update scroll position
currentScroll = newScroll;
//Enable scrolling
unfreeze();
/*
Wait 100ms before enabling the direction function again
(to prevent a loop from occuring).
*/
setTimeout(function() {
preventLoop = true;
}, 100);
}, 1000);
}
}
$(window).on("scroll", scroll);
})();
Implementation B:
Outputs scroll direction, distance and average speed to console, user is able to scroll the amount of pixels set in the distance variable.
If the user scrolls fast they might scroll a few more pixels though.
Demo on JSFiddle
(function iDirectionSpeed() {
var distance = 50; //pixels to scroll to determine speed
var preventLoop = true;
var currentScroll = scrollTop();
var currentDate = false;
function scroll() {
if(preventLoop) {
//Set date on scroll
if(!currentDate) {
currentDate = new Date();
}
//Get new scroll position
var newScroll = scrollTop();
var scrolledDistance = Math.abs(currentScroll - newScroll);
//User scrolled `distance` px or scrolled to the top/bottom
if(scrolledDistance >= distance || !newScroll || newScroll == scrollHeight()) {
//Stop scrolling
preventLoop = false;
freeze(newScroll);
//Get new date
var newDate = new Date();
//Calculate time
var time = newDate.getTime() - currentDate.getTime();
//Output speed
console.log("average speed: "+scrolledDistance+"px in "+time+"ms");
/*
To calculate the animation duration in ms:
x: time
y: scrolledDistance
z: distance you're going to animate
animation duration = z / y * x
*/
//Check direction
if(newScroll > currentScroll) {
console.log("scrolling down");
//scroll down animation here
} else {
console.log("scrolling up");
//scroll up animation here
}
/*
Time in milliseconds the scrolling is disabled,
in most cases this is equal to the time the animation takes
*/
setTimeout(function() {
//Update scroll position
currentScroll = newScroll;
//Unset date
currentDate = false;
//Enable scrolling
unfreeze();
/*
Wait 100ms before enabling the direction function again
(to prevent a loop from occuring).
*/
setTimeout(function() {
preventLoop = true;
}, 100);
}, 1000);
}
}
}
$(window).on("scroll", scroll);
})();
Implementation C:
Outputs scroll direction, distance and speeds to console, user is able to scroll the amount of pixels set in the distance variable.
If the user scrolls fast they might scroll a few more pixels though.
Demo on JSFiddle
(function iDirectionSpeedVelocity() {
var distance = 100; //pixels to scroll to determine speed
var preventLoop = true;
var currentScroll = [];
var currentDate = [];
function scroll() {
if(preventLoop) {
//Set date on scroll
currentDate.push(new Date());
//Set scrollTop on scroll
currentScroll.push(scrollTop());
var lastDate = currentDate[currentDate.length - 1];
var lastScroll = currentScroll[currentScroll.length - 1];
//User scrolled `distance` px or scrolled to the top/bottom
if(Math.abs(currentScroll[0] - lastScroll) >= distance || !lastScroll || lastScroll == scrollHeight()) {
//Stop scrolling
preventLoop = false;
freeze(currentScroll[currentScroll.length - 1]);
//Total time
console.log("Time: "+(lastDate.getTime() - currentDate[0].getTime())+"ms");
//Total distance
console.log("Distance: "+Math.abs(lastScroll - currentScroll[0])+"px");
/*
Calculate speeds between every registered scroll
(speed is described in milliseconds per pixel)
*/
var speeds = [];
for(var x = 0; x < currentScroll.length - 1; x++) {
var time = currentDate[x + 1].getTime() - currentDate[x].getTime();
var offset = Math.abs(currentScroll[x - 1] - currentScroll[x]);
if(offset) {
var speed = time / offset;
speeds.push(speed);
}
}
//Output array of registered speeds (milliseconds per pixel)
console.log("speeds (milliseconds per pixel):");
console.log(speeds);
/*
We can use the array of speeds to check if the speed is increasing
or decreasing between the first and last half as example
*/
var half = Math.round(speeds.length / 2);
var equal = half == speeds.length ? 0 : 1;
var firstHalfSpeed = 0;
for(var x = 0; x < half; x++ ) {
firstHalfSpeed += speeds[x];
}
firstHalfSpeed /= half;
var secondHalfSpeed = 0;
for(var x = half - equal; x < speeds.length; x++ ) {
secondHalfSpeed += speeds[x];
}
secondHalfSpeed /= half;
console.log("average first half speed: "+firstHalfSpeed+"ms per px");
console.log("average second half speed: "+secondHalfSpeed+"ms per px");
if(firstHalfSpeed < secondHalfSpeed) {
console.log("conclusion: speed is decreasing");
} else {
console.log("conclusion: speed is increasing");
}
//Check direction
if(lastScroll > currentScroll[0]) {
console.log("scrolling down");
//scroll down animation here
} else {
console.log("scrolling up");
//scroll up animation here
}
/*
Time in milliseconds the scrolling is disabled,
in most cases this is equal to the time the animation takes
*/
setTimeout(function() {
//Unset scroll positions
currentScroll = [];
//Unset dates
currentDate = [];
//Enable scrolling
unfreeze();
/*
Wait 100ms before enabling the direction function again
(to prevent a loop from occuring).
*/
setTimeout(function() {
preventLoop = true;
}, 100);
}, 2000);
}
}
}
$(window).on("scroll", scroll);
})();
Helper functions used in above implementations:
//Source: https://github.com/seahorsepip/jPopup
function freeze(top) {
if(window.innerWidth > document.documentElement.clientWidth) {
$("html").css("overflow-y", "scroll");
}
$("html").css({"width": "100%", "height": "100%", "position": "fixed", "top": -top});
}
function unfreeze() {
$("html").css("position", "static");
$("html, body").scrollTop(-parseInt($("html").css("top")));
$("html").css({"position": "", "width": "", "height": "", "top": "", "overflow-y": ""});
}
function scrollTop() {
return $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop();
}
function scrollHeight() {
return $("html")[0].scrollHeight ? $("html")[0].scrollHeight : $("body")[0].scrollHeight;
}
Just had a look at scrollify mentioned in the comments, it's 10kb and needs to hook at every simple event: touch, mouse scroll, keyboard buttons etc.
That doesn't seem very future proof, who know what possible user interaction can cause a scroll in the future?
The onscroll event on the other hand will always be triggered when the page scrolls, so let's just hook the animation code on that without worrying about any input device interaction.
As #seahorsepip states, it is not generally possible to know where a scroll will end up without adding custom behavior with JavaScript. The MDN docs do not list any way to access queued scroll events: https://developer.mozilla.org/en-US/docs/Web/Events/scroll
I found this information helpful:
Normalizing mousewheel speed across browsers
It highlights the difficulty of knowing where the page will go based on user input. My suggestion is to trigger a scroll to Y event when the code predicts the threshold is reached. In your example, if the scroll has moved the page 800 of 1000 pixels in a time window of 250ms, then set the scroll to that 1000 pixel mark and cut off the scroll for 500ms.
https://developer.mozilla.org/en-US/docs/Web/API/window/scrollTo
i'm not pretty sure if i've got what you're looking for. I've had project once, where i had to control the scrolling. Back then i've overwritten the default scroll event, after that you can set a custom distance for "one" scroll. Additionally added jQuery animations to scroll to a specific position.
Here you can take a look: http://c-k.co/zw1/
If that's what you're looking for you can contact me, and i'll see how much i still understand of my own thingy there
is easy to use event listener to do it. Here is a React example:
/**
* scroll promise
*/
const scrollPromiseCallback = useCallback((func:Function) => {
return new Promise((resolve, reject) => {
func(resolve, reject)
})
}, [])
/**
* scroll callback
*/
const scrollCallback = useCallback((scrollContainer, onScrollEnd, resolve) => {
/** 防抖时间 */
const debounceTime = 200
/** 防抖计时器 */
let timer = null
const listener = () => {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
scrollContainer.removeEventListener('scroll', listener)
resolve(true)
onScrollEnd?.()
}, debounceTime)
}
scrollContainer.addEventListener('scroll', listener)
}, [])
const scrollTo = useCallback((props:IUseScrollToProps) => {
return scrollPromiseCallback((resolve, reject) => {
const {
scrollContainer = window, top = 0, left = 0, behavior = 'auto',
} = props
scrollCallback(scrollContainer, props?.onScrollEnd, resolve)
scrollContainer.scrollTo({
top,
left,
behavior,
})
})
}, [scrollCallback, scrollPromiseCallback])

If scrollTop is greater than value, then do this ONLY ONCE

When user scrolls past 10px from the top, I'd like to hijack their scroll and scroll them down to certain div. After this happens once, I'd like to release the scroll to be free to scroll wherever. How do I do this?
My current code works but it won't let user to scroll freely after that initial scroll:
$(window).scroll(function() {
//if I scroll more than 1000px...
if($(window).scrollTop() > 10){
$('html,body').animate({scrollTop : $('#main').offset().top}, 900, function(){
h = 2;
});
}
});
Try:
var scrolled = false;
$(window).scroll(function() {
//if I scroll more than 1000px...
if($(window).scrollTop() > 10 && scrolled == false){
$('html,body').animate({scrollTop : $('#main').offset().top}, 900, function(){
h = 2;
});
scrolled = true;
} else if($(window).scrollTop() == 0) {
scrolled = false;
}
});

Getting a floating div to stop upon reaching another div

I have a floating div on the sidebar that scrolls with the page. Is there a way to add code that makes it stop when it reaches the footer?
See code in action: http://openbayou.staging.wpengine.com
jQuery code used to float div:
$j=jQuery.noConflict();
$j(document).ready(function($) {
//this is the floating content
var $floatingbox = $('#one');
if($('#primary').length > 0){
var bodyY = parseInt($('#primary').offset().top) - 20;
var originalX = $floatingbox.css('margin-left');
$(window).scroll(function () {
var scrollY = $(window).scrollTop();
var isfixed = $floatingbox.css('position') == 'fixed';
if($floatingbox.length > 0){
$floatingbox.html();
if ( scrollY > 1561 && !isfixed ) {
$floatingbox.stop().css({
position: 'fixed',
top: 10,
});
} else if ( scrollY < 1561 && isfixed ) {
$floatingbox.css({
position: 'relative',
top: 0,
});
}
}
});
}
});
Why not just set the z-index of the sidebar behind the z-index of the footer?
EDIT: I didn't like the result of this so I went and made this work in jquery the way you want it...
try this for your scroll function:
$(window).scroll(function () {
floatingbox = $("#one");
if(floatingbox.length > 0){
//get our current scroll position
var scrollY = $(window).scrollTop();
//get the position of the tag cloud relative to the document
var contentY = ($("#sidebar .sidebar-tag-cloud").offset().top + $("#sidebar .sidebar-tag-cloud").outerHeight(false));
//calculate the largest possible top margin size before it starts to overlap the footer
var lastY = $("#footer").offset().top - $("#one").outerHeight(false);
//check if our scroll location is past the bottom of the tag cloud
if ( scrollY > contentY )
{
//check if the current top position is less than the maximum position
if(floatingbox.offset().top<lastY)
{
//keep scrolling
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
//check if we have scrolled back up and have a space at the top
if(scrollY<floatingbox.offset().top)
{
floatingbox.stop().animate({"marginTop":scrollY-contentY});
}else
{
// hard set to the maximum position
floatingbox.stop().css({"marginTop":lastY-contentY});
}
}
}
}
});
I also made it a little more dynamic by getting the location of the bottom of the tag cloud and using that instead of your hard-coded number.
Alright, after looking at your latest jsfiddle. I have modified that code to work with yours. http://jsfiddle.net/Tgm6Y/4430/ This will not have the animate lag and should work well for you.
$('#one').followTo('#two','#pointFive');
just replace #two with #footer and #pointFive with "#sidebar .sidebar-tag-cloud" and this should work in your code.
UPDATE: Found a solution to my problem.
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('#one').offset().top;
$(window).scroll(function (event) {
var y = $(this).scrollTop() + 20;
if (y >= top) {
$('#one').addClass('fixed');
}
else {
$('#one').removeClass('fixed');
}
// don't overlap the footer - pull sidebar up using a negative margin
footertotop = ($('#footer').position().top);
scrolltop = $(document).scrollTop() + 760;
difference = scrolltop - footertotop;
if (scrolltop > footertotop) {
$('#one').css('margin-top', 0 - difference);
}
else {
$('#one').css('margin-top', 0);
}
});
}
});
What this does is it stops before the footer and I can configure the stopping point.
I appreciate all the help in solving my problem!

How to determine if vertical scroll bar has reached the bottom of the web page?

The same question is answered in jQUery but I'm looking for solution without jQuery.
How do you know the scroll bar has reached bottom of a page
I would like to know how I can determine whether vertical scrollbar has reached the bottom of the web page.
I am using Firefox3.6
I wrote simple Javascript loop to scroll down by 200 pixel and when the scroll bar reached the bottom of the page, I want to stop the loop.
The problem is scrollHeight() is returning 1989.
And inside loop scrollTop is incremented by 200 per iteration.
200 ==> 400 ==> 600 .... 1715
And from 1715, it won't increment so this loop continues forever.
Looks like scrollHeight() and scrollTop() is not right way to compare in order to determine the actual position of scrollbar? How can I know when the loop should stop?
code:
var curWindow = selenium.browserbot.getCurrentWindow();
var scrollTop = curWindow.document.body.scrollTop;
alert('scrollHeight==>' + curWindow.document.body.scrollHeight);
while(curWindow.document.body.scrollHeight > curWindow.document.body.scrollTop) {
scrollTop = curWindow.document.body.scrollTop;
if(scrollTop == 0) {
if(window.pageYOffset) { //firefox
alert('firefox');
scrollTop = window.pageYOffset;
}
else { //IE
alert('IE');
scrollTop = (curWindow.document.body.parentElement) ? curWindow.document.body.parentElement.scrollTop : 0;
}
} //end outer if
alert('current scrollTop ==> ' + scrollTop);
alert('take a shot here');
selenium.browserbot.getCurrentWindow().scrollBy(0,200);
} //end while
When you tell an element to scroll, if its scrollTop (or whatever appropriate property) doesn't change, then can't you assume that it has scrolled as far as is capable?
So you can keep track of the old scrollTop, tell it to scroll some, and then check to see if it really did it:
function scroller() {
var old = someElem.scrollTop;
someElem.scrollTop += 200;
if (someElem.scrollTop > old) {
// we still have some scrolling to do...
} else {
// we have reached rock bottom
}
}
I just read through the jQuery source code, and it looks like you'll need the "pageYOffset". Then you can get the window height and document height.
Something like this:
var yLeftToGo = document.height - (window.pageYOffset + window.innerHeight);
If yLeftToGo is 0, then you're at the bottom. At least that's the general idea.
The correct way to check if you reached the bottom of the page is this:
Get document.body.clientHeight = the height of the ACTUAL screen shown
Get document.body.offsetHeight or document.body.scrollHeight = the height of the entire page shown
Check if document.body.scrollTop = document.body.scrollHeight - document.body.clientHeight
If 3 is true, you reached the bottom of the page
function scrollHandler(theElement){
if((theElement.scrollHeight - theElement.scrollTop) + "px" == theElement.style.height)
alert("Bottom");
}
For the HTML element (like div) add the event -- onscroll='scrollHandler(this)'.
Here is some code I've used to power infinite scrolling list views:
var isBelowBuffer = false; // Flag to prevent actions from firing multiple times
$(window).scroll(function() {
// Anytime user scrolls to the bottom
if (isScrolledToBottom(30) === true) {
if (isBelowBuffer === false) {
// ... do something
}
isBelowBuffer = true;
} else {
isBelowBuffer = false;
}
});
function isScrolledToBottom(buffer) {
var pageHeight = document.body.scrollHeight;
// NOTE: IE and the other browsers handle scrollTop and pageYOffset differently
var pagePosition = document.body.offsetHeight + Math.max(parseInt(document.body.scrollTop), parseInt(window.pageYOffset - 1));
buffer = buffer || 0;
console.log(pagePosition + "px / " + (pageHeight) + "px");
return pagePosition >= (pageHeight - buffer);
}
<span id="add"></add>
<script>
window.onscroll = scroll;
function scroll () {
if (window.pageYOffset + window.innerHeight >= document.body.scrollHeight - 100) {
document.getElementById("add").innerHTML += 'test<br />test<br />test<br />test<br />test<br />';
}
}
</script>

Categories

Resources