how to check which children overflown the parent's div - javascript

first time posting, i'm trying to build a responsive website, where user/s can add / upload images to the website, but i don't want the page to fill up with images, i just want the page to have one row of every group of pictures the user added, and if the user click the see more button then it expands to show more of the images in that group.
Example:
Lets say i have parent div and 5 child divs of images with same class name.
<div class="parent">
<div class"child"></div>
<div class"child"></div>
<div class"child"></div>
<div class"child"></div>
<div class"child"></div>
</div>
Now the website page can only contain 5 images per row, but if the user added more images, it goes to the next row. also if the page width is smaller, then the page will contain less than 5 images, depends on the available space.
I tried:
To check inside a loop of all the child divs, to see if they have overflown the parent, then move them to a hidden class, but with no luck, i cant figure it out how to check which children overflown the parent's div.
All i want is:
Figure it out how to check which children overflown the parent's div.
I don't know if this needs javascript or only html css... i'm only learning.
Thanks.
Edit
The code i did:
// clicking see more to show the rest of images
folderSeeMore.onclick = function() {
if (folderSeeMore.innerHTML == "See more") {
$(centerViewMid).css("overflow", "visible");
$(centerViewMid).css("height", "auto");
folderSeeMore.innerHTML = "See less";
wait = 1;
} else {
$(centerViewMid).css("overflow", "hidden");
$(centerViewMid).css("height", "150");
folderSeeMore.innerHTML = "See more";
}
}
.center_view_middle {
border-radius: 10px;
height: 150px;
margin-bottom: 15px;
overflow: hidden;
}
.center_view_middle_box {
display: inline-block;
position: relative;
margin-right: 15px;
width: 130px;
height: 150px;
border-radius: 10px;
text-align: center;
}
<h6 class="folder_seeMore"><u>See more</u></h6>
<div class="center_view_middle">
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
<div class="center_view_middle_box">
<div class="middle_box_img"></div>
</div>
</div>

Related

Why is my display of none for my div in css being applied to all of its descendants even though I am setting one of the descendants to display block?

