一.JavaScript調用ActionScript公開的方法

在Flex中通過ExternalInterface調用addCallback()來將AS的一個方法註冊為一個JS和VBScript可以調用的方法。
函數如下:
addCallback(function_name:String, closure:Function):void
function_name就是Flex對外部展示,能夠被JS調用的函數。
closure是Flex中AS寫的函數

as:

<?xml version="1.0" encoding="utf-8"?>    
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"          
     creationComplete="initApp()">    
     <mx:Script>    
         <![CDATA[    
 
             import flash.external.*;                   //引入ExternalInterface 
             public function myAsFuncn(js:String):String    
             {    
                 return  "js:"+js+"訪問了 as:"+asInput.text;    
             }    
 
             public function initApp(): void{
				   ExternalInterface.addCallback("myAsFuncn",myAsFuncn);    
	    }
 
         ]]>    
     </mx:Script>  
     <mx:TextInput  id="asInput"/>             
</mx:Application>

js:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="UTF-8" />
 
 
    <head>  
 
		<script src="swfobject.js" type="text/javascript"></script>
		<script src="jquery.js" type="text/javascript"></script>
 
        <script  type="text/javascript" >     
 
			//var swf = new swfobject("FlexDemo003.swf", "myFlexFun", "300px", "200px", "9.0.0","expressInstall.swf", flashvars,params);
			//swf.write("myFlexFun");
			var flashvars = {};
			var params = {menu: "false",wmode:"opaque"};
			swfobject.embedSWF("FlexDemo003.swf", "myFlexFun", "300px", "200px", "9.0.0","expressInstall.swf", flashvars,params);
 
 
             function callAs()    
             {    
                var myFlexfun = findSWF("myFlexFun");    
                var result = myFlexfun.myAsFuncn("點我看效果按鈕");    
                alert(result);    
             }  
 
			 function findSWF(movieName) {   
				   if (navigator.appName.indexOf("Microsoft")!= -1) {   
					   return window[movieName];   
				   } else {   
					   return document[movieName];   
				   }
			  }
 
       </script>  
   </head>  
 
 
   <body>  
 
	<div id="myFlexFun"></div>
        <input type="button" value=" 點我看效果" onclick="callAs()" />
 
  </body>  
</html>

二.ActionScript調用JavaScript方法

call(ExternalInterface.call 方法)
public static call(methodName:String, [parameter1:Object]) : Object
參數
methodName:String ― 要在容器中調用的函數的名稱。如果該函數接受參數,則這些參數必須顯示在 methodName 參數後面。
parameter1:Object [可選] ― 要傳遞到該函數的任何參數。您可以指定零個或多個參數,參數之間用逗號分隔。此參數可以是任何 ActionScript 數據類型。當調用 JavaScript 函數時,ActionScript 類型自動封裝到 JavaScript 類型中。當調用某個其它 ActiveX 容器時,將在請求消息中對參數進行編碼。
返回
Object ― 從容器接收的響應。如果調用失敗(例如,當容器中沒有這種函數時、接口不可用時、發生遞歸時,或出現安全問題時),則返回 null。

js:

<html>  
    <head>  
        <script language="JavaScript" type="text/javascript">  
         //無參數 
        function myJsFunctionNoPara() {  
             alert("as 調用 js了");  
        }  
        //有參數 
         function myJsFunctionHavePara(p) {  
            alert(p);  
        }  
      </script>  
  </head>  
   <body>  
       <object id="myFlexFun" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"  
           width="250" height="300">  
           <param name="movie" value="AS2JS.swf" />  
           <param name="quality" value="high" />  
           <embed src="AS2JS.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer"  
               type="application/x-shockwave-flash" width="250" height="300"></embed>  
       </object>  
  </body>  
   </html>

as:

<?xml version="1.0" encoding="utf-8"?>    
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">    
       <mx:Script>    
            <![CDATA[    
 
                private function callNoParaJavaScript():void {  
                    ExternalInterface.call("myJsFunctionNoPara");  
                    }   
                private function callHaveParaJavaScript():void {  
                   ExternalInterface.call("myJsFunctionHavePara","as 調用js了");  
                    }   
 
           ]]>    
       </mx:Script>  
       <mx:Button label=" 調用無參數js:Say 'as 調用js了'"  click="callNoParaJavaScript();" />   
       <mx:Button label="調用有參數js:Say 'as 調用js了'"  click="callHaveParaJavaScript();" />        
   </mx:Application>

3.調用內置js函數

ExternalInterface.call("alert", "Hello World, from ActionScript");  
    ExternalInterface.call("eval", "alert('OK')");

三.常見問題

1.ExternalInterface.addCallback參數

JavaScript 跟 ActionScript 3.0 交互也是通過 flash.external.ExternalInterface 這個類,不過與跟 Flash 8 中跟 ActionScript 2.0 交互所使用的 flash.external.ExternalInterface 還是有所不同的。最大的不同就是 ExternalInterface.addCallback 方法在 ActionScript 3.0 中只有 2 個參數了,而不再有 instance 這個參數。

