Stopping jQuery equal height divs from calculating hidden content - javascript

I am using the following jQuery to giv certain divs with the id's #main, #sidebar, #side-event equal height. On most pages, I am using .hide(); to toggle information within the content section of the site. The problem is when JS caluclates the height of the #main div, it's calculating all of the hidden content as well, which I do not want. How can I alter my code so that the height is equal to the tallest div, and not include the hidden information in the equation? In addition I added the code I am using to hide the information upon page load. Here is my page from the site for referencing the issue. Hoping someone can help me with this issue.
http://shadowfaxdigital.com/cdi/events/mba-essentials-business-design-workshops/
Calculating height:
$("#main, #sidebar, #side-event").addClass("heights");
var highestCol = Math.max($('#main').height(),$('#sidebar').height(), $("#side-event").height());
$('.heights').height(highestCol);
Code used to hide the content in the toggles:
//jQuery toggle
$(".toggle_container").hide();
$("h2.trigger").click(function(){
$(this).toggleClass("active").next().slideToggle("slow");
});

you can add the visible selector, this will check if the element has display:none or opacity:0
var $sfd = jQuery.noConflict();
var cols = $sfd('#main:visible, #sidebar:visible, #side-event:visible');
var maxHeight = 0;
$(cols).each(function(){
$(this).addClass('heights');
maxHeight = Math.max($(this).height(), maxHeight);
});
$sfd('.heights').height(maxHeight);

It's not entirely clear what exactly you're asking for help with. .height() will only include the height of child elements that take up space in the layout. So an item that was hidden with .hide() will be marked display:none and will not be included in the height of any parent elements. But an item that has a zero opacity or visibility:hidden will take up space in the layout and will be included in a parent's height.
In jQuery, you can see if anything is visible with:
$("#main").is(":visible");
Or, you can put it directly into a selector to only include visible items:
$("#main:visible")
So, you could change your code to something like this if you only want to include the visible items in your selector:
var visibleItems = $("#main:visible, #sidebar:visible, #side-event:visible");
var highestCol = Math.max.apply(this, visibleItems.map(function() {
return $(this).height();
}).get());

I ran into this issue aswell today. Googled alot and found this thread. Seems this wasn't properly solved, therefore I'm posting my solution:
My issue was that the height-adjusting script was calculating the heights before the elements were successfully hid with jQuery, I therefore copied my height-equalizing script into a $(document).ready(function() {} );
Like this:
$(document).ready(function()
{
if ($('.sidebar').height() < $('#mainwindow').height())
{
var mainwindowHeight = $('#mainwindow').height();
$(".sidebar").css('height', mainwindowHeight+8+'px');
}
});
This solved it for me.
Hope this helps someone.

Related

Automatically expand height of DIV according to the div displayed

I am using a div sliding thing, as you can see in this fiddle example
$(document).ready(function() {
$("#moving").click(function(){
$("#moving").toggleClass("left");
$("#right").toggleClass("right");
});
});
Here is the complexity that I am using:
I have 12 Right Side DIVS, they are all set display: none, except one.
On the moving DIV I have a list of links to other hidden DIVs. They are shown or hidden with show or hide jQuery function....
It all works with height set to 700px (so I can accomodate a lot of content)
How can I make the height automatic according to the content? If, let's say Div number 5 has more content and scroll is required... how can I expand it and show it?
I hope you guys can help me. Thank you very much in advance.
Using jQuery something like this will use the largest of the children's heights for all the children div's of #wrapper.
$(window).on('load', function () {
var maxHeight = 0;
jQuery("#wrapper > div").each(function () {
var thisHeight = jQuery(this).height();
maxHeight = thisHeight > maxHeight ? thisHeight : maxHeight;
}).height(maxHeight);
});
Added a sample here:
https://jsfiddle.net/mq2c2129/15/

Setting up max-height and not overflow

