(转载)Flash8的ExternalInterface.addCallback
我很好奇这个函数是怎么和javascript交互的。经过仔细探索,我发现当在flash中第一次调用ExternalInterface.addCallback 的时候execScript了以下内容:addCallback(ExternalInterface.addCallback 方法)
public static addCallback(methodName:String, instance:Object, method:Function) : Boolean
将 ActionScript 方法注册为可从容器调用。成功调用
addCallBack()
后,容器中的 JavaScript 或 ActiveX 代码可以调用在 Flash Player 中注册的函数。可用性:ActionScript 1.0;Flash Player 8
参数
methodName
:String
- 从 JavaScript 调用 ActionScript 函数时可使用的名称。此名称不必与 ActionScript 方法的实际名称匹配。instance
:Object
-this
在该方法中被解析成的对象。此对象不一定是在其上可找到该方法的对象,您可以指定任何对象(或null
)。method
:Function
- 要从 JavaScript 调用的 ActionScript 方法。返回
true
- 如果调用成功,则返回Boolean
。如果调用由于下列原因而失败,则返回false
:实例不可用、遇到了安全限制、没有这种函数对象、发生了递归或类似情况。返回值为
false
还可能表示包含环境属于调用代码无权访问的安全沙箱。您可以在包含环境的 HTML 中为allowScriptAccess
OBJECT
标签或EMBED
标签设置一个合适的值,以解决此问题。示例
下面的示例将
goToMacromedia()
函数注册为可使用名称goHome
从容器调用。import flash.external.*;var methodName:String = "goHome";var instance:Object = null;var method:Function = goToMacromedia;var wasSuccessful:Boolean = ExternalInterface.addCallback(methodName, instance, method);var txtField:TextField = this.createTextField("txtField", this.getNextHighestDepth(), 0, 0, 200, 50);txtField.border = true;txtField.text = wasSuccessful.toString();function goToMacromedia() { txtField.text = "http://www.macromedia.com"; getURL("http://www.macromedia.com", "_self");}为了使上一示例能够正常运行,应复制以下代码并将其粘贴到包含 HTML 页中。此代码依赖
OBJECT
标签的id
属性和EMBED
标签的name
属性以获得值externalInterfaceExample
。由于 Internet Explorer 和 Netscape 以不同方式引用 movie 对象,所以函数thisMovie
根据浏览器返回相应的语法。除非服务器上承载 HTML 页,否则您的浏览器可能会出现安全警告。注意:请避免使用访问插件对象的其它方法(如
document.getElementById("pluginName")
或document.all.pluginName
),因为这些其它方法在所有浏览器上的运行不一致。<form> <input type="button" onclick="callExternalInterface()" value="Call ExternalInterface" /></form><script>function callExternalInterface() { thisMovie("externalInterfaceExample").goHome();}function thisMovie(movieName) { if (navigator.appName.indexOf("Microsoft") != -1) { return window[movieName] } else { return document[movieName] }}</script>
function __flash__arrayToXML(obj) {而每次调用ExternalInterface.addCallback 的时候都会运行js的__flash__addCallback。这里要注意,instance参数就是网页上的插件,对于IE来说,是一个实现了IDispatch的ActiveX控件,这个控件有一个方法,即CallFunction,该方法就可以调用flash中的函数了。
var s = "<array>";
for (var i=0; i<obj.length; i++) {
s += "<property id=\"" + i + "\">" + __flash__toXML(obj[i]) + "</property>";
}
return s+"</array>";
}
function __flash__argumentsToXML(obj,index) {
var s = "<arguments>";
for (var i=index; i<obj.length; i++) {
s += __flash__toXML(obj[i]);
}
return s+"</arguments>";
}
function __flash__objectToXML(obj) {
var s = "<object>";
for (var prop in obj) {
s += "<property id=\"" + prop + "\">" + __flash__toXML(obj[prop]) + "</property>";
}
return s+"</object>";
}
function __flash__escapeXML(s) {
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
}
function __flash__toXML(value) {
var type = typeof(value);
if (type == "string") {
return "<string>" + __flash__escapeXML(value) + "</string>";
} else if (type == "undefined") {
return "<undefined/>";
} else if (type == "number") {
return "<number>" + value + "</number>";
} else if (value == null) {
return "<null/>";
} else if (type == "boolean") {
return value ? "<true/>" : "<false/>";
} else if (value instanceof Date) {
return "<date>" + value.getTime() + "</date>";
} else if (value instanceof Array) {
return __flash__arrayToXML(value);
} else if (type == "object") {
return __flash__objectToXML(value);
} else {
return "<null/>"; //???
}
}
function __flash__addCallback(instance, name) {
instance[name] = function () {
return eval(instance.CallFunction("<invoke name=\""+name+"\" returntype=\"javascript\">" + __flash__argumentsToXML(arguments,0) + "</invoke>"));
}
}
function __flash__removeCallback(instance, name) {
instance[name] = null;
}