We\'re facing a fairly scary issue in JavaScript that none of us seems to be quite capable of resolving:
How do we get the width and height of a DOM element, including
The problem here is you can't get the element size before you add this element on the page.
On your method "constructElement", you adding the element to a root element, but just on onload you adding to the page. Your property "rootElement" not have the size properties setted.
Rethink the structure of your object/method if you want to manipulate these properties.
Look my update of your fiddle
$(function ()
{
var ex = new exampleElement("Hello", "Here's text");
ex.constructElement();
document.body.appendChild(ex.rootElement);
$("<span/>")
.text(" => Width is " + $("div").width() + ", and Height is " + $("div").height())
.appendTo($("div p"));
});
You run into this often if you need to initially hide components like accordions, sliders, and other things that require bounding box information to work properly.
A simple trick is to just add css that hides the visibility of the content in question and ensures that it doesn't flicker or cause interfere with your layout.
It can be something as simple as:
{ visibility:hidden;
position:absolute;
left: -9999px;
}
And then setting position back to static or relative and visibility back to visible when you're ready to show the component.
The fiddle is here, but there's not much to it: http://jsfiddle.net/gwwar/ZqQtz/1/
Getting the rendered width and height of a box-model DOM node using javascript without actually adding it to the DOM to be displayed is not possible.
To prove this, let's walk through how the rendered height and width of a DOM node is calculated internally to the browser. I will reference how WebKit handles this since it is the most commonly used layout engine.
As the document is parsed and DOM nodes are added to the "DOM Tree", Renderers
are created for the DOM nodes that need to be displayed. This is how the "Render Tree" gets built.
Here is an excerpt from an article entitled "WebCore Rendering I – The Basics" by Dave Hyatt on the official WebKit Blog:
"Renderers are created through a process on the DOM called attachment. As a document is parsed and DOM nodes are added, a method called
attach
gets called on the DOM nodes to create the renderers.
void attach()
The
attach
method computes style information for the DOM node. If the display CSS property for the element is set to none or if the node is a descendant of an element with display: none set, then no renderer will be created."
So, in order to be efficient, the browser does not even bother computing style information for elements with display set to none. As a result, the information is not available to be accessed via javascript. However, if the display property is not set to none, the following occurs:
"During attachment the DOM queries CSS to obtain style information for an element. The resultant information is stored in an object called a RenderStyle... The RenderStyle can be accessed from a RenderObject using the style() method... One of the principal workhorse subclasses of RenderObject is RenderBox. This subclass represents objects that obey the CSS box model. These include any objects that have borders, padding, margins, width and height."
So if your use case allows for you to retrieve the box-model rendering height and width via C/C++ directly from the browser and pass it to your javascript code via some other means, then you could query the height/width methods of the RenderBox subclass of each DOM element. This is basically how the WebKit Developer Tools gets this information.
You can try this jQuery plugin : https://github.com/dreamerslab/jquery.actual
Since you'd asked for related answers...
If your DOM elements are not to be dynamically sized by it's contents, I would suggest the following workflow.
Although it can make your DOM structure a bit more bloated, it is often better off to utilize "container" objects. These objects would possess no borders, padding or margins to keep their DOM dimensions predictable. Then you can force the child to expand snuggly within it's container's bounds.
Your container object would be use for querying specific sizing and placement, since there are no extra attributes to account for size distortion.
http://jsfiddle.net/aywS6/
CSS
#container {
position: absolute;
margin:0px;
padding:0px;
width: 300px;
height: 100px;
background: #aaa;
border: 0 none;
}
#subject {
position: absolute;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
padding: 10px 20px;
background: #aaf;
}
HTML
<div id="container">
<div id="subject">
contents...
</div>
</div>
If the main problem is that you can't get the size before placing it onto the screen I would recommend creating a class that allows the div to be hidden under the page's background. This should work cross browser.
.exampleHidden{
position: absolute;
z-index: -1;
}
If you set the main background of the page's z-index to 0 then attaching the hidden class to your new element it would put it under the background. Assuming it isn't larger than your background it should be hidden for now to allow you to measure and set the height and width before actually bringing it back to the foreground by removing the .exampleHidden class.