prevent target element from scrolling to top under some condition - javascript

Basically I want to disable target from being scrolled to top if the if condition inside handleScroll function is true. So in other words If the condition is true. the user should not be able to scroll to top of the target element anymore and to be able to scroll to bottom of the element.
Also i don't want overflow hidden workarounds if possible.
target.addEventListener('scroll', e => this.handleScroll(e, sectionRect, offset, target));
handleScroll(event, sectionRect, offset, target) {
if ((sectionRect.top - offset) < target.scrollTop)
console.log('dont scroll', event);
},

I dont think its possible you can see more about scroll event here and also i recomend see this part:
"Since scroll events can fire at a high rate, the event handler
shouldn't execute computationally expensive operations such as DOM
modifications. Instead, it is recommended to throttle the event using
requestAnimationFrame, setTimeout or customEvent, as follows:"
and this part:
"In iOS UIWebViews, scroll events are not fired while scrolling is
taking place; they are only fired after the scrolling has completed.
See Bootstrap issue #16202. Safari and WKWebViews are not affected by
this bug."
Maybe creating a custom scroll can be the answer for you.

Related

How to override scroll functions in a window?

How do you override scroll functions of a browser in JavaScript?
Functions which I was able to find are scroll, scrollBy and scrollTo (from the window object).
But, if I try to override them using the standard procedure, like any other function, for example, by executing the following code window.scroll = function(parameter){} it does not have any effect on the browser.
So, if I try to scroll the page after executing the above code (for all 3 methods), the window still scrolls.
Are there any other functions which browser uses to scroll? If so, which function should I override to get a custom scrolling behaviour?
I am using Google Chrome (latest version), of course.
The window.scroll, window.scrollTo and window.scrollBy methods do not refer to the native scrolling functionality. They are used to scroll to specific locations on the webpage. If you want to implement a completly custom scrolling functionality/behaviour you need to listen to the wheel event, prevent the default and define your custom behaviour.
Note: changed scroll to wheel event as comment mentioned error
document.addEventListener("wheel", (event) => {
event.preventDefault();
event.stopPropagation();
// now define custom functionality
}, { passive: false });
Instead of window you can also apply it to any other element on the page that has a scrollbar and therefore being scrollable.
Futhermore the wheel event has values for deltaX and deltaY so you can see how much would have been scrolled since the last scroll and you can use the properties x and y to see how much had been scrolled since the beginning.
With Javascript, I'm not sure how to completely prevent the scroll, but you can scroll to a particular location right after they try to scroll, like this:
document.addEventListener('scroll', function(event)
{
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
window.scrollTo(0,0);
});
<h1>Try to Scroll</h1>
<ol>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
</ol>
Notice that despite my attempts to be thorough, you can still see a little scrolling happen before window.scrollTo(0,0); undoes it.
CSS
If all you're trying to do is prevent scrolling, you can use overflow: hidden with CSS:
html,body { overflow: hidden; }
<h1>Try to Scroll</h1>
<ol>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
<li></li><li></li><li></li><li></li><li></li><li></li>
</ol>

wheel Event Reliability

I'm working on a web project that has animations and page changes on the scroll ( specifically, scroll direction ) and I've been looking for multiple possible good and reliable solutions.
I've been detecting the scroll direction by detected the window's scrollY with the user's previously saved scrollY that I have saved in a variable. The only problem is that the scroll event doesn't fire when at the top or the bottom of page, even though the content is all absolute/fixed positioned.
I want to turn to the wheel event because of its deltaY values from the event, and it still fires when at the top of bottom of the page so I can remove the scrollbar and keep the body of the page 100vh.
The Mozilla dev docs say:
Don't confuse the wheel event with the scroll event. The default
action of a wheel event is implementation-specific, and doesn't
necessarily dispatch a scroll event. Even when it does, the delta*
values in the wheel event don't necessarily reflect the content's
scrolling direction. Therefore, do not rely on the wheel event's
delta* properties to get the scrolling direction. Instead, detect
value changes of scrollLeft and scrollTop of the target in the scroll
event.
(https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event)
And I'm also curious if the wheel event will work correctly on mobile with touch?
Here's a good example of what I'm trying to replicate: https://reed.be
There is no scrollbar, yet things still happen based on your scrolling.
CanIuse shows full compatibility of the wheel event with modern browsers, and some older versions.
see here -> https://caniuse.com/#feat=mdn-api_wheelevent
I've found a solution that references the wheel event (How to determine scroll direction without actually scrolling), though my question still applies -
How reliable is the wheel event across devices and browsers, including mobile?
I am limited to my own current version browsers and android devices for testing.
You can fool the browser by setting the additional height on the body to match the content width and setting the overflow to scroll. Then use some basic script, to set the scrollLeft property of your container to equal the window scrollY.
You will need to set the height of the body equal to the total width of the panels.
body {
height: 400vh; // 4 panels of 100vw each
...
}
.panel {
width: 100vw;
...
}
JS
const viewPort = document.querySelector('#viewport');
let lastScroll = 0;
window.addEventListener('scroll', (e) => {
let scrollY = window.scrollY;
// scroll the container by and equal amount of your window scroll
viewPort.scrollLeft = scrollY;
lastScroll = scrollY;
});
Rough JSFiddle Demo

