Monday, July 30, 2007

Bindows Nifty Round Corners :: No Images!

In March of 2005, Alessandro Fulciniti wrote a piece on using rounded corners without the use of images -- "Nifty Corners". The idea is simple -- by stacking lines of different lengths on top of one another you form a rounded corner.

Alessandro used a combination of block elements and margins to achieve this. We can do the same by using the basic Bindows building block -- BiComponent -- manipulating its width and then using setStyleProperty() to reduce its margins.

The result is the component,
MyRoundedCorners, a BiComponent that allows you to create rounded "top" or "bottom" corner pieces --



You can use the top and the bottom piece to "sandwich" the main body of another BiComponent and create something like this Meebo-like Yahoo! login --



Because MyRoundedCorners is a BiComponent, you can listen for events and add it to other BiComponents. So, you can create a custom dialog, drag it around and even resize it as found here.

Using MyRoundedCorners is simple. To create rounded corners for the top, do this --

var topPiece = new MyRoundedCorners("top");

or with no arguments --

var topPiece = new MyRoundedCorners();

To create rounded corners for the bottom --

var bottomPiece = new MyRoundedCorners("bottom");

There are a few "public" methods ( these are the ones that are meant for you to use; of course, you could iterate through the properties and discover methods that you're not supposed to use! ) that allow you to set properties for the corners.

Most of the methods mimic the behavior found in "out of the box" Bindows components and are self explanatory --


  • setWidth(w)

  • setBackgroundColor(colorInHexOrRgb)

  • setOpacity(oValue)

This is just like BiComponent's setOpacity(). oValue should be a number between 0 and 1 where 1 is totally opaque and 0 invisible.


  • setCSSBorder(borderValue)

"borderValue" is equivalent to the values for the CSS border property like --

border: 1px solid #000;

where "borderValue" is "1px solid #000".


  • setBackgroundImage(url, repeat)
"url" is the URL value or the name of the background image that you want to use. It's the same value used in the CSS property "background-image".

"repeat" is the same as the CSS property "background-repeat". You can use values "repeat", "repeat-x", "repeat-y" or "no-repeat".

So, to create a rounded top border with a width of 400px with the background color of #9bd1fa, you'd do this --

var container = new BiComponent();
container.setSize(400, 20);
var rc = new MyRoundedCorners("top");
container.add(rc);
rc.setWidth(400);
rc.setBackgroundColor("#9bd1fa");
rc.setOpacity(1);
...
application.getWindow().add(container);

Note that the height of the rounded corners are always 5px. You can't ( and shouldn't ) change that. This makes the API even simpler because all you have to worry about is setting the width of MyRoundedCorners.

You can find the examples/test driver here. You can review the XML here and MyRoundedCorners here.

I built the component and the examples with Bindows 3.0, but it should work for other Bindows versions as well.

Have fun!

Monday, July 23, 2007

Meebo Me :: Dressing Up a Widget

In August 2006, Meebo, the web based instant messenger provider, released MeeboMe, a Flash-based chat widget which you can place on your website. MeeboMe allows your visitors to directly chat with you while they're enjoying your site.

Because it's Flash based, you can easily embed it. First, go to Meebo and create the chat widget. Then, add the Meebo generated markup. It's a simple embed tag --

<embed src="http://widget.meebo.com/mm.swf?uSvqMVsYVU" type="application/x-shockwave-flash" wmode="transparent" width="160" height="250"></embed>

You'll get something that looks like like this --



The green button at the upper right disables the widget. The main thing of course is that you can type and send messages. It does that very well.
Though it looks like a dialog, it doesn't behave like one. You can't close the MeeboMe widget and you can't move it around.

So, let's make it a dialog!

The first thing that we'll do is add a close button ( I got the icon from Everaldo.com via IconDB ). Then, we'll make the dialog draggable.

To do both, we have to think in terms of layers or containers. The general idea is to put the embedded Flash widget inside a containing div. Then, add the close button on top of the widget. Being on top, our close button covers the green button. The close button has a higher z-index. Here's the code snippet --

<div id="MeeboWidget" class="MeeboTalker">
<
embed src="http://widget.meebo.com/mm.swf?uSvqMVsYVU" type="application/x-shockwave-flash" wmode="transparent" width="160" height="250"></embed>
<div class="CloseButton"></div>
</div>

Next, we'll listen for the events at the container level ( id is "MeeboMeWidget" ). This allows us to handle events only at one rather than multiple levels. Note that we're not event delegating -- we're only listening for a click and a mousedown event ( this is used to initiate drag ).


Here's the new MeeboMe dialog --



You can view the code by coming here and then view the source.

Have fun!

Wednesday, July 11, 2007

At the Movies with Jaman

As part of front end development, I sign up for a lot of beta testing. It helps me to see what's the state of the art and what everyone else is doing.

