Monday, January 29, 2007

Animated Picture Slider :: Pre-Bindows 3.0

Recently, Bindows released their 3.0 Beta. This new flavor of Bindows comes with a lot of good things including a animation library that allows you to move, resize and fade any BiComponent.

It's pretty powerful and I'll write about that later in the weeks to come. For now, I'll cook up a little practical use of animation with a picture slider control built from the trusty Bindows 2.5 library.

The picture slider is an implementation of Yahoo!'s "Slide Transition" UI Design Pattern. It's also a knockoff of a slider widget in Yahoo! Games. Our control looks like this --

We'll get photos using the Flickr API (this is a RESTful API and returns XML) and get photos from one of my favorite photographers - Nikographer [Jon]. Jon takes great pictures.

Using the API, we'll load only nine and display only three images at a time. We'll also have an indicator to let people know the context of where they are when viewing the slides. These are the three small dots located at the upper right near the left and right buttons.

For navigation, we have the buttons. Clicking on one brings into the view the next three. The movement of the "next three" is animated so the slides actually move to position. They don't just appear and disappear.

In fact, things in real life seldom disappear and appear. Things transition into place.

When we mouseover the photo, a larger version will display to the right of the picture slider (you can't really see it from the small example above because it's cropped, but you'll see it if you go here). We'll also make the mouseover photo slightly opaque so that you know you're "doing something."

Likewise, when we mouseout, the large photo disappears.

With the general description out of the way, we'll focus our discussion on how we animate the slide control. We're not going to talk about how we construct the control or how we use the Flickr API. I'll provide you with the source and you can peruse that at your leisure. Like all Bindows applications, this one is pretty straightforward.

So, let's talk about the animation. First, we're not using any vector graphics (SVG or VML). We're also not using the canvas tag. We're just going to put images and their titles into a container and then add them to a grid panel. Then, we'll move them by changing their left position.

In Bindows-speak, this is taking a BiImage (a photo from Nikographer), its title (BiLabel) and putting them into a BiComponent. We'll add the BiComponent into a BiGridPanel (creatively called pictureSliderPanel).

When we're done, the BiGridPanel will contain nine BiComponents with photos and titles.

Here's how we setup the grid panel --

sliderWindow is the display window. It'll be wide enough to display only three images and the spaces between them.

Here's how we add slides to the grid panel. Once the XML is aysnchronously loaded from Flickr using BiXmlLoader, we'll call the addSlide method --

To "animate", we'll use the power of absolute positioning to move the grid panel to the left or right simply by changing the left CSS property when we press on the left or right button.

The setLeft() method abstracts this for us so we don't have to worry about calling setStyleProperty().

The sliding is actually done by using a timer. The timer goes to sleep and then wakes up and when it's awake, it'll update the left property. In the example above, we're decrementing so, we're moving left.

We'll stop the slide, when we reach a certain count number. This is what the constant SLIDE_AMOUNT is for. When that occurs, we stop the timer, reset the counter and get out of the loop.

About the loop. The loop is used to speed up the animation. The higher that number is, the faster the slide.

That's it.

You can see the example here. You can get the source here.

Feel free to use, modify and study it. If you do use it, let them know where you got it from.


Thursday, January 11, 2007

Smart Scrolling with Bindows

Smart scrolling is the concept of navigating through a large data set (usually a list or grid) by using scroll bars rather than by pagination. The idea is that scroll bars are more "natural" at navigation because they're already there.

Yahoo!'s Bill Scott, most notable for his UI patterns work, blogs about it here ("Rico's LiveGrid"). You can see real life implementations of it as well. uses the concept for its image searching and the Google Reader uses it for long feed lists.

With Bindows, we can create our own "LiveGrid." We do this by using any of the Bindows trees or grids. To populate and then navigate the grid, we'll get data asynchronously and because our data source returns the JSON format, we'll use the JSON loader component.

Where will we get the data? We'll get it from Yahoo!. They have a great search API which conveniently returns results in JSON.

So, the three things we'll be focusing on are --

  • Creation of the grid
  • Asynchronously populating the grid (Ajax!)
  • Handling scroll events

So, let's look closer at the details. Because "smart scrolling" deals with scrolling, it's obvious that we need to be able to listen for and handle scroll events.

In particular, we'll handle vertical and ignore horizontal scrolling. We'll asynchronously fetch a row (in our case, we'll fetch 15 rows) when we scroll down. When we scroll up, we just scroll the data up. No fetching is done.

The grid that we'll use is really a tree -- BiTree2. There's no particular reason why we chose that component. We could have easily chosen BiTree, BiGrid or even BiGrid2 (similar to BiTree2 but has table/grid properties). The functionality that you want will dictate which component you use. In our case, BiTree2 fits nicely.

So, here's how we create our grid. It's pretty straightforward --

Now, to populate the grid, we'll use data from the Yahoo! Search API. You can read more about the API here, but basically, it's a RESTful API.

We'll submit a asynchronous search request (we're using an proxy server based on Yahoo!'s Search example) and tell the API that we want our results back as JSON. Then, we'll go through that data and take out the pieces that we want and add them to the grid.

To do the Ajax part, we'll use BiJsonLoader. We'll first submit the request through BiJsonLoader and then listen for the load event. The load event fires when the data is all there --

Once we have the data, it's just a matter of parsing the JSON formatted data and extracting what we want. It's pretty easy --

The final piece is handling scrolling. Here's the code --

The first few lines of the event handler handleScrolling effectively ignores horizontal scrolling. When it happens, immediately return.

The rest of the handler deals with vertical scrolling. Basically, we're comparing the position of the previous scrollTop with the current scrollTop. If the current scrollTop is greater than the previous scrollTop, then we call the method searchForward which asynchronously requests the next search results. Otherwise, we do nothing or return.

You can see the example here (I'm using Bindows 2.5).

The code is found here.

Feel free to use it and if you have comments, let me know. I only ask that if you do use it, let them know where you got it from.

Have fun!