Friday, March 23, 2012

Flex 4: Auto Resize Text Area

In flex 4.0, you can easily create a resizeable text area by setting the property 'heightInLines' with a value of NaN. (I was pretty excited with this property and it really works.) But, when I update my flex version to 4.1 and beyond, this property doesn't really work as per what I had expected and after spending some time debugging and googling, it seems that this property has been ceased. Therefore I have created a temporary solution to a auto resize text area.

Sour codes for the resizeable Text Area Component:
<?xml version="1.0" encoding="utf-8"?>
<s:TextArea xmlns:fx="http://ns.adobe.com/mxml/2009" 
   xmlns:s="library://ns.adobe.com/flex/spark" 
   xmlns:mx="library://ns.adobe.com/flex/mx"
   width="0" height="0" 
    creationComplete="creationCompleteHandler(event)"
   widthInChars="1" heightInLines="1"
   change="changeHandler(event)"
      paddingBottom="2" paddingLeft="2" 
   paddingRight="2" paddingTop="2"
    borderVisible="false" contentBackgroundAlpha="0"
   selectable="false" editable="false" 
   initialize="initializeHandler(event)"
   verticalScrollPolicy="auto" horizontalScrollPolicy="auto">
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.compose.TextFlowLine;
   import flashx.textLayout.conversion.TextConverter;
   import flashx.textLayout.edit.SelectionManager;
   import flashx.textLayout.elements.TextFlow;
   import flashx.textLayout.elements.TextRange;
   
   import mx.core.IUITextField;
   import mx.core.UIComponent;
   import mx.events.FlexEvent;
   
   import spark.components.RichEditableText;
   import spark.events.TextOperationEvent;
   import spark.utils.TextFlowUtil;
   
   //Variables to store the default width and height
   //of this textfield.
   private var _textWidth:Number = 0;
   private var _textHeight:Number = 0;
   
   private var _autoResizeH:Boolean = false;
   
   //Autoresize the height of the text
   //This property will be used to determine
   //whether u need to resize the height of this
   //textfield.
   public function get autoResizeH():Boolean
   {
    return _autoResizeH;
   }
   
   public function set autoResizeH(value:Boolean):void
   {
    _autoResizeH = value;
    if(_autoResizeH)
    {
     resizeContent();
    }
   }
   
   //Autoresize the width of the text
   //This property is pretty much redundant.
   private var _autoResizeW:Boolean = false;
   
   public function get autoResizeW():Boolean
   {
    return _autoResizeW;
   }
   
   public function set autoResizeW(value:Boolean):void
   {
    _autoResizeW = value;
    if(_autoResizeW)
    {
     resizeContent();
    }
   }
   
   //Autoresize the width and height of the text
   //This property will touch on both width and height
   //of this textfield. Rather than using
   //autoResizeW and autoResizeH, use this instead.
   private var _autoResize:Boolean = false;
   
   public function get autoResize():Boolean
   {
    return _autoResize;
   }
   
   public function set autoResize(value:Boolean):void
   {
    _autoResizeW = value;
    _autoResizeH = value;
    _autoResize = value;
    if(_autoResize)
    {
     resizeContent();
    }
   }
   
   //Override the default text function of a TextArea
   override public function set text(value:String):void
   {
    super.text = value;
    if(_autoResize)
    {
     resizeContent();
    }
   }
   
   //Create a new property for htmlText like what we have
   //in Flex 3.
   private var _htmlText:String = "";
   
   public function set htmlText(value:String):void
   {
    _htmlText = value;
    textFlow = TextConverter.importToFlow(value,
     TextConverter.TEXT_FIELD_HTML_FORMAT);
    if(_autoResize)
    {
     resizeContent();
    }
   }
   
   public function get htmlText():String
   {
    return _htmlText;
   }
   
   //This function will handle all the resizing.
   private function resizeContent():void
   {
    if(textFlow)
    {
     if(_autoResizeH && text != "" 
      && (_textHeight == 0 || isNaN(_textHeight)))
     {
      height = NaN;
      var tempToggle:Boolean = false;
      if(!editable)
      {
       tempToggle = true;
      }
      editable = true;
      textFlow.flowComposer.composeToPosition();              
      textFlow.flowComposer.updateAllControllers();
      if(tempToggle)
      {
       editable = false;
      }
      heightInLines = textFlow.flowComposer.numLines;
      validateNow();
     }
     if(_autoResizeW && text != "" 
      && (_textWidth == 0 || isNaN(_textWidth)))
     {
      width = NaN;
      typicalText = text;
      validateNow();
     }
    }else if(textDisplay){
     if(_autoResizeH && text != "" 
      && (_textHeight == 0 || isNaN(_textHeight)))
     {
      RichEditableText(textDisplay).height = NaN;
      RichEditableText(textDisplay).heightInLines = NaN;
      RichEditableText(textDisplay).validateNow();
      this.validateNow();
     }
     if(_autoResizeW && text != "" 
      && (_textWidth == 0 || isNaN(_textWidth)))
     {
      RichEditableText(textDisplay).width = NaN;
      RichEditableText(textDisplay).widthInChars = text.length;
      RichEditableText(textDisplay).validateNow();
      validateNow();
     }
    }
   }
   
   //On CreationComplete, check if resizing is needed.
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    if(_autoResize)
    {
     resizeContent();
    }
   }
   
   //On Change, check if resizing is needed.
   protected function changeHandler(event:TextOperationEvent):void
   {
    if(_autoResize)
    {
     resizeContent();
    }
   }

   //Store the default width and height of this textfield.
   //Note: we need the default width and height when I'm
   //Resizing the Textfield, or when resizeContent() has
   //been executed.
   protected function initializeHandler(event:FlexEvent):void
   {
    if(width != _textWidth)
    {
     _textWidth = width;
    }
    if(height != _textHeight)
    {
     _textHeight = height;
    }
   }
  ]]>
 </fx:Script>
