!important and display:none and .height() weirdness - javascript

I discovered something weird yesterday when working with a piece of JS code. I had a div that was hidden (display:none), and I was using the height of it in some calculations in JS. This was all working fine, until I added my "hidden" class (which has display:none !important).
Suddenly the height was always 0. There were no other changes than !important on the display.
After some digging I've narrowed the problem down to something I find rather weird:
#b { display:none; } /* reported height is 36 */
#c { display:none !important; } /* reported height is 0 */
I've created a very basic JSFiddle to isolate this. It also uses vanilla JS to get height, which seems to work just fine / as expected.
It seems like jQuery incorrectly reports height on invisible DIVs, and that !important behaves correctly.
Is this a bug in jQuery?

I dont think this is a bug in jQuery, jQuery sets display to block for a fraction of a second to calculate height, when you set !important even that is ovverriden, thats all.
I guess we need some more explanation
There is basically no way to get the height of an element from DOM if it doesn't have any height. So when display is none, the height is nonexistent or zero.
In jQuery if display is none, we can just set display to block for a fraction of a second to get the height, during this inline style is altered as usually done by jQuery.
<div id="something" style="display:block">/div>
And then height is taken, but at this time if you have set display:none!important in css this inline style wont work, and height calculated becomes zero.
In my personal opinion its always better not to use !important as it makes your code/presentation hard to read. Css usually has multitude of ways to override styles.
If you still want to proceed, an inline !important might override your style, and calculate the height by yourself using the jQuery show for a second technique, or just override the jQuery function to calculate height :)

Related

Aurelia JS - Kendo UI vertical sliders with height in percent?

I've taken a version of the code posted on Aurelia JS - iterate through children (kendo UI) elements? and modified it slightly, here:
https://gist.run/?id=323de53223d2ec872f17361378639556
I would basically like to express that the vertical sliders should be 90% of the height of the enclosing div; note that:
If there is no CSS height: specification, the sliders get some height, and that is it
If I set the CSS height (either via div.eqSlider in basic-use.css, or as an inline style attribute) in either px or em, then all is fine
But, if I set the CSS height in percent % (either via div.eqSlider in basic-use.css, or as an inline style attribute), or to calc(90%-10px) or similar - then the display is completely messed up, as shown on the image below:
So, is it somehow possible to set the height of these sliders to 90% of the height of the enclosing div - and if so, how?
Ok, I think I fixed it - the problem was as is typical in these cases: by default, divs and such don't have a height defined, and their height gets computed based on their contents. Since the sliders in the example are the content, without any other further specification, their height in procent then either becomes recursive, or is percentage of height 0.
Which is why then one must ensure that the entire chain from body to the enclosing div have a height defined in % (in essence, 100%, except it may show scrollbar). And I thought I had done that in the previous example - but I made a mistake in the .css: I used a .example selector (for a class), whereas I should have used #example selector (for an id); and that broke the height calculation of the chain of nested divs.
I noticed that once I assigned borders to each and every div in the nested chain; and then could correct so they all have defined height. Once all of the divs - and thus the enclosing one - have a height, then the sliders can get a height in percent, either in the .css file, or by assignment from JavaScript (via slider.wrapper.css("height", "50%");)
And so, the corrected code is now on:
https://gist.run/?id=fcfc066733ad903fa0575388a1637e4f
... and the output looks as expected:

Panes inside kendoSplitter doesn't respect "box-sizing:border-box" property

I am using kendoSplitter to create a page layout with 2 panes.
Setting the first pane size as "100px" and the remaining space for 2nd pane.
Set the padding for the panes as "5px" and set the box-sizing as "border-box".
So,expected the width of pane1 including padding is "100px"
But on page load, it applied padding on top of 100px,making the width as 110px and leading to scrollbar.
$('#splitter').kendoSplitter({
panes:[
{collapsible:true,size:'100px'},
{collapsible:true,resizable:true}
]
});
jsFiddler for this case:
http://jsfiddle.net/nagakiran/xmTJF/
But if I apply the padding after initializing kendoSplitter,it works as in this fiddler.
http://jsfiddle.net/nagakiran/hPVWf/1/
Looks it's a bug in kendoUI or am I missing something?
I don't think it is a bug. Maybe an undocumented feature or a side-effect. It seems that is a question about the order on how things are executed.
Remember that you HTML is "decorated" by KendoUI widgets so what you have defined as splitter1 is not just your div but more things (the decoration).
When you style it after invoking kendoSplitter you are actually re-decorating the result of KendoUI decoration. Since kendoSplitter sets the width of your pane to a fixed width, the padding does not add extra space.
But when you use the CSS, it runs simultaneously to kendoSplitter and when it asks for the size, it gets the wrong size.
Should KendoUI be smarter? Maybe but it's actually pretty hard guessing what CSS are going to do and apply a counter action before the CSS.
Fixed it by adding a flag in kendoSplitter which modifies the way width is assigned to splitter panes. If this flag is set,it will reduce the width that's assigned to each pane by the "padding-left+padding-right" specified for that pane.
After that found a simple solution of creating wrapper div inside each splitter-pane and set "box-sizing:border-box" and "padding:10px", which worked without issues.
Kendo has issues with box-sizing: borderbox. This post may help.

Can't get height of hidden div in Firefox

