Monday, November 27, 2006

Creating a Google Gadget Tips-Like Widget :: Part 2 :: Making It Reusable

In the first part, we looked at how we could create the Google Gadget Tips-Like Widget using the Bindows JavaScript toolkit. Unfortunately, what we created wasn't reusable (i.e. we couldn't instantiate it to make more of the same thing) which made the component pretty useless (a component is synonymous with a widget; Bindows uses the word component to mean widget). However, our prototype did demonstrate functionality and that's what it was supposed to do.

If you missed the first part, you can find it

In this second part, we'll take what we've done and make it so that we can create any number of components with something simple like this --

To start, we need to think about what the developer will use the component for. Here are a number of things that he'll want do with our custom component (let's call this the VerticalTabComponent) --

  • Use their own grabber
  • Give the grab label a completely different name
  • Customize content in the tab pane
  • Control background (and foreground) color
  • Replace the default close button with something more snazzy
  • Etc.
The important point to remember is that the developer customizes the component to suit their particular needs. This means that we need to make customization as easy as possible.

So, armed with that information let's derive VerticalTabComponent from BiComponent.

Basically, we need to put the members and functions from BiComponent into the prototype scope of VerticalTabComponent. We'll also need to call the BiComponent constructor (function) on behalf of the derived component like this --

We'll also expose a few privileged functions (these are like public functions but have access to private members) --

Notice the granularity of the functions. Most of them return derivatives of BiComponent rather than objects like String (i.e. the tab button label, etc.). As we noted in the first part, "BiComponent is by far the most useful component in Bindows."

Of course, much of what we expose to the developer is based on how much we wish to abstract. For example, look at these two functions --

Why on earth would we want to set the background color this way when we can use the power of CSS?

As it turns out in this case, we do want to hide some of the details. When we set the background color for the VerticalTabComponent, what we're really doing is setting the background color for an internal container. This is something that the developer shouldn't worry about.

You'll also notice that we only expose functions. We didn't expose any of the member variables. We want to control what the developer has access to and directly grabbing member variables is not what we want.

We've also removed almost all of the inline styling and placed them in an external CSS file. Bindows uses the concept of themes and to use that we need to define an appearance which is nothing more than a selector rule found in the CSS file within the theme.

So, we'll define the appearance and then make sure that the selector rule is the same name as the appearance. Here's one example of how we create appearances. This one is for the internal container --

Within the theme.css file, we'll add these selector rules --

If you look in the VerticalTabComponent, we did keep a few inline styles --

We did this to styles that change the state of the component that are independent of the theme.

In general, when we make a reusable component, we should do our best to move the styles out of the code and into an external file. In essence, what we are telling the users of our component is that these selector rules are free for you to modify.

Lastly, we'll have a few event handlers to deal with behaviors like dragging, mouseovers and mouseouts --

We're now ready to create the component and with a single line of code we have magic --

If we wanted to create a look different from the default "Google", that too is easy, but a bit wordy. Here's the code for a "Meebo" ( like look --

That's all there is to it. If you're interested in the example, the implementation is found here.

You can download the entire sample
here (including the VerticalTabComponent). Of course, you'll need the Bindows JavaScript Toolkit. My example uses Bindows 2.5, but any version of Bindows should work. Have fun!


Anonymous said...

Hi Oliver

Nice thing!
It would be even more better if you provide solid API for you component for easily reuse. A-la BiTabPane & BiTabPage. So I can easy append new VerticalPage to VerticalPane and set text, icon and other properties...

Thanks, Alexey Zhuravlev

skypoet said...

Hi Alexey,

Yes, I can, but a bit later.
I was lazy. :)