Once in a while, I'm lucky enough to get into private betas. Jaman was one. I've been through the private beta and now, I'm a regular user ( by the way, for all you movie lovers, if you sign up now, you'll get 3 free downloads. If you sign up via this special promotional link, you'll get 4 free downloads. What a deal! ).

I'm really fond of dark, particularly black backgrounds because it provides ample contrast. It's the constrast and not so much color that make things standout.


Jaman's focus is on world cinema. They create virtual film festivals that focus on films that you won't ever see in mainstream theaters.

Super blogger and techman, Robert Scoble did a video interview with Jaman founder, Gaurav Dhillion here. It's worth a watch to get an idea of what they're doing. Om Malik also had a nice piece on them as well.

Jaman has a lot of your art films, but they're also major motion pictures from foreign countries ( for example, you can watch the superb multi-award winning Indian film Black ).

They're also documentaries ( see classic American cars in today's Cuba -- Yank Tanks ), shorts ( watch the 3 minute satire - The American Infant ) and my favorite -- animations ( check out Fumi and the Bad Luck Foot for a smile, a laugh and maybe even a giggle ).

After you watch the movies, you can share your thoughts with other movie lovers as well.

The beauty of the web is that the world is made much smaller. We all can enjoy the wonders of film from great film makers all over the world.

You can enjoy Jaman too.

Hope you are having a fun summer and watch some movies!

Sunday, July 01, 2007

IE Memory Leaks

Mark Wubben blogged that Microsoft recently released a security patch that among other things fixed memory leaks in IE 6.0 on XP. Specifically, Microsoft mentions a fix for --

"A memory leak occurs in Internet Explorer 6 when you view a Web page that uses JScript scripting on a Windows XP-based computer"

More details are found here.

It's important to note that the fix is only for IE 6.0 running in XP. It doesn't address IE 6.0 running in W2K or IE 5.5. It's also a patch that's applied to the entire OS with a number of other fixes. So, some people ( ex. corporations ) may be hesitant to install it until they've fully verified that the patch is more beneficial than hurtful.

Of course, if you're using IE 7, none of this matters because memory leaks don't occur there anymore.

With these elements in play, I'd thought we'd review memory management in IE.

Memory leaks occur in IE because of circular references between DOM elements and JavaScript objects ( it's really JScript objects -- Microsoft's implementation of JavaScript ).

Circular references aren't a problem with other browsers just IE. This is because IE uses two different memory managers -- one for DOM elements ( DOM elements are represented as COM objects and so use the COM garbage collector ) and one for JavaScript objects which uses a different one.

Since the two memory managers don't communicate with one another they don't know that there are "islands" of circular references which are no longer used. The memory managers get confused and then bad things happen.

Note that I've simplified this a lot. If you want the gory details read Joel Webber's dated but really good description of the issue.

In IE, when memory leaks happen, they don't go away when you navigate to a new page. Instead, the memory loss carries over. If you use a process/memory viewer like Process Explorer, you'll observe this.

The only way to free the memory ( other than breaking the circular references ) is to close and restart the browser.

Circular references between DOM and JavaScript objects are common. If you've ever attached an event to a DOM element and have your event handler refer back to the element, you've created a circular reference. They can also occur when you create closures ( inner functions can access variables outside of itself even after the enclosing function has returned ), but the more common occurrence is the first one.

Fortunately, it's easy to break the circular reference and as it turns out, it's easier to break the link from the DOM rather than from the JavaScript side of things.

For events, you do it differently depending on how you've attached the events.

DOM Level 0 Events
All browsers support Level 0 event handling. This is probably the first type of event handling that you learned when learning about HTML and JavaScript events. Level 0 event handling allows you to attach events directly to the HTML element like this --

<div id="SomeDiv" onclick="handleClick();"></div>

The div element has a reference to the JavaScript object handleClick via the onclick attribute. If the method handleClick has a reference back to the div ( for example "this" ), then a circular reference occurs.

It's not optimal to review every event handler to see if a circular reference exists. It's better to just unhook the event handler when you no longer need it.

So, follow this maxim of symmetry - if you add it, remove it.


For DOM Level 0 events, removing it is pretty easy. You nullify it --

<script type="text/javascript">
var someDiv = document.getElementById("SomeDiv");

someDiv.onclick = null; // Set the handler to null

</script>

DOM Level 2 Events
DOM Level 2 event handling supports a number of methods such as addEventListener and removeEventListener. The equivalent methods in IE are attachEvent and detachEvent respectively. We follow the same symmetry with Level 2 events. We add events like this ( with the IE methods ) --

obj.attachEvent( 'onclick', handleClick );

then, we do this to remove them --

obj.detachEvent('onclick', handleClick);

A generic way to do this is to use a Singleton object that abstracts how to add or remove events so you don't have to worry about the browser you're using --



It's best to cleanup the events when you "unload" from a page. Listen for the unload event and when that occurs, have your event handler remove the event handlers.

Here's a DOM Level 0 example and here's a DOM Level 2 example for you to try.

I hope that this is something you can use in your own code.

Have fun!