Hold parent height after child element is toggled with pure CSS - javascript

I need to hold parent height after a child element is toggled.
The parent is a bootstrap panel. #big-menu is the child element.
div.content is the element which can modify its height.
I already have a javascript 'solution' (see resizeContent function).
I would to know if there is a CSS solution.
Plunker: http://plnkr.co/edit/tDYZ5YeppCtOgShw97Em
JSFiddle: https://jsfiddle.net/pedrobad/p2b3uufd/
<!doctype html>
</html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js">
</script>
<script type="text/javascript">
var opened = false;
function action() {
var hBefore = $('.panel').height();
if (opened){
$('#big-menu').hide()
} else {
$('#big-menu').show();
}
opened = !opened;
resizeContent(); // comment this line to see my issue
var hAfter = $('.panel').height();
$('#big-menu').html('BIG MENU <br/>hBefore: ' + hBefore + ' hAfter: ' + hAfter);
}
function resizeContent() {
if (opened){
$('.content').height(250); // 300 - 50
} else {
$('.content').height(300);
}
}
</script>
</head>
<body>
<div class='panel'>
<div class='panel-heading'><h2>Heading</h2></div>
<div class='panel-body'>
<div class='content' style="overflow-y: scroll; height: 300px; background-color: grey;">
<ul>
<li>foo</li><li>foo</li><li>foo</li><li>foo</li><li>foo</li>
<li>foo</li><li>foo</li><li>foo</li><li>foo</li><li>foo</li>
<li>foo</li><li>foo</li><li>foo</li><li>foo</li><li>foo</li>
<li>foo</li><li>foo</li><li>foo</li><li>foo</li><li>foo</li>
<li>foo</li><li>foo</li><li>foo</li><li>foo</li><li>foo</li>
<li>LAST ITEM</li>
</ul>
</div>
</div>
<div class='panel-footer'>
<div id='big-menu' style="height: 50px; display: none">MENU</div>
<button onclick='action()'>Show</button>
</div>
</div>
</body>
</html>

I don't totally understand what you're trying to achieve, but if you want a hidden element to still take up space inside its parent you can use visibility: hidden instead of display: none.
In JS you would need to add a class, for example 'visuallyhidden', to the element you want hide. Then apply styles to that class in CSS like:
.visuallyhidden {
visibility: hidden;
}

Related

Select/edit all children elements inside a div

