Fixed position of content until parent div ends - javascript

I have a piece of code that gets fixed while y-scoll is over 765px. The problem is that this content will be fixed even outside its parent. Here is an example: https://jsfiddle.net/rwbsua3v/
As you can see, while you keep scrolling, the content in the green box gets fixed and will override the blue box as you scroll.
I could fix this issue if I knew the exact heights of the red/green and blue boxes but the problem is that they can be of any length. How would I make the content in the green box fixed until it hits the bottom of parent (green box) without affecting the y-scroll offset and css top: 87px?
Here is my code:
window.onscroll = function() {
myFunction()
};
var floating1 = document.getElementById("floating1");
var yOffset = 765;
function myFunction() {
if (window.pageYOffset > yOffset) {
floating1.classList.add("sticky");
} else {
floating1.classList.remove("sticky");
}
}
table {
width: 100%;
min-height: 2000px;
}
table tr td {
vertical-align: top;
}
.sticky {
position: fixed!important;
top: 87px;
}
<table>
<tr>
<td style="background: red; width: 200px;">
...
</td>
<td style="background: green; width: 200px;">
<div id="floating1">
Floating content
</div>
</td>
</tr>
</table>
<div style="height: 1500px; background: blue;">
...
</div>

Use position: sticky that makes the element fixed in place until it encounters the edge of it's container:
window.onscroll = function() {
myFunction()
};
var floating1 = document.getElementById("floating1");
var yOffset = 765;
function myFunction() {
if (window.pageYOffset > yOffset) {
floating1.classList.add("sticky");
} else {
floating1.classList.remove("sticky");
}
}
table {
width: 100%;
min-height: 2000px;
}
table tr td {
vertical-align: top;
}
.sticky {
position: sticky;
top: 87px;
}
<table>
<tr>
<td style="background: red; width: 200px;">
...
</td>
<td style="background: green; width: 200px;">
<div id="floating1">
Floating content
</div>
</td>
</tr>
</table>
<div style="height: 1500px; background: blue;">
...
</div>

Here is a working fiddle: https://jsfiddle.net/17rn4qtw/2/.
I added id="parent" to the parent of the floating content and used Javascript to get its height.
I addded a second if clause in the function that only fixes the floating content if the page offset if less than the div content height.
I also subtracted the top pixels from the height of the parent so the floating content disappeared a when outside of the parent, not just when the parent was outside of the window view.

add a class green to your div and check when it reaches an end.
window.onscroll = function() {myFunction()};
var floating1 = document.getElementById("floating1");
var yOffset = 765;
function myFunction() {
if (window.pageYOffset > yOffset && window.pageYOffset < $('.green').height()) {
floating1.classList.add("sticky");
} else if (window.pageYOffset > $('.green').height()) {
floating1.classList.remove("sticky");
} else {
floating1.classList.remove("sticky");
}
}
table {
width: 100%;
min-height: 2000px;
}
table tr td {
vertical-align: top;
}
.sticky {
position: fixed!important;
top: 87px;
}
<table>
<tr>
<td style="background: red; width: 200px;">
...
</td>
<td style="background: green; width: 200px;" class="green">
<div id="floating1">
Floating content
</div>
</td>
</tr>
</table>
<div style="height: 1500px; background: blue;">
...
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
https://jsfiddle.net/djkog8ft/

Related

Why my div disappear when I hover it when it over his parent div?

