From 497c9fd2d380d53fa5626f3a0042bd5ceee29fd4 Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sun, 5 Mar 2017 01:06:09 +0300 Subject: [PATCH] up --- .../1-why-return-false-fails/solution.md | 13 +- .../1-why-return-false-fails/task.md | 10 +- .../2-catch-link-navigation/solution.md | 29 +- .../solution.view/index.html | 21 +- .../source.view/index.html | 5 +- .../2-catch-link-navigation/task.md | 13 +- .../3-image-gallery/solution.md | 55 +- .../3-image-gallery/solution.view/index.html | 49 +- .../3-image-gallery/source.view/index.html | 33 +- .../3-image-gallery/task.md | 15 +- .../7-default-browser-action/article.md | 137 ++--- .../menu.view/index.html | 5 +- .../menu.view/menu.js | 4 +- 2-ui/2-events/8-dispatch-events/article.md | 475 +++++------------- 14 files changed, 268 insertions(+), 596 deletions(-) diff --git a/2-ui/2-events/7-default-browser-action/1-why-return-false-fails/solution.md b/2-ui/2-events/7-default-browser-action/1-why-return-false-fails/solution.md index 5bf3d48d..2862e600 100644 --- a/2-ui/2-events/7-default-browser-action/1-why-return-false-fails/solution.md +++ b/2-ui/2-events/7-default-browser-action/1-why-return-false-fails/solution.md @@ -1,16 +1,16 @@ -Дело в том, что обработчик из атрибута `onclick` делается браузером как функция с заданным телом. +When the browser reads the `on*` attribute like `onclick`, it creates the handler from its content. -То есть, в данном случае он будет таким: +For `onclick="handler()"` the function will be: ```js function(event) { - handler() // тело взято из атрибута onclick + handler() // the content of onclick } ``` -При этом возвращаемое `handler` значение никак не используется и не влияет на результат. +Now we can see that the value returned by `handler()` is not used and does not affect the result. -Рабочий вариант: +The fix is simple: ```html run -w3.org +the browser will go to w3.org ``` -По замыслу, переход на `w3.org` при клике должен отменяться. Однако, на самом деле он происходит. +The browser follows the URL on click, but we don't want it. -В чём дело и как поправить? \ No newline at end of file +How to fix? diff --git a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.md b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.md index a10433d7..25079cb8 100644 --- a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.md +++ b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.md @@ -1,28 +1,5 @@ -Это -- классическая задача на тему делегирования. +That's a great use of the event delegation pattern. -В реальной жизни, мы можем перехватить событие и создать AJAX-запрос к серверу, который сохранит информацию о том, по какой ссылке ушел посетитель. - -Мы перехватываем событие на `contents` и поднимаемся до `parentNode` пока не получим `A` или не упремся в контейнер. - -```js -contents.onclick = function(evt) { - var target = evt.target; - - function handleLink(href) { - var isLeaving = confirm('Уйти на ' + href + '?'); - if (!isLeaving) return false; - } - - while (target != this) { - if (target.nodeName == 'A') { -*!* - return handleLink(target.getAttribute('href')); // (*) -*/!* - } - target = target.parentNode; - } -}; -``` - -В строке `(*)` используется атрибут, а не свойство `href`, чтобы показать в `confirm` именно то, что написано в HTML-атрибуте, так как свойство может отличаться, оно обязано содержать полный валидный адрес. +In real life instead of asking we can send a "logging" request to the server that saves the information about where the visitor left. Or we can load the content and show it right in the page (if allowable). +All we need is to catch the `contents.onclick` and use `confirm` to ask the user. A good idea would be to use `link.getAttribute('href')` instead of `link.href` for the URL. See the solution for details. diff --git a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.view/index.html b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.view/index.html index fccc602c..90aecd9d 100755 --- a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.view/index.html +++ b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/solution.view/index.html @@ -16,28 +16,25 @@
#contents

- Как насчет почитать Википедию, или посетить W3.org и узнать про современные стандарты? + How about to read Wikipedia or visit W3.org and learn about modern standards?

+ - - \ No newline at end of file + diff --git a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/source.view/index.html b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/source.view/index.html index c606819f..b88834c9 100755 --- a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/source.view/index.html +++ b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/source.view/index.html @@ -16,10 +16,9 @@
#contents

