Moris' Note Book

本博客所有内容皆收集于网上,非本人原创,非心情日记,非研究心得,只是自己浏览的东西的收集
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Communicating between Actionscript and JSFL

Posted on 2007-10-19 18:30  moris  阅读(512)  评论(0)    收藏  举报

Communicating between Actionscript and JSFL

When creating Commands or Timeline Effects using the extensibility layer, it is sometimes necessary to provide some kind of user interface to allow the user to customise the functionality. JSFL has a little friend who's sole purpose is to provide an easy markup language for describing Dialog Boxes. His name is XML2UI.

XML2UI is a subset of XUL (pronounced "zool"). If this is new to you, then I wrote a pretty comprehensive introduction to using XUL with JSFL for Internet.com some time ago. Check it out. Going further along that line, in this article i want to discuss passing variables to and from XML2UI Dialog boxes.

XML2UI is all well and good for basic user interfaces, but if the user interface needs any kind of complexity, such as drag and drop functionality, then it is makes sense to use the advantages that Flash Movies provide to create your user interface and have that Flash Movie displayed inside of an XML2UI dialog box.

 

Embedding Flash Movies inside XUL Dialog Boxes

Thankfully XML2UI provides a <flash> control that allows you to do just that. Its pretty simple to do:

<dialog title='Configuration' buttons='accept,cancel'>
    <flash width='200' height='100' src='dialog.swf'>
</dialog>

 

Save that XUL inside a textfile and give it a filename,' dialog.xml' works well for now, save it inside of the Commands directory.

Windows XP or Windows 2000:

C:Documents and Settings<user>Local SettingsApplication DataMacromediaFlash MX 2004<language>ConfigurationCommands

Windows 98:

C:WindowsApplication DataMacromediaFlash MX 2004<language>ConfigurationCommands

Macintosh 0SX:

Hard Drive/Users/<username>/Library/Application Support/Macromedia/Flash MX 2004/<language>/Configuration/Commands/

Now create your user interface, using Flash and Export the Movie to the Commands directory. For now, call it 'dialog.swf' as that is the name of the movie we specified in our XUL Dialog Defintion previously. You may also want to change the width and height attributes in your XUL above to match the size of your Flash Movie.

Then you can tell your JSFL scripts to parse and render that XML2UI dialog box using the document.xmlPanel() method:

fl.getDocumentDOM().xmlPanel(fl.configURI + 'Commands/dialog.xml');

 

Inside Flash, choose File > New > Flash Javascript File and then copy and paste the above code into the script editor. Save it inside the Commands directory on your machine. Now open the Command menu inside of Flash and choose your Command from the list. It will execute the above code and you should see a dialog box appear. When the document.xmlPanel() method is encountered by the JSFL interpreter execution of the script is paused so that you can retrieve a response from the dialog box.

Heres one i made earlier:

Dialog Box Example

Passing variables from Embedded Flash Movies back to JSFL

Smashing. So, the next problem is that it's no good having a user interface that cant talk back to JSFL to tell it what settings the user changed.

Thankfully Macromedia have that one covered too. Well sort of. You can only pass strings to and from XML2UI dialog boxes.

The document.xmlPanel() method returns a JSFL object which you can assign to a variable. This object contains one property by default, that tells you whether the dialog box was closed using the Ok button or the Cancel button. It's name is 'dismiss' and you use it as follows:

settings=fl.getDocumentDOM().xmlPanel(fl.configURI + 'Commands/dialog.xml');
if(settings.dismiss == 'accept')
{
    //run the JSFL script based upon the chosen settings
}
else
{
    //settings.dismiss = 'cancel'
    //they cancelled the dialog box
}

 

If the user closed the dialog box using the 'Ok' button then the 'dismiss' property will contain the string value 'accept' otherwise if the user closed the dialog box using the 'Cancel' button or the close button in the top right hand corner then the 'dismiss' property will contain the string value 'cancel'.

You can add further properties to this object by defining expected variables in your XUL Dialog Definition. To do this, we use the <property> XUL element.

Lets say for the sake of example, that our Flash User Interface contains a checkbox, we want to tell JSFL whether that checkbox was selected or not.

Back to our original markup for the dialog box. We now need to add a new <property> tag underneath the <flash> tag that will tell JSFL that it should expect a variable called 'checked':

