Enable scroll within a function - javascript

When I use scrollWheel I'm incremeting the currentSlide by one, when currentSlide === 2 the red div is going up and I want to enable the scrolling to the body. As you see my bind function is returning false. I tried to put conditions on that and return true when currentSlide === 2 but apparently it won't work.
Can anybody explain to me how to fix that?
var currentSlide = 0;
function scrollDown() {
console.log('Scroll Down', currentSlide);
if(currentSlide < 3) {
currentSlide += 1;
}
if(currentSlide === 3) {
$('#el').addClass('hide');
}
}
http://jsbin.com/rovicawija/1/edit?js,console,output

Technically you are hiding the element when currentSlide is equal to 3 not 2.
Anyways instead of return false; in the bindings you will want to do return currentSlide >= 3; so that when the red div is hidden you can now scroll.
Also as someone else noted use on instead of bind because bind has been deprecated.

I'm totally not sure what you are trying to do as your question and expected result is quite unclear
I made the code as following
var currentSlide = 0;
function scrollDown() {
console.log('Scroll Down', currentSlide);
if(currentSlide < 10) {
currentSlide += 1;
return false;
}
if(currentSlide === 10) {
$('#el').addClass('hide');
}
}
$(window).on('DOMMouseScroll', function(e) {
if (e.originalEvent.detail > 0) {
return scrollDown();
}
})
.on('mousewheel', function(e) {
if (e.originalEvent.wheelDelta < 0) {
return scrollDown();
}
});
By using on(which you should) and having the scrollDown returning a boolean false if not good to go, and return nothing if there's nothing to do.

I just put return true on the last function and everything seemed to work fine, see here:
$(window).bind('DOMMouseScroll', function(e) {
if (e.originalEvent.detail > 0) {
scrollDown();
}
return false;
})
.bind('mousewheel', function(e) {
if (e.originalEvent.wheelDelta < 0) {
scrollDown();
}
return true;
});

Related

How to determine if mouse is not over an element?

I know that there are many similar questions, but I can't understand what is the mistake in my if statement.
So basically I want to stop clicking nextBtn once I hover over timeoutArea,
but this: timeoutArea.mouseover != true doesn't seems to work.
const timeoutArea = document.getElementById("slider");
var time = 1;
let interval = setInterval(function() {
if (time <= 20 && window.pageYOffset < 393) {
if (timeoutArea.mouseover != true) {
nextBtn.click();
};
time++;
}
else {
time = 1;
}
}, 2000);
if u are using jquery u can use $('#slider').is(':hover') in if statement.
if u use only pure javascript u can use with one function
example fiddle https://jsfiddle.net/9x5hjpk3/
function isHover(e) {
return (e.parentElement.querySelector(':hover') === e);
}
so change
if (timeoutArea.mouseover != true) {
nextBtn.click();
};
to
if (!isHover(timeoutArea)) {
nextBtn.click();
};

classList and scroll event

I have some simple script to adding classes to my navbar relied on pageYOffset:
var navContainer = document.querySelector('.nav-container');
var firstTitle = document.querySelector('.first-title')
document.addEventListener('scroll',function(){
if(window.pageYOffset < 75){
navContainer.classList.remove('nav-action','yellow');
}else if(window.pageYOffset > 75){
navContainer.classList.add('nav-action')
}else if(window.pageYOffset<firstTitle.offsetTop){
navContainer.classList.remove('yellow');
}
else if(window.pageYOffset > firstTitle.offsetTop){
navContainer.classList.add('yellow');
};
});
my trouble is this that last condition is fulfilled when window.pageYOffset is bigger than firstTitle.offsetTop, writing this line between brackets in the console returns true, but nothing happens when I'm trying this all code.
Unless window.pageYOffset === 75, none of these lines will actually be executed. The previous conditions already catch all the cases.
I would suggest treating nav-action and yellow separately:
var navContainer = document.querySelector('.nav-container');
var firstTitle = document.querySelector('.first-title')
document.addEventListener('scroll', function() {
if (window.pageYOffset < 75) {
navContainer.classList.remove('nav-action');
} else {
navContainer.classList.add('nav-action')
}
if (window.pageYOffset < firstTitle.offsetTop) {
navContainer.classList.remove('yellow');
} else {
navContainer.classList.add('yellow');
}
});