- Как насчет почитать Википедию, или посетить W3.org и узнать про современные стандарты? + How about to read Wikipedia or visit W3.org and learn about modern standards?

- - \ No newline at end of file + diff --git a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/task.md b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/task.md index 18fc94b6..c03e5f8e 100644 --- a/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/task.md +++ b/2-ui/2-events/7-default-browser-action/2-catch-link-navigation/task.md @@ -2,16 +2,15 @@ importance: 5 --- -# Поймайте переход по ссылке +# Catch links in the element -Сделайте так, чтобы при клике на ссылки внутри элемента `#contents` пользователю выводился вопрос о том, действительно ли он хочет покинуть страницу и если он не хочет, то прерывать переход по ссылке. +Make all links inside the element with `id="contents"` ask the user if he really wants to leave. And if he doesn't then don't follow. -Так это должно работать: +Like this: [iframe height=100 border=1 src="solution"] -Детали: - -- Содержимое `#contents` может быть загружено динамически и присвоено при помощи `innerHTML`. Так что найти все ссылки и поставить на них обработчики нельзя. Используйте делегирование. -- Содержимое может содержать вложенные теги, *в том числе внутри ссылок*, например, `...`. +Details: +- HTML inside the element may be loaded or regenerated dynamically at any time, so we can't find all links and put handlers on them. Use the event delegation. +- The content may have nested tags. Inside links too, like `...`. diff --git a/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.md b/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.md index d0db6ffd..5ff60b5c 100644 --- a/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.md +++ b/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.md @@ -1,54 +1 @@ -Решение состоит в том, чтобы добавить обработчик на контейнер `#thumbs` и отслеживать клики на ссылках. - -Когда происходит событие, обработчик должен изменять `src` `#largeImg` на `href` ссылки и заменять `alt` на ее `title`. - -Код решения: - -```js -var largeImg = document.getElementById('largeImg'); - -document.getElementById('thumbs').onclick = function(e) { - var target = e.target; - - while (target != this) { - - if (target.nodeName == 'A') { - showThumbnail(target.href, target.title); - return false; - } - - target = target.parentNode; - } - -} - -function showThumbnail(href, title) { - largeImg.src = href; - largeImg.alt = title; -} -``` - -**Предзагрузка картинок** - -Для того, чтобы картинка загрузилась, достаточно создать новый элемент `IMG` и указать ему `src`, вот так: - -```js -var imgs = thumbs.getElementsByTagName('img'); -for (var i = 0; i < imgs.length; i++) { - var url = imgs[i].parentNode.href; - -*!* - var img = document.createElement('img'); - img.src = url; -*/!* -} -``` - -Как только элемент создан и ему назначен `src`, браузер сам начинает скачивать файл картинки. - -При правильных настройках сервера как-то использовать этот элемент не обязательно -- картинка уже закеширована. - -**Семантичная верстка** - -Для списка картинок используется `DIV`. С точки зрения семантики более верный вариант -- список `UL/LI`. - +The solution is to assign the handler to the container and track clicks. If a click is on the `` link, then change `src` of `#largeImg` to the `href` of the thumbnail. diff --git a/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.view/index.html b/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.view/index.html index 8b6bc894..e0de1563 100755 --- a/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.view/index.html +++ b/2-ui/2-events/7-default-browser-action/3-image-gallery/solution.view/index.html @@ -2,69 +2,48 @@ - Галерея + Gallery -

Large image

+

Large image

- - \ No newline at end of file + diff --git a/2-ui/2-events/7-default-browser-action/3-image-gallery/source.view/index.html b/2-ui/2-events/7-default-browser-action/3-image-gallery/source.view/index.html index cb22595c..c488ddcc 100755 --- a/2-ui/2-events/7-default-browser-action/3-image-gallery/source.view/index.html +++ b/2-ui/2-events/7-default-browser-action/3-image-gallery/source.view/index.html @@ -2,24 +2,33 @@ - Галерея + Gallery -

Large image

+

Large image