2.avaScript 調用 Flash 中的 ActionScript3.0提示方法不存在

這個問題是跟 Flash 中執行 ExternalInterface.addCallback 的時間有關的,ExternalInterface.addCallback 必須要在 HTML 的完全載入之後也就是 window.onload 事件執行後才可以執行,否則,它所發佈的方法都無法在 JavaScript 中調用。

解決方法:在 Flash 9 的 ActionScript 3.0 幫助中有個例子,裏面包含了這個解決方法,就是首先在 js 中設置兩個標誌,例如 jsReady 和 swfReady 這兩個變量作為標誌,開始都設置為 false,當 window.onload 時,設置 jsReady 為 true,在 Flash 中一開始檢查 JavaScript 中的這個 jsReady 標誌是否是 true(通過 ExternalInterface.call 方法調用 JavaScript 中的返回這個標誌的一個函數),如果不為 true,就設置一個定時器,經過一段時間後(例如 50 或 100 毫秒)重複這個檢查這個標誌,一旦為 true,則執行 ExternalInterface.addCallback 來發布 ActionScript 要提供給 JavaScript 調用的函數或方法,執行完所有的 ExternalInterface.addCallback 後,通過 ExternalInterface.call 方法調用 JavaScript 中的設置 swfReady 標誌的函數設置 swfReady 為 true。之後,當 JavaScript 檢測到 swfReady 為 true 後,再調用 ActionScript 中的方法就不會遇到上的説的這個問題了。

如果簡單一點的調用這樣還可以,如果是有好多這樣的調用就比較麻煩了。我是通過建立兩個執行隊列:jsTaskQueue 和 swfTaskQueue,當在 jsReady 為 true 之前,如果有要調用 ActionScript 的操作,就把這個操作放到 jsTaskQueue 中,當 js 在 window.onload 中執行設置 jsReady 時,把這個隊列中的任務取出來執行,當 jsReady 為 true 後 swfReady 為 true 之前,如果有要調用 ActionScript 的操作,就把這個操作放到 swfTaskQueue 中,當 ActionScript 通過 ExternalInterface.call 方法調用 JavaScript 中的設置 swfReady 標誌的函數設置 swfReady 為 true 時,把這個隊列中的任務取出來執行。當 jsReady 和 swfReady 都為 true 時,那麼如果有要調用 ActionScript 的操作,直接運行就可以了。通過這種方法把這些任務封裝後,使用這些封裝之後的操作,在編寫代碼就可以按照順序(而不是異步)來寫了,執行時也是順序執行啦。

3. 在IE中用JavaScript 動態創建的 Flash 標籤的問題

如果你是通過 JavaScript 動態創建的 Flash 標籤然後插入到 html 中的話(例如通過 innerHTML 賦值的方法或者 appendChild 的方法),很可能你這個操作是在 window.onload 之後才進行,在這種情況下,其它瀏覽器可以正常進行 JavaScript 和 ActionScript 3.0 的交互,IE 就不行。所以,為了保險,最好的方法就是直接把 flash 標籤的 html 寫在 html 的 body 中,或者用 JavaScript 的 document.write 來寫入 html 的 body 中,後面這種方法對於 IE 來説更合適一些,因為這樣的話,可以不需要點擊激活 Flash。

4. 在IE中 as發佈方法名問題

不要在 ActionScript 3.0中發佈名字為 invoke 的方法,否則在 IE 中,JavaScript 調用該方法時會出錯。

5.在ie中flash在form的位置

不要把 flash 放到 form 中,否則在 IE 中,JavaScript 調用 ActionScript 時會出錯。當然,網上也給出了一個解決這個問題的腳本,不過那個貌似是針對 Flash 8 的 ActionScript 2.0 的,我沒有試過,不知道對

ActionScript 3.0 是否同樣有效。

6.方法參數包含轉移符號的問題

如果在 ActionScript 中通過 ExternalInterface.call 調用 JavaScript 時,參數中如果含有轉義字符(\)和特殊字符(\n,\r等)就可能出錯。因為在ActionScript和JavaScript中都將“\”作為轉義字符,這裏的”\\”在程序執行時實際上就是一個[\].

解決辦法1:如要傳遞的數據是 data,將它進行一次 data.replace(/\\/, “\\\\”) 替換之後,在傳遞給 JavaScript 就可以了。

解決辦法2:js和as中有現成的兩個全局函數:escape()和unescape()。在調用函數和函數返回前escape一下,接收到參數和函數返回值後再unescape一下就可以了。

as:

var str:String = "\n\r123\\abc";    
   str = escape(str); // encode 
   var jsret:Object = ExternalInterface.call("jsfun", str);  
 
    if (jsret is String) {  
 
       jsret = unescape(jsret as String); // decode 
 
      Alert.show(jsret.toString());  
 
   }

js:

function jsfun(str) {    
       str = unescape(str); // decode 
       str += "from js";  
       str = escape(str); // encode 
       return str;  
   }