В этом уроке мы покажем вам различные способы общения Flash с внешними источниками (получения и передачи данных). Затем вы сможете воспользоваться полученными знаниями при построении несложного Flash-приложения, которое даст пользователям возможность "голосовать" за фильм, причем результаты голосования будут отображаться на экране, и все полученные сообщения будут сохраняться в журнале на вашем жестком диске.
В этом уроке:

Приложение-журнал (мы создадим его в этом уроке) позволит добавлять новые записи, просматривать предыдущие и сохранять их.
На выполнение этого урока требуется примерно один час.
Файлы-носители:
Lesson11/Assets/poll.asp Lesson11/Assets/poll.mdb
Стартовые файлы:
Lesson11/Assets/poll1.fla Lesson11/Assets/journal1.fla
Законченные проекты:
poll2.fla journal2.fla
Бонус:
Lesson11/Bonus/highscoreList.fla
Источник данных – это объект или место, из которого Flash может загрузить внешние данные (то есть данные, не запрограммированные непосредственно внутри фильма). Например, Flash может загружать данные из обычного текстового файла – тогда этот файл будет считаться источником данных.
Любые данные, которые вы собираетесь загружать во Flash из внешнего источника, должны быть определенным образом структурированы – иметь определенный формат. Flash поддерживает следующие форматы:
name=Jobewebsite=http://www.electrotank.comhairColor=brown описывает три переменные ( name, website, hairColor ) с соответствующими им значениями ( Jobe, http://www.electrotank.com, brown ). После загрузки этой строки Flash автоматически разделит ее на пары имя-значение, и эти переменные можно будет использовать так же, как переменные, запрограммированные в фильме. Здесь, как видите, знак равенства связывает ) указывает конец описания одной переменной и начало следующей. Число переменных, описываемых в таком формате, неограниченно. Учтите, однако, что в таком формате можно хранить лишь простые переменные, для хранения данных в виде <States>
<State>
<Name>North Carolina</Name>
<Capital>Raleigh</Capital>
</State>
<State>
<Name>Virginia</Name>
<Capital>Richmond</Capital>
</Sate>
</States>
После загрузки документа XML во Flash данные из него извлекаются скриптом (который вы сами должны написать).
Примечание Подробнее о формате XML смотри Урок 12 – Применение XML во Flash.
cookies : это объекты (данные), которые хранятся локально, на жестком диске пользователя. Что это означает? Пользователь запустил и просмотрел фильм (по сети либо в виде проектора). В ходе воспроизведения фильма формируются и сохраняются некие данные (имя пользователя, последний посещенный им раздел и т.п.). Впоследствии эти данные могут быть получены, когда пользователь вновь запустит фильм на том же компьютере. С помощью общих объектов можно хранить не только переменные, но данные любого типа – массивы, XML-объекты, любые другие объекты. Итак, вы познакомились с различными типами форматов данных, поддерживаемых Flash. Теперь рассмотрим источники, из которых Flash способен загружать данные.
loadVariables() или load() объекта LoadVars. В этом уроке мы с вами применим оба эти метода. Создать такой источник данных можно с помощью любого простейшего текстового редактора, вроде Windows Notepad или Apple SimpleText.ASP, CFM , CGI или JSP и выполняемые сервером. Эти страницы, будучи невидимыми пользователю, генерируют форматированные данные (в виде HTML, XML и т.д.) и пересылают их по запросу. Например, представьте себе страницу под названием news .asp, которая не имеет визуального содержания, а содержит только выполняемый сервером скрипт. При посещении пользователем этой страницы скрипт динамически сформирует и передаст на его браузер HTML-страницу, содержащую последние новости (взятые, например, из базы данных). Серверные скрипты могут возвращать данные и в формате XML, и в виде URL-строки – а это значит, что Flash, взаимодействуя со страницей, содержащей такой скрипт, может загружать данные, созданные динамически, "на лету".
*.xml.Совет. Во Flash встроена функция защиты, запрещающая загрузку данных через домены. Например, если фильм был загружен с www.site1.com, то попытка загрузить данные с www.site2.com не удастся.
При работе с серверными скриптами существует два способа обмена данными между сервером и Flash: посредством GET или POST. Оба они используются, как в обычных HTML-страницах, так и во Flash, для передачи данных (переменных и их значений), введенных в форму, на сервер для обработки (специальные методы Flash для передачи данных мы обсудим в следующих упражнениях).
При посылке переменных с помощью GET пары имя/значение просто присоединяются к самой адресной строке URL. Например, если я (автор этой книги) желаю с помощью GET послать свое имя и адрес электронной почты скрипту, расположенному на странице , я указываю URL так: http://www.somedomain.com/. Знак вопроса говорит скрипту и серверу, что все последующее есть GET проще в использовании, чем POST, он годится не во всех ситуациях, поскольку ограничен размером в 1024 символа.
Теперь посмотрим, как применяется POST. При передаче данных с помощью POST, переменные и значения содержатся внутри заголовка HTTP-запроса – то есть невидимы для пользователя. POST немного более удобный способ передачи, поскольку не ограничен числом символов.

Мы вернемся к теме применения GET и POST в упражнении к следующему разделу – "Применение объекта LoadVars".
Совет. Поскольку совместить GET и POST не всегда легко, скрипты обычно пишутся так, что они способны принимать либо GET, либо POST, но не то и другое
Объект LoadVars используется при работе с данными в формате URL-строки. С помощью этого объекта можно загружать данные из текстового файла, а также осуществлять обмен (посылать и загружать) данными с серверным скриптом.
Примечание Flash может загружать данные, содержащиеся в текстовом файле, однако
Создать объект LoadVars во Flash легко. Взгляните на этот пример:
container = new LoadVars();
Этим создается новый объект класса LoadVars с именем container. Для load():
container.load("http://www.myDomain.com/myFile.txt");
Совет. В любой момент можно узнать общее число байтов, которые необходимо загрузить, а также число уже загруженных байтов – для этого предназначены методы объекта getBytesTotal() и getBytesLoaded().
После того, как данные загружены в объект LoadVars, для получения доступа к ним следует указать LoadVars с именем myData следующую строку:
name=Jobeage=25wife=Kelly
Ссылки на эти переменные будут такими:
myData.name myData.age myData.wife
Например:
userAge = myData.age;
Здесь userAge получит значение 25. Точно так же скрипт во Flash может присвоить переменным, находящимся в объекте LoadVars, новые значения:
myData.age = 45;
Таким образом, значения переменных внутри объекта LoadVars можно задать не только путем загрузки из внешнего источника, но также и прямым присвоением с помощью скрипта в фильме.
Совет. При загрузке переменных в объект LoadVars Flash перезаписывает все значения переменных, которые уже существовали в этом объекте и добавляет переменные, которых не было.
Если требуется переслать переменные из объекта LoadVars для обработки скрипту на сервере, применяется метод . Синтаксис следующий:
myLoadVarsObject.send("http://www.mydomain.com/process.cfm");
При использовании этого метода серверный скрипт не посылает Flash никакого ответа – переменные обрабатываются на сервере и там остаются.
Метод sendAndLoad() позволяет отправить на сервер для обработки содержимое объекта LoadVars, и при этом загрузить "ответ" сервера в другой объект LoadVars:
myLoadVarsObject.sendAndLoad("http://www.mydomain.com/process.cfm", receivingLoadVarsObject);
В этом случае переменные из myLoadVarsObject отсылаются на указанный URL. Скрипт на сервере обрабатывает данные и посылает результаты в receivingLoadVarsObject. После этого скрипты в фильме могут работать с данными, присланными в последний объект. Если необходимо, чтобы результаты обработки были загружены в тот же самый объект LoadVars, который послал данные на сервер, просто воспользуйтесь методом load().
C помощью метода toString() объекта LoadVars можно создать форматированную URL-строку, содержащую переменные/значения, содержащиеся в объекте.
Объект LoadVars имеет два свойства: и loaded. Свойство (которое можно изменить перед отсылкой переменных) просто дает тип содержания, указанный в HTTP-заголовке загружаемого документа. Свойство loaded возвращает true, если false – если не завершена, и , если метод load() для этого объекта еще не вызывался.
Для объекта LoadVars доступно только одно событие: onLoad. Это событие можно использовать, например, для вызова функции, как только
Для того, чтобы по завершении LoadVars, вызвать функцию, следует:
LoadVars при помощи конструктора new LoadVars().load() объекта LoadVars.Например:
function myFunction(){
trace("Данные загружены");
}
container = new LoadVars();
container.onLoad = myFunction;
container.load("http://www.somedomain.com/myFile.asp");
В этом примере функция myFunction() будет вызвана, как только LoadVars с именем container.
Примечание Если вы знакомы с применением метода loadVariables() из Flash 5, вам следует знать, что, хотя этот метод работает и во Flash LoadVars.
В следующем упражнении мы с вами создадим несложную систему голосования, применив при этом объект LoadVars, который будет обмениваться данными (отсылать и получать) в формате URL-строки со страницей ASP. Эта страница содержит серверный скрипт, умеющий читать и записывать данные в базе данных Microsoft Access. Скрипт интерпретирует данные, посланные ASP-странице, и соответствующим образом обновляет значения в базе данных. По запросу объекта LoadVars на загрузку данных с ASP-страницы, скрипт берет данные из различных полей таблицы, формирует из них URL-строку и отсылает ее объекту LoadVars.
Страницу со скриптом ( ) и соответствующую базу данных ( ) вы найдете на прилагающемся CD-ROM в папке Lesson11. Для успешного выполнения упражнений этого урока вы должны иметь доступ к серверу Windows, чтобы серверный скрипт на ASP-странице мог быть выполнен. До начала этого упражнения вы должны выгрузить на сервер и и запомнить их расположение (адрес URL).
Мы уже создали все нужные слои, кадры, метки и клипы, так что вам остается сосредоточиться на программировании.
Если монтажный стол установлен на кадр 1, на экране отображается надпись: "What was the best movie of 2001?" ("Какой фильм был лучшим в 2001 году"). Под этим текстом оставлено RadioButton. С их помощью пользователь будет выбирать лучший, по его мнению, фильм 2001 года. После того, как он нажмет кнопку Submit, фильм выполнит скрипт, который пошлет на сервер данные (о том, какой из фильмов выбрал пользователь) и переместит курсор воспроизведения фильма на кадр 3, с меткой , и будет ожидать ответа сервера. По получении ответа (LoadVars ) фильм перейдет к кадру с меткой display. Этот кадр будет содержать скрипт, интерпретирующий данные, полученные с сервера. На основании этих данных будет вычислено процентное соотношение голосов, поданных за каждый из четырех фильмов. Это соотношение будет затем отображено в текстовых полях и графически, в виде диаграммы.