I'm trying to get the height of an initially hidden div element in Netscape and Firefox using javascript (it works fine in IE). I have tried using MyElement.scrollHeight, MyElement.offetHeight, MyElement.style.height and many different ways of setting the element initially visible, getting the height and then hiding it again. I keep getting a value of 0. Any thoughts?
Correct me if I'm wrong (Which I may be), but from doing some research, elements with display: none have no height.
To get the height, you would need to unhide them, get the height, then rehide them. Issues like this have popped up in the past like so:
jQuery: height()/width() and "display:none"
jQuery: Get height of hidden element in jQuery
(Both jQuery examples, but you get the point)
Hidden elements in Netscape is not accessible.
you can set that position with styling hole of div out of your screen. for example move it to -9999 on top left. then you can access that's attributes like height and width.
you can also visible that element and get your attribute and hide it again, but it is not usual because your element will be show a little bit of the second and user maybe feel jumping on screen.
you should position it by setting style to "absolute" and "top" to -9999px or more (depend of your project height) and then get your element height and width with DOM and anythings that you want ...

Getting div height

Firebug tells me the computed style of my_div:
width 300px
height 453.167px
Yet when I execute console.log(mydiv.style.height), it gives me an empty string, even though console.log(mydiv) logs the correct element. I am sure the page has loaded by the time this logging code is called. I'd appreciate a solution that does not use jQuery.
Depending on the browser of choice, one of these will do:
mydiv.offsetHeight
mydiv.clientHeight
Get full height of a clipped DIV
Getting the height of a div
UPDATE:
Many browser inconsistencies have been fixed since my original answer. Now the clientHeight property of a DOM element is reliable.
var height = element.clientHeight;
The Element.clientHeight read-only property is zero for elements with no CSS or inline layout boxes, otherwise it's the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin.
clientHeight can be calculated as CSS height + CSS padding - height of horizontal scrollbar (if present).
Note: This property will round the value to an integer. If you need a fractional value, use element.getBoundingClientRect().
Source: https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight
Original answer:
If you use the jQuery JS library, you can just do this:
var computed_height = $('#my_div').height();
If you use the Prototype JS library, it's similar:
var computed_height = $('my_div').getHeight();
Using a library is often the easiest & most cross-browser way to do something. Getting computed styles with vanilla js is unreliable because the properties are different across browsers.

Javascript clientHeight and alternatives

I am currently trying to modify a Javascript function that "slides in" a <div>. The script as it is requires you to define the height of the div, so it is mostly useless in dynamically filled <div>s. I found some text on the clientHeight property in javascript, but it would appear that it doesn't support <div>s with display set to none (which is the method used to slide the div in). That makes sense, as the height of that div in the client window is nothing.
Basically I was wondering what other methods you all know of, or if there's a way to get around the clientHeight = 0 when display: none.
Thanks!
Oh, and here's the function I'm using:
function getDivHeight(objName) {
return boxHeight = document.getElementById(objName).clientHeight;
}
A simple solution is to set it's visibility to "hidden" and it's display to "block" and measure it. However, some modern browsers will manage to update the page layout during this short time and you will get a nasty flicker. The easiest way to overcome this is to place the element in an absolutely positioned container with overflow set to "hidden".
I've had luck cloning the element, moving it offscreen, then displaying it to get the client height:
var original = document.getElementById(some_id);
var new_item = original.cloneNode(true);
document.body.appendChild(new_item); // item already hidden, so it won't show yet.
// you may wish to validate it is hidden first
new_item.style.position = "absolute";
new_item.style.left = "-1000px";
new_item.style.display = "block";
var height = new_item.clientHeight;
EDIT: Looking through the jQuery code, they do exactly what Tsvetomir Tsonev suggests. jQuery temporarily sets the style to "display: block; position: absolute; visibility: none", and then measures the height, swapping the properties back after the measurement.
So, it looks like you're stuck with having to do something hackish, whether it's cloning the node or risking having it flicker in some browsers... I like Tsvetomir's suggestion better than my initial hack as it, at least, doesn't involve cloning a node into the DOM that you don't need. Either way, the element must not be set to "display: none" in order to measure it's height. Isn't the DOM wonderful? :-)
EDIT 2: Also worth noting that, after jQuery gathers the height, it adds allowances for padding, margin and border sizes, so you may need to as well.
Yes, an element that is not displayed on the page has no dimensions.
It kind of makes sense. Consider an element that has been created and filled with a bunch of text, but not yet added to the document tree. How high is it? Depends on font-size. How big is font-size? Depends where in the document that div is inserted; its parent font-size would inherit through.
Similarly for an element with “display: none”. It's not rendered, so it has no dimensions. Couldn't we ask “how high would this be if it were ‘display: block’”? Turns out no, because if it were displayed, that in itself could change the dimensions of its parent block, and then the dimension of displayed elements would be inconsistent with the dimensions of non-displayed elements!
The typical solution is to unset “display: none”, measure the height of the element, and then immediately re-set “display: none”. The browser won't redraw in the middle of a bit of JavaScript, so you won't see a flicker on the page.
I nkow you guys solved this a long time ago but I thought I should share this since it quite tricky to get the height of a hidden div tag.
heres what I did after reading your post,
I placed the div i want to slide inside a 1px height div with overflow set to hidden.
you dont even need to set the display of the inner div to none since it is already there and if you use offsetHeight it should return the proper height for all browsers and you can use that height to slide your div up an down.
PEACE!!!
In IE you could try scrollHeight, but I'm not sure if it will work or if it is cross browser.

Categories

Resources