Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #11142 (new enhancement)

Opened 2 years ago

Last modified 2 years ago

[PATCH] [TEST] make Element#getDimensions works with display:none ancestors

Reported by: staaky Assigned to: sam
Priority: normal Milestone: 2.x
Component: Prototype Version: edge
Severity: normal Keywords:
Cc:

Description

Element#getDimensions returns 0,0 when the element has ancestors set to display:none. The current implementations sets only the element itself to display:block and visibility:hidden before checking it's dimensions.

When doing this for all display:none ancestors as well the dimensions will always return correctly.

I've added a patch with unit test, and a test-page

One thing to note is that I've removed the Safari bug from the current implementation, as tests passed. The Safari bug involves all values returning null when an element is set to display:none. I'm not able to test this on Safari2, but if it's still required I can work it back in.

Attachments

elementgetdimensions_displaynone_ancestors_withunit.diff (5.1 kB) - added by staaky on 02/17/08 19:21:24.
elementgetdimensions_displaynone_anc_noreject_unit.js (5.2 kB) - added by staaky on 02/17/08 22:17:40.
elementgetdimensions_displaynone_anc_noreject_unit.diff (5.1 kB) - added by staaky on 02/18/08 00:13:47.
elementgetdimensions_displaynone_anc_reccollect_unit.diff (6.8 kB) - added by staaky on 02/18/08 02:53:19.
elementgetdimensions_disnone_anc_performance.diff (7.0 kB) - added by staaky on 02/26/08 21:54:46.

Change History

02/17/08 19:21:24 changed by staaky

  • attachment elementgetdimensions_displaynone_ancestors_withunit.diff added.

02/17/08 19:29:47 changed by kangax

Maybe it would also make sense to "null" this "huge" styles array before returning value?

02/17/08 19:33:40 changed by staaky

The garbage collector should get to that

02/17/08 19:56:24 changed by kangax

I really like this patch but am concerned about performance:

ancestors -> reject -> each -> each

is just a little too much for such common method, don't you think? : )

02/17/08 20:16:00 changed by staaky

It could be turned into 2x each

ancestors -> each( fill up styles with invis. ) -> each

The downside af that is you also have to pass along all the visible elements again in the 2nd each when you set the styles back. I wonder what's the difference in performance compared to having reject filter things out, making the array smaller. Suggestions?

02/17/08 20:23:57 changed by kangax

I suggest to change recursivelyCollect (which affects ancestors and couple of other methods) to accept iterator (which in this case could be !Element.visible)

  recursivelyCollect: function(element, property, iterator) {
    element = $(element);
    var elements = [], iterator = iterator || function(){ return true; };
    while (element = element[property])
      if (element.nodeType == 1 && iterator(element))
        elements.push(Element.extend(element));
    return elements;
  }
...
element.ancestors(Element.visible);
element.nextSiblings(function(el){ return el.hasClassName('foo') });

02/17/08 22:17:40 changed by staaky

  • attachment elementgetdimensions_displaynone_anc_noreject_unit.js added.

02/17/08 22:32:42 changed by staaky

That's a nice idea, I wonder how that performs so I did some tests with all implementations.

I also wrote the patch again without reject and avoided the downside I mentioned earlier using an extra array. It's about 20% faster then my previous patch.

The extra functionality comes with a price, but I think getting the results you expected is worth that extra bit of time. These tests where done using up to 4 display:none ancestors, in a real setup I don't expect that much display:none ancestors, but the more you have of those, the slower it gets.

500 x Element#getDimensions test:

Without reject:
IE: 156ms - 383ms - 2.4x slower
FF: 113ms - 287ms - 2.5x slower

With reject:
IE: 156ms - 467ms - 3.0x slower
FF: 147ms - 433ms - 2.9x slower

recursivelyCollect with iterator:
IE: 159ms - 473ms - 3.0x slower
FF: after 1 cycle of 60 tests firefox freezes

02/18/08 00:13:47 changed by staaky

  • attachment elementgetdimensions_displaynone_anc_noreject_unit.diff added.

02/18/08 00:48:43 changed by kangax

Well, the with/without reject tests are pretty much what I expected. Not sure why recursivelyCollect freezes FF - I'll take a look at it.

02/18/08 02:52:27 changed by staaky

Turns out I forgot something, after using your patch from #11143 it worked.

Added a patch to use with kangax' recursivelyCollect and created a page where the 3 methods can be timed/tested

Out of the three I prefer recursivelyCollect.

02/18/08 02:53:19 changed by staaky

  • attachment elementgetdimensions_displaynone_anc_reccollect_unit.diff added.

02/26/08 21:48:35 changed by staaky

A patch with performance improvements. Based on Szymon Wilkołazki's suggestion in the spinnofs mailing list, uses #11143

Makes sure the speed will remain the same as is now for visible elements, giving less speed only when required.

02/26/08 21:54:46 changed by staaky

  • attachment elementgetdimensions_disnone_anc_performance.diff added.