В этот слой мы поместим четыре экземпляра компонента RadioButton (между вопросом и кнопкой Submit).
Итак, вы поместили на сцену четыре экземпляра компонента Label, – это подпись, отображаемая рядом с кнопкой. Следующее свойство, Group Name – Group Name (мы используем для всех четырех стандартное значение – ). В каждый момент времени может быть включена (выбрана) только одна селективная кнопка из группы. Кроме того, каждой кнопке назначается связанное значение (ее свойство Data ). Когда одна из кнопок группы выбрана, значение ее свойства Data становится общим значением данных группы. Например, если кнопка из группы выбрана, и ее свойство Data равно 47, значение данных группы также становится равным 47 (этот факт будет очень важен для нашего проекта). После свойства Data в инспекторе Параметры мы видим свойство Label

Изменяя свойство Label в инспекторе Параметры, вы увидите, что меняются подписи у экземпляров компонентов на сцене.
Примечание Если этого не происходит, выполните команду меню Управление > Включить просмотр в реальном времени (Control > Enable
Когда после опубликования фильма пользователь выберет одну из наших Data станет значением данных группы . Это значение можно в любой момент получить, вызвав метод getData() компонента RadioButton. Предположим, например, что выбрана кнопка со значением свойства Data, равным 3, и эта кнопка входит в состав группы с именем . Тогда с помощью выражения
selectedValue = radioGroup.getData();
переменной selectedValue будет присвоено значение 3.
Это действие предотвратит воспроизведение следующих кадров фильма – до тех пор, пока фильм не получит соответствующих инструкций.
pollURL = "http://www.myDomain.com/poll.asp";
Этим будет создана переменная с именем pollURL и значением, представляющим расположение страницы , которую вы должны были выгрузить на сервер перед началом этого упражнения. Указанный здесь URL следует заменить реальным адресом страницы на вашем сервере.
poll = new LoadVars();
Этим создается новый объект LoadVars. C его помощью мы сможем загружать данные из внешнего источника и использовать их в фильме, применяя описанные выше методы.
function pollLoaded() {
_root.gotoAndStop("display");
}
Эта функция будет перемещать курсор воспроизведения к кадру с меткой display.
poll.onLoad = pollLoaded;
Этот скрипт указывает, что как только в объект LoadVars будет загружен последний байт данных, следует вызвать функцию pollLoaded(). Таким образом, по окончании display. Чуть позже мы добавим в этот кадр скрипт, который будет использовать загруженные данные для отображения результатов на диаграмме.
function submitChoice() {
var choice = radioGroup.getData();
poll.load(pollURL + "?choice=" + choice);
_root.gotoAndStop("waiting");
}

Эта функция будет вызываться при нажатии кнопки Submit, подтверждая сделанный пользователем выбор лучшего фильма года.
Первая строка функции создает . Ей присваивается текущее значение данных группы получит значение 2.
Следующей строкой вызывается метод load() объекта LoadVars . Выражение в скобках конструирует URL: берется URL страницы (pollURL), к нему добавляется строка "? ; получившаяся в итоге строка используется для обмена данными с сервером методом GET. Если, например, пользователь выбрал селективную кнопку 3, то аргумент метода load() будет выглядеть так: "http://www.mydomain.com/. Напомним: все, что стоит здесь после вопросительного знака – это переменные для передачи серверу. В данном случае мы посылаем странице ). В соответствии с этим голосом скрипт этой страницы обновит значения в базе данных, чтобы затем загрузить результат в объект LoadVars . Эти результаты мы используем на шаге 14.

Последняя строка в функции говорит, что фильм должен перейти к кадру с меткой . Фильм останется на этом кадре до тех пор, пока результаты с сервера не будут загружены во Flash. Как только это произойдет, будет вызвана функция pollLoaded(), переведя фильм к кадру с меткой display.
on (release) {
submitChoice();
}
При нажатии этой кнопки выполняется функция submitChoice(), которую мы описали на предыдущем шаге.
В этом кадре вы видите на сцене четыре горизонтальные планки – по одной на каждый фильм. Эти планки – экземпляры одного и того же фильма-символа; имена экземпляров – barGraph1, barGraph2, barGraph3 и barGraph4. Обратите внимание, что имена различаются лишь цифрами в конце – мы воспользуемся этим при отображении результатов голосования. Каждый из этих экземпляров включает в себя два текстовых поля: topPercent и bottomPercent – в них будет отображаться процент голосов, только в текстовом виде. Оба текстовых поля будут отображать один и тот же текст, поле bottomPercent служит просто для создания эффекта тени позади topPercent. Также фильм-символ содержит горизонтальную планку – клип с именем . Она будет отображать (при помощи масштабирования) процент голосов графически.
for (i=1; i<=4; ++i) {
var graphName = "barGraph" + i;
var votes = poll["item" + i + "total"];
var totalVotes = poll.totalVotes;
var percent = Math.round((votes/totalVotes) * 100);
_root[graphName].bar._xscale = percent;
}

Если курсор воспроизведения переместится к этому кадру (метка display ), значит, пользователь сделал свой выбор и подтвердил его, сервер принял данные, добавил их в базу данных и загрузил результаты в объект LoadVars . Как вы помните, на шагах 9 и 10 мы запрограммировали наш фильм таким образом, что он перейдет к этому кадру лишь после того, как данные с сервера будут полностью загружены в объект . Скрипт в этом кадре использует эти данные. Переменные, загружаемые удаленным (серверным) скриптом в объект LoadVars, называются totalVotes, item1total, item2total, item3total и item4total. Переменная totalVotes, естественно, имеет числовое значение, представляющее общее число голосований (вскоре мы воспользуемся им для расчета процентных значений). Прочие переменные содержат количество голосов, полученных каждым фильмом. Поскольку все эти переменные загружены в объект LoadVars , обращаться к ним мы должны следующим образом:
poll.totalVotes poll.item1total poll.item2total poll.item3total poll.item4total
Цикл в последнем нашем скрипте вычисляет процент голосов, полученных каждым фильмом, и, в соответствии с полученным значением, масштабирует горизонтальную планку соответствующего фильма-символа. Первая строка graphName. Ее значение есть i, что дает в результате имя экземпляра фильма-символа, над которым будет вестись работа на данной итерации цикла ( barGraph1, barGraph2 и т.д.). Таким же способом, с помощью значения i, в следующем действии цикла формируется ссылка на переменную, содержащую число голосов, полученных текущим фильмом ( и т.д.). Ее значение присваивается переменной . Затем переменной totalVotes присваивается значение общего числа голосований. После этого вычисляется значение переменной : число голосов за текущий фильм делится на общее число голосов и умножается на 100, после чего результат округляется при помощи метода Math. объекта Math. На конец, клип в текущем фильме-символе (на него указывает текущее значение graphName ) масштабируется в соответствии со значением . Действия в теле цикла повторяются четыре раза, масштабируя все четыре планки диаграммы.

Примечание Подробнее о циклах см. в Уроке 10 – Автоматизация скриптов с помощью циклов.
_root[graphname].topPercent.text = percent + "%"; _root[graphname].bottomPercent.text = percent + "%";
Текст, отображаемый в полях topPercent и bottomPercent, поверх масштабированного экземпляра клипа , формируется из значения переменной
После нажатия кнопки Submit ваш выбор будет сообщен странице LoadVars . Фильм перейдет к кадру с меткой display и покажет вам результаты голосования!
Итак, мы только что завершили простое приложение, использующее объект LoadVars для общения с внешним скриптом. Полученные знания вы сможете применить для создания более сложных и полезных приложений.
Файл SWF способен , используемыми веб-браузерами, но более мощная. Общие объекты могут хранить информацию, генерируемую пользователем при просмотре фильма (имя, последний посещенный кадр, музыкальные установки и многое другое). Общие объекты могут использоваться как фильмами, проигрываемыми в браузере, так и теми, которые опубликованы как самостоятельные проекторы.
Примечание Общие объекты также можно использовать при посредстве Flash Application Services от Macromedia (подробности о Flash Application Services вы найдете на macromedia.com).
Вот пример скрипта, создающего общий объект:
myObject = SharedObject.getLocal("stuff_I_saved");
Если общий объект "stuff_I_saved" существует на жестком диске пользователя, данные из него будут загружены в myObject. Если "stuff_I_saved" не существует, он будет создан – по-прежнему со ссылкой на myObject. В последнем случае myObject может быть пустым, не содержащим никаких данных.
Примечание Еще раз поясним, что один и тот же метод – getLocal() – и создает общий объект (если он не существует), и получает данные из существующего общего объекта.

Как вы видите в примере, настоящее имя общего объекта – "stuff_I_saved". Однако в myObject. Это значит, что в скриптах все обращения к myObject на самом деле будут обращениями к общему объекту с именем "stuff_I_saved" – концепция немного мудреная, но понять ее важно для работы с общими объектами в
Данные в общий объект помещаются посредством использования свойства data. Например:
myObject.data.userName = userName.text;
Эта строка сохраняет переменную (и ее значение – текст из поля ) в общем объекте. Так можно сохранять не только переменные, но и целые объекты. Например, если нужно сохранить имеющийся в проекте массив, используется тот же синтакис:
myObject.data.savedArray = nameOfArray;
Единственный общий объект может хранить одновременно несколько элементов данных:
myObject.data.savedArray = nameOfArray; myObject.data.savedXML = nameOfXMLObject; myObject.data.userName = userName.text;
Удалить из общего объекта имеющийся элемент данных можно при помощи null, как в этом примере:
myObject.data.userName = null;
Этот скрипт "сотрет" элемент
Извлечь данные из общего объекта так же просто, как сохранить:
userName.text = myObject.data.userName;
Этот скрипт отобразит в текстовом поле значение переменной из общего объекта. Если в общем объекте такая переменная не существует, в текстовом поле будет отображено "
По завершении сеанса SWF (то есть, когда фильм закончится или будет закрыт пользователем) вся информация свойства data общего объекта автоматически записывается в файл общего объекта, и может быть получена с помощью метода getLocal(), как мы описывали. Можно и специально сохранить общий объект (записать в файл), применив метод . Например:
myObject.flush();
Эта строка скрипта вызывает сохранение общего объекта и всех данных, которые он содержит. Поскольку myObject есть ссылка на общий объект "stuff_I_saved", под этим последним именем и будет сохранен общий объект.
Flash помещает все общие объекты в одно общее "хранилище"; при этом точное расположение каждого общего объекта зависит от того, где находится фильм, создавший этот объект.
В Windows все общие объекты помещаются в следующий каталог:
Windows\Application Data\Macromedia\Flash Player\
На
System Folder\Preferences\Macromedia\Flash Player\
Это – общие, основные каталоги, общие объекты, создаваемые фильмами, помещается в соответствующие подкаталоги основного каталога. Предположим, что фильм был запущен с такого URL:
http://www.electrotank.com/fun/games/MiniGolf.swf
Все общие объекты, созданные этим фильмом, на машине под Windows будут, по умолчанию, сохранены в каталог:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\games\MiniGolf
Обратите внимание – структура создаваемых подкаталогов соответствует URL.

Фильмы, запускаемые локально (как проекторы) не имеют URL, и потому Flash сохраняет создаваемые ими общие объекты в подкаталоге localhost:
Windows\Application Data\Macromedia\Flash Player\localhost
Все указанные здесь пути и каталоги используются для сохранения общих объектов по умолчанию. Вы обладаете полной свободой при размещении и загрузке общих объектов – но в пределах основного каталога. Как в предыдущем примере, предположим, что воспроизведенный фильм находится по URL
http://www.electrotank.com/fun/games/MiniGolf.swf
В этом фильме имеется следующий общий объект:
myScores = SharedObject.getLocal("scoreData");
При сохранении этого общего объекта путь к нему (под Windows) будет таким:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\games\MiniGolf\scoreData.sol
Когда этот фильм будет вновь запущен с того же URL, Flash будет искать общий объект именно в этом месте. Однако метод getLocal() позволяет дополнительно указать путь, по которому следует сохранять и впоследствии искать общий объект. Предположим, что в том же фильме общий объект объявлен таким образом:
myScores = SharedObject.getLocal("scoreData", "/fun");
В этом случае путь к общему объекту будет следующим:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\scoreData.sol
Зная это, вы можете создавать фильмы, которые расположены в разных местах, но при этом используют один и тот же общий объект – очень полезная возможность, если вы хотите, например, чтобы все фильмы вашего сайта использовали один общий объект, содержащий, скажем, информацию о пользователе. Просто сохраните этот общий объект в основной каталог ("/").
Примечание Будьте внимательны, сопоставляя один общий объект нескольким при этом фильмам: существует возможность того, что данные, содержащиеся в общем объекте, будут перезаписаны, заменены новыми.
Один фильм может одновременно работать – создавать, сохранять и загружать – с несколькими общими объектами.
Совет. Можно ограничить количество данных, которые данный URL имеет право поместить на ваш жесткий диск посредством Flash Player. Щелкнув правой кнопкой мыши в окне открытого SWF и выбрав в меню Settings, перейдите в открывшемся окне настроек на вкладку

Примечание На прилагаемом к книге CD-ROM, в папке этого урока, имеется бонусный файл – highscorelist.highScoreList, описанный в этом файле. Среди прочего, здесь можно отсортировать список по возрастанию или убыванию, удалить список, начать новый, исправить сущестующий счет в списке и добавить новый.
В этом упражнении мы создадим журнал, сохраняющий текстовые записи в виде массива в общем объекте.
Как видите, здесь лишь один кадр и четыре слоя, которые называются в соответствии с их содержимым. На сцене имеется два текстовых поля для отображения информации. Большое поле в центре, journalBody, будет содержать саму запись. Меньшее поле в нижней части экрана, entryNumber, будет отображать номер текущей записи по журналу. Слой Buttons содержит кнопки навигации – Prev, Next, New и Save.

Это приложение будет позволять вводить новую запись, сохранять ее, просматривать уже имеющиеся записи.
myJournal = SharedObject.getLocal("JournalObject");
Эта строка создает ссылку на общий объект JournalObject. Теперь во всех скриптах этого фильма, обращаясь к myJournal, мы будем на самом деле иметь дело с общим объектом под названием JournalObject.
if (myJournal.data.journal == undefined) {
myJournal.data.journal = [];
}
Этот оператор проверяет, имеется ли в общем объекте массив с именем . Если такого массива нет ( ), выполняется действие, создающее его.
Примечание Как только массив создан, он, после выхода из фильма или сохранения общего объекта, автоматически становится частью общего объекта.
Массив будет иметь значение лишь при самом первом воспроизведении фильма. При последующих запусках фильма массив уже будет существовать, и это действие будет игнорироваться.
Совет. Хорошая идея – проверять данные в общем объекте на значение . Это позволит присвоить им начальные стандартные значения, если фильм воспроизводится пользователем впервые.
function displayEntry(num) {
_root.entryNumber.text = num;
_root.journalBody.text = myJournal.data.journal[num - 1];
}
Эта функция устанавливает значения двух текстовых полей – entryNumber и journalBody – на основе значения num. Например, если при вызове функции num имеет значение 1, в текстовом поле entryNumber отобразится "1" (номер текущей записи журнала). Во второй строке значение num используется для определения элемента массива (из общего объекта), который должен быть отображен в текстовом поле journalBody. Если num имеет значение 1, то эта строка скрипта расшифруется так:
_root.journalBody.text = myJournal.data.journal[1 - 1];
или
_root.journalBody.text = myJournal.data.journal[0];
Почему здесь из num вычитается единица? Дело в том, что первая запись журнала ("1" в поле entryNumber ) – это нулевой элемент массива . Конечно, можно было бы показать для первой записи номер "0", но это было бы как-то не совсем привычно. Поэтому запомните этот принцип сопоставления номеров записей и индексов элементов массива (запись с номером "3" – это элемент массива с индексом 2, и так далее).
displayEntry(myJournal.data.journal.length);
Этот вызов функции находится в кадре 1, и значит, будет выполнен, как только начнется воспроизведение фильма. Вызывается функция displayEntry() (которую мы описали на предыдущем шаге) с передачей ей в качестве параметра значения свойства length массива из общего объекта. В результате на экране будет отображена последняя запись, сделанная пользователем в предыдущем сеансе фильма. Если, к примеру, в массиве имеется три записи, функции displayEntry() будет передано значение 3, и на экране будет показана третья запись журнала. Если же массив создан только что (как описано а шаге 3), он будет содержать единственную, пустую, запись – длина массива будет равна 1, и это значение станет аргументом функции.
function save() {
var num = Number(_root.entryNumber.text) - 1;
myJournal.data.journal[num] = _root.journalBody.text;
myJournal.data.flush();
}
Мы уже упоминали, что при выходе из фильма данные сохраняются в общий объект автоматически. А с помощью метода можно
Первая строка функции создает num. Значение этой переменной определяется так: значение, отображенное в текстовом поле entryNumber, минус один. Для уверенности в том, что num получит числовое, а не текстовое, значение, использована функция Number(). Значение num используется в следующей строке – в качестве индекса элемента массива, соответствующего текущей записи журнала. Как мы упоминали на шаге 4, число, отображенное в поле entryNumber (номер записи), на единицу больше, чем индекс соответствующего элемента массива; поэтому и вычитается единица в первой строке.
Итак, вторая строка текст, отображенный в поле journalBody. Как всегда, возьмем для иллюстрации пример. Допустим, что номер текущей записи (показанный в поле entryNumber ) – 9. При вызове данной функции num получит значение 8 (девять минус один). Вторая строка тогда получится такой:
myJournal.data.journal[8] = _root.journalBody.text;
Тем самым текст из поля journalBody будет записан в элемент с индексом 8 массива . Еще раз повторим, что текущий номер записи – 9, а индекс соответствующего элемента массива – 8. Таким образом, если 8-й элемент массива был до этого пустым ( ), в него будет записан текст; если этот элемент уже содержал текст, этот текст будет перезаписан (измененным или тем же самым текстом).

Последнее действие в функции с помощью метода принудительно сохраняет на жестком диске пользователя общий объект вместе с данными – в нашем случае это все записи, имеющиеся в массиве .
function newEntry() {
_root.entryNumber.text = myJournal.data.journal.length + 1;
_root.journalBody.text = undefined;
Selection.setFocus("_root.journalBody");
}
Первое действие в этой функции устанавливает номер текущей записи журнала (текст в поле entryNumber ) – длина массива плюс один. Так, например, если в массиве две записи, он имеет длину 2. В результате добавления единицы в текстовом поле entryNumber будет отображено "3". Таким образом, все новые записи будут добавляться в конец массива. Два последних действия этой функции очищают текстовое поле journalBody и устанавливают в него фокус, так что пользователь может сразу начать вводить свою новую запись. Чтобы все стало понятнее, давайте рассмотрим работу данной функции во взаимодействии с функцией save(), которую мы создали на предыдущем шаге.
Предположим, в массиве имеется две записи. Эти записи хранятся в элементах массива с индексами 0 и 1, длина массива ( length ) равна 2. При выполнении данной функции в текстовом поле entryNumber отобразится "3" (свойство length массива плюс один), текстовое поле journalBody пусто. Теперь пользователь вводит в это поле текст и нажимает кнопку Save – происходит вызов функции save(). Эта функция вычитает единицу из числа, отображенного в поле entryNumber, и в итоге помещает текст из поля journalBody в элемент с индексом 2 массива . Теперь массив содержит три записи – в элементах с индексами 0, 1 и 2, и его длина ( length ) равна 3. Если теперь вновь вызвать функцию newEntry(), процесс повторится.
function nextEntry () {
var num = Number(_root.entryNumber.text) + 1;
if (num > myJournal.data.journal.length) {
num = myJournal.data.journal.length;
}
displayEntry(num);
}
Эта функция отображает на экране следующую запись из имеющихся в массиве. Первым делом присваивается значение переменной num – число, отображенное в поле entryNumber плюс один. Далее, чтобы не случилось попытки отображения несуществующей записи, значение num сравнивается с общим числом записей, имеющихся в массиве (свойство length массива). Если значение num оказалось больше, выполняется действие в операторе if, присваивающее переменной num значение свойства length массива – это приведет к тому, что на экране будет отображена последняя запись из массива. Последнее действие – вызов функции displayEntry() с передачей ей значения num. В результате на экран будет выведена нужная запись (следующая либо последняя).
function previousEntry() {
var num = Number(_root.entryNumber.text) - 1;
if (num < 1) {
num = 1;
}
displayEntry(num);
}
Эта функция похожа на предыдущую. Первым делом num получает значение, равное номеру текущей записи минус один. Оператор if проверяет, чтобы не произошло попытки вывести на экран запись с номером меньше 1. Рассмотрим на примере, как это работает.
Предположим, в данный момент на экране отображена запись номер 6. При вызове данной функции num получает значение 5 (шесть минус один); затем оператор if проверяет, чтобы значение num было не меньше 1. В данном случае это не так, поэтому действие внутри оператора if игнорируется и вызывается функция displayEntry() с передачей ей в качестве аргумента значения 5 – на экран выводится пятая запись журнала.
Теперь допустим, что на экране – запись номер 1. Переменная num получает значение 0. Это меньше 1, поэтому оператор if присваивает num значение 1. Первая запись и так уже была выведена на экран, поэтому внешне не происходит никаких изменений. Как уже было сказано, этот механизм предотвращает попытки вывода на экран записей с номерами меньше 1, поскольку таковых попросту не может быть.
on (release) {
newEntry();
}
Когда пользователь нажмет эту кнопку, будет вызвана функция newEntry(), которая на единицу увеличит номер текущей записи и очистит поле journalBody, подготовив его для ввода текста новой записи.
on (release) {
save();
}
Когда пользователь нажмет эту кнопку, будет вызвана функция save(), в результате либо текст из поля journalBody либо заменит существующую запись, либо будет создана новая запись в массиве (как описано на шаге 6).
on (release) {
previousEntry();
}

Вызов функции previousEntry() приведет к выводу на экран записи, номер которой на единицу меньше номера текущей записи.
on (release) {
nextEntry();
}
Скрипт просто вызывает функцию nextEntry() при нажатии данной кнопки. На экран будет выведена следующая "по списку" запись журнала.
После перезапуска фильма общий объект будет загружен с вашего жесткого диска (как описано в шагах 2 и 3), и вы сможете просматривать сохраненные данные, пользуясь кнопками Prev и Next.
В этом уроке вы изучили основы использования общих объектов – их создание, сохранение в них данных и получение этих данных.
Общие объекты хороши для сохранения таких данных:
x, y, alpha, поворот) элементов фильмаВ этом уроке мы покажем вам различные способы общения Flash с внешними источниками (получения и передачи данных). Затем вы сможете воспользоваться полученными знаниями при построении несложного Flash-приложения, которое даст пользователям возможность "голосовать" за фильм, причем результаты голосования будут отображаться на экране, и все полученные сообщения будут сохраняться в журнале на вашем жестком диске.
В этом уроке:

