Кінцеві автомати в JavaScript. Частина 1: Розробимо віджет (исходники), Різне, Програмування, статті

Протягом декількох років web-дизайнери без особливого пожвавлення використовували інтерпретатори JavaScript в популярних web-браузерах, щоб поліпшити зовнішній вигляд своїх web-сайтів. Найчастіше для цього вони копіювали короткі фрагменти коду в свої web-сторінки. Зараз же, завдяки недавньому поширенню технологій AJAX, інженери з програмного забезпечення стали, крім того, використовувати JavaScript для розробки нового покоління додатків, які виконуються в web-браузері. Оскільки розмір додатків на основі браузерів стає все більше, то для них все частіше потрібні ті ж шаблони проектування і дисципліна розробки, які характерні для інших середовищ виконання.


Програми на базі браузерів виконуються в середовищі реального часу, в якій події миші, клавіатури, таймера, мережі і програм можуть відбутися в будь-який момент часу. Коли поведінка керованої подіями програми залежить від порядку, в якому відбуваються події, написання такої програми стає дуже заплутаним, а значить, і більш складним для налагодження та внесення змін. Інженери з програмного забезпечення давно використовують кінцеві автомати в якості організуючого принципу при розробці керованих подіями програм.


Дисципліна, яка диктується кінцевими автоматами, надає проекту строгість, замінюючи заплутану логіку простими таблицями, в результаті програми стають простіше в реалізації і в тестуванні. За традицією, кінцеві автомати вважаються корисними в розробці таких несхожих програм, як мережеві драйвери і компілятори. В рівній мірі вони можуть бути корисні при розробці додатків на базі браузерів.


У цій статті вам буде запропоновано розробити просте додаток-кінцевий автомат в якості вправи, що дозволяє вивчити деякі особливості мови JavaScript:


Ці функції надають лаконічний і компактний спосіб організувати дії для подій і переходів між станами, а також витончений спосіб впоратися з відмінностями між моделями обробки подій в браузерах.


Приклад програми, Поступово з’являється і поступово зникає підказка – це більш досконалий елемент, ніж вбудовані підказки більшості браузерів. Підказки, створені за допомогою віджета Fading Tooltip (Поступово з’являється і зникає підказка) використовують анімацію, щоб поступово з’являтися, а потім поступово зникати, замість того, щоб раптово вискакувати і раптово зникати, крім того, вони переміщаються слідом за курсором. Шаблон кінцевого автомата, який використовується для розробки цієї поведінки, робить його логіку прозорою. Особливості мови JavaScript, що використовується для реалізації програми, роблять вихідний код компактним та ефективним.


У цій статті показано, як спроектувати поведінку анімованого віджета за допомогою табличного і графічного представлення кінцевого автомата. У наступних статтях серії мова піде про те, як реалізувати табличне представлення кінцевого автомата на мові JavaScript, і що робити з практичними проблемами тестування реалізації віджета в популярних браузерах.


Звичайні підказки


Більшість сучасних програм із графічним інтерфейсом можуть короткочасно відображати маленькі текстові вікна, що містять корисні визначення, інструкції або рекомендації, коли курсор зупиняється над деякими візуальними елементами управління, такими як кнопка, поле вибору або поле введення. Ці корисні текстові вікна отримали назву “balloon help” (спливаючі пояснення) в ранніх системах Apple. У деяких продуктах IBM вони називалися infopops (спливаючій інформацією), а в деяких продуктах Microsoft – ScreenTips (екранними підказками). У цій статті використовується більш загальний термін підказка.


Такі популярні web-браузери, як Netscape Navigator, Microsoft Internet Explorer, Opera і Mozilla Firefox відображають підказки для будь-якого HTML-елемента, який має атрибут title. Наприклад, в лістингу 1 показано три HTML-елемента з атрибутами title.


Лістинг 1. HTML-код для відображення підказок браузером





