We're speaking at
CFUnited 2008:
CFUnited - The Premiere ColdFusion Technical Conference

Search

Calendar

SunMonTueWedThuFriSat
    123
45678910
11121314151617
18192021222324
25262728293031

Subscribe Enter your email address to subscribe to this blog. You'll receive an email when we write a new post.

Recent Entries Come On In, Rails-The Water's Warm
Shan's Simple Examples: File uploads with Flex and ColdFusion

Recent Comments Google Calendar API - Creating a new Calendar with ColdFusion
Steve Julian said: When and where are you going to post the finished CFC's ? Thanks [more]

Three Phases of Programmer Development
Pat Branley said: I normally think of those phase 2 people as 'programmers' and the phase 3 people as 'developers'. I... [more]

New Job Title: Front End Engineer
Sean Corfield said: Well, there's always the excellent Fusion Authority Quarterly Journal... [more]

Down To The Wire: HTTP Sniffers
Brian M said: I second the mention of the Charles Web Debugging Proxy that Tariq mentioned. It is fantastic. It s... [more]

New Job Title: Front End Engineer
Patrick said: Heya Sean. Good point. I never understood how they did things over there at SysCon, and I understand... [more]

Archives By Subject Business of Software (4) [RSS]
ColdFusion (318) [RSS]
Conferences (6) [RSS]
Databases (87) [RSS]
Flex & Flash (109) [RSS]
Fusebox (87) [RSS]
General Development (29) [RSS]
Google (9) [RSS]
Hardware (5) [RSS]
JVM & Java (132) [RSS]
Linux (20) [RSS]
Miscellaneous (254) [RSS]
Performance (8) [RSS]
SeeFusion (36) [RSS]
Shan's Simple Examples (6) [RSS]
User Interface (3) [RSS]
Windows (5) [RSS]

Archives By Poster Daryl Banttari (10)
Nat Papovich (29)
Patrick Quinn (36)
Shannon Hicks (22)
Steve Nelson (21)
Tyson Vanek (3)


bottom corner

Shan's Simple Examples: File uploads with Flex and ColdFusion

Someone in #flex was talking about how there were no good examples for doing uploads with Flex and ColdFusion. Sounded like an excellent topic to cover here. Now this example is a tiny bit more complex than previous examples, because I needed to cover two methods of functionality: single file uploads and multi-file uploads. Both processes are very similar, and in my code they actually share a method.