I try to construct a structure with 3 scrollbars, one on the top of the table one on the bottom and one tiny scrollbar that appear only if you hover the table(because it's a big table). And this tiny scrollbar should follow you until you get out of the table. So I construct the structure in 3 part.
the firsts two parts are litterally the tiny scrollbar and the top scrollbar. But the third part is more complex. Firstly we have the main div that contain all the div. Then I put the div to start the structure of the scrollbar. Then I put a div AND the table in the new div. The div next to the table aims to floating over the table to create a zone of interaction between the mouse of the user and the tiny scrollbar. I need this div because I don't want the whole table to have this type of interaction, indeed, the very top of the table and the very bottom of the table would normally don't have any interaction.
Once the tinybar appear because I hover the floating div I try to scroll it but it doesn't work because it disappear when I try to scroll it in the "main" div. I try to fix this by changing the position but it doesn't work. But I put top:10% on the tinybar and I added a paragraphe tag with a bottom padding of 100px to see what happen if th tiny bar is outof the main div: and it's works ! The Tiny scrollbar can work ony out of the main div.
So my question is how to fix that ? I want to scroll the tinybar even if my mouse is over the main div.
HTML:
<p id="zola" style="padding-bottom: 100px"> <p>
<div class="wrapper_mobile" id="w_mob" onscroll="move_scrollbar_mobile()">
<div class="child_mobile" id="w_mob_child">
</div>
</div>
<div class="wrapper_top" id="w_top" onscroll="move_scrollbar_top()">
<div class="child_top" id="w_top_child">
</div>
</div>
<div id="main" style="position: relative" onmouseout="hide_scroll_mob()">
<div class="wrapper_table" id="w_tab" onscroll="move_scrollbar_table()">
<div class="wrapper_float" id="w_flo" onmouseover="disp_scroll_mob()">
</div>
<table class="search_table" id="w_tab_child">
<tbody>
<tr>
<th>Col1</th>
<th>Col2</th>
<th>Col3</th>
<th>Col4</th>
<th>Col5</th>
<th>Col6</th>
<th>Col7</th>
</tr>
</tbody>
</table>
</div>
</div>
CSS:
.wrapper_top, .wrapper_table{
width: 300px;
overflow-x: scroll;
overflow-y:hidden;
}
.wrapper_mobile{
position: fixed;
width: 100px;
height: 50px;
top: 10%;
overflow-x: scroll;
overflow-y: hidden;
display: none;
padding: 10px;
background-color: red;
z-index: 2;
padding-bottom: 10px;
}
.wrapper_float {
width: 100%;
height: 90%;
top: 10%;
position: relative;
background-color: #88FF88;
z-index: 1;
}
.wrapper_top{
height: 20px;
}
.wrapper_table{
height: 200px;
}
.child_top {
width:1000px;
height: 20px;
}
.child_mobile {
width:300px;
height: 20px;
}
.search_table{
table-layout: fixed;
}
th{
font-size:15px;
background:#66C2E0;
}
th {
min-width: 200px;
}
#main {
height: 500px;
border: 1px solid red;
}
JS:
let w_mob_len = getComputedStyle(document.getElementById('w_mob_child'), null).width.replace("px", "") - getComputedStyle(document.getElementById('w_mob'), null).width.replace("px", "");
let w_top_len = getComputedStyle(document.getElementById('w_top_child'), null).width.replace("px", "") - getComputedStyle(document.getElementById('w_top'), null).width.replace("px", "");
let w_tab_len = getComputedStyle(document.getElementById('w_tab_child'), null).width.replace("px", "") - getComputedStyle(document.getElementById('w_tab'), null).width.replace("px", "");
function move_scrollbar_mobile(){
let wrap_mob = document.getElementById("w_mob");
let wrap_top = document.getElementById("w_top");
let wrap_tab = document.getElementById("w_tab");
wrap_top.scrollLeft = wrap_mob.scrollLeft * w_top_len/w_mob_len;
wrap_tab.scrollLeft = wrap_mob.scrollLeft * w_tab_len/w_mob_len;
}
function move_scrollbar_top(){
let wrap_mob = document.getElementById("w_mob");
let wrap_top = document.getElementById("w_top");
let wrap_tab = document.getElementById("w_tab");
wrap_mob.scrollLeft = wrap_top.scrollLeft * w_mob_len/w_top_len;
wrap_tab.scrollLeft = wrap_top.scrollLeft * w_tab_len/w_top_len;
}
function move_scrollbar_table(){
let wrap_mob = document.getElementById("w_mob");
let wrap_top = document.getElementById("w_top");
let wrap_tab = document.getElementById("w_tab");
wrap_mob.scrollLeft = wrap_tab.scrollLeft * w_mob_len/w_tab_len;
wrap_top.scrollLeft = wrap_tab.scrollLeft * w_top_len/w_tab_len;
}
function disp_scroll_mob(){
document.getElementById("w_mob").style.display = "inline-block";
}
function hide_scroll_mob(){
document.getElementById("w_mob").style.display = "none";
}
function over_w3(){
document.getElementById("w_mob").style.position = "absolute";
}

