IFrame Demo

•July 29, 2009 • Leave a Comment

http://rrao.host.adobe.com/kannan/FlexiFrame/IFrameDemo.html

http://rrao.host.adobe.com/kannan/FlexiFrame/srcview/index.html

RollOver Image

•July 24, 2009 • Leave a Comment

Main.MXML

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” xmlns:com=”com.*”>
<com:RollOverComp UpImage=”@Embed(source=’assets/UpImage.png’)” OverImage=”@Embed(source=’assets/OverImage.png’)”
ImageLink=”http://www.google.com”/&gt;
</mx:Application>

RollOverComp.MXML

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Canvas xmlns:mx=”http://www.adobe.com/2006/mxml&#8221;
creationComplete=”init()” creationPolicy=”all” >
<mx:Script>
<![CDATA[
public var UpImage:Class;
public var OverImage:Class;
public var ImageLink:String;
private function init():void{
up.source = UpImage;
addEventListener(MouseEvent.ROLL_OVER, mouseOver);
addEventListener(MouseEvent.ROLL_OUT, mouseOut);
addEventListener(MouseEvent.CLICK, mouseClick);
}
private function mouseOver(e:MouseEvent):void{
currentState = ‘overState’;
}
private function mouseOut(e:MouseEvent):void{
currentState = ”;
}
private function mouseClick(e:MouseEvent):void{
navigateToURL(new URLRequest(ImageLink),”_blank”);
}
]]>
</mx:Script>
<mx:states>
<mx:State name=”overState”>
<mx:RemoveChild target=”{up}”/>
<mx:AddChild relativeTo=”{this}”>
<mx:Image source=”{OverImage}” id=”over”/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:transitions>
<mx:Transition fromState=”*” toState=”overState”>
<mx:Fade duration=”800″ alphaFrom=”0″ alphaTo=”1″ target=”{over}”/>
</mx:Transition>
<mx:Transition fromState=”overState” toState=”*”>
<mx:Fade duration=”500″ alphaFrom=”0″ alphaTo=”1″ target=”{up}”/>
</mx:Transition>
</mx:transitions>
<mx:Image id=”up”/>
</mx:Canvas>

Steps using SWC files in your Flex projects

•July 22, 2009 • Leave a Comment

To use SWC files in your Flex projects, you add them to the project’s library path. The SWC files can be located in the project, in a Flex library project, in a shared folder within the workspace, or any other location that has been linked to the project (using a shared folder that was added to the project’s source path, for example).

When you use SWC files in applications, there are configuration options that determine whether they are statically or dynamically linked to the application, merged into the application SWF file, or external to it and accessed separately at run time.

Add an SWC file to the library path

  1. With a project selected in the Flex Navigator view, select Project > Properties > Flex Build Path.
  2. Click on the Library Path tab.
  3. Select any of these options to add SWC files:

Add Project Adds a Flex library project.

Add SWC Folder Lets you add a folder that contain SWC files.

Add SWC Adds a compiled SWC file.

Add Flex SDK Lets you add other Flex SDKs. If your project already has a Flex SDK in its library path, this button is disabled. If you remove the existing Flex SDK from your library path, the button is enabled. When you click this button, a Flex SDK node is added, but you are not prompted which one is added. To control which Flex SDK to use, select Project > Properties > Flex Compiler.

  1. Enter or browse to and select the location of the SWC file, project, or folder. Click OK.

The SWC file, library project, or folder is added to the library path.

Merge the SWC file into the application SWF file when compiled

  1. With a project selected in the Flex Navigator view, select Project > Properties > Flex Build Path.
  2. Click on the Library Path tab, and then select and expand the SWC file entry to display the SWC options.
  3. Double-click the Link Type option. The Library Path Items Options dialog box appears.
  4. Select the Merged into Code option, and click OK.

This procedure is the equivalent of using the library-path compiler option.

