Learning Flex 4 | O'Reilly Media

Google Search Application in Flex 4

with one comment

Unfortunately, the Yahoo! web services, which we consumed using the ASTRA Flex library and introduced near pages 232-233, are deprecated and discontinued, devaluing the book I realize many of you bought with hard-earned money. In light of this reversal, I applied myself to replacing the YahooSearch example with something comparable.

This alternative arrangement consumes the Google Search API, which is simplified into callable methods exposed through googleas3api.swc—an ActionScript library package created by Joris Timmerman (my apologies if I am incorrect about the creator and maintainer). Because googleas3api is an ActionScript library and not a Flex library, we can’t instantiate  the service component in MXML like we did with the Yahoo! search component (but to be honest, I didn’t even try so maybe I am wrong about that), so this alternate example uses more ActionScript and looks a little different. On the bright side, I believe that is good for you; on the other hand, it will require more of your intuition at timesto understand the similarities and differences between the original YahooSearch code illustrated in the book, which will fail at runtime (i.e. when you perform a search), and this GoogleSearch variation, which looksdifferent in code, but performs as you would expect.

Application: GoogleSearch.mxml

The application requires two supporting libraries—as3corelib.swc and googleas3api.swc. Make sure to download these, unzip if necessary, and copy their SWC files into the “libs” folder of your Flex 4 project.

<?xml version="1.0" encoding="utf-8"?>
    * This project requires two reference libraries.
    * as3corelib.swc:
    *   https://github.com/mikechambers/as3corelib
    *   (Downloads > Download Packages > as3corelib-93.zip)
    *   Find the .swc file in the extracted "lib" folder.
    * googleas3api.swc:
    *   http://code.google.com/p/googleas3api
    *   (Downloads > googleas3api.swc)
    * Copy/paste or drag/drop these into the "libs" folder
    * for this Flex 4 project.
   import be.boulevart.google.ajaxapi.search.GoogleSearchResult;
   import be.boulevart.google.ajaxapi.search.web.GoogleWebSearch;
   import be.boulevart.google.events.GoogleAPIErrorEvent;
   import be.boulevart.google.events.GoogleApiEvent;
   import mx.collections.ArrayCollection;
   private var googleSearch:GoogleWebSearch;
   private var searchResultAC:ArrayCollection;
   private function onComplete():void
    googleSearch = new GoogleWebSearch();
       GoogleApiEvent.WEB_SEARCH_RESULT, searchResult);
       GoogleAPIErrorEvent.API_ERROR, searchFault);
   private function onSearch():void
    // See the API library example here..
    // http://code.google.com/p/googleas3api
    // "en" means English
    // ..try "de", which is Danish, etc..
    googleSearch.search(queryTI.text, 0, "en");
    // you can also leave the string out, which may
    // allow Google to introspect by IP and "guess"
    // the correct language (I am supposing this):
    //  googleSearch.search(queryTI.text, 0);
   private function searchResult(event:GoogleApiEvent):void
    // Cast the event.data response as GoogleSearchResult
    // to enable code completion and compile-time error checking.
    var searchResult:GoogleSearchResult;
    searchResult = event.data as GoogleSearchResult;
    // searchResult.results is an Array, so we can pass it
    // into a new ArrayCollection and use it as a dataprovider.
    searchResultAC = new ArrayCollection(searchResult.results);
    resultsList.dataProvider = searchResultAC;
   private function searchFault(event:GoogleAPIErrorEvent):void
    // Catch search faults and trace to the console.
 <s:VGroup left="10" right="10" top="10" bottom="10">
  <s:Label text="Google Search:" fontWeight="bold"/>
   <mx:FormItem label="Query:" fontWeight="bold">
    <s:TextInput id="queryTI" width="350"/>
    <s:Button id="searchButton" label="Search"
  <s:List id="resultsList" width="100%" height="100%"


The ItemRenderer used in the application is created using the same approach described in pages 235-238. However, note the use of the Ternary Operator to create a shorthand if..then conditional statement; this is described on page 354 as an inline if..then for use in MXML code, but here I’m demonstrating its use in an ActionScript-only context.

