How to force scroll in overflow-y div - javascript

I'm trying to force an offset scroll in a div that contain a ngfor list
I tried this on the div that as the overflow-y:
#ViewChild('list') listRef: ElementRef;
then on click I try this with some log to be sure it's called
this.listRef.nativeElement.offsetTop = 500;
Nothing happens, any idea how I can achieve this ?
EDIT :
Html :
<div
#gridContainerId
class="gridContainer">
<a *ngFor="let item of images;">
<img src="{{getImage(item)}}"/>
</a>
</div>
css :
.gridContainer {
height: 90vh;
overflow-y: scroll;
}
component :
#ViewChild('gridContainerId') ref: ElementRef;
this.store.pipe(
select(fromImages.getImages),
takeWhile(() => this.componentActive)
).subscribe(imagesItems => {
this.images = imagesItems;
updateScroll();
}
);
updateScroll(){
this.ref.nativeElement.scrollTop = this.ref.nativeElement.scrollHeight;
}

I've been recently in your same scenario, when click certain button, the div scrolled to bottom, i achieved it with this code:
this.messagesContainer.nativeElement.scrollTop = this.messagesContainer.nativeElement.scrollHeight;
the property scrollTop is to specify the number of pixels to be scrolled from the top of the view.
and the property scrollHeight is to get the total height of the div.

Related

How Do I Stop Parent Div From Expanding Because of Its Children?

So child div is has a list of items next to each other, each with a fix width.
In this image child div extends past MainContent but in the actual app, MainContent extends to fit the width of child div.
I would like to make it so that when child overflows, it just has a scroll wheel instead of becoming so large.
I have tried setting Child Div to 'overflow-x : auto'
Child div width is at 100%, as is MainContent.
JSX/HTML
<div className = 'app'>
<div className = 'navbar'></div>
<div className = 'maincontent'>
<div className = 'child'>
<div className = 'childlist'>
<button className = 'btn'></button>
<button className = 'btn'></button>
<button className = 'btn'></button>
</div>
</div>
</div>
</div>
CSS
.app : {
display : flex,
width: 100vw,
height :100vh
}
.navbar : {
display : flex,
flex-direction :column,
width : 112
}
.maincontent:{
display : flex,
width : 100%
}
.child: {
width :100%
}
.childlist:{
display : flex,
width :90%
}
.btn:{
width : 200,
height :200
}
All your containers widths are relative, so it will adjust, not overflow. If your child's width is % of the parent's, then it'll never overflow.
You need to have fixed width to make it overflow.
Plus your code looks really messy, you may want to try Prettier

Setting div height to another div's height

I've made a timeline using a sort of following this: https://www.w3schools.com/howto/howto_css_timeline.asp and set it to position: sticky. This is in a container called, div.timeContainer. Next to it, there's some text in a separate div. The idea is that the user scrolls down, reading the text on the right, while the timeline/overview on the left is in view.
The problem right now is that if I set the height of div.timeContainer, resizing the window means that the timeline will stop being in view/sticky around half-way through since the div on the right has become longer.
This (and variations) is what I have tried so far:
const historyContainer = document.querySelector("div.history").style.height
document.querySelector("div.timeContainer").style.height = historyContainer
I have prepared for you a simple example of assigning parent height to a child. An example in vanilla js.
let parent_div = document.querySelector('.parent');
let child_div = document.querySelector('.child');
let click_button = document.querySelector('input');
click_button.onclick = function(){
child_div.style.height = parent_div.offsetHeight + 'px';
};
.parent {
width: 100%;
height: 300px;
background-color: yellow;
}
.child {
width: 50%;
background-color: green;
}
<input type="button" value="click me to get the height of the child div">
<div class="parent">
<div class="child">
</div>
</div>

How do I prevent window.pageYOffset from resetting on render?