</s:TextArea>

And here's the source codes for my main application.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      xmlns:mx="library://ns.adobe.com/flex/mx"
      xmlns:CommonControls="CommonControls.*"
      viewSourceURL="srcview/index.html">
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <fx:Script>
  <![CDATA[
   //Dummy normal text
   [bindable]
   private var basicText:String = "Lorem ipsum dolor sit amet, " +
    "consectetur adipiscing elit. Fusce quis risus pellentesque " +
    "ipsum venenatis luctus a quis nulla. Cras rhoncus turpis " +
    "vel ligula iaculis sagittis. Donec eget dolor ac lectus " +
    "pharetra convallis et vitae eros. Pellentesque vestibulum " +
    "nisl ut dolor malesuada vel dictum sem ultricies. Ut " +
    "scelerisque mollis quam eu luctus. Curabitur erat massa, " +
    "accumsan sed adipiscing et, mollis quis lectus. Suspendisse " +
    "nec mauris quis mi varius ultricies at eleifend massa.";
   
   //Dummy HTML encoded text
   [bindable]
   private var specialText:String = "<b>Lorem ipsum dolor sit</b> " +
    "amet, <a target='_blank' href='http://www.google.com'>" +
    "consectetur</a> adipiscing elit. Fusce quis risus " +
    "pellentesque ipsum venenatis luctus a quis nulla. Cras " +
    "rhoncus turpis vel ligula iaculis sagittis. Donec eget " +
    "dolor ac lectus pharetra convallis et vitae eros. " +
    "Pellentesque vestibulum nisl ut dolor malesuada vel dictum " +
    "sem <b><a target='_blank' href='http://www.google.com'>" +
    "ultricies</a></b>. Ut scelerisque mollis quam eu luctus. " +
    "Curabitur erat massa, accumsan sed adipiscing et, mollis " +
    "quis lectus. Suspendisse nec mauris quis mi varius ultricies " +
    "at eleifend massa.";
  ]]>
 </fx:Script>
 <s:BorderContainer width="100%" height="100%">
  <s:layout>
   <s:VerticalLayout verticalAlign="middle" 
         horizontalAlign="center"
         gap="0"/>
  </s:layout>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Basic Text with w='100%' h='100%' 
      and autoresize='true':" paddingTop="3"/>
   <CommonControls:CustomTextArea text="{basicText}"
             width="100%" 
             height="100%" 
             autoResize="true"/>
  </s:BorderContainer>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Basic Text with w='350' h='100':" 
      paddingTop="3"/>
   <CommonControls:CustomTextArea text="{basicText}"
             width="350" 
             height="100" />
  </s:BorderContainer>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Basic Text with w='350'
      and autoresize='true':" paddingTop="3"/>
   <CommonControls:CustomTextArea text="{basicText}"
             width="350" 
             autoResize="true"/>
  </s:BorderContainer>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Html Text with w='100%' h='100%' 
      and autoresize='true':" paddingTop="3"/>
   <CommonControls:CustomTextArea htmlText="{specialText}"
             width="100%" 
             height="100%" 
             autoResize="true"/>
  </s:BorderContainer>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Html Text with w='350' h='100':" 
      paddingTop="3"/>
   <CommonControls:CustomTextArea htmlText="{specialText}"
             width="350" 
             height="100" />
  </s:BorderContainer>
  <s:BorderContainer width="100%">
   <s:layout>
    <s:HorizontalLayout verticalAlign="top" 
         horizontalAlign="left" 
         paddingLeft="2" 
         paddingRight="2"
         gap="0"/>
   </s:layout>
   <s:Label width="200" height="100%" 
      text="Html Text with w='350'
      and autoresize='true':" paddingTop="3"/>
   <CommonControls:CustomTextArea htmlText="{specialText}"
             width="350" 
             autoResize="true"/>
  </s:BorderContainer>
 </s:BorderContainer>