Click toggle with multiple targets

I have a two images and when you click on one, text (relevant to image) slides into view below the image. Currently the method for closing/toggling the text is to click on the image again.
If I click on the second image while the text on the first image is still visible, it closes the text. I then have to click on the second image again to see its text content appear.
I'd like to be able to click on the second image and either the text content just swaps OR it closes the text for the first image and opens the text for the second image (in just one click, not two).
Any input appreciated!
I have a fiddle here
JS:
var teamMember = document.getElementsByClassName("team-member");
var teamRow = document.getElementsByClassName("team-row");
var bioContainer = $( "<div class='container' id='bio-container'></div>" );
$(bioContainer).hide();
$(teamMember).click(function() {
$(this).toggleClass('member-selected');
$('.team-grid').toggleClass('member-active');
$(bioContainer).html("");
var thisBio = $(this).find(".team-bio");
var thisRow = $(this).parent(teamRow);
$(thisRow).after(bioContainer);
var bioHTML = $(thisBio).html();
$height = $(thisBio).outerHeight(true)
$(bioContainer).css('height', $height);
$(bioContainer).slideToggle( "slow", function() {
$(this).html(bioHTML);
});
});
HTML:
<section class="team-grid">
<div class="team-row">
<div class="col-sm-6 team-member">
<img src="https://www.catster.com/wp-content/uploads/2017/11/A-Siamese-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
JOHN'S Bio
</div>
</div>
</div>
<div class="col-sm-6 team-member">
<img src="https://r.hswstatic.com/w_907/gif/tesla-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
SALLY'S Bio
</div>
</div>
</div>
</div>
</section>
CSS:
.col-sm-6 {
width:50%;
float:left;
}
img {
width:100%;
height:200px;
object-fit:cover;
cursor:pointer;
}
.close-bio {
color:pink;
font-weight:bold;
}
.team-bio {
visibility: hidden;
padding: 80px 20%;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
#bio-container {
background: #666;
width: 100%;
max-width: none;
position: relative;
float: left;
padding: 25px;
color:#fff;
font-size:20px;
}
Please check this answer,
Js Fiddle
var teamMember = document.getElementsByClassName("team-member");
var teamRow = document.getElementsByClassName("team-row");
var bioContainer = $( "<div class='container' id='bio-container'></div>" );
var bioContainerExpanded = false;
$(bioContainer).hide();
$(teamMember).click(function() {
if(bioContainerExpanded){
$(bioContainer).slideToggle( "slow", function() {});
bioContainerExpanded = false;
}
$('.team-grid').toggleClass('member-active');
// Resets bioContainer html to blank
$(bioContainer).html("");
$(this).toggleClass('member-selected');
// Assign 'this' team bio to variable
var thisBio = $(this).find(".team-bio");
// Assign 'this' row to variable (find teamRow parent of this teamMember)
var thisRow = $(this).parent(teamRow);
// Place bio after row
$(thisRow).after(bioContainer);
// Assign 'this' bio html to variable
var bioHTML = $(thisBio).html();
// Dynamically calculte height of the bio including padding
$height = $(thisBio).outerHeight(true)
//assign height to bioContainer before the toggle so that it slides smoothly
$(bioContainer).css('height', $height);
// Slide toggle the bioContainer
$(bioContainer).slideToggle( "slow", function() {
// Insert bioHTML into 'this' bioContainer
$(this).html(bioHTML);
});
bioContainerExpanded = true;
});
.col-sm-6 {
width:50%;
float:left;
}
img {
width:100%;
height:200px;
object-fit:cover;
cursor:pointer;
}
.close-bio {
color:pink;
font-weight:bold;
}
.team-bio {
visibility: hidden;
padding: 80px 20%;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
#bio-container {
background: #666;
width: 100%;
max-width: none;
position: relative;
float: left;
padding: 25px;
color:#fff;
font-size:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="team-grid">
<div class="team-row">
<div class="col-sm-6 team-member">
<img src="https://www.catster.com/wp-content/uploads/2017/11/A-Siamese-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
JOHN'S Bio
</div>
</div>
</div>
<div class="col-sm-6 team-member">
<img src="https://r.hswstatic.com/w_907/gif/tesla-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
SALLY'S Bio
</div>
</div>
</div>
</div>
</section>

CSS Flex - When re-sizing wrapper flex item change its width dimension

I am using CSS Flex in order to display three DIVs consequential in a wrapper.
The width dimension for the first DIV (item0) is to 50px.
I need to change the height of the wrapper and keep the original width for item0 and item1 DIVs inside the wrapper.
My current problem is that:
When re-sizing the wrapper, item for flex (item0) get a different width. size
Please click the two buttons in the example to see the change in dimension.
I would like to know:
Why the width size change?
How to maintain the width size for item0 and item2same as my original CSS settings?
Notes:
I understand scroll-bar appears taking space. How I could I keep item0 and item2 at a fix width and item1 stretching to fill up the remaining space? (I have tried to use % but I cannot get the result wanted).
var btn0 = document.getElementById('btn0');
var btn1 = document.getElementById('btn1');
var item0 = document.getElementById('item0');
var result = document.getElementById('result');
var wrapper = document.getElementById('wrapper');
btn0.addEventListener('click', function(event) {
wrapper.style.height = '25px';
result.value = item0.getBoundingClientRect().width;
});
btn1.addEventListener('click', function(event) {
wrapper.style.height = '350px';
result.value = item0.getBoundingClientRect().width;
});
#wrapper {
width: 250px;
height: 350px;
background-color: gray;
overflow: auto;
}
#flex-container {
display: flex;
}
#item0 {
width: 50px;
background-color: red;
height: 150px;
}
#item1 {
width: 150px;
background-color: orange;
height: 150px;
}
#item2 {
width: 50px;
background-color: pink;
height: 150px;
}
<div id="wrapper">
<div id="flex-container">
<div id="item0" class="item">a
</div>
<div id="item1" class="item">b
</div>
<div id="item2" class="item">c
</div>
</div>
</div>
<button id='btn0' type="button">Smaller wrapper</button>
<button id='btn1' type="button">Bigger wrapper</button>
item0 width is: <input id="result"type="text">
Use flex: 0 0 50px for the item0 style.
See jsfiddle
It tells the flexbox layout don't grow and don't shrink and give it a width of 50px.
It is always good to use the flex: property for flexbox items because the default value for it may be different from browser to browser.
(Actually your problem doesn't happen in firefox for example)
When the width of the container is reduced, all child elements are reduced proportionally too.
Add flex: 0 0 auto; to item0 and item2. It disallows element to shrink to its minimum when there is not enough space.
var btn0 = document.getElementById('btn0');
var btn1 = document.getElementById('btn1');
var item0 = document.getElementById('item0');
var result = document.getElementById('result');
var wrapper = document.getElementById('wrapper');
btn0.addEventListener('click', function(event) {
wrapper.style.height = '25px';
result.value = item0.getBoundingClientRect().width;
});
btn1.addEventListener('click', function(event) {
wrapper.style.height = '350px';
result.value = item0.getBoundingClientRect().width;
});
#wrapper {
width: 250px;
height: 350px;
background-color: gray;
overflow: auto;
}
#flex-container {
display: flex;
}
#item0 {
flex: 0 0 auto;
width: 50px;
background-color: red;
height: 150px;
}
#item1 {
width: 150px;
background-color: orange;
height: 150px;
}
#item2 {
flex: 0 0 auto;
width: 50px;
background-color: pink;
height: 150px;
}
<div id="wrapper">
<div id="flex-container">
<div id="item0" class="item">a
</div>
<div id="item1" class="item">b
</div>
<div id="item2" class="item">c
</div>
</div>
</div>
<button id='btn0' type="button">Smaller wrapper</button>
<button id='btn1' type="button">Bigger wrapper</button>
item0 width is: <input id="result"type="text">

