Using Flex Framework Assets

October 5th, 2010

There may be times when you want to use an asset/graphic that exactly matches an asset/graphic used by the Flex framework. For example, if you’re already using the Tree component and need to mimic the opening and closing of folders, you may want to use the same icons that the tree uses. It’s really very simple to do this.

The Flex framework stores these types of assets in Assets.swf. To find out what assets are available in Assets.swf, you can peruse the “default.css” file provided in the sdk ([path-to-your-sdk]/frameworks/projects/framework/default.css).

For example, the Tree component has this entry in default.css:

/*
//------------------------------
//  Tree
//------------------------------
*/

Tree
{
	defaultLeafIcon: Embed(source="Assets.swf",symbol="TreeNodeIcon");
	disclosureClosedIcon: Embed(source="Assets.swf",symbol="TreeDisclosureClosed");
	disclosureOpenIcon: Embed(source="Assets.swf",symbol="TreeDisclosureOpen");
	folderClosedIcon: Embed(source="Assets.swf",symbol="TreeFolderClosed");
	folderOpenIcon: Embed(source="Assets.swf",symbol="TreeFolderOpen");
	paddingLeft: 2;
	paddingRight: 0;
	verticalAlign: "middle";
}

There are five assets here that we can use (TreeNodeIcon, TreeDisclosureClosed, TreeDisclosureOpen, TreeFolderClosed, TreeFolderOpen).

One way that we might use them in our application is to embed them into a Class object and then use that as the source property for an Image object. For example, if you wanted to use the little triangle that appears next to a closed folder in the Tree component, you could do the following:

Declare this in your <fx:Script> section:

[Embed(source="Assets.swf", symbol="TreeDisclosureClosed")]
private const myClosedIcon:Class;

Then, use this in your MXML code:

<mx:Image source="{myClosedIcon}" />

… lather, rinse, repeat.

Separating drag from drop

July 20th, 2010

In my previous post, I discussed separating drag-and-drop logic from view components as another tool to help achieve the cleanliness of single-responsibility classes. In this post, I’m going a step further by examining how the drag-and-drop functionality itself can be decoupled to achieve encapsulated components.

This post focuses on a scenario where objects are being dragged from one component to another (as opposed to simply rearranging objects within a single component). Further, these components may be quite different from each other (as opposed to being separate instances of the same component — although that scenario can benefit, too).

For example, one component may display a pool of objects that are “available” to be dragged somewhere. We can think of this as the “source” component (the “source” of the objects that can be dragged). In addition to this source component, we may have several “target” components. Perhaps the source/pool holds objects named “penny”, “nickel”, “dime”, and “quarter”. Then, we would have (at least) four “target” components displaying an image of each type of coin (and a place to drop a single, dragged object).

Across clients and projects, I see a tendency for drag-and-drop functionality to be lumped into a single, large view class. In the example discussed above, all of the logic for the source and target components, as well as their drag-and-drop logic, would be coupled (quadrupled?) together. This creates a lot of complexity, making it difficult to follow the flow. The method that handles the drag_drop logic, for example, would have to have conditional logic to determine whether the object was dropped on a target (and which one) … or dropped back on the source component (where do I need to add this object?). The same complexity typically exists for every drag-handler method. And, it often ends up a lot more complex if you start casting to different objects or implementing one-off behaviors for each component type. The root-cause of this complexity is the fact that each drag-handler method is responsible for multiple objects (the one where the drag started and the one where the object was dropped).

We tend to think of the happy-path drag-drop procedure progressing like this:

  1. drag start
  2. drag enter
  3. drag drop
  4. drag complete

This is simple and irresistibly logical. And, it is fine if all of your drag actions are occurring on a single component. However, if you are creating custom drag-and-drop functionality for separate components using this style of thinking, then the complexity and confusion discussed above can start to creep in.

It would be cleaner if each drag-handler was specific to a given component. But, if the source and target component logic is truly separated into separate components, what does this mean for the drag events (which events are called on which objects?)?

Once you separate these components, it eventually becomes clear that the events are separated like this:

  • On the component that the item is being dragged AWAY FROM:
    1. drag start
    2. drag complete
  • On the component that the item is being dragged TO:
    1. drag enter / over / exit
    2. drag drop

And, since the components are now separated, your drag-and-drop logic can only be for that object. This can really simplify your drag-and-drop logic. First of all, you can get rid of the conditional logic. Second, you can now build decoupled, encapsulated components that are not cluttered by the logic of other components.

