Этот образец приложения демонстрирует применение подходящих методов обмена данными между ActionScript и JavaScript в веб-обозревателе в контексте приложения для мгновенного обмена сообщениями, которое позволяет человеку участвовать в чате с самим собой (отсюда и имя приложения: Introvert IM). Пересылка сообщений между формой HTML на веб-странице и интерфейсом SWF выполняется с помощью внешнего API. В этом примере показаны, например, следующие методы:
-
Правильная инициация обмена данными путем проверки готовности обозревателя к связи перед установкой подключения
-
Проверка наличия у контейнера поддержки внешнего API
-
Вызов функций JavaScript из ActionScript, передача параметров и получение в ответ значений
-
Предоставление возможности вызова с помощью JavaScript методов ActionScript и выполнение этих вызовов
Получить файлы приложения для этого примера можно на странице
www.adobe.com/go/learn_programmingAS3samples_flash_ru
. Файлы приложения Introvert IM находятся в папке Samples/IntrovertIM_HTML. Приложение состоит из следующих файлов.
File
|
Описание
|
IntrovertIMApp.fla
или
IntrovertIMApp.mxml
|
Основной файл приложения в формате Flash (FLA) или Flex (MXML).
|
com/example/programmingas3/introvertIM/IMManager.as
|
Класс, который устанавливает связь между ActionScript и контейнером и управляет ею.
|
com/example/programmingas3/introvertIM/IMMessageEvent.as
|
Заказной тип события, отправляемого классом IMManager при получении сообщения из контейнера.
|
com/example/programmingas3/introvertIM/IMStatus.as
|
Перечислимый тип, значения которого отражают разные значения состояния «доступности», которые можно выбрать в приложении.
|
html-flash/IntrovertIMApp.html
или
html-template/index.template.html
|
HTML-страница приложения для Flash (html-flash/IntrovertIMApp.html) или шаблон, который использовался для создания HTML-страницы приложения для Adobe Flex (html-template/index.template.html). Этот файл содержит все функции JavaScript, которые делают контейнер частью приложения.
|
Подготовка связи между ActionScript и обозревателем
Одно из наиболее частых применений внешнего API состоит в том, чтобы позволять приложениям ActionScript связываться с обозревателем. С помощью внешнего API методы ActionScript могут вызывать код, написанный на языке JavaScript, и наоборот. Из-за сложности обозревателей и их метода внутренней визуализации страниц не существует метода, гарантирующего, что документ SWF зарегистрирует обратные вызовы перед тем, как будет запущен первый код JavaScript на HTML-странице. По этой причине перед вызовом функций в SWF-документе из JavaScript ваш SWF-документ должен всегда вызывать HTML-страницу, чтобы уведомить ее о том, что SWF-документ готов к приему подключений.
Например, выполнив ряд действий с применением класса IMManager, Introvert IM определяет, готов ли обозреватель для связи, и подготовить SWF-файл для связи. Первый шаг состоит в определении времени, когда обозреватель готов для связи. Он выполняется в конструкторе IMManager следующим образом:
public function IMManager(initialStatus:IMStatus)
{
_status = initialStatus;
// Check if the container is able to use the external API.
if (ExternalInterface.available)
{
try
{
// This calls the isContainerReady() method, which in turn calls
// the container to see if Flash Player has loaded and the container
// is ready to receive calls from the SWF.
var containerReady:Boolean = isContainerReady();
if (containerReady)
{
// If the container is ready, register the SWF's functions.
setupCallbacks();
}
else
{
// If the container is not ready, set up a Timer to call the
// container at 100ms intervals. Once the container responds that
// it's ready, the timer will be stopped.
var readyTimer:Timer = new Timer(100);
readyTimer.addEventListener(TimerEvent.TIMER, timerHandler);
readyTimer.start();
}
}
...
}
else
{
trace("External interface is not available for this container.");
}
}
Первым делом код проверяет, доступен ли внешний API в текущем контейнере с помощью свойства
ExternalInterface.available
. При этом он приступает к установке подключения. Поскольку исключения, связанные с безопасностью, и другие ошибки могут происходить при попытке связи с внешним приложением, код упакован в блок
try
(соответствующие блоки
catch
были пропущены при перечислении для краткости).
Затем код вызывает метод
isContainerReady()
:
private function isContainerReady():Boolean
{
var result:Boolean = ExternalInterface.call("isReady");
return result;
}
Метод
isContainerReady()
в свою очередь обращается к методу
ExternalInterface.call()
, чтобы вызвать функцию JavaScript
isReady()
следующим образом:
<script language="JavaScript">
<!--
// ------- Private vars -------
var jsReady = false;
...
// ------- functions called by ActionScript -------
// called to check if the page has initialized and JavaScript is available
function isReady()
{
return jsReady;
}
...
// called by the onload event of the <body> tag
function pageInit()
{
// Record that JavaScript is ready to go.
jsReady = true;
}
...
//-->
</script>
Функция
isReady()
просто возвращает значение переменной
jsReady
. Этой переменной исходно присвоено значение
false
; после запуска события
onload
на веб-странице переменная принимает значение
true
. Другим словами, если ActionScript вызывает функцию
isReady()
перед загрузкой страницы, JavaScript возвращает
false
для
ExternalInterface.call("isReady")
, а метод ActionScript
isContainerReady()
возвращает соответственно значение
false
. После завершения загрузки страницы функция JavaScript
isReady()
возвращает значение
true
. Поэтому метод
isContainerReady()
в ActionScript также возвращает
true
.
В конструкторе IMManager происходит одно из двух событий в зависимости от готовности контейнера. Если
isContainerReady()
возвращает
true
, код просто вызывает метод
setupCallbacks()
, который завершает процесс установки связи с JavaScript. С другой стороны, если
isContainerReady()
возвращает
false
, процесс по существу откладывается. Создается объект Timer, которому дается инструкция вызывать метод
timerHandler()
раз в 100 миллисекунд:
private function timerHandler(event:TimerEvent):void
{
// Check if the container is now ready.
var isReady:Boolean = isContainerReady();
if (isReady)
{
// If the container has become ready, we don't need to check anymore,
// so stop the timer.
Timer(event.target).stop();
// Set up the ActionScript methods that will be available to be
// called by the container.
setupCallbacks();
}
}
Каждый раз, когда вызывается метод
timerHandler()
, он снова проверяет результат метода
isContainerReady()
. После инициализации контейнера этот метод возвращает значение
true.
Затем код останавливает Timer и вызывает метод
setupCallbacks()
, завершая процесс установки подключения к обозревателю.
Предоставление методов ActionScript JavaScript
Как показано в предыдущем примере, после того, как код определяет, что обозреватель готов, вызывается метод
setupCallbacks()
. Этот метод готовит ActionScript для принятия вызовов со стороны JavaScript, как указано ниже:
private function setupCallbacks():void
{
// Register the SWF client functions with the container
ExternalInterface.addCallback("newMessage", newMessage);
ExternalInterface.addCallback("getStatus", getStatus);
// Notify the container that the SWF is ready to be called.
ExternalInterface.call("setSWFIsReady");
}
Метод
setCallBacks()
завершает задачу подготовки связи с контейнером путем вызова метода
ExternalInterface.addCallback()
для регистрации двух методов, которые можно будет вызвать из JavaScript. В этом коде первый параметр (имя, под которым этот метод известен JavaScript (
"newMessage"
и
"getStatus"
) идентичен имени метода в ActionScript. В данном случае использование других имен не давало преимущества, поэтому для простоты повторно применялось одно и то же имя. В итоге метод
ExternalInterface.call()
использовался для вызова функции JavaScript
setSWFIsReady()
, которая уведомляет контейнер о том, что функции ActionScript были зарегистрированы.
Связь между ActionScript и обозревателем
Приложение Introvert IM демонстрирует целый ряд примеров вызова функций JavaScript на странице контейнера. В простейшем случае (пример из метода
setupCallbacks()
) функция
setSWFIsReady()
в JavaScript вызывается без передачи каких-либо параметров или получения в ответ значения:
ExternalInterface.call("setSWFIsReady");
В другом примере из метода
isContainerReady()
ActionScript вызывает функцию
isReady()
и получает в ответ логическое значение:
var result:Boolean = ExternalInterface.call("isReady");
Передать параметры функциям JavaScript можно также с помощью внешнего API. Рассмотрим, к примеру, метод
sendMessage()
класса IMManager, который вызывается, когда пользователь отправляет новое сообщение своему «собеседнику»:
public function sendMessage(message:String):void
{
ExternalInterface.call("newMessage", message);
}
И снова здесь применяется метод
ExternalInterface.call()
для вызова назначенной функции JavaScript, уведомляя обозревателя о новом сообщении. Кроме того, само сообщение передается в качестве дополнительного параметра методу
ExternalInterface.call()
и соответственно передается в качестве параметра функции JavaScript
newMessage()
.
Вызов кода ActionScript из JavaScript
Связь предполагает двусторонний обмен, и приложение Introvert IM не является исключением. Не только клиент системы мгновенного обмена сообщениями в проигрывателе Flash Player вызывает JavaScript для отправки сообщений. HTML-форма также вызывает код JavaScript для отправки сообщений и запроса информации из SWF-файла. Например, когда SWF-файл уведомляет контейнер о том, что он закончил устанавливать контакт и готов к связи, обозреватель первым делом вызывает метод
getStatus()
класса IMManager, чтобы узнать исходное состояние доступности пользователя из клиента системы мгновенного обмена сообщениями SWF. Это выполняется на веб-странице функции
updateStatus()
следующим образом:
<script language="JavaScript">
...
function updateStatus()
{
if (swfReady)
{
var currentStatus = getSWF("IntrovertIMApp").getStatus();
document.forms["imForm"].status.value = currentStatus;
}
}
...
</script>
Код проверяет значение переменной
swfReady
, которая следит за тем, уведомил ли SWF-файл обозреватель о том, что он зарегистрировал свои методы в классе ExternalInterface. Если SWF-файл готов к приему связи, следующая строка (
var currentStatus =
...) фактически вызывает метод
getStatus()
в классе IMManager. В этой строке происходят три события.
-
Вызывается функция
getSWF()
для JavaScript, которая возвращает ссылку на объект JavaScript, представляющий SWF-файл. Параметр, переданный
getSWF()
, определяет, какой объект обозревателя возвращается в том случае, если на HTML-странице имеется более одного SWF-файла. Значение, переданное этому параметру, должно соответствовать атрибуту
id
тега
object
и атрибуту
name
тега
embed
, используемым для включения SWF-файла.
-
С помощью ссылки на SWF-файл метод
getStatus()
вызывается так, как если бы он был методом объекта SWF. В данном случае применяется имя «
getStatus
», потому что это то имя, под которым зарегистрирована функция ActionScript с помощью метода
ExternalInterface.addCallback()
.
-
Метод
getStatus()
для ActionScript возвращает значение, и это значение присваивается переменной
currentStatus
, которая затем назначается в качестве содержимого (свойство
value
) текстового поля
status
.
Примечание.
Если вы внимательно отслеживаете код, то, вероятно, заметили, что в исходном коде для функции
updateStatus()
строка кода, вызывающая функцию
getSWF()
, на самом деле записана следующим образом: var currentStatus = getSWF("${application}").getStatus(). Текст
${application}
является местозаполнителем в шаблоне страницы HTML. Когда Adobe Flash Builder создает конкретную страницу HTML для приложения, этот местозаполнитель заменяется тем же текстом, который используется в качестве атрибута
id
тега
object
и атрибута
name
тега
embed
(в данном примере это текст
IntrovertIMApp
). Именно это значение и ожидается функцией
getSWF()
.
Функция
sendMessage()
для JavaScript демонстрирует передачу параметра функции ActionScript. (
sendMessage()
— это функция, которая вызывается, когда пользователь нажимает кнопку «Отправить» на HTML-странице.)
<script language="JavaScript">
...
function sendMessage(message)
{
if (swfReady)
{
...
getSWF("IntrovertIMApp").newMessage(message);
}
}
...
</script>
Метод
newMessage()
для ActionScript ожидает один параметр. Поэтому переменная
message
для JavaScript передается в ActionScript. Она служит в качестве параметра при вызове метода
newMessage()
в коде JavaScript.
Определение типа обозревателя
Из-за различий в методе доступа обозревателей к содержимому важно всегда применять JavaScript, чтобы определить выбранный пользователем обозреватель и вызвать ролик в соответствии с синтаксисом для конкретного обозревателя с помощью объекта окна или документа, как показано в функции
getSWF()
для JavaScript в этом примере:
<script language="JavaScript">
...
function getSWF(movieName)
{
if (navigator.appName.indexOf("Microsoft") != -1)
{
return window[movieName];
}
else
{
return document[movieName];
}
}
...
</script>
Если в вашем сценарии не определен тип обозревателя пользователя, пользователь может столкнуться с неожиданным поведением при воспроизведении SWF-файлов в контейнере HTML.
|
|
|