jQuery calculation doesn't add up as expected when toggling height - javascript

I have the following function for calculating the height of .node. It then takes away the height of a possible image, .node-image, from the height of the .node, and sets a column, .node-content-column to have a height that is the difference (i.e. 500 - 50 = 450; column becomes 450 in height).
function initColumnSizer() {
imageHeight = $('.node-image').outerHeight(true);
resizeHeight = ($('.node').outerHeight() + 75) - imageHeight;
$('.node-content-column').removeAttr('style');
$('.node-content-column').css('min-height', resizeHeight);
$('.node-content-column').css('height', 'auto !important');
$('.node-content-column').css('height', resizeHeight);
}
This function gets called on page load, and resizes .node-content-column as expected.
It also gets called when a div within .node is toggled using jQuery.toggle(), but this calculation returns a larger number everytime, instead of reverting back to the original once this toggle is reverted.
Can anyone see where I am going wrong with this calculation? Or if I am going about it the wrong way?
Thanks in advance!
Karl

1) Maybe the problem is in outerHeight() function (it takes into account padding and border). Try using just height or clientHeight:
var img = document.getElementById('imageid');
//or however you get a handle to the IMG
var width = img.clientWidth;
var height = img.clientHeight;
2) why do you need to cleanup the whole elements' style?
and then you try to assign height = auto, and after that: height = resizeHeight - what's the purpose for that ? check the logic of your code.

outerHeight(true) will return height + padding + border + margin. Possibly, you might want to use height() ?

Most possible is that "larger number everytime" have always constant difference -- for example 75.
May be you just have some dependecies between .node-content-column and .node?
If your nodes like .node-content-column, .node and .node-image are all singles, then it's better to use IDs for them -- not CSS classes.

Related

How to obtain effective iframe height [duplicate]