-
- - - - - - -
+ - - \ No newline at end of file + diff --git a/2-ui/2-events/7-default-browser-action/3-image-gallery/task.md b/2-ui/2-events/7-default-browser-action/3-image-gallery/task.md index efc204e1..f7571cc8 100644 --- a/2-ui/2-events/7-default-browser-action/3-image-gallery/task.md +++ b/2-ui/2-events/7-default-browser-action/3-image-gallery/task.md @@ -2,19 +2,12 @@ importance: 5 --- -# Галерея изображений +# Image gallery -Создайте галерею изображений, в которой основное изображение изменяется при клике на уменьшенный вариант. +Create an image gallery where the main image changes by the click on a thumbnail. -Результат должен выглядеть так: +Like this: [iframe src="solution" height=600] -Для обработки событий используйте делегирование, т.е. не более одного обработчика. - -P.S. Обратите внимание -- клик может быть как на маленьком изображении `IMG`, так и на `A` вне него. При этом `event.target` будет, соответственно, либо `IMG`, либо `A`. - -Дополнительно: - -- Если получится -- сделайте предзагрузку больших изображений, чтобы при клике они появлялись сразу. -- Всё ли в порядке с семантической вёрсткой в HTML исходного документа? Если нет -- поправьте, чтобы было, как нужно. +P.S. Use event delegation. diff --git a/2-ui/2-events/7-default-browser-action/article.md b/2-ui/2-events/7-default-browser-action/article.md index 49fc5dfb..e17551a0 100644 --- a/2-ui/2-events/7-default-browser-action/article.md +++ b/2-ui/2-events/7-default-browser-action/article.md @@ -1,145 +1,116 @@ -# Действия браузера по умолчанию +# Browser actions -Многие события автоматически влекут за собой действие браузера. +Many events automatically lead to browser actions. -Например: +For instance: -- Клик по ссылке инициирует переход на новый URL. -- Нажатие на кнопку "отправить" в форме -- отсылку ее на сервер. -- Двойной клик на тексте -- инициирует его выделение. +- A click on a link -- initiates going to its URL. +- A click on submit button inside a form -- initiates its submission to the server. +- Pressing a mouse button over a text and moving it -- selects the text. -Если мы обрабатываем событие в JavaScript, то зачастую такое действие браузера нам не нужно. К счастью, его можно отменить. +If we handle an event in JavaScript, often we don't want browser actions. Fortunately, it can be prevented. [cut] -## Отмена действия браузера +## Preventing browser actions -Есть два способа отменить действие браузера: +There are two ways to tell the browser we don't want it to act: -- **Основной способ -- это воспользоваться объектом события. Для отмены действия браузера существует стандартный метод `event.preventDefault()`.** -- Если же обработчик назначен через `onсобытие` (не через `addEventListener`), то можно просто вернуть `false` из обработчика. +- The main way is to use the `event` object. There's a method `event.preventDefault()`. +- If the handler is assigned using `on` (not by `addEventListener`), then we can just return `false` from it. -В следующем примере при клике по ссылке переход не произойдет: +In the example below there a click to links don't lead to URL change: ```html autorun height=60 no-beautify -Нажми здесь -или -здесь +Click here +or +here ``` -```warn header="Возвращать `true` не нужно" -Обычно значение, которое возвращает обработчик события, игнорируется. +```warn header="Not necessary to return `true`" +The value returned by an event handler is usually ignored. -Единственное исключение -- это `return false` из обработчика, назначенного через `onсобытие`. +The only exception -- is `return false` from a handler assigned using `on`. -Иногда в коде начинающих разработчиков можно увидеть `return` других значений. Но они не нужны и никак не обрабатываются. +In all other cases, the return is not needed and it's not processed anyhow. ``` -### Пример: меню +### Example: the menu -Рассмотрим задачу, когда нужно создать меню для сайта, например такое: +Consider a site menu, like this: ```html ``` -Данный пример при помощи CSS может выводиться так: +Here's how it looks with some CSS: [iframe height=70 src="menu" link edit] -HTML-разметка сделана так, что все элементы меню являются не кнопками, а ссылками, то есть тегами ``. +Menu items are links ``, not buttons. There are several benefits, for instance: -Это потому, что некоторые посетители очень любят сочетание "правый клик - открыть в новом окне". Да, мы можем использовать и ` + ``` +```smart header="event.isTrusted" +There is a way to tell a "real" user event from a script-generated one. + +The property `event.isTrusted` is `true` for events that come from real user actions and `false` for script-generated events. +``` + +## Bubbling example + +We can create a bubbling event with the name `"hello"` and catch it on `document`. + +All we need is to set `bubbles` to `true`: + +```html run no-beautify +

