Руководство по actionscript. часть 2, стр. 063
«cancelable». «eventPhase». «isOn»);
}
}
// Класс ToggleSwitch package {
import flash. display.*; import flash. events.*;
// Представляет простую кнопку-переключатель со стандартным поведением public class ToggleSwitch extends Sprite {
// Запоминает состояние переключателя.
private var isOn:Boolean;
// Содержит графическое изображение кнопки-переключателя private var icon.-Sprite;
// Конструктор
public function ToggleSwitch ( ) { // Создаем объект Sprite, который будет содержать графическое // изображение кнопки-переключателя icon = new Sprite( ); addChild(icon);
// По умолчанию переключатель выключен isOn = false; drawOffState( );
// Регистрируем приемник для получения уведомлений всякий раз.
Советы web-дизайнеру
Каждый специалист имеет свои секреты, который он применяет в своей работе. Так и дизайнеры имеют свои маленькие секреты.
Вот некоторые из них:
1. Использование изображений должно быть оправдано, они должны быть дополнением в тему, а не лишь бы что влепить;
2. В изображении должно максимальное значение соотношения качество-размер; Прочитать остальную часть записи »
Руководство по actionscript. часть 2, стр. 064
// Если пользователь щелкнет кнопкой мыши
// на графическом изображении переключателя
icon. addEventLi stener(MouseEvent. CLICK, cli ckLi stener);
}
// Приемник, выполняемый после щелчка кнопкой мыши // на кнопке-переключателе
private function clickListener (e:MouseEvent):void { // Пользователь попытался включить или выключить переключатель. // поэтому просим среду Flash выполнить диспетчеризацию // события ToggleEvent. TOGGLE_ATTEMPT. получателем которого // является данный объект ToggleSwitch. Сначала создадим // событийный объект… var toggleEvent:Toggl eEvent =
new ToggleEvent(ToggleEvent. TOGGLE_ATTEMPT. true, true);
// …затем отправляем запрос на диспетчеризацию события dispatchEvent(toggleEvent);
// Диспетчеризация события ToggleEvent. TOGGLE_ATTEMPT завершена. // Если никакой приемник не отменил стандартное поведение события… if (!toggleEvent. isDefaultPrevented( )) {
// …изменяем состояние переключателя
toggle( );
}
}
// Включает переключатель, если в настоящий момент он выключен, или
// выключает его. если переключатель включен. Стоит отметить, что состояние
// переключателя может быть изменено программным путем, даже если пользователь // не имеет привилегий изменить состояние переключателя вручную, public function toggle ( ):void {
// Изменяем состояние переключателя
isOn = IisOn;
// Рисуем для нового состояния переключателя соответствующее изображение if (isOn) {
drawOnState( ); } else {
drawOffState( );
}
// Просим среду Flash выполнить диспетчеризацию события // ToggleEvent. TOGGLE, получателем которого является данный // объект ToggleSwitch
var toggleEvent:ToggleEvent = new ToggleEvent(ToggleEvent. TOGGLE.
Руководство по actionscript. часть 2, стр. 065
True, false. isOn);
dispatchEvent(toggleEvent);
}
// Рисуем изображение для выключенного состояния private function drawOffState ( ):void {
icon. graphics. clear( );
icon. graphics. lineStyle(l);
icon. graphics. beginFill(OxFFFFFF);
icon. graphics. drawRect(0. 0. 20. 20);
}
// Рисуем изображение для включенного состояния private function drawOnState ( ):void {
icon. graphics. clear( );
i con. g raphi cs.1i neSty1e(1);
icon. graphics. beginFill(OxFFFFFF);
icon. graphics. drawRect(0. 0. 20. 20);
icon. graphics. beginFill(0×000000);
icon. graphics. drawRect(5. 5. 10. 10);
}
}
}
// Класс Control Panel (основной класс приложения) package { import flash. display.*;
// Базовое приложение, которое демонстрирует отмену // стандартного поведения для пользовательских событий public class ControlPanel extends Sprite {
// Присваиваем уровень привилегий для пользователя данного приложения.
Руководство по actionscript. часть 2, стр. 066
// В данном примере только пользователи с привилегиями UserType. ADMIN
// могут использовать кнопку-переключатель.
private var userType:int = UserType. GUEST;
// Конструктор
public function Control Panel ( ) { // Создаем объект ToggleSwitch var toggleSwitch:ToggleSwitch = new ToggleSwitch( ); // Регистрируем приемник для событий // ToggleEvent. TOGGLE_ATTEMPT
toggleSwi tch. addEventLi stener(ToggleEvent. TOGGLE_ATTEMPT.
toggleAttemptListener);
// Регистрируем приемник для событий ToggleEvent. TOGGLE toggleSwi tch. addEventLi stener(ToggleEvent. TOGGLE,
toggleListener); // Добавляем кнопку-переключатель в иерархию отображения // данного объекта addChi1dCtoggleSwitch);
}
// Приемник выполняется всякий раз. когда возникает событие // ToggleEvent. TOGGLE_ATTEMPT
private function toggleAttemptListener (e:ToggleEvent):void { // Если пользователь является «гостем»… if (userType == UserType. GUEST) {
// …запретить изменение состояния переключателя
e. preventDefault( );
}
}
// Приемник выполняется всякий раз. когда возникает событие // ToggleEvent. TOGGLE
private function toggleListener (e:ToggleEvent):void { if (e. isOn) {
traceC’The ToggleSwitch is now on.»); } else {
trace(«The ToggleSwitch is now off.»);
}
}
}
// Класс UserType package {
// Определяет константы, представляющие уровни // пользовательских привилегий в приложении // с панелью управления public class UserType {
public static const GUEST:int =0;
public static const ADMIN:int = 1;
}
} •
Теперь, когда мы познакомились с пользовательскими событиями в ActionScript, рассмотрим две последние темы, связанные с событиями.
Руководство по actionscript. часть 2, стр. 067
Недостаток проверки типов
в событийной модели языка ActionScript
Событийная модель ActionScript, основанная на приемниках, включает несколько различных участников: приемник события, объект, регистрирующий этот приемник, получатель события, событийный объект и имя события. Диспетчеризация определенного события (и его обработка) завершится успешно только в том случае, если все участники будут надлежащим образом взаимодействовать между собой. Для этого должны выполняться следующие основные условия.
? Должен существовать тип события, для которого регистрируется приемник.
? Должен существовать сам приемник.
? Приемник должен знать, как обрабатывать событийный объект, передаваемый в процессе диспетчеризации возникшего события.
? Объект, осуществляющий регистрацию приемника, должен поддерживать указанный тип события.
Когда приемник регистрируется в объекте для получения события, он вступает в соглашение, основанное на типах данных, которое гарантирует выполнение первых трех условий. Если это соглашение не выполняется, компилятор генерирует ошибку типа. Например, рассмотрим следующий код, описывающий и регистрирующий приемник, в котором умышленно допущены три нарушения (выделенные полужирным шрифтом) контракта приемника события:
urlLoader. addEventLi stener(Event. COMPLTE, completeLi stenr);
private function completeListener (e:MouseEvent):void { traceCLoad complete»);
}
В приведенном коде нарушения контракта приемника события заключаются в следующем.
? Константа Event. COMPLTE записана с ошибкой: пропущена буква Е. Компилятор сгенерирует ошибку, которая предупредит программиста о том, что тип события, для получения которого пытается зарегистрироваться приемник, не существует.
Руководство по actionscript. часть 2, стр. 068
? Название приемника события записано с ошибкой: пропущена еще одна буква е. Компилятор сгенерирует ошибку, которая предупредит программиста о том, что регистрируемый приемник не существует.
? Типом данных первого параметра, передаваемого в метод completeListener ( ), является Мои s еЕ ve n t, который не соответствует типу данных событийного объекта для события Event. COMPLETE. На этапе диспетчеризации события среда выполнения Flash сгенерирует ошибку, которая предупредит программиста, что приемник не может обработать переданный в него событийный объект.
Если мы изменим предыдущий код, исправив все указанные ошибки типа, диспетчеризация события и его обработка будут успешно выполнены.
^ I Соглашение между приемником события и объектом, который регистрирует этот при-d, m емник, основанное на типах данных, позволяет гарантировать корректное выполнение нашего кода, обрабатывающего события.
Тем не менее соглашение между приемником и объектом, регистрирующим этот приемник, имеет один недостаток: оно не гарантирует, что объект поддерживает указанный тип события. Например, рассмотрим следующим код, который регистрирует приемник в объекте urlLoader для событий TextEvent. TEXT_INPUT:
url Loader. addEventLi stener (TextEvent. TEXTJNPUT. text InputLi stener);
Хотя с практической точки зрения у нас есть все основания полагать, что объект URLLoader никогда не будет получателем события TextEvent. TEXT_INPUT, приведенный код не вызовет ошибки. В языке ActionScript регистрация приемников для событий осуществляется по любому имени. Например, следующий бессмысленный код также является допустимым:
urlLoader. addEventLi stener(«dlrognw», dlrognwLi stener);
Каким бы очевидным ни казалось то, что объект urlLoader никогда не будет получателем события с именем 11 dl rognw «, программа на самом деле может выполнить диспетчеризацию такого события. Это демонстрирует следующий код:
urlLoader. dispatchEvent(new Event(«dlrognw»));
Учитывая, что программа имеет возможность назначать любой объект в качестве получателя любого события, язык ActionScript намеренно не использует концепцию «поддерживаемых событий». Подобная гибкость является предметом споров, поскольку она может привести к трудновыявляемым ошибкам в коде. Например, предположим, что мы используем класс Loader для загрузки внешнего изображения, как показано в следующем коде:
var loader:Loader = new Loader( );
1oader.1oad(new URLRequest(«i mage. jpg»)):
Предположим также, что объект loader будет являться получателем событий, информирующих о завершении загрузки изображения (во многом аналогично тому, как объект URLLoader является получателем событий о завершении загрузки элемента). Таким образом, мы пытаемся обработать событие Event. COMPLETE для нашего загружаемого элемента, зарегистрировав приемник непосредственно в объекте Loader, как показано в следующем коде:
1oader. addEventLi stener(Event. COMPLETE. completeLi stener);
Запустив код, мы будем удивлены, поскольку, даже несмотря на отсутствие ошибок, метод completeListener ( ) не был вызван ни разу. Так как никаких ошибок не возникло, мы не сможем сразу же определить источник проблемы в нашем коде. Последующий анализ и отладка кода будут стоить нам времени и, по всей вероятности, значительного неудовлетворения. Только прочитав соответствующий раздел документации корпорации Adobe, мы определим проблему: объекты Loader на самом деле не являются получателями событий о завершении загрузки; вместо этого события о завершении загрузки должны обрабатываться
экземпляром класса Loaderlnf о каждого объекта Loader, как показано в следующем коде:
1oader. contentLoaderInfо. addEventLi stener(Event. COMPLETE. completeLi stener);
В будущем язык ActionScript, возможно, позволит классам перечислять события, которые они поддерживают, и генерировать соответствующие предупреждения компилятора на попытки зарегистрировать приемник на события, которые не поддерживаются данным классом. Пока же классы, которые реализуют пользовательские события, путем переопределения метода addEventListener ( ) могут самостоятельно генерировать пользовательские ошибки в тех случаях, когда программа пытается зарегистрировать приемник для неподдерживаемых событий, как показано в следующем коде:
public override function addEventListener(eventType:String.
Руководство по actionscript. часть 2, стр. 069
Handler:Function, capture:Boolean = false, priority:int = 0. weakRef:Boolean = false):void { // Метод canDispatchEv. entC ) (не показан) проверяет наличие // указанного типа eventType в списке поддерживаемых // данным классом событий и возвращает значение типа Boolean. // которое говорит о том. является ли указанный тип eventType // поддерживаемым типом событий if(canDispatchEvent(eventType)) { // Событие поддерживается, поэтому приступаем к регистрации super. addEventListener(eventType. handler, capture, priority. weakRef); } else {
// Событие не поддерживается, поэтому генерируем ошибку throw new ErrorCthis + » does not support events of type ‘» + eventType + );
}
}
Мораль этой истории такова: будьте особенно внимательны при регистрации приемника для события. Всегда убеждайтесь в том, что объект, в котором регистрируется приемник, на самом деле поддерживает требуемое событие.
Теперь рассмотрим последний вопрос, касающийся событийной модели: обработку событий в приложениях, состоящих из нескольких SWF-файлов, которые размещены в различных интернет-доменах. Для изучения следующего раздела необходимс иметь общее представление о методах загрузки SWF-файлов, которые рассматриваются в гл. 28.
Обработка событий между границами зон безопасности
В гл. 19 будет рассмотрено несколько сценариев, в которых ограничения безопас ности не позволяют одному SWF-файлу осуществлять кросс-скриптинг (управ лять программным путем) над другим файлом. Когда два SWF-файла не могу]
осуществлять кросс-скриптинг друг над другом из-за ограничений безопасности приложения Flash Player, к ним применяются следующие ограничения, связанные с обработкой событий.
? Приемники событий из одного SWF-файла не могут регистрироваться для событий в объектах другого SWF-файла.
? Если получателем события является объект в иерархии отображения, любые объекты, недоступные в SWF-файле объекта получателя, не включаются в цепочку диспетчеризации событий.
К счастью, описанные ограничения можно полностью обойти с помощью статического метода allowDomain ( ) класса flash. system. Security. Рассмотрим два примера, которые демонстрируют применение метода allowDomain ( ) для обхода каждого из этих ограничений.
*«, _
*« Информацию по загрузке SWF-файлов можно найти в гл. 28.
Руководство по actionscript. часть 2, стр. 070
Приемник из файла Module. swf регистрируется в объекте файла Main. swf
Предположим, что SWF-файл, находящийся на одном сайте (site-a. com/Main. swf), загружает SWF-файл, расположенный на другом сайте (site-b. com/Module. swf). Предположим также, что в файле Module. swf определен приемник, который желает зарегистрироваться в объекте, созданном в файле Main. swf. Чтобы разрешить данную регистрацию, перед регистрацией приемника из файла Modul е. swf в файле Main. swf должна быть выполнена следующая строка кода:
Security. а11owDoma i n(«s i tе-b. com»);
Эта строка позволяет всем SWF-файлам, находящимся на сайте site-b. com (включая файл Module. swf), регистрировать приемники в любом объекте, созданном в файле Main. swf.
Приемник из файла Main. swf получает уведомление
о событии, получателем которого является отображаемый
объект в файле Module. swf
Продолжая рассматривать сценарий, в котором файл Main. swf загружает файл Module. swf из предыдущего раздела, предположим, что экземпляр основного класса файла Main. swf добавляет объект класса Loader, содержащий файл Module. swf, в свою иерархию отображения, как показано в следующем коде:
package { import flash. display.*; import flash. net.*; import flash. events.*;
public class Main extends Sprite { private var loader:Loader;
public function Main( ) { loader = new Loader( );
1oader.1oad(new URLRequest(«http://site-b. com/Module. swf»));
// Добавляем объект Loader, содержащий файл Module. swf, в иерархию
// отображения данного объекта
addChild(loader);
• } .} }.
Руководство по actionscript. часть 2, стр. 071
Предположим также, что экземпляр основного класса файла Main. swf желает получать уведомления всякий раз, когда пользователь щелкает кнопкой мыши на объекте из файла Module. swf. Следовательно, экземпляр основного класса файла Main, swf регистрирует приемник в объекте loader для событий MouseEvent. CLICK, как показано в следующем коде:
package { import flash. display.*: import flash. net.*; import flash. events.*;
public class Main extends Sprite { private var loader:Loader;
public function Main( ) { loader = new Loader( );
1 oader.-load(new URLRequest(«http://site-b. com/Module. swf»)); addChild(loader);
1oader. addEventLi stener(MouseEvent. CLICK. clickListener); } •
private function clickListener (e:MouseEvent):void { trace(«Module. swf was clicked»);
}
}
}
Тем не менее, поскольку файлы Ma in. swf и Module, swf размещены в различных интернет-доменах, ограничения безопасности запрещают вызывать метод clickListener ( ) для возникающих событий MouseEvent. CLICK, получателями которых являются отображаемые потомки объекта loader (то есть отображаемые объекты из файла Module. swf).
Для того чтобы обойти данное ограничение, конструктор основного класса файла Module. swf содержит следующую строку кода:
Security. al1owDoma i n(«s i te-a. com»);
После выполнения этой строки файл Module. swf начнет доверять файлу Main. swf (и всем SWF-файлам с сайта site-a. com), благодаря чему экземпляр основного класса файла Ma in. swf будет включен клиентской средой выполнения Flash в цепочку диспетчеризации события MouseEvent. CLICK, получателем которого являются объекты из файла Module. swf. В результате метод clickListener ( )
будет вызываться всякий раз при щелчке кнопкой мыши на объекте из файла Module. swf.