Set the SWC file as an external library file

  1. With a project selected in the Flex Navigator view, select Project > Properties > Flex Build Path.
  2. Select the Library Path tab, and then select and expand the SWC file entry to display the SWC options.
  3. Double-click the Link Type option. The Library Path Items Options dialog box appears.
  4. Select the External option, and click OK.

This procedure is the equivalent of using the external-library-path compiler option.

Use the SWC file as an RSL

  1. With a project selected in the Flex Navigator view, select Project > Properties > Flex Build Path.
  2. Select the Library Path tab, and then select and expand the SWC file entry to display the SWC options.
  3. Double-click the Link Type option. The Library Path Items Options dialog box appears.
  4. Select the Run-time Shared Library (RSL) option.
  5. Enter the URL where the SWC library will reside when the application is deployed.
  6. (Optional) To extract the SWF file in the SWC file when it is placed in the deploy location, select the Automatically extract swf to deployment path option.
  7. Click OK.

Using the SWC files as an RSL simplifies the process for using RSLs manually. To do this, you extract the SWF file from the SWC file and set the values of the runtime-shared-library-path compiler option.

For more information about using SWC files as an RSL, see Using Runtime Shared Libraries in Building and Deploying Adobe Flex 3 Applications.

Resize the controls using ResizeManager Class

•July 21, 2009 • 3 Comments

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; layout=”absolute” initialize=”initApp();”>

