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>

One Comment

  1. atar
    Posted August 11, 2008 at 4:03 pm | Permalink

    good

One Trackback

  1. [...] 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). [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word