You can couple this technique of drag-and-drop component separation with the previous post’s technique of keeping the drag-and-drop logic separate from the component. This can go a long way toward achieving clean, clear, single-responsibility classes. Instead of having all of this logic in a single, confusing, monolithic view class, the logic would now be split into four (or more) small, targeted classes (source component, target component, drag logic for source component, drag logic for target component). It can be quite refreshing to maintain code that is focused on a single-responsibility, rather than cluttered by logic that you are not interested in at the moment.

Below is some sample code to get you started. It shows the basic drag handlers for a source component and a target component. It does not show the components themselves, or refer to interfaces, etc. that you might use. But, hopefully, it’ll give you the basic idea.

*** Drag Logic for Source Component ***

public class DragSourceBehavior {

private var component:MyDragSourceUIComponent;

public function DragSourceBehavior(_component:MyDragSourceUIComponent) {
	component = _component;
	component.addEventListener(DragEvent.DRAG_ENTER, onDragEnter, false, 0, true);
	component.addEventListener(DragEvent.DRAG_DROP, onDragDrop, false, 0, true);
}

private function onDragStart(event:MouseEvent):void {
	if (DragManager.isDragging)
		return;

	var dragSource:DragSource = new DragSource();

	DragManager.doDrag(event.currentTarget, dragSource, event);

	component.removeObject(event.currentTarget);
}

private function onDragComplete(event:DragEvent):void {
	var dragObject:UIComponent = event.currentTarget as UIComponent;
	dragObject.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_UP));

	if (droppedOnDifferentObject(event))
		removeDragEvents(event.currentTarget);
}

private function onDragEnter(event:DragEvent):void {
	DragManager.acceptDragDrop(event.currentTarget as IUIComponent);
}

public function onDragDrop(event:DragEvent):void {
	component.addObject(event.dragInitiator);
	addDragEvents(event.dragInitiator);
}

public function addDragEvents(dragObject:UIComponent):void {
	dragObject.addEventListener(MouseEvent.MOUSE_DOWN, onDragStart);
	dragObject.addEventListener(DragEvent.DRAG_COMPLETE, onDragComplete);
}

public function removeDragEvents(dragObject:UIComponent):void {
	dragObject.removeEventListener(MouseEvent.MOUSE_DOWN, onDragStart);
	dragObject.removeEventListener(DragEvent.DRAG_COMPLETE, onDragComplete);
}

private function droppedOnDifferentObject(event:DragEvent):Boolean {
	var droppedOnAnotherObject:Boolean = false;

	if (event.relatedObject != component)
		droppedOnAnotherObject = true;

	return droppedOnAnotherObject;
}

}

*** Drag Logic for Target Component ***

public class MyDragTargetBehavior extends EventDispatcher {

private var component:MyDragTargetUIComponent;

public function MyDragTargetBehavior(_component:MyDragTargetUIComponent) {
	component = _component;
	component.addEventListener(DragEvent.DRAG_ENTER, onDragEnter, false, 0, true);
	component.addEventListener(DragEvent.DRAG_DROP, onDragDrop, false, 0, true);
}

private function onDragStart(event:MouseEvent):void {
	if (DragManager.isDragging)
		return;

	var dragSource:DragSource = new DragSource();

	DragManager.doDrag(event.currentTarget, dragSource, event);

	component.removeObject(event.currentTarget);
}

private function onDragComplete(event:DragEvent):void {
	var dragObject:UIComponent = event.currentTarget as UIComponent;

	if (droppedOnDifferentObject(event))
		removeDragEvents(dragObject);
}

private function onDragEnter(event:DragEvent):void {
	DragManager.acceptDragDrop(event.currentTarget as IUIComponent);
}

public function onDragDrop(event:DragEvent):void {
	component.addObject(event.dragInitiator);
	dispatchEvent(new CustomDragEvent(CustomDragEvent.OBJECT_DROPPED, event.dragInitiator, component));
}

private function droppedOnDifferentObject(event:DragEvent):Boolean {
	var droppedOnAnotherObject:Boolean = false;

	if (event.relatedObject != component)
		droppedOnAnotherObject = true;

	return droppedOnAnotherObject;
}

public function addDragEvents(dragObject:UIComponent):void {
	dragObject.addEventListener(MouseEvent.MOUSE_DOWN, onDragStart);
	dragObject.addEventListener(DragEvent.DRAG_COMPLETE, onDragComplete);
}

public function removeDragEvents(dragObject:UIComponent):void {
	dragObject.removeEventListener(MouseEvent.MOUSE_DOWN, onDragStart);
	dragObject.removeEventListener(DragEvent.DRAG_COMPLETE, onDragComplete);
}

}