add reset function to click counter

This works, but the problem is it works only one time -- and then class ('active') is never added again -- it needs to be removed after 5 clicks as as done with the below, but after 5 it needs to reset and I would like the counter to go back to 0 so that after another 5 clicks it could work again!
var clickCount = 0;
$(".arrowRight").click(function () {
clickCount++;
if (clickCount >= 5)
// alert ("stop it!");
$(".arrowRight").removeClass("active");
else {
$(".arrowRight").addClass("active");
}
});
just set clickCount = 0 in the if statement
if (clickCount >= 5)
clickCount = 0;
$(".arrowRight").removeClass("active");
else {
$(".arrowRight").addClass("active");
}
Will something like this work?
var clickCount = 0;
$(".arrowRight").click(function () {
clickCount++;
if (clickCount >= 5) {
clickCount = 0;
$(".arrowRight").removeClass("active");
}
else {
$(".arrowRight").addClass("active");
}
});
This is another option:
if (clickCount%5==0) {
$(".arrowRight").removeClass("active");
} else {
$(".arrowRight").addClass("active");
}

Detecting scroll direction

So I am trying to use the JavaScript on scroll to call a function. But I wanted to know if I could detect the direction of the the scroll without using jQuery. If not then are there any workarounds?
I was thinking of just putting a 'to top' button but would like to avoid that if I could.
I have now just tried using this code but it didn't work:
if document.body.scrollTop <= 0 {
alert ("scrolling down")
} else {
alert ("scrolling up")
}
It can be detected by storing the previous scrollTop value and comparing the current scrollTop value with it.
JavaScript :
var lastScrollTop = 0;
// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
element.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
if (st > lastScrollTop) {
// downscroll code
} else if (st < lastScrollTop) {
// upscroll code
} // else was horizontal scroll
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);
Simple way to catch all scroll events (touch and wheel)
window.onscroll = function(e) {
// print "false" if direction is down and "true" if up
console.log(this.oldScroll > this.scrollY);
this.oldScroll = this.scrollY;
}
Use this to find the scroll direction. This is only to find the direction of the Vertical Scroll. Supports all cross browsers.
var scrollableElement = document.body; //document.getElementById('scrollableElement');
scrollableElement.addEventListener('wheel', checkScrollDirection);
function checkScrollDirection(event) {
if (checkScrollDirectionIsUp(event)) {
console.log('UP');
} else {
console.log('Down');
}
}
function checkScrollDirectionIsUp(event) {
if (event.wheelDelta) {
return event.wheelDelta > 0;
}
return event.deltaY < 0;
}
Example
You can try doing this.
function scrollDetect(){
var lastScroll = 0;
window.onscroll = function() {
let currentScroll = document.documentElement.scrollTop || document.body.scrollTop; // Get Current Scroll Value
if (currentScroll > 0 && lastScroll <= currentScroll){
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling DOWN";
}else{
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling UP";
}
};
}
scrollDetect();
html,body{
height:100%;
width:100%;
margin:0;
padding:0;
}
.cont{
height:100%;
width:100%;
}
.item{
margin:0;
padding:0;
height:100%;
width:100%;
background: #ffad33;
}
.red{
background: red;
}
p{
position:fixed;
font-size:25px;
top:5%;
left:5%;
}
<div class="cont">
<div class="item"></div>
<div class="item red"></div>
<p id="scrollLoc">0</p>
</div>
Initialize an oldValue
Get the newValue by listening to the event
Subtract the two
Conclude from the result
Update oldValue with the newValue
// Initialization
let oldValue = 0;
//Listening on the event
window.addEventListener('scroll', function(e){
// Get the new Value
newValue = window.pageYOffset;
//Subtract the two and conclude
if(oldValue - newValue < 0){
console.log("Up");
} else if(oldValue - newValue > 0){
console.log("Down");
}
// Update the old value
oldValue = newValue;
});
This is an addition to what prateek has answered.There seems to be a glitch in the code in IE so i decided to modify it a bit nothing fancy(just another condition)
$('document').ready(function() {
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
console.log("down")
}
else if(st == lastScrollTop)
{
//do nothing
//In IE this is an important condition because there seems to be some instances where the last scrollTop is equal to the new one
}
else {
console.log("up")
}
lastScrollTop = st;
});});
While the accepted answer works, it is worth noting that this will fire at a high rate. This can cause performance issues for computationally expensive operations.
The recommendation from MDN is to throttle the events. Below is a modification of their sample, enhanced to detect scroll direction.
Modified from: https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event
// ## function declaration
function scrollEventThrottle(fn) {
let last_known_scroll_position = 0;
let ticking = false;
window.addEventListener("scroll", function () {
let previous_known_scroll_position = last_known_scroll_position;
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function () {
fn(last_known_scroll_position, previous_known_scroll_position);
ticking = false;
});
ticking = true;
}
});
}
// ## function invocation
scrollEventThrottle((scrollPos, previousScrollPos) => {
if (previousScrollPos > scrollPos) {
console.log("going up");
} else {
console.log("going down");
}
});
This simple code would work: Check the console for results.
let scroll_position = 0;
let scroll_direction;
window.addEventListener('scroll', function(e){
scroll_direction = (document.body.getBoundingClientRect()).top > scroll_position ? 'up' : 'down';
scroll_position = (document.body.getBoundingClientRect()).top;
console.log(scroll_direction);
});
You can get the scrollbar position using document.documentElement.scrollTop. And then it is simply matter of comparing it to the previous position.
If anyone looking to achieve it with React hooks
const [scrollStatus, setScrollStatus] = useState({
scrollDirection: null,
scrollPos: 0,
});
useEffect(() => {
window.addEventListener("scroll", handleScrollDocument);
return () => window.removeEventListener("scroll", handleScrollDocument);
}, []);
function handleScrollDocument() {
setScrollStatus((prev) => { // to get 'previous' value of state
return {
scrollDirection:
document.body.getBoundingClientRect().top > prev.scrollPos
? "up"
: "down",
scrollPos: document.body.getBoundingClientRect().top,
};
});
}
console.log(scrollStatus.scrollDirection)
I personally use this code to detect scroll direction in javascript...
Just you have to define a variable to store lastscrollvalue and then use this if&else
let lastscrollvalue;
function headeronscroll() {
// document on which scroll event will occur
var a = document.querySelector('.refcontainer');
if (lastscrollvalue == undefined) {
lastscrollvalue = a.scrollTop;
// sets lastscrollvalue
} else if (a.scrollTop > lastscrollvalue) {
// downscroll rules will be here
lastscrollvalue = a.scrollTop;
} else if (a.scrollTop < lastscrollvalue) {
// upscroll rules will be here
lastscrollvalue = a.scrollTop;
}
}
Modifying Prateek's answer, if there is no change in lastScrollTop, then it would be a horizontal scroll (with overflow in the x direction, can be used by using horizontal scrollbars with a mouse or using scrollwheel + shift.
const containerElm = document.getElementById("container");
let lastScrollTop = containerElm.scrollTop;
containerElm.addEventListener("scroll", (evt) => {
const st = containerElm.scrollTop;
if (st > lastScrollTop) {
console.log("down scroll");
} else if (st < lastScrollTop) {
console.log("up scroll");
} else {
console.log("horizontal scroll");
}
lastScrollTop = Math.max(st, 0); // For mobile or negative scrolling
});
This seems to be working fine.
document.addEventListener('DOMContentLoaded', () => {
var scrollDirectionDown;
scrollDirectionDown = true;
window.addEventListener('scroll', () => {
if (this.oldScroll > this.scrollY) {
scrollDirectionDown = false;
} else {
scrollDirectionDown = true;
}
this.oldScroll = this.scrollY;
// test
if (scrollDirectionDown) {
console.log('scrolling down');
} else {
console.log('scrolling up');
}
});
});
Sometimes there are inconsistencies in scrolling behavior which does not properly update the scrollTop attribute of an element. It would be safer to put some threshold value before deciding the scroll direction.
let lastScroll = 0
let threshold = 10 // must scroll by 10 units to know the direction of scrolling
element.addEventListener("scroll", () => {
let newScroll = element.scrollTop
if (newScroll - lastScroll > threshold) {
// "up" code here
} else if (newScroll - lastScroll < -threshold) {
// "down" code here
}
lastScroll = newScroll
})
let arrayScroll = [];
window.addEventListener('scroll', ()=>{
arrayScroll.splice(1); //deleting unnecessary data so that array does not get too big
arrayScroll.unshift(Math.round(window.scrollY));
if(arrayScroll[0] > arrayScroll[1]){
console.log('scrolling down');
} else{
console.log('scrolling up');
}
})
I have self-made the above solution. I am not sure if this solution may cause any considerable performance issue comparing other solutions as I have just started learning JS and not yet have completed my begginer course. Any suggestion or advice from experienced coder is highly appriciated. ThankYou!