Hello from the script!

+ + +``` + +Notes: + +1. We must use `addEventListener` for our custom events, because `on` only exists for built-in events. +2. Must set `bubbles`, otherwise the event won't bubble up. + +The bubbling mechanics is the same for built-in (`click`) and custom (`hello`) events. There are also capturing and bubbling stages. + +## MouseEvent, KeyboardEvent and others + +Here's a short list of classes for UI Events from the [UI Event specification](https://www.w3.org/TR/uievents): + +- `UIEvent` +- `FocusEvent` +- `MouseEvent` +- `WheelEvent` +- `KeyboardEvent` +- ... + +We should use them instead of `new Event` if we want to create such events. For instance, `new MouseEvent("click")`. + +The right constructor allows to specify standard properties for that type of event. + +Like `clientX/clientY` for a mouse event: + +```js run +let event = new MouseEvent("click", { + bubbles: true, + cancelable: true, + clientX: 100, + clientY: 100 +}); + +*!* +alert(event.clientX); // 100 +*/!* +``` + +Please note: the generic `Event` constructor does not allow that. + +Let's try: + +```js run +let event = new Event("click", { + bubbles: true, // only bubbles and cancelable + cancelable: true, // work in the Event constructor + clientX: 100, + clientY: 100 +}); + +*!* +alert(event.clientX); // undefined, the unknown property is ignored! +*/!* +``` + +Technically, we can work around that by assigning directly `event.clientX=100` after creation. So that's a matter of convenience and following the rules. Browser-generated events always have the right type. + +The full list of properties for different UI events is in the specification, for instance [MouseEvent](https://www.w3.org/TR/uievents/#mouseevent). + +## Custom events + +For our own, custom events like `"hello"` we should use `new CustomEvent`. Technically [CustomEvent](https://dom.spec.whatwg.org/#customevent) is the same as `Event`, with one exception. + +In the second argument (object) we can add an additional property `detail` for any custom information that we want to pass with the event. + +For instance: + +```html run +

Hello for John!

+ + +``` + +The `detail` can be anything. Once again, technically we can assign any properties into a regular `Event` object after its creation. But `CustomEvent` clearly states that the event is not built-in, but our own. And reserves the special `detail` field, so that we can write to it safely, without conflicts with standard event properties. + + + + + + + ## Отмена действия по умолчанию На сгенерированном событии, как и на встроенном браузерном, обработчик может вызвать метод `event.preventDefault()`. Тогда `dispatchEvent` возвратит `false`. @@ -92,324 +211,9 @@ var event = new Event(тип события[, флаги]); ``` -```smart header="Как отличить реальное нажатие от скриптового?" -В целях безопасности иногда хорошо бы знать -- инициировано ли действие посетителем или это кликнул скрипт. -Единственный способ, которым код может отличить реальное нажатие от программного, является проверка свойства `event.isTrusted`. -Оно на момент написания статьи поддерживается IE и Firefox и равно `true`, если посетитель кликнул сам, и всегда `false` -- если событие инициировал скрипт. -``` -## Другие свойства событий - -При создании события браузер автоматически ставит следующие свойства: - -- `isTrusted: false` -- означает, что событие сгенерировано скриптом, это свойство изменить невозможно. -- `target: null` -- это свойство ставится автоматически позже при `dispatchEvent`. -- `type: тип события` -- первый аргумент `new Event`. -- `bubbles`, `cancelable` -- по второму аргументу `new Event`. - -Другие свойства события, если они нужны, например координаты для события мыши -- можно присвоить в объект события позже, например: - -```js no-beautify -var event = new Event("click", {bubbles: true, cancelable: false}); -event.clientX = 100; -event.clientY = 100; -``` - -## Пример со всплытием - -Сгенерируем совершенно новое событие `"hello"` и поймаем его на `document`. - -Всё, что для этого нужно -- это флаг `bubbles`: - -```html run no-beautify -

