Calling JavaScript from Flex with External Interface

The Flex Ajax Bridge, which for some reason you can only download with Flex Data Services (a 150mb+ download for a 16k file), isn’t the only way to send data from Flex to JavaScript there’s also the External Interface API. I’m working on a Rails project tracker application for a construction company and need to set start and end dates for each project. To make sure dates are entered without mistakes I needed a calendar widget that I could easily drop in a form and customize. I tried out some of the Ajax libraries calendars but they where either a) hard to figure out or b) hard to customize or c) both.

I was worried the Flex solution would be a large file at 152k but was surprised to find the files needed for the best Ajax Calendar I found, the Yahoo! UI one, were double in size at 292k (js, css, and gifs). You can download the source here.

A live example is here.

Here’s the MXML code to layout the calendars:

<mx:HBox horizontalAlign="center" verticalAlign="middle" horizontalGap="10" x="0" y="0" width="375">
    <mx:VBox verticalGap="0">
        <mx:Label text="Start Date" color="#333333" fontSize="13" fontWeight="bold" width="100%" textAlign="center" height="25"/>
        <mx:DateChooser id="startDate" yearNavigationEnabled="true"
            change="setDate(DateChooser(event.target))"
            height="175" width="175"
            borderColor="#006600" borderThickness="3"
            cornerRadius="10"
            selectionColor="#99FF33"/>
    </mx:VBox>
    <mx:VBox verticalGap="0">
        <mx:Label text="End Date" color="#333333" fontSize="13" fontWeight="bold" width="100%" textAlign="center" height="25"/>
        <mx:DateChooser id="endDate" yearNavigationEnabled="true"
            change="setDate(DateChooser(event.target))"
            height="175" width="175"
            cornerRadius="10"
            borderColor="#990000" borderThickness="3"
            selectionColor="#FF9999"
            enabled="false"/>
    </mx:VBox>
</mx:HBox>

Here’s the ActionScript to validate the dates and send the data to JavaScript. ExternallInterface.call() is the method that sends the data:

import flash.external.*;
import mx.controls.Alert;

public var startDate_reset:Date     = undefined;
public var endDate_reset:Date       = undefined;

public function setDate(calendar:DateChooser) : void
{
    // start date
    if (calendar.id == "startDate")
    {
        if (endDate.enabled && endDate.selectedDate <= startDate.selectedDate)
        {
            Alert.show("Start Date must be before End Date");
            startDate.selectedDate = startDate_reset;
        }
        else
        {
            endDate.enabled = true;
            startDate_reset = startDate.selectedDate;
            setDateJS(calendar);
        }
    }
    // end date
    else
    {
        if (endDate.selectedDate <= startDate.selectedDate)
        {
            Alert.show("End Date must be after Start Date");
            endDate.selectedDate = endDate_reset;
        }
        else
        {
            endDate_reset = endDate.selectedDate;
            setDateJS(calendar);
        }
    }
}

public function setDateJS(calendar:DateChooser) : void
{
   var s:String;
   if (ExternalInterface.available)
   {
      var eventObj:Object = new Object();
      eventObj.id = calendar.id;
      eventObj.date = calendar.selectedDate;
      var wrapperFunction:String = "setDate";
      s = ExternalInterface.call(wrapperFunction, eventObj);
   }
   else
   {
      s = "Wrapper not available";
   }
}

And finally the JavaScript and markup on the page, Prototype is used to set the input values (they have ids to match their Flex counterparts):

<html>
<head>
<title>Flex to JavaScript, Calendar Example</title>
<script src="javascripts/AC_RunActiveContent.js" type="text/javascript"></script>
<script src="javascripts/prototype.js" type="text/javascript"></script>
</head>
<body>

<SCRIPT LANGUAGE="JavaScript">
    function setDate(eventObj)
    {
        var date = new Date(eventObj.date);
        $(eventObj.id).value = eventObj.date.getMonth() + 1 + "/" + eventObj.date.getDate() + "/" + eventObj.date.getFullYear();
    }
</SCRIPT>

<div>
    <script type="text/javascript">
AC_FL_RunContent( id,mySwf,codebase,http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0,height,200,width,375,name,mySwf,src,Calendar,pluginspage,http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash,flashvars, ); //end AC code
</script><noscript><object id=mySwf classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0 height=200 width=375>
<param name=src value=Calendar.swf/>
        <param name=flashVars value=/>
        <embed name=mySwf src=Calendar.swf pluginspage=http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash height=200 width=375 flashVars=/>
    </object></noscript>
</div>

<form id="dateForm" action="#" method="post">
    <p>
        Start Date: <input id="startDate" type="text" />
    </p>
    <p>
        End Date: <input id="endDate" type="text" />
    </p>
</form>

</body>
</html>

2 Responses to “Calling JavaScript from Flex with External Interface”

  1. Vixiom Axioms » Flex DateChooser select a week Says:

    […] My Flex DateChooser to JavaScript example didn’t solve my date selection problem entirely as the project I’m working on requires a project to have a start week rather than a start day. The Flex DateChooser has built in selectable ranges so it’s pretty easy to set that up (right click on swf to view source). […]

  2. atar Says:

    good

Leave a Reply

*
To prove you're a person (not a spam script), type the security word shown in the picture.
Anti-Spam Image