Note: To work with the application code, above, this custom ItemRenderer needs to be created in the default package (i.e. the local package), the same folder as GoogleSearch.mxml.

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
   import be.boulevart.google.ajaxapi.search.web.data.GoogleWebItem;
   import flashx.textLayout.conversion.TextConverter;
   private function onComplete():void
    // Cast the data record as GoogleWebItem to expose
    // code commpletion and enjoy tighter compile-time
    // error-checking. We could use object notation
    // on the data variable like this..
    //   urlLabel.text = "From: " + data.url;
    // but casting the object is preferred.
    var item:GoogleWebItem = data as GoogleWebItem;
    urlLabel.text = "From: " + item.url;
    // Create "content teaser" with no more than 100 chars..
    var teaserString:String=item.title + " | " + item.content;
    // Shorthand if..then using the ternary operator..
    // See pg. 354 for background on this syntax.
    teaserString = (teaserString.length>99)
        ? teaserString.substr(0,99)+"..[more].."
        : teaserString ;
    contentTA.textFlow = TextConverter.importToFlow(teaserString,
   private function onClick(event:MouseEvent, url:String):void
    var urlRequest:URLRequest = new URLRequest(url);
    navigateToURL(urlRequest, "_blank");
 <s:VGroup width="100%" gap="2" paddingTop="2" paddingBottom="2">
  <s:Label id="urlLabel" fontWeight="bold" buttonMode="true"
     click="onClick(event, data.url);"/>
  <s:TextArea id="contentTA" width="100%" heightInLines="1"
     editable="false" selectable="false"


Written by elrobis

29 September 2011 at 10:06 am

Posted in AIR, Flex 4

Load PDF Content into an AIR Application

with 6 comments

It’s deceptively simple to load a PDF file into an AIR appliction. Basically, point an HTMLLoader at a URLRequest—which can take a local file path—add the HTMLLoader to a UIComponent, then add the UIComponent to a container.

In this case, I added the UIComponent directly to the application, but it stands to reason you could put it in any container.

Flex 4 / AIR Application Code

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication title="PDF Viewer"
      height="600" width="525"

<s:Button label="Load The PDF" click="loadPdf(path)" top="4" left="4"/>

<s:Button label="Close The PDF" click="closePdf()" top="4" right="4"/>

  import mx.core.FlexGlobals;
  import mx.core.UIComponent;

  private var pdfUIC:UIComponent;

  // double forward-slashes necessary for win file paths..
  private var path:String = "C:\\pdf_files\\original\\filename.pdf";

  private function loadPdf(fullPathToPDF:String):void
    var pdfRequest:URLRequest = new URLRequest(fullPathToPDF);
    var pdfHTMLLoader:HTMLLoader = new HTMLLoader();

    // 1) load the PDF into an HTMLLoader (Air-only)
    pdfHTMLLoader.height = FlexGlobals.topLevelApplication.height-70;
    pdfHTMLLoader.width = FlexGlobals.topLevelApplication.width-60;

    // 2) add the HTMLLoader to a UIComponent
    pdfUIC = new UIComponent();
    pdfUIC.name = "pdfPrintPreview";

    // 3) add the UIComponent to the application
    pdfUIC.y = 33;
    pdfUIC.x = (FlexGlobals.topLevelApplication.width - pdfHTMLLoader.width) / 2;

  // destroy the PDF, call garbage collector..
  private function closePdf():void
      // make the object a candidate for garbage collection..
      pdfUIC = null;



Lo! The sample application running in Debug mode..

Load a PDF into Adobe AIR Using Flex 4

Load a PDF into Adobe AIR Using Flex 4

Written by elrobis

2 July 2011 at 6:41 am

Posted in ActionScript 3, AIR, Flex 4

Debugging in FlashDevelop: Stepping Through Code

with 7 comments

This post discusses debugging with breakpoints in FlashDevelop 4 as well as FlashDevelop 3.3.4. My original tutorial covered FlashDevelop 3.3.4 RTM, but it fell out of date with the release of FlashDevelop 4, so I added details to accomodate that release.

Debugging in FlashDevelop 4 (FlashDevelop 4 Beta2)

If you want to debug your ActionScript code in FlashDevelop 4 (FD4) and you’re wondering why your breakpoints won’t catch, you probably just need to impose a simple two-step fix:

1) Install the 32-bit Java Development Kit
2) create a JAVA_HOME environment variable.

