JS 与 AS交互的一些事情
说来话长了,记得2002年的第一场雪。余下省略5000字...
说归说,笑归笑,咱们言归正传啊。关于JS于AS交互的文章网上也是一搜罗一大把的。在这呢,我就是想写一点我遇到的问题。哎呀,可折腾了我不少时间啊。 近日由于工作需求 ,需要和一名AS同事负责进行交互,网上也瞅了瞅,看了些文章,觉得好弄。挺简单的。然后卷起袖子准备大干一场!不巧就遇上了绊子。
1.(Flash 文件访问跨域)
首先的请求跨域的问题。如果flash文件要请求一段地址的话。会先请求其服务器根目录下是否存在 crossdomain.xml 文件,然后对其XML格式内容进行解析。如果确实对你的请求授予权限了。那就OK,结果就理所当然响应给你。不然就整个XML 跨域文件放到服务器根目录下就行。flash在跨域时唯一的限制策略就是crossdomain.xml文件,该文件限制了flash是否可以跨域读写数据以及允许从什么地方跨域读写数据。若不存在主策略文件,则该域将禁止任何第三方域的flash跨域请求。一般格式如下:
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
domain:该属性指定一个确切的 IP 地址、一个确切的域或一个通配符域(任何域)。只有domain中指定的域,才有权限通过flash读取本域中的内容。
一般情况下还是设置比较信任的域才能访问自身服务器,如果写成通配符"*"的话,是极不安全的。
2.(Javascript 脚本限制)
没什么说的,如果该属性不写的话,会提示安全沙箱的错误。意指执行JS脚本受限,未授予访问权限。
在 <object> 标签之内添加:<param value="always" name="allowScriptAccess">还没完,接着还要在 <embed> 标签写上 allowScriptAccess="always" 为了兼容IE和其他W3C标准浏览器。 基本上JS脚本受限制的问题就解决了。。
3.(关于 ActionScript 脚本执行 Externalinterface.addCallback() 的时机)
有时候,大家可能会遇到当在HTML页面中插入一段FLASH文件,然后进行JS交互时,会有AS函数调取不到('xxx' not is a function)的问题存在。如果当页面DOM数量少,且请求文件少和带宽占用少的页面进行交互,大概不会出现这种问题。一般情况下 addCallback 执行的最好时机就是当页面完全加载好时,onload complete(注意:这里的加载完成不是指DOM树构造完毕,而是说页面中所有请求的资源:图片、flash等等的加载完毕).再用AS去执行 addCallback 注册的函数,就不会发生这种 AS 函数不存在的问题了。至于怎么去判定和准时注册AS函数,我觉得是可以这么去做。
首先JS代码如下:
var jsReady = false; window.onload = function(){ jsReady = true; } function pageIsReady() { return jsReady; }
然后ActionScript那边生成一个定时器,隔上500ms 或 1000ms 执行一次该函数。(时间长短可由个人需要指定),如果返回值为真,说明页面已经加载完毕了。此时将需要注册的函数Externalinterface.addCallback() 一并写入,并解除定时器,就行了!一般情况下来说,解决AS调取不到的问题是可以了。
4.(关于ActionScipt 调用JS函数一个比较容易忽略的问题)
有时大家可能有将 FLASH文件 嵌入在一个 iframe 子框架中,但是这个flash文件又需要调用到外部的JS函数。可能就直接 call(FuncName) 的调用了。结果出错。JS函数未找到、未定义。
很苦恼,很费解,很压抑,觉得生活不能自理了。呵呵,我的想法就是。在FLASH文件嵌入的当前 窗体对象中。写入一段javascript代码。也可以是动态创建添加都行。不过我这边IE浏览器好像有点问题,通过如下形式:
var scriptEl = document.createElement('script'); scriptEl.type = 'text/javascript'; scriptEl.innerHTML = 'function mutualCallback( f ) { typeof window.top[f] === 'function' && window.top[f](); }'; (iframe.contentWindow.document || iframe.contentDocument).getElementsByTagName('head')[0].appendChild(scriptEl);
没有成功,会报错。。很是郁闷。然后无奈之下将该代码放入外部文件引入才罢休。
好了,就如以上形式就可以实现AS 调用 JS 不在一个frame框架环境的问题了。当然每个人有每个人的需求。再作相应修改和处理便是。
5.(最后一个也就是 JS调用AS函数)
关于JS调用AS,网上罗列了不少方法,形形色色大同小异。
首先 将<object>标签的ID属性和<embed>标签的NAME属性 设为一样即可。chrome, ff, ie ... 获取形式各异。
IE 是通过 Active控件 来加载flash, 且仅仅支持<object>标签,<embed>标签留与不留没有影响的。
其它标准浏览器就是 通过 <embed> 标签来解析flash了。
具体获取方法:
function getFlashObject( id ) { if (navigator.appName.indexOf("Microsoft Internet") == -1) { if (document.embeds && document.embeds[id]){ if(navigator.userAgent.indexOf("Firefox")>0){ return document.embeds[id]; }else{ return window[id]; } } else{ return window.document[id]; } } else { return window[id]; } }
然后将object的id 或者 embed的name,传进来即可。然后就返回的标签对象 比如:getFlashObject('flashObj')['callAS']();即可。callAS 是AS那边注册的函数名称!
这里需要注意一个问题就是。IE 浏览器当中,如果你添加了很多个 FLASH 对象,且ID值一样,方法会出现在第一个对象身上。比如页面中有10个flash对象。ID="myflash"然后每个flash对象 有不同的
Externalinterface.addCallback() 注册的函数,这时候调用 getFlashObject('myflash'),会返回10个Object元素。那么你想遍历该DOM集合,然后依次调用该flash对象注册的函数。那么结果会
让你百思不得其解的。。只有第一个object元素 能获取到注册的函数,往后的都是空。然后还有一种情况:
页面中有10个flash对象,然后只有一个flash有注册函数。但是问题是10个flash是无序且打乱的插入在你的页面当中的。你并不能具体指定到哪个flash对象,然后只能将10个都给获取。然后通过
判断检查元素是否有某个注册函数,如果有就调用。那么结果也是不一样的。比如现在是第5个flash对象是有注册函数的:名称是 callAS. 然后你通过window[id]获取到当前所有的 flash 集合。
并检测属性是否为函数,那么会返回第一个元素也就是 window[id][0] 有['callAS'] 属性且类型为函数。 但调用时出错。因为该flash并没有该注册的函数。所以肯定失败。 由此看来。在IE当中。
若想JS 调用 AS函数成功,还是要指名道姓,指定一个元素然后来调用注册函数。
本文属于原创,希望各位多批评指正!
- 羽翼飞扬