2013-01-11

Dart Widgets Dev Journal 1 - Basic Animations


tl;dr: Implementing features similar to Bootstrap is hard without basic animation support in Dart. Basic animation support is not as easy as you'd think. I've made a stab. Check out the demo.
I've started a new Dart project - Dart Widgets. The inspiration is Bootstrap, but with a focus on features that map cleanly to Web Components.

While digging into Bootstrap, I realized that there was a heavy dependency on jQuery--specifically the show/hide/toggle functionality. This is critical for expanders, menus, modals, pretty much everything.

Show, hide, toggle

It turns out implementing show/hide/toggle is not as easy as one might guess.

One could naively toggle display: none; in an element's style attribute and call it a day, but a lot of edge cases would be missed.

Throw in the ability to optionally animate the show/hide behavior and things get a lot more complicated.

A short list of the cases to ponder:

  • Element with a non-standard display value. (e.g. a div inherited a display of inline-block)
  • Element with a local display of none 
  • Element inherited a display of none
  • Show is called while an element is hiding and vice versa
  • Toggle is called 10 times before the first animation finishes
  • Show is called on an element with effect A while effect B is hiding it.
Huge props to the jQuery and jQuery-ui folks for tackling this problem. Their code served a great starting spot. I feel bad that they had to implement this logic in Javascript.

Test

I can't tell you how valuable test-driven development was in getting this project off the ground. It would have been next to impossible to ensure all of the edge cases were handled cleanly.

I need to write another post about how my approach to testing in Dart has evolved. Let's just say I didn't code up 939 tests by hand.
After a lot of head scratching, I think I ended up with pretty clean, extensible model.

As proof, I offer the code for doing a open/close door effect:

class DoorEffect extends Css3TransitionEffect {
  DoorEffect() : super(
    '-webkit-transform',
    'perspective(1000px) rotateY(90deg)',
    'perspective(1000px) rotateY(0deg)',
    {'-webkit-transform-origin': '0% 50%'}
  );
}

There are still a few things I'd like to get working--get tests working in Firefox, find a way to handle browser prefixes cleanly--but generally I'm happy with progress.

Check out the demo.

Check out the code.

Let me know what you think.