Приложение-журнал (мы создадим его в этом уроке) позволит добавлять новые записи, просматривать предыдущие и сохранять их.
На выполнение этого урока требуется примерно один час.
Файлы-носители:
Lesson11/Assets/poll.asp Lesson11/Assets/poll.mdb
Стартовые файлы:
Lesson11/Assets/poll1.fla Lesson11/Assets/journal1.fla
Законченные проекты:
poll2.fla journal2.fla
Бонус:
Lesson11/Bonus/highscoreList.fla
Источник данных – это объект или место, из которого Flash может загрузить внешние данные (то есть данные, не запрограммированные непосредственно внутри фильма). Например, Flash может загружать данные из обычного текстового файла – тогда этот файл будет считаться источником данных.
Любые данные, которые вы собираетесь загружать во Flash из внешнего источника, должны быть определенным образом структурированы – иметь определенный формат. Flash поддерживает следующие форматы:
name=Jobewebsite=http://www.electrotank.comhairColor=brown описывает три переменные ( name, website, hairColor ) с соответствующими им значениями ( Jobe, http://www.electrotank.com, brown ). После загрузки этой строки Flash автоматически разделит ее на пары имя-значение, и эти переменные можно будет использовать так же, как переменные, запрограммированные в фильме. Здесь, как видите, знак равенства связывает ) указывает конец описания одной переменной и начало следующей. Число переменных, описываемых в таком формате, неограниченно. Учтите, однако, что в таком формате можно хранить лишь простые переменные, для хранения данных в виде <States>
<State>
<Name>North Carolina</Name>
<Capital>Raleigh</Capital>
</State>
<State>
<Name>Virginia</Name>
<Capital>Richmond</Capital>
</Sate>
</States>
После загрузки документа XML во Flash данные из него извлекаются скриптом (который вы сами должны написать).
Примечание Подробнее о формате XML смотри Урок 12 – Применение XML во Flash.
cookies : это объекты (данные), которые хранятся локально, на жестком диске пользователя. Что это означает? Пользователь запустил и просмотрел фильм (по сети либо в виде проектора). В ходе воспроизведения фильма формируются и сохраняются некие данные (имя пользователя, последний посещенный им раздел и т.п.). Впоследствии эти данные могут быть получены, когда пользователь вновь запустит фильм на том же компьютере. С помощью общих объектов можно хранить не только переменные, но данные любого типа – массивы, XML-объекты, любые другие объекты. Итак, вы познакомились с различными типами форматов данных, поддерживаемых Flash. Теперь рассмотрим источники, из которых Flash способен загружать данные.
loadVariables() или load() объекта LoadVars. В этом уроке мы с вами применим оба эти метода. Создать такой источник данных можно с помощью любого простейшего текстового редактора, вроде Windows Notepad или Apple SimpleText.ASP, CFM , CGI или JSP и выполняемые сервером. Эти страницы, будучи невидимыми пользователю, генерируют форматированные данные (в виде HTML, XML и т.д.) и пересылают их по запросу. Например, представьте себе страницу под названием news .asp, которая не имеет визуального содержания, а содержит только выполняемый сервером скрипт. При посещении пользователем этой страницы скрипт динамически сформирует и передаст на его браузер HTML-страницу, содержащую последние новости (взятые, например, из базы данных). Серверные скрипты могут возвращать данные и в формате XML, и в виде URL-строки – а это значит, что Flash, взаимодействуя со страницей, содержащей такой скрипт, может загружать данные, созданные динамически, "на лету".
*.xml.Совет. Во Flash встроена функция защиты, запрещающая загрузку данных через домены. Например, если фильм был загружен с www.site1.com, то попытка загрузить данные с www.site2.com не удастся.
При работе с серверными скриптами существует два способа обмена данными между сервером и Flash: посредством GET или POST. Оба они используются, как в обычных HTML-страницах, так и во Flash, для передачи данных (переменных и их значений), введенных в форму, на сервер для обработки (специальные методы Flash для передачи данных мы обсудим в следующих упражнениях).
При посылке переменных с помощью GET пары имя/значение просто присоединяются к самой адресной строке URL. Например, если я (автор этой книги) желаю с помощью GET послать свое имя и адрес электронной почты скрипту, расположенному на странице , я указываю URL так: http://www.somedomain.com/. Знак вопроса говорит скрипту и серверу, что все последующее есть GET проще в использовании, чем POST, он годится не во всех ситуациях, поскольку ограничен размером в 1024 символа.
Теперь посмотрим, как применяется POST. При передаче данных с помощью POST, переменные и значения содержатся внутри заголовка HTTP-запроса – то есть невидимы для пользователя. POST немного более удобный способ передачи, поскольку не ограничен числом символов.

