Flex Tab Navigator with Close Buttons

We are working on an application over here that would benefit from having tabbed navigation. To my dismay the Tab Navigator component in Flex does not support this, so you really have to do a bit of lifting yourself. (Gawd! imaging having to actually create something! ). Sarcasm aside, a quick web search brought up this tutorial from Keun Lee , showing a tab close button that is added to the application container when you mouse over the tabBar object of the TabNavigator. While it’s not as pretty as elegant the TabNavigator class itself, Keuns tutorial is quite a bit faster. Since this tutorial does not contain any code, I thought I might post up what we’ve done here.

The core concept is to create an instance of your close tab button when you mouse over the tabBar object of the TabNavigator. I simply created the listener on the TabNavigator itself:

this.tabBar.addEventListener(MouseEvent.MOUSE_OVER, createCloseButtons);
this.tabBar.addEventListener(MouseEvent.MOUSE_OUT, removeCloseButtons);

The next two functions really just simply utilize two variables, closeBtn an extended button customized for use on the tab, and a Boolean variable buttonShow set to false that simply indicates if you are on the button or not. This little vat might not seem necessary, but I’ll explain as we go along. So for brevity, I’ll leave out the function signature and just give you the body of createCloseButton:

if(buttonShow == false){
//creates the custom button
closeBtn = new tabCloseButton();
//add a name to id the button
closeBtn.name = “closeBtn“;
//get the index of the moused over tab
mouseOverIndex = this.tabBar.getChildIndex(this.tabBar.getChildByName(event.target.name));
//Target the tab that the mouse is over
tabButton = this.tabBar.getTabAt(mouseOverIndex);
//generate the insertPoint
insertPoint = new Point(_lotWorkspace.x,_lotWorkspace.y);
//add coordinae to closeBtn
closeBtn.x = (tabButton.x + this.localToGlobal(insertPoint).x + tabButton.width – 20);
closeBtn.y = (tabButton.y + this.localToGlobal(insertPoint).y + 5);
//add an event listener
closeBtn.addEventListener(MouseEvent.CLICK, closeRequestHandler);
//add the button
mx.core.Application.application.addChild(closeBtn);
//set the Boolean
buttonShow = true;}

So okay, now you’re (hopefully) adding buttons to your TabNavigator component. But you’ve got nothing to remove the buttons, and things up there are looking a little fuzzy. Enter function removeCloseBtn. This function is much shorter but a bit tricky. You see if you move your mouse from the tabBar onto the closeBtn, you are essentially firing off a mouseOut event. If you simply remove the close button at this point, the mouse is back on the tabBar, which was underneath the close button the whole time. Without some conditionals, you’ll be stuck with a crazy flickering closeBtn, and it will give you a seizure. So here’s the removeCloseBtn function:

if(event.relatedObject.name != “closeBtn“){
mx.core.Application.application.removeChild(closeBtn);
buttonShow = false;}

Do a trace and check out the relatedObject property in the MouseEvent. It’s pretty critical in this technique. Basically it allows you to see if you are firing a mouseOut from this.tabBar because you are on the closeBtn or not. And if you’re not about to click the closeBtn, remove it.

Well thats about it. I know this is really not the most elegant solution out there, but it works well, and you don’t have to write a whole bunch of code to get it run properly. Happy Coding – I’m going to get some coffee!

About Curious Minds
We are a web development firm in New York and Chicago, providing development resources and consulting for websites and mobile apps since 2004.