I’ll walk you through it, but first, I’m making the following assumptions about your FlashDevelop installation:

— FD4 (I used Beta2 at the time) recognizes your Flex 4 SDK, and you can build/launch Flex 4 applications.
— FlashDevelop properly launches the Flash debug player, and trace statements appear in the output pane.

While experimenting withFlashDevelop 4 Beta2, I was vexed once again by the task of configuring the debugger. At a glance, there several obvious improvements over FD3, but none of my breakpoints were catching, and the steps I used to setup debugging in FD3 were no longer applicable. So I started poking around, and I eventually identified the problem by enabling Verbose Output (FD4 > Tools > Program Settings > FlashDebugger > Verbose Output = True). The Verbose Output setting pushes additional notifications to the FD4 output pane that revealed a sly, behind-the-scenes exception I wasn’t seeing previously. Basically the debugger wanted the JAVA_HOME environment variable, and it couldn’t find it. Googling the exception statement led me here:


To fix the problem, I downloaded JDK 7 for Windows (use the 32-bit, x86 variant, even if you have a 64-bit OS), installed it, then created a new environment variable called JAVA_HOME and set it’s value to the JDK install path (C:\Program Files (x86)\Java\jdk1.7.0).

If you’ve never created an environment variable, do this: open the Windows Start menu (lower-left), right-click on “Computer” and select “Properties”. In the new window, select “Advanced system settings” from the choices at left, and when the System Properties dialog opens, select “Environment Variables” at the bottom. The bottom-half of the Environment Variables dialog is devoted to your System variables.. select “New” and for Variable name use JAVA_HOME. For Variable value use C:\Program Files (x86)\Java\jdk1.7.0 (note that your install path may be different). Now Ok/Save your way out of the dialogs and restart Windows.

I was surprised I needed to restart Windows 7 for a new system variable to go into effect, but it was in fact necessary. [EDIT] While restarting Windows is one way to refresh the environment variables, you may find it smoother to kill and reload the explorer.exe process. For more info, see the comment provided by joebain, appearing below. –Thanks joebain.

When Windows reloads, you should be able to set a breakpoint in FlashDevelop 4 and walk through your code using the F10 key. Conveniently, FD4 provides a ready-set-go “Step Into” shortcut (among others—see the Debug menu) that just works once your system environment is properly tweaked.

Thanks to lutfihilfan (see comments) for informing me that my original tutorial discussing debugging in FlashDevelop 3 fell out of date. This has been my most popular blog post, so hopefully these updates will continue to prove useful for Flex developers wanting to use FlashDevelop. —Thanks lutfihilfan.

Debugging in FlashDevelop 3 (FlashDevelop 3.3.4 RTM)

FlashDevelop 3 [I used 3.3.4 RTM] provides some native support for debugging, but walking through your code line-by-line isn’t exposed in the menu options. Moreover, the options that are exposed do not have default keyboard shortcuts. Here’s how you fix that:

1) Open the Tools Menu and select Program Settings
–> This view gives you access to a variety of customizations

2) Select “FlashDebugger” from the categories on the left
–> This is where you configure special keyboard shortcuts

3) Left-click to the right of “Next Shortcut” to set values
–> I ultimately used Ctrl+L

