Wednesday, September 19, 2007

SplitPane Control :: YUI

One of the basic controls is the split pane control. YUI doesn't have one right out of the box. So, we'll build one.

Note that Jack Slocum created one based on YUI about a year ago for his ExtJS library. He called his a "SplitBar Component."

Of course, Bindows has a **pure** JavaScript one.

We'll base ours off of the YAHOO.widget.Slider. We'll take advantage of its ability to slide horizontally and vertically. This also means that whatever YUI pieces that the YAHOO.widget.Slider uses, we'll use those as well.

Here it is in action --

Like the YAHOO.widget.Slider, we'll retrieve a horizontal and vertical split pane by doing it the static way --

var horzSplitPane = MySplitPane.getHorizSplitPane("SliderBg", "Thumb", 145, 200, "LeftContainer", "RightContainer");

var vertSplitPane = MySplitPane.getVertSplitPane("SliderBg", "Thumb", 194, 250, "TopContainer", "BottomContainer");

So, we'll mimic the YAHOO.widget.Slider API --

var horzSlider = YAHOO.widget.Slider.getHorizSlider(sBGElId, sHandleEId, iLeft, iRight);

var verSlider = YAHOO.widget.Slider.getVertSlider(sBGElId, sHandleEId, iUp, iDown);

With the exception of the additional two panels, we'll keep the arguments the same. Leveraging what YUI users already know allows them to easily learn your API.

We'll use these two methods to get the split panes --

MySplitPane.getHorizSplitPane(sBGElId, sHandleEId, iLeft, iRight, leftContainer, rightContainer)

MySplitPane.getVertSplitPane(sBGElId, sHandleEId, iUp, iDown, topContainer, bottomContainer)

  • sBGElId is the ID of the slider background
  • sHandleEId is the ID of the slider thumb
  • iLeft/iUp is the number of pixels the slider can move left or up
  • iRight/iDown is the number of pixels the slider can move right or down
  • leftContainer/topContainer is the ID of the left or top pane
  • rightContainer/bottomContainer is the ID of the right or bottom pane
The actual augmentation isn't based on prototype inheritance. MySplitPane is really a wrapper around the getHorzSlider and getVertSlider methods --

Each method, getHorzSplitPane and getVertSplitPane, is treated as an object in an object literal which is returned within the Singleton method/object MySplitPane. The end result are two public methods.

We subscribe to the "change" event which through the handler, handleChange, resizes the panels.

You of course can add more functionality by subscribing to your own "change" event and then using the handler to do something else like update the text in the panels --

Two of the more interesting utility methods are YAHOO.util.Dom.setStyle and YAHOO.util.Dom.getStyle. They're used instead of so that you can get "style" name/value pairs even if they're not defined inline or via JavaScript.

The YUI documentation notes that getStyle "normalizes currentStyle and ComputedStyle."

That's it!

You can view MySplitPane here. Visual examples for everything above are found here and here.

Feel free to use or modify the code.

Have lotsa fun!

Saturday, September 15, 2007

YUI :: First Impressions

People must think I've been living in a cave, but I've only recently been playing with YUI. In the past two years, I've been a Bindows developer creating a few examples here and there and so, I know that framework pretty well.

Of course, now that I'm at Yahoo!, I'm supposed to get a firm grasp on the library. Unlike other web devs at Yahoo!, I haven't taken any classes on YUI. So, this series of entries will be a "fresh eyes" approach to YUI.

It's not a difficult library to learn and it's definitely not as comprehensive with it's controls/widgets as Bindows.

As you probably know, I think Bindows is great. IMHO, it's one of the best ( if not the best ) traditional front-end frameworks out there. You can do a lot with it ( just check my archives for examples or visit my site ).

In contrast, YUI isn't a framework. It's **mainly** an a la carte library of JavaScript utilities and widgets that help with web development. It abstracts browser differences so that you don't have to worry about it.

YUI also contains other things like CSS files that help with layout, font sizes and other troubling difficult to solve cross-browser issues.

What's interesting about YUI is that it's a mixture of things --
  • Utilities that help with DOM manipulation and event handling
  • CSS for cross-browser visual consistency
  • A few "hard to do by yourself" controls/widgets
One of the fundamental assumptions of YUI is that you need to know the DOM and how to manipulate it. You also need to know event handling. You'll need to know the structure of your application and how to style it. So, you need to know the "Big 3" - HTML, CSS and JavaScript.

YUI doesn't attempt to abstract these things ( which is a lot different than Bindows and a few other libraries which abstracts everything and all you really need to learn is JavaScript and the API. Of course, these libraries are typically "fatter" than a la carte libraries, but also have ways to remove libraries if they're not used ).

One advantage to the YUI approach is that it's a lot easier to add functionality to pre-existing systems. This is because you directly manipulate DOM elements. So, you basically load the library and then pass nodes, ids, etc. to helper methods which performs the magic.

Because YUI is an a la carte system, you'll only pick and choose what you want. It's easy for you to control the "size" of your library.

Like Ajax technologies, you can gradually introduce it into your system. For example, if you're interested in cross-browser event handling, you'd just pull in event.js which includes the YAHOO.util.Event class. You can throw one away home grown solutions like my own.

For now, we're just going to look at two of the utility components. In the future, we'll look at the core components and some of the handful of YUI controls/widgets.