Separating Drag-and-Drop from View components

May 12th, 2010

I was recently working on a set of view classes that, among other things, implemented custom drag-and-drop behavior. As we all know, Drag-and-drop requires several different event handlers for the various drag events (DRAG_START, DRAG_ENTER, etc.). Adding these event handlers to your view class adds a lot of bulk to the existing view logic.

In addition to the issues that are directly related to the sheer size of the class, including drag-and-drop logic in a view can often be considered a 2nd responsibility of the view. I often find that, when I’m working on a view that contains drag-and-drop behavior, I’m typically doing one of two things:

  1. Working on the view (look-and-feel, data set-up, gathering results after user interaction, etc.).
  2. Working on the drag-and-drop behavior.

Thus, if I am working on the view, all of the drag-and-drop logic is excess clutter in my way (and vice versa).

This should actually be an immediate red flag. Good coding practice suggests that a class should have a single responsibility. The Single Responsibility Principle, a term coined by Uncle Bob, correlates a “responsibility” with “a reason to change”. In other words, a class should have only one reason to change. In this example, there are two reasons that I might change the view. Therefore, one of the reasons-for-change should be refactored out of this class. It seems silly to refactor the view out of the view class. So, my approach was to move the drag-and-drop functionality into its own class.

There are probably a number of ways to structure the association between the view and the class containing the drag-and-drop functionality. However, one simple method is to inject the view component into the drag-and-drop class. This will allow the drag-and-drop class to register for the drag events emitted by the view. To limit coupling, the injected reference can be typed as a generic UIComponent (to have access to the drag events).

private var viewComponent:UIComponent;

public function DragAndDropFunctionality(component:UIComponent) {
	viewComponent = component;
	viewComponent.addEventListener(DragEvent.DRAG_ENTER, onDragEnter, false, 0, true);
	viewComponent.addEventListener(DragEvent.DRAG_EXIT, onDragExit, false, 0, true);
	viewComponent.addEventListener(DragEvent.DRAG_DROP, onDragDrop, false, 0, true);
}

Some events, such as DRAG_DROP will require the view to take action (add the dropped item to the appropriate place). Again, we want to limit coupling in our communication. The standard technique to maintain separation is for the lower-level component (the drag-and-drop class, in this case) to dispatch events. Then, the higher-level component (the view, in this case) can listen for those events and take the appropriate action.

Once this separation is achieved, we will have classes that have (hopefully) a single responsibility. When you need to work on the drag-and-drop logic, you can go directly to the drag-and-drop class. I find it much easier to follow the drag-and-drop logic without the view code cluttering the class. Similarly, the view component is no longer cluttered with all of the drag-and-drop event handlers. The classes are smaller and more obvious. And, the two “responsibilities” can now be worked on by multiple developers without lock conflicts or merging, to boot.

Reflection / Introspection in Flex ActionScript

July 15th, 2009

As part of an effort to create enterprise components, libraries, and architectures, a company may want to take advantage of reflection. For example, a company may want a consistent way to create and populate various components. This might allow your developers to work more quickly since all of the components are handled in the same manner. However, many of the components in Flex (and, likely, many of a company’s custom components), have differences in how they’re created and populated … even when the functionality is conceptually similar. In order to accomplish a consistent interface, you may need some abstraction that allows you to dynamically create and populate objects at runtime. To that end, I thought it might be helpful to discuss the low-level how-to’s of reflection within Flex / ActionScript.

The Flex framework includes an implementation of the Class Factory pattern in mx.core.ClassFactory. This class allows you to instantiate classes determined at runtime.

Here are a couple of examples of how to instantiate a class determined at runtime:

INSTANTIATE AN OBJECT FROM IT’S CLASS

import mx.core.ClassFactory;
public static function instantiateUsingClass(classToInstantiate:Class):* {
	var myClassFactory : ClassFactory = new ClassFactory(classToInstantiate);
	var myObjectInstance : * = myClassFactory.newInstance();
	return myObjectInstance;
}

INSTANTIATE AN OBJECT FROM IT’S CLASS NAME (i.e., from a String like “com.domain.Person”)

import flash.utils.getDefinitionByName;
import mx.core.ClassFactory;
public static function instantiateUsingClassName(className:String):* {
	var classToInstantiate : Class = getDefinitionByName(className) as Class;
	var myClassFactory : ClassFactory = new ClassFactory(classToInstantiate);
	var myObjectInstance : * = myClassFactory.newInstance();
	return myObjectInstance;
}