</s:Application>

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Thursday, March 15, 2012

Flex: Drawing Shapes in Flex

Every single shape in this world are made out of simple shapes like circles, triangles and squares. Therefore, there might be situations where a coded shape or graphic can turn out to be much much more useful and flexible and lighter (in terms of the files size) than a normal image file(*.png, *.jpg, etc...). As for this week, I'm going to show you the steps in creating a simple Shape in flex.

Source codes for the main application
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute"
     creationComplete="creationCompleteHandler(event)">
 <mx:Script>
  <![CDATA[
   import com.shapes.ShapeClass;
   
   import mx.core.UIComponent;
   import mx.events.FlexEvent;
   
   //Array to store a list of blue colors
   private var blueColorArray:Array = [0xFFFFFF, 0xEEEEFF, 
    0xDDDDFF, 0xCCCCFF, 0xBBBBFF, 0xAAAAFF,
    0x8888FF, 0x6666FF, 0x4444FF, 0x2222FF];
   private var blueColorCount:int = 0;
   
   //Array to store a list of black colors
   private var blackColorArray:Array = [0xFFFFFF, 0xCCCCCC, 
    0x999999, 0x666666, 0x333333, 0x000000];
   private var blackColorCount:int = 0;   
   
   //A timer that will be used to draw the Shapes
   //over and over again.
   private var timer:Timer = new Timer(100,0);
   
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    timer.addEventListener(TimerEvent.TIMER, executeTimer);
    executeTimer();
   }
   
   //Function that will return an array of colors
   //based on the starting point, so that the Shapes
   //will appear to be animating
   private function getBlueColorsArray(tempColorArray:Array, 
            tempCount:int):Array
   {
    var tempArray:Array = new Array();
    for(var i:int = tempCount; 
     i < tempColorArray.length; i ++)
    {
     tempArray.push(tempColorArray[i]);
    }
    for(i = 0; i < tempCount; i ++)
    {
     tempArray.push(tempColorArray[i]);
    }
    return tempArray;
   }
   
   //This function will be trigger once the timer has 
   //run finish a cycle.
   private function executeTimer(event:Event = null):void
   {
    //Stops the timer first.
    if(timer.running)
    {
     timer.stop();
    }
    //Remove all the graphics and draw a new Shape
    layer1.removeAllChildren();
    layer1.addChild(ShapeClass.drawCircleTower(50, 
     getBlueColorsArray(blueColorArray, blueColorCount)));
    //Remove all the graphics and draw a new Shape
    layer2.removeAllChildren();
    layer2.addChild(ShapeClass.drawCircleTower(layer2.width, 
     getBlueColorsArray(blackColorArray, blackColorCount)));
    //As the shape is position at (0,0) we will need to
    //reassign the position of the shape everytime we draw
    //it so that the shape will always appear on the point
    //(10,10).
    layer3.removeAllChildren();
    var tempDisplayObject:DisplayObject;
    tempDisplayObject = layer3.addChild(
     ShapeClass.drawCircle(layer3.width/2,
     blueColorArray[Math.round(Math.random()*
      (blueColorArray.length - 1))],
     true));
    tempDisplayObject.x = layer3.width/2;
    tempDisplayObject.y = layer3.height/2;
    blueColorCount ++;
    if(blueColorCount >= blueColorArray.length)
    {
     blueColorCount = 0;
    }
    blackColorCount ++;
    if(blackColorCount >= blackColorArray.length)
    {
     blackColorCount = 0;
    }
    timer.start();
   }
   
  ]]>
 </mx:Script>
 <mx:Canvas width="100%" height="100%">
  <mx:VBox width="100%" height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
   <mx:Canvas id="layer1"/>
  </mx:VBox>
  <mx:Canvas width="100%" height="100%">
   <mx:Canvas id="layer3"  
        width="150" height="150"
        top="10" left="10"/>
   <mx:Canvas id="layer2" 
        width="100" height="100"
        right="10" bottom="10"/>
  </mx:Canvas>
 </mx:Canvas>