Ok, step 3 proved to be tedious. First I tried good ol’ F6 so I could stay in-sync with Flash Builder. But that doesn’t work. Neither did Ctrl+F6 (which isn’t convenient anyway). In short, I tried several different key combos before I finally found Ctrl+L. Most e left-hand combos I tried already had default functionality, for instance saving the application or trying to open a new file, etc. You may come up with a better combo than Ctrl+L if you poke around–certainly a left-hand combo is better than a right-hand combo, which requires repositioning the mouse hand a lot while debugging. Basically, I’m tired so I settled.

4) If you don’t already have a project lined up to debug, here’s a simple app you can write just to demonstrate the stepping:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
  [Bindable] private var i:int = 0;
  private function onClick():void
   do {
    trace("now i = " + i.toString());
   } while (i <= 31)
 <s:VGroup verticalCenter="0" horizontalCenter="0">
  <s:Button id="button" label="Start Debugging!"
  <s:Label id="label" text="New Count: {i}"/>


 5) With an app ready to go, set a breakpoint by left-clicking in the gutter, just to the left of the line you want to intercept; in this case I’m at the trace() statement inside the do..Loop at line #14.

In my example, you have to click the Button in the app to trigger the function with the breakpoint, but assuming your app compiled and you launched the Debug version, it should hit your breakpoint as expected. At this point, do your thing and walk through the code using Ctrl+L.

Cheers, Elijah

Written by elrobis

19 June 2011 at 12:07 am

Primer on Byte-Level Development in AS3

leave a comment »


Lee Brimelow posted a fantastic primer on byte-level development using ActionScript 3.  This tutorial is a 30-minute screencast where Lee demonstrates how to read a format spec and develop a solution for handling an unsupported file format with ActionScript 3.  This is a fantastic tutorial and well worth the time of anyone interested in byte-level programming in ActionScript.

Written by elrobis

11 December 2010 at 10:27 am

Create an AIR Application to Write Your XML

with 6 comments

I keep finding myself wishing we spent more time in the book discussing Adobe AIR, so I decided to add some extra content here.  Of course, if you run into any questions or concerns, feel free to post them here.

The following application demonstrates a few key uses for AIR’s File() class, particularly:

1) Open a dialog for browsing the file system
2) Create a new file in the file system
3) Use the FileStream() class to write content into a file


The application presented below builds upon various topics covered in Learning Flex 4.  I’m assuming you’ve become comfortable with XML basics. If you need some extra info, chapters 4, 11, 12, and 16 discuss using XML data in Flex applications.  Appendix C (PHP Basics) presents a solution for first concatenating XML as a text string on the server, then receiving that text later in the Flex application as an XML object.  This exercise builds upon these concepts.

The use case for the following application is a scenario where you require fairly dynamic XML data, but you’ve decided it’s impractical to handle XML generation on the web server.  To support the book, I considered the case of the PhotoGallery application (Chapt 12), which relies on some ready-made XML to reference the image content.  While manually typing the XML for about a dozen photos isn’t a big problem, this would quickly become tedious if you were working with a hundred images.  Similarly, the task would consume a lot of time if you frequently recreate or revise the XML.  With this use case in mind, it may be desirable to write a program that automates the XML writing for you.  And hey, if nothing else, writing a 100-line AIR program to handle a programming scenario is generally more fun than writing a couple hundred lines of XML.  :)

Here’s the gist:   When you browse to a folder in your local file system, the AIR app will inspect the files in that directory and build an XML file required for the PhotoGallery application (i.e. photos.xml).  While likely you’d only want to run this utility on a folder of images intended for the PhotoGallery, the app will ensure you’re only adding references to PNG, JPG, and GIF files–this could be helpful in case there was an unassuming LOG file looming about, marooned in the otherwise clean and purposed images folder.

What to Look For

Selecting a directory in the file system:

The function getDirectory()  shows how to use the browseForDirectory() method on a File() object to select and access file objects as directories via the Flex UI.

Creating a New (XML) File and Writing its Content:

The function saveXmlFile() demonstrates how to create a new File() object and use the FileStream() class to write data into the new File(). 