At a basic level, mx.core.ClassFactory does the following to instantiate the class:

public var generator:Class;
...
this.generator = classToInstantiate;
...
var instance:Object = new generator();

There are other times when you need more than to simply instantiate a class. For example, you may need to query the class definition to find out what methods, properties, etc. are declared on that class. The flash.utils package provides some package-level functions for introspecting classes and objects. Here is a link to the flash.utils API: http://livedocs.adobe.com/flex/3/langref/flash/utils/package.html. For the purposes of reflection, the describeType() method is one of the best places to start (the call to getDefinitionByName() that was used above is another package-level function provided by flash.utils). Here is a way to find out what “accessor” methods (get/set methods) are declared for a class:

RETRIEVE NAMES OF ACCESSOR METHODS FOR A GIVEN CLASS

import flash.utils.describeType;
public static function getNonstaticAccessors(classOfInterest:Class):Array {
	var xmlDescriptionOfClass:XML = describeType(classOfInterest);
	var nonstaticAccessorsXML:XMLList = xmlDescriptionOfClass.factory.accessor;

	var accessors:Array = [];
	for each (var accessorXML:XML in nonstaticAccessorsXML) {
		accessors.push(accessorXML.@name);
	}
	return accessors;
}

In order to obtain the static accessors, use xmlDescriptionOfClass.accessor, instead of xmlDescriptionOfClass.factory.accessor. In addition to @name, you might also be interested in information contained in @access, @type, and @declaredBy.

When you modify a public property on an object using dot notation (i.e., myPerson.name = “Fred”;), Flex does exactly what you’d expect and modifies the public property value. But, Flex offers an additional convenience. If you decide, at a later time, that you’d like to make the properties private and force them to be accessed through accessor methods (i.e., public function set name(myName:String):void {…}), Flex will automatically call your accessor method (without having to change your code to call the accessor, instead of the property). Hooray!

When it comes to reflection, however, the factual separation between properties (class attributes … class variables … whatever term you prefer) and accessors is maintained. The point of this tangent is that your public properties (that do not have declared accessor methods) will not be returned by the above method. Instead, in order to discover the properties of a given class, you’ll need to query for them specifically (using the “.variable” notation).

Here is an example of how to query for the attributes of a class:

RETRIEVE NAMES OF PROPERTIES (CLASS ATTRIBUTES) FOR A GIVEN CLASS

import flash.utils.describeType;
public static function getProperties(classOfInterest:Class):Array {
	var xmlDescriptionOfClass:XML = describeType(classOfInterest);
	var nonstaticPropertiesXML:XMLList = xmlDescriptionOfClass.factory.variable;
	var properties:Array = [];

	for each (var propertyXML:XML in nonstaticPropertiesXML) {
		var property:Property = new Property(	propertyXML.@name,
							propertyXML.@type.toString(),
							isStatic );
		properties.push(propertyXML.@name);
	}
	return properties;
}

In order to obtain the static accessors, use xmlDescriptionOfClass.variable, instead of xmlDescriptionOfClass.factory.variable. In addition to @name, you might also be interested in information contained in @type.

Accessor methods (discussed earlier) are also kept separate from all of the other methods. Here is an example of how to query for the non-accessor methods of a given class

RETRIEVE NAMES OF METHODS FOR A GIVEN CLASS

import flash.utils.describeType;
public static function getMethods(classOfInterest:Class):Array {
	var xmlDescriptionOfClass:XML = describeType(classOfInterest);
	var nonstaticMethodsXML:XMLList = xmlDescriptionOfClass.factory.method;

	var methods:Array = [];
	for each (var methodXML:XML in nonstaticMethodsXML) {
		methods.push(methodXML.@name);
	}
	return methods;
}

In order to obtain the static accessors, use xmlDescriptionOfClass.method, instead of xmlDescriptionOfClass.factory.method. In addition to @name, you might also be interested in information contained in @type.

OK, great! We now have a few tools (I’m sure you’ll discover more as you begin experimenting with the reflection capabilities provided by Flex) to help us with introspection of ActionScript classes at runtime. But, hey, maybe we actually want to DO something with that information. Here is an example of how to trigger a method call on a class and method discovered at runtime:

INVOKE A METHOD ON AN INSTANTIATED OBJECT

public static function invokeMethod(objectContainingMethod:*, methodName:String, parms:Array):* {
	var method:Function = objectContainingMethod[methodName];
	var returnValue:* = method.apply(objectContainingMethod, parms);

	return returnValue;
}

