Using Parent Scrollbar instead of Sub Component Scrollbar with Angular Virtual Scroll - javascript

Context
I'm using angular virtual scroll to display a long list of elements. My design is very simple and can be seen in the image below.
Current Behaviour
Currently, the virtual scroll has its own scrollbar which operates differently from the parent scroll bar. This makes it very tedious to scroll to the footer. i.e. When you scroll to the end of the list it does not scroll to the footer.
Desired Behaviour
I want the virtual scroll container to use the parent scroll bar instead of its own such that when the end of the list is reached, regular scrolling is resumed.
A Stackblitz can be found here illustrating the undesired behaviour: https://stackblitz.com/angular/aemdyrjmebn

This is default scrolling behavior native to the browser (I tried it on Chrome). For example the same thing will happen with the overflow: scroll example on MDN: after the container has been fully scrolled down, the scrolling of the parent/window will not begin until the mouse is moved. This is also what happens with Angular Virtual Scrolling
If there is another way to achieve what you're looking for you would need to do it when the virtual container has been scrolled to the bottom - and you can get this event with the following code:
#ViewChild(CdkVirtualScrollViewport, {static: false}) virtualScroll: CdkVirtualScrollViewport;
ngAfterViewInit() {
this.virtualScroll.elementScrolled().pipe(
filter(event => {
return this.virtualScroll.measureScrollOffset('bottom') === 0;
}),
tap((event)=> {
// do something here
})
).subscribe()
}

Related

How to get window.scrollTop, ScrollY or any other distance value when using css scroll snap

I am using css scroll snap to scroll through that are 100vh in height. The scroll snap works beautifully.
That said I need to determine how far the site visitor has scrolled for a few different reasons.
I have tried:
let wrapper = document.getElementById('landing-page-wrapper');
console.log(wrapper.offsetTop);
console.log(window.scrollY);
I have also tried window.scrollTop, wrapper.scrollTop and more.
Here is a Codepen of what I am seeing
How can I know the distance scrolled while using 100vh sections and css scroll-snap
TIA
Based on your shared code, the reason why window.onscroll does not work as expected is because neither window nor document.body are overflowing vertically. Only the element that is overflowing will fire the scroll event, and in this case it is actually the element that matches the .box-wrapper selector.
Therefore if you listen to the scroll event on that element, then you should be able to retrieve its vertical scroll position using event.currentTarget.scrollTop:
document.querySelector(".box-wrapper").addEventListener("scroll", (e) => {
console.log(e.currentTarget.scrollTop);
});
See proof-of-concept example:

How can I target a specific element on scroll in React using JS?

So I want to target my About section on scroll, to add a class to the about section to make it fade in on scroll. As well as other sections as well I would like to target on scroll. Is there a way to target the specific element by ID or something on scroll?
showAbout = () => {
const top = window.pageYOffset;
if(top>400)
this.setState({
showAbout: true,
})
}
componentDidMount(){
window.addEventListener("scroll", this.showAbout)
}
This is the code I have currently, 400 is more of an arbitrary number, its different on each screen size. I was wondering if there is a way to do this same function, but by targeting the element ID on scroll?
Thank you for the help!
You can calculate the exact window offset for each of these elements on page load and trigger your animation when those offsets hit. You would also need to have a window.resize event that re-calculates those offsets for when a user resizes their window (or changes orientation on a phone).
OR, you can use a pre-built JS library to do this a lot easier for you. My recommendation is Scroll Magic:
https://scrollmagic.io/
You can indeed set up trigger points based on element IDs, and it works very smoothly.

How to handle only scroll on child DOM element instead of body element?

I am using the code below for scrolling to the element on a button click event.
Here is the code :
this.scrollTo = function(id) {
var old = $location.hash();
$location.hash(id);
$anchorScroll();
$location.hash(old);
};
With the above code, scroll is working fine. But actually my html page is having two scroll bars one is the default at page level and the other is at sub DOM element level. When the above code executes, its moving both the scroll bars and due to that its not visible correctly.
How can i restrict the default scroll bar and allow only the child/sub scroll bar to handle to scroll event ?
Please look into the below example in Chrome Browser:
plnkr.co/edit/pXwnjjh3VxCnhTHwd0tJ?p=preview
Actually I am facing the problem when I use navigation/top bar. There could be multiple ways to solve the problem by applying CSS styles.
I solved my problem by removing child scroll bar and using the below method:
window.scrollTo(0, element.offset().top - 120);
Instead of
$anchorScroll();