I have a react component where I want to change the header based on the scroll event. I'm attaching an event handler and based on scroll position and toggling a display class to hide ro show the desired elements.
Where I'm having trouble is, there seems to be some glitchy behavior when my component tries to re render. I have an example in codesandbox below.
import React from "react";
import "./styles.css";
export default function App() {
const [scrollY, setScrollY] = React.useState(0);
React.useEffect(() => {
const handleScroll = () => {
console.log(window.pageYOffset);
setScrollY(window.pageYOffset);
};
window.addEventListener("scroll", handleScroll, { passive: true });
return () => window.removeEventListener("scroll", handleScroll);
}, [setScrollY]);
const scrolled = () => scrollY > 40;
return (
<div className="App">
<div className={`header ${scrolled() ? "d-none" : ""}`}>Header Main</div>
<div>
<div className={`header-secondary ${scrolled() ? "d-none" : ""}`}>
Header Secondary
</div>
<div className={`header-scrolled ${!scrolled() ? "d-none" : ""}`}>
HeaderScrolled
</div>
<div>Scroll Position: {scrollY}</div>
{[...Array(100)].map((e, i) => (
<div>
<div className={scrolled()}>{`SCROLLING`}</div>
</div>
))}
</div>
</div>
);
}
My code sandbox: https://codesandbox.io/s/wizardly-saha-0oklr
If you notice I have my hide/unhide compnent condition set at 40px. When you scroll slowly around 40px the header will snap back and for some reason the window.pageYOffset will reset to 0. I can't figure out why this is?
If you scroll past fast enough it doesn't matter but right around where I toggle the display class there is some odd behavior.
EDIT: Updated Example
Effectively what I need to do is have a smmoth transition from Header Main to Header Secondary. I can't really change styling on Header Main because I don't own that part of the product.
The problem is about your header. When you are at the top header affects the height of the scrolling body because it is position relative. When you start to scroll down it becomes fixed and leaves the body so it doesn't affect. When you scroll back to top it affect scroll height again.
So there are some tricks to resolve this issue. Giving padding-top: 50px; to scrolling element and using header always fixed will save you.
.App {
padding-top: 50px;
}
.header {
width: 100%;
height: 50px;
background-color: teal;
position: fixed;
top: 0;
}
.header-scrolled {
width: 100%;
height: 50px;
background-color: green;
color: white;
position: fixed;
top: 0;
}
https://codesandbox.io/s/lingering-pine-puunf
I was having the exact same issue for two days. The fix I implemented was to render a "sticky-nav" component in addition to the original "nav" component. This way the original nav will still exist on top (but above the visible window so you'd never know) and when you scroll down the "sticky-nav" appears. Since the original nav is always there and doesn't change position, it won't affect the scroll position and cause the glitch when slowly scrolling back up.

Change heights of elements dynamically - Angular 5

I have 2 div elements that are connected, in the left one I have list of images, and in the right one I have details of each image. I open the right div on clicking on image, and it has absolute position, but then I get into a problem.
I need to calculate heights of those 2 divs, so I always have the same height - each time i click something, change something... (I can have only one image in the left div and it has a lot of information so the right div's height is bigger, or I can have 100 images on the left so left height is bigger). This is what I tried, but it doesn't work good enough:
leftHeight: number;
rightHeight: number;
ngDoCheck() {
if (window.innerWidth < 1336 && this.openDetails) {
this.chRef.detectChanges();
if (this.leftElement.nativeElement.clientHeight > this.rightElement.nativeElement.clientHeight) {
this.rightHeight = this.leftElement.nativeElement.clientHeight;
} else {
this.leftHeight = this.rightElement.nativeElement.clientHeight;
}
this.chRef.detectChanges();
}
}
HTML:
<div class="wrapper">
<div class="left-part" #leftElement [style.height.px]="leftHeight - 40">
<!-- some ngFor is here with images -->
</div>
<div [#focusPanel]='smallScreen' *ngIf="openDetails" #rightElement class="right-part" [style.height.px]="rightHeight - 65">
<!-- some details of each image -->
</div>
</div>
Any suggestion on what to try, what else to do?
EDIT: This semi-works, I set the height of elements at start, but it doesn't change the height after it, doesn't calculate again
I'm not sure this will help, but have you try to call to your function ngDoCheck in ngAfterViewChecked event?
It shoul'd be something similar to this:
export class YourComponent implements AfterViewChecked {
constructor(private cdRef:ChangeDetectorRef) {}
ngAfterViewChecked() {
this.ngDoCheck();
}
You can set scroll bars on right div. Simply add to css:
.scrollBarClass {
max-height: 500px;
overflow-y: scroll;
}
and then in your right div add:
<div class="scrollBarClass"> </div>
Edited answer:
If you have dinamicaly set height of both div's, then simply set
<div class="scrollBarClass"> </div>
on both divs, and you will have scroll if they become too large.

Javascript: prevent internal element "scrolling" in an element

I have a script that has a div with a width larger than its' parent, with the parent being set to overflow: hidden;. I have javascript that is setting the left positioning of the big div to create "pages". You can click a link to move between pages.
All of that works great, but the problem is if you tab from one "page" element to another, it completely messes up all the left positioning to move between the pages.
You can recreate this bug in the fiddle I set up by setting your focus to one of the input boxes on page ONE and tabbing until it takes you to page two.
I've set up a demo here.
The code that is important is as follows:
HTML:
<div class="form">
<div class="pagesContainer">
<div class="page" class="active">
<h2>Page One</h2>
[... Page 1 Content here...]
</div>
<div class="page">
<h2>Page Two</h2>
[... Page Content here...]
</div>
</div>
CSS:
.form {
width: 400px;
position: relative;
overflow: hidden;
border: 1px solid #000;
float: left;
}
.pagesContainer {
position: relative; /*Width set to 10,000 px in js
}
.form .page {
width: 400px;
float: left;
}
JS:
slidePage: function(page, direction, currentPage) {
if (direction == 'next') {
var animationDirection = '-=';
if (page.index() >= this.numPages) {
return false;
}
}
else if (direction == 'previous') {
var animationDirection = '+=';
if (page.index() < 0) {
return false;
}
}
//Get page height
var height = page.height();
this.heightElement.animate({
height: height
}, 600);
//Clear active page
this.page.removeClass('active');
this.page.eq(page.index()).addClass('active');
//Locate the exact page to skip to
var slideWidth = page.outerWidth(true) * this.difference(this.currentPage.index(), page.index());
this.container.animate({
left: animationDirection + slideWidth
}, 600);
this.currentPage = page;
}
The primary problem is that whatever happens when you tab from say, an input box on page one to something on page 2, it takes you there, but css still considers you to be at left: 0px;. I've been looking all over for a solution but so far all google has revealed to me is how to stop scrollbar scrolling.
Any help or suggestions would be appreciated, thanks!
P.S. The html was set up like this so that if javascript is disabled it will still show up all on one page and still function properly.
I updated your fiddle with a fix for the first tab with the form: http://jsfiddle.net/E7u9X/1/
. Basically, what you can do is to focus on the first "tabbable" element in a tab after the last one gets blurred, like so:
$('.form input').last().blur(function(){
$('.form input').first().focus();
});
(This is just an example, the first active element could be any other element)
Elements with overflow: hidden still have scrolling, just no scroll bars. This can be useful at times and annoying at others. This is why your position left is at zero, but your view of the element has changed. Set scrollLeft to zero when you change "pages", should do the trick.

Categories