</mx:Application>

Source codes for a Shape Class that I have written:
package com.shapes
{
 import flash.display.Shape;
 
 import mx.core.UIComponent;

 public class ShapeClass
 {
  public function ShapeClass()
  {
  }
  
  /**
   * 
   * @param radius - radius of the circle 
   * @param color - fill color of the circle
   * @param createView - do you need this function
   * to return a view that can be added to any view
   * or a Shape using (0,0) as the midpoint.
   * @return either a Shape or a View
   * 
   */  
  public static function drawCircle(radius:int, 
            color:uint,
            createView:Boolean = false):*
  {
   var shape:Shape = new Shape();
   shape.graphics.beginFill(color,1);
   shape.graphics.drawCircle(0,0,radius);
   shape.graphics.endFill();
   if(createView)
   {
    var tempUI:UIComponent = new UIComponent();
    tempUI.addChild(shape);
    return tempUI;
   }else{
    return shape;
   }
  }
  
  /**
   * 
   * @param radius - radius of the circle 
   * @param colors - an array of colors of this Shape
   * @return a view that shows a sequence of Circles
   * using (0,0) as the midpoint.
   * 
   */  
  public static function drawCircleTower(radius:int, 
              colors:Array):*
  {
   var length:int = colors.length;
   var diff:Number = radius / length;
   var tempUI:UIComponent = new UIComponent();
   var tempShape:Shape = null;
   for(var i:int = 0; i < length; i ++)
   {
    tempShape = drawCircle(radius - (i * diff),
     colors[i]);
    tempUI.addChild(tempShape); 
   }
   return tempUI;
  }
 }
}
* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Friday, March 9, 2012

Flex: Smart way of Clipping Content

In flex, there are various situation where masking of a content is needed, but yet at the same time, rather than creating a separate Component to work as a mask, they is a property 'clipContent' that allows you to display part of a content too.

Rather than doing some crazy explanation, let us look at a simple demo.