Notice how we use the nativePath property of the selected directory (file.nativePath), followed by the operating system’s separator symbol (File.separator, as a static property), followed by a file name provided by the user, followed by the desired file extension (.xml)–all concatenated together–to establish where to save the new XML file (newXMLFile).

Notice also that the FileStream() object must open() the new file (newXMLFile) in FileMode.WRITE in order to access it for modification purposes.  The FileStream() method writeUTFBytes() is called to pass the concatenated XML string into the new file.  When finished, the close() method is called on the FileStream() to finalize the data input.

The Try..Catch Block!

The Try..Catch block (see the saveXMLFile() function) is good stuff.  It works like this:  First, in the Try section, you try some code that you suspect capable of throwing unanticipated errors; this section should be programmed to handle the task completely, as you’re assuming it will work more often than not.  Next, you follow the Try with a Catch section that allows your program to gracefully catch any “surprise!”, unanticipated errors that might happen when attempting to process the function.  In this case, our Try section ends with an Alert box that notifies us if the XML file is created sucessfully.  Alternatively, our Catch section creates an Alert box notifying the user of the exact error message (er.message) in hopes that it may be detailed enough for the user to consider what caused the error then followup with a successful attempt.

Caveat:  It is too easy to abuse the Try..Catch system as an all-purpose error handling tactic.  Good practice dictates using Try..Catch only when you want to account for unknowns that may throw a wrench, or a chainsaw, or some other mess-making boobalatosomitch into your function.  The Try..Catch system is fairly “expensive” as far as system resources go; plus, it’s just wise to think about your code and handle your use case with a true understanding instead of an attitude that could be epitomized by the phrase “well, I really hope this works, but just in case it doesn’t I’ll Try it and Catch it.”  ….please, just don’t do that.

The String class’s split() method–someString.split(“.”)

The split() method, which is available to String objects, is ultra-useful.  If you have a text String–in this case fileNameAndExt, which is the filename, followed by a dot (.), followed by the file’s extension (.png, .jpg, .gif, .xml, etc..)–you can call the String’s split() method to divide that text string into an Array of String objects as pieces separated by a delimiter.  For this example, the dot (.) is the delimiter. 

This code:
var fileNameArray:Array = new Array();
var fileNameAndExt:String = fileObj.name;      // “photo.jpg”
fileNameArray = fileNameAndExt.split(“.”);

Would create the following index values in the Array:
fileNameArray[0] = “photo”
fileNameArray[1] = “jpg”

Breaking apart the filename into its component portions helps us later when we’re concatenating together our XML text.

The Application Code