How can i clearInterval(myFunc) after myFunc has executed 5 times?

The purpose of the code below is to alert online shoppers that they must select a color (via a select/option menu) before putting an item into their basket. If they don't select a color (ie, make a selection) some blinking text displays alerting them.
I'm trying to have the text blink 3 times then stop. I tried using some counter vars but didn't work. How can I re-write this so the blink executes 3 times only?
function blink() {
if ($('.pleaseSelect').css('visibility') == 'hidden') {
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
}
}
function showNotice() {
timerId = setInterval(blink, 200);
}
$('#addToCart').click(function() {
if ($("select > option:first").is(":selected")) {
showNotice();
} else {
clearInterval(showNotice);
$('.pleaseSelect').css('visibility', 'hidden');
}
})
Well you can have counter declared and incremented each time blink is called. then check if you have called blink three times, clear the interval. Also your showNotice function is not defined properly.
var counter = 0,
timerId;
function blink() {
if ($('.pleaseSelect').css('visibility') == 'hidden') {
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
if (counter > 4) {
showNotice(false);
}
}
counter++;
}
function showNotice(show) {
if (show) {
timerId = setInterval(blink, 200);
} else {
clearInterval(timerId);
counter = 0;
}
}
$('#addToCart').click(function () {
if ($("select > option:first").is(":selected")) {
showNotice(true);
} else {
showNotice(false);
$('.pleaseSelect').css('visibility', 'hidden');
}
})
Here is working fiddle
function blink(){
var blinkCount = 0;
return function () {
if($('.pleaseSelect').css('visibility')== 'hidden'){
$('.pleaseSelect').css('visibility', 'visible');
} else {
$('.pleaseSelect').css('visibility', 'hidden')
}
blinkCount = blinkCount + 1;
if (blinkCount === 3) {
clearInterval(timerId);
}
}
}
the only thing is that timeId is global - bad practice... however you would have to refactor more of your code in order to correct that issue.
another option is to just fadIn and fadeOut rather than what you're doing.
It would look something like:
if(element.val() == ''){
element.fadeOut("fast");
element.fadeIn("fast");
element.fadeOut("fast");
element.fadeIn("fast");
element.fadeOut("fast");
element.fadeIn("fast");
}
How about this example? Use an anonymous function to call your blink method and keep decrementing a counter.
id = setInterval(function () {
counter--;
if (!counter) {
clearInterval(id);
}
blink();
}, 200);
See the JSFiddle for the complete context.
You can accomplish the desired behavior using variables within a private scope:
$('#addToCart').click(function(e) {
blink(e);
});
function blink(e) {
var blink_count = 0;
var timer = setInterval(function(e) {
blink_count++;
$('.pleaseSelect').toggle();
if (blink_count >= 6) {
clearInterval(timer);
blink_count = 0;
}
}, 200);
}

Categories