How can I use jquery or css to assign a .class to all elements inside a div?
i.e this is what I have
<div class="nav">
one
two
</div>
But this is what I want
<div class="nav">
one
two
</div>
Using as little code as possible, so that when the page loads, the elements in .nav have the class "test" assigned to them and I don't have to assign it in every single
You can achieve this by following code
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
</head>
<body>
<div>
one
two
</div>
</body>
<script type="text/javascript">
$(document).ready(function () {
$('div > a').addClass('test')
})
</script>
</html>
Pretty simple in jQuery: $('div a').addClass('class');
Or in JavaScript something like this:
let links = document.querySelectorAll("div a");
for(let link of links) {
link.classList.add("class");
}
.class {
text-decoration: none;
color: orange;
font-size: 50px;
margin-right: 100px;
}
<div class="nav">
one
two
</div>
$(document).ready(function() { $('.nav a').each(function(){ $(this).addClass("Test"); }) });
.Test{
color:red
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
one
two
</div>

Javascritpt change class to a div near to his grand-father

I want to dynamically change the class of the element #sidePanel from .compact to .expanded, in this code:
<div id="sidePanel" class="compact"></div>
<div id="topbar">
<div id="buttonContainer">
<div id="button"></div>
</div>
</div>
I'm stuck here, I can't apply the class to the correct <div>, I can just add the class to the topbar:
$(document).ready(function(){
$("#button").mouseover(function(){
$("this").parent().eq(2).addClass(".expanded").removeClass(".compact");
});
});
I also tried this:
$(document).ready(function(){
$("#button").mouseover(function(){
$("#sidepanel").addClass(".expanded").removeClass(".compact");
});
});
Your second example was pretty close. When you $.addClass() and $.removeClass(), or are referring to classnames outside of using a selector to target something, just reference the class name (no need for the leading .). Also JS (and CSS) are case-sensitive, so $('#sidepanel') won't target #sidePanel - the cases need to match.
$("#button").mouseover(function() {
$("#sidePanel").addClass("expanded").removeClass("compact");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>.expanded {color: red;}</style>
<div id="sidePanel" class="compact">sidepanel</div>
<div id="topbar">
<div id="buttonContainer">
<div id="button">button</div>
</div>
</div>
In your first example, $(this) is how you reference this in jQuery. If you put this in quotes, the word this is treated as a string literal instead. And since to use $.parent() you would need to go up 2 levels, you should use $.parents() with the ID of the parent you want to target, then use $.prev() to select the previous element, which is #sidePanel. So to traverse the DOM like that, this is how I would do it.
$("#button").mouseover(function() {
$(this).parents('#topbar').prev().removeClass('compact').addClass('expanded');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>.expanded {color: red;}</style>
<div id="sidePanel" class="compact">sidepanel</div>
<div id="topbar">
<div id="buttonContainer">
<div id="button">button</div>
</div>
</div>
Your problem is you used $("#sidepanel") instead of $("#sidePanel")
Here's a working example after the change is made:
$(document).ready(function(){
$("#button").on('mouseover', function(){
$("#sidePanel").addClass("expanded").removeClass("compact");
});
});
#topbar > div {
width: 100px;
height: 30px;
background: #ccc;
margin-top: 20px;
}
#sidePanel {
width: 100%;
height: 40px;
background: #ccc;
}
#sidePanel.expanded {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="sidePanel" class="compact"></div>
<div id="topbar">
<div id="buttonContainer"></div>
<div id="button"></div>
</div>
first: the solution
$(document).ready(function()
{
$("#button").mouseover(function()
{
// class names - without the dot
$("#sidepanel").addClass("expanded").removeClass("compact");
});
});
then: why you were really close on your first attempt
$(document).ready(function()
{
$("#button").mouseover(function()
{
// $(this) selector uses the `this` keyword (not as a string)
$(this).parent().eq(2).addClass(".expanded").removeClass(".compact");
});
});

HTML load the content of a div in a html file into another html file

Recently I started learning a little of HTML, and I have a little doubt. My intention is to make in the first page a section div which can change depending of the element that you click on a menu (instead of carrying you to another HTML).
I've tried a few things with javascript to see if I could make it work, but I don't achieve anything despite that in other posts that is the given solution.
This is what i have so far:
.sideNav {
position: fixed;
width: 250px;
height: 100vh;
left: 0;
right: 0;
background-color: red;
top: 60px;
}
.contentWrapper {
margin: 60px 0 0 250px;
padding: 0 30px;
left: 0;
top: 0;
background-color: blue;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset = utf-8>
<link rel = "stylesheet" href = "./assets/stylesheets/main.css">
<script type="text/javascript">
function toggleMenu(id) {
var menuBox = document.getElementById(id);
if(menuBox.style.display == "block") {
menuBox.style.display = "none";
} else {
menuBox.style.display = "block";
}
}
</script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$(".menuAnchor").on("click", function() {
event.preventDefault();
$("#contentWrapper").load("food.html" + " #contentWrapper");
return false;
)};
)};
</script>
<title>The Nest</title>
</head>
<body>
<aside class = "sideNav">
<div>
<a class = "menuAnchor" onclick = "toggleMenu('foodMenu')"> Food</a>
<ul class = "menuBox" id = "foodMenu" style = "display : none">
<li>
<a id = "burguer" href = "#">Burguer</a>
</li>
<li>
<a id = "hotDog" href = "#">Hot Dog</a>
</li>
<li>
<a id = "pizza" href = "#">Pizza</a>
</li>
</ul>
</div>
</aside>
<div id = "contentWrapper">
<section class = "contentWrapper">
d
</section>
</div>
</body>
</html>
This is the other HTML file:
<!DOCTYPE html>
<html lang="en">
<body>
<div id = "contentWrapper">
<section class = "contentWrapper">
<h1>Food</h1>
<article id = "burguer">
<h2>Burguer</h2>
<p>
Burguer
</p>
</article>
<article id = "hotDog">
<h2>Hot Dog</h2>
<p>
Hot Dog
</p>
</article>
<article id = "pizza">
<h2>Pizza</h2>
<p>
Pizza
</p>
</article>
</section>
</div>
</body>
</html>
I wanted that, when i press the String (button in a future) the menu would cascade and the "p" that appear in the div section would change to the second HTML info, but I only could link to the other page.
As I said, part of those scripts seem to work as the script of the div load is around in other answers, but can't make it to work for me.
I'm unsure if what I'm doing and how I'm doing it is the best option.
Thank you and sorry for the trouble.
What I'm trying is to, having a main html with the head and the menus:
Graphic for the main html
Being the content changed with another from other html, let's say food, when one of the link in the menu is pressed.
What you are asking in quite unclear, however, I'll offer a solution based on my understanding of your question:
If you want to have some html that is used to replace the contents of a div, consider the template tag: https://developer.mozilla.org/en/docs/Web/HTML/Element/template
Templates are not displayed but can be accessed with jQuery (which I see you are using), for example:
html:
<div id="replace-area">
</div>
<template id="replace-content">
<ol>
<li>Here</li>
<li>Are</li>
<li>Some</li>
<li>Items</li>
</ol>
</template>
jQuery:
$("replace-area").html($("replace-content").clone().html());
With replace-area containing the content you want the user to see at the end and replace-content containing the content you want to put into replace-area.
This will result in:
<div id="replace-area">
<ol>
<li>Here</li>
<li>Are</li>
<li>Some</li>
<li>Items</li>
</ol>
</div>
<template id="replace-content">
<ol>
<li>Here</li>
<li>Are</li>
<li>Some</li>
<li>Items</li>
</ol>
</template>
With only the div being visible.
Hopefully this helps you get what you're after.

JS/jQuery: When prepending a dynamic element, how to force the container div to extend upwards instead of downwards?

If you've noticed, it seems that when prepend() is used, the additional elements get piled at the top but the container div is extended downwards.
Comparing with FB's load previous message, you will notice that elements are loaded on top of each other but your view does not change. It is like append() except the container div "seems" to extend upwards.
I've tried doing this to simulate the div extending upwards but failed
var scrolldif = $('#response')[0].scrollHeight-$('#response').scrollTop();
$('#response').scrollTop(scrolldif);
Here is the sample html to try. Just copy/paste/run in browser.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script src="http://code.jquery.com/jquery-1.10.2.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://maxcdn.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</head>
<style type="text/css">
.chatbox div{
height: 100%;
}
#response{
height: 300px;
overflow-y: scroll;
overflow-wrap: break-word;
}
</style>
<script type="text/javascript">
function appendMessage()
{
var data = 'test';
var message = document.createElement('p');
message.innerHTML = data;
$('#response').append(message);
}
function prependMessage()
{
var data = 'test'+Math.floor((Math.random() * 10) + 1);
var message = document.createElement('p');
message.innerHTML = data;
console.log(message.innerHTML);
$('#response').prepend(message);
}
</script>
<body>
<div class="container">
<div class="chatbox">
<div class="col-sm-8 rightP">
<div class="row contents">
<a onclick="return appendMessage()" class="load btn btn-default">Append</a>
<a onclick="return prependMessage()" class="load2 btn btn-default">Prepend</a>
<div class="row msg">
<div id="response" class="msg form-group">
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Thank you!
I have finally found the answer but if there are better solutions, do share! It seems that my previous trial actually worked but the position of scrolldif was in reference to the top of container div so I reversed to reference it from bottom like so :
$('#response').scrollTop($('#response')[0].scrollHeight-scrolldif);
In my code above, just do this :
function prependMessage()
{
//this scrollHeight is the total height of div including hidden parts of the
//div caused by overflow BEFORE elements were prepended to it.
var scrolldif = $('#response')[0].scrollHeight-$('#response').scrollTop();
for(var $i = 0;$i<10;$i++)
{
//prepend elements....
}
//this scrollHeight is the total height of div including hidden parts of the
//div caused by overflow AFTER elements were prepended to it.
$('#response').scrollTop($('#response')[0].scrollHeight-scrolldif);
}
Although the 'div' does not extends to the top, but it seems to extend just by adjusting the scrollTop value of the container div. If there are better solutions, do share!

Javascript mouseover Element Flickers & Uncaught TypeError

I am trying to use javaScript mouseover and mousout function to get elements from the DOM. sourced child elements from that event.target and add styling to the childNode that matches the specified class name.
Issue that are occurring:
Error: Uncaught TypeError: Cannot read property 'style' of undefined
Displayed class flickers. when mouse is moved even with in the mouse Over current DOM element.
I've tried to get elements by tag name and childNodes filtered through for statemant to apply css, but still issue's
Its probably an easy fix but am baffled.
Any assistance would be great.
The HTML
<!doctype HTML>
<html>
<head>
<title>Gmail Label List</title>
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="func.js"></script>
</head>
<body>
<div id="sideBar-left">
<div class="SbInner-body">
<ul id="label-list">
<li class="lb_li">
<div class="lb-title">Label List 1</div>
<div class="lb-a-icon">
<img src="chevron_expand.png">
</div>
</li>
<li class="lb_li">
<div class="lb-title">Label List 1</div>
<div class="lb-a-icon">
<img src="chevron_expand.png">
</div>
</li>
<li class="lb_li">
<div class="lb-title">Label List 1</div>
<div class="lb-a-icon">
<img src="chevron_expand.png">
</div>
</li>
<li class="lb_li">
<div class="lb-title">Label List 1</div>
<div class="lb-a-icon">
<img src="chevron_expand.png">
</div>
</li>
</ul>
</div>
</div>
</body>
</html>
THE CSS
body
{
background-color: #f0f0f0;
}
div#sideBar-left{
position:relative;
float:left;
width:180px;
}
div.SbInner-body{}
ul#label-list{
background-color: #898989;
width:auto;
height:auto;
overflow: hidden;
}
ul#label-list li {
list-style: none;
cursor:pointer;
background-color: #989898;
width:100%;
height:auto;
overflow: hidden;
}
div.lb-title{
position:relative;
float:left;
height:auto;
width:auto;
padding:5px;
}
div.lb-a-icon{
position:relative;
float:right;
height:15px;
padding:10px;
width:16px;
border:1px solid black;
display: none;
}
THE JS
function showLabel_icon(element)
{
element.target.getElementsByClassName('lb-a-icon')[0].style.display="block";
}
function closeLabel_icon(element)
{
element.target.getElementsByClassName('lb-a-icon')[0].style.display="none";
}
//[ Listeners]
function Add_DOM_listeners(){
if(window.addEventListener){
var lb = document.getElementById('label-list')
var lb_child = lb.getElementsByClassName('lb_li');
for(var i = 0; i < lb_child.length; i++){
lb_child[i].addEventListener('mouseover',showLabel_icon, false);
}// end for
var lc = document.getElementById('label-list')
var lc_child = lc.getElementsByClassName('lb_li');
for(var j = 0; j < lc_child.length; j++){
lc_child[j].addEventListener('mouseout',closeLabel_icon, false);
}// end for
}// end if
}//end function
window.onload = function(){
Add_DOM_listeners();
}
Suggested solution
I think that, unless there's other logic not described in the question, the entire JavaScript section can be replaced by the following CSS declaration:
/* By default the icon is not rendered: */
.lb-a-icon {
display: none;
}
/* When <li> is hovered, its icon child is displayed: */
.lb_li:hover .lb-a-icon {
display: block;
}
Demo: http://jsfiddle.net/CHTKM/
You can also play around with visibility: hidden; and visibility: visible;
Reason of TypeError
The event.target references an element the cursor is pointing to. Suppose you add the event listener to your <li> that has the following HTML structure...
<li class="lb_li">
<div class="lb-title">Label List 1</div>
<div class="lb-a-icon">
<img src="chevron_expand.png">
</div>
</li>
Now when you hover the mouse over <li> contents, the event.target could point, for example, to <div class="lb-title">Label List 1</div> which doesn't have any elements with lb-a-icon class. Attempting to get those non-existing elements results in undefined which, obviously, has no style property and thus an error is thrown.
To solve the issue you can use this (but not in IE6-8!), which references the element to which the event listener is added.
function showLabel_icon() {
// In this particular case "this" is <li class="lb_li">
this.getElementsByClassName('lb-a-icon')[0].style.display = 'block';
}
JavaScript advice
If you want to stick with JavaScript, instead of:
window.onload = function () {
Add_DOM_listeners();
}
It's much better to write:
window.addEventListener('load', add_DOM_listeners);
Doing it this way, you won't have the overhead of creating an additional function. You will also avoid inadvertently overriding any other onload listener present on your page.
Also, your Add_DOM_listeners function can be reduced to the following:
function Add_DOM_listeners() {
var labelList = document.getElementById('label-list'),
labelChildren = labelList.getElementsByClassName('lb_li'),
ii = labelChildren.length,
i;
for (i = 0; i < ii; i += 1) {
labelChildren[i].addEventListener('mouseover', showLabel_icon);
labelChildren[i].addEventListener('mouseout', closeLabel_icon);
}
}
Compatibility
For IE6-8, of course, you'll need attachEvent and window.event.srcElement.

Categories