= = = = = = = = = =
Now that I’ve taken your time discussing some basics of how to implement reflection within Flex / ActionScript, I’m now going to suggest that you do it differently!

I was discussing writing a blog on reflection awhile back with Justin Shacklette (Justin’s blog) and Jon Rose (Jon’s blog). Justin immediately pointed out that Spring was splitting their reflection functionality out into a separate library. This reflection library improves on some of the above techniques by implementing work-arounds for some known bugs, etc., etc. behind the scenes. In addition, it allows you to deal with objects that might be a bit more intuitive than the XML object that is returned by describeType(). On the other hand, this means that you’ll occasionally need to step down through the object hierarchy to find the desired value. I found it pretty easy to investigate the various classes and source code at this site: http://as3-commons.googlecode.com/svn/trunk/as3-commons-reflect/src/main/actionscript/org/as3commons/reflect/. The best classes to start with are Type.as and ClassUtils.as.

To get started, download the AS3 Commons Reflection library (as3commons-reflect-1.0.0.swc) from http://code.google.com/p/as3-commons/.

Add this SWC file to your Flex project’s lib folder.

Now, let’s revisit the above examples to see how they might differ when using the AS3 Commons Reflection library.

INSTANTIATE AN OBJECT FROM IT’S CLASS

import org.as3commons.reflect.ClassUtils;
public static function instantiateUsingClass(classToInstantiate:Class):* {
	var myObjectInstance:* = ClassUtils.newInstance(classToInstantiate);
	return myObjectInstance;
}

INSTANTIATE AN OBJECT FROM IT’S CLASS NAME (a String like “com.domain.Person”)

import org.as3commons.reflect.ClassUtils;
public static function instantiateUsingClassName(className:String):* {
	var classToInstantiate:Class = ClassUtils.forName(className);
	var myObjectInstance:* = ClassUtils.newInstance(classToInstantiate);
	return myObjectInstance;
}

RETRIEVE NAMES OF ACCESSOR METHODS FOR A GIVEN CLASS

public static function getStaticAccessors(classOfInterest:Class):Array {
	var type:Type = Type.forClass(classOfInterest);
	var accessors:Array = type.accessors;
	return accessors;
}

RETRIEVE NAMES OF PROPERTIES (CLASS ATTRIBUTES) FOR A GIVEN CLASS

public static function getProperties(classOfInterest:Class):Array {
	var type:Type = Type.forClass(classOfInterest);

	var nonstaticProperties:Array = type.variables;
	var staticProperties:Array = type.staticVariables;

	var properties:Array = nonstaticProperties.concat(staticProperties);
	return properties;
}

RETRIEVE METHODS DECLARED BY A GIVEN CLASS

public static function getMethods(classOfInterest:Class):Array {
	var type:Type = Type.forClass(classOfInterest);
	var methods:Array = type.methods;
	return methods;
}

INVOKE A METHOD ON AN INSTANTIATED OBJECT

public static function invokeMethod(objectContainingMethod:*, methodName:String, parms:Array):* {
	var methodInvoker:MethodInvoker = new MethodInvoker();

	methodInvoker.target = objectContainingMethod;
	methodInvoker.method = methodName;
	methodInvoker.arguments = parms;

	var returnValue:* = methodInvoker.invoke();

	return returnValue;
}

Ultimately, the AS3 Commons Reflection library makes a few things easier or more intuitive. Moreover, it handles some complexities and bug work-arounds for you. But, the nuts-and-bolts are still basically using the the same techniques that I discussed in the upper-half of this post.

Enterprise Reuse of Flex Components and Classes

April 8th, 2009

In a simple Flex (SWF) application, all of the necessary components and classes are defined in a single Flex project. In the enterprise, however, you may want to refactor some of the components and classes into a separate library so that these common components and classes can be reused across multiple Flex applications (or project teams). The most common way to do this is to create a separate Flex project that will be used to create *.SWC file. Each Flex application will then be configured to link to this SWC. A SWC file is basically an archive of external components and classes, similar to a *.jar file in Java land.

There are various reasons that an enterprise might choose to decouple the common components and classes and put them in a separate, reusable SWC file:

  • * Reuse across Flex projects
  • * Reuse across Enterprise project teams
  • * Reuse across Enterprise applications
  • * Influence/enforce/decouple enterprise look-and-feel
  • * Improve application performance
    • – Startup time
    • – file size
    • – network bandwidth usage

Once the SWC file is created, you must decide how your SWF code will link to the necessary classes residing in the SWC. At a high level, Flex provides two linking options: Static linking and Dynamic linking.

