Equal Heights JS - javascript

Good evening,
I have been using a javascript to generate equal height columns using the following JS:
<script type="text/javascript">
var maxHeight = 0;
$(".level").each(function(){
maxHeight = $(this).height() > maxHeight ? $(this).height() : maxHeight;
}).height(maxHeight);
</script>
However, I wanted to be able to add additional classes and was advised to amend my code to that shown below. One other reason was to prevent the script creating a global variable like the one above.
Now the problem is, the first class works but the additional ones don't seem to be. They are generating a height but not an equal height. Can anyone help me work out the problem?
<script type="text/javascript">
(function() {
function equalHeights(selector) {
var maxHeight = 0;
function calcEqualHeight() {
var el = $(this);
maxHeight = el.height() > maxHeight ? el.height() : maxHeight;
el.height(maxHeight);
}
selector.each(calcEqualHeight);
}
equalHeights($('.level-1'));
equalHeights($('.level-2'));
equalHeights($('.level-3'));
})();
</script>

You need to set the height after you complete the loop:
(function() {
function equalHeights(selector) {
var maxHeight = 0;
function calcEqualHeight() {
var el = $(this);
maxHeight = el.height() > maxHeight ? el.height() : maxHeight;
}
selector.each(calcEqualHeight).height(maxHeight);
}
equalHeights($('.level-1'));
equalHeights($('.level-2'));
equalHeights($('.level-3'));
})();

Related

resize bootstrap div on window resize

This is a continuation from my previous question here.
I'm using bootstrap and it doesn't arrange the div such that they have the same height.
I have solved the problem of resizing the div to same height for the children div.
But it doesn't resize in realtime i.e. when I'm resizing the window, "maxHeight" still remains the same though the function still runs when the window's resized.
Below is the function and code.
function resized(){
var maxHeight = -1;
if (size == "xs"){
$('.col-xs-12').each(function(){
$(this).height("auto");
maxHeight = 0;
});
}
if (size == "sm"){
$('.col-sm-6').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$('.col-sm-6').each(function() {
$(this).height(maxHeight);
});
}
if (size == "md"){
$('.col-md-4').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$('.col-md-4').each(function() {
$(this).height(maxHeight);
});
}
console.log("maxHeight : " + maxHeight);
};
$().ready(function(){
$(document).ready(resized)
$(window).resize(resized);
})
Thanks in advance!

Why is this only working correctly on page load?

I have a procedure
<script type="text/javascript">
function rescaleStuff ( )
{
jQuery('.children-have-equal-height').each(function(){
var children = jQuery(this).children();
var numChildren = children.length;
if (numChildren > 1)
{
var firstChild = children.first();
var maxHeight = firstChild.height();
firstChild.siblings().each(function()
{
var thisHeight = jQuery(this).height();
if (thisHeight > maxHeight)
maxHeight = thisHeight;
});
children.height(maxHeight);
}
});
}
jQuery(window).load(function() {
rescaleStuff();
});
jQuery(window).resize(function()
{
rescaleStuff();
});
</script>
which is intended to make all children of elements with class children-have-equal-height have a height equal to that of the tallest child. Why is it only working on page load, and then the height of the child elements stays the same as it was on page load?
Try setting the height to 'auto' at the begining of rescaleStuff with this code:
jQuery('.children-have-equal-height').children().height('auto')

Get the visible height of a div with jQuery