How can I keep iPhone Safari keyboard from scrolling a fixed navbar up?

I'm building an app with PhoneGap and I have a screen that has a fixed navigation bar, a scrollable area below, and a text field in that area (think facebook message screen). When you tap on the text field, keyboard pops up and although nav bar is fixed, it scrolls up and out of the screen. I want it to stay fixed and scrollable area should get narrower.
Is there a way to do this?
Here's a diagram (sorry for poor quality):
diagram
set frames here:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// change base view frame
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
// reset base view frame
}
Rather than using C, just use javascript and window.scrollTo for this (on input focus)
$('input').live('focus', function(e) {
e.preventDefault(); e.stopPropagation();
window.scrollTo(0,0); //no scroll > stays fixed!
});
If you don't want to set a static value for the Y scroll position, feel free to use this short plugin I've written that automatically aligns the keyboard underneath the input field (unless there's no need to scroll). Just call this on focus as shown above:
setKeyboardPos(e.target.id);

Trigger an event when user clicks on a divs horizontal scrollbar arrow

I have a div with a horizontal scroll.
Is there any way I can detect the click on the horizontal scrolls
arrow using jQuery ?
Note:
Actually I want the scroll to move a fixed no of pixels to the right when the user clicks the right scroll arrow and vice versa.
The event should not be triggered on scroll. It should be only triggered if user explicitly clicks the scrolls arrow.
There are multiple divs having scrollbars, having same class and no ids.
Would prefer to not use any plugins
Here is a demo for what you want
http://jsbin.com/opufow/4/edit
I hope this will help you?
you can use .scroll function of jquery.
Edit 2: Another suggestion is to do something like this depending on your implementation of scrolling areas (see working jsfiddle):
function CustomScrollArrow(elementToScroll) {
var $el = $(elementToScroll);
return $('<a>Click me to scroll</a>').css(/*...*/).click(function(){
$el.scrollLeft($el.scrollLeft()+10);
});
}
$('.ScrollAreaClass').each(function(){
// You could choose to append to your scrolling
// areas or their wrapper classes or whatever...
$('body').append(new CustomScrollArrow(this));
});​
Afterwards it's just a matter of styling your handmade arrows.
Edit 1: I've seen you updated your question, so here's an updated answer with an alternative solution.
You can try to circumvent the problem by using a customized scrollbars implementation, for example jScrollPane by Kelvin Luck or any other, whatever. If the solution offers click events on arrows - then you're set. Otherwise just do a bit of tinkering...
I maintain, however, my point of view that unless you are looking to perform an action before the browser executes the arrow click, I would recommend adding an event handler to the actual result of that click, i.e. the scroll.
Doing this will help to avoid inconsistencies across various implementations of scrolling in browsers; will keep working if scrolling is performed in another manner (i.e. swipe gesture); will still work if there's some javascript code that replaces the default browser implementation of scrollbars.
jQuery offers the .scroll handler to capture scrolling and .scrollLeft to determine the resulting position of the horizontally scrolled content.
Try a working jsfiddle or see the code below:
// Cache the initial scroll position:
var initialLeftScroll = $('#wrapper').scrollLeft();
// Bind event:
$('#wrapper').scroll(function (ev) {
// Get new horizontal scroll offset:
var currentLeftScroll = $('#wrapper').scrollLeft();
// Determine the difference
// (did the user scroll horizontally or just vertically?):
var leftScrollDifference = currentLeftScroll - initialLeftScroll;
// Now we can check
if (leftScrollDifference) {
/* Do something here */
}
// Reset the cache:
initialLeftScroll = currentLeftScroll;
});

Categories