Some background: I have a div in which elements of different height will be added to and I'm in need of achieving the following:
The div has a max-height property, when the different elements that are added to the Div overlap such height, I can't have the div "overflowing (putting a scrollbar on it)". Instead, I need to detect when this happens, so I can create ANOTHER div in which I could put the rest of the elements. Attached is an image that I hope illustrates what I'm trying to do.
Use jQuery:
var maxHeight = $(".someElement").css("max-height");
var height = 0;
$(".elements").each(function(){
height += $(this).height();
if(height >= maxHeight){
//create new div here and put the rest of the elements there
height = 0; //so you can continue with the loop and creating more divs.
}
});
I have a pseudo function below that I think could get you started on the right track. You will have to fill in the appropriate information for it.
$(elements).each(function() {
var currentDiv = $(currentDiv);
if($(currentDiv ).height() > MAX_HEIGHT)
{
$(currentDiv).insertAfter(newDiv);
currentDiv = $(newDiv);
}
$(currentDiv).append(element);
});
You'll have to keep track of the current div you are adding info to. Just add info like normal but when it overflows you should insertAfter it a new div and change the current div variable to be that one and then continue appending again.
To test if a div is currently overflowing, compare it's scrollHeight to its height.
With jQuery
if ($(obj)[0].scrollHeight > $(obj).height()) {
// do stuff
}
In this case though, you'll probably want to test against the css max-height before adding content. To do this (again in jQuery) load the content you plan to add into a variable so you can check its height before adding it to the document.
var content = // your content here
if ($(container).height() + content.height() > parseInt($(container).css("max-height"), 10)) {
// this means it would overflow, so do stuff
} else {
// no overflow here
$(container).append(content);
}
Here's a quick fiddle. http://jsfiddle.net/k0g47xdr/2/
edit:
the parseInt call around .css("max-height") is to convert from the text format it comes in to a regular number. As written it assumes the value is in px, not em or percent.

Making the column height same and remove extra content

I have a question, my webpage has many div section and have multiple ul li.
It is 2 column design and what i need to do is to set the same height for both corresponding div section.
For example check the image, it is one section and what i want is to set the height for the shortest div and remove the large div content. Is this possible to do?
I checked on internet but what i am getting is to set the both column height but unable to find how can i remove the content.
The right image is what i want.
Please help :)
Assuming you're using jQuery, try this:
var $targets = $('.awesomeClass'),
targetHeight = $targets.first().height();
$targets.each(function() {
var $this = $(this);
if( $this.height() < targetHeight ) {
targetHeight = $this.height();
}
});
$targets.height( targetHeight );
This code will set the height of all matching elements to the height of the shortest member.
Just make sure all your target elements have the class awesomeClass, or whatever class you decide to use, and add an overflow: hidden; so the overflowing elements are cut off. This method will remain functional even if you decide to change the number of elements etc.
Removes elements until the first div height is less than or equal to the second one:
while($('#div1').height() > $('#div2').height()) {
$('#div1').find('li:last-child').remove();
}
Say you have following two div's on the page as:
<div class="left">
<ul>/<ul>
</div>
<div class="right">
<ul></ul>
</div>
You want both of them to have the same height i.e. the minimum out of the two.
Well, its simple with following jQuery Code:
var leftHeight = $(".left").height();
var rightHeight = $(".right").height();
if(leftHeight > rightHeight)
{
$(".left").height(rightHeight);
}
else
{
$(".right").height(leftHeight);
}
Of course you need to set Overflow-y:hidden, for the div and ul, so the scroll bar doesn't appear.
It's better to set explicit height, then to remove html elements

Test if element can be seen by the user on an html page

Is there any way to know if an element is visible on an html page?
Like this:
One can probably do it considering the horizontal/vertical scrolling positions, the width/height of the browser window and the position/size of the element on the page, but I have little experience in jQuery so I don't know how to do it. And there might be a simple function one can call, I don't know.
You can use the .is(':visible') selectors to check if an element is currently visible in the DOM.
Edit:
However, as #BenM mentioned, this doesn't check if the elements on your page are actually out of your scrollable range - a great little plugin you could use in that case would be Viewport Selectors for jQuery.
Here is some code that I use to do this. It has been tested to work great.
function isVisible($obj) {
var top = $(window).scrollTop();
var bottom = top + $(window).height();
var objTop = $obj.offset().top;
var objBottom = objTop + $obj.height();
if(objTop < bottom && objBottom > top) {
//some part of $obj is visible on the screen.
//does not consider left/right, only vertical.
}
}

Find the "potential" width of a hidden element