I am working on a page of mine.
The aim is that when I click on the image of apples, everything except for the rest of my images gets set to a display of none.
Here is my code:
// hideAll() hides everything except the images in the fruits class.
function hideAll() {
let fruit = document.querySelectorAll("div.main div.fruits");
let mainContainer = document.querySelectorAll("div.main");
mainContainer[0].style.display = 'none';
for (i = 0; i < fruit.length; i++) {
fruit[i].style.display = 'block';
//fruit[i].style.setProperty('display', 'block', '!important'); //This did not work
}
}
.fruits {
display: none;
}
img {
width: 100px;
height: 100px;
}
.Categories {
padding: 5px 5px 5px 5px;
background-color: red;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="main">
<h1>Main Page</h1>
<div class="base">
<h2>Fruit Categories</h2>
<div class="some-content">
<p>This page contains some fruit information.</p>
<div class="Categories">
<p>We have apples, bananas, oranges, etc.</p>
</div>
</div>
<img src="https://foodprint.org/wp-content/uploads/2018/10/IMG_3392-e1539129880189.jpg" onclick="hideAll();">
<div class="element-container">
<div class="fruits">
<img src="https://foodprint.org/wp-content/uploads/2018/10/IMG_3392-e1539129880189.jpg">
</div>
<div class="fruits">
<img src="https://foodprint.org/wp-content/uploads/2018/10/imageedit_127_5581342771.jpg">
</div>
<div class="fruits">
<img src="https://i0.wp.com/moodymoons.com/wp-content/uploads/2016/02/img_8986.jpg?fit=4560%2C3000&ssl=1">
</div>
<div class="fruits">
<img src="https://www.naturalhealth365.com/wp-content/uploads/2016/04/blueberries.jpg">
</div>
<div class="fruits">
<img src="https://th.bing.com/th/id/OIP.gBifOTB-F-wBTx3bzYPiGgHaE-?pid=ImgDet&rs=1">
</div>
<div class="fruits">
<img src="https://th.bing.com/th/id/OIP.3yrzbKoKIgyR7eBhHma26AHaGm?pid=ImgDet&rs=1">
</div>
</div>
</div>
</div>
</body>
</html>
Basically, all of the images contained within the div class of fruits (6 images in total) needs to get set to a display of "block". Everything else gets set to a display of none (when the apple image is clicked).
Since there are many divs (and nested divs) within the main class, I thought that I could set the entire main class to a display of none. Then, I could set all of the elements within the fruits class to a display of block. I even tried using the !important keyword within the fruits class to override the effect of setting everything within the main div to none but that did not seem to do the trick.
Is there any way of targeting css for every descendant of a div except for the one specified?
All of the children elements are not visible because their parent is invisible; not because they are inheriting anything, but because the element they are contained in is invisible.
The !important value only applies when you want to disrupt the CSS hierarchy; it has nothing to do with the HTML hierarchy.
In your case, you want to set the display attribute in your loop for each child individually; forget about the parent.
You can do something like this snippet.
Note that I replaced your image src with placeholders since yours weren't showing up for me (and/or might stop showing up at some point).
It's coded such that all images show at the outset, and each time you click one, it'll hide itself and show all others. It's not clear what you're trying to achieve, but this behavior should at least illustrate how you can set it up for your needs.
//capture all fruits into an array variable
let allFruits = [...document.querySelectorAll("#elcon > div.fruits")];
allFruits.forEach((fruit) => {
//add a click listener on each fruit element
fruit.addEventListener("click", () => {
//show all fruits
allFruits.forEach(e => e.style.display = 'block');
//hide the fruit that got clicked
fruit.style.display = 'none';
})
});
img {
width: 100px;
height: 100px;
}
.Categories {
padding: 5px 5px 5px 5px;
background-color: red;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="main">
<h1>Main Page</h1>
<div class="base">
<h2>Fruit Categories</h2>
<div class="some-content">
<p>This page contains some fruit information.</p>
<div class="Categories">
<p>We have apples, bananas, oranges, etc.</p>
</div>
</div>
<div class="element-container" id="elcon">
<div class="fruits">
<img src="https://via.placeholder.com/150/000000">
</div>
<div class="fruits">
<img src="https://via.placeholder.com/150/FF8000">
</div>
<div class="fruits">
<img src="https://via.placeholder.com/150/8F0000">
</div>
<div class="fruits">
<img src="https://via.placeholder.com/150/008000">
</div>
<div class="fruits">
<img src="https://via.placeholder.com/150/00FF00">
</div>
<div class="fruits">
<img src="https://via.placeholder.com/150/0000FF">
</div>
</div>
</div>
</div>
</body>
</html>

How to make the mobile keyboard appearance bump the div rather than absolutely position itself over it?

I'm developing a simple chat component and I'm having an issue where, on mobile, if I click the textbox to send a message, rather than bumping up the messages list above it, the virtual keyboard instead absolutely positions itself on top of it.
This is undesirable because I want the user to be able to see the latest message while typing a message. However, I cannot figure out how to rectify this behavior. (and I cannot put the textbox inside the messages div because it should always be at the bottom)
I've created an example snippet that demonstrates the problem here (adding bottom margin demonstrates the problem identically to clicking the textbox and having the mobile keyboard pop up)
Basically, if you scroll to the bottom and click the "add margin" button, you'll see that rather than push the contents above it, such that you can still see the latest message, it instead scrolls up. Is there any way to avoid this?
Here is a copy of the code in case the fiddle goes down:
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
}
Fortunately, there is. The problem here is you are not handling the scroll position of the .messages when the .send-message div expands (i.e. gets more margin). I presume you want to adjust it so that the scroll position takes the last visible message as its pivot (i.e. the last visible message before the div expands has to appear after the div expands, and vice-versa). To adjust said scroll position, here's a minimal working example (I changed your HTML content a little so that you can indicate what the last message is and I adjusted your JS code):
function test() {
let messageBox = document.querySelector('.messages')
let beforeMessageBoxHeight = messageBox.clientHeight
let afterMessageBoxHeight
let messageBoxHeightDifference
let beforeScrollTop = messageBox.scrollTop
let afterScrollTop
document.querySelector(".send-message").classList.toggle("some-margin")
afterMessageBoxHeight = messageBox.clientHeight
messageBoxHeightDifference = beforeMessageBoxHeight - afterMessageBoxHeight
afterScrollTop = beforeScrollTop + messageBoxHeightDifference
messageBox.scrollTop = afterScrollTop
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
The idea is:
Get the clientHeight (visible height, read MDN Docs for more details) before the div expands
Get the scrollTop value (how many pixels measured from the topmost visible/invisible element to the topmost visible element)
When the div (.send-message) expands, the visible height (clientHeight) automatically reduces in size. The scrollTop value is still the same, which means that the topmost visible element before the div expands will still be visible. However, that is not what we want: we want the bottommost visible element before the div expands to remain visible
We measure the height difference after the div expands and before the div expands. Logically, the height difference is what is making the bottom parts of the visible messages (before the div expands) to appear invisible (due to overflow).
To address that issue, add the height difference to the previous scrollTop value so that it scrolls nicely to the bottommost visible message before the div expands.
Voila, it works. You can apply the same logic when the div retracts.

How to Align a div in Center When Contents added Dynamically

Please have a look at this Image.
Here I was use the Bootstrap for aligning the divs. And created only one div. The Contents are added in this div dynamically from the admin side. then it will loop the div. That's Working fine.
But here you can see only 6 Contents are available. So 2 Divs are aligned in the left. I need these div should align in the middle of the Page. If the Contents are 7 or 5 the Second row Contents should be in the Middle. How to align these Divs Middle. Please Help me to Solve this Problem.
Here Is My Code..
<div class="col-sm-6 col-md-3">
<div class="service-item hvr-grow wow fadeIn" data-wow-duration="500" data-wow-delay="100ms">
<img src="{{ 'assets/img/icon-services.png' |theme }} ">
<h4>{{ service['name'] }}</h4>
<p>{{ str_limit(service['description'], 100) }}</p>
Read More
</div>
</div>
Thank you in Advance.
Add display: inline to child div and text-align: center to the parent div. Don't use col-md of bootstrap because it have float: left propertive
.parent {
text-align: center;
}
.child {
display: inline-block;
width: 24%;
border: solid 1px #123;
height: 50px;
margin: 0 auto !important;
}
<div class="parent" id="parent">
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
<div class='child'></div>
</div>
You can use bootstrap to set an offset for each div dynamically depending on your div's desired position or set the margin of the divs to auto. See this post for a detailed explanation.

Angular - detect click background div but not on divs within

On ollynural.github.io, in the portfolio page i'm trying to simulate a pop-up div giving more information on the project you clicked on. To go back off the pop-up, I've added an ng-click so when you click on the main portfolio-pop-up container, the pop-up is removed.
Is it possible to only have the parts of the portfolio-pop-up div that are exposed (not on the photo nor the description white box) removing the main div once clicked? So you can click freely on the picture and the white box
<div class="portfolio-pop-up container" ng-click="losePortfolioFocus()">
<div class="row">
<div class="col-xs-12">
<img class="portfolio-image portfolio-image-popup" src="{{portfolioImageClass}}">
</div>
<div class="col-xs-12 pop-up-container">
<div class="pop-up-row">
<div class="col-xs-9" style="background: red">
<h1>
{{portfolioTitle}}
</h1>
<p>
{{portfolioDescription}}
</p>
</div>
<div class="col-xs-3" style="background: cyan">
Click me
<div ng-repeat="tech in portfolioTech">
{{tech}}
</div>
</div>
</div>
</div>
</div>
</div>
JS
$scope.losePortfolioFocus= function() {
angular.element('.portfolio-pop-up').css("display", "none");
}
CSS
.portfolio-pop-up {
display: none;
position: absolute;
width: 100%;
height: 100%;
/* color with alpha transparency */
background-color: rgba(0, 0, 0, 0.70);
top: 0;
left: 0;
bottom: 0;
right: 0;
}
Any help would be appreciated, can post more css or code if needed
You can stop the propagation of the click event on the element that wraps the pop-up's content like this:
<div class="portfolio-pop-up container" ng-click="losePortfolioFocus()">
<div class="row" ng-click="$event.stopPropagation()">
...
</div>
</div>
This way the clicks inside the popup will not trigger the losePortfolioFocus() handler.
I suggest you crawl up the event chain from you event' target and check whether your pop-up-container is in there. This way, you'll have a way to distinguish click in the pop-up or out of it.

How to change styling of a specific div onhover of another element when divs share an id

I have multiple rows with 3 divs per row. Each div consists of two rows; in the first row a picture is displayed, in the second row a description is shown. HTML is like this:
<div id="row">
<div id="block1">
<div id="block1-top"><a><img></a></div>
<div id="block1-bottom">Text here</div>
</div>
<div id="block2">
<div id="block2-top"><a><img></a></div>
<div id="block2-bottom">Text here</div>
</div>
<div id="block3">
<div id="block3-top"><a><img></a></div>
<div id="block3-bottom">Text here</div>
</div>
</div>
<div id="row">
<div id="block1">
<div id="block1-top"><a><img></a></div>
<div id="block1-bottom">Text here</div>
</div>
<div id="block2">
<div id="block2-top"><a><img></a></div>
<div id="block2-bottom">Text here</div>
</div>
<div id="block3">
<div id="block3-top"><a><img></a></div>
<div id="block3-bottom">Text here</div>
</div>
</div>
Some CSS:
#block1, #block2, #block3
{
width: 25%;
height: 150px;
display: inline-block;
vertical-align: top;
background-color: #FFFFFF;
border: 1px solid #154494;
}
#block1-bottom, #block2-bottom, #block3-bottom
{
color:#FFFFFF;
}
I want the color of the text in the bottom of the block to change to #FEB90D on hover of the parent div. So for example when hovering over block1, I want the text color of block1-bottom to change into #FEB90D. I found a script which does this for me:
$(function() {
$('#block1').hover(function() {
$('#block1-bottom').css('color', '#FEB90D');
}, function() {
// on mouseout, reset the background colour
$('#block1-bottom').css('color', '#FFFFFF');
});
});
However, this only works for the first block of the first row. I think this is because the id's of the 1st, 2nd and 3rd blocks have the same name and the script cannot figure out on which block to apply the script.
Does anyone have any thoughts on how to fix this, without changing all the divs id's? I have 11 rows in total so using separate names for each div is not really an option in my opinion. So basically, the scripts needs to change the color of the second child of the hovered div.
You shouldn't be using id for more than one element. Change those ids for classes and it will work.
It's better to do this with CSS
.block1 > .block1-bottom {
color: #FFFFFF;
}
.block1:hover > .block1-bottom {
color: #FEB90D;
}
<div class='block1'>
<p class='block1-top'>This is paragraph 1</p>
<p class='block1-bottom'>This is paragraph 2</p>
</div>
IDs should be unique anyways. If you do it in jQuery, it should look like this.
$(function() {
$('.block1').on("mouseover", function() {
$('.block1-bottom').css('color', '#FEB90D');
}).on("mouseout", function() {
$('.block1-bottom').css('color', '#FFFFFF');
});
});
Ids should be unique. So add necessary classes and use class selector. So code is similar to below
$('.row .box').hover(function() {
$(this).find(".boxbottom").css('color', '#FEB90D');
}, function() {
// on mouseout, reset the background colour
$(this).find(".boxbottom").css('color', '#FFFFFF');
});
Here is the demo https://jsfiddle.net/afnhjdjy/
After you clean up your duplicate IDs problem, you can do this without javascript at all:
<div class="row">
<div class="block">
<div class="block-top"><a><img></a></div>
<div class="block-bottom">Text here</div>
</div>
<div class="block">
<div class="block-top"><a><img></a></div>
<div class="block-bottom">Text here</div>
</div>
</div>
CSS:
.block:hover .block-bottom {color: #FEB90D}
According to this situation:
I want the color of the text in the bottom of the block to change to #FEB90D on hover of the parent div
You may simply use:
.block:hover .block-bottom{
color: #FEB90D;
}

Categories