Element.getDimensions() -- Element display not set, but ancestor's display:none. Bug?

16 views
Skip to first unread message

SWilk

unread,
Feb 20, 2008, 1:10:57 PM2/20/08
to Ruby on Rails: Spinoffs
Hi,

I have found an irritating behaviour of Element.getWidth(), or a bug
maybe.


Assume we have some code:

<div style="display: none;">
<!-- many elements here: a table with about 60 inputs, labels etc -->
<input id="elem" class="a_class_that_sets_the_width" />
</div>

I read the elem.getWidth() in page onLoad event handler. The div is
invisible ATM. I need to change the width (substract 22px and add it
to padding, then place an icon over the input, to be specific). I'm
doing it from script that have to be universal, so I can't hard-code
the final width.

Unfortunatelly, the Prototype's getDimensions() method used by
getWidth() checks only if the elems.style.display is none/null, which
isn't in this case - it's inline. As the result, getDimensions returns
zeros for both width and height.

I tried to modify method to disable checking for display, so the metod
did it's "magic" to determine dimensions. Not succeded either.


Is there any way of determining dimensions of an element inside
another, invisible, element?


Regards,
Szymon Wilkołazki

kangax

unread,
Feb 20, 2008, 2:16:23 PM2/20/08
to Ruby on Rails: Spinoffs
Szymon,

There's a patch in a trac [1] which might or might not make its way
into the core. The patch makes sure #getDimensions temporarily
"displays" all "hidden" ancestors of an element, allowing clientWidth/
clientHeight (used internally) to yield the correct results.

We are deciding on some performance issues at the moment, as this
could lead to undesired overhead.

[1] http://dev.rubyonrails.org/ticket/11142

Best,
kangax

Jon L.

unread,
Feb 20, 2008, 2:24:43 PM2/20/08
to Ruby on Rails: Spinoffs
The short answer: no, you can't.

There's work-arounds, as kangax suggested.

But, dynamic width and height are based on the browser's rendering of
an element.
So, if the element is not rendered (or, hidden) then its width and
height are 0.

There aren't any "what would" values; just "what are" (hopefully, that
makes sense).

- Jon L.

SWilk

unread,
Feb 21, 2008, 4:46:16 AM2/21/08
to rubyonrail...@googlegroups.com
Hi,

kangax wrote:
>
> There's a patch in a trac [1] which might or might not make its way
> into the core. The patch makes sure #getDimensions temporarily
> "displays" all "hidden" ancestors of an element, allowing clientWidth/
> clientHeight (used internally) to yield the correct results.

I applied the patch and it works perfectly for me. Thank you.

> We are deciding on some performance issues at the moment, as this
> could lead to undesired overhead.
>

In my case it works grate and I haven't experience much performance
influence by this change but I'll test it more before I'll put patched
prototype.js into my production env.

Thanks once more for your help and much thanks for all of you who
writes prototype.

Regards
Szymon Wilkolazki


> On Feb 20, 1:10 pm, SWilk <wilkola...@gmail.com> wrote:
>> Hi,
>>
>> I have found an irritating behaviour of Element.getWidth(), or a bug
>> maybe.
>>
>> Assume we have some code:
>>
>> <div style="display: none;">
>> <!-- many elements here: a table with about 60 inputs, labels etc -->
>> <input id="elem" class="a_class_that_sets_the_width" />
>> </div>

[cut]

Szymon Wilkołazki

unread,
Feb 26, 2008, 11:48:13 AM2/26/08
to rubyonrail...@googlegroups.com
Hi,

kangax wrote:
> Szymon,
>
> There's a patch in a trac [1] which might or might not make its way

[...]


> We are deciding on some performance issues at the moment, as this
> could lead to undesired overhead.
>

Ok, I noticed performance issues with this patch. It happens in one of
my pages where I call getDimensions in onScroll event. The element
which dimensions I need to fetch is visible.

I assumed that if the element has either width or height non-zero,
then it is visible and we can safely return those values. If both
width and height are zeros, then we can't be sure if the element is
visible but width and height set to zeros or if it or it's ancestors
are invisible, so we execute the code staaky provided in his patch [1].

Please correct me if this assumption is incorrect.

I modified my copy of prototype.js (previously patched with [1],
elementgetdimensions_displaynone_anc_reccollect_unit.diff)
so it looks like this:


getDimensions: function(element) {
element = $(element);
+ var dimensions = {
+ width: element.clientWidth,
+ height: element.clientHeight
+ };
+ if (dimensions.width == 0 && dimensions.height == 0) {
var restore = element.ancestors(function(element) {
return !element.visible() }),
styles = [];
restore.push(element);

// All *Width and *Height properties give 0 on elements with
// display none,
// or when ancestors have display none, so enable those
// temporarily
restore.each(function(r) {
styles.push({
display: r.getStyle('display'),
position: r.getStyle('position'),
visibility: r.getStyle('visibility')
});
r.setStyle({display: 'block',
position: 'absolute', visibility: 'visible'});
});

- var dimensions = {
+ dimensions = {
width: element.clientWidth,
height: element.clientHeight
};
restore.each(function(r, index) {
r.setStyle(styles[index]);
});
+ }
return dimensions;
},

Now the function works fast when it is possible and provides correct
results for both hidden and shown elements.

I will optimize my code, too. It should not execute getDimensions with
every onscroll event.

> [1] http://dev.rubyonrails.org/ticket/11142
>

Regards,
Szymon Wilkolazki

kangax

unread,
Feb 26, 2008, 2:39:53 PM2/26/08
to Ruby on Rails: Spinoffs
Good point!
It definitely makes sense to check if element is visible before diving
into a somewhat heavy "ancestors enabling" routine.

- kangax

staaky

unread,
Feb 26, 2008, 4:59:20 PM2/26/08
to Ruby on Rails: Spinoffs
Thanks Szymon,

Good find, I've added a patch in http://dev.rubyonrails.org/ticket/11142
that uses your suggestion.
Reply all
Reply to author
Forward
0 new messages