Here's the MXML application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()" layout="absolute">
   <mx:Script>
      <![CDATA[
         import mx.controls.Alert;
         private var myFileList:FileReferenceList;
         private var myFile:FileReference;
         private var uploadTarget:URLRequest = new URLRequest("upload.cfm");
         
         private function init():void {
            myFileList = new FileReferenceList();
            myFileList.addEventListener(Event.SELECT,fileListSelected);
            
            myFile = new FileReference();
            myFile.addEventListener(Event.SELECT,fileSelected);
         }
         
         private function fileListBrowse():void {
            // we only want to allow images to be uploaded             var imagesFilter:FileFilter = new FileFilter("Images", "*.jpg;*.jpeg");
            myFileList.browse([imagesFilter]);
         }
         
         private function fileBrowse():void {
            // we only want to allow images to be uploaded             var imagesFilter:FileFilter = new FileFilter("Images", "*.jpg;*.jpeg");
            myFile.browse([imagesFilter]);
         }
         
         private function fileListSelected(e:Event):void {
            // here we could do whatever we want, but we're just going to             // upload right away             uploadFromList();
         }
         
         private function fileSelected(e:Event):void {
            // here we could do whatever we want, but we're just going to             // upload right away             uploadFile(myFile);
         }
         
         private function uploadFromList():void {
            if (myFileList.fileList.length > 0) {
               // if there are still files left to upload, continue                myFile = myFileList.fileList[0] as FileReference;
               uploadFile(myFile);
            } else {
               // if there are no more files, stop                return;
            }
         }
         
         // NOTE: this method is used for one or multiple files          private function uploadFile(f:FileReference):void {
            // here we build out the other form items             var urlVars:URLVariables = new URLVariables();
            urlVars.myFirstValue = 1;
            urlVars.myOtherValue = "something else";
            
            // add the form items to the request             uploadTarget.data = urlVars;
            // set request the method to POST             uploadTarget.method = URLRequestMethod.POST;
            
            // add the event listeners             // DataEvent.UPLOAD_COMPLETE_DATA only fires if data is returned and the flash player supports it             // otherwise, use Event.COMPLETE             f.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,onDataComplete);
            f.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            f.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            
            // show the progress bar             myProgress.visible = true;
            
            // start the upload             f.upload(uploadTarget,"myUploadFieldName");
         }
         
         private function ioErrorHandler(e:IOError):void {
            // there was some error, you'll want to tell someone             Alert.show("Error occured, oops!","I/O Error");
         }
         
         private function progressHandler(e:ProgressEvent):void {
            // update the ProgressBar             myProgress.setProgress(e.bytesLoaded,e.bytesTotal);
         }
         
         private function onDataComplete(e:DataEvent):void {
            // here we could handle whatever was returned by the server. XML is probably your best bet.             // var myResult:XML = XML(e.data); // would work for XML             var myResult:String = e.data;
            
            // if there were multiple files, delete the one we uploaded and try another             if (myFileList.fileList.length > 1) {
               // remove what we just uploaded                myFileList.fileList.splice(0,1);
               // go upload another another                uploadFromList();
            } else {
               // if this was the last of a multiple file upload, remove it                if (myFileList.fileList.length > 0) {
                  myFileList.fileList.splice(0,1);
               }
               
               // we're done uploading                myProgress.visible = false;
               return;
            }
         }
      ]]>
   </mx:Script>
   <mx:VBox height="100%" width="100%" horizontalAlign="center" verticalAlign="middle">
      <mx:Button label="Choose One File to Upload..." click="fileBrowse()"/>
      <mx:Button label="Choose Multiple Files to Upload..." click="fileListBrowse()"/>
      <mx:ProgressBar id="myProgress" mode="manual" label="Uploading" visible="false"/>
   </mx:VBox>
</mx:Application>

The comments point out all the nuances you need to know about. It does the major features, including passing more data with the file, what you can do with the progress event, how to do an upload queue, rather than uploading all selected files at the same time, and how to handle responses from the upload script. This code will work with any backend processor, not just ColdFusion.

Here's the ColdFusion file:

<cfsetting enablecfoutputonly="true">
<!--- this will upload the file --->
<cffile action="upload" fileField = "myUploadFieldName" destination="#expandPath("./")#uploads/">

<!--- note that all formfields including FORM.myFirstValue and FORM.myOtherValue --->
<cfscript>
   myVal1 = FORM.myFirstValue;
   myVal2 = FORM.myOtherValue;
</cfscript>

<!--- here you can send stuff back to flex, only if the flash player is 9.0.28.0 or later --->
<cfoutput><myXML>
   <file uploadedAs="#cffile.serverFile#">
</myXML></cfoutput>

It doesn't do much, but you can see how to get non-file data passed from flex, and how to send a response. Make sure that, when sending a response, you don't send any whitespace before what you intend to send back to Flex. Also, note that your users need the Flash Player version 9.0.28.0 or later in order to send responses back to flex.

New Job Title: Front End Engineer

There's a pretty good article about job titles in the current ColdFusion Developer's Journal:

Are the Job Titles "Web Designer" and "Web Developer" Too General? - There are a lot of professions that have emerged from the web: designers, developers, strategists, search engine optimists, information architects, usability and accessibility consultants, the list goes on... Today, I'd like to talk about the first two. I wouldn't go so far to say that the titles should be considered harmful by any means, rather we have just outgrown our job titles!

My favorite part is where the author, at his most recent job, gave himself the title "Front End Engineer", because it seemed to fit what he was doing. As it happens, just yesterday Nat (Papovich, Lead Architect here) and I were having a discussion about how, with the recent evolution of rich applications in the Web development realm, it's time for a more-or-less official title of UI Developer. There's no doubt now that the proliferation of development tools/languages/frameworks/etc. that are solely focused on producing better UIs means that there's a whole lot more programming that happens just in the UI layer of an application. Just taking one tool as an example--Flex--requires proficiency in a range of skills, including OO development (ideally, but not required), CSS, Actionscript, MXML, and more.