The following would be the source code of the demo.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute"
    width="100%" height="100%"
    creationComplete="creationCompleteHandler(event)">
 
 <mx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   [Embed(source="../assets/image.jpeg")]
   [Bindable]
   public var imgCls:Class;
   
   //Here's the mouse Down handler for the red border box
   //at the same time allows it to be draggable around
   //the canvas
   protected function mouseDownHandler(event:MouseEvent):void
   {
    stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEvent);
    stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    dragger.startDrag(false,
     new Rectangle(0,0,
      dragCanvas.width - dragger.width, 
      dragCanvas.height - dragger.height));
   }
   
   //Here's the mouse Up handler for the red border box
   //stops all the crazy dragging.
   protected function mouseUpHandler(event:MouseEvent):void
   {
    stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEvent);
    stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
    dragger.stopDrag();
   }
   
   //Function to update the position of the main Image
   //base on the position of the draggable red border
   //box.
   private function mouseMoveEvent(event:Event):void
   {
    var maxX:int = dragCanvas.width - dragger.width;
    var maxY:int = dragCanvas.height - dragger.height;
    var minX:int = dragger.width;
    var minY:int = dragger.height;
    var currX:int = (dragger.x + dragger.width - minX);
    var currY:int = (dragger.y + dragger.height - minY);
    currX = Math.ceil((currX / maxX) * 100);
    currY = Math.ceil((currY / maxY) * 100);
    
    maxX = mainImg.width - mainCanvas.width;
    maxY = mainImg.height - mainCanvas.height;
    minX = mainCanvas.width;
    minY = mainCanvas.height;
    mainImg.x = currX * (maxX/100) * -1;
    mainImg.y = currY * (maxY/100) * -1;
   }
   
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    mouseMoveEvent(null);
   }
   
  ]]>
 </mx:Script>
 <mx:HBox width="100%" height="100%"
    verticalAlign="middle" 
    horizontalAlign="center">
  <mx:Spacer width="100%"/>
  <mx:VBox height="100%"
     width="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
   <mx:HBox width="100%" horizontalAlign="center">
    <mx:Label text="Drag the red box around..."/>
   </mx:HBox>
   <mx:Canvas width="150" height="100"
        id="dragCanvas"
        verticalScrollPolicy="off" 
        horizontalScrollPolicy="off">
    <mx:Image source="{imgCls}" 
        width="150" height="100" 
        scaleContent="true" 
        maintainAspectRatio="true"/>
    <mx:Canvas backgroundAlpha="0"
         id="dragger"
         width="20"
         height="20"
         x="0" y="0"
         borderThickness="1"
         borderColor="#FF0000"
         borderStyle="solid"
         backgroundColor="#000000"
         mouseDown="mouseDownHandler(event)"
         mouseUp="mouseUpHandler(event)"/>
   </mx:Canvas>
   <mx:HBox width="100%" horizontalAlign="center">
    <mx:Label text="Clip Main Content?"/>
    <!-- Checkbox used to toggle the clipContent
     property of the main Canvas-->
    <mx:CheckBox id="chkClipContent" 
        selected="true"/>
   </mx:HBox>
  </mx:VBox>
  <mx:VBox width="100%" height="100%"
     verticalAlign="middle" 
     horizontalAlign="center">
   <mx:HBox width="100%" horizontalAlign="center">
    <mx:Label text="Selection is shown here."/>
   </mx:HBox>
   <mx:Canvas id="mainCanvas"
        verticalScrollPolicy="off" 
        horizontalScrollPolicy="off"
        width="80"
        height="80"
        clipContent="{chkClipContent.selected}">
    <mx:Image source="{imgCls}"
        x="0" y="0" id="mainImg"
        scaleContent="false"/>
    <mx:Canvas width="80"
         height="80"
         borderThickness="1"
         borderColor="#FF0000"
         borderStyle="solid"/>
   </mx:Canvas>
  </mx:VBox>
  <mx:Spacer width="100%"/>
 </mx:HBox>
</mx:Application>
* Click here to view the demo of this example.
^ Click here for the source files of this demo.

By the way the following URLs are pretty good in generating dummy contents.

Friday, March 2, 2012

Flex: Accessing a function of a loaded/embedded SWF file

Flex is pretty powerful when it comes to handling and displaying data, but there times when I would still prefer using the WYSIWYG interface of Flash Professional, especially when I just want to create a simple animation. Therefore, I shall show you my method of accessing the functions of a loaded SWF today.