I need to retrieve the visible height of a div within a scrollable area. I consider myself pretty decent with jQuery, but this is completely throwing me off.
Let's say I've got a red div within a black wrapper:
In the graphic above, the jQuery function would return 248, the visible portion of the div.
Once the user scrolls past the top of the div, as in the above graphic, it would report 296.
Now, once the user has scrolled past the div, it would again report 248.
Obviously my numbers aren't going to be as consistent and clear as they are in this demo, or I'd just hard code for those numbers.
I have a bit of a theory:
Get the height of the window
Get the height of the div
Get the initial offset of the div from the top of the window
Get the offset as the user scrolls.
If the offset is positive, it means the top of the div is still visible.
if it's negative, the top of the div has been eclipsed by the window. At this point, the div could either be taking up the whole height of the window, or the bottom of the div could be showing
If the bottom of the div is showing, figure out the gap between it and the bottom of the window.
It seems pretty simple, but I just can't wrap my head around it. I'll take another crack tomorrow morning; I just figured some of you geniuses might be able to help.
Thanks!
UPDATE: I figured this out on my own, but looks like one of the answers below is more elegant, so I'll be using that instead. For the curious, here's what I came up with:
$(document).ready(function() {
var windowHeight = $(window).height();
var overviewHeight = $("#overview").height();
var overviewStaticTop = $("#overview").offset().top;
var overviewScrollTop = overviewStaticTop - $(window).scrollTop();
var overviewStaticBottom = overviewStaticTop + $("#overview").height();
var overviewScrollBottom = windowHeight - (overviewStaticBottom - $(window).scrollTop());
var visibleArea;
if ((overviewHeight + overviewScrollTop) < windowHeight) {
// alert("bottom is showing!");
visibleArea = windowHeight - overviewScrollBottom;
// alert(visibleArea);
} else {
if (overviewScrollTop < 0) {
// alert("is full height");
visibleArea = windowHeight;
// alert(visibleArea);
} else {
// alert("top is showing");
visibleArea = windowHeight - overviewScrollTop;
// alert(visibleArea);
}
}
});
Calculate the amount of px an element (height) is in viewport
Fiddle demo
This tiny function will return the amount of px an element is visible in the (vertical) Viewport:
function inViewport($el) {
var elH = $el.outerHeight(),
H = $(window).height(),
r = $el[0].getBoundingClientRect(), t=r.top, b=r.bottom;
return Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H));
}
Use like:
$(window).on("scroll resize", function(){
console.log( inViewport($('#elementID')) ); // n px in viewport
});
that's it.
jQuery .inViewport() Plugin
jsFiddle demo
from the above you can extract the logic and create a plugin like this one:
/**
* inViewport jQuery plugin by Roko C.B.
* http://stackoverflow.com/a/26831113/383904
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : Math.min(b, H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
Use like:
$("selector").inViewport(function(px) {
console.log( px ); // `px` represents the amount of visible height
if(px > 0) {
// do this if element enters the viewport // px > 0
}else{
// do that if element exits the viewport // px = 0
}
}); // Here you can chain other jQuery methods to your selector
your selectors will dynamically listen to window scroll and resize but also return the initial value on DOM ready trough the first callback function argument px.
Here is a quick and dirty concept. It basically compares the offset().top of the element to the top of the window, and the offset().top + height() to the bottom of the window:
function getVisible() {
var $el = $('#foo'),
scrollTop = $(this).scrollTop(),
scrollBot = scrollTop + $(this).height(),
elTop = $el.offset().top,
elBottom = elTop + $el.outerHeight(),
visibleTop = elTop < scrollTop ? scrollTop : elTop,
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
$('#notification').text(`Visible height of div: ${visibleBottom - visibleTop}px`);
}
$(window).on('scroll resize', getVisible).trigger('scroll');
html,
body {
margin: 100px 0;
}
#foo {
height: 1000px;
background-color: #C00;
width: 200px;
margin: 0 auto;
}
#notification {
position: fixed;
top: 0;
left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="foo"></div>
<div id="notification"></div>
The logic can be made more succinct if necessary, I've just declared separate variables for this example to make the calculation as clear as I can.
Here is a version of Rory's approach above, except written to function as a jQuery plugin. It may have more general applicability in that format. Great answer, Rory - thanks!
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
return visibleBottom - visibleTop
}
Can be called with the following:
$("#myDiv").visibleHeight();
jsFiddle
Here is the improved code for jquery function visibleHeight: $("#myDiv").visibleHeight();
$.fn.visibleHeight = function() {
var elBottom, elTop, scrollBot, scrollTop, visibleBottom, visibleTop, height;
scrollTop = $(window).scrollTop();
scrollBot = scrollTop + $(window).height();
elTop = this.offset().top;
elBottom = elTop + this.outerHeight();
visibleTop = elTop < scrollTop ? scrollTop : elTop;
visibleBottom = elBottom > scrollBot ? scrollBot : elBottom;
height = visibleBottom - visibleTop;
return height > 0 ? height : 0;
}

Need equal height columns to resize with dynamic content

I have a script for equal height columns. I just ran into a problem where the table-filter/sort/paginate plugin can change the height of my inner window beyond the initial document load. Im not really sure how to use resize() correctly someone up for walking me through this?
/*******************************/
/* EQUAL HEIGHT COLUMNS
/*******************************/
$(window).load(function() {
var maxHeight = -1;
$('.equal').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$('.equal').each(function() {
$(this).height(maxHeight);
});
});
EDIT:
I tried to bind the resize and load like this, but did not work...
/*******************************/
/* EQUAL HEIGHT COLUMNS
/*******************************/
$(window).on("resize", function() {
var maxHeight = -1;
$('.equal').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$('.equal').each(function() {
$(this).height(maxHeight);
});
});.resize();
Try to change your code to:
$('window .equal').on('resize', function() {
var maxHeight = -1;
$('.equal').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
$(this).height(maxHeight);
});
});
EDIT: I lied, you need the jquery resize plugin for this to work!
<script src="http://github.com/cowboy/jquery-resize/raw/v1.1/jquery.ba-resize.js"></script>
Window is not resizing, it is the .equal columns that resize. attatch to their resize event.
$('.equal').on("resize", function(){
var maxHeight = -1;
$('.equal').each(function() {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$('.equal').each(function() {
$(this).height(maxHeight);
});
});
CSS
#wrapper{overflow:hidden;}
#div1{width:200px;background: red;float: left;padding-bottom:10000px;margin-bottom:-10000px;}
#div2{width:300px;background: blue;float: left;padding-bottom:10000px;margin-bottom:-10000px;}
HTML
<div id="wrapper">
<div id="div1">
a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>a<br>
</div>
<div id="div2">
a<br>a<br>a<br>a<br>
</div>
</div>
You don't need any javascript, if you think your page could have more than 10000px hieght than just increase the padding-bottom and margin-bottom in negative and maintain in same amount.

how to access a global variable in javascript?

consider this example:
/**/
var sizes;
$(window).resize(function() {
var viewportWidth = $(window).width();
//var viewportHeight = $(window).height();
if (viewportWidth > 1024) {
sizes = '320';
} else if (viewportWidth < 1024) {
sizes = '300';
}
}); /**/
jQuery(document).ready(function($) {
console.log(sizes);
$('#full_width_anything_slider').anythingSlider({
delay: sizes
});
});​
how can i have access to the sizes var inside the other method?
right now it doesn't work
thanks
sizes has no value associated with it when your document onReady function executes. In fact it will not have a value until your onResize function executes.
as long as the posted code is not wrapped in a function your declaration is global.
However if your viewportWidth is exactly 1024 sizes is never set. so do something like this:
sizes won't have a value until resize is called so set the value when you declare it and reset it when the window is resized
var sizes = $(window).width() <= 1024 ? '300' : '320';
$(window).resize(function() {
var viewportWidth = $(window).width();
sizes = $(window).width() <= 1024 ? '300' : '320';
});
be aware that global variables in general is a bad idea. In your case you might as well do
$(function() {
$('#full_width_anything_slider').anythingSlider({
delay: $(window).width() <= 1024 ? '300' : '320';
});
});​
note the first part of the code will not really work with the way you are using it since, the value is passed to anythingSlider when the document is loaded and will not change when the window is resized (it's a value not a reference). The second part won't solve this problem either but repeating the code in window.resize like below will
var setupSlider = function()
$('#full_width_anything_slider').anythingSlider({
delay: $(window).width() <= 1024 ? '300' : '320';
});
});​
$(function(){
setupSlider();
});
$(window).resize(setupSlider);
You are correctly declaring a global variable, however what you are passing into anythingSlider is a snapshot of what the value is, not a reference to a variable that contains that value. Changing the global variable will not change the delay of anythingSlider unless you re-initialize anythingSlider with the new value every time you change it (on resize)
It doesn't need to be global anyway.
$(window).resize(function() {
var sizes = '0';
var viewportWidth = $(window).width();
//var viewportHeight = $(window).height();
if (viewportWidth >= 1024) {
sizes = '320';
} else if (viewportWidth < 1024) {
sizes = '300';
}
$('#full_width_anything_slider').anythingSlider({
delay: sizes
});
});
$(document).ready(function(){
$(window).trigger("resize");
});
Note however i can't find any documentation on re-initializing this plugin or changing it's options, I'm not sure if this is the correct way to re-initialize it.
This isn't very good practice... but:
/**/
$(window).resize(function() {
updateSize();
}); /**/
function updateSize() {
var viewportWidth = $(window).width();
//var viewportHeight = $(window).height();
if (viewportWidth > 1024) {
sizes = '320';
} else if (viewportWidth <= 1024) {
sizes = '300';
}
}
jQuery(document).ready(function($) {
updateSize();
console.log(sizes);
$('#full_width_anything_slider').anythingSlider({
delay: sizes
});
});​
I assume (and hope) you'll be using sizes at a later time as well?

Categories