Adobe ExternalInterface在IE9中无法工作

3

我正在从JavaScript调用Actionscript函数,它在除IE9以外的所有浏览器中都有效。我将其缩小到检索电影对象的js函数:

<script type="text/javascript"> 
var swf;
... 

function flashReady() // This is called from ActionScript
{
    swf = getSWF("MyMovie");
    swf.MyExternalFunction(); 
}

function getSWF(movieName) 
{ 
    if (navigator.appName.indexOf("Microsoft") != -1) 
    { 
        return window[movieName]; 
    } 
    else 
    { 
        return document[movieName]; 
    } 
} 
... 
</script>

这里是我的HTML代码:
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="1" height="1" id="MyMovie">
    <param name="allowScriptAccess" value="always" />
    <param name="movie" value="/swf/movie.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffcc00" />
    <embed src="/swf/movie.swf" quality="high" bgcolor="#ffcc00" width="1" height="1" name="MyMovie" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object>

当我像这样调用外部函数:

swf.MyExternalFunction(); 

在IE9中,我遇到了一个JS错误:
"Object doesn't support property or method 'MyExternalFunction'" 

显然,适用于IE的window[movieName]在IE9中不再像以前那样起作用。有什么建议吗?

:::更新:::

这是我目前的解决方案。它可能看起来不太好看,但它可以工作:

var movie = false;

function initSWF(movieName) {
    if (navigator.appName.indexOf("Microsoft") != -1) {
        //alert("IE");
        if (typeof (window[movieName].MyExternalFunction) == 'function') {
            // alert("< IE9");
            movie = window[movieName];
        }
        else if (typeof (document[movieName].MyExternalFunction) == 'function') {
            // alert(">= IE9");
            movie = document[movieName];
        }
    }
    else {
        // alert("NON IE");
        movie = document[movieName];
    }

    return ((movie) ? true : false);
}

然后它的使用方式如下:

function flashReady() // This is called from ActionScript
{
    if(initSwf("MyMovie")) {
        movie.MyExternalFunction();
    } else {
        alert("Failed to initialize");
    }
}

可能与此无关,但您应该使用<script type="text/javascript">而不是<script language="JavaScript"> - shanethehat
是的,谢谢,我实际上使用了type="text/javascript",但这不应该有影响。 - OctoRazor
你什么时候调用外部函数?当你调用它时,你的Flash对象可能还没有加载。此外,现在已经不是1990年了,document.getElementById在所有浏览器上都可以使用,不要使用window[movieName]document[movieName] - HoLyVieR
我有一个flashReady()JS函数,它在swf加载完成后被调用。它试图通过从getSWF()获取正确的对象来进行初始化。据我所知,window [movieName] 获取<object>标记,而document [movieName] 获取<embed>标记。您建议使用getElementById适用于哪个浏览器? - OctoRazor
1
@OctoRazor 所有的,window[movieName] 是 IE 的一个旧特性,用于通过 ID 获取元素。document.getElementById 现在是访问元素 ID 的标准方式。它适用于所有浏览器,除非你正在处理超过 14 年的浏览器(例如:IE4)。 - HoLyVieR
@HoLyVieR 使用window[name]/document[name]的整个想法是在IE中获取<object>标签,在非IE中获取<embed>标签(顺便说一下,是按名称而不是按ID)。 Adobe AS3手册建议使用它,因此它不是14年前的东西。 http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7cb1zephyr_serranozephyr.html 如果我给我的对象和嵌入标记相同的ID,它只会选择在DOM中找到的第一个标记。 即使我使用jQuery..像$("#MyMovie > object")或$("#MyMovie > embed")这样的东西,我也会得到与getElementById相同的错误:TypeError:MyExternalFunction不是函数 - OctoRazor
2个回答

0
我一直遇到类似的问题,只是在IE9中可以工作而在IE7/8中不行。我相信我们两个问题的原因是相同的。我通过偶然发现A List: Apart上的这篇精彩文章解决了这个问题http://www.alistapart.com/articles/flashsatay/
按照这篇文章,你正确格式化的HTML应该是:
<object type="application/x-shockwave-flash" data="/swf/movie.swf" width="1" height="1" id="MyMovie">
    <param name="allowScriptAccess" value="always" />
    <param name="movie" value="/swf/movie.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#ffcc00" />
</object>

特别注意,我添加了一个 type 并移除了 <embed> 标签。
据我所见,现在不再需要使用 <embed> 标签了。而移除它意味着我们可以使用更简单的代码来触发我们的 ExternalInterface 函数:
// After the flash object has loaded...
var movie = document.getElementById('MyMovie');
if (typeof movie.MyExternalFunction === 'function') movie.MyExternalFunction();

希望这能有所帮助。


0

我曾经遇到过IE9完全相同的问题,对我来说,它是IE9缓存Flash的情况。请尝试清除浏览器缓存(按F12打开开发者工具,然后有一个清除缓存的图标或Ctrl-R),然后再试一次。

如果这样做不起作用,请尝试延迟您的JavaScript调用ActionScript 1或2秒钟,类似于以下内容:

<SCRIPT LANGUAGE='Javascript'>

function delayForFlash() {
setTimeout("startFlash()", 1000);
}

function startFlash() {
getFlashMovie("flashdemo").restartFlash();
}

window.onload = function(){ delayForFlash();}
</SCRIPT>

这是为了给您的闪存足够的时间来加载所有内容。


谢谢您的建议,但这不是我要找的。我知道电影何时准备好了,因为我从电影本身触发JS初始化过程。无论如何,出于好奇,我尝试添加了延迟,但它没有起作用。 - OctoRazor
所以你的代码工作方式是这样的:ActionScript调用Javascript,然后Javascript将一些信息传递回来给Actionscript?我曾经这样做,但后来我改为等待Flash加载,而JavaScript首先联系ActionScript,因为某些IE9缓存问题。您是否在本地运行时遇到此问题,还是在服务器上运行? - Stefan
问题在服务器和本地都存在。即使等几分钟,该函数也无法被调用(我知道,很傻)。您可以使用开发工具控制台来测试这一点。我已经发布了一个新的解决方案来回答我的问题。它有点不正规,并且依赖于特定的 AS 函数以供 JS 验证其可用性。 - OctoRazor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接