Here's the code of the Main Flex Application.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute" 
    creationComplete="creationCompleteHandler(event)">
 <mx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   //Embed a swf file
   [Embed(source="../assets/simpleAnimation.swf")]
   private var simpleSWF:Class;
   
   //Assign the source of the SWFLoader to the embedded swf
   protected function creationCompleteHandler(event:FlexEvent):void
   {
    swfLoader2.source = simpleSWF;
   }
   
   //Upon clicking on the button, access the swf files that
   //are loaded in swfLoader and pass a parameter into the
   //functions in the swf file.
   //Note: SWF file must be exported in as3 otherwise it
   //don't work.
   protected function clickHandler(event:MouseEvent):void
   {
    var tempSWFLoader:* = getSWFLoaderContent(swfLoader1);
    tempSWFLoader["startMovie"](txtInput.text);
    tempSWFLoader = getSWFLoaderContent(swfLoader2);
    tempSWFLoader["startMovie"](txtInput.text);
   }
   
   //Function that will access the given SWFLoader component
   //and return a direct pointer to the swf file so that you
   //can gain access to the functions inside.
   private function getSWFLoaderContent(tempSWF:SWFLoader):*
   {
    var tempSWFContent:*;
    var tempSWFContent1:*;
    tempSWFContent1 = tempSWF.content;
    tempSWFContent = tempSWFContent1.getChildAt(0);
    tempSWFContent = tempSWFContent.content;
    if(tempSWFContent)
    {
     return tempSWFContent; 
    }else{
     return tempSWFContent1;     
    }
   }   
  ]]>
 </mx:Script>
 <mx:VBox width="100%" height="100%" 
     verticalAlign="middle" 
     horizontalAlign="center">
  <mx:HBox verticalAlign="middle"
      horizontalAlign="center"
      width="100%">
   <mx:Spacer width="100%"/>
   <!-- Load a SWF file on demand -->
   <mx:SWFLoader id="swfLoader1" 
       source="simpleAnimation.swf"/>
   <mx:Spacer width="100%"/>
   <mx:SWFLoader id="swfLoader2"/>
   <mx:Spacer width="100%"/>
  </mx:HBox>
  <mx:TextInput id="txtInput" text="5" restrict="0-9"/>
  <mx:Button id="btnAnimateNow" label="Animate Now!"
      click="clickHandler(event)"/>
 </mx:VBox>
</mx:Application>

And the script inside the SWF file that I am going to load.
In the 1st Frame
stop();
var count:Number;
function startMovie(tempNum)
{
 count = tempNum;
 init();
}

function stopMovie()
{
 this.gotoAndStop(1);
}

function init()
{
 if(count < 0)
 {
  movie_mc.text_txt.text = "";
  count = 0;
  stop();
 }else{
  movie_mc.text_txt.text = count;
  count --;
  this.gotoAndPlay(2);
 }
}
In the last Frame
init();
* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Friday, February 24, 2012

R u ready for the first Mega IT Show in Singapore for the year 2012?

Have a spoilt PC? Mobile Phone? Printer? IT Gadget? Want to get a new replacement? How about spending some time going down to the first IT Show in Singapore for the year 2012?


IT Show 2012

More information about the event:
Date : 8 - 11 March 2012
Venue : Levels 1, 2, 3, 4 & 6
Suntec Convention Hall Singapore
Opening Hours : 12 noon - 9 pm


I wonder... should I or should I not get a new...

* Click here to find out more about 'IT Show 2012'.

Friday, February 17, 2012

AS 3: Handling Text URL Links in the TLF TextField of Flash

It used to be pretty easy in the past. You just need to add a EventListener of TextEvent.LINK to the textfield and you can capture the url that the user has click on. But Adobe have made some new improvements to the TLF Textfield and I am going to show you how to capture the URL that the user has clicked, when it comes to TLF Textfield.

