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>
Related
I have a page with a div in the middle of content, whose height can change from javascript.
How can I control which way the page will scroll when the div height's changes? I want content to be always pushed down, never up.
Currently, the content is pushed down or up, depending on where the page scroll is when the button is clicked.
Here is a minimal example:
function toggle(ev) {
const div = document.querySelector("div");
if (div.style.height === "336px") {
div.style.height = "147px";
} else {
div.style.height = "336px";
}
}
body {max-width: 60em; margin: auto;}
<p style="background-color: coral; height: 400px;"></p>
<div style="background-color:grey; height: 147px;"></div>
<button href="#" onclick="toggle()">toggle div size</button>
<p style="background-color: olive; height: 3000px;"></p>
To make things clearer, I'm looking for a solution where the top paragraph never moves when the div expands, no matter where on the window the button currently is. i.e. the bottom paragraph should be move up/down as well as the button.
Try blurring the element (e.target.blur() on click handler) to make it inactive before updating the height of the content. Since the window no longer sees the button as active, it will no longer scroll the page to keep it in view.
const handleClick = e => {
e.target.blur()
updateScrollHeight()
}
function toggle(ev) {
const div = document.querySelector("div");
ev.target.blur();
if (div.style.height === "336px") {
div.style.height = "147px";
} else {
div.style.height = "336px";
}
}
document.querySelector("button").addEventListener("click", toggle);
body {max-width: 60em; margin: auto;}
<p style="background-color: coral; height: 400px;"></p>
<div style="background-color:grey; height: 147px;"></div>
<button href="#">toggle div size</button>
<p style="background-color: olive; height: 3000px;"></p>
If I understand correctly you want to scroll at the bottom every time you set the height
function toggle(ev) {
const div = document.querySelector("div");
if (div.style.height === "336px") {
div.style.height = "147px";
} else {
div.style.height = "336px";
}
div.scrollTop = div.scrollHeight
}
You can scroll to the selected element using window.scrollTo function.
<!doctype html>
<style>
body {max-width: 60em; margin: auto;}
</style>
<script>
function toggle(ev) {
const div = document.querySelector("div");
if (div.style.height === "336px") {
div.style.height = "147px";
} else {
div.style.height = "336px";
}
window.scrollTo(0, div.scrollHeight);
}
</script>
<p style="background-color: coral; height: 400px;"></p>
<div style="background-color:grey; height: 147px;"></div>
<button href="#" onclick="toggle()">toggle div size</button>
<p style="background-color: olive; height: 3000px;"></p>
The page is keeping the currently active element in view - i.e. the button that you clicked on - so the extra height will appear to move up or down depending on where the button is in relation to the screen.
What you want to do is to make the page look like it didn't scroll up after the element expanded. To do this we can just scroll the page back to the position it was before the element expanded - this makes it look as if the height expanded downwards.
1. Save the current position of the top of the page
var pagePosBeforeExpand = window.pageYOffset;
2. Scroll the page back to the position it was before we changed the height, if the div has been expanded:
// if we are increasing the height, then scroll to the previous top...
window.scrollTo({ top: pagePosBeforeExpand });
Note that this doesn't affect when you collapse the height again as you didn't ask for that in your question, however you could adapt this to suit in that scenario - e.g. you could simply move the scroll code to execute outside of the if.
Working Example:
function toggle(ev) {
// 1. Save the current position of the top of the page
var pagePosBeforeExpand = window.pageYOffset;
const div = document.querySelector("div");
if (div.style.height === "336px") {
div.style.height = "147px";
} else {
div.style.height = "336px";
// 2. scroll the page back to the position it was beforewe changed the height
window.scrollTo({ top: pagePosBeforeExpand })
}
}
body {max-width: 60em; margin: auto;}
<p style="background-color: coral; height: 400px;"></p>
<div style="background-color:grey; height: 147px;">Top of content</div>
<button href="#" onclick="toggle()">toggle div size</button>
<p style="background-color: olive; height: 3000px;"></p>
I have a series of elements that collapse ondragstart, and then uncollapse ondragend using Bootstrap's Collapse/Show classes
What I'm running into is that if the user is scrolled far enough down the page that removing that element's height makes the bottom of the page higher than the bottom of the viewport, the viewport is forced to scroll up to make up for it, which cancels the drag and calls ondragend, which then un-collapses the element and resizes the document to where it was, making it look like nothing happened.
My question is: How would I force the document/body to always be tall enough to prevent the auto-scroll?
Or, is it possible to somehow maintain the drag even through the scroll?
I have the min-height of the body set to 100vh, but that doesn't account for a page starting out to be taller than the viewport anyway.
Fiddle: https://jsfiddle.net/robertgreenstreet/jcodbv5n/21/
I see that your sections are wrapped by a form element.
<form>
<section</section>
<section</section>
<section</section>
<section</section>
</form>
What if, before you collapse any cards, you detect the form's actual height and force it to maintain that height using element.style.height?
Something like this:
function setHeight(element) {
element.style.height = element.offsetHeight + "px";
}
function clearHeight(element) {
element.style.height = "";
}
I haven't tried it, but I suspect it will do what you need.
Here's a little demo, it seems to work just fine.
function setHeight(element) {
element.style.height = element.offsetHeight + "px";
}
function clearHeight(element) {
element.style.height = "";
}
const wrapper = document.getElementById('wrapper');
const el2 = document.getElementById('el2');
const el3 = document.getElementById('el3');
function collapse () {
setHeight(wrapper);
el2.classList.add('collapse');
el3.classList.add('collapse');
setTimeout( () => clearHeight(wrapper), 2000);
}
function expand () {
clearHeight(wrapper)
el2.classList.remove('collapse');
el3.classList.remove('collapse');
}
#wrapper {
background-color: #ccc;
padding: 0.5rem;
}
#el1, #el2, #el3, #el4 {
border: 1px solid gray;
margin: 2px;
padding: 0.5rem;
background: white;
}
.el {
height: 40px;
}
.collapse {
height: 12px;
}
<body>
<button onclick="collapse();">Collapse el 2 and 3</button>
<button onclick="expand();">Expand el 2 and 3</button>
<div id="wrapper">
<div id="el1" class="el">el1</div>
<div id="el2" class="el">el2</div>
<div id="el3" class="el">el3</div>
<div id="el4" class="el">el4</div>
wrapper
</div>
</body>
I am building a website that expands horizontally as user takes action like http://portal.azure.com style. When they click a button(from a list) in one div, the details of the selected items appear in another div beside it. this can get really long and over flow the mother div.
I am looking for a way i can automatically scroll the page to the right most edge when a new div overflows.
layout
<div style="overflow-x: auto">
<div layout="row">
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
</div>
</div>
As you can see above, the first div shows by default but the other divs appear based on user interaction.
By the time the 3 div appears, it overflows.
How can i scroll to the right edge anytime it over flows? (you should really check out http://portal.azure.com to see what im talking about)
PS: i am using AngularJS. I am not using jquery. But i dont mind including it if its the only option
You can use plain Javascript for keeping the scroll to right.
Something like this:
var myDiv = document.getElementById("row");
myDiv.scrollLeft = myDiv.scrollWidth;
You need to fire the above function every time you add a new div. That way it will always automatically be scrolled when divs are dynamically added.
You will need to hook up the DOMNodeInserted event on your container. The function will be called whenever a div is added to your row container. This way you will not have to change anything in your existing code.
Here is a very simple example with dynamically added divs:
var num = 1,
btn = document.getElementById('btn'),
row = document.getElementById("row");
scroller(); // fire teh scroller right away for initial scroll
// function to keep it scrolled towards right
// function scroller() { row.scrollLeft = row.scrollWidth; }
// edited to add simple animation
function scroller() {
var maxScroll = row.scrollWidth - row.clientWidth; // required to stop
row.scrollLeft += 2;
if (row.scrollLeft < maxScroll) {
timer = window.setTimeout(scroller, 1000 / 60);
}
}
// hook up event to call scroller whenever an element is dynamically added
row.addEventListener("DOMNodeInserted", scroller);
// for demo to simluate dynamically adding divs
btn.addEventListener("click", function() {
var newDiv = document.createElement("div");
newDiv.setAttribute("class", "col");
num += 1; newDiv.innerText = num;
row.appendChild(newDiv);
});
div[layout] {
width: 500px; height: 140px; white-space: nowrap;
overflow: hidden; overflow-x: auto;
}
div.col { height: 140px; width: 400px; display: inline-block; text-align:center; }
div { border: 1px solid red; }
<div id="row" layout="row"><div class="col">1</div></div>
<button id="btn">Add</button>
Edit: Added simple animation using setTimeout (in order to keep jQuery away). Ideally you should be using requestAnimationFrame or a suitable library if you are already using one.
I have a div element with vertical scrolling. It has span elements with text in it. How can I get the coordinates of these span elements. But I don't want it relative to the scroll position.
For example, in the div, lets say its 400px width, 1000px in height (but the view height is 500px), and its scrolled half way vertically. Then in the center of the view, I see a text, and if I click on it, I want the coordinate like (200, 250)
How can I get coordinates that are absolute to the div container?
Use element.getBoundingClientRect? (Subtract the container's top if you want it relative to the container.)
function client() {
alert(document.getElementById('child').getBoundingClientRect().top);
}
function local() {
var container = document.getElementById('container');
var containerRect = container.getBoundingClientRect();
var child = document.getElementById('child');
var childRect = child.getBoundingClientRect();
localTop = childRect.top - containerRect.top;
alert(localTop);
}
#container {
height: 100px;
overflow:scroll;
border:1px solid red;
margin-top:100px;
}
#child {
background: yellow;
}
<div id="container">
<div>Test</div>
<div>Test</div><div>Test</div><div>Test</div><div>Test</div>
<div id="child">Item of interest</div>
<div>Test</div><div>Test</div><div>Test</div><div>Test</div>
</div>
<button onclick="client()">Global top</button>
<button onclick="local()">Local top</button>
Let's say the scrollable div has an id of 'myDiv' and one element inside the div has an id of 'element1'. To find its true 'top' value in javascript try this:
alert($('myDiv').css('top') + $('element1').css('top'));
I need to know how one can get the maximum possible width of a div. Generally, a <div>'s width is limited by it's parent, meaning that it can not be larger than a certain amount. How that certain amount can be calculated?
I need this to calculate if the text inside the current <div> has overflown, (since the only way to detect a text overflow is to compare it's current width to its current clientWidth).
Thanks!
A couple ways to do this, let's start with your div...
<div id='mr_cleaver'>
<div id='beaver'>Blah</div>
</div>
...and then someJavascript:
//Method One: Find the width of the div's parent
var max_beaver_width = $('mr_cleaver').offsetWidth
//Method Two: Max out the div, find length, return to original size.
var beaver_width = $('beaver').offsetWidth;
$('beaver').style.width = "100%";
var max_beaver_width = $('beaver').offsetWidth;
$('beaver').style.width = beaver_width + 'px';
//Method Three: Check for overflow
$('beaver').scrollWidth > $('beaver').offsetWidth ? alert("Over") : alert("Within")
Thanks Steve!
Your suggestions were very helpful. Although none of them worked for me(probably I didn't explain my situation very well), but using your hints, I could find a way to detect text overflow:
/* specifying the height of 'beaver'*/
var font_size= $('beaver').css("font-size");
font_size = parseInt(font_size.replace(/[a-z]*/gi,''));
var maxHeight = font_size + 4; // 4 is to make sure that the font fits in the maxHeight
/*now calculate current height*/
$('beaver').style.overflow-y:visible;
$('beaver').style.overflow-x:hidden;
var cuurentHeight = $('beaver').clientHeigth;
/* check whether overflow is occured*/
if(cuurentHeight > maxHeight){
//overflow has been occured
}
If you want the div to be 100 % in width with no space between the edges, you can try to add this simpel CSS style to the div:
<style type="text/css">
#FullWidthDiv { // EDIT
position: absolute; // If you use 'fixed' as position, then the div
display: block; // won't become smaller when the screen is at is smallest.
float: left; // The fixed position is good when you for example want the
width: 100%; // menu to stay in place.
background-color: #06F;
height: auto;
left: 0px;
top: 0px
}
</style>
<html>
<body>
<div id="FullWidthDiv"></div>
</body>
</html>
You can append a div into parent element to measure it.
var test = document.querySelector('#test');
var div = document.createElement('div');
div.style.width = '10000px';
test.appendChild(div);
var maxWidth = test.offsetWidth;
test.removeChild(div);
alert(maxWidth);
#test {
display: inline-block;
max-width: 100px;
}
<div id="test"></div>