STATIC LINKING (“Merged Into Code”):
When you use static linking, the compiler includes all referenced classes and their dependencies in the application SWF file. The end result is a larger SWF file. Obviously, a larger SWF file takes longer to download from the server. On the other hand, since all of the necessary code is contained in the SWF, it will load and run quickly. Keep in mind that the browser can cache the SWF file. So, if a given user will be accessing the same SWF file multiple times, the initially increased download time might be a reasonable trade-off for faster startup times.

DYNAMIC LINKING (“External” (or Runtime Shared Library “RSL”)):
When you use dynamic linking, the refactored components and classes are not included in (they are not compiled into) the application SWF file. Instead, the SWC file remains separate from the SWF. The result is a smaller SWF file size for the main application. The downside is that the SWC must be loaded at run time. In addition, the application loads the entire library (as opposed to static linking that can limit the linking to only the items that the SWF actually uses). This can result in slower startup times and greater memory usage.

Once again, however, client-side caching can play a role. The external SWC file can be cached and reused by multiple SWF applications. Each individual SWF will be smaller due to the exclusion of the common components and classes. If the enterprise has multiple SWF applications that will use the same SWC file, the cumulative size of the downloads might be lessened by using dynamic linking.

The enterprise will need to consider the tradeoffs of each option with respect to its situation and goals, in order to determine the best course of action. Components that will be reused across the enterprise will likely result in the creation of enterprise guidance and best practices. Components and classes whose reuse is limited to smaller divisions may need the flexibility to make the decision that is best for their particular sitation.

Using Flex to integrate with existing web sites

April 2nd, 2009

In a couple of my previous posts, I discussed the integration of a Flex application into an existing web site. One post (link to post) discussed dynamically controlling the HTML real estate used by an embedded Flex application. The other post (link to post) gave a (hopefully) simplified view of code snippets that can be used to communicate between Flex and JavaScript under various scenarios. These were low-level, “how-to” posts. In this post, I’d like to explore some of the ways that this type of integration might benefit the enterprise.

In this particular situation, I was representing a company that had a new product/service offering. This offering is something that many existing E-Commerce web sites would like to add to their existing web site. Conceptually, this is a pretty common situation. However, integration is often more difficult to implement than it is to conceive.

That was not the case in this situation. Implementing this business offering by embedding a Flex application into an existing web site was embarrassingly easy. The integration instructions given to the E-Commerce site’s developers consisted of about 30 lines of text. This text consisted of the HTML Object/Embed tags and the JavaScript functions that the E-Commerce site’s developers needed to copy and paste into their web page. Beyond copying and pasting this text, all the E-Commerce site’s developers needed to do was to modify the JavaScript return values with the values from their web page.

They did not have to change any code on their server. They did not have to change the flow of their web pages. The Flex application that we provided them handled the external-domain server communication. We did not have to work-out the details of how the customer’s servers would access our servers and our services. We did not have to match technologies or protocols. The E-Commerce web site’s developers did not have to modify their server code to know, understand, and call our services.

This integration did not take months or years. This integration took something on the order of minutes or hours. I suppose you could say it took days, if you include time to arrange phone calls between the developers, etc.

Think about that. A new business offering was implemented in a matter of days.

Obviously, the company (or enterprise project team) providing the services, will have to build the backend for the services. But, they would have to do this anyway. The huge payoff is at integration time. And, if these services are used by many “clients” (either by selling the same offering over and over to many customers … or, within an enterprise, by allowing many project teams and existing applications to leverage your services), the cost-benefit analysis becomes compelling. Moreover, the more you can shrink the integration time, the easier it becomes to close a deal. In corporations, various levels of the hierarchy often have different levels of budgetary decision-making power. The lower the integration cost, the fewer levels of approval you will need to close a deal.

Admittedly, this was a specific type of business offering. It clearly does not replace all other forms of integration. As with any architectural tool (or software design pattern), you still must choose the best solution for a given challenge. There are many places where SOA, RESTful Web Services, XML, etc. will be the better solution. But, when this type of solution fits, it can really payoff!

Dynamically modifying the HTML space allocated to a Flex Application

March 28th, 2009

If you need to integrate a Flex application into an existing web page, you will probably want control over the amount of space that the Flex application uses on the web page. If the Flex application size never changes, you can simply set the height and width of the Flex application in the HTML code (in the Object and Embed tags). However, if the Flex application size is dynamic based upon user interaction, you will may want the HTML space allocated to the Flex application to change as the Flex application size changes. The purpose of this post is to show how this can be done.

