Sunday, April 29, 2007

Sprites :: Reduce the Number of HTTP Requests

Recently, Matthew Batchelder wrote a piece entitled "Faster Page Loads with Image Concatenation." It's similar to the "Sprite" pattern described by Michael Mahemoff.

The idea is that you load small icon-blocks and from those blocks, use the icons as images in your application. This allows you to load the images once rather than making separate requests for each image.

As front end web developers, we know that reducing the number of HTTP requests is very important. As Yahoo!'s first Performance Research noted, "Reducing the number of HTTP requests has the biggest impact on reducing response time and is often the easiest performance improvement to make."

Matthew's technique uses background images and a little CSS to display icons.


We can easily apply the same technique in Bindows especially for components like toolbars, menus and buttons.

First, we'll choose an icon-block. Matthew used this one and so will we

We'll use the icon-block to build a custom non-modal window that contains a photo and descriptive text. Other than providing a visual cue for mouseover, mouseout and click, the icons aren't "hooked up" and so don't do anything more.



Though you see seven images, there
are only two that are loaded. The icons are treated as background images each in a BiToolBarButton which of course are found in a BiToolBar.

The highlighted dashed lines indicate the two toolbars


We build the toolbar as we normally do, but this time instead of specifying a separate image for each icon, we'll use a transparent GIF. Then, we'll specify the background image by positioning the icon-block in the correct location.

Here's how we do it "inline" using the setStyleProperty(property, value) method found in BiComponents --



Of course, you can and should pull all the inlining out and then put them in a theme --



where the class names and selector rules associate with appearances. Here are the ones for the expand and close tab menu buttons --



Repeat this process for each icon and you're done! Note that we've only shown how this applies to toolbars, but you can apply it to almost anything.

Keep in mind that it's best to have predictable images ( i.e. the icons should be same size, etc. ). It makes it easier to apply this technique.

You can get all the associated code including the theme here. To see the example go here.

Have fun!

Tuesday, April 24, 2007

See Your Bindows Applications this Way Part 2

I updated the Bindows AboutComponent ( the first part is found here ) to show properties associated with the Bindows component. These aren't nested at all and are shown as a long list. You can click on them and their values appear in the giant bubble dialog.

Of course, the properties are nothing more than what you would get with the "for (var p in object)" syntax. You can probably get the same information if you're using an IDE, but since I don't use an IDE and since it's convenient to associate the properties with the component, I added this feature.

The AboutComponent is also now resizable. I also brought back the column headers. You can increase the width and sort the column. After using it to debug a "real" Bindows application, I realized that the components and events can be very well nested! So, these changes were necessary to make the AboutComponent usable.

Here's what it looks like now --




Here are other examples --

BiButton
BiWindow
BiTabPane with Four Tab Pages
Custom Component

You can download the AboutComponent here. It's all zipped up so just unzip to the "samples" directory of your Bindows install.

Note that this component only works for Bindows 2.0 and above.

Have fun!

Friday, April 06, 2007

Seeing Your Bindows Application This Way

Almost everything useful that you do with Bindows requires you to create parent child relationships with components. In other words, to create "controls" you always end up adding components to other components. After all, one of the main functionalities of the toolkit is to build visual controls that express behavior ( without behavior, your application is just another pretty face ).

For example, if you wanted to use a window component, you would instantiate BiWindow and then add it to the BiApplicationWindow. Like all components, BiWindow has a number of event listeners that provide behavior.

That got me thinking. Wouldn't it be nice to know the parent child relationships of a Bindows component or application? After all, that is one way of measuring how "big" your application is.

Or better yet, wouldn't it be nice to know the total number of events, the event types and their event handlers for application you're writing? Sometimes, your application is so big that it's tedious to go through the code, look at the events and then review the handlers.

So, I came up with a little reusable component called "AboutComponent" ( I thought about Bindow Eyes but people might think that this has something to do with a screen reader but it doesn't! ) that does just that --

  • Shows the parent child relationship in a component/application ( all components added to the parent )
  • Shows the total number of events that the component is listening for, the total number of events that each child is listening for and their event handlers

I've used it to look at out-of-the-box Bindows components. Here's one for BiWindow --



Here's another with the BiTabPane component with four tab pages --




Of course, it's really useful and fun to analyze your own components. Here's my imitation of the Yahoo! movie rater ( this is also their "Hover Invitation" UI Pattern; read more about it here ) --




What does this all mean?

The first tab shows the parent child relationships or how the components contain each other. It doesn't show inheritance or how the component extends/derives. So, if you're looking at a BiButton, what you won't see is anything pertaining to a BiLabel or BiComponent. Why? Well, those aren't added as children to BiButton.

So, if you wanted to see the whole structure tree, you'd need to check BiComponent and BiLabel separately.

But, the tree does show you all the children found in your component and does show you the "structure" of your design.

The second tab shows all the events that the components are listening for. You can click on each event and a list of the event handlers show up. You can use this to see if you've accidently added unnecessary event handlers. Instead of scanning possibly a large code base, this immediately tells you how many events ( and what they do ) and how they associate with the component.

Remember, adding an event listener doesn't replace/remove previous ones! There's always a symmetry involved. If you add an event, you have to remove it explicitly ( by calling the method removeEventListener() ) or implicitly ( by disposing of the component or calling the removeAll() method from the parent component ).

How do you use it?

All you do is instantiate the AboutComponent with the component that you're interested in. Here's one where we pass a BiWindow component as a parameter to AboutComponent --



Pretty simple.

Now, you might be wondering how all this works. It's pretty straightforward. First, you can find all the children in a component by calling the getChildren() method. It's available for all BiComponents. Then, for each child, you call getChildren(), and then repeat ( i.e. recurse ).

You do this a n times and build up your tree. Here's an example of how I built the component tree for the first tab --



For the second tab, we do the same sort of thing. Only now, we're also after the events. Every BiComponent is a BiEventTarget and so contains event listeners -- a multidimensional array hashed on the event name and a key.

With that information, you can access an object literal representing the event handler and the "this" object. In other words, the "_listener" object contains the arguments passed to the method addEventListener(evtName, fHandler, [obj]).

Here's how we do it in the method getEventHandlers() --



Of course, we're pretty dependent on whether Bindows continues to handle their event in the same way. In general, it's not a good idea to directly access internal data structures like _listeners.

It's this way today ( Bindows 2.55 ), but tomorrow, who knows.

I hope you find this useful. You can download everything here. Unzip them into the "samples" directory of your Bindows library. You'll see a directory called AboutComponent. All the HTML files there are examples. So, click and run!

You'll find AboutComponent defined in AboutComponent.js. I've tested this only on Bindows 2.55 ( Just an update. AboutComponent won't work in pre-2.5 versions of Bindows. I'll look into that and update AboutComponent in the next few days ).

If you want to see the four examples without downloading the ZIP file, you can go here --


Feel free to use and improve it. I'd love to hear your feedback. If you do use it, let people know where you got it.

Have fun!