Here are some
<span title=”Move your cursor a bit to the right, please.”>
fields with built-in tooltips
</span>:
<input type=”text”
title=”Type your bank account and PIN numbers here, please …”
size=25>
<input type=”button”
title=”Go ahead. Press it. What”s the harm? Trust me.”
value=”Press this button”>

Сторінка прикладів показує, як ваш браузер інтерпретує HTML-елементи з атрибутом title. Зверніть увагу, що підказки з’являються і зникають, коли ви переміщаєте курсор над елементами. Текстові вікна містять простий текст без якого-небудь форматування або стилю. Вони з’являються після короткої паузи в переміщенні курсора і раптово зникають або після закінчення деякого довільного часу, або після того, як курсор зміститься з HTML-елемента, або після натискання будь-якої клавіші. Браузер ніколи не відображає більш одного текстового вікна за один раз. Вид і поведінку цих підказок жорстко вбудовані в ваш браузер; змінити їх не можна.


Більш досконалі підказки


Вбудовані підказки мають багато можливостей для поліпшень, а останні версії популярних браузерів надають всі вихідні інгредієнти для створення більш досконалих підказок. TML-елемент Division створює текстове вікно, яке можна розташувати в будь-якому вікні браузера. Майже будь-який аспект зовнішнього вигляду цього вікна можна визначити за допомогою каскадних таблиць стилів (CSS). Переміщення курсора, запрограмовані на мові JavaScript, можуть запускати різні дії для будь-яких видимих ​​елементів у вікні браузера. Для організації послідовності цих дій можна програмувати таймери.


На сторінці прикладів показані також деякі HTML-елементи з більш досконалими підказками. Якщо у вас остання версія одного з популярних браузерів, ви можете порівняти досконаліші підказки з вбудованими підказками:





 



Якщо у вас застарілий браузер, то ви, можливо, не зможете побачити всі аспекти цієї поведінки. Наприклад, в браузерах Opera до версії 9 підказки просто з’являються і зникають, замість того, щоб робити це поступово, тому що в Opera порівняно пізно була додана реалізація властивості стилю opacity (Непрозорість).
 


Це вдосконалене поведінку і зовнішній вигляд не є тільки косметичним поліпшенням; воно сприяє підвищенню зручності використання. Коли користувачі потрапляють на сторінки, насичені тисячами елементів, вони можуть не помітити підказки, яка раптово з’являється на екрані. Людське зір, який особливо чутливо до рухомих об’єктів, з більшою ймовірністю помітить підказку, яка поступово з’являється в полі зору і рухається разом з курсором, навіть якщо увагу розгубленого користувача сфокусовано в іншому місці сторінки. Зображення, форматування і стильове оформлення можуть більш ефективно підносити інформацію, ніж звичайний текст. Крім того, всі параметри цих досконаліших підказок є налаштованим.


Далі в статті розповідається про проектування віджету зникаючої підказки FadingTooltip у вигляді кінцевого автомата. У наступних статтях серії буде розказано про те, як реалізувати і протестувати програму.


Кінцеві автомати


Кінцеві автомати моделюють поведінку, при якому реакції на майбутні події залежать від попередніх подій. Існує величезний пласт наукової літератури з цієї теми, але зручне робоче визначення дуже просте. Кінцевий автомат – це комп’ютерна програма, яка складається з:


Кінцеві автомати найбільш корисні в ситуаціях, в яких поведінка управляється багатьма різними типами подій, а реакція на певну подію залежить від послідовності попередніх подій. Події, які управляють кінцевими автоматами, можуть бути зовнішніми по відношенню до комп’ютера і виходити від клавіатури, миші, таймера або мережевої активності, або внутрішніми, що виходять від інших компонентів прикладної програми або від інших додатків.


Стани – це метод запам’ятовування попередніх подій, а переходи – метод організації реагування на майбутні події. Одне з подій має бути позначено як початковий стан. Може існувати також кінцевий стан, але це необов’язково, і у віджета FadingTooltip кінцевого стану немає.


Існує два найпоширеніших подання кінцевих автоматів:


Орієнтовані графи
Еліпси представляють стану, а стрілки між ними – переходи, над якими зазначені події та дії.
Двовимірні таблиці
Стовпці і рядки являють події і стани, а осередки містять дії і переходи.

Ці уявлення еквівалентні, але роблять акцент на різних аспектах проекту. Обидва подання корисні і використовуються в даній статті.

Розробка керованих подіями програм за допомогою кінцевих автоматів трохи складніше звичайного процедурного програмування; така розробка потребує більше дисципліни загалом і більше проектної роботи зокрема. При хорошому виконанні в результаті можна отримати більш простий програмний код, меншу тривалість тестування і полегшене супровід. Незважаючи на це, складність підходу кінцевих автоматів виправдана не для всіх керованих подіями програм. Якщо, наприклад, діапазон подій невеликий, або дії, що запускаються подіями, завжди одні й ті ж, додаткові витрати ресурсів на розробку можуть не виправдатися.


Кінцеві автомати та середу виконання


Кінцеві автомати управляються подіями і потребують способі прив’язки до подій, про які йде мова, в їхньому середовищі виконання. Такі прив’язки, які називаються обробниками подій, представляють собою дуже невеликі фрагменти коду, вставлені в середу виконання так, щоб вони могли виконуватися при настанні конкретного події. Для виконання обробники подій потребують наступної базової інформації:


Мова JavaScript чудово підходить для побудови керованих подіями кінцевих автоматів. Насправді, JavaScript, можливо, підходить для цього навіть занадто добре – в мові можливі три різні способи прив’язки подій. Кожна з цих моделей подій не відрізняється складністю, однак, щоб програми могли виконуватися в будь-якому популярному браузері, вони повинні реалізувати всі три моделі. Контекст події передається безпосередньо обробникам подій за двома з цих моделей подій; для ще однієї моделі охопити контекст події обробником цієї події дозволяють замикання функцій JavaScript.


JavaScript надає об’єктну модель, яка може здатися дещо незвичайною програмістам на Java і C + +, тим не менш, вона повністю придатна для програмування змінних і методів кінцевих автоматів. Крім того, асоціативні масиви JavaScript дозволяють безпосередньо програмувати подання кінцевих автоматів у вигляді двовимірних таблиць.


Методична розробка поведінки


Основні інгредієнти для кінцевого автомата – це події, на які він реагує, і стани, в яких він очікує між подіями. Проект повинен передбачати всі можливі події для всіх можливих станів:


Почнемо проектування процедури з графа на малюнку 1, На якому стану показані у вигляді еліпсів, а переходи – у вигляді стрілок, що з’єднують еліпси, і закінчимо таблицею, показаної на малюнку 4, В якій події і стани перераховуються відповідно в заголовках рядків і стовпців. У кожній клітинці таблиці перераховані дії, які повинні виконуватися, коли в певному стані відбудеться певна подія, або показано, що дана подія не може настати в даному стані.


Звичайно потрібно кілька ітеративних повторень цієї проектної процедури, щоб отримати граф або таблицю без помилок. Якщо кінцевий автомат має багато подій і станів, то процедура може бути досить стомлюючої, тому від розробника потрібна певна дисципліна, щоб методично працювати над кожною клітинкою таблиці в процесі кожної ітерації. Завдяки цьому ви зможете продумати, яка поведінка бажаєте бачити у всіх можливих ситуаціях. Можливо, ви побачите шляхи для подальшого удосконалення або деталізації поведінки, можливо, відкриєте, що знадобиться більше станів, ніж передбачалося спочатку, а може бути, доведеться перетасувати дії між осередками, щоб визначити правильну поведінку в кожній ситуації.


Ця методична процедура проектування кінцевих автоматів виправдана, хоча і втомлює. Заповнена таблиця, яку ви бачите на малюнку 4, Показує всю логіку поведінки і може бути переведена безпосередньо в програмний код (див. вихідний код actionTransitionFunctions).


Про можливості JavaScript


Для розробки віджету FadingTooltip потрібно познайомитися з деякими можливостями мови JavaScript. У дусі проектування зверху вниз, я коротко змалюю тут основні ідеї, а подробиці реалізації виділю в наступній статті цієї серії.


