I started playing around with a few different things in Flex and decided the features would make a good tutorial - or at least an interesting one. The main item on the agenda today is to talk about PopUpManager and creating pop ups. In Flex you can basically create a pop up out of any Flex component that is created, so in this tutorial I am going to show how to create a pop up menu in Flex that will allow us to edit text attributes of selected text inside of a text area.
Some other items that will be making an appearance in this tutorial include TextRange, css, embedding images, and more. Some or all of these features have been touched upon in earlier tutorials but don't worry, I won't skip over explaining them here. For example, we are going to use TextRange to handle changing the selected text in our TextArea, which I wrote a tutorial on earlier, check it out here.
The first item of business is checking out the example application of the day. This application shows off only the tip of the iceberg when it comes to pop ups. It has a text box which can be typed in and is also pre-populated with some text. If you simply highlight some text the pop up menu should jump up at you (note - selecting text using "Shift" key doesn't work). On the menu you have the option to change the selected text to bold, italic, change the color, increase font size, and decrease font size. Also the X in the right hand corner will close the menu. One added perk is the far left side of the menu, it has a couple little circles, can be used to move the menu; you can simply click in that side area and drag around the menu. Well that is enough talk - so it check it out:
Now that you have played for a minute - on to the code. As usual we will start by setting up the initial application interface. Again it is initialized to a very simple interface to start off with. The basic application with a panel and a TextArea - the text area you see in the example has some more text in it but that is all that is different. The only other item that might catch your eye is the <Style> tag, this just says we are going to use a style sheet to style the application.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="305" height="364">
<mx:Style source="style.css" />
<mx:Panel x="0" y="0" width="305" height="364" layout="absolute"
title="Text Edit PopUps">
<mx:TextArea x="10" y="10" width="265" height="304" id="txtMain">
<mx:text><![CDATA[text]]></mx:text>
</mx:TextArea>
</mx:Panel>
</mx:Application>
The application now has a basic layout, next on the agenda is creating the custom component that will popup. This can basically be any custom component which means it can be based off of almost any Flex component. I choose to base mine off of HBox and added a canvas and an VBox. Then in the VBox I added a couple HBox components. These are just used to layout the menu nicely. We are going to use the canvas for a drag handle and then inside the final HBox components there are a few buttons used for the different items on the menu.
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="76" height="49"
styleName="textPopUp" verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:Canvas height="100%" width="5" styleName="textPopUpDragArea"
mouseDown="startDrag();" mouseUp="stopDrag()"/>
<mx:VBox width="70" height="49" verticalScrollPolicy="off"
horizontalScrollPolicy="off" styleName="textPopUpButtonArea" >
<mx:HBox height="24" horizontalGap="0" paddingTop="1" paddingLeft="1">
<mx:Button id="butFontSizeUp" height="22" width="22"
styleName="fontUpButton" />
<mx:Button id="butFontSizeDown" height="22" width="22"
styleName="fontDownButton" />
<mx:Button id="butClose" height="22" width="22" styleName="closeButton" />
</mx:HBox>
<mx:HBox height="24" horizontalGap="0" paddingLeft="1">
<mx:Button id="butBold" height="22" width="22" styleName="boldButton" />
<mx:Button id="butItalic" height="22" width="22"
styleName="italicButton" />
<mx:ColorPicker id="butColorPick" height="22" width="22"
change="changeFontColor()" />
</mx:HBox>
</mx:VBox>
</mx:HBox>
Ok, so let's now work on getting that component popped up on the screen. For this task we are going to use PopUpManager - this class lets us pop up a window on our stage, move them up and down, and remove them. If you want more specific info you can check out the livedocs page. In this tutorial we are going to use two functions of this class, createPopUp and removePopUp. To trigger a pop up we are going to add an event handler to the TextArea for the click event. This function is named popUpTextMenu. The next TextArea code looks like the following:
<mx:text><![CDATA[[text]]></mx:text>
</mx:TextArea>
We now create the actionscript function, where we first throw some <Script> tags under our opening application tag. The first thing inside the script is importing the two items we will be using then we create a private variable for the pop up menu that is being created and used. Next we actually create the function. The function takes no arguments and returns nothing. Inside the function we are going to check a couple things first to make sure we are actually going to create a pop up and that one is not already in use. The first check is checking to make sure some text is actually selected. Then if that is the case we then check to see if the pop up has never been made or that it is not in use (don't worry we will go over the in use in a minute). If we get through all that then it is time to create a pop up.
To do this we call PopUpManager.createPopUp with the arguments this and TextModPopUp. The first parameter is the parent class and the second is the class name of the pop up we want to create. With this we cast it as a TextModPopUp because the function returns an IFlexDisplayObject. That pretty much takes care of the heavy lifting. After that function call we set a couple parameters of our pop up and move it close to the cursor. The important parameter is setting the current text which again we will see here in a minute. The final product is some actionscript that looks very much like what is below.
<![CDATA[
import mx.controls.textClasses.TextRange;
import mx.managers.PopUpManager;
private var textPopUp:TextModPopUp
private function popUpTextMenu():void
{
if(txtMain.selectionEndIndex != txtMain.selectionBeginIndex)
{
if(!textPopUp || !textPopUp.inUse)
{
textPopUp = TextModPopUp(PopUpManager.createPopUp(this, TextModPopUp));
textPopUp.inUse = true;
textPopUp.currentText = new TextRange(txtMain, true,
txtMain.selectionBeginIndex, txtMain.selectionEndIndex - 1);
textPopUp.move(mouseX + 10, mouseY + 10);
}
}
}
]]>
</mx:Script>
All of that will take care of the main file, now we can finish up our custom pop up component. The first step is adding these properties that we used above. They are currentText and inUse - these are used to modify the text from inside our component here and defining whether the pop up is currently being used. We use a TextRange object to take care of modifying the text - I wrote an earlier tutorial on using this object this which can be found here. So these two along with a couple imports and we have the start of our script for this component. The following <Script> tag goes right below the opening application tag.
<![CDATA[
import mx.managers.PopUpManager;
import mx.controls.textClasses.TextRange;
public var currentText:TextRange;
public var inUse:Boolean = false;
]]>
</mx:Script>
Next we are going to create the functions to modify the text. These functions don't do any crazy heavy lifting or anything so I am going to just throw them out there. Each will modify the current text in a different way, they are very self explanatory. These also go in the script tag.
{
currentText.fontSize++;
}
private function decreaseFontSize():void
{
currentText.fontSize--;
}
private function boldFont():void
{
if(currentText.fontWeight != "bold")
currentText.fontWeight = "bold"
else
currentText.fontWeight = "normal";
}
private function italicFont():void
{
if(currentText.fontStyle != "italic")
currentText.fontStyle = "italic";
else
currentText.fontStyle = "normal";
}
private function changeFontColor():void
{
currentText.color = butColorPick.selectedColor;
}
The last function we are going to write up is going to take care removing the pop up. This will call PopUpManager.removePopUp which will remove whatever pop up is passed into the function. Also in this function we set the inUse to false because we aren't using it any more. And the final actionscript function looks like:
{
inUse = false;
PopUpManager.removePopUp(this);
}
The final addition to the custom component is hooking up the buttons to the correct functions. We use the click event for the buttons and the change event for the ColorPicker. And finally we hook up click and release on the canvas to start and end dragging of the pop up. Again nothing special is going on so lets get to the code. This is actually the final iteration of the file so I will throw the whole thing out there.
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml" width="76" height="49"
styleName="textPopUp" verticalScrollPolicy="off" horizontalScrollPolicy="off">
<mx:Script>
<![CDATA[
import mx.managers.PopUpManager;
import mx.controls.textClasses.TextRange;
public var currentText:TextRange;
public var inUse:Boolean = false;
private function increaseFontSize():void
{
currentText.fontSize++;
}
private function decreaseFontSize():void
{
currentText.fontSize--;
}
private function boldFont():void
{
if(currentText.fontWeight != "bold")
currentText.fontWeight = "bold"
else
currentText.fontWeight = "normal";
}
private function italicFont():void
{
if(currentText.fontStyle != "italic")
currentText.fontStyle = "italic";
else
currentText.fontStyle = "normal";
}
private function changeFontColor():void
{
currentText.color = butColorPick.selectedColor;
}
private function closeMe():void
{
inUse = false;
PopUpManager.removePopUp(this);
}
]]>
</mx:Script>
<mx:Canvas height="100%" width="5" styleName="textPopUpDragArea"
mouseDown="startDrag();" mouseUp="stopDrag()"/>
<mx:VBox width="70" height="49" verticalScrollPolicy="off"
horizontalScrollPolicy="off" styleName="textPopUpButtonArea" >
<mx:HBox height="24" horizontalGap="0" paddingTop="1" paddingLeft="1">
<mx:Button id="butFontSizeUp" height="22" width="22"
styleName="fontUpButton" click="increaseFontSize()" />
<mx:Button id="butFontSizeDown" height="22" width="22"
styleName="fontDownButton" click="decreaseFontSize()" />
<mx:Button id="butClose" height="22" width="22"
styleName="closeButton" click="closeMe()" />
</mx:HBox>
<mx:HBox height="24" horizontalGap="0" paddingLeft="1">
<mx:Button id="butBold" height="22" width="22"
styleName="boldButton" click="boldFont()" />
<mx:Button id="butItalic" height="22" width="22"
styleName="italicButton" click="italicFont()" />
<mx:ColorPicker id="butColorPick" height="22" width="22"
change="changeFontColor()" focusThickness="0" />
</mx:HBox>
</mx:VBox>
</mx:HBox>
The ending piece in this tutorial that we are going to hit on is the css file, which I will show here and then we will touch on a few items.
.textPopUp
{
background-color: #F5F5F5;
horizontal-gap: 0;
}
.textPopUpDragArea
{
background-image: Embed("assets/popup_handle.gif");
border-style: solid;
border-color: #868686;
border-thickness: 1;
}
.textPopUpButtonArea
{
vertical-gap: 0;
border-style: solid;
border-color: #868686;
border-thickness: 1;
}
.boldButton
{
up-skin: Embed("/assets/but_bold_up.gif");
over-skin: Embed("/assets/but_bold_hover.gif");
down-skin: Embed("/assets/but_bold_down.gif");
}
.italicButton
{
up-skin: Embed("/assets/but_italic_up.gif");
over-skin: Embed("/assets/but_italic_hover.gif");
down-skin: Embed("/assets/but_italic_down.gif");
}
.fontUpButton
{
up-skin: Embed("/assets/but_fontup_up.gif");
over-skin: Embed("/assets/but_fontup_hover.gif");
down-skin: Embed("/assets/but_fontup_down.gif");
}
.fontDownButton
{
up-skin: Embed("/assets/but_fontdown_up.gif");
over-skin: Embed("/assets/but_fontdown_hover.gif");
down-skin: Embed("/assets/but_fontdown_down.gif");
}
.closeButton
{
up-skin: Embed("/assets/close_up.png");
over-skin: Embed("/assets/close_over.png");
down-skin: Embed("/assets/close_over.png");
}
The main piece of the file is just skinning the buttons. The other items are styling the other aspects of the pop up box. That pretty much just leaves us with a small Wonkalicious application. The main file ends up looking like the following.
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
width="305" height="364">
<mx:Style source="style.css" />
<mx:Script>
<![CDATA[
import mx.controls.textClasses.TextRange;
import mx.managers.PopUpManager;
private var textPopUp:TextModPopUp
private function popUpTextMenu():void
{
if(txtMain.selectionEndIndex != txtMain.selectionBeginIndex)
{
if(!textPopUp || !textPopUp.inUse)
{
textPopUp = TextModPopUp(PopUpManager.createPopUp(this, TextModPopUp));
textPopUp.inUse = true;
textPopUp.currentText = new TextRange(txtMain, true,
txtMain.selectionBeginIndex, txtMain.selectionEndIndex - 1);
textPopUp.move(mouseX + 10, mouseY + 10);
}
}
}
]]>
</mx:Script>
<mx:Panel x="0" y="0" width="305" height="364" layout="absolute"
title="Text Edit PopUps">
<mx:TextArea x="10" y="10" width="265" height="304" id="txtMain"
click="popUpTextMenu()">
<mx:text><![CDATA[text]]></mx:text>
</mx:TextArea>
</mx:Panel>
</mx:Application>
Also I have zipped up the source and assets and they can be downloaded from here. If you have any questions or concerns drop a line.
10/16/2007 - 01:17
Excellent tutorials, very useful and helpful. I am really interesting in the recent Flex and AIR releases. Thanks for sharing, this helps greatly..
02/03/2008 - 22:33
Thanks - great tutorial.
One small issue with selecting text in general, though...
If I select some text but only release the mouse button outside the text area, then the popup does not show.
I've tried doing things like detecting for the mouseOut event, but this is no good because further moving of the mouse outside the text area can cause the selection to change.
Any ideas on how to overcome this?
06/02/2008 - 04:51
I wuz searching all over for info on how to change a popup's position. Thanks!
06/10/2008 - 04:09
Great information on popups..
I have a requirement where in i need to open a in a popup window. I heard that i can open only in a popup window.
If i am wrong then how can i acheive this?
Please do help me in achieving this.
Thanks in advance.
12/12/2008 - 04:17
Its a really helpful and cool tutorial. Thanks !!!!
06/26/2009 - 09:14
any license?
06/26/2009 - 09:51
Here's our licence page.
Add Comment
[language] [/language]
Examples:
[javascript] [/javascript]
[actionscript] [/actionscript]
[csharp] [/csharp]
See here for supported languages.
Javascript must be enabled to submit anonymous comments - or you can login.