In our development practice, we certainly see this playing out. We typically have several developers working solely on the UI layer, be it AJAX (in its million different forms), Flex, etc.

On a related note, I recently read about the new workflow integrations between Flex and design tools, which is a great thing. What I find interesting about the "UI Developer" role is that, on average, I think it entails developers learning better graphic design, usability, and other "designer" skills more so than it entails designers learning to program. But that's a side note to the whole store. The bottom line is, the fact that we have Front End Engineers, or even the possibility of them, is great for users, and it's another sign of the maturing of the Web as a platform for business computing.

Shan's Simple Examples: Using events (aka how to pass data from components)

There was some confusion in #flex yesterday. The question came up on how a child component could access the parent component. Eventually, it came down to they wanted to pass some data from the child back to the parent.

Well, the "black box" method of component programming says that we should use custom events to send data from the component back to the parent. I whipped up an example that uses both a basic custom event and a custom event that passes back data.

One note, when you create your own event that passes back data, you not only need to add your custom attributes, but you also need to override the clone() method. Look at the MyCustomEvent.as file in the source.

You can view the example here. As always, right-click to view the source.

Shan's Simple Examples: Keyboard shortcuts and TextInput

Someone on #flex asked about preventing text from appearing in a TextInput or TextArea, when the user is using a keyboard shortcut. After a little discussion, I came up with a working example. I decided to use shift-space to simplify things.

The first assumption is that you're listening for keyboard shortcuts at the application level:

application.addEventListener(KeyboardEvent.KEY_UP,shortcutHandler);

Now, you've got your input box, and it's listeners:

<mx:TextArea height="100%" width="95%" keyDown="shortcutPreprocess(event)" textInput="shortcutPreventer(event)"/>
private function shortcutPreprocess(e:KeyboardEvent):void {
   if (e.shiftKey && e.keyCode == 32) {
   _isShiftSpace = true;
} else {
   _isShiftSpace = false;
}
}

private function shortcutPreventer(e:Event):void {
   if (_isShiftSpace) {
      e.stopImmediatePropagation();
      e.preventDefault();
   }
}

Note that I had to set a boolean in my shortcutPreprocess method, and then I check for the boolean in shortcutPreventer. The reason being is that the textInput event doesn't pass in the KeyboardEvent in any way, so I don't know if there was a key combo pressed.

Working example & source: http://www.iotashan.com/examples/KeyboardShortcut/

Shan's Simple Examples: Using an XML datasource with mx:ComboBox

Over the weekend I was writing a simple little app, and came across something that should have been trivial, but turned out to throw me for a loop momentarily. I needed to drive some data from XML instead of my tried-and-true ColdFusion components, and I realized I'd never done it before. So, here's the example:

First off, you need to actually get the XML file using a HTTPService:

<mx:HTTPService id="sectionService" url="pet.xml" resultFormat="e4x" result="sectionResult(event)"/>

Looks simple enough, but to produce valid XML, I needed to have a root node around my other nodes:

<?xml version="1.0" encoding="utf-8"?>
<varieties>
   <variety name="Standard"/>
   <variety name="Angora"/>
   <variety name="Satin"/>
   <variety name="Rex"/>
   <variety name="Texel"/>
   <variety name="Satin Texel"/>
   <variety name="Satin Rex"/>
   <variety name="Satin Angora"/>
   <variety name="Fuzzy"/>
   <variety name="Fuzzy Angora"/>
   <variety name="Fuzzy Hairless"/>
   <variety name="Fuzzy Hairless Angora"/>
   <variety name="Hairless"/>
</varieties>

Now, when I put this directly into a XMLList object, I got a ComboBox with one option... my entire XML packet. It took a few tries to realize that I needed to make the DataProvider only the "variety" nodes, and that was easy to do:

private function varietyResult(e:ResultEvent):void {
   varietyXML = XMLList(e.result.variety);
}

