近期正在做有关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!";
} else
lblMessage.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" οnclick="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="Get Adobe Flash Player" />
</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!"; } else lblMessage.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 class="sample">
<tr>
<td>
Data coming into Javascript
</td>
</tr>
<tr>
<td>
<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>
</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" οnclick="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="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</noscript>
</body>
</html>
有完整下载奥~~