How do I start with the tab expanded (toggle)?

So I am modifying a web page and there is a table on the bottom of the page that starts minimized. When you click the arrow it opens upward to reveal the table. I am attempting to modify it so that it already starts off opened when the page loads.
HTML Snippet:
<div class="row" id="cp-toggle">
<div class="col-sm-12">
<div class="col-sm-2 col-sm-offset-5 toggle-button">
<a><span class="glyphicon glyphicon-chevron-up"></span></a>
</div>
<div class="col-sm-12" style="height: calc(100% - 25px);max-height: 250px;background-color:#d3d3d3;">
<div style="height: 100%;max-height: 250px;">
<div style="height: 25px;padding-top: 4px;">
<div style="float: left;padding-right: 9px;">
<span> Posts: </span> <span id="posts_count"></span>
</div>
</div>
<div style="overflow-y: scroll;height: 100%;max-height: 225px;">
<table id="result_table" class="table" style="display:table;" >
<thead class="result_thead"></thead>
<tbody class="result_tbody"></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
Javascript:
var control_panel= (function(){
var container = $('#cp-toggle div:first-child');
var btn = $('#cp-toggle div:first-child').find("div").first();
var table_panel = $('#cp-toggle div:first-child div:nth-child(2)').first();
var open_css = "glyphicon-chevron-up";
var close_css = "glyphicon-chevron-down";
var open = function(){
container.find("span").first().switchClass(open_css, close_css);
var h = table_panel.height() + 25;
container.css("top", "calc(100% - "+ h +"px)");
};
var close = function(){
container.find("span").first().switchClass(close_css, open_css);
container.css("top", "calc(100% - 25px)")
};
var isOpen = function(){
return _.contains(container.find("span").first().attr('class').split(/\s+/), close_css);
};
var toggle = function(){
if (isOpen()){
close();
} else {
open();
}
};
btn.on('click', toggle);
return {
open: open,
close: close,
toggle: toggle,
isOpen : isOpen
};
}());
CSS Snippet:
#cp-toggle > div:first-child {
top: calc(100% - 25px);
position: fixed;
z-index: 25;
}
.toggle-button {
height: 25px;
padding-top: 3px;
background-color: #d3d3d3;
border-top-right-radius: 7px;
border-top-left-radius: 7px;
text-align: center;
cursor: pointer;
}
#cp-toggle a {
color: #111;
}
#cp-toggle a:hover {
color: #777;
}
.tab-pane { height: 100%;}
#email-body { height: calc(100% - 80px); }
.body-view { height: 100%; overflow-y: scroll; }
.marked {
color: #ffd700;
}
.marked:hover {
color: #ffd700;
}
I have tried modifying the javascript to call control_panel.open(); at the end. I have tried altering the toggle to start with open();. None of these seem to have any effect on the code. I am not sure if I am looking in the correct area or if I am doing something incorrectly.
Try this (you tried something similar in a comment, but I'll explain in a minute...):
<script>
window.addEventListener('load', function() {
control_panel.open();
});
</script>
The problem with your original attempt...
<script>onLoad=control_panel.open();</script>
... was that it was setting a variable called 'onLoad' with the value of whatever was returned by running the function control_panel.open(), which it did immediately instead of waiting until the page was loaded. Instead, in my example I'm setting an 'onload' listener on the window, so that when the window finishes loading, then it'll run the control_panel.open() function that it is now aware of.

how to scroll to bottom of a div

I would like to scroll to the bottom of the div content-main, so that the button Button is displayed at the bottom of the window. I tried the following:
<div class="container">
<div class="content-main">
dynamic content dynamic content.....
<button>Button </button>
</div>
<div class ="footer"></div>
</div>
<script>
var mainContentHeight = $(".content-main").height();
var footerHeight = $(".content-footer").height();
window.scrollTo(0, mainContentHeight - footerHeight);
</script>
This works differently, when I test it in two monitors with different size. How to display the button at the bottom of the window?
Instead binding scrollTo to the window object, bind it to the element you want to scroll:
var container = $('.container')[0];
var contentMain = $('.content-main')[0];
var mainContentHeight = $(".content-main").height();
var footerHeight = $(".content-footer").height();
container.scrollTo(0, mainContentHeight - footerHeight);
.container {
overflow: auto;
height: 100px;
}
.content-main {
height: 100%;
position: relative;
border: 1px solid #000;
height: 1000px;
}
.content-footer {
height: 50px;
}
button {
position: absolute;
bottom: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="content-main">
dynamic content dynamic content.....
<button>Button </button>
</div>
<div class="content-footer"></div>
</div>

Categories