About the Example
I'm really fond of DnD. People are still amazed that you can drag and drop in the browser. So, our first example will use the dragdrop library with a little sprinkle of animation.

Here's the example -- we'll drag a little box around and as we drag it, we'll provide visual indicators of the location of the box. Once we stop, we can undo our current position ( see it full screen here ) --

Both of these libraries manipulate the DOM, so you have to have markup.

So, the very first thing we do is take care of all the visual pieces. For us, it's the little draggable box, the "Undo Button" ( which is initially is not shown ), the left and the top positional markers which result in this simple structure --

The CSS is just as simple --

To use the dragdrop and animation libraries, you'll need to pull in three JavaScript files --

Note that yahoo-dom-event.js is used by both libraries.

Next, the fun begins! The general sequence for DnD is -
  • Get the element you want to drag
  • Instantiate a YAHOO.util.DD object with that element
  • Override the drag event handlers ( typically onDrag, but in our case we also overrode startDrag and endDrag as well; note that you can find a slew of event handlers as well as other information here; the dragdrop library is pretty comprehensive; you can even drop to targets; here's one of my examples )

YAHOO.util.DD is the wrapper around the object that's being dragged. So, if you need to get the object, you'll need to do this --

var dragEl = this.getDragEl();

dragEl is the node with ID "ThingToDrag". You'll also notice that we can use the node to get position information relative to the entire HTML document --


The x and y positions are tucked away in object literals which are pushed on an array. This is a stack of starting positions which we pop when we undo ( we'll talk more about this in the animation section ).

The handler that does most of the **work** is onDrag. It basically handles all the visual updates like --
  • The information on the position of the dragged element
  • Positions both the top and left grid markers so that they move with the element
Note that we're directly manipulating the node ( i.e., etc. ). Of course, we don't have to do it this way. We could have just use YUI and the YAHOO.util.Dom.get/set methods, but we did it this way to remind us that we directly manipulate elements in the DOM ( this is in contrast to other toolkits like Bindows which totally abstracts the DOM ).

Once we've completed the drag, we can undo it. Undo starts the animation.

We'll instantiate the YAHOO.util.Motion object for the ThingToDrag node, subscribe to ( listen for ) the onTween and onComplete event handlers and then start the animation --

onTween is fired for each frame of the animation ( for each movement of ThingToDrag ) and onComplete is fired when the animation is finished ( ThingToDrag no longer moves ).

In this example the onTween handler, handleTween is the same handler as onDrag. Likewise, the onComplete handler, handleComplete is the same as endDrag.

This makes sense. There's a symmetry to undoing what you just did so it's no surprise that these event handlers are the same!

In the handler, handleComplete, we also unhook our event handlers. It's good practice to free up resources like this when they're not needed to avoid nasty memory leaks.

That's it! You can read more about the YUI dragdrop and the animation library here and here.

Feel free to study and use the example anyway you like.

Have fun!

Sunday, September 09, 2007


Two weeks ago, I joined Yahoo!.

If you're a front-end web engineer, it's the best place to be. They have some of the best front-end engineers in the world in an environment where you can become a better cloud developer.

If you're smirking ( or laughing ), you've probably haven't noticed what Yahoo! has contributed to the world of front-end development.

A few years ago, I would have thought the same. Do you remember the *old* front page? Or, how about the pre-OddPost Yahoo! mail? Or, how about Yahoo! photo ( thank goodness for Flickr! ). Those things are legacies of Web 1.0.

Then, something happened. A couple of years ago, Yahoo! published their Design Pattern Library which catered to the user interface design and interaction folks. The Bill Scott led project really struck me as something that was useful and came at a critical time when Web 2.0 and Ajax concepts were coming into popularity.

Having a set of UI interaction patterns was only one piece of the solution. Creating a *free* library that implemented ( or at least allowed you to easily implement ) those patterns was the other. Having a library bridged the knowledge of the UI designer with the implementation skills of the front-end developer.

It demonstrated a commitment by Yahoo! to take *theoretical* concepts ( ok, some people would say "fluff" ) and introduce them to the web development community with tools to help implementation.

As an outsider, I heard Yahoo! say --

OK, here's some UI patterns that we think are really valuable and will help with usability. We've focused on interaction because that's the most important thing. UI designers will dig this stuff.

Oh and by the way, we've created a library that your web devs can easily use to supplement their code and slowly introduce these patterns into their application.

And yes, it's all free!

Then, they wanted to train all those folks to use these libraries. As a first step, Yahoo! introduced an amazing series of talks on JavaScript and the DOM by Douglas Crockford.

In fact, on YUI Theater, you'll find a complete program or "web polytechnic" for the front-end developer. You'll see talks on improving web performance, accessibility, using the YUI library, Firebug and an amazing array of web related things.

It's just amazing what they offer to cloud programmers who don't work for Yahoo!.

Since I've started, I've attended a front-end development class by CSS and JavaScript expert Natt Koechley and attended a meeting with accessibility expert Victor Tsaran.

On my immediate team, I'm working with some equally amazing people one of whom created the "Personal Assistant" ( here's my imitation. I even blogged about it. It's humbling to meet the guy that did it! ).

Last week, there was a long internal thread on sprites ( or tiling ) and whether stacked were better performing than horizontal images. Going through the responses, I realized how deep and thorough my colleagues were in their thinking and how much I still have to learn.

This is really going to be a fun ride. I've buckled my seat belt.