jQuery Resize Event

by Justin Meyer

jQuery Resize Event

Justin Meyer When building web applications, it can be tricky to get

posted in Development on May 23, 2011 by Justin Meyer

When building web applications, it can be tricky to get pages to layout
correctly, especially when layout can’t be done with CSS. Widgets that
can dynamically change the layout only complicate matters. JavaScriptMVC
3.1 packs a new resize event that greatly simplifies these layouts.

The Past

In the long long ago, the before time, we would have various controls
listening to the window’s resize event and sizing themselves
appropriately. But, eventually we discovered several problems or
difficulties with this approach:

Problem 1: Callback Ordering

If you look at the demo
page
,
you’ll notice there are several elements that need to be resized:

  • The RED Border element (fills the window)
  • The BLUE Border element (fills the RED Element)
  • The Splitter content elements
  • The Scrollable element in the table

Each of these elements need to be resized after their parent
elements have been resized. For example, the BLUE element needs to
know the final size of the RED element before calculating its size.

We could be very careful to register and maintain all event handlers in
the right order, but this would be tricky, error prone, and downright
annoying.

Instead, what’s needed is a resize event that fires in document order.
That is, resize is fired first on the window, then the document, and
then all child elements from the outside in.

But, this is opposite of how DOM events and jQuery’s synthetic event
system (trigger) works. The DOM calculates all the elements between the
document and the target and then fires event handlers in two passes:

  • Walks from document to target, firing event handlers listening to
    the ‘capture’ phase.
  • Walks back from the target to the document, firing event handlers
    listening to the ‘bubble’ phase.

Bubble

jQuery’s trigger only bubbles. And, even if it supported a capture
phase, it would not help. A resize event doesn’t have a single target;
instead, every element is a potential resize target!

So, instead of capturing or bubbling, our resize event can be thought of
‘cascading’ the document – firing every resize listener in order from
parent to child.

Note If you are worried about this performing … well, don’t. We’ve
got it covered.

Problem 2: Widgets That Resize Children.

As the demo … um … demonstrates, we often have widgets (ex:
splitters) that can adjust the size of their child elements. We could
have these widgets trigger a resize event on the window which would call
every resize handler. But, this would be inefficient. Only the elements
within our widget might need to adjust themselves.

In the past, we handled this by having child widgets to resize and the
parent widget trigger resize on the child widgets:

subElement.triggerHandler('resize');

This worked, but there were cases where subElement wasn’t the element
that had the resize event handler.

Instead, we wanted something where we could trigger resize on an element
and any of its own or its child elements resize handlers would be
called:

subElement.resize()

Problem 3: Browser Differences

There is no standard around the resize event. IE fires resize events on
elements, all other browsers only fire a resize event on the window.

Furthermore, it was easy in IE to create recursive resize events that
would freeze the browser. You just would have to listen to resize and
change the DOM so it would fire another resize event.

Naturally, we fixed all these problems.

Use

Download or steal the jquery/event/resize plugin. Then listen to resize
like:

$('#foo').resize(function(){
  // make the element the right size
});

If you didn’t need to resize yourself, you can stopPropagation(),
preventing your child elements from getting a resize event:

$('#foo').resize(function(ev){
  if( IdontNeedToResize ){
    ev.stopPropagation()
  }
});

Finally, if you want to call child element’s resize event handlers
outside of a window resize event, simply call resize on the child:

child.resize();

How it works

When an element first listens to resize, that element is inserted into
array of elements sorted by document order.

When a resize event happens, resize is call on elements in that array.
If the outer element being resized is not the document, it only calls
event handlers on elements within the outer element.

What about Ben Alman’s Resize Plugin?

Ben’s fantastic resize
plugin
lets you
listen to when an element has been resized by polling for element width
and height changes. This is great because you don’t have to call resize
if you change the dimensions of an element. However, it has 3 potential
drawbacks:

  • Checking width and height is relatively expensive in some browsers.
    If you have lots of elements listening to resize, this could cause
    slowness.

  • To create smooth-ish resizing, you need all resize events to fire
    immediately one after the other. If your outer widget sets the width
    of an inner element, it could be another 250ms until that element
    resizes itself and its child elements.

  • Inner elements have to listen to parent resizes.

Ben’s widget is a good choice for pages that don’t have many nested
structures that need to be resized.

Conclusion

The resize event has made our lives a lot easier. We’ve created a number
of
splitter,
filler,
resizable,
and
grid
like widgets that exploit its power. Hopefully you can use it to clean
up this often tricky part of JS application development.

blog comments powered by Disqus

Getting Started with Cordova

Brian Moschelposted in Development on March 26, 2015 by Brian MoschelAt Bitovi, we’re big fans of building applications with web technologies and using build tools to target other platforms like iOS, Android, and desktop. This article will provide a quick guide to getting up and running quickly with Cordova.

Web Application Theory

Justin Meyerposted in Development on June 27, 2014 by Justin MeyerUnderstand the technology and architecture choices Bitovi make and why we make them. What Bitovi does and why.

Contact Us
(312) 620-0386 | contact@bitovi.com
 or cancel