<dialog title='Configuration' buttons='accept,cancel'>
    <flash width='200' height='100' src='dialog.swf' />
    <property id='checked' value='false' />
</dialog>

 

We have also specified that the 'checked' property will have a default value of "false".

Now we need our Flash User Interface to populate that variable with the selected state of the checkbox. We do this using the XMLUI actionscript object. The XMLUI actionscript object is only available inside of Flash Movies that are embedded inside of XUL Dialog Boxes. It has four static methods, we are interested in the XMLUI.set() method.

In actionscript we need to write some code that updates the value of the 'checked' property whenever a user clicks on a checkbox. This is fairly straightforward:

import mx.utils.Delegate

 

function clickHandler()
{
   XMLUI.set('checked',myCheckBox.selected);
}
myCheckBox.addEventListener('click',Delegate.create(this,clickHandler));

 

The above code tells the checkbox component to call the function called 'clickHandler' in the scope of the current timeline, whenever the checkbox is clicked on. The 'clickHandler' function then uses the XMLUI.set() static method to update the property we declared in our XUL Dialog Defitition with the 'selected' value. Note that this value although it is a boolean (true/false) in actionscript, will be converted into a string when passed to JSFL.

Back to JSFL, we can now check to see whether the checkbox was clicked in our Flash User Interface:

settings=fl.getDocumentDOM().xmlPanel(fl.configURI + 'Commands/dialog.xml');
if(settings.dismiss == 'accept')
{
    //run the JSFL script based upon the chosen settings
   if(settings.checked == 'true')

 

  {
      //the user clicked on the checkbox and selected it
  }
}
else
{
    //settings.dismiss = 'cancel'
    //they cancelled the dialog box
}

 

That is a pretty basic example, but you can specify as many expected properties as you like. Just remember that they will always contain strings when passed back from actionscript, so for example passing an actionscript object to JSFL requires some kind of interim toString() method that will convert the object into a readable string that JSFL can then parse back into an object when it is recieved. Same is true of arrays.

Passing variables to Embedded Flash Movies from JSFL

Now let's consider another scenario we have two JSFL script's, they both do similar things so they use the same Flash User Interface to configure both scripts. The Flash User Interface needs to know which JSFL script opened the dialog box so it can show the appropriate options.

Unfortuneatley, this should be quite simple to do, but due to a suspected bug i found today it is actually quite trivial.

The Suspected Bug

According to the Macromedia Documentation, the actionscript XMLUI.get() method is supposed to return the value of a property defined in an XUL dialog box definition file. This would suit us perfectly, all we would have to do is have two seperate XUL dialog box definition's, one for each script. Each XUL file would contain a property that the Flash User Interface could retrieve to determine which script opened the dialog box. However, we are not so lucky this time. The XMLUI.get() method returns nothing until you have used the actionscript XMLUI.set() method to define the value of the property. Which is kind of useless in my opinion.

But... and a big but, there is usually a solution to a problem, and that is part of the fun of working with Flash, solving little bugs with hacky code.

The Solution

This solution will only work in Flash MX 2004 7.2 and greater as it utilises the JSFL FLfile object which wasnt added until the 7.2 updater.

Since the good old days of Flash 4 it has been possible to loadVariables into a Flash Movie using actionscript. So, if you ever need to pass variables into a Flash Movie from a JSFL script, heres how you do it.

You create a textfile using JSFL that contains url encoded name/value pairs just before you open an XUL dialog box that requires variables to be passed to it. The Embedded Flash Movie then loads in that textfile using the LoadVars actionscript object. In your JSFL script on the line after the code that opens the dialog box, you then need to delete the textfile you created before the dialog box is opened.

//create a temporary textfile that contains the required variables
FLfile.write(fl.configURI+'/Commands/variables.txt','someVariables=someValue&amp;anotherVariable=anotherValue');

 

//open the dialog box - remember the JSFL script is paused until this dialog box is closed
var r = fl.getDocumentDOM().xmlPanel(fl.configURI + 'Commands/xmlPanel.xml');

//now the dialog box has been closed and the variables are no longer needed, we should remove the temporary textfile we created previously
FLfile.remove(fl.configURI+'/Commands/variables.txt');