Мы вернемся к теме применения GET и POST в упражнении к следующему разделу – "Применение объекта LoadVars".
Совет. Поскольку совместить GET и POST не всегда легко, скрипты обычно пишутся так, что они способны принимать либо GET, либо POST, но не то и другое
Объект LoadVars используется при работе с данными в формате URL-строки. С помощью этого объекта можно загружать данные из текстового файла, а также осуществлять обмен (посылать и загружать) данными с серверным скриптом.
Примечание Flash может загружать данные, содержащиеся в текстовом файле, однако
Создать объект LoadVars во Flash легко. Взгляните на этот пример:
container = new LoadVars();
Этим создается новый объект класса LoadVars с именем container. Для load():
container.load("http://www.myDomain.com/myFile.txt");
Совет. В любой момент можно узнать общее число байтов, которые необходимо загрузить, а также число уже загруженных байтов – для этого предназначены методы объекта getBytesTotal() и getBytesLoaded().
После того, как данные загружены в объект LoadVars, для получения доступа к ним следует указать LoadVars с именем myData следующую строку:
name=Jobeage=25wife=Kelly
Ссылки на эти переменные будут такими:
myData.name myData.age myData.wife
Например:
userAge = myData.age;
Здесь userAge получит значение 25. Точно так же скрипт во Flash может присвоить переменным, находящимся в объекте LoadVars, новые значения:
myData.age = 45;
Таким образом, значения переменных внутри объекта LoadVars можно задать не только путем загрузки из внешнего источника, но также и прямым присвоением с помощью скрипта в фильме.
Совет. При загрузке переменных в объект LoadVars Flash перезаписывает все значения переменных, которые уже существовали в этом объекте и добавляет переменные, которых не было.
Если требуется переслать переменные из объекта LoadVars для обработки скрипту на сервере, применяется метод . Синтаксис следующий:
myLoadVarsObject.send("http://www.mydomain.com/process.cfm");
При использовании этого метода серверный скрипт не посылает Flash никакого ответа – переменные обрабатываются на сервере и там остаются.
Метод sendAndLoad() позволяет отправить на сервер для обработки содержимое объекта LoadVars, и при этом загрузить "ответ" сервера в другой объект LoadVars:
myLoadVarsObject.sendAndLoad("http://www.mydomain.com/process.cfm", receivingLoadVarsObject);
В этом случае переменные из myLoadVarsObject отсылаются на указанный URL. Скрипт на сервере обрабатывает данные и посылает результаты в receivingLoadVarsObject. После этого скрипты в фильме могут работать с данными, присланными в последний объект. Если необходимо, чтобы результаты обработки были загружены в тот же самый объект LoadVars, который послал данные на сервер, просто воспользуйтесь методом load().
C помощью метода toString() объекта LoadVars можно создать форматированную URL-строку, содержащую переменные/значения, содержащиеся в объекте.
Объект LoadVars имеет два свойства: и loaded. Свойство (которое можно изменить перед отсылкой переменных) просто дает тип содержания, указанный в HTTP-заголовке загружаемого документа. Свойство loaded возвращает true, если false – если не завершена, и , если метод load() для этого объекта еще не вызывался.
Для объекта LoadVars доступно только одно событие: onLoad. Это событие можно использовать, например, для вызова функции, как только
Для того, чтобы по завершении LoadVars, вызвать функцию, следует:
LoadVars при помощи конструктора new LoadVars().load() объекта LoadVars.Например:
function myFunction(){
trace("Данные загружены");
}
container = new LoadVars();
container.onLoad = myFunction;
container.load("http://www.somedomain.com/myFile.asp");
В этом примере функция myFunction() будет вызвана, как только LoadVars с именем container.
Примечание Если вы знакомы с применением метода loadVariables() из Flash 5, вам следует знать, что, хотя этот метод работает и во Flash LoadVars.
В следующем упражнении мы с вами создадим несложную систему голосования, применив при этом объект LoadVars, который будет обмениваться данными (отсылать и получать) в формате URL-строки со страницей ASP. Эта страница содержит серверный скрипт, умеющий читать и записывать данные в базе данных Microsoft Access. Скрипт интерпретирует данные, посланные ASP-странице, и соответствующим образом обновляет значения в базе данных. По запросу объекта LoadVars на загрузку данных с ASP-страницы, скрипт берет данные из различных полей таблицы, формирует из них URL-строку и отсылает ее объекту LoadVars.
Страницу со скриптом ( ) и соответствующую базу данных ( ) вы найдете на прилагающемся CD-ROM в папке Lesson11. Для успешного выполнения упражнений этого урока вы должны иметь доступ к серверу Windows, чтобы серверный скрипт на ASP-странице мог быть выполнен. До начала этого упражнения вы должны выгрузить на сервер и и запомнить их расположение (адрес URL).
Мы уже создали все нужные слои, кадры, метки и клипы, так что вам остается сосредоточиться на программировании.
Если монтажный стол установлен на кадр 1, на экране отображается надпись: "What was the best movie of 2001?" ("Какой фильм был лучшим в 2001 году"). Под этим текстом оставлено RadioButton. С их помощью пользователь будет выбирать лучший, по его мнению, фильм 2001 года. После того, как он нажмет кнопку Submit, фильм выполнит скрипт, который пошлет на сервер данные (о том, какой из фильмов выбрал пользователь) и переместит курсор воспроизведения фильма на кадр 3, с меткой , и будет ожидать ответа сервера. По получении ответа (LoadVars ) фильм перейдет к кадру с меткой display. Этот кадр будет содержать скрипт, интерпретирующий данные, полученные с сервера. На основании этих данных будет вычислено процентное соотношение голосов, поданных за каждый из четырех фильмов. Это соотношение будет затем отображено в текстовых полях и графически, в виде диаграммы.