Let us take a look at the source code first.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
      xmlns:s="library://ns.adobe.com/flex/spark" 
      xmlns:mx="library://ns.adobe.com/flex/mx"
      creationComplete="creationCompleteEvent(event)"
      backgroundColor="#CCCCCC">
 <fx:Script>
  <![CDATA[
   import flashx.textLayout.conversion.TextConverter;
   import flashx.textLayout.elements.LinkElement;
   import flashx.textLayout.events.FlowElementMouseEvent;
   
   import mx.events.FlexEvent;
   
   protected function creationCompleteEvent(event:FlexEvent):void
   {
    //Populate the Flex 4 TextArea with some contents
    //Follow with a Listener for clicking on urls.
    var htmlText:String = "Click <a " +
     "href='http://nekyouto-tech.blogspot.com/'>" +
     "here</a> for my blog.";    
    txt.textFlow = TextConverter.importToFlow(htmlText,
     TextConverter.TEXT_FIELD_HTML_FORMAT);
    txt.textFlow.addEventListener(FlowElementMouseEvent.CLICK,
     clickTextURLEvent);
    
    //Populate the Flex 3 TextArea with some contents
    //Follow with a Listener for clicking on urls.
    htmlText = "Click <a " +
     "href='event:http://nekyouto-tech.blogspot.com/'>" +
     "here</a> for my blog.";  
    oldTxt.htmlText = htmlText;
    oldTxt.addEventListener(TextEvent.LINK, clickTextURLEvent);
   }
   
   //A function that will handle the url request from both 
   //TextArea Components
   private function clickTextURLEvent(event:Event):void 
   {
    var url:String;
    
    if(event as TextEvent)
    {
     url = TextEvent(event).text;
    }else if(event as FlowElementMouseEvent){
     var link:LinkElement;
     link = FlowElementMouseEvent(event)
      .flowElement as LinkElement;    
     url = link.href;    
    }
    navigateToURL(new URLRequest(url), "_blank");
    event.stopImmediatePropagation();
    event.preventDefault();
   }
   
  ]]>
 </fx:Script>
 <s:layout>
  <s:VerticalLayout verticalAlign="middle" horizontalAlign="center"/>
 </s:layout>
 <s:Label text="Flex 3 Text Area"/>
 <mx:TextArea id="oldTxt" editable="false" selectable="false"/>
 <s:Spacer height="10"/>
 <s:Label text="Flex 4 Text Area"/>
 <s:TextArea id="txt" editable="false" selectable="false"/>
</s:Application>

The result of the above will show a Flex 3 TextArea followed by a Flex 4 TextEvent.
Observe how the codes differ.

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

Friday, February 10, 2012

AS3: Playing with Regular Expressions

How useful can Regular Expressions be? This is a question I have been continuously asking myself. Hence I have done up a simple demo of Regular Expression and you can easily identify how much time it can actually save you.

Let's take a look at the source code first.
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    layout="absolute"
    creationComplete="creationCompleteEvent(event)">
 <mx:Script>
  <![CDATA[
   import mx.events.FlexEvent;
   
   //Dummy text for testing
   [Bindable]
   private var testStr:String = "info@info.com " +
    "apple@apple.com bestkirdape@gmail.com " +
    "best_kird_ape@gmail.com The above are " +
    "dummy email address.";
   //Regular Expression for checking email address
   private var emailRegExp:RegExp = /\b[\w\.-]+@[\w\.-]+\.\w{2,4}\b/gi;
   
   //The pattern you want the text that was found by the
   //Regular Expression to change into.
   private var pattern:String = "<a href='event:mailto:$&'>$&</a>";
   
   //Click Handler for button
   protected function clickHandler(e:MouseEvent):void
   {
    lblResult.htmlText = String(lblInput.text).
     replace(emailRegExp,pattern); 
   }
   
   //Upon clicking on the link in the validated result,
   //open up the email address.
   protected function linkHandler(e:TextEvent):void
   {
    navigateToURL(new URLRequest(e.text),"_self");
   }
   
   //Once the view have been created validate the Dummy text
   //using the Regular Expression and display the result.
   protected function creationCompleteEvent(e:FlexEvent):void
   {
    btnChange.dispatchEvent(
     new MouseEvent(MouseEvent.CLICK));
   }
  ]]>
 </mx:Script>
 
 <mx:VBox width="100%" 
    height="100%"
    paddingLeft="50"
    paddingRight="50"
    paddingBottom="50"
    paddingTop="50"
    verticalAlign="middle"
    horizontalAlign="center">
  <mx:TextInput id="lblInput"
       width="100%"
       height="20%"
       text="{testStr}"/>
  <mx:Button id="btnChange" 
       label="Change Text Now..."
       click="clickHandler(event)"/>
  <mx:TextArea id="lblResult"
      width="100%"
      height="20%"
      link="linkHandler(event)"/>
 </mx:VBox>
</mx:Application>
Although the source codes might look pretty short but it's actually something that was pretty useful.

The user will enter some text into the text field and upon clicking on the button, the program will automatically change all the text into clickable urls. Isn't that great? This have definitely shorten the amount of time required to write out individual functions to create the same effect.

* Click here to view the demo of this example.
^ Click here for the source files of this demo.

~ Click here for one of the best guide to get your way around Regular Expressions.