<mx:Script>
<![CDATA[
import mx.events.DropdownEvent;
import flash.display.*;
import flash.utils.*;
import mx.controls.*;
import mx.containers.*;
import mx.core.UIComponent;
import mx.containers.Panel
import sjd.managers.*;
import mx.managers.PopUpManager;

[Bindable]
public var cards: Array = [{label:”mx.controls.ComboBox”, data:”mx.controls.ComboBox”},
{label:”mx.containers.Panel”, data:”mx.containers.Panel”},
{label:”mx.containers.Canvas”, data:”mx.containers.Canvas”},
{label:”mx.containers.TitleWindow”, data:”mx.containers.TitleWindow”},
{label:”mx.controls.TextArea”, data:”mx.controls.TextArea”},
{label:”mx.controls.Button”, data:”mx.controls.Button”}];

private function initApp():void{
var window:TitleWindow = TitleWindow(PopUpManager.createPopUp( this, TitleWindow , false));
window.x = 100;
window.y = 100;
window.width = 200;
window.height = 200;
window.title = “PopUp Window”
ResizeManager.enableResize(window, 50);
}
private function creatObj():void{
var itemName:String = c1.selectedItem[“data”];
var obj:UIComponent;
switch(itemName){
case “mx.controls.ComboBox”:
obj = new ComboBox();
break;
case “mx.containers.Panel”:
obj = new Panel();
obj.width = Math.random() * this.width / 2;
obj.height = Math.random() * this.height / 2;
break;
case “mx.containers.TitleWindow”:
obj = new TitleWindow();
obj.width = Math.random() * this.width / 2;
obj.height = Math.random() * this.height / 2;
break;
case “mx.controls.TextArea”:
obj = new TextArea();
break;
case “mx.controls.Button”:
obj = new Button();
break;
case “mx.containers.Canvas”:
obj = new Canvas();
obj.width = Math.random() * this.width / 2;
obj.height = Math.random() * this.height / 2;
obj.setStyle(“borderStyle”, “solid”);
obj.setStyle(“backgroundColor”, “#FFFF00″);
break;
}
obj.x = Math.random() * this.width – obj.width;
obj.y = Math.random() * this.height – obj.height + 50;
this.addChild(obj);
ResizeManager.enableResize(obj, 50);
}
]]>
</mx:Script>
<mx:ComboBox id=”c1″ x=”0″ dataProvider=”{cards}” width=”200″ />
<mx:Button id=”b1″ label=”Create” x=”210″ click=”creatObj();” />
</mx:Application>

ResizeManager.as

package sjd.managers{

import flash.events.MouseEvent;
import flash.geom.Point;
import mx.containers.Panel;
import mx.core.Application;
import mx.core.UIComponent;
import mx.events.FlexEvent;
import mx.managers.CursorManager;
import mx.managers.CursorManagerPriority;

/**
* @class ResizeManager
* @brief Enable any UIComponent to resize
* @author Jove
* @version 1.1
*/
public class ResizeManager{

[Embed(source=”/sjd/assets/mouseMove.gif”)]
private static const CURSOR_MOVE:Class;
[Embed(source=”/sjd/assets/verticalSize.gif”)]
private static const VERTICAL_SIZE:Class;
[Embed(source=”/sjd/assets/horizontalSize.gif”)]
private static const HORIZONTAL_SIZE:Class;
[Embed(source=”/sjd/assets/leftObliqueSize.gif”)]
private static const LEFT_OBLIQUE_SIZE:Class;
[Embed(source=”/sjd/assets/rightObliqueSize.gif”)]
private static const RIGHT_OBLIQUE_SIZE:Class;

private static const RESIZE_OLD_POINT:String = “oldPoint”;
private static const RESIZE_OLD_HEIGHT:String = “oldHeight”;
private static const RESIZE_OLD_WIDTH:String = “oldWidth”;
private static const RESIZE_OLD_X:String = “oldX”;
private static const RESIZE_OLD_Y:String = “oldY”;
private static const RESIZE_MIN_SIZE:String = “minSize”;
private static const RESIZE_IS_POPUPE:String = “isPopup”;

private static const SIDE_OTHER:Number = 0;
private static const SIDE_TOP:Number = 1;
private static const SIDE_BOTTOM:Number = 2;
private static const SIDE_LEFT:Number = 4;
private static const SIDE_RIGHT:Number = 8;

private static var resizeObj:UIComponent;
private static var mouseState:Number = 0;

public static var isResizing:Boolean = false;
public static var mouseMargin:Number = 4;
public static var defaultCursor:Class = null;
public static var defaultCursorOffX:Number = 0;
public static var defaultCursorOffY:Number = 0;

public static function setDefaultCursor(cursor:Class = null, offX:Number = 0, offY:Number = 0):void{
defaultCursor = cursor;
defaultCursorOffX = offX;
defaultCursorOffY = offY;
}

/**
* Enable the UIComponent to have resize capability.
* @param targetObj The UIComponent to be enabled resize capability
* @param minSize The min size of the UIComponent when resizing
*/
public static function enableResize(targetObj:UIComponent, minSize:Number):void{
//Application.application.parent:SystemManager
Application.application.parent.addEventListener(MouseEvent.MOUSE_UP, doMouseUp);
Application.application.parent.addEventListener(MouseEvent.MOUSE_MOVE, doResize);

initPosition(targetObj);

targetObj.setStyle(RESIZE_OLD_POINT, new Point());
targetObj.setStyle(RESIZE_MIN_SIZE, minSize);
targetObj.setStyle(RESIZE_IS_POPUPE, targetObj.isPopUp);

targetObj.addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
//targetObj.addEventListener(MouseEvent.MOUSE_UP, doMouseUp);
targetObj.addEventListener(MouseEvent.MOUSE_MOVE, doMouseMove);
targetObj.addEventListener(MouseEvent.MOUSE_OUT, doMouseOut);
}

/**
* Disable the UIComponent to have resize capability.
* @param targetObj The UIComponent to be disabled resize capability
*/
public static function disableResize(targetObj:UIComponent):void{
targetObj.removeEventListener(MouseEvent.MOUSE_DOWN, doMouseDown);
//targetObj.removeEventListener(MouseEvent.MOUSE_UP, doMouseUp);
targetObj.removeEventListener(MouseEvent.MOUSE_MOVE, doMouseMove);
targetObj.removeEventListener(MouseEvent.MOUSE_OUT, doMouseOut);
}

private static function initPosition(obj:Object):void{
obj.setStyle(RESIZE_OLD_HEIGHT, obj.height);
obj.setStyle(RESIZE_OLD_WIDTH, obj.width);
obj.setStyle(RESIZE_OLD_X, obj.x);
obj.setStyle(RESIZE_OLD_Y, obj.y);
}

/**
* Set the first global point that mouse down on the resizeObj.
* @param The MouseEvent.MOUSE_DOWN
*/
private static function doMouseDown(event:MouseEvent):void{

if(mouseState != SIDE_OTHER){

resizeObj = UIComponent(event.currentTarget);

initPosition(resizeObj);

var point:Point = new Point();
point.x = resizeObj.mouseX;
point.y = resizeObj.mouseY;

point = resizeObj.localToGlobal(point);
resizeObj.setStyle(RESIZE_OLD_POINT, point);
}
}

/**
* Clear the resizeObj and also set the latest position.
* @param The MouseEvent.MOUSE_UP
*/
private static function doMouseUp(event:MouseEvent):void{
isResizing = false;
if(resizeObj != null){
initPosition(resizeObj);
}
resizeObj = null;
}

/**
* Show the mouse arrow when not draging.
* Call doResize(event) to resize resizeObj when mouse is inside the resizeObj area.
* @param The MouseEvent.MOUSE_MOVE
*/
private static function doMouseMove(event:MouseEvent):void

{
var thisObj:UIComponent = UIComponent(event.currentTarget);
var point:Point = new Point();
point = thisObj.localToGlobal(point);
isResizing = true;
if(resizeObj == null)

{
var xPosition:Number = Application.application.parent.mouseX;
var yPosition:Number = Application.application.parent.mouseY;
if(xPosition >= (point.x + thisObj.width – mouseMargin) && yPosition >= (point.y + thisObj.height – mouseMargin)){
changeCursor(LEFT_OBLIQUE_SIZE, -6, -6);
mouseState = SIDE_RIGHT | SIDE_BOTTOM;
}else if(xPosition <= (point.x + mouseMargin) && yPosition <= (point.y + mouseMargin)){
changeCursor(LEFT_OBLIQUE_SIZE, -6, -6);
mouseState = SIDE_LEFT | SIDE_TOP;
}else if(xPosition <= (point.x + mouseMargin) && yPosition >= (point.y + thisObj.height – mouseMargin)){
changeCursor(RIGHT_OBLIQUE_SIZE, -6, -6);
mouseState = SIDE_LEFT | SIDE_BOTTOM;
}else if(xPosition >= (point.x + thisObj.width – mouseMargin) && yPosition <= (point.y + mouseMargin)){
changeCursor(RIGHT_OBLIQUE_SIZE, -6, -6);
mouseState = SIDE_RIGHT | SIDE_TOP;
}else if(xPosition >= (point.x + thisObj.width – mouseMargin)){
changeCursor(HORIZONTAL_SIZE, -9, -9);
mouseState = SIDE_RIGHT;
}else if(xPosition <= (point.x + mouseMargin)){
changeCursor(HORIZONTAL_SIZE, -9, -9);
mouseState = SIDE_LEFT;
}else if(yPosition >= (point.y + thisObj.height – mouseMargin)){
changeCursor(VERTICAL_SIZE, -9, -9);
mouseState = SIDE_BOTTOM;
}else if(yPosition <= (point.y + mouseMargin)){
changeCursor(VERTICAL_SIZE, -9, -9);
mouseState = SIDE_TOP;
}else{
changeCursor(defaultCursor, defaultCursorOffX, defaultCursorOffY);
mouseState = SIDE_OTHER;
isResizing = false;
}

if(thisObj.getStyle(RESIZE_IS_POPUPE)){
//When cursor is move arrow, disable popup
if(mouseState != SIDE_OTHER){
thisObj.isPopUp = false;
}else{
thisObj.isPopUp = true;
}
}
}
//Use SystemManager to listen the mouse reize event, so we needn’t handle the event at the current object.
//doResize(event);
}

/*** Hide the arrow when not draging and moving out the resizeObj.
* @param The MouseEvent.MOUSE_MOVE*/
private static function doMouseOut(event:MouseEvent):void{
if(resizeObj == null)

{
changeCursor(defaultCursor, defaultCursorOffX, defaultCursorOffY);
mouseState = SIDE_OTHER;
}
}

/*** Resize when the draging resizeObj, resizeObj is not null.
* @param The MouseEvent.MOUSE_MOVE*/

private static function doResize(event:MouseEvent):void

{
if(resizeObj != null){
var point:Point = Point(resizeObj.getStyle(RESIZE_OLD_POINT));
var xPlus:Number = Application.application.parent.mouseX – point.x;
var yPlus:Number = Application.application.parent.mouseY – point.y;
var windowMinSize:Number = Number(resizeObj.getStyle(RESIZE_MIN_SIZE));
var ow:Number = Number(resizeObj.getStyle(RESIZE_OLD_WIDTH));
var oh:Number = Number(resizeObj.getStyle(RESIZE_OLD_HEIGHT));
var oX:Number = Number(resizeObj.getStyle(RESIZE_OLD_X));
var oY:Number = Number(resizeObj.getStyle(RESIZE_OLD_Y))
switch(mouseState)

{
case SIDE_RIGHT | SIDE_BOTTOM:
resizeObj.width = ow + xPlus > windowMinSize ? ow + xPlus : windowMinSize;
resizeObj.height = oh + yPlus > windowMinSize ? oh + yPlus : windowMinSize;
break;
case SIDE_LEFT | SIDE_TOP:
resizeObj.width = ow – xPlus > windowMinSize ? ow – xPlus : windowMinSize;
resizeObj.height = oh – yPlus > windowMinSize ? oh – yPlus : windowMinSize;
resizeObj.x = xPlus < ow – windowMinSize ? oX + xPlus: resizeObj.x;
resizeObj.y = yPlus < oh – windowMinSize ? oY + yPlus : resizeObj.y;
break;
case SIDE_LEFT | SIDE_BOTTOM:
resizeObj.width = ow – xPlus > windowMinSize ? ow – xPlus : windowMinSize;
resizeObj.height = oh + yPlus > windowMinSize ? oh + yPlus : windowMinSize;
resizeObj.x = xPlus < ow – windowMinSize ? oX + xPlus: resizeObj.x;
break;
case SIDE_RIGHT | SIDE_TOP:
resizeObj.width = ow + xPlus > windowMinSize ? ow + xPlus : windowMinSize;
resizeObj.height = oh – yPlus > windowMinSize ? oh – yPlus : windowMinSize;
resizeObj.y = yPlus < oh – windowMinSize ? oY + yPlus : resizeObj.y;
break;
case SIDE_RIGHT:
resizeObj.width = ow + xPlus > windowMinSize ? ow + xPlus : windowMinSize;
break;
case SIDE_LEFT:
resizeObj.width = ow – xPlus > windowMinSize ? ow – xPlus : windowMinSize;
resizeObj.x = xPlus < ow – windowMinSize ? oX + xPlus: resizeObj.x;
break;
case SIDE_BOTTOM:
resizeObj.height = oh + yPlus > windowMinSize ? oh + yPlus : windowMinSize;
break;
case SIDE_TOP:
resizeObj.height = oh – yPlus > windowMinSize ? oh – yPlus : windowMinSize;
resizeObj.y = yPlus < oh – windowMinSize ? oY + yPlus : resizeObj.y;
break;
}
}
}

private static var currentType:Class = null;
/*** Remove the current cursor and set an image.
* @param type The image class
* @param xOffset The xOffset of the cursorimage
* @param yOffset The yOffset of the cursor image*/

private static function changeCursor(type:Class, xOffset:Number = 0, yOffset:Number = 0):void

{
if(currentType != type)

{
currentType = type;
CursorManager.removeCursor(CursorManager.currentCursorID);
if(type != null)

{
CursorManager.setCursor(type, CursorManagerPriority.MEDIUM, xOffset, yOffset);
}
}
}
}
}

Binding of properties between sub components

•July 21, 2009 • Leave a Comment

In the process of testing what he outlined, I created a simple example, which I have posted here.

The point of this example is to show how you can declare “public” variables in a component, and then access those variables as properties form the component that uses it…

The example consists of 2 files:

FormExample.mxml (Application File)

Code:

<?xml version=“1.0” encoding=“utf-8”?>
<mx:Application xmlns:mx=http://www.adobe.com/2006/mxml layout=“absolute” >

<mx:Panel>
<!– call in the MyForm component –>
<local:MyForm
id=“myForm”
title=“My Form”
xmlns:local=“*”
/>

<!–
a button with the “enabled” property bound to the “formValid” property of the myForm component above
–>

<mx:Button
id=“myButton”
label=“My Button: enabled is ‘{myButton.enabled.toString()}'”
enabled=“{myForm.formValid}”
/>

</mx:Panel>

</mx:Application>

MyForm.mxml (in the root folder of the project)

Code:

<?xml version=“1.0” encoding=“utf-8”?>
<mx:Panel xmlns:mx=http://www.adobe.com/2006/mxml layout=“vertical”>

<mx:Script>
<![CDATA[
/*
Create property and expose it by declaring it as “public”,
and let the compiler know to make if bindable using the [Bindable] meta tag
*/

[Bindable] public var formValid:Boolean = false;
]]>
</mx:Script>
<!– Something to let us know if the ‘form’ is currently Valid or Invalid –>
<mx:Text text=“Form is Currently {formValid == true ? ‘Valid’ : ‘Invalid’}” />

<!– simple button to toggle the formValid status –>
<mx:Button label=“Toggle Form Valid” click=“formValid = !formValid;” />

</mx:Panel>

Result:

//

AutoComplete

•July 21, 2009 • 2 Comments

POSTED BY: hillelcoren

While there are a number of other Flex AutoComplete components out there, I wasn’t able to find one which fit my needs. After struggling for a while I ended up creating my own.

Important Info

  • License: The component is freeware with the source code available. You can use it any way you like, I just ask that if you make any improvements or fix any bugs that you send them back to me so I can include them in the component.
  • Support: I try as hard as possible to respond to any questions posted on the blog within a day. I’ve been using the component for a while now and am pretty confident that it works well. If you’d like to extend it I’m happy to work with you to get your feature working.
  • What’s next: I’m currently working on improving the documentation and starting to test it under Flex 4.

Version History

http://web.me.com/hillelcoren/Site/Demo.html

Importing Contacts from Mail Server

•July 21, 2009 • Leave a Comment

One of the requirements called for importing contacts from their email addresses. With the number of websites implementing contact importers these days, I figured there would be plenty of Flex components out there to import your contacts.

After googling for about half an hour, I was quite frustrated not finding any. I started looking for PHP solutions that I could port to Flex. I found OpenInviter.

As of now, it allows you to import contacts from 62 different email and social network providers.

So I started working on a Flex component that imports contacts via OpenInviter.

What the component does

Enter your email address and password and the component will attempt to retrieve contacts from your email provider and display it in a datagrid. Also, that component will attempt to detect your provider from email address you’ve entered. Feel free to extend it to your liking.

Note: The component is still very basic. If you’ve got suggestions on how it can be improved upon or simplified, feel free to comment on this page. I’ll be listening and updating as time allows.

Disclaimer: I happened to have come across some claims that OpenInviter may be storing email addresses and passwords you inpuy while accessing their APIs. Although those were only comments at some blog post, I feel compelled to distance myself from OpenInviter’s team. I take no responsibility for OpenInviter’s actions. The component mentioned in this tutorial uses OpenInviter’s API. If you’re not comfortable with OpenInviter’s handling of your personal information, do not use any information or content on this tutorial.

If anyone has any sort of information on this, please share it with us.

By clicking on the links below, you agree to have read and understood the disclaimer above.

Implementation from Source files

If you’ve got the source files, these are the steps you’ll need to take before the component can be used.

  1. Register for a private key at http://openinviter.com/register.php
  2. If you download the OpenInviter class from their website, it comes pre-filled with your username and private key. If you are using the openinviter class included in the source, enter your username and private_key in the config.php file.
  3. Upload the OpenInviter class and FlexInviter.php on your server. Make sure they’re both on the same folder.
  4. Import the Flex Project file (if you’ve downloaded application source). Otherwise add the com folder to your project. The component is called FlexOpenInviter.
  5. Open the FlexOpenInviter component and fill in the importerGatewayURL string pointing to the url of the FlexInviter.php file that you just uploaded.
  6. That should be it… test the application!

Code Review

MXML

	<mx:HTTPService id="svc"
		method="POST"
		url="{importerGatewayURL}"
		resultFormat="e4x"
		result="svcResult_handler( event )" />

	<mx:Form>
		<mx:FormItem label="Email address">
			<mx:TextInput id="txtEmail"
				change="emailInput_handler( event )" />
		</mx:FormItem>
		<mx:FormItem label="Password">
			<mx:TextInput id="txtPassword"
				displayAsPassword="true" />
		</mx:FormItem>
		<mx:FormItem label="Provider">
			<mx:ComboBox id="cmbProvider" 
				dataProvider="{xmlProviders.email..name}" />
		</mx:FormItem>
		<mx:FormItem>
			<mx:Button id="btnSubmit" 
				label="Submit"
				click="sumbitClick_handler( event )" />
		</mx:FormItem>		
	</mx:Form>

	<mx:DataGrid id="dg" 
		dataProvider="{xmlContacts.contact}" 
		width="400" height="80%"
		allowMultipleSelection="true"  >
		<mx:columns>
			<mx:DataGridColumn dataField="name" />
			<mx:DataGridColumn dataField="email" />
		</mx:columns>
	</mx:DataGrid>

For those familiar with MXML, the above code should be self-explanatory. I will get to the XML Schema soon.

PHP File (FlexInviter.php)

<?php
include( 'OpenInviter/openinviter.php' );
$inviter = new OpenInviter();
$plugins = $inviter->getPlugins();

if ( $_POST[ 'action' ] == "get_plugins" )
{
	echo arrayToXMLProviders( $plugins );	
}
else if ( $_POST[ 'action' ] == "get_contacts" )
{
	$inviter->startPlugin( $_POST[ 'provider' ] );
	$inviter->login( $_POST[ 'user_username' ], $_POST[ 'user_userpwd' ] );

	echo arrayToXMLContacts( $inviter->getMyContacts() );
}

function arrayToXMLContacts( $paramxml )
{
	$xml = new XmlWriter();
	$xml->openMemory();
	$xml->startDocument('1.0', 'UTF-8');
	$xml->startElement('root');

	function write(XMLWriter $xml, $param){
	    foreach($param as $key => $value){
		/*if(is_array($value)){
	            $xml->startElement("contact");
	            write($xml, $value);
	            $xml->endElement();
	            continue;
	        }*/
	        $splitKey = split( "@", $key );
	        $key = $splitKey[0];
	        $xml->startElement('contact');
	        $xml->writeElement( "name", $key );
	        $xml->writeElement( "email", $value );
		$xml->endElement();

	    }
	}
	write($xml, $paramxml);

	$xml->endElement();
	return $xml->outputMemory(true);	
}

function arrayToXMLProviders( $paramxml )
{
	$xml = new XmlWriter();
	$xml->openMemory();
	$xml->startDocument('1.0', 'UTF-8');
	$xml->startElement('root');

	function write(XMLWriter $xml, $param){
	    foreach($param as $key => $value){
		if(is_array($value)){
	            $xml->startElement($key);
	            write($xml, $value);
	            $xml->endElement();
	            continue;
	        }

	        $xml->writeElement( $key, $value );	        
	    }
	}
	write($xml, $paramxml);

	$xml->endElement();
	return $xml->outputMemory(true);	
}
?>

Note: The PHP script is lacking and so is the XML schema it generates. Comments and suggestions are welcomed!

Before we look at the ActionScript code, let’s look at how the provider and contact data is being received.

  1. Includes the OpenInviter class (openinviter.php)
  2. Instantiates an object of that class ($inviter)
  3. Gets plugin list. Plugins are used synonymous with providers here. For example… Gmail, Hotmail, Yahoo are plugins.
  4. If Flex sends in action parameter as get_plugins, convert plugin list (array by default) to XML and return to Flex. I had some issues returning the array. So it’s XML for now!
  5. If Flex sends in action parameter as get_contacts, call the OpenInviter class method startPlugin passing in the provider. Meaning, connect to the provider (Gmail, Hotmail, Yahoo, etc ). Then, login with the username and password provided by Flex as parameters. And finally, convert contact list (array by default) to XML and return to Flex.
  6. arrayToXMLContacts and arrayToXMLProviders functions do what their names imply. Converts provider and contact arrays to XML.

XML Schema

Sample Provider

<root>
  <email>
    <name>Abv</name>
    <version>1.0.0</version>
    <description>Get the contacts from a Abv account</description>
    <base_version>1.6.5</base_version>	
    <type>email</type>
    <check_url>http://www.abv.bg/</check_url>
  </email>
</root>

Sample Contact

<root>
  <contact>
    <name>PersonName</name>
    <email>person@gmail.com</email>
  </contact>
</root>

ActionScript

?View Code ACTIONSCRIPT
import mx.utils.StringUtil;

/** THIS NEEDS TO BE FILLED TO COMPONENT TO WORK **/
[Bindable]
private var importerGatewayURL:String = "";

[Bindable]
private var xmlProviders:XML;

[Bindable]
private var xmlContacts:XML;

private function init():void
{
	getProviders();
}

private function getProviders():void
{
	var param:Object = new Object();
	param.action = "get_plugins";
	svc.send( param );
}

private function getContacts():void
{
	var providerXMLString:String = xmlProviders.email.children()[ cmbProvider.selectedIndex ];
	var xmlSplitArray:Array = providerXMLString.split(">");
	var providerString:String = xmlSplitArray[0].toString().substr(1);

	var param:Object = new Object();
	param.action = "get_contacts";
	param.user_username = txtEmail.text;
	param.user_userpwd = txtPassword.text;
	param.provider = StringUtil.trim( providerString );

	svc.send( param );
}

private function emailInput_handler( e:Event ):void
{
	var arrEmailParts:Array = txtEmail.text.split("@");
	if ( arrEmailParts.length <= 1 )
	{
		return
	}				

	var strProvider:String = arrEmailParts[1];	
	for ( var i:int = 0; i < cmbProvider.dataProvider.length; i++ )
	{
		if ( cmbProvider.dataProvider[i].toString().substr( 0, strProvider.length ).toLowerCase() == strProvider.toLowerCase())
		{
			cmbProvider.selectedIndex = i;
			break;
		}
	}
}

private function sumbitClick_handler( e:Event ):void
{	
	getContacts();
}

private var resultIsProviderList:Boolean = true;
private function svcResult_handler( e:Event ):void
{
	if ( resultIsProviderList ) 
	{
		xmlProviders = XML( svc.lastResult );
		resultIsProviderList = false;
	}
	else
	{
		xmlContacts = XML( svc.lastResult );
	}					
}
  • importerGatewayURL should point to the FlexInviter.php file
  • init() called on component’s creationComplete event
  • getContacts() – providerXMLString, xmlSplitArray and providerString basically drill down to the name of the selected provider, so it can be sent to the php code alongwith the username and password.
  • emailInput_handler() – this function basically tries to match the domain of the email address to the provider. So, if you type your email address as myemailaddress@gmail.com, this function will switch your provider to Gmail.

Known Bugs

  1. Contact name and email may be switched depending on the provider
  2. Provider detector is basic. Doesn’t work with all providers
  3. No fault handler