В этот слой мы поместим четыре экземпляра компонента RadioButton (между вопросом и кнопкой Submit).
Итак, вы поместили на сцену четыре экземпляра компонента Label, – это подпись, отображаемая рядом с кнопкой. Следующее свойство, Group Name – Group Name (мы используем для всех четырех стандартное значение – ). В каждый момент времени может быть включена (выбрана) только одна селективная кнопка из группы. Кроме того, каждой кнопке назначается связанное значение (ее свойство Data ). Когда одна из кнопок группы выбрана, значение ее свойства Data становится общим значением данных группы. Например, если кнопка из группы выбрана, и ее свойство Data равно 47, значение данных группы также становится равным 47 (этот факт будет очень важен для нашего проекта). После свойства Data в инспекторе Параметры мы видим свойство Label

Изменяя свойство Label в инспекторе Параметры, вы увидите, что меняются подписи у экземпляров компонентов на сцене.
Примечание Если этого не происходит, выполните команду меню Управление > Включить просмотр в реальном времени (Control > Enable
Когда после опубликования фильма пользователь выберет одну из наших Data станет значением данных группы . Это значение можно в любой момент получить, вызвав метод getData() компонента RadioButton. Предположим, например, что выбрана кнопка со значением свойства Data, равным 3, и эта кнопка входит в состав группы с именем . Тогда с помощью выражения
selectedValue = radioGroup.getData();
переменной selectedValue будет присвоено значение 3.
Это действие предотвратит воспроизведение следующих кадров фильма – до тех пор, пока фильм не получит соответствующих инструкций.
pollURL = "http://www.myDomain.com/poll.asp";
Этим будет создана переменная с именем pollURL и значением, представляющим расположение страницы , которую вы должны были выгрузить на сервер перед началом этого упражнения. Указанный здесь URL следует заменить реальным адресом страницы на вашем сервере.
poll = new LoadVars();
Этим создается новый объект LoadVars. C его помощью мы сможем загружать данные из внешнего источника и использовать их в фильме, применяя описанные выше методы.
function pollLoaded() {
_root.gotoAndStop("display");
}
Эта функция будет перемещать курсор воспроизведения к кадру с меткой display.
poll.onLoad = pollLoaded;
Этот скрипт указывает, что как только в объект LoadVars будет загружен последний байт данных, следует вызвать функцию pollLoaded(). Таким образом, по окончании display. Чуть позже мы добавим в этот кадр скрипт, который будет использовать загруженные данные для отображения результатов на диаграмме.
function submitChoice() {
var choice = radioGroup.getData();
poll.load(pollURL + "?choice=" + choice);
_root.gotoAndStop("waiting");
}

Эта функция будет вызываться при нажатии кнопки Submit, подтверждая сделанный пользователем выбор лучшего фильма года.
Первая строка функции создает . Ей присваивается текущее значение данных группы получит значение 2.
Следующей строкой вызывается метод load() объекта LoadVars . Выражение в скобках конструирует URL: берется URL страницы (pollURL), к нему добавляется строка "? ; получившаяся в итоге строка используется для обмена данными с сервером методом GET. Если, например, пользователь выбрал селективную кнопку 3, то аргумент метода load() будет выглядеть так: "http://www.mydomain.com/. Напомним: все, что стоит здесь после вопросительного знака – это переменные для передачи серверу. В данном случае мы посылаем странице ). В соответствии с этим голосом скрипт этой страницы обновит значения в базе данных, чтобы затем загрузить результат в объект LoadVars . Эти результаты мы используем на шаге 14.

Последняя строка в функции говорит, что фильм должен перейти к кадру с меткой . Фильм останется на этом кадре до тех пор, пока результаты с сервера не будут загружены во Flash. Как только это произойдет, будет вызвана функция pollLoaded(), переведя фильм к кадру с меткой display.
on (release) {
submitChoice();
}
При нажатии этой кнопки выполняется функция submitChoice(), которую мы описали на предыдущем шаге.
В этом кадре вы видите на сцене четыре горизонтальные планки – по одной на каждый фильм. Эти планки – экземпляры одного и того же фильма-символа; имена экземпляров – barGraph1, barGraph2, barGraph3 и barGraph4. Обратите внимание, что имена различаются лишь цифрами в конце – мы воспользуемся этим при отображении результатов голосования. Каждый из этих экземпляров включает в себя два текстовых поля: topPercent и bottomPercent – в них будет отображаться процент голосов, только в текстовом виде. Оба текстовых поля будут отображать один и тот же текст, поле bottomPercent служит просто для создания эффекта тени позади topPercent. Также фильм-символ содержит горизонтальную планку – клип с именем . Она будет отображать (при помощи масштабирования) процент голосов графически.
for (i=1; i<=4; ++i) {
var graphName = "barGraph" + i;
var votes = poll["item" + i + "total"];
var totalVotes = poll.totalVotes;
var percent = Math.round((votes/totalVotes) * 100);
_root[graphName].bar._xscale = percent;
}

Если курсор воспроизведения переместится к этому кадру (метка display ), значит, пользователь сделал свой выбор и подтвердил его, сервер принял данные, добавил их в базу данных и загрузил результаты в объект LoadVars . Как вы помните, на шагах 9 и 10 мы запрограммировали наш фильм таким образом, что он перейдет к этому кадру лишь после того, как данные с сервера будут полностью загружены в объект . Скрипт в этом кадре использует эти данные. Переменные, загружаемые удаленным (серверным) скриптом в объект LoadVars, называются totalVotes, item1total, item2total, item3total и item4total. Переменная totalVotes, естественно, имеет числовое значение, представляющее общее число голосований (вскоре мы воспользуемся им для расчета процентных значений). Прочие переменные содержат количество голосов, полученных каждым фильмом. Поскольку все эти переменные загружены в объект LoadVars , обращаться к ним мы должны следующим образом:
poll.totalVotes poll.item1total poll.item2total poll.item3total poll.item4total
Цикл в последнем нашем скрипте вычисляет процент голосов, полученных каждым фильмом, и, в соответствии с полученным значением, масштабирует горизонтальную планку соответствующего фильма-символа. Первая строка graphName. Ее значение есть i, что дает в результате имя экземпляра фильма-символа, над которым будет вестись работа на данной итерации цикла ( barGraph1, barGraph2 и т.д.). Таким же способом, с помощью значения i, в следующем действии цикла формируется ссылка на переменную, содержащую число голосов, полученных текущим фильмом ( и т.д.). Ее значение присваивается переменной . Затем переменной totalVotes присваивается значение общего числа голосований. После этого вычисляется значение переменной : число голосов за текущий фильм делится на общее число голосов и умножается на 100, после чего результат округляется при помощи метода Math. объекта Math. На конец, клип в текущем фильме-символе (на него указывает текущее значение graphName ) масштабируется в соответствии со значением . Действия в теле цикла повторяются четыре раза, масштабируя все четыре планки диаграммы.

Примечание Подробнее о циклах см. в Уроке 10 – Автоматизация скриптов с помощью циклов.
_root[graphname].topPercent.text = percent + "%"; _root[graphname].bottomPercent.text = percent + "%";
Текст, отображаемый в полях topPercent и bottomPercent, поверх масштабированного экземпляра клипа , формируется из значения переменной
После нажатия кнопки Submit ваш выбор будет сообщен странице LoadVars . Фильм перейдет к кадру с меткой display и покажет вам результаты голосования!
Итак, мы только что завершили простое приложение, использующее объект LoadVars для общения с внешним скриптом. Полученные знания вы сможете применить для создания более сложных и полезных приложений.
Файл SWF способен , используемыми веб-браузерами, но более мощная. Общие объекты могут хранить информацию, генерируемую пользователем при просмотре фильма (имя, последний посещенный кадр, музыкальные установки и многое другое). Общие объекты могут использоваться как фильмами, проигрываемыми в браузере, так и теми, которые опубликованы как самостоятельные проекторы.
Примечание Общие объекты также можно использовать при посредстве Flash Application Services от Macromedia (подробности о Flash Application Services вы найдете на macromedia.com).
Вот пример скрипта, создающего общий объект:
myObject = SharedObject.getLocal("stuff_I_saved");
Если общий объект "stuff_I_saved" существует на жестком диске пользователя, данные из него будут загружены в myObject. Если "stuff_I_saved" не существует, он будет создан – по-прежнему со ссылкой на myObject. В последнем случае myObject может быть пустым, не содержащим никаких данных.
Примечание Еще раз поясним, что один и тот же метод – getLocal() – и создает общий объект (если он не существует), и получает данные из существующего общего объекта.

Как вы видите в примере, настоящее имя общего объекта – "stuff_I_saved". Однако в myObject. Это значит, что в скриптах все обращения к myObject на самом деле будут обращениями к общему объекту с именем "stuff_I_saved" – концепция немного мудреная, но понять ее важно для работы с общими объектами в
Данные в общий объект помещаются посредством использования свойства data. Например:
myObject.data.userName = userName.text;
Эта строка сохраняет переменную (и ее значение – текст из поля ) в общем объекте. Так можно сохранять не только переменные, но и целые объекты. Например, если нужно сохранить имеющийся в проекте массив, используется тот же синтакис:
myObject.data.savedArray = nameOfArray;
Единственный общий объект может хранить одновременно несколько элементов данных:
myObject.data.savedArray = nameOfArray; myObject.data.savedXML = nameOfXMLObject; myObject.data.userName = userName.text;
Удалить из общего объекта имеющийся элемент данных можно при помощи null, как в этом примере:
myObject.data.userName = null;
Этот скрипт "сотрет" элемент
Извлечь данные из общего объекта так же просто, как сохранить:
userName.text = myObject.data.userName;
Этот скрипт отобразит в текстовом поле значение переменной из общего объекта. Если в общем объекте такая переменная не существует, в текстовом поле будет отображено "
По завершении сеанса SWF (то есть, когда фильм закончится или будет закрыт пользователем) вся информация свойства data общего объекта автоматически записывается в файл общего объекта, и может быть получена с помощью метода getLocal(), как мы описывали. Можно и специально сохранить общий объект (записать в файл), применив метод . Например:
myObject.flush();
Эта строка скрипта вызывает сохранение общего объекта и всех данных, которые он содержит. Поскольку myObject есть ссылка на общий объект "stuff_I_saved", под этим последним именем и будет сохранен общий объект.
Flash помещает все общие объекты в одно общее "хранилище"; при этом точное расположение каждого общего объекта зависит от того, где находится фильм, создавший этот объект.
В Windows все общие объекты помещаются в следующий каталог:
Windows\Application Data\Macromedia\Flash Player\
На
System Folder\Preferences\Macromedia\Flash Player\
Это – общие, основные каталоги, общие объекты, создаваемые фильмами, помещается в соответствующие подкаталоги основного каталога. Предположим, что фильм был запущен с такого URL:
http://www.electrotank.com/fun/games/MiniGolf.swf
Все общие объекты, созданные этим фильмом, на машине под Windows будут, по умолчанию, сохранены в каталог:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\games\MiniGolf
Обратите внимание – структура создаваемых подкаталогов соответствует URL.

Фильмы, запускаемые локально (как проекторы) не имеют URL, и потому Flash сохраняет создаваемые ими общие объекты в подкаталоге localhost:
Windows\Application Data\Macromedia\Flash Player\localhost
Все указанные здесь пути и каталоги используются для сохранения общих объектов по умолчанию. Вы обладаете полной свободой при размещении и загрузке общих объектов – но в пределах основного каталога. Как в предыдущем примере, предположим, что воспроизведенный фильм находится по URL
http://www.electrotank.com/fun/games/MiniGolf.swf
В этом фильме имеется следующий общий объект:
myScores = SharedObject.getLocal("scoreData");
При сохранении этого общего объекта путь к нему (под Windows) будет таким:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\games\MiniGolf\scoreData.sol
Когда этот фильм будет вновь запущен с того же URL, Flash будет искать общий объект именно в этом месте. Однако метод getLocal() позволяет дополнительно указать путь, по которому следует сохранять и впоследствии искать общий объект. Предположим, что в том же фильме общий объект объявлен таким образом:
myScores = SharedObject.getLocal("scoreData", "/fun");
В этом случае путь к общему объекту будет следующим:
Windows\Application Data\Macromedia\Flash Player\electrotank.com\fun\scoreData.sol
Зная это, вы можете создавать фильмы, которые расположены в разных местах, но при этом используют один и тот же общий объект – очень полезная возможность, если вы хотите, например, чтобы все фильмы вашего сайта использовали один общий объект, содержащий, скажем, информацию о пользователе. Просто сохраните этот общий объект в основной каталог ("/").
Примечание Будьте внимательны, сопоставляя один общий объект нескольким при этом фильмам: существует возможность того, что данные, содержащиеся в общем объекте, будут перезаписаны, заменены новыми.
Один фильм может одновременно работать – создавать, сохранять и загружать – с несколькими общими объектами.
Совет. Можно ограничить количество данных, которые данный URL имеет право поместить на ваш жесткий диск посредством Flash Player. Щелкнув правой кнопкой мыши в окне открытого SWF и выбрав в меню Settings, перейдите в открывшемся окне настроек на вкладку

Примечание На прилагаемом к книге CD-ROM, в папке этого урока, имеется бонусный файл – highscorelist.highScoreList, описанный в этом файле. Среди прочего, здесь можно отсортировать список по возрастанию или убыванию, удалить список, начать новый, исправить сущестующий счет в списке и добавить новый.
В этом упражнении мы создадим журнал, сохраняющий текстовые записи в виде массива в общем объекте.
Как видите, здесь лишь один кадр и четыре слоя, которые называются в соответствии с их содержимым. На сцене имеется два текстовых поля для отображения информации. Большое поле в центре, journalBody, будет содержать саму запись. Меньшее поле в нижней части экрана, entryNumber, будет отображать номер текущей записи по журналу. Слой Buttons содержит кнопки навигации – Prev, Next, New и Save.

Это приложение будет позволять вводить новую запись, сохранять ее, просматривать уже имеющиеся записи.
myJournal = SharedObject.getLocal("JournalObject");
Эта строка создает ссылку на общий объект JournalObject. Теперь во всех скриптах этого фильма, обращаясь к myJournal, мы будем на самом деле иметь дело с общим объектом под названием JournalObject.
if (myJournal.data.journal == undefined) {
myJournal.data.journal = [];
}
Этот оператор проверяет, имеется ли в общем объекте массив с именем . Если такого массива нет ( ), выполняется действие, создающее его.
Примечание Как только массив создан, он, после выхода из фильма или сохранения общего объекта, автоматически становится частью общего объекта.
Массив будет иметь значение лишь при самом первом воспроизведении фильма. При последующих запусках фильма массив уже будет существовать, и это действие будет игнорироваться.
Совет. Хорошая идея – проверять данные в общем объекте на значение . Это позволит присвоить им начальные стандартные значения, если фильм воспроизводится пользователем впервые.
function displayEntry(num) {
_root.entryNumber.text = num;
_root.journalBody.text = myJournal.data.journal[num - 1];
}
Эта функция устанавливает значения двух текстовых полей – entryNumber и journalBody – на основе значения num. Например, если при вызове функции num имеет значение 1, в текстовом поле entryNumber отобразится "1" (номер текущей записи журнала). Во второй строке значение num используется для определения элемента массива (из общего объекта), который должен быть отображен в текстовом поле journalBody. Если num имеет значение 1, то эта строка скрипта расшифруется так:
_root.journalBody.text = myJournal.data.journal[1 - 1];
или
_root.journalBody.text = myJournal.data.journal[0];
Почему здесь из num вычитается единица? Дело в том, что первая запись журнала ("1" в поле entryNumber ) – это нулевой элемент массива . Конечно, можно было бы показать для первой записи номер "0", но это было бы как-то не совсем привычно. Поэтому запомните этот принцип сопоставления номеров записей и индексов элементов массива (запись с номером "3" – это элемент массива с индексом 2, и так далее).
displayEntry(myJournal.data.journal.length);
Этот вызов функции находится в кадре 1, и значит, будет выполнен, как только начнется воспроизведение фильма. Вызывается функция displayEntry() (которую мы описали на предыдущем шаге) с передачей ей в качестве параметра значения свойства length массива из общего объекта. В результате на экране будет отображена последняя запись, сделанная пользователем в предыдущем сеансе фильма. Если, к примеру, в массиве имеется три записи, функции displayEntry() будет передано значение 3, и на экране будет показана третья запись журнала. Если же массив создан только что (как описано а шаге 3), он будет содержать единственную, пустую, запись – длина массива будет равна 1, и это значение станет аргументом функции.
function save() {
var num = Number(_root.entryNumber.text) - 1;
myJournal.data.journal[num] = _root.journalBody.text;
myJournal.data.flush();
}
Мы уже упоминали, что при выходе из фильма данные сохраняются в общий объект автоматически. А с помощью метода можно
Первая строка функции создает num. Значение этой переменной определяется так: значение, отображенное в текстовом поле entryNumber, минус один. Для уверенности в том, что num получит числовое, а не текстовое, значение, использована функция Number(). Значение num используется в следующей строке – в качестве индекса элемента массива, соответствующего текущей записи журнала. Как мы упоминали на шаге 4, число, отображенное в поле entryNumber (номер записи), на единицу больше, чем индекс соответствующего элемента массива; поэтому и вычитается единица в первой строке.
Итак, вторая строка текст, отображенный в поле journalBody. Как всегда, возьмем для иллюстрации пример. Допустим, что номер текущей записи (показанный в поле entryNumber ) – 9. При вызове данной функции num получит значение 8 (девять минус один). Вторая строка тогда получится такой:
myJournal.data.journal[8] = _root.journalBody.text;
Тем самым текст из поля journalBody будет записан в элемент с индексом 8 массива . Еще раз повторим, что текущий номер записи – 9, а индекс соответствующего элемента массива – 8. Таким образом, если 8-й элемент массива был до этого пустым ( ), в него будет записан текст; если этот элемент уже содержал текст, этот текст будет перезаписан (измененным или тем же самым текстом).

Последнее действие в функции с помощью метода принудительно сохраняет на жестком диске пользователя общий объект вместе с данными – в нашем случае это все записи, имеющиеся в массиве .
function newEntry() {
_root.entryNumber.text = myJournal.data.journal.length + 1;
_root.journalBody.text = undefined;
Selection.setFocus("_root.journalBody");
}
Первое действие в этой функции устанавливает номер текущей записи журнала (текст в поле entryNumber ) – длина массива плюс один. Так, например, если в массиве две записи, он имеет длину 2. В результате добавления единицы в текстовом поле entryNumber будет отображено "3". Таким образом, все новые записи будут добавляться в конец массива. Два последних действия этой функции очищают текстовое поле journalBody и устанавливают в него фокус, так что пользователь может сразу начать вводить свою новую запись. Чтобы все стало понятнее, давайте рассмотрим работу данной функции во взаимодействии с функцией save(), которую мы создали на предыдущем шаге.
Предположим, в массиве имеется две записи. Эти записи хранятся в элементах массива с индексами 0 и 1, длина массива ( length ) равна 2. При выполнении данной функции в текстовом поле entryNumber отобразится "3" (свойство length массива плюс один), текстовое поле journalBody пусто. Теперь пользователь вводит в это поле текст и нажимает кнопку Save – происходит вызов функции save(). Эта функция вычитает единицу из числа, отображенного в поле entryNumber, и в итоге помещает текст из поля journalBody в элемент с индексом 2 массива . Теперь массив содержит три записи – в элементах с индексами 0, 1 и 2, и его длина ( length ) равна 3. Если теперь вновь вызвать функцию newEntry(), процесс повторится.
function nextEntry () {
var num = Number(_root.entryNumber.text) + 1;
if (num > myJournal.data.journal.length) {
num = myJournal.data.journal.length;
}
displayEntry(num);
}
Эта функция отображает на экране следующую запись из имеющихся в массиве. Первым делом присваивается значение переменной num – число, отображенное в поле entryNumber плюс один. Далее, чтобы не случилось попытки отображения несуществующей записи, значение num сравнивается с общим числом записей, имеющихся в массиве (свойство length массива). Если значение num оказалось больше, выполняется действие в операторе if, присваивающее переменной num значение свойства length массива – это приведет к тому, что на экране будет отображена последняя запись из массива. Последнее действие – вызов функции displayEntry() с передачей ей значения num. В результате на экран будет выведена нужная запись (следующая либо последняя).
function previousEntry() {
var num = Number(_root.entryNumber.text) - 1;
if (num < 1) {
num = 1;
}
displayEntry(num);
}
Эта функция похожа на предыдущую. Первым делом num получает значение, равное номеру текущей записи минус один. Оператор if проверяет, чтобы не произошло попытки вывести на экран запись с номером меньше 1. Рассмотрим на примере, как это работает.
Предположим, в данный момент на экране отображена запись номер 6. При вызове данной функции num получает значение 5 (шесть минус один); затем оператор if проверяет, чтобы значение num было не меньше 1. В данном случае это не так, поэтому действие внутри оператора if игнорируется и вызывается функция displayEntry() с передачей ей в качестве аргумента значения 5 – на экран выводится пятая запись журнала.
Теперь допустим, что на экране – запись номер 1. Переменная num получает значение 0. Это меньше 1, поэтому оператор if присваивает num значение 1. Первая запись и так уже была выведена на экран, поэтому внешне не происходит никаких изменений. Как уже было сказано, этот механизм предотвращает попытки вывода на экран записей с номерами меньше 1, поскольку таковых попросту не может быть.
on (release) {
newEntry();
}
Когда пользователь нажмет эту кнопку, будет вызвана функция newEntry(), которая на единицу увеличит номер текущей записи и очистит поле journalBody, подготовив его для ввода текста новой записи.
on (release) {
save();
}
Когда пользователь нажмет эту кнопку, будет вызвана функция save(), в результате либо текст из поля journalBody либо заменит существующую запись, либо будет создана новая запись в массиве (как описано на шаге 6).
on (release) {
previousEntry();
}

Вызов функции previousEntry() приведет к выводу на экран записи, номер которой на единицу меньше номера текущей записи.
on (release) {
nextEntry();
}
Скрипт просто вызывает функцию nextEntry() при нажатии данной кнопки. На экран будет выведена следующая "по списку" запись журнала.
После перезапуска фильма общий объект будет загружен с вашего жесткого диска (как описано в шагах 2 и 3), и вы сможете просматривать сохраненные данные, пользуясь кнопками Prev и Next.
В этом уроке вы изучили основы использования общих объектов – их создание, сохранение в них данных и получение этих данных.
Общие объекты хороши для сохранения таких данных:
x, y, alpha, поворот) элементов фильмаДля получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.