Привет от скрипта!

- - -``` - -Обратите внимание: - -1. Обработчик события `hello` стоит на `document`. Мы его поймаем на всплытии. -2. Вызов `event.preventDefault()` приведёт к тому, что `dispatchEvent` вернёт `false`. -3. Чтобы событие всплывало и его можно было отменить, указан второй аргумент `new Event`. - -Никакой разницы между встроенными событиями (`click`) и своими (`hello`) здесь нет, их можно сгенерировать и запустить совершенно одинаково. - -## Конструкторы MouseEvent, KeyboardEvent и другие - -Для некоторых конкретных типов событий есть свои, специфические, конструкторы. - -Вот список конструкторов для различных событий интерфейса которые можно найти в спецификации [UI Event](http://www.w3.org/TR/uievents/): - -- `UIEvent` -- `FocusEvent` -- `MouseEvent` -- `WheelEvent` -- `KeyboardEvent` -- `CompositionEvent` - -Вместо `new Event("click")` можно вызвать `new MouseEvent("click")`. - -**Специфический конструктор позволяет указать стандартные свойства для данного типа события.** - -Например, `clientX/clientY` для события мыши: - -```js run -var e = new MouseEvent("click", { - bubbles: true, - cancelable: true, - clientX: 100, - clientY: 100 -}); - -*!* -alert( e.clientX ); // 100 -*/!* -``` - -Это нельзя было бы сделать с обычным конструктором `Event`: - -```js run -var e = new Event("click", { - bubbles: true, - cancelable: true, - clientX: 100, - clientY: 100 -}); - -*!* -alert( e.clientX ); // undefined, свойство не присвоено! -*/!* -``` - -Обычный конструктор `Event` не знает про "мышиные" свойства, поэтому их игнорирует. - -Впрочем, использование конкретного конструктора не является обязательным, можно обойтись `Event`, а свойства записать в объект отдельно, после конструктора. Здесь это скорее вопрос удобства и желания следовать правилам. События, которые генерирует браузер, всегда имеют правильный тип. - -Полный список свойств по типам событий вы найдёте в спецификации, например для `MouseEvent`: [MouseEvent Constructor](http://www.w3.org/TR/uievents/#constructor-mouseevent). - -## Свои события - -Для генерации своих, нестандартных, событий, хоть и можно использовать конструктор `Event`, но существует и специфический конструктор [CustomEvent](http://www.w3.org/TR/dom/#customevent). - -Технически, он абсолютно идентичен `Event`, кроме небольшой детали: у второго аргумента-объекта есть дополнительное свойство `detail`, в котором можно указывать информацию для передачи в событие. - -Например: - -```html run -

Привет для Васи!

- - -``` - -Надо сказать, что никто не мешает и в обычное `Event` записать любые свойства. Но `CustomEvent` более явно говорит, что событие не встроенное, а своё, и выделяет отдельно "информационное" поле `detail`, в которое можно записать что угодно без конфликта со стандартными свойствами объекта. - -## Старое API для IE9+ - -Способ генерации событий, описанный выше, не поддерживается в IE11-, там нужен другой, более старый способ, описанный в стандарте [DOM 3 Events](http://www.w3.org/TR/DOM-Level-3-Events). - -В нём была предусмотрена [иерархия событий](http://www.w3.org/TR/DOM-Level-3-Events/#event-interfaces), с различными методами инициализации. - -Она поддерживается как современными браузерами, так и IE9+. Там используется немного другой синтаксис, но по возможностям -- всё то же самое, что и в современном стандарте. - -Можно использовать этот немного устаревший способ, если нужно поддерживать IE9+. Далее мы на его основе создадим полифилл. - -Объект события создаётся вызовом `document.createEvent`: - -```js -var event = document.createEvent(eventInterface); -``` - -Аргументы: - -- `eventInterface` -- это тип события, например `MouseEvent`, `FocusEvent`, `KeyboardEvent`. В [секции 5 DOM 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#events-module) есть подробный список, какое событие к какому интерфейсу относится. - -На практике можно всегда использовать самый общий интерфейс: `document.createEvent("Event")`. - -Далее событие нужно инициализировать: - -```js -event.initEvent(type, boolean bubbles, boolean cancelable); -``` - -Аргументы: - -- `type` -- тип события, например `"click"`. -- `bubbles` -- всплывает ли событие. -- `cancelable` -- можно ли отменить событие. - -Эти два кода аналогичны: - -```js -// современный стандарт -var event = new Event("click", { - bubbles: true, - cancelable: true -}); - -// старый стандарт -var event = document.createEvent("Event"); -event.initEvent("click", true, true); -``` - -Единственная разница -- старый стандарт поддерживается IE9+. - -Этот пример с событием `hello` будет работать во всех браузерах, кроме IE8-: - -```html run -