The following Flex application has an “Add Fields” button. If you click that button, two things will happen. First, the “Add Fields” button will be removed. Second, a TextArea and another button (“Remove Fields”) will be added. This behavior will cause the height of the Flex application to grow. The Flex application will make a JavaScript call to the containing page to dynamically change the space allocated to the Flex application.

Similarly, if the “Remove Fields” button is clicked the height of the Flex application will shrink. So, again, the Flex application will make a JavaScript call to the containing page to dynamically change the space allocated to the Flex application.

In order to accomplish this, we first need to insert our Flex application into the containing HTML page:

<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
	codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab
#version=6,0,40,0"
	WIDTH="1" HEIGHT="1" id="mySwf" scrolling="no">
	<PARAM NAME=movie VALUE="FlexibleGorilla.swf">
	<PARAM NAME=quality VALUE=high>
	<EMBED src="FlexibleGorilla.swf"
		quality=high
		scrolling="no"
		WIDTH="1"
		HEIGHT="1"
		NAME="mySwf" ALIGN="" TYPE="application/x-shockwave-flash"
		PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
	</EMBED>
</OBJECT>

Next, we will add the following JavaScript function to the containing HTML page:

function updateSwfSize(myHeight, myWidth) {
	var flexibleGorillaSwf = document.getElementById("mySwf");
	flexibleGorillaSwf.height = myHeight;
	flexibleGorillaSwf.width = myWidth;
}

Then, in the Flex application, we will call this JavaScript function everytime the Flex application size changes. Here is the Flex code used in the example application:

<?xml version="1.0" encoding="utf-8"?>
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
							creationComplete="create()">

	<mx:Script>
		<![CDATA[

			private function create():void {
				updateSwfSize();
			}

			private function addFields():void {
				this.addButton.visible = false;
				this.addButton.includeInLayout = false;

				this.myTextArea.visible = true;
				this.myTextArea.includeInLayout = true;
				this.removeButton.visible = true;
				this.removeButton.includeInLayout = true;

				updateSwfSize();
			}

			private function removeFields():void {
				this.addButton.visible = true;
				this.addButton.includeInLayout = true;

				this.myTextArea.visible = false;
				this.myTextArea.includeInLayout = false;
				this.removeButton.visible = false;
				this.removeButton.includeInLayout = false;

				updateSwfSize();
			}

			private function updateSwfSize():void {
				this.validateNow();

				var newHeight:Number = this.myVBox.height;
				var newWidth:String = "100%";

				if (ExternalInterface.available) {
					ExternalInterface.call("updateSwfSize",
								newHeight,
								newWidth);
				}
			}

		]]>
	</mx:Script>

	<mx:VBox id="myVBox" horizontalAlign="center" width="100%">
		<mx:Label text="Dynamic Sizing Example" />
		<mx:Button id="addButton" label="Add Fields" click="addFields()" />

		<mx:TextArea id="myTextArea" text="FlexibleGorilla.com"
					width="90%" height="100"
					visible="false" includeInLayout="false" />
		<mx:Button id="removeButton" label="Remove Fields"
					click="removeFields()"
					visible="false" includeInLayout="false" />
	</mx:VBox>

</mx:VBox>

Flex JavaScript Communication

March 26th, 2009

I was recently developing a Flex application that needed to be integrated into an existing e-Commerce site. As part of the integration, I needed to communicate information between the Flex application and the containing HTML / JavaScript page. I don’t believe I’ve ever seen a web site that put together all of the various scenarios that I wanted in one place. So, I put together an application that contains small examples of each scenario that I was interested in. I thought it might be helpful to post these simple examples for others.

Presenting Summary-Detail Content

November 3rd, 2008

I was recently working on a task with Jon Rose (Jon’s Blog). We basically needed to implement the typical summary-detail functionality.

At a high level, we needed to show a DataGrid containing a list of items, along with some summary information about each item. The user would then select the item that they wanted to work with. At that point, we would remove the summary list and display the details of the item.

Removing the summary list allowed us to save screen real estate by removing now-irrelevant information (the user no longer needed to see the items that they did not select). However, this also meant that we were no longer displaying the summary information about the item that the user did select.

Although the summary information is typically present in the detail section, it is usually preferred that it also be presented as a header or title above the details. We could have created a Label to display this header/summary information. However, we already had a DataGrid row that displayed exactly what we needed. Furthermore, at this point, the user is already accustomed to seeing the summary data in this format. We wanted to keep the flow from summary-view to detail-view as obvious as possible.