So, for everyone who likes to see the whole picture, like me, here's the entire MXML code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%" initialize="init()">
   <mx:HTTPService id="varietyService" url="varieties.xml" resultFormat="e4x" result="varietyResult(event)"/>
   <mx:Script>
      <![CDATA[
         import mx.rpc.events.ResultEvent;
         
         [Bindable] private var varietyXML:XMLList;
         
         private function init():void {
            varietyService.send();
         }
         
         private function varietyResult(e:ResultEvent):void {
            varietyXML = XMLList(e.result.variety);
         }
      ]]>
   </mx:Script>
   <mx:ComboBox id="variety" dataProvider="{varietyXML}" labelField="@name"/>
</mx:Application>

Down To The Wire: HTTP Sniffers

At Webapper, we've always described our tuning & troubleshooting consulting as a "wire-to-wire" service. This means that we find and fix performance and/or stability problems wherever they are, even if they're in the network layer (e.g., the TCP "silly window" problem). And beyond troubleshooting production systems, we've always found that HTTP sniffers are useful during development, too. We just heard about a free tool from Microsoft, named Fiddler, so I thought I'd blog it here along with some others that we use regularly:

  • Fiddler: It's a free tool written by Eric Lawrence at Microsoft. It's really technically an HTTP proxy, and thus is a specialized tool for sniffing Web requests.
  • Wireshark (formerly Ethereal): This is one we've used for a long time. It's a general purpose packet sniffer, and sees all packets, not just HTTP.
  • ServiceCapture: Written by Kevin Langdon, we've got copies of this laying all over the virtual office. The killer feature in this tool is its decoding of service requests. It'll decode AMF/remoting packets, for example, and show you their full data structure. Very, very useful.

Flex: Making Scrollbars Follow Focus

If you've ever created a form tall enough to require a vertical scroll bar in Flex, you may have not even have noticed that you have you scroll down manually when focus moves below the visible part of a window. Users, however, notice, especially if they don't have a scroll wheel on their mouse.

There doesn't seem to be any built-in or easy way to correct this, so I wrote a helper class to facilitate. I called it "com.webapper.autoscroll.AutoScroll", and it has one static function "autoScroll(event)" that should be called anytime a given container changes focus (focusIn) or finishes resizing (updateComplete).

To use it, simply add the following to the scrolling container (Canvas, Panel, etc) that contains the input fields you want to chase focus on:

updateComplete="AutoScroll.autoScroll(event);"
focusIn="AutoScroll.autoScroll(event);"

The autoScroll() method determines the y position of the current focus relative to the top of the container, and repositions its vertical scroll bar to ensure that the item with focus is completely visible, if necessary.

Source, library SWC, and demo are at: http://www.darylb.net/flexautoscroll/

Shan's Simple Examples: Scale all children in Flex

I've decided since I attempt to help people in #flex (on EFNet) and #coldfusion / #cfflex (on DALNet) on a daily basis, that I'll pick one simple question and try to whip up an example for everyone to see.

Today, someone asked how to scale all children of a container. The basic answer is to just loop over all the children, and set their scaleX and scaleY properties.

Click through for the example and source code.

List manipulation library for Actionscript 3

I forgot to mention here that I wrote up a nice Actionscript library for manipulating lists. It includes a majority of ColdFusion's list functions, plus a few that we commonly use here at Webapper. Sometimes you just need a list instead of an array.

Get the library here.

Flex Not-So Custom Preloader

Today I got a request to change the "Loading" text in the preloader of a Flex app. To my surprise, I didn't see any examples on how to do this, so I thought I'd share my results.

When you like the existing preloader, but want to just make little tiny changes to it, here's what you do. You'll first need to go ahead and create a custom preloader class that extends DownloadProgressBar (the default preloader). In this new class, you'll see the spot where you can just make tweaks to the preloader's values:

package org.iotashan.components
{
   import mx.preloaders.DownloadProgressBar;

   public class CustomPreloader extends DownloadProgressBar
   {
      public function CustomPreloader()
      {
         super();
         // set your properties here          this.downloadingLabel = "Getting the hampster to run on the wheel";
      }
      
   }
}

Once you've created this custom preloader, you just have to assign it to your application:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preloader="org.iotashan.components.CustomPreloader">

That's it. Check out the live example here.

More Entries

bottom corner