Привет от скрипта!

- - -``` - -````smart header="`initMouseEvent`, `initKeyboardEvent` и другие..." -У конкретных типов событий, например `MouseEvent`, `KeyboardEvent`, есть методы, которые позволяют указать стандартные свойства. - -Они называются по аналогии: `initMouseEvent`, `initKeyboardEvent`. - -Их можно использовать вместо базового `initEvent`, если хочется, чтобы свойства событий соответствовали встроенным браузерным. - -Выглядят они немного страшновато, например (взято из [спецификации](http://www.w3.org/TR/DOM-Level-3-Events/#idl-interface-MouseEvent-initializers)): - -```js -void initMouseEvent( - DOMString typeArg, // тип - boolean bubblesArg, // всплывает? - boolean cancelableArg, // можно отменить? - AbstractView ? viewArg, // объект window, null означает текущее окно - long detailArg, // свойство detail и другие... - long screenXArg, - long screenYArg, - long clientXArg, - long clientYArg, - boolean ctrlKeyArg, - boolean altKeyArg, - boolean shiftKeyArg, - boolean metaKeyArg, - unsigned short buttonArg, - EventTarget ? relatedTargetArg); -}; -``` - -Для инициализации мышиного события нужно обязательно указать *все* аргументы, например: - -```html run - - - -``` - -Браузер, по стандарту, может сгенерировать отсутствующие свойства самостоятельно, например `pageX`, но это нужно проверять в конкретных случаях, иногда это не работает или работает некорректно, так что лучше указать все. -```` - -## Полифилл CustomEvent - -Для поддержки `CustomEvent` в IE9+ можно сделать небольшой полифилл: - -```js -try { - new CustomEvent("IE has CustomEvent, but doesn't support constructor"); -} catch (e) { - - window.CustomEvent = function(event, params) { - var evt; - params = params || { - bubbles: false, - cancelable: false, - detail: undefined - }; - evt = document.createEvent("CustomEvent"); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - return evt; - }; - - CustomEvent.prototype = Object.create(window.Event.prototype); -} -``` - -Здесь мы сначала проверяем -- в IE9-11 есть `CustomEvent`, но его нельзя создать через `new`, будет ошибка. В этом случае заменяем браузерную реализацию на свою, совместимую. - -## Антистандарт: IE8- - -В совсем старом IE были "свои" методы `document.createEventObject()` и `elem.fireEvent()`. - -Пример с ними для IE8: - -```html run - - - -``` - -**При помощи `fireEvent` можно сгенерировать только встроенные события.** - -Если указать `"hello"` вместо `"onclick"` в примере выше -- будет ошибка. - -Параметры `bubbles` и `cancelable` настраивать нельзя, браузер использует стандартные для данного типа событий. - -Существуют полифиллы для генерации произвольных событий и для IE8-, но они, по сути, полностью подменяют встроенную систему обработки событий браузером. И кода это требует тоже достаточно много. - -Альтернатива -- фреймворк, например jQuery, который также реализует свою мощную систему работы с событиями, доступную через методы jQuery. ## Итого @@ -426,4 +230,3 @@ try { - Либо как явный и грубый хак, чтобы заставить работать сторонние библиотеки, в которых не предусмотрены другие средства взаимодействия. - Либо для автоматического тестирования, чтобы скриптом "нажать на кнопку" и посмотреть, произошло ли нужное действие. - Либо при создании своих "элементов интерфейса". Например, никто не мешает при помощи JavaScript создать из `
` красивый календарь и генерировать на нём событие `change` при выборе даты. Эту тему мы разовьём позже. -