What we really wanted was to keep the summary DataGrid, but shrink it to only show a single row. That single row should only show the item that the user had selected. We tried setting the row count to 1 and scrolling to put the selected item in view. But, that led to dealing with a scrollbar and some other annoying issues.

What we decided to do, instead, turned out to be much more simple (and, in hindsight, seemingly obvious!). Instead of trying scroll a DataGrid to the proper item, we created a filter to eliminate everything except the selected item. At that point, the DataGrid would only contain one item (the selected item). Thus, we could set the DataGrid’s row count to 1, and not have any of the other issues (scrollbars, etc.). Here is an example:

This behavior allowed us to keep the selected item’s summary information available in the form that the user was used to. It avoided the creation/maintenance of another way of displaying the summary information. It also allowed us to reclaim screen real estate. And, it was simple.

The remainder of this page discusses the code behind the example. I have omitted things like widths and resizing effects in an effort to simplify the conversation. First, we create your basic DataGrid:

<mx:DataGrid id="stockDG" dataProvider="{this.stocks}" itemClick="selectStock(event)">
	<mx:columns>
		<mx:DataGridColumn headerText="Company Name" dataField="companyName" />
		<mx:DataGridColumn headerText="Symbol" dataField="symbol" />
		<mx:DataGridColumn headerText="Exchange" dataField="exchange" />
		<mx:DataGridColumn headerText="Industry" dataField="industry" />
	</mx:columns>
</mx:DataGrid>

In addition, we will create a “details” section that will initially be invisible:

<mx:VBox id="viewDetailVbox" visible="false" includeInLayout="false">
	<mx:HBox width="100%" height="100%" backgroundColor="#F2F1F1">
		<mx:Label text="Company" />
		<mx:TextInput id="companyDetail" />
		<mx:Label text="Symbol" />
		<mx:TextInput id="symbolDetail" />
	</mx:HBox>
	<!-- ... (continue adding details fields) -->
</mx:VBox>

We will also create some buttons to allow the user to either update the data with any changes they made in the details section … or to cancel any changes they may have made.

<mx:HBox id="buttonsBox" visible="false" includeInLayout="false">
	<mx:Button label="Update" click="updateSelectedStock(event)"/>
	<mx:Button label="Cancel" click="closeSelectedStock(event)"/>
</mx:HBox>

When an item in the DataGrid is clicked, the selectStock(event) function will be called. Here is that code:

private function selectStock(event:ListEvent):void {
	this.selectedStock = Stock(stockDG.selectedItem);
	stockDG.selectedItem = null;

	filterArrayCollectionToSelectedItemOnly();
	collapseDataGridToOneRow();
	displayDetailsOfSelection();
}

And, here are the functions that are called by the selectStock(event) function:

private function filterArrayCollectionToSelectedItemOnly():void {
	//assign the filter function to use
	this.stocks.filterFunction = filterStocksToSelectedItemOnly;

	//run the filter
	this.stocks.refresh();
}

private function filterStocksToSelectedItemOnly(item:Object):Boolean {
	var thisIsTheSelectedItem:Boolean = false;
	if(item == this.selectedStock) {
		thisIsTheSelectedItem = true;
	}
	return thisIsTheSelectedItem;
}

private function collapseDataGridToOneRow():void {
	stockDG.rowCount = 1;
}

private function displayDetailsOfSelection():void {
	this.companyDetail.text = this.selectedStock.companyName;
	this.symbolDetail.text = this.selectedStock.symbol;
	//... (continue setting remaining values)

	showDetailsAndButtons();
}

If the user wishes to return to the summary list (by clicking either the Update or Cancel button), we will reset the DataGrid to contain all of the items by removing the fiter, calling refresh() on the collection being used by the dataProvider, and setting the rowCount to the number of items in the list. In addition, we will remove the details section and the buttons from display.

private function closeSelectedStock(event:Event):void {
	this.selectedStock = null;
	this.stocks.filterFunction = null;
	this.stocks.refresh();
	stockDG.rowCount = this.stocks.length;

	hideDetailsAndButtons();
}

Finally, here are the two functions that hide and display the details section and the buttons:

private function showDetailsAndButtons():void {
	viewDetailVbox.visible = true;
	viewDetailVbox.includeInLayout = true;
	this.buttonsBox.visible = true;
	this.buttonsBox.includeInLayout = true;
}

private function hideDetailsAndButtons():void {
	viewDetailVbox.visible = false;
	viewDetailVbox.includeInLayout = false;
	this.buttonsBox.visible = false;
	this.buttonsBox.includeInLayout = false;
}