<?xml version="1.0" encoding="utf-8"?>
 minWidth="600" minHeight="400">

   import mx.controls.Alert;

   private var file:File = new File();
   private var xmlString:String;

   private function getDirectory():void{
    file.browseForDirectory("Select Image Directory");
    file.addEventListener(Event.SELECT, directorySelected);

   private function directorySelected(event:Event):void{
    var filesArray:Array = new Array();
    filesArray = file.getDirectoryListing();

    // create the XML..
    xmlString = '';
    xmlString += '<?xml version="1.0" encoding="utf-8"?>\n';
    xmlString += '<photos>\n';

    // loop through file objects and add XML nodes..
    for each(var fileObj:File in filesArray){
     // make sure the file is not a directory, etc.,
     // or an image format not supported in Flash Player..
     if(((fileObj.isDirectory == false) &&
      (fileObj.isHidden == false) &&
      (fileObj.isPackage == false) &&
      (fileObj.isSymbolicLink == false)) &&
      ((fileObj.extension.toUpperCase() == "PNG") ||
      (fileObj.extension.toUpperCase() == "JPG") ||
      (fileObj.extension.toUpperCase() == "GIF"))){

      // separate "name" into filename AND extension..
      var fileNameAndExt:String = fileObj.name;
      var fileNameArray:Array = new Array();
      var fileName:String;
      var ext:String;
      var path:String;
      var thumbPathNameAndExt:String;
      var imagePathNameAndExt:String;

      fileNameArray = fileNameAndExt.split(".");
      fileName = fileNameArray[0].toString();
      ext = fileNameArray[1].toString();
      // of course, use your own URL here..
      path = "http://www.learningflex4.com/photos/";
      thumbPathNameAndExt = path + fileName + '_th.' + ext;
      imagePathNameAndExt = path + fileNameAndExt;

      xmlString += 
       '<photo credit=""\n' +
        '  title="' + fileName + '"\n' +
        '  thumb="' + thumbPathNameAndExt + '"\n' +
        '  image="' + imagePathNameAndExt + '"/>\n';

    // close the XML and show content in the TextArea..
    xmlString += '</photos>';
    textArea.text = xmlString;

   private function saveXmlFile():void{
     var newXMLFile:File = new File();
     var fileStream:FileStream = new FileStream();
     var sep:String = File.separator;
     var xmlFilePath:String =
      file.nativePath + sep + fileNameTI.text + ".xml";

     newXMLFile.nativePath = xmlFilePath;
     fileStream.open(newXMLFile, FileMode.WRITE);
     Alert.show("XML Data File Created..", "XML-Builder");

     Alert.show("XML Data File FAILURE!!" + "\n\n" +
      er.message, "XML-Builder");

  <s:VerticalLayout paddingTop="14" horizontalAlign="center"/>

 <s:Label text="XML-Builder for the PhotoGallery Application"/>
 <s:Button label="Select Folder to Parse" click="getDirectory()"/>
 <s:TextArea id="textArea" width="90%" height="75%"/>
 <s:HGroup verticalAlign="middle">
  <s:Label text="(provide filename WITHOUT extension)" fontStyle="italic"/>
  <s:TextInput id="fileNameTI"/>
  <s:Button label="Save File" click="saveXmlFile()"/>


Written by elrobis

7 December 2010 at 8:06 pm

Posted in AIR, Flex 4

The Book’s Source Code by Chapter

with 11 comments

Just in case people come here looking for the book’s example code:

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16


[Update: It seems the Yahoo searching service has gone offline. I modified the code from pages 232-233, as follows, and using debugging techniques, I see that the application is catching errors in the searchFault() method.]

<?xml version=”1.0″ encoding=”utf-8″?>
<s:Application xmlns:fx=”http://ns.adobe.com/mxml/2009
import com.yahoo.webapis.search.events.SearchFaultEvent;
import com.yahoo.webapis.search.events.SearchResultEvent;
import mx.collections.ArrayCollection;

private var searchResultAC:ArrayCollection;

private function onSearch():void {
searchService.query = queryTI.text;

private function searchResult(e:*):void {
// breakpoints here won’t hit…………………….
searchResultAC = e.result as ArrayCollection;
resultsList.dataProvider = searchResultAC;

private function searchFault(e:SearchFaultEvent):void {
// this breakpoint catches every time…………
<yahoo:SearchService id=”searchService”
<s:VGroup left=”10″ right=”10″ top=”10″ bottom=”10″>
<s:Label text=”Yahoo! Search:” fontWeight=”bold”/>
<mx:FormItem label=”Query:” fontWeight=”bold”>
<s:TextInput id=”queryTI” width=”350″/>
<s:Button id=”searchButton” label=”Search”
<s:List id=”resultsList” width=”100%” height=”100%”/>

This screenshot came right out of FlashBuilder 4.5, with a breakpoint set in the searchFault() method:

The Variables pane showing errors attached to the SearchFaultEvent object.

I’ll give this problem some thought. Perhaps I can post an alternative API example here. Does anybody have an API they’d like to recommend for an example application? If so, I’m open to suggestions.

Written by elrobis

7 November 2010 at 11:13 pm

Posted in Uncategorized

Drag From a List, Drop in a TextInput

leave a comment »

Today I wanted to drag an item from a List and drop it into a TextInput. I had never used the DragManager in this manner, but Kumar Gandhi’s post exposed the task for its simplicity. Check it out here:


Written by elrobis

27 August 2010 at 12:33 pm

Posted in Uncategorized