I'm currently extending the lavalamp plugin to work on dropdown menus but I've encountered a small problem. I need to know the offsetWidth of an element that is hidden. Now clearly this question makes no sense, rather what I'm looking for is the offsetWidth of the element were it not hidden.
Is the solution to show it, grab the width, then hide again? There must be a better way...
The width of an element that has CSS visibility: hidden is measurable. It's only when it's display: none that it's not rendered at all. So if it's certain the elements are going to be absolutely-positioned (so they don't cause a layout change when displayed), simply use css('visibility', 'hidden') to hide your element instead of hide() and you should be OK measuring the width.
Otherwise, yes, show-measure-hide does work.
The only thing I can think of is to show it (or a clone of it) to allow retrieval of the offsetWidth.
For this measurement step, just make its position absolute and its x or y value a big negative, so it will render but not be visible to the user.
You can use the following function to get the outer width of an element that is inside a hidden container.
$.fn.getHiddenOffsetWidth = function () {
// save a reference to a cloned element that can be measured
var $hiddenElement = $(this).clone().appendTo('body');
// calculate the width of the clone
var width = $hiddenElement.outerWidth();
// remove the clone from the DOM
$hiddenElement.remove();
return width;
};
You can change .outerWidth() to .offsetWidth() for your situation.
The function first clones the element, copying it to a place where it will be visible. It then retrieves the offset width and finally removes the clone. The following snippet illustrates a situation where this function would be perfect:
<style>
.container-inner {
display: none;
}
.measure-me {
width: 120px;
}
</style>
<div class="container-outer">
<div class="container-inner">
<div class="measure-me"></div>
</div>
</div>
Please be aware that if there is CSS applied to the element that changes the width of the element that won't be applied if it's a direct descendant of body, then this method won't work. So something like this will mean that the function doesn't work:
.container-outer .measure-me {
width: 100px;
}
You'll either need to:
change the specificity of the CSS selector ie. .measure-me { width: 100px; }
change the appendTo() to add the clone to a place where your CSS will also be applied to the clone. Ensure that where ever you do put it, that the element will be visible: .appendTo('.container-outer')
Again, this function assumes that the element is only hidden because it's inside a hidden container. If the element itself is display:none, you can simply add some code to make the clone visible before you retrieve it's offset width. Something like this:
$.fn.getHiddenOffsetWidth = function () {
var hiddenElement $(this)
width = 0;
// make the element measurable
hiddenElement.show();
// calculate the width of the element
width = hiddenElement.outerWidth();
// hide the element again
hiddenElement.hide();
return width;
}
This would work in a situation like this:
<style>
.measure-me {
display: none;
width: 120px;
}
</style>
<div class="container">
<div class="measure-me"></div>
</div>
Two options:
position the element outside the viewport (ex: left:-10000px)
use visibility: hidden or opacity: 0 instead of hide().
Either way will work as hiding the element but still being able to get the computed width. Be careful with Safari on thi, it's awfully fast and sometimes too fast...
Actual jQuery plugin!
Usage:
console.log('width without actual: ' + $('#hidden').width());
console.log('width with actual: ' + $('#hidden').actual('width'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script>
<div style="width: 100px; display: none;">
<div id="hidden"></div>
</div>
If you know the element to be the full width of a parent element another approach is to create a recursive method:
es5:
var getWidth;
getWidth = function($el){
return $el.offsetWidth || getWidth($el.parentElement);
}
var width = getWidth(document.getElementById('the-element'));
es6:
let getWidth
getWidth = ($el) => $el.offsetWidth || getWidth($el.parentElement)
const width = getWidth(document.getElementById('the-element'))
What I did was ;
by the time hiding that element, stored its width in its dataset.
It only will work for you if you can hide programmatically.
ie.
When Hiding ;
var elem = $("selectorOfElement");
elem.dataset.orgWidth = elem.clientWidth;
Later when getting ;
var elem = $("selectorOfElement");
var originalWidthWas = elem.dataset.orgWidth;
thats because its hidden via display: none; What ive done in the past is to make a "reciever" div which i use absolute positioning on to get it off the page. Then i load the new element into that, grab the dimensions and then remove it when im done - then remove the reciever when im done.
Another thing you can do is to not use hide(); but to instead set visibility: hidden; display: ; However this means the blank area will be rendered wherever the node is attached.
var $hiddenElement = $('#id_of_your_item').clone().css({ left: -10000, top: -10000, position: 'absolute', display: 'inline', visibility: 'visible' }).appendTo('body');
var width = parseInt($hiddenElement.outerWidth());
$hiddenElement.remove();
I try to find working function for hidden element but I realize that CSS is much complex than everyone think. There are a lot of new layout techniques in CSS3 that might not work for all previous answers like flexible box, grid, column or even element inside complex parent element.
flexibox example
I think the only sustainable & simple solution is real-time rendering. At that time, browser should give you that correct element size.
Sadly, JavaScript does not provide any direct event to notify when element is showed or hidden. However, I create some function based on DOM Attribute Modified API that will execute callback function when visibility of element is changed.
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
For more information, Please visit at my project GitHub.
https://github.com/Soul-Master/visible.event.js
demo: http://jsbin.com/ETiGIre/7
Sorry I am late to this conversation. I am surprised no one has mentioned getComputedStyle. (Note this only works if the CSS sets a width value)
Grab the element:
let yourEle = document.getElementById('this-ele-id');
and use the function:
getComputedStyle(yourEle).width
This returns a string so you will have to remove the numbers from the string.
This works even when the element's display style is set to none.
Other articles to read about this includes here at zellwk.com

Categories

Resources