HTML内容加载到HTMLLoader中,无论是通过mx:HTML控件或通过创建一个HTMLLoader,都已完成与JavaScript和ActionScript环境之间的双向访问。 JavaScript可以用调用ActionScript方法,创建ActionScript对象,甚至在ActionScript处理程序中触发事件。相反,ActionScript可以用调入JavaScript方法,处理未处理的JavaScript异常,处理HTML DOM,使用JavaScript端点触发ActionScript事件。有不少方法可以做到这一点,而我们只在这里介绍基础知识。
39.4.1 从ActionScript调用嵌入式JavaScript
embeddedPlayer.html页面上嵌入的YouTube Chromeless Player具有几个JavaScript函数,用于控制视频播放器的播放、暂停、静音等(请参见程序清单39-1)。任何公开定义的JavaScript函数将可用于从ActionScript中调用。
我们将定义我们自己的UI,列出用于在MXML中播放的潜在视频。当用户按下在MXML List中定义的屏幕元素后,ActionScript将调用JavaScript的loadNewVideo()函数,这将使嵌入的YouTube播放器开始播放视频。这同样适用于自定义按钮,自定义按钮控制何时可以播放、暂停或停止视频。甚至在Flex完全确定时,通过调入JavaScript API,就可控制音量滑块。
程序清单39-1 ActionScript中可用的JavaScript函数的部分清单
function loadNewVideo(id, startSeconds) {
if (ytplayer) {
ytplayer.loadVideoById(id, parseInt(startSeconds));
}
}
function play() {
if (ytplayer) {
ytplayer.playVideo();
}
}
function pause() {
if (ytplayer) {
ytplayer.pauseVideo();
}
}
function stop() {
if (ytplayer) {
ytplayer.stopVideo();
}
}
function mute() {
if (ytplayer) {
ytplayer.mute();
}
}
function unMute() {
if (ytplayer) {
ytplayer.unMute();
}
}
function setVolume(newVolume) {
if (ytplayer) {
ytplayer.setVolume(newVolume);
}
}
function getVolume() {
if (ytplayer) {
return ytplayer.getVolume();
}
}
为了使AIR调用JavaScript代码,必须等待HTML内容被加载(通过HTMLLoader),然后使用htmlLoader的引用调用该方法。
下面的ActionScript代码演示了调用JavaScript的loadNewVideo()方法:
public function loadVideoAndPlay(videoId:String):void
{
youTubeEmbeddedPlayer.domWindow.loadNewVideo(videoId ,0);
}
该youTubeEmbeddedPlayer就是上面定义的mx:HTML组件,其中加载了embeddedPlayer.html。访问的domWindow是包含在此mx:HTML的实例中的HTML DOM的根。程序清单39-1中列出的所有公有的JavaScript函数可从domWindow属性访问,这和调用视频的播放、停止和静音函数看起来很相似。
从ActionScript代码调用JavaScript函数就是这么简单。Chapter_39_Demo.mxml文件中的代码显示了从ActionScript方法执行JavaScript代码的相似过程。
39.4.2 从JavaScript调用ActionScript
从JavaScript访问ActionScript代码几乎一样简单。但是,需要创建对主ActionScript代码的引用,这样JavaScript就可以访问它。这通过在引用实际AIR应用程序的JavaScript上下文中动态地创建一个变量来完成。HTML内容就加载完毕后这就完成。
记住,mx:HTML组件的定义有一个complete事件处理程序:
<html:HTMLLoader id="youTubeEmbeddedPlayer" width="600" height="400"
complete="onHtmlLoadComplete(event)"
/>
当HTML内容加载完毕后,就会执行整个处理程序,调入onHtmlLoadComplete()处理程序,它负责在JavaScript上下文中对AIR应用程序的引用进行设置:
private function onHtmlLoadComplete(event:Event):void
{
trace("onHtmlLoadComplete");
youTubeEmbeddedPlayer.domWindow.airAppRef = this;
}
同样,使用domWindow,创建airAppRef变量,它通过该AIR应用程序的一个引用动态地添加到JavaScript上下文中。AIR和JavaScript之间的桥接就这么简单。
现在,从使用embededPlayer.html加载的JavaScript中调用一些ActionScript方法。当一个新的视频加载到嵌入式YouTube播放器中时,使许多度量指标可用:视频的长度、大小(单位为字节),以及加载的字节数等。我们的目标是将此数据传递回ActionScript上下文,以便AIR应用程序可以显示数据。
当加载嵌入式JavaScript时,它设置时间间隔(即每250毫秒,或约4次/秒)来调用updateytplayerInfo()。然后这个函数通过airAppRef调用适当的AIR ActionScript,该airAppRef是在AIR应用程序中成功加载HTML内容后创建的:
function updateytplayerInfo() {
airAppRef.setBytesLoaded( getBytesLoaded());
airAppRef.setBytesTotal( getBytesTotal());
airAppRef.setLengthOfVideo( getDuration());
airAppRef.setCurrentTime( getCurrentTime());
airAppRef.setStartBytes( getStartBytes());
airAppRef.setVolume( getVolume());
}
此JavaScript函数依赖于许多辅助函数(getBytesLoaded()、getBytesTotal()、getDuration()等),这些辅助函数查看关于嵌入式YouTube播放器的属性从而可以读取已加载视频的相关元数据。这里最重要的事情是创建连接使airAppRef与前面在onHtmlLoadComplete事件创建的引用相同,它是JavaScript领域和ActionScript领域之间的生命线。
现在,在ActionScript方面,通过updateytplayerInfo()设置的每个度量指标都有一个函数实现,如setBytesLoaded,setBytesTotal,setLengthOfVideo等。它们都遵循与setBytesLoaded的示例相似的约定,如下所示:
public var setBytesLoaded:Function = function( value:String ) : void
{
currentBytesLoaded = value;
bytes.text = currentBytesLoaded + "/" + currenttotalBytes ;
}
这可能有点混乱,因为有一个setBytesLoaded变量被设置为一个泛型函数,它接受一个字符串值。从这个意义上讲,setBytesLoaded实际上不是一个方法,而是一个方法的一个指针,即使在JavaScript中仍认为它是方法并采取相应的措施。
在实现所有这些方法后,JavaScript将数据传递回ActionScript供AIR应用程序使用是没有问题的。
39.4.3 从ActionScript控制HTML DOM
另一个期望可能是从ActionScript代码中操作加载的HTML DOM。在embeddedPlayer.html中,有一个命名为h2的HTML标记,它将呈现正在播放的视频的标题。这个h2标记可以直接从ActionScript中操作:
<h2 id="videoTitle"></h2>
当一个用户按下Play按钮播放视频时,HTML标记将从ActionScript并在标题字节中呈现视频的标题。可以通过访问videoTitle DOM元素和修改innerHTML属性在HTML页面中加载标题。
public function setVideoTitleinHtml(title:String):void
{
youTubeEmbeddedPlayer.domWindow.document.getElementById("videoTitle").innerHTML =
title;
}
利用JavaScript标准的getElementById()方法,搜索相应对象的DOM,然后设置该属性。这种模式的用法同在JavaScript中的用法。