AS3中的JS函数调用与参数中的复杂对象

时间:2011-10-17 22:12:43

标签: javascript actionscript-3 flex air jwplayer

我正在构建一个AIR桌面应用程序。有一次,应用程序加载了一个弹出窗口(基于s:Window的MXML组件),其中包含一个mx:HTML组件,用于加载本地(在应用程序目录中)html文件, blank.html blank.html 中的相关元素是:

<script src="jw/jwplayer.js"/> <!--JW Player's JS-based Embedder-->
...
<div id="jwtarget" /> <!-- the target that the embedder will use -->

由于我想要使用的参数是在运行时确定的,因此我使用domWindow属性来调用加载播放器的方法。这是一个有效的例子:

private function injectPlayer():void {
  var playerVars:Object = {};
  playerVars.flashplayer = "jw/player.swf";
  playerVars.file = "http://www.archive.org/download/meet_john_doe_ipod/meet_john_doe_512kb.mp4";
  playerVars.height = 360;
  playerVars.width = 640;

  try { // attempt to invoke the js function
    htmlComponent.domWindow.jwplayer("jwtarget").setup(playerVars);
  } catch(e:Error) {}

}

在页面完成加载时调用:

<mx:HTML id="htmlComponent" location="assets/blank.html" complete="injectPlayer()" />

一切正常。

现在回答这个问题。我需要能够将更复杂的playerVars对象传递给函数,但我似乎没有得到正确的语法。这是我一直在尝试的最简单的例子:

private function injectPlayer():void {
  var playerVars:Object = {};
  //playerVars.flashplayer = "jw/player.swf";
  playerVars.file = "http://www.archive.org/download/meet_john_doe_ipod/meet_john_doe_512kb.mp4";
  playerVars.height = 360;
  playerVars.width = 640;
  playerVars.modes = [{"type":"flash","src":"jw/player.swf"}];

  try { // attempt to invoke the js function
    htmlComponent.domWindow.jwplayer("jwtarget").setup(playerVars);
  } catch(e:Error) {}

}

此代码应创建与上述代码完全相同的内容,但无法执行。我假设我需要以某种方式更改语法,以允许对象数组(modes)作为参数正确传递给js函数。

我尝试过各种各样的事情,例如将modes作为字符串传递,或者将整个事情放在JSON.stringify()之前,但无济于事。任何人都知道为参数构造复杂对象的正确方法吗?

其他详细信息,如果您现在还没有推断出它们:Flex 4.5.1是我正在构建的SDK,包括AIR 3.0扩展(这意味着定位到FP11)。

更新

我尝试过的其他配置,它确实有效:

playerVars.modes = {"type":"flash", "src":"jw/player.swf"};

但是,这仍然无法解决我应该能够在modes属性中传递对象数组的问题。但至少这种方式会加载视频播放器。

更新更新:

所以,我从 jwplayer.js 中找到了这段代码,我怀疑播放器加载失败了:

if (typeof parsedConfig.modes == "string") {
  _modes = _playerDefaults();
  _modes[0].src = parsedConfig.modes;
} else if (parsedConfig.modes instanceof Array) {  // I suspect this was eval'd as false
  _modes = parsedConfig.modes;
} else if (typeof parsedConfig.modes == "object" && parsedConfig.modes.type) {
  _modes = [parsedConfig.modes];
}

为了测试我的怀疑,我在 blank.html 中添加了以下功能:

<script type="text/javascript">
  var instanceOfArrayTest = function(arr) {
    return arr instanceof Array;
  }
</script>

在我的ActionScript代码中尝试了以下内容:

trace([1,2,3] is Array); // true
trace(htmlComponent.domWindow.instanceOfArrayTest([1,2,3])); // false!!!!

所以,似乎问题是ActionScript没有将AS3 Array对象作为JS Array对象传递!

2 个答案:

答案 0 :(得分:2)

尝试这样做:

playerVars.modes = [{type:"flash",src:"jw/player.swf"}];

答案 1 :(得分:1)

call()类的ExternalInterface方法不同,当mx:HTML作为参数传递给JS函数时,它不会自动将AS3类转换为相应的JS类。相反,HTML Control维护了一个环境,其中保留了AS3类本机的方法和属性,并使JS可以直接访问它们。

如果JS函数需要JS Array对象,则必须使用JavaScript Window对象显式创建JS Array以访问JS Array构造函数。 HTML控件使用它的domWindow属性提供对此的访问。否则,无法将AS3阵列“转换”为JS阵列。

这是一个基本的例子:

var JSArray:Function = htmlComponent.domWindow.Array;
htmlComponent.domWindow.instanceOfArrayTest( JSArray(1,2,3) ); // true

对于使用JW Player的config参数的更复杂的例子:

playerVars.modes = JSArray({"type":"flash","src":"jw/player.swf"},{"type":"html5"});

创建一个包含两个对象的JS数组。

有关HTML控件中JavaScript环境的更多信息,请查看Adobe的使用Flex开发AIR应用程序JavaScript in AIR部分。