Do something for every n pixel the window is scrolled

I want to do something for every 27px the window is scrolled. I've written the following code, placed inside a scroll event handler:
scrollSpy++
if (scrollSpy > 27) {
scrollSpy = 0;
console.log("27px scrolled");
}
But somehow it's not working.
When I scroll really slow, the events are triggered quite regularly (although I can't tell if it's really after 27px), but when I scroll fast, the event seems to be triggered random/not at all.
I guess the error lies in the assumption that the scroll event is triggered for every px scrolled, because that would be a requirement for the scrollSpy++ method to work.
But of course, I am not sure if that's really the error. How do I do this correctly?
Note: This question is no duplicate of this question, because there the accepted answer is geared towards reel.
Edit:
So based on the answers, I've written this if statement:
if (window.pageYOffset % 27 === 0) {
// do something
}
But its still not working. When I scroll fast the function fails. So it has something to do with how the scroll event is triggered. Do you know any solution for this? setTimeout or setInterval maybe?
You are correct in your assumption. You should check how much
document.documentElement.scrollTop + document.body.scrollTop
changes between calls of the function. If it increases, the user is scrolling down, and vice versa.
Use this knowledge to determine when to do whatever you're doing.
No, scroll events aren’t triggered for every pixel scrolled. Anyways, you can just use window.pageYOffset instead, with fallbacks as necessary as described in the MDN documentation for pageYOffset, and check in which direction and by how much that value changes on each scroll event.

Programmatically halt -webkit-overflow-scrolling

I have a phonegap application that uses iOS native scrolling through -webkit-overflow-scrolling in a div. I want to be able to manually halt an ongoing scroll when the user clicks a button (to scroll back to the top of the page). Is this doable?
This is actually very possible when using fastclick.js. The lib removes the 300ms click delay on mobile devices and enables event capturing during inertia/momentum scrolling.
After including fastclick and attaching it to the body element, my code to stop scrolling and go to the top looks like this:
scrollElement.style.overflow = 'hidden';
scrollElement.scrollTop = 0;
setTimeout(function() {
scrollElement.style.overflow = '';
}, 10);
The trick is to set overflow: hidden, which stops the inertia/momentum scrolling. Please see my fiddle for a full implementation of stop scrolling during inertia/momentum.
Unfortunately this is not possible at the moment. The scroll event is triggered only when the scrolling has come to an end. As long as the momentum keeps moving the content no events are fired at all. You can see this in Figure 6-1 The panning gesture in Apple's "Safari Web Content Guide".
I also created a fiddle to demonstrate this behavior. The scrollTop value is set after iOS is done animating.
You can capture a touch event using 'touchstart' instead of 'click', as the click event sometimes doesn't seem to get fired until the momentum scroll completes. Try this jQuery solution:
$('#yourTrigger').on('touchstart', function () {
var $div = $('.yourScrollableDiv');
if ($div.scrollTop() === 0) {
return false; //if no scroll needed, do nothing.
}
$div.addClass('scrolling'); //apply the overflow:hidden style with a class
$div.animate({
scrollTop: 0
}, 600, function () {
$div.removeClass('scrolling'); //scrolling has finished, remove overflow:hidden
});
}
where the 'scrolling' class simply has the CSS property, overflow:hidden, which as #Patrick-Rudolph said, will halt any momentum scrolling in progress.
.scrolling {
overflow: hidden;
}
Note: It's best to use a callback function to tell when your scroll animation finishes, rather than setting a timer function.

Trigger JQuery function when passed half way down the page

Is there a way to tell if you have scrolled passed the center of the web page or in other words, when you have scrolled passed exactly half of the web page and your scrollbar is situated in the lower half of the browser window?
I want to be able to trigger this:
$('.pineapple-man').show(); when I have scrolled down passed half of the page?
Is this possible at all?
Your help would be so kind!
You can get the pixel amount of an element has been scrolled by using .scrollTop(). To listen to scroll events use .scroll().
When you want to identify the halfway, use height of the scroll:
$(window).scroll(function () {
if ($(window).scrollTop() > $('body').height() / 2) {
$('.pineapple-man').show();
}
});
If you are scrolling some other element than the whole window/body, please feel free to change the selectors.
To make the showing one-timer, add the removal of scroll event listener, by adding the following after the .show() call:
$(window).unbind('scroll');
I guess you want to do something like this:
if($(document).scrollTop() > $(document).height()/2){
$('.pineapple-man').show();
}
where scrollTop() gets the current horizontal position and height() defines the document height.
See the scroll event and the scrollTop method.
you can use the focus event if you scroll down to it (just like jQuery uses for their comments)
jQuery('selector').focus(function() {
jQuery('.page').show();
});

Categories