How do you get the rendered height of an element?
Let's say you have a <div> element with some content inside. This content inside is going to stretch the height of the <div>. How do you get the "rendered" height when you haven't explicitly set the height. Obviously, I tried:
var h = document.getElementById('someDiv').style.height;
Is there a trick for doing this? I am using jQuery if that helps.
Try one of:
var h = document.getElementById('someDiv').clientHeight;
var h = document.getElementById('someDiv').offsetHeight;
var h = document.getElementById('someDiv').scrollHeight;
clientHeight includes the height and vertical padding.
offsetHeight includes the height, vertical padding, and vertical borders.
scrollHeight includes the height of the contained document (would be greater than just height in case of scrolling), vertical padding, and vertical borders.
It should just be
$('#someDiv').height();
with jQuery. This retrieves the height of the first item in the wrapped set as a number.
Trying to use
.style.height
only works if you have set the property in the first place. Not very useful!
NON JQUERY since there were a bunch of links using elem.style.height in the top of these answers...
INNER HEIGHT:
https://developer.mozilla.org/en-US/docs/Web/API/Element.clientHeight
document.getElementById(id_attribute_value).clientHeight;
OUTER HEIGHT:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement.offsetHeight
document.getElementById(id_attribute_value).offsetHeight;
Or one of my favorite references: http://youmightnotneedjquery.com/
I use this to get the height of an element (returns float):
document.getElementById('someDiv').getBoundingClientRect().height
It also works when you use the virtual DOM. I use it in Vue like this:
this.$refs['some-ref'].getBoundingClientRect().height
For a Vue component:
this.$refs['some-ref'].$el.getBoundingClientRect().height
You can use .outerHeight() for this purpose.
It will give you full rendered height of the element. Also, you don't need to set any css-height of the element. For precaution you can keep its height auto so it can be rendered as per content's height.
//if you need height of div excluding margin/padding/border
$('#someDiv').height();
//if you need height of div with padding but without border + margin
$('#someDiv').innerHeight();
// if you need height of div including padding and border
$('#someDiv').outerHeight();
//and at last for including border + margin + padding, can use
$('#someDiv').outerHeight(true);
For a clear view of these function you can go for jQuery's site or a detailed post here.
it will clear the difference between .height() / innerHeight() / outerHeight()
style = window.getComputedStyle(your_element);
then simply: style.height
Definitely use
$('#someDiv').height() // to read it
or
$('#someDiv').height(newHeight) // to set it
I'm posting this as an additional answer because theres a couple important things I just learnt.
I almost fell into the trap just now of using offsetHeight. This is what happened :
I used the good old trick of using a debugger to 'watch' what properties my element has
I saw which one has a value around the value I was expecting
It was offsetHeight - so I used that.
Then i realized it didnt work with a hidden DIV
I tried hiding after calculating maxHeight but that looked clumsy - got in a mess.
I did a search - discovered jQuery.height() - and used it
found out height() works even on hidden elements
just for fun I checked the jQuery implementation of height/width
Here's just a portion of it :
Math.max(
Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]),
Math.max(document.body["offset" + name], document.documentElement["offset" + name])
)
Yup it looks at BOTH scroll and offset. If that fails it looks even further, taking into account browser and css compatibility issues. In other words STUFF I DONT CARE ABOUT - or want to.
But I dont have to. Thanks jQuery!
Moral of the story : if jQuery has a method for something its probably for a good reason, likely related to compatibilty.
If you haven't read through the jQuery list of methods recently I suggest you take a look.
I think the best way to do this in 2020 is to use vanilla js and getBoundingClientRect().height;
Here's an example
let div = document.querySelector('div');
let divHeight = div.getBoundingClientRect().height;
console.log(`Div Height: ${divHeight}`);
<div>
How high am I? 🥴
</div>
On top of getting height this way, we also have access to a bunch of other stuff about the div.
let div = document.querySelector('div');
let divInfo = div.getBoundingClientRect();
console.log(divInfo);
<div>What else am I? 🥴</div>
I made a simple code that doesn't even need JQuery and probably gonna help some people.
It gets the total height of 'ID1' after loaded and use it on 'ID2'
function anyName(){
var varname=document.getElementById('ID1').offsetHeight;
document.getElementById('ID2').style.height=varname+'px';
}
Then just set the body to load it
<body onload='anyName()'>
document.querySelector('.project_list_div').offsetHeight;
Hm we can get the Element geometry...
var geometry;
geometry={};
var element=document.getElementById(#ibims);
var rect = element.getBoundingClientRect();
this.geometry.top=rect.top;
this.geometry.right=rect.right;
this.geometry.bottom=rect.bottom;
this.geometry.left=rect.left;
this.geometry.height=this.geometry.bottom-this.geometry.top;
this.geometry.width=this.geometry.right-this.geometry.left;
console.log(this.geometry);
How about this plain JS ?
So is this the answer?
"If you need to calculate something but not show it, set the element to visibility:hidden and position:absolute, add it to the DOM tree, get the offsetHeight, and remove it. (That's what the prototype library does behind the lines last time I checked)."
I have the same problem on a number of elements. There is no jQuery or Prototype to be used on the site but I'm all in favor of borrowing the technique if it works. As an example of some things that failed to work, followed by what did, I have the following code:
// Layout Height Get
function fnElementHeightMaxGet(DoScroll, DoBase, elementPassed, elementHeightDefault)
{
var DoOffset = true;
if (!elementPassed) { return 0; }
if (!elementPassed.style) { return 0; }
var thisHeight = 0;
var heightBase = parseInt(elementPassed.style.height);
var heightOffset = parseInt(elementPassed.offsetHeight);
var heightScroll = parseInt(elementPassed.scrollHeight);
var heightClient = parseInt(elementPassed.clientHeight);
var heightNode = 0;
var heightRects = 0;
//
if (DoBase) {
if (heightBase > thisHeight) { thisHeight = heightBase; }
}
if (DoOffset) {
if (heightOffset > thisHeight) { thisHeight = heightOffset; }
}
if (DoScroll) {
if (heightScroll > thisHeight) { thisHeight = heightScroll; }
}
//
if (thisHeight == 0) { thisHeight = heightClient; }
//
if (thisHeight == 0) {
// Dom Add:
// all else failed so use the protype approach...
var elBodyTempContainer = document.getElementById('BodyTempContainer');
elBodyTempContainer.appendChild(elementPassed);
heightNode = elBodyTempContainer.childNodes[0].offsetHeight;
elBodyTempContainer.removeChild(elementPassed);
if (heightNode > thisHeight) { thisHeight = heightNode; }
//
// Bounding Rect:
// Or this approach...
var clientRects = elementPassed.getClientRects();
heightRects = clientRects.height;
if (heightRects > thisHeight) { thisHeight = heightRects; }
}
//
// Default height not appropriate here
// if (thisHeight == 0) { thisHeight = elementHeightDefault; }
if (thisHeight > 3000) {
// ERROR
thisHeight = 3000;
}
return thisHeight;
}
which basically tries anything and everything only to get a zero result. ClientHeight with no affect. With the problem elements I typically get NaN in the Base and zero in the Offset and Scroll heights. I then tried the Add DOM solution and clientRects to see if it works here.
29 Jun 2011,
I did indeed update the code to try both adding to DOM and clientHeight with better results than I expected.
1) clientHeight was also 0.
2) Dom actually gave me a height which was great.
3) ClientRects returns a result almost identical to the DOM technique.
Because the elements added are fluid in nature, when they are added to an otherwise empty DOM Temp element they are rendered according to the width of that container. This get weird, because that is 30px shorter than it eventually ends up.
I added a few snapshots to illustrate how the height is calculated differently.
The height differences are obvious. I could certainly add absolute positioning and hidden but I am sure that will have no effect. I continued to be convinced this would not work!
(I digress further) The height comes out (renders) lower than the true rendered height. This could be addressed by setting the width of the DOM Temp element to match the existing parent and could be done fairly accurately in theory. I also do not know what would result from removing them and adding them back into their existing location. As they arrived through an innerHTML technique I will be looking using this different approach.
* HOWEVER * None of that was necessary. In fact it worked as advertised and returned the correct height!!!
When I was able to get the menus visible again amazingly DOM had returned the correct height per the fluid layout at the top of the page (279px). The above code also uses getClientRects which return 280px.
This is illustrated in the following snapshot (taken from Chrome once working.)
Now I have noooooo idea why that prototype trick works, but it seems to. Alternatively, getClientRects also works.
I suspect the cause of all this trouble with these particular elements was the use of innerHTML instead of appendChild, but that is pure speculation at this point.
offsetHeight, usually.
If you need to calculate something but not show it, set the element to visibility:hidden and position:absolute, add it to the DOM tree, get the offsetHeight, and remove it. (That's what the prototype library does behind the scenes last time I checked).
Sometimes offsetHeight will return zero because the element you've created has not been rendered in the Dom yet. I wrote this function for such circumstances:
function getHeight(element)
{
var e = element.cloneNode(true);
e.style.visibility = "hidden";
document.body.appendChild(e);
var height = e.offsetHeight + 0;
document.body.removeChild(e);
e.style.visibility = "visible";
return height;
}
If you are using jQuery already, your best bet is .outerHeight() or .height(), as has been stated.
Without jQuery, you can check the box-sizing in use and add up various paddings + borders + clientHeight, or you can use getComputedStyle:
var h = getComputedStyle(document.getElementById('someDiv')).height;
h will now be a string like a "53.825px".
And I can't find the reference, but I think I heard getComputedStyle() can be expensive, so it's probably not something you want to call on each window.onscroll event (but then, neither is jQuery's height()).
With MooTools:
$('someDiv').getSize().y
If i understood your question correctly, then maybe something like this would help:
function testDistance(node1, node2) {
/* get top position of node 1 */
let n1Pos = node1.offsetTop;
/* get height of node 1 */
let n1Height = node1.clientHeight;
/* get top position of node 2 */
let n2Pos = node2.offsetTop;
/* get height of node 2 */
let n2Height = node2.clientHeight;
/* add height of both nodes */
let heightTogether = n1Height + n2Height;
/* calculate distance from top of node 1 to bottom of node 2 */
let actualDistance = (n2Pos + n2Height) - n1Pos;
/* if the distance between top of node 1 and bottom of node 2
is bigger than their heights combined, than there is something between them */
if (actualDistance > heightTogether) {
/* do something here if they are not together */
console.log('they are not together');
} else {
/* do something here if they are together */
console.log('together');
}
}
Have you set the height in the css specifically? If you haven't you need to use offsetHeight; rather than height
var h = document.getElementById('someDiv').style.offsetHeight;

Repeatedly reduce the width of a div

I need the width of a specific <div> to get smaller by 50px every time a JavaScript function is called.
I tried
document.getElementById("Zivot").style.width = "100px";
But that just sets the width, and doesn't add or subtract it.
Use this code. Get the width using offsetWidth and reduce it by 50px every time.
var element = document.getElementById('Zivot');
element.style.width = (element.offsetWidth - 50) + 'px';
A pure Javascript way of getting this working-
var zivotID = document.getElementById("Zivot");
zivotID.style.width = zivotID.offsetWidth - 50;
document.getElementById("Zivot").style.width or myID.style.width - Here you actually set the value of width. I mean, you wait for a value to be given so that you can set.
document.getElementById("Zivot").offsetWidth or myID.offsetWidth - This gets the width of the div/element.
Some reference links-
How to find the width of a div using raw Javascript?
HTMLElement.offsetWidth
How do I retrieve an HTML element's actual width and height?
Hope it helps :)
var currentWidth = $('#Zivot').width();
$('#Zivot').css('width', currentWidth - 50 + 'px');

JavaScript get size of content box

I was using padding to restrict the size of the content-box. I need a way to get the size of the content box width and hight in pixels.
I'm open to work around's like nesting elements, pseudo-elements, trying out something like flex box setups.
However, a vanilla JavaScript way to get these values is the subject of the question.
Example: http://codepen.io/anon/pen/lbzJi
Taken from the answer to a similar question; you can use window.getComputedStyle(element, null).getPropertyValue('css-property'); to obtain the value of a computed CSS property. In your case, you can use this for the properties padding-left, padding-right, padding-top and padding-bottom.
For example, to compute the height of the content box of your "box" div you can do something similar to the following where I assume the padding is specified as an integer (hence the parseInt);
function property(e, p) {
return parseInt(window.getComputedStyle(e, null).getPropertyValue(p));
}
var box = document.getElementById('box');
var paddingTop = property(box, 'padding-top');
var paddingBottom = property(box, 'padding-bottom');
var contentHeight = box.clientHeight - paddingTop - paddingBottom;
Try this using jquery: http://codepen.io/anon/pen/shoun
$(document).ready(function(){
$("pre").append("Total Height = " + ($("#box").height() - parseInt($("#box").css("padding-top"))));
});
Well, you could try:
element.clientHeight
element.clientWidth
-or-
element.offsetWidth
element.offsetHeight
depending on what you want, but we'd need some code to really help you out.

Javascript function to find total page height

I'm after a simple javascript function that will detect the total height of my web page which is dynamic and apply it to the height of a div which is the page background. Would it be possible to implement it?
The div is called bg...
Any ideas? Thanks in advance
Try:
var height = body.offsetHeight ? body.offsetHeight : html.offsetHeight;
document.getElementById ('divID').style.height = height + 'px';
Here an useful documentation:
http://www.quirksmode.org/dom/w3c_cssom.html
Im using currently following code to do that:
var getBodyHeight = function () {
var d = document,
bd = d.body,
dd = d.documentElement,
max = Math.max(
bd.scrollHeight,
bd.offsetHeight,
bd.clientHeight,
dd.offsetHeight,
dd.scrollHeight,
dd.clientHeight
);
return max;
};
This is what I use to figure out the height of content in iFrame for the purpose of adjusting it properly.
var body = document.body,
html = document.documentElement,
height = 0;
height = body.offsetHeight;
if(height === 0){
height = html.offsetHeight;
}
The reason for checking the body first is that the height of html is actually the height of the iFrame, which could be bigger than the content itself. However, in certain cases such as when body has no height, then it falls back to use height of html instead.
For your case, you might want to experiment with a similar scheme. I'm not sure why you have to use a div to set background so I can't really suggest a better alternative (if any).
Solution based on the comment below:
What you can do is the following. Have a div inside the main container with position absolute, width/height 100% and z-index -1. Then it will always be the correct size no matter how large the contain grow or shrink. With this approach, you will have to make sure that container always has size. This is a pure CSS solution, which might be simpler than using Javascript to adjust.
var height = screen.height;
var width = screen.width;
var resolution = width+"x"+height;
alert(resolution);
it gives the resolution of the screen.i know you want page height and width but it will help you later in web development. i am using it as most important part for my web!

Animate DIV to full height and toggle back to defined height

I am trying to animate the div to its full height when a button is pressed and come back to its original height if the button is clicked again. The full height of the div is auto as it contains text with different word counts. I tried doing the below codes but it does not work properly.
The CSS :
.category_brief{
text-align:justify;
height:100px;
overflow:hidden;
}
Example 1 : This code does not animate the div when opening to full height , but animates while coming back to old height.
$(".slide").toggle(function(){
$('.category_brief').animate({height:'100%'},200);
},function(){
$('.category_brief').animate({height:100},200);
});
Example 2 : The output of this code is the same as of Example 1
var toggle = true, oldHeight = 0;
$('.slide').click(function(event) {
event.preventDefault();
var $ele = $('.category_brief');
var toHeight = ((toggle = !toggle) ? oldHeight : newHeight);
oldHeight = $ele.height();
var newHeight = $ele.height('auto').height();
$ele.animate({ height: toHeight });
});
Example 3 : This code animates the div to its full height but does not toggle.
var slide = $('.slide');
var slidepanel = $('.category_brief');
// On click, animate it to its full natural height
slide.click(function(event) {
event.preventDefault();
var oldHeight, newHeight;
// Measure before and after
oldHeight = slidepanel.height();
newHeight = slidepanel.height('auto').height();
// Put back the short height (you could grab this first
slidepanel.height(oldHeight);
slidepanel.animate({height: newHeight + "px"});
});
If possible please provide a bit explanation also as i am a newbie..
Update : Solved by the idea from #chazm..
#chazm : thanks for the idea. I got it working by combining 1st and 3rd example ... Here is the code in case anyone needs it .
var slidepanel = $('.category_brief');
$(".slide").toggle(function(){
var oldHeight, newHeight;
// Measure before and after
oldHeight = slidepanel.height();
newHeight = slidepanel.height('auto').height();
// Put back the short height (you could grab this first
slidepanel.height(oldHeight);
slidepanel.animate({height: newHeight + "px"})
},function(){
$('.category_brief').animate({height:100},300);
});
Working with 'auto' height it always quite tricky. I think there are different issues in your examples.
1) Browser can't define correct 100% height. Possible solutions - define height to all its parents. Either set it to 100% (till html tag) or set closest parent as relative (because height is calculated from closest relative parent). If you want to animate div to 100% of the entire page - think of the absolute positioning
2)The same as above i assume
3)When this code supposed to toggle back it can't determine that it should become lower that it is now. Not absolutely sure why though. Probably because 'auto' height from 100% is set to something wrong. You may check in firebug what value it has on the computed tab after that function is toggled back. Probably it will give you a clue
Try to combine 2) and 3). The idea - if toggle is true (it shoud be lowered) then set newHeight = slidepanel.height('100').
The solution depends on your implementation needs. If you know that at first the div should be 100px etc in height and when you click, it maximizes to an unknown height, the following solution would work. If you had a structure similar to
<div class="outer">
<div class="wrapper">Content of unknown length here</div>
</div>
and css
div.wrapper { position:relative; height:100px; overflow:hidden; }
div.outer { position:absolute; height:auto; }
then you'd get a div that is 100px in height, with the content that doesn't fit in 100px cut off. Now when you press the desired button, you could get the height of the wrapper div, since it is a long as it's content is (even though you only see the top 100px) and set the outer div's height according to it. Like so
var newHeight = $('div.wrapper').height();
$('div.outer').animate({height:newHeight},200);
Which would then animate the outer div to display the whole contents. When you click the button again, you could just do
$('div.outer').animate({height:'100px'},200);
And you would again have only the 100px height.

Categories