Всі популярні браузери здатні передавати події коду JavaScript, коли курсор проходить над HTML-елементом на web-сторінці. Ці події називаються mouseover, mousemove і mouseout; назви показують, що курсор переміщується над, рухається в межах і зміщується за межі HTML-елемента. Браузер передає поточні координати положення курсору разом з цими подіями. При настанні події програма на JavaScript може динамічно створювати HTML-елементи Division, вносити в них текст, зображення і розмітку, і поміщати їх поруч з курсором.


Браузери не мають вбудованих функцій поступового появи і зникнення, але їх можна імітувати, змінюючи ступінь прозорості (ну, насправді, непрозорості, яка протилежна прозорості) елемента Division з плином часу.


У JavaScript є два типи таймерів: разові таймери, які генерують подія timeout після закінчення встановленого часу, і тікери, які генерують події timetick періодично. Для віджету FadingTooltip нам знадобляться обидва цих типу.


Малюємо начерк графа стану


Почнемо проектування з розгляду базового поведінки, яке потрібно запрограмувати для віджету FadingTooltip. При проходженні курсора над певним HTML-елементом нам потрібно, щоб віджет чекав зупинки курсора над цим елементом. Якщо курсор зупинився над елементом, то віджет повинен, поступово підсилюючи, вивести підказку на екран, мить потримати її на екрані, а потім, поступово послаблюючи, видалити її з екрану.


Нашому кінцевому автомату доведеться реагувати на такі події:


Ми створимо деякі стану, в яких кінцевий автомат чекатиме між подіями. Давайте назвемо початковий стан віджету Inactive; це такий стан, при якому він буде чекати активації подією mouseover. У стані Pause віджет буде чекати, поки подія timeout не покаже, що курсор затримався над HTML-елементом на досить тривалий час. Потім, в стані FadeIn, віджет буде чекати, поки виконується анімацію ефекту поступового появи подіями timetick, і далі, в стані Display, очікувати настання наступної події timeout. Нарешті, в стані FadeOut віджет буде чекати, поки виконується анімацію ефекту поступового зникнення наступними подіями timetick. Після цього віджет повертається в стан Inactive, в якому він буде чекати наступного події mouseover.


На малюнку 1 цей процес відображений у вигляді графа, на якому стану відображені у вигляді еліпсів, переходи у вигляді з’єднують ці еліпси стрілок, а події – як написи над стрілками. Подвійний обведенням виділений еліпс вихідного стану.


Рисунок 1. Початковий нарис графа станів

Складання списку змінних стану


Після складання таблиці і графа стану корисно переглянути їх ще раз, щоб скласти список змінних, які автомату потрібно буде запам’ятовувати між подіями, щоб він міг виконувати родинні дії в різних осередках. Нашому кінцевому автомату знадобляться змінні стану для всього, що перераховано в лістингу 2.


Лістинг 2. Початковий список змінних станів





currentState string value equal to one of the state names
currentTimer pointer to timer object, obtained when set, used to cancel
currentTicker pointer to ticker object, obtained when started, used to cancel
currentOpacity float that varies from 0.0 (invisible) to 1.0 (fully visible)
lastCursorPosition floats obtained from cursor events, used when an HTML Division
element is created
tooltipDivision pointer to HTML Division element, set when created, used when
faded, moved, or deleted

Хоча змінні JavaScript є нетипізований, значення, які вони містять, типізовані (тобто, значення якого типу можуть бути присвоєні будь змінної). У цьому ж дусі я виберу імена для змінних стану і, в примітках, вкажу типи, які я збираюся ним привласнити.


Все готово для реалізації проекту


Тепер у нас є заповнена таблиця станів і список змінних станів, і ми готові реалізувати кінцевий автомат. Не пропустіть наступну статтю, в якій розповідається про те, як це зробити. Однак не забувайте, що розробка – це ітеративний процес, можливо, доведеться повернутися до фази проектування …


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*