Flex与JavaScript的相互通信(真情贡献)
近期正在做有关Flex的项目,由于需要将Flex的应用嵌入到HTML中,实现Flex与JavaScript的相互通信。本人在做这项工作的时候也浏览了一些贴子,发现国人的帖子太过简单,让刚刚接手的人总有一种摸不着头脑的感觉。在众多的网站和帖子中有一英文的网站对Flex与Javascript之间的相互通信的问题进行了详细的介绍,名曰:Switch On the Code,写的委实不错,现借他示例对该问题做一个了结。
进入正题。。。
在Flex与JavaScript相互通信的过程中,使用了一个非常重要的类——ExternalInterface?。通过 ExternalInterface 类,您可以在 Flash 运行时中使用 HTML 页面中的 JavaScript 调用 ActionScript 函数。ActionScript 函数可以返回一个值,JavaScript 会立即接收它作为该调用的返回值。它有两个非常重要且比较常用的方法:
?
?ExternalInterface.call?(functionName:String, ...parameters):ExternalInterface.addCallback?(functionName:String, closure:Function);其中,第一个方法是为Flex调用JS做准备的,第二个方法是为JS调用Flex方法准备的他们的具体用法将在下面的小例子中得以体现。
在这个小示例中要实现的是:1,将Flex中有关人的信息:姓名、年龄、性别传递到HTML页面中。2,新创建一个人,并将其信息传到Flex中显示。
如果你正在用FLEX Builder(我用的时FlashBuilder 4),那么你需要先创建一flex应用,我为它起了个名字叫“FlexAndJavascript".接下来你将看到下面最简单的应用:?
?
<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="462" height="328"><fx:Declarations><!-- 将非可视元素(例如服务、值对象)放在此处 --></fx:Declarations></s:Application>
?
?然后需要加入一个DataGrid用以显示人的信息,其中包括姓名、年龄和性别,如下布局:
?
<fx:Script><![CDATA[import flash.external.*;import mx.collections.ArrayCollection;public function initDG():void{var people:Array = new Array();people.push({Name: "Charlie", Age: "23", Sex: "Male"});people.push({Name: "Brandon", Age: "23", Sex: "Male"});people.push({Name: "Mike", Age: "23", Sex: "Male"});people.push({Name: "Caroline", Age: "23", Sex: "Female"});var peopleCollection:ArrayCollection = new ArrayCollection(people);dgPeople.dataProvider = peopleCollection;dgPeople.selectedIndex = 0;}]]></fx:Script><s:Panel id="pnlMain" x="0" y="0" width="462" height="328" title="Simple Javascript Interaction"><s:DataGrid id="dgPeople" x="10" y="10" width="422" height="229" initialize="initDG()"><s:columns><s:ArrayList><s:GridColumn dataField="Name" headerText="Name"></s:GridColumn><s:GridColumn dataField="Age" headerText="Age"></s:GridColumn><s:GridColumn dataField="Sex" headerText="Sex"></s:GridColumn></s:ArrayList></s:columns></s:DataGrid><s:Button id="butJSDisplay" x="10" y="256" label="JavaScript Display" click="jsDisplayPerson()"/><s:Label id="lblMessage" x="149" y="260"/></s:Panel>
?
? initialize="initDG()"方法是用来初始化DataGrid数据的,将会在DataGrid中显示出ArrayCollection中的数据。下面我要
实现的是,当我点击一个按钮式我要将Datagrid当前行的数据传到HTML中。好看代码:
?
public function jsDisplayPerson():void{if (ExternalInterface.available) {ExternalInterface.call("displayPerson", dgPeople.selectedItem); lblMessage.text = "Data Sent!";} elselblMessage.text = "Error sending data!";}
?在这里我们用了粗体显示的方法,这个方法就是用来通过调用JS中的方法displayPerson()将Flex中的数据传到HTML中。下面看JS中的displayPerson()方法:
?
function displayPerson(person){if(person == null){ alert("Please select a person, or maybe I screwed up.");}else{document.getElementById('nameDisplay').innerHTML = person.Name;document.getElementById('ageDisplay').innerHTML = person.Age;document.getElementById('sexDisplay').innerHTML = person.Sex;}}
?也许你将困惑nameDisplay之类是什么东西,贴出来你就明白了,这里是要让person的Name,Age和Sex传到text中显示出来:贴代码:
?
<table width="100%" style="border-spacing:5px;"> <tr> <td>Name:</td> <td id="nameDisplay" style="width:150px;"> </td> </tr> <tr> <td>Age:</td> <td id="ageDisplay" style="width:150px;"> </td> </tr> <tr> <td>Sex:</td> <td id="sexDisplay" style="width:150px;"> </td> </tr> </table>
?清晰了吗,好,接下来要做的就是要将swf文件嵌入到HTML中来搭成我们实验的环境。如何才能有效嵌入是个很大的问题,也是解决问题的关键,先看代码:
?
<div><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="newSWF" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="movie" value="FlexAndJavaScript.swf" /> <param name="wmode" value="transparent"> <param name="quality" value="high" /> <param name="bgcolor" value="ffffff" /> <param name="allowScriptAccess" value="always" /> <embed src="FlexAndJavaScript.swf" quality="high" bgcolor="ffffff" width="500" height="350" align="middle"name="newSWF" play="true" wmode="transparent" loop="false" quality="high" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"> </embed> </object> </div>
?这是一种嵌入的方式,粗体显示的是基本上必须要有的,而且命名属性值要搞的明白才行。<object>要有一个id,它要与<embed> 中的name相匹配。allowScriptAccess="sameDomain" 是用来处理不同域的情况。要注意的是SWF的路径要搞明白。
下面在说一下swf文件的问题,由于我们建立了flex工程,在bin—debug中生成的FlexAndJavaScript.swf是不能直接
拿来用的,需要先导出发行版的才可以拿来用——导出工程-发行版-生成bin-release,OK。
上面谈的是FLEX调用JS的方法,后面要说的时JS调用FLEX方法的情况,实现将HTML中提供的参数值传到FLEX的DataGrid中,不多说,看代码:
?
public function addPerson(name:String, age:String, sex:String):void{(dgPeople.dataProvider as ArrayCollection).addItem({Name: name, Age: age, Sex: sex});}public function initApp():void{if (ExternalInterface.available)ExternalInterface.addCallback("addPerson", addPerson); }
?addPerson是等着让JS调用的,在JS中调用后,传入参数,然后可以添加到DataGrid中。ExternalInterface.addCallback("addPerson", addPerson); 是一个非常重要的函数,他完成了一个比较艰巨的、
任务:完成注册功能,只有注册之后才能够顺利的Flex的函数进行调用,所以如此重要的方法现在Flex应用初始完成后就赶紧调用他吧,不调用就完蛋了,如下:
?
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="462" height="328" creationComplete="initApp();">
?flex端已经完成,在看HTML端是怎样的吧:
?
function getSWF(movieName){if (navigator.appName.indexOf("Microsoft") != -1){ return window[movieName] } else { return document[movieName] }}function addPerson(){var name = document.getElementById('txtName').value;var age = document.getElementById('txtAge').value;var sex = document.getElementById('selSex').value;getSWF('newSWF').addPerson(name, age, sex);}
?getSWF()方法的主要功能是对不同浏览器的支持,这个最好要,在addPerson()方法中完成了对Flex方法的调用——getSWF('newSWF').addPerson(name, age, sex);参数newSWF就是我们嵌入flash时定义的,就是在这里用的
?
<table style="border-spacing:5px;" width="100%"> <tr> <td style="border-style:none;padding:0px;">Name:</td> <td style="border-style:none;padding:0px;"><input id="txtName" type="text" /></td> </tr> <tr> <td style="border-style:none;padding:0px;">Age:</td> <td style="border-style:none;padding:0px;"><input id="txtAge" type="text" /></td> </tr> <tr> <td style="border-style:none;padding:0px;">Sex:</td> <td style="border-style:none;padding:0px;"><select id="selSex" style="width:100px;"><option value="Male">Male</option><option value="Female">Female</option></select></td> </tr> <tr> <td colspan="2" style="border-style:none;padding:0px;"><input type="button" id="butAddPerson" onclick="addPerson()" value="Add Person" /></td> </tr> </table>
输入, 点一下按钮,OK了,完成。补充一下,对于不允许JS的浏览器也有办法:
?
<noscript> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="462" height="328" id="FlexAndJavaScript"> <param name="src" value="FlexAndJavaScript.swf" /> <param name="movie" value="FlexAndJavaScript.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="allowScriptAccess" value="sameDomain" /> <param name="allowFullScreen" value="true" /> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="FlexAndJavaScript.swf" width="462" height="328"> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="allowScriptAccess" value="sameDomain" /> <param name="allowFullScreen" value="true" /> <!--<![endif]--> <!--[if gte IE 6]>--> <p> Either scripts and active content are not permitted to run or Adobe Flash Player version 10.2.0 or greater is not installed. </p> <!--<![endif]--> <a href="http://www.adobe.com/go/getflashplayer"> <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Flex与JavaScript的互相通信(真情贡献)" /> </a> <!--[if !IE]>--> </object> <!--<![endif]--> </object> </noscript>
?j加上就OK了。好完整的代码看一下:
FlexAndJava.mxml
?
<?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="462" height="328" creationComplete="initApp();"><fx:Declarations><!-- 将非可视元素(例如服务、值对象)放在此处 --></fx:Declarations><fx:Script><![CDATA[import flash.external.*;import mx.collections.ArrayCollection;public function initDG():void{var people:Array = new Array();people.push({Name: "Charlie", Age: "23", Sex: "Male"});people.push({Name: "Brandon", Age: "23", Sex: "Male"});people.push({Name: "Mike", Age: "23", Sex: "Male"});people.push({Name: "Caroline", Age: "23", Sex: "Female"});var peopleCollection:ArrayCollection = new ArrayCollection(people);dgPeople.dataProvider = peopleCollection;dgPeople.selectedIndex = 0;}public function addPerson(name:String, age:String, sex:String):void{(dgPeople.dataProvider as ArrayCollection).addItem({Name: name, Age: age, Sex: sex});}public function initApp():void{if (ExternalInterface.available)ExternalInterface.addCallback("addPerson", addPerson); }public function jsDisplayPerson():void{if (ExternalInterface.available) {ExternalInterface.call("displayPerson", dgPeople.selectedItem); lblMessage.text = "Data Sent!";} elselblMessage.text = "Error sending data!";}]]></fx:Script><s:Panel id="pnlMain" x="0" y="0" width="462" height="328" title="Simple Javascript Interaction"><s:DataGrid id="dgPeople" x="10" y="10" width="422" height="229" initialize="initDG()"><s:columns><s:ArrayList><s:GridColumn dataField="Name" headerText="Name"></s:GridColumn><s:GridColumn dataField="Age" headerText="Age"></s:GridColumn><s:GridColumn dataField="Sex" headerText="Sex"></s:GridColumn></s:ArrayList></s:columns></s:DataGrid><s:Button id="butJSDisplay" x="10" y="256" label="JavaScript Display" click="jsDisplayPerson()"/><s:Label id="lblMessage" x="149" y="260"/></s:Panel> </s:Application>
?FlexAndJava.html
?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" ><head><title>SWFObject 2 static publishing example page</title><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /></head><body> <center> <div><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="newSWF" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"> <param name="movie" value="FlexAndJavaScript.swf" /> <param name="wmode" value="transparent"> <param name="quality" value="high" /> <param name="bgcolor" value="ffffff" /> <param name="allowScriptAccess" value="always" /> <embed src="FlexAndJavaScript.swf" quality="high" bgcolor="ffffff" width="500" height="350" align="middle"name="newSWF" play="true" wmode="transparent" loop="false" quality="high" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"> </embed> </object> </div> <br> <br> <table style="border-spacing:5px;"> <tr> <td>Name:</td> <td id="nameDisplay" style="width:150px;"> </td> </tr> <tr> <td>Age:</td> <td id="ageDisplay" style="width:150px;"> </td> </tr> <tr> <td>Sex:</td> <td id="sexDisplay" style="width:150px;"> </td> </tr> </table> </td> </tr> <tr> <td> Data sending from Javascript </td> </tr> <tr> <td> <table style="border-spacing:5px;" width="100%"> <tr> <td style="border-style:none;padding:0px;">Name:</td> <td style="border-style:none;padding:0px;"><input id="txtName" type="text" /></td> </tr> <tr> <td style="border-style:none;padding:0px;">Age:</td> <td style="border-style:none;padding:0px;"><input id="txtAge" type="text" /></td> </tr> <tr> <td style="border-style:none;padding:0px;">Sex:</td> <td style="border-style:none;padding:0px;"><select id="selSex" style="width:100px;"><option value="Male">Male</option><option value="Female">Female</option></select></td> </tr> <tr> <td colspan="2" style="border-style:none;padding:0px;"><input type="button" id="butAddPerson" onclick="addPerson()" value="Add Person" /></td> </tr> </table> </td> </tr> </table> </center> <script>function getSWF(movieName){if (navigator.appName.indexOf("Microsoft") != -1){ return window[movieName] } else { return document[movieName] }}function addPerson(){var name = document.getElementById('txtName').value;var age = document.getElementById('txtAge').value;var sex = document.getElementById('selSex').value;getSWF('newSWF').addPerson(name, age, sex);}function displayPerson(person){if(person == null){ alert("Please select a person, or maybe I screwed up.");}else{document.getElementById('nameDisplay').innerHTML = person.Name;document.getElementById('ageDisplay').innerHTML = person.Age;document.getElementById('sexDisplay').innerHTML = person.Sex;}}</script><noscript> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="462" height="328" id="FlexAndJavaScript"> <param name="src" value="FlexAndJavaScript.swf" /> <param name="movie" value="FlexAndJavaScript.swf" /> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="allowScriptAccess" value="sameDomain" /> <param name="allowFullScreen" value="true" /> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="FlexAndJavaScript.swf" width="462" height="328"> <param name="quality" value="high" /> <param name="bgcolor" value="#ffffff" /> <param name="allowScriptAccess" value="sameDomain" /> <param name="allowFullScreen" value="true" /> <!--<![endif]--> <!--[if gte IE 6]>--> <p> Either scripts and active content are not permitted to run or Adobe Flash Player version 10.2.0 or greater is not installed. </p> <!--<![endif]--> <a href="http://www.adobe.com/go/getflashplayer"> <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Flex与JavaScript的互相通信(真情贡献)" /> </a> <!--[if !IE]>--> </object> <!--<![endif]--> </object> </noscript> </body></html>
?有完整下载奥~~