Function event javascript что это
Перейти к содержимому

Function event javascript что это

  • автор:

Events in JavaScript

This articles shows how to handle events in JavaScript, such as a user clicking a button, and perform actions in response.

Introduction

Now you are comfortable with using CSS for styling and layout, and have taken your first stumbling steps with understanding variables, functions, methods, etc. in JavaScript, it is time to start using that knowledge to provide your site visitors with interactivity and dynamic behavior (such as dragging and dropping, animation, etc). Controlling events with JavaScript allows you to step into the role as Doctor Frankenstein and really give life to your creations!

But enough about the joys of JavaScript—this Web Standards Curriculum article will get practical, telling you what events are and how to make use of them on your pages.

Bear in mind that you can download the code example for this article and try it out for yourself.

What are events?

Events occur when some sort of interaction takes place in a web page. This can be the end user clicking on something, moving the mouse over a certain element or pressing down certain keys on the keyboard. An event can also be something that happens in the web browser, such as the web page completing the loading of a page, or the user scrolling or resizing the window.

Through the use of JavaScript, you can detect when certain events happen, and cause things to occur in response to those events.

How events work

When events happen to an HTML element in a web page, it checks to see if any event handlers are attached to it. If the answer is yes, it calls them in respective order, while sending along references and further information for each event that occurred. The event handlers then act upon the event.

There are two types of event order: event capturing and event bubbling.

Event capturing starts with the outer most element in the DOM and works inwards to the HTML element the event took place on and then out again. For example, a click in a web page would first check the HTML element for onclick event handlers, then the body element, and so on, until it reaches the target of the event.

Event bubbling works in exactly the opposite manner: it begins by checking the target of the event for any attached event handlers, then bubbles up through each respective parent element until it reaches the HTML element.

The evolution of events

In the early days of JavaScripting, we used event handlers directly within the HTML element, like this:

The problem with this approach is that it resulted in event handlers spread throughout the code, no central control and missing out on web browsers’ caching features when it comes to external JavaScript file includes.

The next step in event evolution was to apply events from within a JavaScript block, for example:

Note the clean HTML in the last example. This is generally what’s referred to as unobtrusive JavaScript. The benefit of this, besides JavaScript caching and code control, is code separation: you have all your content in one location and your interaction code in another. This also allows for a more accessible approach where the link will work perfectly fine with JavaScript disabled; it is also something that will please search engines.

DOM Level 2 Events

Back in November in 2000, the Document Object Model (DOM) Level 2 Events Specification was released by the W3C, offering a more detailed and granular way to control events in a web page. The new way to apply events to HTML elements looked like this:

The first parameter of the addEventListener method is the name of the event, and you should note that it no longer uses the “on” prefix. The second parameter is a reference to the function we want to call when the event occurs. The third parameter controls the so-called useCapture of the event, ie if event capturing or event bubbling should be used.

The counterpart of addEventListener is removeEventListener , which removes any applied event from an HTML element.

Internet Explorer event model exception

Unfortunately, Internet Explorer has so far not implemented the DOM Level 2 event model, and instead has its own proprietary attachEvent method. It looks like this in action:

Note that the attachEvent still uses the “on” prefix before the name of the actual event, and it doesn’t include any support for deciding the capture phase.

The counterpart of attachEvent is detachEvent , to remove any applied event from an HTML element.

Applying events cross-browser

With the inconsistencies between web browsers in event handling implementations, there have been numerous attempts from web developers to offer a good solution for applying events sucessfully across all major browsers. These solutions have different pros and cons, and are usually referred to as addEvent functions.

Most major JavaScript libraries have these built in, and there are also a number of stand-alone solutions available online. One suggestion is to use addEvent by Dean Edwards; you should also consider looking at something like event handling options with the jQuery JavaScript library.

Events and accessibility

Before we delve deeper into explaining how to control and call events, I just want to emphasize accessibility. While it’s normally a broad term for most people, I use it here to convey that what you want to do through the usage of events really should work when JavaScript is disabled or for other reasons blocked in the web browser.

Some people do turn off JavaScript in their web browsers, but more commonly proxy servers, firewalls and overzealous antivirus programs stop JavaScript from behaving as expected. Don’t let this discourage you; my aim is to guide you through creating events that have an accessible fallback in case of JavaScript not being available.

In general, never apply events to HTML elements that don’t already have a built-in behavior for that certain event. You should only apply onclick events to elements like a , which already have a fallback behavior for click events (eg browsing to the location specified in the link, or submitting a form).

Controlling events

Let’s start out with a simple example of an event, and how you can react to it. For the sake of simplicity, I will be using the addEvent solution referred to above, to avoid delving into the intricacies of cross-browser workarounds in each example.

Our first example is the onload event, which belongs to the window object. Generally, any events that affect the browser window (like onload , onresize and onscroll ) are available through the window object.

The onload event takes place when everything in the web page has completely loaded. This includes the HTML code itself as well as external dependencies such as images, CSS files and JavaScript files. When all of them have finished loading, window.onload gets called, and you can trigger web page functionality to occur. The following very simple example makes an alert message appear when the page has loaded:

That wasn’t too bad, right? If you want to, you can use so-called anonymous functions instead, eliminating the need for a name for your function. Like this:

Applying events to certain elements

To take this further, we should start by looking into adding events to some other elements on the page. For the sake of argument, let’s suppose you want to have an event happen every time a link is clicked. Combining this with what we learned above, this would be the way to go about it:

Ok, what just happened? First we used the onload event to check when the web page had completely loaded. Then we found all the links in the page by using the getElementsByTagName method of the document object. With an established reference to them, we looped through all links and applied an event to them to cause an action to occur once they were clicked.

But what about the cheeky “won’t take you there” part? After the alert has been shown, the line below reads return false . This means that within that context, returning false prevents the default action. We’ll get into other ways to dictate how events behave in the last section of this article.

Event object references

To add more detail to your event handling, you can take different actions depending on certain properties of the event that took place. For instance, if you are dealing with an onkeypress , you might want the event to occur only if the user presses the enter key, but no other keys.

As with the event model, Internet Explorer has decided to use a global event object called event for handling objects, while the W3C-recommended way implemented by all other web browsers is passing event objects belonging just to that specific event. The most common problem with implementing such functionality across browsers is getting a reference to the event itself, and a reference to the element that the event is targeting. This code solves that for you:

The first line in the eventCheck function checks if there’s an event object passed along to the function. If yes, it automatically becomes the first parameter of the function, hence getting the name evt in this example. If it doesn’t exist, meaning that the current web browser is Internet Explorer, it refers to a global property of the window object named event .

The second line looks for a target property on the established event reference. If it doesn’t exist, it falls back to the srcElement property implemented by Internet Explorer.

Note: this control and behavior is also addressed with the above referenced addEvent function, where the event object has been normalized to work the same in all web browsers. The above code is written out as if this is not the case, though, to give you an insight into web browser differences.

Checking an event-specific property

Let’s put this into action. The following example executes a different code block depending on what key was pressed:

The code inside the whatKey function checks a property on the event that took place, namely keyCode , to see which key was actually pressed on the keyboard. The number 13 means the Enter key and the number 9 means the Tab key.

Event defaults and event bubbling

There are a number of cases where you would be interested in stopping the default behavior of an event. For instance, you might want to prevent the user from submitting a form if certain fields aren’t filled out. The same goes for event bubbling, and this part will explain how you can take control of such situations.

Preventing the default behavior of events

Just as with event model and event object differences, there are two ways to go about this to support IE, and all other browsers. Building on the previous code for getting an event object reference, the next listing includes code to stop the default link behaviour occuring when links are clicked:

This approach uses something called object detection, to confirm that a method is actually available before it is called, which helps prevent possible errors. The preventDefault method is available in every web browser but Internet Explorer, and it prevents the default action of an event from happening.

If that method isn’t supported, it falls back to setting the returnValue of the global event object to false , thus stopping the default behaviour in Internet Explorer.

Stopping event bubbling

Consider the following HTML hierarchy:

Suppose you had applied an onclick event to all the a elements, li elements and the ul element. The onclick event would first call the event handler of the link, then the list items, and finally the event handler of the unordered list.

If the user clicks the link, most likely, you don’t want to call any possible event handler for the parent li element, but instead just let the user navigate to the corresponding page. However, if the user clicks the li item beside the link, you might want to trigger an event handler for the li as well as the ul element.

Note that with the DOM level 2 Event Model and useCapture enabled, ie using event capturing, it would start with the unordered list, then the list item and finally the link. However, since event capturing isn’t an option in Internet Explorer, this functionality is very seldom used in real practice.

Here’s how to write code to stop the bubbling of an event:

Complete event handling example

I have put together an example page showcasing adding an event handler and preventing that event’s default action, depending on certain criteria. The event handler checks whether a form is allowed to be submitted or not depending on if the user has filled out all fields. The JavaScript code is as follows:

Summary

I have merely scratched the surface of event handling in this article, but I hope you have gained a good understanding of how events work. I might have been a little hard on you with web browser inconsistencies, but my belief is that it’s very important to know these issues from the start.

Once you have accepted these issues and learned to master the solutions above, there’s no end to the possibilities you can achieve with JavaScript and event handling!

Выразительный JavaScript: Обработка событий

Некоторые программы работают с вводом пользователя, мышью и клавиатурой. Время возникновения такого ввода и последовательность данных нельзя предсказать заранее. Это требует иного подхода к контролю над порядком выполнения программы, чем уже привычный нам.

Обработчики событий

Представьте интерфейс, в котором единственным способом узнать, нажали ли на кнопку клавиатуры, было бы считывание текущего состояния кнопки. Чтобы реагировать на нажатия, вам пришлось бы постоянно считывать состояния кнопок, чтобы вы могли поймать это состояние, пока кнопка не отжалась. Было бы опасно проводить другие подсчёты, отнимающие процессорное время, так как можно было бы пропустить момент нажатия.

Таким образом ввод обрабатывался на примитивных устройствах. Шагом вперёд было бы, если железо или операционка замечали бы нажатие кнопки и передавали бы его в очередь. Затем программа периодически могла бы проверять очередь на новые события и реагировать на то, что находится в очереди.

Разумеется, она должна помнить о проверке, и делать это достаточно часто, потому что наличие длительного промежутка времени между нажатием кнопки и тем, когда программа замечает и реагирует на это, ведёт к восприятию этой программы как медленно работающей. Такой подход называется опросом. Большинство программистов по возможности избегают его. Такой подход используется достаточно редко.

Вариант получше – некая промежуточная система, которая позволяет коду реагировать на события в момент их возникновения. Браузеры позволяют это делать путём регистрации функций как обработчиков заданных событий.

Функция addEventListener регистрирует свой второй аргумент как функцию, которая вызывается, когда описанное в первом аргументе событие случается.

События и узлы DOM

Каждый обработчик событий браузера зарегистрирован в контексте. Когда вы вызываете addEventListener, вы вызываете её как метод целого окна, потому что в браузере глобальная область видимости – это объект window. У каждого элемента DOM есть свой метод addEventListener, позволяющий слушать события от этого элемента.

Пример назначает обработчик на DOM-узел кнопки. Нажатия на кнопку запускают обработчик, а нажатия на другие части документа – не запускают.

Присвоение узлу атрибута onclick работает похоже. Но у узла есть только один атрибут onclick, значит таким способом вы можете зарегистрировать только один обработчик. Метод addEventListener позволяет добавлять любое количество обработчиков, так что вы не замените случайно уже назначенный ранее обработчик.

Метод removeEventListener, вызванный с такими же аргументами, как addEventListener, удаляет обработчик.

Чтобы это провернуть, мы даём функции имя (в данном случае, once), чтобы её можно было передать и в addEventListener, и в removeEventListener.

Объекты событий

В примерах мы проигнорировали тот факт, что функциям-обработчикам передаётся аргумент – объект события. В нём хранится дополнительная информация о событии. К примеру, если надо узнать, какая кнопка мыши была нажата, мы можем обратиться к свойству which этого объекта.

Хранящаяся в объекте информация – разная для каждого типа событий. Мы обсудим эти типы позже. Свойство объекта type всегда содержит строку, описывающую событие (например, «click» или «mousedown»).

Распространение (propagation)

События, зарегистрированные на узлах, имеющих дочерние узлы, получат и некоторые события, случившиеся с их детьми. Если кликнуть на кнопку внутри параграфа, обработчики событий параграфа получат событие click.

Если и у параграфа и у кнопки есть обработчики, то первым запустится более конкретный – то есть, обработчик кнопки. Событие как бы распространяется наружу, от узла, где оно случилось, до его родительского и далее до корня документа. После отработки всех обработчиков всех промежуточных узлов, очередь среагировать на событие доходит и до самого окна.

В любой момент обработчик может вызвать метод stopPropagation объекта события, чтобы «высшие» узлы не получили его. Это может быть полезным, когда у вас есть кнопка внутри другого кликабельного элемента, и вы не хотите, чтобы клики по кнопке активировали поведение внешнего элемента.

Следующий пример регистрирует обработчики «mousedown» как на кнопке, так и на окружающем параграфе. При щелчке правой кнопкой обработчик кнопки вызывает stopPropagation, который предотвращает запуск обработчика параграфа. При клике другой кнопкой запускаются оба обработчика.

У большинства объектов событий есть свойство target, ссылающееся на узел, который запустил обработку. Его можно использовать для проверки того, что вы не обрабатываете что-то, пришедшее с ненужного вам узла.

Также возможно использовать свойство target, чтобы распространить обработку конкретного типа события. К примеру, если у вас есть узел, содержащий длинный список кнопок, было бы удобнее зарегистрировать один обработчик событий для узла, и в нём выяснять, нажали ли на кнопку – вместо того, чтобы регистрировать обработчики каждой кнопки по отдельности.

Действия по умолчанию

У многих событий есть действия по умолчанию. При клике на ссылку вы перейдёте по ней. При нажатии на стрелку вниз браузер прокрутит страницу вниз. По правому клику мыши вы увидите контекстное меню. И так далее.

Для большинства типов событий обработчики событий вызываются до того, как сработает действие по умолчанию. Если обработчик не хочет, чтобы это действие происходило (часто потому, что он уже обработал его), он может вызвать метод preventDefault объекта события.

Это можно использовать для создания своих горячих клавиш или контекстного меню. Также это можно использовать для слома привычного пользователю интерфейса. К примеру, вот ссылка, по которой нельзя пройти.

Не делайте так – если у вас нет очень серьёзной причины! Пользователям вашей страницы будет очень неудобно, когда они столкнутся с неожиданными результатами своих действий. В зависимости от браузера, некоторые события перехватить нельзя. В Chrome нельзя обрабатывать горячие клавиши закрытия текущей закладки (Ctrl-W or Command-W).

События от кнопок клавиатуры

При нажатии кнопки на клавиатуре браузер запускает событие «keydown». Когда она отпускается, происходит событие «keyup».

Несмотря на название, «keydown» происходит не только тогда, когда на кнопку нажимают. Если нажать и удерживать кнопку, событие будет происходить каждый раз по приходу повторного сигнала от клавиши (key repeat). Если вам, к примеру, надо увеличивать ускорение игрового персонажа, когда нажата кнопка со стрелкой, и уменьшать его, когда она отпущена – надо быть осторожным, чтобы не увеличивать ускорение каждый раз при повторе сигнала от кнопки, иначе скорость возрастёт очень сильно.

В примере упомянуто свойство keyCode объекта события. Так вы можете узнать, какая именно кнопка нажата или отпущена. К сожалению, не всегда очевидно, как преобразовать числовые коды в нужную кнопку.

Для цифр и букв код будет кодом символа Unicode, связанного с прописным символом, изображённым на кнопке. Метод строки charCodeAt даёт нам этот код.

У других кнопок коды менее предсказуемы. Лучший способ их выяснить – экспериментальный. Зарегистрировать обработчик, который записывает коды клавиш, и нажать нужную кнопку.

Кнопки-модификаторы типа Shift, Ctrl, Alt, и Meta (Command на Mac) создают события, как и нормальные кнопки. Но при разборе комбинаций клавиш можно выяснить, были ли нажаты модификаторы, через свойства shiftKey, ctrlKey, altKey, и metaKey событий клавиатуры и мыши.

События «keydown» и «keyup» дают информацию о физическом нажатии кнопок. А если вам нужно узнать, какой текст вводит пользователь? Создавать его из нажатий кнопок – неудобно. Для этого существует событие «keypress», происходящее сразу после «keydown» (и повторяющееся вместе с «keydown», если клавишу продолжают удерживать), но только для тех кнопок, которые выдают символы. Свойство объекта события charCode содержит код, который можно интерпретировать как код Unicode. Мы можем использовать функцию String.fromCharCode для превращения кода в строку из одного символа.

Источником события нажатия клавиши узел становится в зависимости от того, где находился фокус ввода во время нажатия. Обычные узлы не могут получить фокус ввода (если только вы не задали им атрибут tabindex), а такие, как ссылки, кнопки и поля форм – могут. Мы вернёся к полям ввода в главе 18. Когда ни у чего нет фокуса, в качестве целевого узла событий работает «document.body».

Щелчки мышью

Нажатие кнопки мыши тоже запускает несколько событий. События «mousedown» и «mouseup» похожи на «keydown» и «keyup», и запускаются, когда кнопка нажата и когда отпущена. События происходят у тех узлов DOM, над которыми находился курсор мыши.

После события «mouseup» на узле, на который пришлись и нажатие, и отпускание кнопки, запускается событие “click”. Например, если я нажал кнопку над одним параграфом, потом передвинул мышь на другой параграф и отпустил кнопку, событие “click” случится у элемента, который содержал в себе оба эти параграфа.

Если два щелчка происходят достаточно быстро друг за другом, запускается событие «dblclick» (double-click), сразу после второго запуска “click”.

Для получения точных координат места, где произошло событие мыши, обратитесь к свойствам pageX и pageY – они содержат координаты в пикселях относительно верхнего левого угла документа.

В примере создана примитивная программа для рисования. Каждый раз по клику на документе он добавляет точку под вашим курсором. В главе 19 будет представлена менее примитивная программа для рисования.

Свойства clientX и clientY похожи на pageX и pageY, но дают координаты относительно части документа, которая видна сейчас (если документ был прокручен). Это удобно при сравнении координат мыши с координатами, которые возвращает getBoundingClientRect – его возврат тоже связан с относительными координатами видимой части документа.

Движение мыши

Каждый раз при сдвиге курсора мыши запускается событие «mousemove». Его можно использовать для отслеживания позиции мыши. Обычно это нужно при создании некоей функциональности, связанной с перетаскиванием объектов мышью.

К примеру, следующая программа отображает полоску и устанавливает обработку событий так, что движение влево и вправо уменьшает или увеличивает её ширину.

Обратите внимание – обработчик «mousemove» зарегистрирован у всего окна. Даже если мышь уходит за пределы полоски, нам надо обновлять её размер и прекращать это, когда кнопку отпускают.

Когда курсор попадает на узел и уходит с него, происходят события «mouseover» или «mouseout». Их можно использовать, кроме прочего, для создания эффектов проведения мыши, показывая или меняя стиль чего-либо, когда курсор находится над этим элементом.

К сожалению, создание такого эффекта не ограничивается запуском его при событии «mouseover» и завершением при событии «mouseout». При движении мыши от узла к его дочерним узлам на родительском узле происходит событие «mouseout», хотя мышь, вообще говоря, его и не покидала. Что ещё хуже, эти события распространяются как и все другие, поэтому вы всё равно получаете «mouseout» при уходе курсора с одного их дочерних узлов того узла, где вы зарегистрировали обработчик.

Для обхода проблемы можно использовать свойство relatedTarget объекта событий. Он сообщает, на каком узле была до этого мышь при возникновении события «mouseover», и на какой элемент она переходит при событии «mouseout». Нам надо менять эффект, только когда relatedTarget находится вне нашего целевого узла. Только в этом случае событие на самом деле представляет собой переход на наш узел (или уход с узла).

Функция isInside перебирает всех предков узла, пока не доходит до верха документа (и тогда узел равен null), или же не находит заданного ей родителя.

Должен добавить, что такой эффект достижим гораздо проще через псевдоселектор CSS под названием :hover, как показано ниже. Но когда при наведении вам надо делать что-то более сложное, чем изменение стиля узла, придётся использовать трюк с событиями «mouseover» и «mouseout».

События прокрутки

Когда элемент прокручивается, запускается событие «scroll». Это используется во многих случаях, например чтобы узнать, на что сейчас пользователь смотрит (чтобы останавливать анимацию, не попавшую на экран, или отправлять секретные шпионские донесения в ваш злодейский штаб), или визуально демонстрировать прогресс (подсвечивая часть содержания или показывая номер страницы).

В примере в правом верхнем углу документа создаётся индикатор процесса, который заполняется по мере прокрутки элемента вниз.

Позиция элемента fixed означает почти то же, что absolute, но ещё и предотвращает прокручивание элемента вместе с остальным документом. Смысл в том, чтобы оставить наш индикатор в углу. Внутри него находится другой элемент, который изменяет размер, отражая текущий прогресс. Мы используем проценты вместо px для задания ширины, чтобы размер элемента изменялся относительно размера всего индикатора.

Глобальная переменная innerHeight даёт высоту окна, которую надо вычесть из полной высоты прокручиваемого элемента – при достижении конца элемента прокрутка заканчивается. (Также в дополнение к innerHeight есть переменная innerWidth). Поделив текущую позицию прокрутки pageYOffset на максимальную позицию прокрутки, и умножив на 100, мы получили процент для индикатора.

Вызов preventDefault не предотвращает прокрутку. Обработчик события вызывается уже после того, как прокрутка случилась.

События, связанные с фокусом

При получении элементом фокуса браузер запускает событие “focus”. Когда он теряет фокус, запускается событие “blur”.

В отличие от предыдущих событий, эти два не распространяются. Обработчик родительского узла не уведомляется о получении или утрате фокуса дочерним элементом.

Следующий пример демонстрирует текст подсказки для того текстового поля, у которого в данный момент фокус.

Объект window получает события focus и blur, когда пользователь выделяет или убирает фокус с закладки браузера или окна браузера, в котором показан документ.

Событие загрузки

Когда заканчивается загрузка страницы, на объектах window и body запускается событие “load”. Это часто используется для планирования инициализирующих действий, которым необходим полностью построенный документ. Вспомните, что содержимое тегов <script> запускается сразу, как только тег встречается. Иногда это слишком рано – например, когда скрипту нужно что-то сделать с теми частями документа, которые находятся после тега <script>.

У элементов типа картинок или тегов скрипта, которые загружают внешний файл, тоже есть событие “load”, которое показывает, что файл загружен. Как и события фокуса, события загрузки не распространяются.

Когда страница закрывается или с неё уходят (например, по ссылке), запускается событие «beforeunload». Основная цель – защитить пользователя от случайной потери данных при закрытии документа. Предотвращение закрытия страницы не производится, как вы могли подумать, при помощи preventDefault. Вместо этого используется возврат строки из обработчика. Строка будет использована в диалоге, который спрашивает пользователя, хочет ли он остаться на странице или покинуть её. Этот механизм гарантирует, что пользователь может покинуть страницу, даже если на ней работает зловредный скрипт, который бы хотел не отпускать пользователя, а вместо этого показывал бы ему мошенническую рекламу по снижению веса.

График выполнения скрипта

Несколько вещей могут привести к старту скрипта. Чтение тега <script> — одна из них. Запуск события – ещё одна. В главе 13 обсуждается функция requestAnimationFrame, которая планирует запуск функции перед следующей перерисовкой страницы. Это ещё один способ запустить скрипт.

Важно понять, что хотя события и запускаются в любой момент, два разных скрипта одновременно работать не могут. Если скрипт работает, обработчики событий и запланированные другим способом куски кода будут ждать своей очереди. Поэтому документ подвисает, когда скрипт работает слишком долго. Браузер не обрабатывает щелчки и другие события внутри документа потому, что он не может запустить обработчики событий, пока работает текущий скрипт.

В некоторых программных окружениях можно запускать несколько потоков одновременно. Можно сделать программу быстрее, если выполнять несколько вещей одновременно. Но когда несколько действующих лиц трогают одни и те же части системы в одно и то же время, продумывать программу становится на порядок сложнее.

То, что программы JavaScript делают по одной вещи за раз, облегчает нашу жизнь. Если вам очень надо сделать в фоне что-то тяжёлое, не подвешивая при этом страницу, браузеры предоставляют штуку под названием «сетевые рабочие» (web worker) – изолированное окружение JavaScript, работающее вместе с главной программой над документом, которое может общаться с ней только посредством сообщений.

Предположим, у нас есть следующий код в файле code/squareworker.js:

Представьте, что возведение в квадрат – очень тяжёлое, долго работающее вычисление, которое нам надо запустить фоновым потоком. Такой код порождает «рабочего», отправляет ему несколько сообщений, и выводит результаты.

Функция postMessage отправляет сообщение, которое запускает событие “message” у принимающей стороны. Скрипт, создавший рабочего, отправляет и получает сообщения через объект Worker, тогда как рабочий общается со скриптом, создавшим его, отправляя и получая сообщения через его собственное глобальное окружение – которое является отдельным окружением, не связанным с оригинальным скриптом.

Установка таймеров

Функция setTimeout схожа с requestAnimationFrame. Она планирует запуск другой функции в будущем. Но вместо вызова функции при следующей перерисовке страницы, она ждёт заданное в миллисекундах время. Эта страница через две секунды превращается из синей в жёлтую:

Иногда вам надо отменить запланированную функцию. Это можно сделать, сохранив значение, возвращаемое setTimeout, и затем вызвав с ним clearTimeout.

Функция cancelAnimationFrame работает так же, как clearTimeout – вызов её со значением, возвращённым requestAnimationFrame, отменит этот кадр (если он уже не был вызван).

Похожий набор функций, setInterval и clearInterval используется для установки таймеров, которые будут повторяться каждые X миллисекунд.

Устранение помех (debouncing)

У некоторых событий есть возможность выполняться быстро и много раз подряд (например, «mousemove» и «scroll»). При обработке таких событий надо быть осторожным и не делать ничего «тяжёлого», или ваш обработчик займёт столько времени на выполнение, что взаимодействие с документом будет медленным и прерывистым.

Если в таком обработчике надо сделать что-то нетривиальное, можно использовать setTimeout, чтобы гарантировать, что вы делаете это не слишком часто. Это обычно называют «устранением помех» в событии. К этому существует несколько слегка различающихся подходов.

В первом примере надо сделать что-то, когда пользователь печатает, но не надо делать это сразу после запуска каждого события нажатия на клавиши. Когда они быстро печатают, нам надо подождать, когда возникнет пауза. Вместо немедленного выполнения действия в обработчике, мы устанавливаем таймаут. Также мы очищаем предыдущий таймаут, если он был, так что если события близко одно от другого (ближе, чем задержка таймера), предыдущее событие будет отменено.

Если задать undefined для clearTimeout, или вызвать его с таймаутом, который уже произошёл, то ничего не произойдёт. Таким образом, не надо осторожничать при его вызове, и мы просто поступаем так для каждого события.

Можно использовать немного другой подход, если нам надо разделить ответы минимальными промежутками времени, но при этом запускать их в то время, когда происходят события, а не после. К примеру, надо реагировать на события «mousemove», показывая текущие координаты мыши, но только каждые 250 миллисекунд.

Обработчики событий позволяют обнаруживать и реагировать на события, над которыми мы не властны. Для их регистрации используется метод addEventListener.

У событий есть определяющий их тип («keydown», «focus», и так далее). Большинство событий вызываются конкретными узлами DOM, и затем распространяются на их предков, позволяя связанными с ними обработчикам обрабатывать их.

При вызове обработчика ему передаётся объект события с дополнительной информацией о событии. У объекта также есть методы, позволяющие остановить дальнейшее распространение (stopPropagation) и предотвратить обработку события браузером по умолчанию (preventDefault).

Нажатия на клавиши запускают события «keydown», «keypress» и «keyup». Нажатия на кнопки мыши запускают события «mousedown», «mouseup» и «click». Движения мыши запускают события «mousemove», и возможно «mouseenter» и «mouseout».

Прокрутку можно обнаружить через событие “scroll”, а изменения фокуса через события «focus» и «blur». Когда заканчивается загрузка документа, у объекта window запускается событие “load”.

В одно и то же время может работать один участок программы. Поэтому обработчики событий и другие запланированные скрипты будут ждать окончания работы текущих.

Упражнения
Цензура клавиатуры

В промежутке с 1928 по 2013 год турецкие законы запрещали использование букв Q, W и X в официальных документах. Это являлось частью общей инициативы подавления курдской культуры – эти буквы используются в языке курдов, но не у турков.

В качестве упражнения на тему странного использования технологий, я прошу вас запрограммировать поле для ввода текста так, чтобы эти буквы нельзя было туда вписать. Насчет копирования и вставки и других подобных возможных обходов правила не беспокойтесь.

След мыши

В ранние дни JavaScript, когда было время кричащих домашних страниц с обилием анимированных картинок, люди использовали язык очень вдохновляющими способами. Одним из них был «след мыши» — серия картинок, которые следовали за курсором при его движении по странице.

Я хочу, что бы вы в упражнении сделали такой след. Используйте <div> с абсолютным позиционированием, фиксированным размером и цветом фона. Создайте кучку элементов и при движении мыши показывайте их следом за курсором.

К этому можно подойти многими способами. Можно сделать очень простое или очень сложное решение, как угодно. Простое – хранить фиксированное количество элементов и проходить по ним в цикле, двигая каждый следующий на текущее место курсора, каждый раз когда случается событие «mousemove».

Закладки

Интерфейс закладок встречается часто. Он позволяет вам выбирать панель интерфейса, выбирая одну из нескольких торчащих закладок над элементом.

В упражнении вам нужно сделать простой интерфейс закладок. Напишите функцию asTabs, которая принимает узел DOM, и создаёт закладочный интерфейс, показывая дочерние элементы этого узла. Ей нужно вставлять список элементов <button> вверху узла, по одному на каждый дочерний элемент, содержащих текст, полученный из атрибута data-tabname. Все, кроме одного из дочерних элементов, должны быть спрятаны (при помощи значения none свойства стиля display), а текущий видимый узел можно выбирать нажатием кнопки.

Когда оно заработает, расширьте функционал, чтобы у текущей активной кнопки был свой стиль.

Введение в события

События — это действия или случаи, возникающие в программируемой вами системе, о которых система сообщает вам для того, чтобы вы могли с ними взаимодействовать. Например, если пользователь нажимает кнопку на веб-странице, вы можете ответить на это действие, отобразив информационное окно. В этой статье мы обсудим некоторые важные концепции, связанные с событиями, и посмотрим, как они работают в браузерах. Эта статья не является исчерпывающим источником по этой теме — здесь только то, что вам нужно знать на этом этапе.

Предпосылки: Базовая компьютерная грамотность, базовое понимание HTML и CSS, Первые шаги в JavaScript.
Задача: Понять фундаментальную теорию событий, как они работают в браузерах и как события могут различаться в разных средах программирования.

Серия удачных событий

При возникновении события система генерирует сигнал, а также предоставляет механизм, с помощью которого можно автоматически предпринимать какие-либо действия (например, выполнить определённый код), когда происходит событие. Например, в аэропорту, когда взлётно-посадочная полоса свободна для взлёта самолёта, сигнал передаётся пилоту, и в результате они приступают к взлёту.

В Web события запускаются внутри окна браузера и, как правило, прикрепляются к конкретному элементу, который в нем находится. Это может быть один элемент, набор элементов, документ HTML, загруженный на текущей вкладке, или все окно браузера. Существует множество различных видов событий, которые могут произойти, например:

  • Пользователь кликает мышью или наводит курсор на определённый элемент.
  • Пользователь нажимает клавишу на клавиатуре.
  • Пользователь изменяет размер или закрывает окно браузера.
  • Завершение загрузки веб-страницы.
  • Отправка данных через формы.
  • Воспроизведение видео, пауза или завершение воспроизведения.
  • Произошла ошибка.

Подробнее о событиях можно посмотреть в Справочнике по событиям.

Каждое доступное событие имеет обработчик событий — блок кода (обычно это функция JavaScript, вводимая вами в качестве разработчика), который будет запускаться при срабатывании события. Когда такой блок кода определён на запуск в ответ на возникновение события, мы говорим, что мы регистрируем обработчик событий. Обратите внимание, что обработчики событий иногда называют **слушателями событий (от англ. event listeners). Они в значительной степени взаимозаменяемы для наших целей, хотя, строго говоря, они работают вместе. Слушатель отслеживает событие, а обработчик — это код, который запускается в ответ на событие.

Примечание: Важно отметить, что веб-события не являются частью основного языка JavaScript. Они определены как часть JavaScript-API, встроенных в браузер.

Простой пример

Рассмотрим простой пример. Вы уже видели события и обработчики событий во многих примерах в этом курсе, но давайте повторим для закрепления информации. В этом примере у нас есть кнопка <button> , при нажатии которой цвет фона изменяется случайным образом:

JavaScript выглядит так:

В этом коде мы сохраняем ссылку на кнопку внутри переменной btn типа const , используя функцию Document.querySelector() . Мы также определяем функцию, которая возвращает случайное число. Третья часть кода — обработчик события. Переменная btn указывает на элемент <button> — для этого типа объекта существуют возникающие при определённом взаимодействии с ним события, а значит, возможно использование обработчиков событий. Мы отслеживаем момент возникновения события при щелчке мышью, связывая свойство обработчика события onclick с анонимной функцией, генерирующей случайный цвет RGB и устанавливающей его в качестве цвета фона элемента <body> .

Этот код теперь будет запускаться всякий раз, когда возникает событие при нажатии на элемент <button> — всякий раз, когда пользователь щёлкает по нему.

Пример вывода выглядит следующим образом:

События не только для веб-страниц

События, как понятие, относятся не только к JavaScript — большинство языков программирования имеют модель событий, способ работы которой часто отличается от модели в JavaScript. Фактически, даже модель событий в JavaScript для веб-страниц отличается от модели событий для просто JavaScript, поскольку используются они в разных средах.

Например, Node.js — очень популярная среда исполнения JavaScript, которая позволяет разработчикам использовать JavaScript для создания сетевых и серверных приложений. Модель событий Node.js основана на том, что существуют обработчики, отслеживающие события, и эмиттеры (передатчики), которые периодически генерируют события. В общем-то, это похоже на модель событий в JavaScript для веб-страниц, но код совсем другой. В этой модели используется функция on() для регистрации обработчиков событий, и функция once() для регистрации обработчика событий, который отключается после первого срабатывания. Хорошим примером использования являются протоколы событий HTTP connect event docs.

Вы также можете использовать JavaScript для создания кросс-браузерных расширений — улучшения функциональности браузера с помощью технологии WebExtensions. В отличии от модели веб-событий здесь свойства обработчиков событий пишутся в так называемом регистре CamelCase (например, onMessage , а не onmessage ) и должны сочетаться с функцией addListener . См. runtime.onMessage page для примера.

На данном этапе обучения вам не нужно особо разбираться в различных средах программирования, однако важно понимать, что принцип работы событий в них отличается.

Способы использования веб-событий

Существует множество различных способов добавления кода обработчика событий на веб-страницы так, чтобы он срабатывал при возникновении соответствующего события. В этом разделе мы рассмотрим различные механизмы и обсудим, какие из них следует использовать.

Свойства обработчика событий

В этом курсе вы уже сталкивались со свойствами, связываемыми с алгоритмом работы обработчика событий. Вернёмся к приведённому выше примеру:

В данной ситуации свойство onclick — это свойство обработчика события. В принципе это обычное свойство кнопки как элемента (наравне с btn.textContent или btn.style ), но оно относится к особому типу. Если вы установите его равным какому-нибудь коду, этот код будет запущен при возникновении события (при нажатии на кнопку).

Для получения того же результата, вы также можете присвоить свойству обработчика имя уже описанной функции (как мы видели в статье Создайте свою функцию):

Давайте теперь поэкспериментируем с другими свойствами обработчика событий.

Создайте локальную копию файла random-color-eventhandlerproperty.html и откройте её в своём браузере. Это всего лишь копия простого примера про случайные цвета, который мы уже разобрали в этой статье. Теперь попробуйте изменить btn.onclick на следующие значения и понаблюдайте за результатами:

    и btn.onblur — Цвет изменится, когда кнопка будет сфокусирована или не сфокусирована (попробуйте нажать Tab, чтобы выбрать кнопку или убрать выбор). Эти свойства часто применяются для отображения информации о том, как заполнить поля формы, когда они сфокусированы, или отобразить сообщение об ошибке, если поле формы было заполнено с неправильным значением. — Цвет будет изменяться только при двойном щелчке. , window.onkeydown , window.onkeyup — Цвет будет меняться при нажатии клавиши на клавиатуре, причём keypress ссылается на обычное нажатие (нажатие кнопки и последующее её отпускание как одно целое), в то время как keydown и keyup разделяют действия на нажатие клавиши и отпускание, и ссылаются на них соответственно. Обратите внимание, что это не работает, если вы попытаетесь зарегистрировать этот обработчик событий на самой кнопке — его нужно зарегистрировать на объекте window, который представляет все окно браузера. и btn.onmouseout — Цвет будет меняться при наведении указателя мыши на кнопку или когда указатель будет отводиться от кнопки соответственно.

Некоторые события очень общие и доступны практически в любом месте (например, обработчик onclick может быть зарегистрирован практически для любого элемента), тогда как некоторые из них более конкретны и полезны только в определённых ситуациях (например, имеет смысл использовать onplay (en-US) только для определённых элементов, таких как <video> ).

Встроенные обработчики событий — не используйте их

Самый ранний из введённых в сеть Web методов регистрации обработчиков событий базируется на HTML атрибутах (встроенные обработчики событий):

Примечание: вы можете найти полный исходник кода из этого примера на GitHub (также взгляните на его выполнение).

Значение атрибута — это буквально код JavaScript, который вы хотите запустить при возникновении события. В приведённом выше примере вызывается функция, определённая внутри элемента <script> на той же странице, но вы также можете вставить JavaScript непосредственно внутри атрибута, например:

Для многих свойств обработчика событий существуют эквиваленты в виде атрибутов HTML. Однако, не рекомендуется их использовать — это считается плохой практикой. Использование атрибутов для регистрации обработчика событий кажется простым и быстрым методом, но такое описание обработчиков также скоро становится неудобным и неэффективным.

Более того, не рекомендуется смешивать HTML и JavaScript файлы, так как в дальнейшем такой код становится сложнее с точки зрения обработки (парсинга). Лучше держать весь JavaScript в одном месте. Также, если он находится в отдельном файле, вы можете применить его к нескольким документам HTML.

Даже при работе только в одном файле использование встроенных обработчиков не является хорошей идеей. Ладно, если у вас одна кнопка, но что, если у вас их 100? Вам нужно добавить в файл 100 атрибутов; обслуживание такого кода очень быстро превратится в кошмар. С помощью JavaScript вы можете легко добавить функцию обработчика событий ко всем кнопкам на странице независимо от того, сколько их было.

Обратите внимание, что для перебора всех элементов, которые содержит объект NodeList , можно воспользоваться встроенным методом forEach() :

Примечание: Разделение логики вашей программы и вашего контента также делает ваш сайт более дружественным к поисковым системам.

Функции addEventListener() и removeEventListener()

Новый тип механизма событий определён в спецификации Document Object Model (DOM) Level 2 Events, которая предоставляет браузеру новую функцию — addEventListener() . Работает она аналогично свойствам обработчика событий, но синтаксис совсем другой. Наш пример со случайным цветом мог бы выглядеть и так:

Примечание: вы можете найти исходный код из этого примера на GitHub (также взгляните на его выполнение).

Внутри функции addEventListener() мы указываем два параметра — имя события, для которого мы хотим зарегистрировать этот обработчик, и код, содержащий функцию обработчика, которую мы хотим запустить в ответ. Обратите внимание, что будет целесообразно поместить весь код внутри функции addEventListener() в анонимную функцию, например:

Этот механизм имеет некоторые преимущества по сравнению с более старыми механизмами, рассмотренными ранее. Например, существует аналогичная функция removeEventListener() , которая удаляет ранее добавленный обработчик. Это приведёт к удалению набора обработчиков в первом блоке кода в этом разделе:

Это не важно для простых небольших программ, но для более крупных и более сложных программ он может повысить эффективность очистки старых неиспользуемых обработчиков событий. Кроме того, это позволяет вам иметь одну и ту же кнопку, выполняющую различные действия в разных обстоятельствах — все, что вам нужно сделать, это добавить/удалить обработчики событий, если это необходимо.

Также вы можете зарегистрировать несколько обработчиков для одного и того же события на элементе. Следующие два обработчика не будут применяться:

Поскольку вторая строка будет перезаписывать значение onclick , установленное первой. Однако, если:

Обе функции будут выполняться при щелчке элемента.

Кроме того, в этом механизме событий имеется ряд других мощных функций и опций. Эта тема выходит за рамки данной статьи, но если вы хотите изучить подробнее, переходите по ссылкам: Метод EventTarget.addEventListener() и Метод EventTarget.removeEventListener().

Какой механизм мне использовать?

Из трёх механизмов определённо не нужно использовать атрибуты событий HTML. Как упоминалось выше, это устаревшая и плохая практика.

Остальные два являются относительно взаимозаменяемыми, по крайней мере для простых целей

  • Свойства обработчика событий имеют меньшую мощность и параметры, но лучше совместимость между браузерами (поддерживается ещё в Internet Explorer 8). Вероятно, вам следует начать с них, когда вы учитесь.
  • События уровня 2 DOM ( addEventListener() и т. д.) являются более мощными, но также могут стать более сложными и хуже поддерживаться (поддерживается ещё в Internet Explorer 9). Вам также стоит поэкспериментировать с ними и стремиться использовать их там, где это возможно.

Основные преимущества третьего механизма заключаются в том, что при необходимости можно удалить код обработчика событий, используя removeEventListener() , и так же можно добавить несколько элементов-обработчиков того же типа к элементам. Например, вы можете вызвать addEventListener(‘click’, function() <. >) для элемента несколько раз, с разными функциями, указанными во втором аргументе. Это невозможно при использовании свойств обработчика событий, поскольку любые последующие попытки установить свойство будут перезаписывать более ранние, например:

Примечание: Если вам требуется поддержка браузеров старше Internet Explorer 8 в вашем проекте, вы можете столкнуться с трудностями, так как такие старые браузеры используют старые модели событий из более новых браузеров. Но не бойтесь, большинство библиотек JavaScript (например, jQuery ) имеют встроенные функции, которые абстрагируют различия между браузерами. Не беспокойтесь об этом слишком много на этапе вашего учебного путешествия.

Другие концепции событий

Рассмотрим некоторые современные концепции, имеющие отношение к событиям. На данный момент не обязательно понимать их полностью, но представление о них поможет лучше понять некоторые модели кода, с которыми вы, вероятно, столкнётесь.

Объекты событий

Иногда внутри функции обработчика событий вы можете увидеть параметр, заданный с таким именем, как event , evt или просто e . Называется он объектом события и он автоматически передаётся обработчикам событий для предоставления дополнительных функций и информации. Например, давайте немного перепишем наш пример со случайным цветом:

Примечание: вы можете найти исходник кода для этого примера на GitHub (также взгляните на его выполнение).

Итак в коде выше мы включаем объект события e в функцию, а в функции — настройку стиля фона для e.target , который является кнопкой. Свойство объекта события target всегда является ссылкой на элемент, с которым только что произошло событие. Поэтому в этом примере мы устанавливаем случайный цвет фона на кнопке, а не на странице.

Примечание: Вместо e / evt / event можно использовать любое имя для объекта события, которое затем можно использовать для ссылки на него в функции обработчика событий. e / evt / event чаще всего используются разработчиками, потому что они короткие и легко запоминаются. И хорошо придерживаться стандарта.

e.target применяют, когда нужно установить один и тот же обработчик событий на несколько элементов и, когда на них происходит событие, применить определённое действие к ним ко всем. Например, у вас может быть набор из 16 плиток, которые исчезают при нажатии. Полезно всегда иметь возможность просто указать, чтобы объект исчез, как e.target , вместо того, чтобы выбирать его более сложным способом. В следующем примере (см. исходный код на useful-eventtarget.html,а как он работает можно посмотреть здесь), мы создаём 16 элементов <div> с использованием JavaScript. Затем мы выберем все из них, используя document.querySelectorAll() , и с помощью цикла for выберем каждый из них, добавив обработчик onclick к каждому так, чтобы случайный цвет применялся к каждому клику:

Результат выглядит следующим образом (попробуйте щёлкнуть по нему):

Большинство обработчиков событий, с которыми вы столкнулись, имеют только стандартный набор свойств и функций (методов), доступных для объекта события (см. Event для ссылки на полный список). Однако некоторые более продвинутые обработчики добавляют специальные свойства, содержащие дополнительные данные, которые им необходимо выполнять. Например, Media Recorder API (en-US) имеет событие, доступное для данных, которое срабатывает, когда записано какое-либо аудио или видео и доступно для выполнения чего-либо (например, для сохранения или воспроизведения). Соответствующий объект события ondataavailable handler имеет свойство данных, содержащее записанные аудио- или видеоданные, чтобы вы могли получить к нему доступ и что-то сделать с ним.

Предотвращение поведения по умолчанию

Иногда бывают ситуации, когда нужно остановить событие, выполняющее то, что оно делает по умолчанию. Наиболее распространённым примером является веб-форма, например, пользовательская форма регистрации. Когда вы вводите данные и нажимаете кнопку отправки, естественное поведение заключается в том, что данные должны быть отправлены на указанную страницу на сервере для обработки, а браузер перенаправляется на страницу с сообщением об успехе (или остаться на той же странице, если другое не указано).

Но если пользователь отправил данные не правильно, как разработчик, вы хотите остановить отправку на сервер и выдать сообщение об ошибке с информацией о том, что не так и что нужно сделать. Некоторые браузеры поддерживают функции автоматической проверки данных формы, но, поскольку многие этого не делают, вам не следует полагаться на них и выполнять свои собственные проверки валидации. Давайте посмотрим на простой пример.

Простая форма HTML, в которой требуется ввести ваше имя и фамилию:

В JavaScript мы реализуем очень простую проверку внутри обработчика события onsubmit (событие «отправить» запускается в форме, когда оно отправлено), который проверяет, пусты ли текстовые поля. Если они пусты, мы вызываем функцию preventDefault() объекта события, которая останавливает отправку формы, а затем выводит сообщение об ошибке в абзаце ниже нашей формы, чтобы сообщить пользователю, что не так:

Очевидно, что это довольно слабая проверка формы — это не помешает пользователю отправить форму с пробелами или цифрами, введёнными в поля, но для примера подходит. Вывод выглядит следующим образом:

Примечание: чтобы увидеть исходный код, откройте preventdefault-validation.html (также запустите здесь).

Всплытие и перехват событий

Последним предметом для рассмотрения в этой теме является то, с чем вы не часто будете сталкиваться, но это может стать настоящей головной болью, если вы не поймёте, как работает следующий механизм. Всплытие и перехват событий — два механизма, описывающих, что происходит, когда два обработчика одного и того же события активируются на одном элементе. Посмотрим на пример. Чтобы сделать это проще — откройте пример show-video-box.html в одной вкладке и исходный код в другой вкладке. Он также представлен ниже:

Это довольно простой пример, который показывает и скрывает <div> с элементом <video> внутри него:

При нажатии на кнопку <button> , изменяется атрибут класса элемента <div> с hidden на showing (CSS примера содержит эти два класса, которые размещают блок вне экрана и на экране соответственно):

Затем мы добавляем ещё пару обработчиков событий onclick. Первый к <div> , а второй к <video> . Идея заключается в том, чтобы при щелчке по области <div> вне зоны видео поле снова скрылось, а при клике в области <video> видео начало воспроизводиться.

Но есть проблема: когда вы нажимаете на видео, оно начинает воспроизводиться, но одновременно вызывает скрытие <div> . Это связано с тем, что видео находится внутри <div>, это часть его, поэтому нажатие на видео фактически запускает оба вышеуказанных обработчика событий.

Всплытие и перехват событий — концепция выполнения

Когда событие инициируется элементом, который имеет родительские элементы (например, <video> в нашем случае), современные браузеры выполняют две разные фазы — фазу захвата и фазу всплытия.

На стадии захвата происходит следующее:

  • Браузер проверяет, имеет ли самый внешний элемент ( <html> ) обработчик события onclick , зарегистрированный на нем на этапе захвата и запускает его, если это так.
  • Затем он переходит к следующему элементу внутри <html> и выполняет то же самое, затем следующее и так далее, пока не достигнет элемента, на который на самом деле нажали.

На стадии всплытия происходит полная противоположность:

  • Браузер проверяет, имеет ли элемент, который был фактически нажат, обработчик события onclick , зарегистрированный на нем в фазе всплытия, и запускает его, если это так.
  • Затем он переходит к следующему непосредственному родительскому элементу и выполняет то же самое, затем следующее и так далее, пока не достигнет элемента <html> .

(Нажмите на изображение, чтобы увеличить диаграмму)

В современных браузерах по умолчанию все обработчики событий регистрируются в фазе всплытия. Итак, в нашем текущем примере, когда вы нажимаете видео, событие click вызывается из элемента <video> наружу, в элемент <html> . По пути:

  • Он находит обработчик video.onclick. и запускает его, поэтому видео сначала начинает воспроизводиться.
  • Затем он находит обработчик videoBox.onclick. и запускает его, поэтому видео также скрывается.
Исправление проблемы с помощью stopPropagation()

Чтобы исправить это раздражающее поведение, стандартный объект события имеет функцию, называемую stopPropagation() , которая при вызове в обработчике событий объекта делает так, чтобы обработчик выполнялся, но событие не всплывало дальше по цепочке, поэтому не будут запускаться другие обработчики.

Поэтому мы можем исправить нашу текущую проблему, изменив вторую функцию-обработчик в предыдущем блоке кода:

Вы можете попробовать создать локальную копию show-video-box.html и попробовать его самостоятельно исправить или просмотреть исправленный результат в show-video-box-fixed.html (также см. исходный код здесь).

Примечание: Зачем беспокоиться как с захватом, так и с всплыванием? Что ж, в старые добрые времена, когда браузеры были менее совместимы, чем сейчас, Netscape использовал только захват событий, а Internet Explorer использовал только всплывающие события. Когда W3C решил попытаться стандартизировать поведение и достичь консенсуса, они в итоге получили эту систему, которая включала в себя и то, и другое, что реализовано в одном из современных браузеров.

Примечание: Как упоминалось выше, по умолчанию все обработчики событий регистрируются в фазе всплытия и это имеет смысл в большинстве случаев. Если вы действительно хотите зарегистрировать событие в фазе захвата, вы можете сделать это, зарегистрировав обработчик с помощью addEventListener() и установив для третьего дополнительного свойства значение true .

Делегирование события

Всплытие также позволяет нам использовать делегирование событий. Если у какого-либо родительского элемента есть множество дочерних элементов, и вы хотите, чтобы определённый код выполнялся при щелчке (событии) на каждом из дочерних элементов, можно установить обработчик событий на родительском элементе и события, происходящие на дочерних элементах будут всплывать до их родителя. При этом не нужно устанавливать обработчик событий на каждом дочернем элементе.

Хорошим примером является серия элементов списка. Если вы хотите, чтобы каждый из них, например, отображал сообщение при нажатии, вы можете установить обработчик событий click для родительского элемента <ul> и он будет всплывать в элементах списка.

Эту концепцию объясняет в своём блоге Дэвид Уолш, где приводит несколько примеров. (см. How JavaScript Event Delegation Works.)

Вывод

Это все, что вам нужно знать о веб-событиях на этом этапе. Как уже упоминалось, события не являются частью основного JavaScript — они определены в веб-интерфейсах браузера (Web API).

Кроме того, важно понимать, что различные контексты, в которых используется JavaScript, обычно имеют разные модели событий — от веб-API до других областей, таких как браузерные WebExtensions и Node.js (серверный JavaScript). Может сейчас вы не особо в этом разбираетесь, но по мере изучения веб-разработки начнёт приходить более ясное понимание тематики.

Если у вас возникли вопросы, попробуйте прочесть статью снова или обратитесь за помощью к нам.

Введение в события

Практически все JavaScript-приложения выполняют те или иные действия, откликаясь на различные события.

Событие — это сигнал от браузера о том, что что-то произошло.

Есть множество самых различных событий.

  • DOM-события, которые инициируются элементами DOM. Например, событие click происходит при клике на элементе, а событие mouseover — когда указатель мыши появляется над элементом,
  • События окна. Например событие resize — при изменении размера окна браузера,
  • Другие события, например load , readystatechange . Они используются, скажем, в технологии AJAX.

Именно DOM-события связывают действия, происходящие в документе, с кодом JavaScript, тем самым обеспечивая динамический веб-интерфейс.

Назначение обработчиков

Для того, чтобы скрипт реагировал на событие — нужно назначить хотя бы одну функцию-обработчик. Обычно обработчики называют «on+имя события» , например: onclick .

Нужно сразу отметить, что JavaScript — однопоточный язык, поэтому обработчики всегда выпоняются последовательно и в общем потоке. Это значит, что при установке обработчиков двух событий, которые возникают на элементе одновременно, например mouseover (мышь появилась над элементом) и mousemove (мышь двигается над элементом), их обработчики будут выполнены последовательно.

Существует несколько способов назначать обработчик на конкретное событие элемента. Все они представлены ниже.

Через атрибут HTML-тега

Обработчик события можно указать в виде inline-записи, прямо в атрибуте onсобытие .

Например, для обработки события click на кнопке input , можно назначить обработчик onclick вот так:

Этот код в действии:

Можно назначить и функцию.

Например, пусть при клике на кнопку input запускается функция count_rabbits() . Для этого запишем вызов функции в атрибут onclick :

Напомним, что имена атрибутов HTML-тегов нечувствительны к регистру, поэтому атрибут oNcLiCk сработает также, как onClick или onclick .

Но если вы хотите придерживаться хорошего стиля (или спецификации XHTML), то имена тегов и их атрибуты должны быть указаны в нижнем регистре.

Когда использовать

Такой способ установки обработчиков очень удобен — он нагляден и прост, поэтому часто используется в решении простых задач.

У этого способа установки обработчика есть и минусы. Как только обработчик начинает занимать больше одной строки — читабельность резко падает.

Впрочем, сколько-нибудь сложные обработчики в HTML никто не пишет. Вместо этого лучше устанавливать обработчики из JavaScript способами, которые будут представлены ниже.

  • Просто для простых задач
  • Смесь javascript-кода и HTML-разметки
  • Сложные обработчики писать сложно или невозможно

Через свойство объекта

Самый близкий родственник описанного выше способа — установка функции-обработчика через свойство onсобытие соответствующего элемента. Этот способ тоже будет работать в любом браузере с поддержкой JavaScript.

Для этого нужно:

  1. получить элемент
  2. назначить обработчик свойству on+имя

Вот пример установки обработчика события click на элемент с id="myElement" :

Этот код в действии:

Стоит сразу обратить внимание на две детали:

    Это именно свойство, а не атрибут. Поэтому, хотя технически и есть кроссбраузерные способы назначать обработчики через setAttribute , но лучше их даже не знать, а пользоваться прямым присвоением.

Когда браузер видит свойство on. в HTML-разметке — он создает функцию из содержимого кавычек.

В этом смысле эти два кода работают одинаково:

  1. Только HTML:
  2. HTML + JS:

Иначе узел просто не будет найден.

Конечно, можно и не создавать анонимную функцию, а использовать любую уже готовую:

Обратите внимание — свойству присваивается именно сама функция-обработчик doSomething , а не doSomething() :

doSomething() — это результат запуска функции, а так как вызова return в ее коде нет, то этот результат будет undefined .

Сравните это с атрибутом. Там — наоборот, скобки нужны:

Это различие легко объяснить. Дело в том, что при назначении onclick в HTML браузер автоматически создает функцию-обработчик из содержимого кавычек. Получается, что последний пример — это по сути то же самое, что:

Когда использовать

Описанная установка обработчика через свойство — очень популярный и простой способ.

У него есть один недостаток: на элемент можно повесить только один обработчик нужного события.

  1. Удобный и надежный способ, работает из javascript
  2. Только один обработчик на событие

Конечно, можно при назначении нового обработчика копировать предыдущий и запускать его самостоятельно. Но лучше использовать специальные методы назначения.

Специальные методы

Представленных выше методов недостаточно для случаев, которые возникают при разработке серьёзного JavaScript-приложения.

Классический пример — установка обработчика на событие «содержимое окна загрузилось»:

Существует два основных интерфейса для установки событий.

Решение Microsoft

Методы, предложенные Microsoft, работают только в браузерах Internet Explorer и Opera(она поддерживает метод Microsoft для лучшей совместимости).

Обратите внимание — установка и удаление обработчика оперируют одной и той же функцией handler .

Так было бы неправильно:

Поэтому при назначении обработчика, если вы планируете его потом снимать — необходимо где-то сохранить указатель на функцию.

Как уже говорилось ранее, вы можете установить несколько обработчиков на одно событие одного элемента:

Этот код в действии (будет работать только в Internet Explorer/Opera):

Установка по стандарту W3C

Решение W3C работает во всех современных браузерах, кроме Internet Explorer.

Обратите внимание, что имя события указывается без префикса «on».

Еще одно отличие от решения Microsoft это третий параметр – фаза.
Если он установлен в true , то при срабатывании события во вложенном элементе, обработчик будет вызван на фазе «перехвата», а если значение будет false , то — на фазе «всплывания». Подробнее об этом будет написано далее, в разделе этой статьи «Порядок срабатывания событий».

Использование — аналогично решению от Microsoft:

Как и в других случаях, вы должны передать имя обработчика не ставя круглых скобок, иначе функция будет выполнена сразу, а в качестве обработчика будет передан лишь её результат.

  1. Сколько угодно обработчиков
  2. Кросс-браузерные несовместимости

Далее мы вернемся к различным способам установки обработчиков и в подробностях рассмотрим, как сделать все кросс-браузерно.

Объект «событие» ( event )

Объект событие всегда передается обработчику и содержит массу полезной информации о том где и какое событие произошло.

Способов передачи этого объекта обработчику существует ровно два, и они зависят от способа его установки и от браузера.

В браузерах, работающих по рекомендациям W3C, объект события всегда передается в обработчик первым параметром.

При вызове обработчика объект события event будет передан ему первым аргументом.

Можно назначить и вот так:

Интересный побочный эффект — в возможности использования переменной event при назначении обработчика в HTML:

Это работает благодаря тому, что браузер автоматически создает функцию-обработчик с данным телом, в которой первый аргумент event .

Internet Explorer

В Internet Explorer существует глобальный объект window.event , который хранит в себе информацию о последнем событии. А первого аргумента обработчика просто нет.

То есть, все должно работать так:

Обратите внимание, что доступ к event при назначении обработчика в HTML (см. пример выше) по-прежнему будет работать. Такой вот надежный и простой кросс-браузерный доступ к объекту события.

Кросс-браузерное решение

Можно кросс-браузерно получить объект события, использовав такой приём:

Получение события при inline-записи

Как мы уже говорили раньше, при описании обработчика события в HTML-разметке для получения события можно использовать переменную с названием event .

Этот код в действии:

Это совершенно кросс-браузерный способ, так как по стандарту event — название первого аргумента функции-обработчика, которую автоматом создаст браузер; ну а в IE значение event будет взято из глобального объекта window .

Что дает объект события?

Из объекта события обработчик может узнать, на каком элементе оно произошло, каковы были координаты мыши (для событий, связанных с мышью), какая клавиша была нажата (для событий, связанных с клавиатурой), и извлечь другую полезную информацию.

Например, для события по клику мыши ( onclick ), свойство event.target (в IE event.srcElement ) содержит DOM-элемент, на котором этот клик произошел.

Более подробно это описано в следующей статье Свойства объекта событие.

Порядок срабатывания событий

Примечательно, что на одно событие может реагировать не только тот элемент, на котором произошло событие, но и элементы над ним.

Это очень удобно, например если в элементе содержатся много дочерних HTML-тегов — не обязательно ставить обработчик на каждый, достаточно указать один обработчик на родителе и в нем ловить все события.

Рассмотрим ситуацию, когда у вас есть три элемента «вложенных» друг в друга.

Если на каждом из них будет свой обработчик события, например onclick , то обработчик для какого элемента будет вызван первым при клике, скажем, на d3 ?

Всего существует 2 модели поведения, они не имеют преимуществ между собой, но используют принципиально разные подходы. Стандарт W3C объединяет две модели в одну универсальную.

Всплывающие события (Bubbling)

В этой модели сначала будет выполнен обработчик на элементе 3, затем на элементе 2, и последним будет выполнен обработчик на элементе 1.

Такой порядок называется «всплывающим», потому что событие поднимается с самых «глубоких» элементов в представлении DOM, к самым «верхним», как пузырек воздуха в воде.

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события):

Остановка всплытия

Нужно понимать, что «всплытие» происходит всегда. При возникновении события на элементе, сигнал будет подниматься до самого высокого элемента, выполняя нужные обработчики.

Если какой-то обработчик хочет остановить всплытие и не выпускать событие дальше вверх — это делает следующий код:

Можно уложить блок if/else в одну строчку:

Перехват событий (Capturing)

Перехват — вторая, альтернативная всплытию модель порядка выполнения для события.

В этой модели сначала будет выполнен обработчик на элементе 1, затем — на элементе 2 и последним будет выполнен обработчик на элементе 3. Она называется «перехват», потому что родительские элементы могут обработать событие раньше, чем непосредственная цель события, как бы «перехватывая» обработку.

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события, не поддерживается в IE):

Такой порядок был предложен Netscape и никогда не поддерживался в Internet Explorer, поэтому в IE вы не сможете увидеть этот пример в действии.

Остальные браузеры поддерживают одновременно такой порядок и порядок всплытия, но из-за проблем с Internet Explorer де-факто его почти никто не использует.

Порядок обработки в стандарте W3C

Решение от W3C объединяет обе модели: перехват и всплытие в одну универсальную.

При совершении действия, сначала событие перехватывается, пока не достигнет конечного элемента, затем всплывает.

Таким образом, разработчик сам решает, когда должен срабатывать обработчик события – при перехвате или при всплытии.

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события, не для IE):

Если в качестве третьего параметра функции addEventListener передать значение true , то событие будет срабатывать на фазе захвата, если false – то после окончания захвата, на фазе всплытия.

При установке обработчиков классическими методами (через свойство элемента или атрибут html тега) события всегда будут срабатывать на фазе всплытия.

Дальше мы вообще не будем рассматривать фазу захвата, так как в реальной жизни используется только всплытие.

Действие браузера по умолчанию

Браузер имеет своё собственное поведение по умолчанию для различных событий.

Например, клик по ссылке — сменить URL, клик правой кнопкой мыши — показать контекстное меню и т.п.

В ряде случаев реакцию браузера на событие можно убрать в обработчике.Для этого у IE и W3C есть, как и раньше, два по сути близких, но по виду разных способа:

Вместо if/else можно записать одну строчку:

Некоторые поведения по умолчанию происходят до вызова обработчика события. В этом случае их, конечно же, отменить нельзя.

Например, при фокусировке на ссылке — браузер выделяет ее пунктирной рамочкой.
Это действие выполняется до события focus , поэтому отменить выделение в обработчике onfocus нельзя.

А переход по ссылке выполняется после события, поэтому его отменить можно.
Обработчики onfocus и onclick на этой ссылке отменяют поведение по умолчанию:

При клике перехода не произойдет, а рамка вокруг ссылки появится.

Смысл return false из обработчика

Возвращение return false из обработчика события предотвращает действие браузера по умолчанию, но не останавливает всплытие. В этом смысле следующие два кода эквивалентны:

Заметим, что хотя даже если всплытие и действия по умолчанию остановлены, но другие обработчики на текущем элементе все равно сработают.

Действительно, браузер даже не гарантирует порядок, в котором сработают обработчики на одном элементе. Назначить можно в одном порядке, а сработают в другом.

Поэтому тем более один обработчик никак не может влиять на другие того же типа на том же элементе.

Резюме

  • Что такое события и как они работают.
  • Как назначать обработчики — от HTML до специальных методов.
  • Зачем нужен объект события и как его получить.
  • Как событие плывет в DOM-документе. Где можно поймать и как остановить.
  • Что такое и как предотвратить действие браузера по умолчанию.
  • Как с этим соотносится return false.

В следующих статьях мы разберем, какие свойства есть у объекта события, как их кроссбраузерно обрабатывать и назначать обработчики.

Спасибо за статью.
Эта часть наверное самая важная для понимания javascript

Полностью согласен, давно ждал подобной статьи. Огромное спасибо.

Статья супер, адрес в избранное

А вы знаете что когда вы нажимаете посмотреть! на одном из скриптов происходит xss атака??у меня просто защита стоит(noscript) всем посоветую

А вы знаете что когда вы нажимаете посмотреть! на одном из скриптов происходит xss атака??у меня просто защита стоит(noscript) всем посоветую

А если в FireFox тег div не реагирует на onkeyup (press и т.п.), можно ли ему прописать обработчик на событие onkeyup?

Вот еще один метод установки нескольких обработчиков событий, о котором не было сказано в статье:

И вызов данного метода:

А каким образом в данном подходе можно удалить один из вложенных обработчиков?

т.е. alert(‘1’); произойдет лишь один раз, в момент первого клика, после оно никогда не повториться (сколько не кликай). Но при ситуации нескольких обработчиков на одно событие данный код начнёт разрастаться как снежный ком. И код может стать не универсальным.
Хотя, может кто из читателей сайта то придумает более симпатичное решение по удалению обработчика?

Непонятно как реализовать функционал detachEvent в таком подходе.

Ну если честно, то по-моему мнению, в хорошем коде вообще в событии стоит лишь вызов функции, реагирующих на событие и ни какой логики по обработке события! 🙂

А показанный выше мной пример, скорее для того, что б все знали, что и такое тоже работает.

Непонятно как реализовать функционал detachEvent в таком подходе.

Сам думал долго над этим, но кроме варианта показанного чуть выше ничего не нашел.


С уважением, Владимир Вашурин

Отличная статья! Спасибо.

Есть еще нюанс, связанный со стилями для элементов. Если есть абсолютное позиционирование.
Например:

Если в стилях поменять position: relative на position: absolute для элемента (чем выше по дереву DOM, тем хуже), то в IE(6/7) событие даже не будет генерироваться.
Например поменяем для wndMain, то события вообще не будут генериться для его внутренних элементов и его самого(хоть какой кнопкой кликать).

Выложили бы что ли где-нибудь этот код. Я пока не понимаю, что такого IE делает не так.

У меня лично абсолютно позиционированные элементы обрабатывались всегда без проблем. Может, чего-то не заметил?

Дело не в нюансах, у вас проблема с версткой, точнее с перекрытием элементов, barStatus если позиционировать абсолютно перекрывает barTitle на которорый и вешается событие. а по причине того, что элементы друг в друга не вложены всплытия события не происходит.

P.S. Знаю что некропост, просто такие комменты могу ввести в заблуждение тех кто этот инструмент (javascript) осваивает.

Спасибо! Это лучший сайт по ява-скрипту! )))

Если необходимо прикрепить обработчик для события, передав ему параметры, специфичные для данного объекта, то как это сделать?

Например, при таком назначении в момент прикрепления сразу произойдёт вызов alert(‘test’)

Если же вместо al(‘test’) использовать function()< al('test') >, то позже, как я понимаю, будет сложность снять этот обработчик?

Отличная статья. Доходчиво изложено и с примерами
Хотелось бы видеть развитие темы, углубление. В связи с этим появился вопрос. В статье было сказано что.

При установке обработчиков методами attachEvent/detachEvent this внутри обработчика всегда указывает на объект window и совершенно бесполезен.

Поэтому при использовании этих методов в библиотеках и фреймворках добавляется дополнительная «обертка для обработчика», устанавливающая правильный this.

Приведите, пожалуйста, пример реализации «обертки» или посоветуйте где об этом можно почитать?

Спасибо за статью, за существование этого сайта.

// Обработчик для mouseout
function mouseoutHandler(event) <
event = event || window.event
var relTarg = event.relatedTarget || event.fromElement;
// relTarg — элемент, на который перешел курсор мыши
>

тут наверно вместо fromElement надо toElement;

Спасибо полезная информация особенно про захват

Методы
myElement.attachEvent(«on» + событие, обработчик) и
myElement.detachEvent(«on» + событие, обработчик)
поддерживает не только IE, но и Opera

Универсальный кроссбраузерный способ обработки событий:

targt — объект, поэтому запускать скрипт лучше вот так:

а функцию attachEvents записать вот так:

Да, ну и вызвать функцию main() в документе:

Объясните пожалуйста,
если у DOM элемента несколько свойств,
на которые повешены обработчики событий мыши,
то в какой последовательности они будут срабатывать?

Например при наведении на него и щелчке мыши:

  • onmouseover
  • onmousedown
  • onfocus
  • onclick

и еще, чем отличается
onmouseover=»return fun1(arg1,arg2)»
от
onmouseover=»fun1(arg1,arg2)»

и куда собственно эти функции возвращают значение(если возвращают)?

Вот не пойму никак, а чего событие onclick() можно только Id присваивать, всему классу одно событие нельзя?
Например:
Вот так работает:

Потому что событие вешается на элемент, а функция getElementsByClassName , которая, кстати, не кроссбраузерная, возвращает *список* элементов.

Событие можно повесить на каждый.

Кстати, селекторы библиотеки jQuery предоставляют возможность вешать обработчики на список.

Илья Кантор спасибо
Просто я уже третий день бьюсь вот над такой задачей:

И нужно присвоить одно событие onclick для всех ссылок. Не подскажете как это можно организовать?

Все решил задачу Спасибо за наводку, сам бы не догадался

никогда не задумывался и писал всегда «ev = ev || window.event».

но ведь «ev» не передается только если обработчик задан так

те если нигде не ошибся то «ev = ev || window.event» совсем и не нужно когда речь идет о EventListener

В Internet Explorer существует глобальный объект window.event, который хранит в себе информацию о последнем событии. А первого аргумента обработчика просто нет.

это не так. еще ие6 вполне корректно выполнял строчку

Ещё один способ напоследок:

Доброго всем дня.
Объясните пожалуйста для «чайников» как правильно кроссбраузерно остановить всплытие. на своих примерах получается только для IE сделать или только для FF.

у меня почему то

не работает нигде кроме Opera , не подскажете почему ? вот так у меня это реализовано :

в html документе

в javascript документе

да, кстати , когда javascript код переношу в html файл в конец

, то во всех браузерах(ff , opera , chrome, safari) работает нормально

Все дело в разнице генерации страницы браузерами. В этой статье специально было выделено в рамочку:
«Все вызовы типа getElementById должны запускаться после описания соответствующего HTML-узла, а лучше — после окончания загрузки страницы.
Иначе узел просто не будет найден.»

Судя по описанной вами проблеме, строчка:

Выполняется до того как сгенерится сам элемент. И следовательно выполнится:

И корректно (вернее не корректно, а так чтобы работало) обработает только Опера. В остальных браузерах скрипт упадет в ошибку. А вот если перенести скрипт в конец, то все будет работать.

Здравствуйте, подскажите пожалуйста как организовать таку вещь:
мне нужно что бы при окне браузера развернутом не в максимайзе(т.е. не на весь экран) и при этом стрница находится в граничном положении(самый низ/верх/право/лево) при расширении окна вручную(когда наводишь на грань браузера и начинаешь ее увеличивать как хочешь) в сторону от границы наружу, сторона приклеевалась к стороне браузера, помогите плз.

В каких случаях alert() может выскакивать дважды?
Удивляет цепочка: post — alert (‘ушло’) — OK — alert (‘ушло’) -OK
Странно, что не 3 раза выскакивает — было бы ещё веселее .

На самом деле, capturing в IE использовать можно. Ограничений масса: метод расчитан только на события мыши, перехват теряется при потере окном фокуса, геморройная работа с preventDefault и масса других факторов.
Но если в целом, это вкупе с альтернативными макрософтовыми событиями (напр. activate и deactivate — такие же focus и blur, только бабблятся) может помочь сделать более-менее вменяемую эмуляцию capturing.

Иллюстрация метода setCapture:

Не пугайтесь: в IE6 этот код может вызвать блокировку окна.

Под диспетчером (dispatcher) подразумевается некий корневой элемент, собирающий события, и потом обрабатывающий их с учетом (e.srcElement||e.target), т.е., непосредственно практическое применение capturing.

Автор:
«Все вызовы типа getElementById должны запускаться после описания соответствующего HTML-узла, а лучше — после окончания загрузки страницы.
Иначе узел просто не будет найден. » Тогда почему в
document.getElementById(‘myElement’).onclick = function() <
alert(‘Спасибо’)
>

вызов идет до создания кнопки?

Нашел статью по запросу getElementById. Сам щас пишу скрипт, и не могу прикрутить событие к iframe по onKeyUp.
Хорошая статья, но у меня в браузере не работают Ваши примеры с getElementById, даже с textarea, даже большая половина с вашего сайта не работает — странно.
У меня 7 ИЕ. Ни че не понимаю.

Не могли бы подробнее?

«Кликни меня
При клике перехода не произойдет, а рамка вокруг ссылки появится.»

В IE8 сыпется иксепшн а в хроме нет рамки

Почти В IE8 нет иксепшна — это хорошо.
Но теперь в IE8 клик на ссылке перекидывает на самый верх страницы. А в Chrome рамка так и не появилась.

Chrome не выделяет таким образом активные ссылки по стандарту.
Но можно сделать, добавив в css:

Аналогичным же способом данную пунктирную рамку можно убрать из firefox.
(P.S. Извиняюсь что не по коду, IE для меня пока не доступен.)

А в ie «перебрасывает» на верх страницы, наверное из-за #

Че то вообще ничего не понятно. Когда начнется объяснение нормальное.. Может кто нить подкинет что нибудь по проще..Для новичка?7

С какого момента непонятно? Что непонятно?

Если честно только сейчас понял разницу между свойством и атрибутом . )

А можно вопрос, использую

в FF срабатывает нормально, а в IE событие не присваивается

все разобрался для IE написал

Хороший сайт, но к сожалению ссылку на вас разместить негде. Но советовать буду обязательно.

Сколько не вчитывался в статью и приведенные в кометариях примеры, так и не смог понять как сделать в приведенном ниже примере так. Что бы событие срабатывало только для первого элемента, но не страбатывало для вложеных в него.

Понятно что div c наследует событие от div c , и div c наследует событие от div c

Но из статьи я так и не понял как ОСТАНОВИТЬ срабатывание события на «дочерних» к первому элементах, или если сказать по другому. как запретить наследование события «дочерними» элементами.

Очень надеюсь на помощь знающих людей.

Вписать обработчик того же события для всех потомков первого уровня, в котором добавить event.stopPropagation()(для Лисы)

Небольшое уточнение к моему предыдущему посту, цель не просто остановить обработку событий, это можно было бы просто организовать через:

А сделать страбатывание Алерта в любом случае, даже когда onmouseover происходит над областями даже перекрытое Div с и

Еще раз. алерт должен выполнится только один раз, при наведении на любой из DIV’ов, учитывая что обработка события запускается с старшего в ерархии элемента.

Простите, не заметил, что вы уточнили свой вопрос, и он изменился по сути. Впрочем, все же рассмотрим еще раз способ решения того вопроса, так как предложенный выше был неудачен. Соответственно, это относится и к этому вашему посту. В случае, если бы у корневого дива имелся не 1 потомок 1-го уровня, а несколько, то пришлось бы для каждого из них прописывать такой обработчик, который вы и предложили. В этом случае лучше всего проверять target(srcElement) в обработчике корневого дива. И если className(ну или id, если по нему проверять) не совпадает с таковым у корневого дива — то ничего не делать.

Теперь перейдем собственно к вашему вопросу. Для удобства понимания сути проблемы лучше переформулировать задачу так: mouseover не должен вызываться в случае, если переход мыши осуществляется между потомками одного корневого элемента(или между потомками и самим корневым элементом). Теперь способ решения становится очевиден. В обработчике корневого элемента производится проверка target и relatedTarget(toElement и fromElement). Если оба объекта имеют общим предком корневой элемент, то обработчик ничего не делает.

О. нашел как проще обьяснить что мне нужно.
Нужен кросбраузерное решение — аналог функции onmouseenter

отличная статья, но меня интересует вопрос: можно ли из javascript управлять перемещением курсоры мышки?

Помогите пожалуйста
есть такая функция(код из вашей статьи)

эта функция присваивается событию onScroll,в идеале нужно чтобы при прокручивании скрола,блок «my-message» оставался на месте,но при этом он перескакивает-как это можно исправить?

Для этого существует css правило position:fixed. А ИЕ6 бодро идет лесом

Ах, я вас так понимаю.

М. Есть возможность поверять, находится ли курсор мыши над объектом? Предположим, функция запускается, когда над объектом курсор мышки, в ней есть задержка, и некоторая другая функция запускается после этой задержки, но в случае, если курсор мыши остался над объектом. Как проверить?

Устанавливать флажок в событии mouseover. Снимать флажок в событии mouseout. В «некоторой другой» функции проверять значение флажка.

Гость, спасибо! Да, старею я, похоже.

Народ, как повесить событие на все строки ввода разом??

Что в этой шняге неправильно?

P.S. isMSIE() — функция, определяющая, уж не эксплорер ли это часом.

Вообще понять не могу. У меня в браузере кнопка не получила никакого события. Страница загрузилась и сразу «Не активный кнопкоо! ))». Почему так? При том такая ситуация только в FF 3.5. Opera, Chrome, Safari выполняют скрипт именно так, как я ожидаю. В IE не пробовал.

Это проблема FF, как оказалось Разобрался

После данной статьи, я возненавидел окончательно и основательно, бесповоротно и навсегда IE.

В IE6 «йа кнопкоо» работает нормально.

Добрый вечер!Не могу понять, почему не работает обычный пример как в статье(в JS совсем еще зеленый), то есть при клике на #pip эффекта никакого

и соответственно html

Причем Лис FireBug’ом ошибок не выдает

Привет
Не работает потому что
1. addEventListener в качестве первого параметра принимает имя события без префикса on h.addEventListener(«click», p, false);
2. li с обработчиком event.stopPropagation() перекрывает распространиение события к предку, попробуйте раскрасить список и все станет очевидно. Красная область кликабельная, так как клик происходит непосредственно на элементе ul, а вот синяя перекрытая stopPropagation и алерта нету.

Привет!Елки!насчет stopPropagation так задумано и было, опробовать хотел, останавливает он событие только для себя, или также и всплытие дальше по дереву DOM, а вот с «click» вместо «onclick» — спасибо, невнимательность, сейчас в статье повнимательнее глянул, так и есть.В общем благодарю!

Мне надо заблокировать все события на странице, в особенности onmousedown, onkeydown (onclick, ondblclick тоже). Чтобы и мышка, и клавиатура страницей на какое-то время не обрабатывалась. Как это сделать?

Такая штука не срабатывает (explorer игнорирую):

Мне надо заблокировать все события на странице, в особенности onmousedown, onkeydown (onclick, ondblclick тоже). Чтобы и мышка, и клавиатура страницей на какое-то время не обрабатывалась. Как это сделать?

Вариант 1. Вернуть false при возникновении события.
Пример:

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

и 2 варианта вместе тоже можно применять.

У меня такой вопрос: допустим написал свою очень нужную функцию (myfunction), приаттачил к HTML такой файлик:

Далее написал еще одну функцию и приаттачил еще один подобный файлик. Ясно что я переопределил событие onload для document и работать будет только вторая функция. Ну а что же делать когда я прикручу jQuery? Получается будет работать только что-то одно. Не хочется в конец HTML перед тегом < /body> вставлять < script> if (. ) . ; if (. ) . ;< /script> Как обойти не навредив другим скриптам и чтоб все в onload влезло? Писать перед < body> : этот злосчастный < script> c «ифами»? — выход, но я не знаю что случится если я прикручу стороннюю библиотеку которая может переназначить событие onload! Или в этих умных библиотеках как то все по другому и они onload не трогают?

Вопрос может быть и глупый, но.
На радиокнопку навешена функция

Выдаёт TRUE независимо от состояния кнопки до клика.
Собственно вопрос — как тогда узнать состояние кнопки?

а если так?
if($(this).is(«:checked»))

Parse error: syntax error, unexpected ‘:’

Виноват, насчёт ошибки — сгрешил.
Но результат тот же.
Можно, конечно, пробежаться по значениям всех других кнопок.
Их состояние даётся реальное.
И методом исключения, так сказать, установить состояние кликнутой кнопки до клика.
Но как-то это коряво.

Сам себе говорю — глупость сморозил.
В функцию по клику передаются уже изменённые значения радиокнопок.
Поэтому всегда TRUE.
Никакого другого выхода кроме как запоминать кликнутую кнопку в переменной не проглядывается.
Тогда в функции можно определить повторное нажатие той же кнопки

Не очень понял смысл return false в этом примере (да и вообще отличия в работе, когда для остановки действия по умолчанию используется возврат, от метода preventDefault и свойства returnValue):

preventDefault останавливает действие браузера по умолчанию, зачем еще false возвращать?

На всякий случай.

Проясните пожалуйста один момент:

Зачем нужно event = event || window.event

если во всех браузерах, реализующих w3c, event и без того будет доступен в теле обработчика как первый параметр, а в IE — как глобальный объект?

То есть в каком таком случае код не заработает без этой строки.

В ослике не заработает.

Как видите event уже резервируется как локальная переменая перекрывая глобальную, а потому ту приходится получать через window.

Подскажите плиз, как реализовать следующую задачу:

На сайте есть окно для ввода текста с применением тега input и ниже текстовая гиперссылка. необходимо чтобы она отправляла на две разные страницы: в первом случае — при вводе в окно определенного слова или значения — на одну страницу, во втором случае — при вводе любых других слов или значений — на другую страницу.

Очень нужно, помогите пожалуйста с кодом! Зараннее благодарен!

А вообще для вопросов есть форум, в комментариях следует задавать вопросы по статье.

Привет,
пытаюсь повторить ваш пример и не получается . Событие не назначается. Т.е. я нажимаю на кнопку, а сообщение с текстом «test» не появляется.

Необходимо поменять местами код кнопки и код скрипта. Код кнопки должен быть выше.

Здесь сначала один раз сработает alert(x), а потом всё время alert(‘2’)

а здесь кнопка сработает всего лиш один раз

Здравствуйте!
Сразу скажу, что я не кодер (или не скриптер, как это у вас правильно сказать не знаю, не программист в общем), я дизайнер.
Но не думайте, я именно по теме пишу! Вопрос касается объект события — window.event.
Мне в работе моей частенько помогает одна страничка, уж не помню где добытая. Она подбирает более менее приемлемую цветовую гамму на основе одного цвета. Но есть одна загвоздка: на отрез отказывается работать в FF и замечательно пашет в IE. Из-за моей ненависти к ослику (как это у меня так сдержанно получилось!? %) без мата даже) я решился-таки на изучение js (ну, изучение — это сильно сказано).
Цель простая: понять, где мелкософтовская собака зарыта в том коде, и исправить этот код. Причём замечу, мне хочется исправить не на кроссбраузерность, а именно так, чтоб в FF всё работало а в ie — кукиш!
Кстати, тег мета сообщает, что штуковина сгенерирована фронтпэйдем, может это важная информация для вас.
Для себя я уже выделил в одтельные файлы таблицу css (отредактировав её не мало) и скрипт js (который изначально был одной строчкой, мной же отстркуктурирован в более читабельный вид переводами строк)
Здесь попытаюсь представить код, изначальный, но скрипт для вас же вставлю отструктурированный.

Не удаётся всё сразу, попытаюсь отдельно.

не запускается, как его запустить

C html вообще ничего не удалось вставить но внутри тела его есть вставки скрипров:

Я выделил в предыдущем посте строки, на которые ругается FireBug — мол window.event is not defined
Я пробовал и с этой страницы кроссбраузерную примочку применить, пробовал даже прикрутить event.js с вашего же сайта.
Я сдаюсь, не понимаю как это вылечить.
А программка эта очень нужна (часто в момент общения с заказчиком нужно пожонглировать цветовыми гаммами).

Помогите переделать этот скрипт в скрипт для FireFox (желательно, чтоб ie при этом отвалилось!)
Было бы вообще супер, если бы я ещё и понял, как лечение прошло! Потому что, меня js заинтересовал в процессе чтения этого самоучителя.
Кстати, огроное спасибо Илье, автору самоучителя!
И конечно же тем спасибо, кто в проблеме моей мне поможет)

только в IE ивентом является window.event
в нормальных браузерах ивент передается в функцию

привет, нужна помощь.
в функции сделал вот такой цикл

по идее после выполнения цикла при щелчке на любой ссылке должен всплывать ее номер, а у меня всегда выводится последний номер ссылки.

В чем проблема?? Зарание спасибо.

Классический пример на замыкания.

прочитал про замыкания, разобрался.

Подскажите пож. Хотел посмотреть, как можно менять надпись на кнопке, оперативно. Не стал заморачиваться, немного изменил код кролей. Где ошибка? Я хотел что бы после нажатия, надпись на самой кнопки поменялась, а не выскакивал в отельном окне. Спасибо.

function count_rabbits() <
onclick=»this.style.value = «спасибо»
>

Ошибка во второй строчке. Огромная такая ошибка. «Полнейшее незнание и непонимание JS» называется. Исправляется так.

Да, действительно. Такая строка была допустима в ActionSсript , так как там изначально скрипт можно расположить в теле объекта и его ID использовано по умолчанию, без дополнительно указания.

Буду искать книги по JS, на сайте материал хороший, но структура и объяснения хромают. Нужны базовые навыки JS для понимания.

Очень хочется понять как реализовать самому событие mouseenter из jQuery. Я так понимаю, что весь фокус в игре со всплытием и перехватом событий, только вот ничего не приводит в нужному результату.
У кого нибудь есть идеи, или все пользуются jQuery mouseenter и даже не задумываются как это работает?

Привет!
А подскажите пожалуйста, как с помощью указанных примеров добавлять данные в функцию, и можно ли вообще.

Скрипт для примера:

В Хроме ИЕ — работает в ФФ — нет,
а —

сообщает e=null во всех браузерах?
заранее спасибо )

Задачка такая:
Есть ряд кнопок

Мне нужно прикрутить к ним обработчик onclick «processor_javascript».
При этом если в браузере включено исполнение javascript, то мне не нужно обращаться к «processor_php», а все обрабатывать в «processor_javascript».

Вроде все просто.

Запускаю (в FF), кликаю, а меня все равно отправляет в «processor_php».

При этом если тупо писать в тег

, то все работает как задумано — при включенном js — работает processor_javascript, при выключенном — processor_php.

Долго экспериментировал, нашел такую конструкцию (думаю что она кривая)

Можно ли как-то решить мою задачу способом form.childNodes[i].onclick = function()<>?

Подскажите пожалуйста, а можно ли с помощью события onclick в теге <а> достать значение атрибута title и поместить его в переменную


Методы, предложенные Microsoft, работают только в браузерах Internet Explorer и Opera(она поддерживает метод Microsoft для лучшей совместимости).

а вот здесь я наблюдаю что этим методо пользуется только IE , Opera также использует метод addEventListener как и Firefox , так что получается Opera в первую очередь использует этот метод.

Здравствуйте, у меня вопрос. Если присвоить событию анонимную функцию, как передаваемые параметры function(arg1,arg2. ) будут интерпретироваться в событии

document.getElementById(‘button’).onclick = function() <
alert(‘Клик’)
равнозначно строке ниже.
Только HTML:

Спасибо за статью. Хотелось бы уточнить некоторые моменты.

В этом смысле следующие два кода эквивалентны:
function handler(event) <
.
return false
>
function handler(event) <
.
if (event.preventDefault) <
event.preventDefault()
> else <
event.returnValue = false
>
>

Для основных обработчиков событий (не назначенных с помощью addEventListener) эти два кода полностью эквивалентны? Или есть разница?
И какие ещё стандартные объекты, кроме event, доступны в атрибутах?

И чтобы не появлялись контуры вокруг объектов, нужно определять css свойства:

>Способов передачи этого объекта обработчику существует ровно два, и они зависят от способа его установки и от браузера.

Почему в браузере firefox 22.0 ни один из них не работает? Существует какой-то еще способ для fiirefox’a или firefox не умеет работать с событиями?

«Заметим, что хотя даже если всплытие и действия по умолчанию остановлены, но другие обработчики на текущем элементе все равно сработают»

— как сделать чтобы другие обработчики на текущем элементе останавливали срабатывание первого обработчика .

Объясните кто знает плиз
есть html

в результате в callback в event.target — img
почему?

Потому что клик происходит по изображению, то есть, если просто, то таргет — это объект вызвавший событие, а до элемента «а» просто «доходит» событие по всплытию или перехвату.
В колбеке «а» — это this.
О порядке срабатывания события

Не могу понять, почему кросс платформенная запись event = event || window.event вдруг превратилась в e = e || window.event. e — это эквивалент event?

В статье говорится:

Решение W3C работает во всех современных браузерах, кроме Internet Explorer.

Наверно, стоит добавить, что в последних версиях IE (по крайней мере, в IE 11 — точно) работает решение W3C, а вот прежнее решение MS (attachEvent) — больше не работает.

И «перехват событий» (capturing) — в IE 11 работает, а в статье говорится, что нет.

дата первого камента: 17 сентября, 2008 — 15:17
стало быть статья из тех времен, если не редактируется постоянно.
за 6 лет много чего поменялось.

Пробую следующий код:
HTML-HEAD-SCRIPT
function showevent(a) <
alert(a);
alert(«event» in window);
alert(«tag: » + event.srcElement.tagName);
>
/SCRIPT-/HEAD-BODY-TABLE-TBODY-TR
TD onmousedown=»showevent(‘first-param’)»>Событие mousedown
/TR-/TBODY-/TABLE-/BODY-/HTML
Работает одинаково в:
IE6
Opera 32.0
Google Chrome 45.0.2454.101 m
и говорит, что «event» in window == true.
Вопрос: если первым параметром передается объект event, то почему «a» не является объектом event?

Может кто-нибудь объяснить эту конструкцию?

function setupHandlers(root) <
setAttributes(root, <
В особенности это ->
«onmouseup» : «handleMouseUp(evt)»,
«onmousedown» : «handleMouseDown(evt)»,
«onmousemove» : «handleMouseMove(evt)»,
>);
>

function setAttributes(element, attributes) <
// doSomething
>

Здравствуйте. Скажите пожалуйста, почему в опере не работает , если нажатие на него осуществляется посредством . В хроме и мозиле все работает. Попытка увязать события клика по метке с кликом по кнопке безрезультатны. Я абсолютно узколобый в отношении JS (Паскалем всю жизнь занимался), пытаюсь разобраться и освоить. Буду весьма благодарен за консультацию. Интересуют лишь азы JS, без JQuery и прочих надстроек. Ваш сайт на редкость понятен и информативен, в отличие от остального мусора в Сети. С уважением, Amon.

Незаменимая помощь в разработке любых программ и сайтов. То, что нужно!

I adore this article for its well-researched content and great wording 1v1 battle

have a peek at these guys

Wordle is a word game that combines the power of words with game-like fun. The goal of the game is to arrange as many words as possible into a grid and try to create a beautiful piece of artwork. This one-of-a-kind experience will challenge your mind while providing hours of entertainment.

Мероприятия — один из важнейших компонентов любого веб-сайта. Они могут варьироваться от торжественного posterdle открытия компании до flagle запуска продукта или даже праздника для сотрудников.

five nights at freddy’s is a horror game series created by Scott Cawthon. The games are set in a pizza restaurant called Freddy Fazbear’s Pizza, which is home to five animatronic animals — Freddy, Bonnie, Chica, Foxy and Golden Freddy.
The player controls the protagonist who must defend themselves from the animatronics and survive until 6 AM when they are rescued by the security guard.
The first game was released on August 8th, 2014 for Microsoft Windows and macOS platforms. A mobile version of Five Nights at Freddy’s was released on November 17th, 2016 and a console version of the game was released on September 23rd, 2017 for Xbox One and PlayStation 4 consoles.
Five Nights at Freddy’s has been critically acclaimed with some
You should also take part in wordle unlimited, the best crossword puzzle game out there!

wow, great post. it gave me a lot of useful information. sedecordle I look forward to your next posts.

Thank you for providing such useful information. I’ve been having trouble coming up with many questions about this topic. I’ll stick with you! play build now gg free

I had a lot of harvest after seeing this post of yours! Before, I used to play games, this is a fun game for entertainment, but now I will follow you, read your articles will have more knowledge. run 3

The information you shared is very accurate, heardle anime drift boss it gives me the knowledge that I need to learn. Thank you for sharing this useful information.

Я попробую реализовать это на сайте run games, и, возможно, это сработает. Я долго искал это решение, спасибо за разъяснение.

If you live in NY you might want to watch of a potential accident. In the case of one, don’t wait and contact today a car accident lawyer in NY

Will discover several games from the most well-known developers. geometry dash

An excellent way to show off the capabilities of a sports car’s brakes is to drive up to their maximum while applying them, throwing the car into a controlled skid. drift boss

The most alluring pastime possible is playing exciting io games with buddies. Take advantage of the opportunity to connect friendship and love while playing IO games.

It is very useful for me. I am so glad I found this article. I also always learn something new from your posts wordle answer today.

hi there, i do assume your blog ought to in all likelihood be having internet browser compatibility troubles. Each time i take a look at your weblog in safari, it appears high-quality but while opening in net explorer, it has a few overlapping issues. I truly wanted to provide you a short heads up! Except that, extremely good weblog! hello there! This blog put up couldn’t be written an awful lot better! Looking at this text reminds me of my previous roommate! He continuously saved talking approximately this. I maximum truly will ahead this newsletter to him. Pretty positive he could have a good examine. I appreciate you for sharing! This web site become… how do i say it? Relevant!! In the end i’ve found something that helped me.
메이저토토

Please do maintain up the extremely good paintings. I surely adored perusing your blog. It become quite all around created and simple. By no means like specific web sites i’ve perused that are genuinely no longer that accurate. Thank you alot! Certainly, this text is genuinely one of the very best in the history of articles. I am a antique ’article’ collector and that i from time to time read a few new articles if i discover them interesting. And i found this one pretty captivating and it must move into my series. Excellent paintings! Thank you a lot! A way to play on-line slots for the pleasant online casino apps, the quality online on line casino apps are apps like on-line casino video games which can be compiled for you in one app. Which has been very famous whether or not in thailand or neighboring countries and additionally meet the worldwide on line casino requirements of the world as properly similarly .먹튀폴리스

It’s a great and helpful piece of information. I am glad that you simply shared this information with us. I also refer to our article about these sources are trustworthy to use as tools for research. thank you so much for sharing this, it is extremely useful. Thanks again . Thanks for providing such good training. & Thank you for giving us such a great information. Thank you for sharing the information. Looking for such more content in the future. I feel very grateful that I read this. It is very helpful and very informative and I really learned a lot from it.
토토사이트

This submit couldn’t be written a great deal better! Looking through this post reminds me of my previous roommate! This is very exciting, you’re a completely skilled blogger. I have joined your feed and look forward to seeking more of your top notch publish. The writer is fiery about acquiring wood fixtures on the net and his examination approximately satisfactory wood furnishings has understood the association of this text. Exquisite data! I recently got here throughout your blog and had been studying alongside. I notion i might leave my first remark. I don’t understand what to say besides that i have. Quite accurate post. I simply stumbled upon your blog and desired to mention that i’ve honestly loved studying your weblog posts. Any way i will be subscribing on your feed and i wish you post once more soon. Massive thank you for the beneficial info. That is a fab weblog. Extremely helpful information. Thanks! Pleasant weblog here! Moreover your internet site loads up very fast! What internet host are you using? Can i am getting your accomplice link on your host?
선시티카지노도메인

For older parents, retirement or a large promotion at paintings is a time whilst celebration events are going to be a notable idea. Wonderful know-how. With thanks. That is a extremely good platform. I also give you an article about fortnite. Essentially, it’s far a pc recreation. It gives a brand new pores and skin to your favorite characters. Get this skins with skin generator. Revel in your fortnite enjoy. Thank you. This is such a notable resource that you are offering and you give it away without cost. I like seeing blog that recognize the cost of supplying a quality useful resource for free. I assume this is an informative put up and it’s far very beneficial and knowledgeable. I simply tripped upon your blog and ached to mention that i have absolutely loved reading your blog submit. Thank you for sharing. You’ve got stated very interesting information ! Ps first rate web page. fantastic goods from you, guy. I have apprehend your stuff previous to and you are just too outstanding. I clearly like what you’ve obtained here, surely like what you’re saying and the way in that you say it.
토토사이트

It’s so useful! Those seeking relaxation should go with this option
stumble guys 2

you are so exciting! I don’t consider i’ve examine some thing like this before. So great to discover any other character with a few proper mind in this issue. Significantly.. Thanks for beginning this up. This website is some thing that is required at the net, a person with some originality! I quite like studying via a submit which can make males and females assume. Also, many thank you for allowing me to comment! Spot on with this write-up, i genuinely suppose this superb web site needs a remarkable deal more attention. I’ll likely be returning to peer more, thanks for the advice! I’m very thrilled to discover this page. I wanted to thanks on your time for this outstanding read!! I certainly truely favored every little bit of it and i also have you ever saved as a favourite to have a look at new matters to your internet site.

I have been searching to find a comfort or effective procedure to complete this process and I think this is the most suitable way to do it effectively. I am really enjoying reading your well written articles. It looks like you spend a lot of effort . thank for dropping this story. I am definitely tired of struggling to find relevant and intelligent commentary on this subject. Everyone nowadays seem to go to extremes to either drive home their viewpoint or suggest that everybody else in the globe is wrong. thank for your concise and relevant insight. This is such a great resource that you are providing and you give it away for free.
안전놀이터

I’m having a small problem. I’m unable to subscribe to your rss feed for some reason. I’m using google reader by the way. This is actually appealing, You’re a significantly seasoned author. I have joined with your feed plus expect witnessing the very good write-ups. And additionally, We’ve shared your web blog inside our social networking sites. After reading your article I was amazed. I know that you explain it very well. And I hope that other readers will also experience how I feel after reading your article. I found this one pretty fascinating and it should go into my collection. Very good work!
다음드보증업체

Hello I am so delighted I located your blog, I really located you by mistake, while I was watching on google for something else, Anyways I am here now and could just like to say thank for a tremendous post and a all round entertaining website. Please do keep up the great work. Wonderful article, thanks for putting this together! This is obviously one great post. Thanks for the valuable information and insights you have so provided here. Pretty wonderful post. I simply came across your blog and wanted to state that I have really enjoyed surfing your post. I’ll be subscribing to your feed and I hope you compose once again soon . Found your blog in the Google bulk turtleneck shirts directory, very nice job, thanks.
메이저토토사이트

I perpetually visit your blog and retrieve everything you post here however I never commented however these days once I saw this post,메이저사이트

I have been searching to find a comfort or effective procedure to complete this process and I think this is the most suitable way to do it effectively. I am really enjoying reading your well written articles. It looks like you spend a lot of effort . thank for dropping this story. I am definitely tired of struggling to find relevant and intelligent commentary on this subject. Everyone nowadays seem to go to extremes to either drive home their viewpoint or suggest that everybody else in the globe is wrong. thank for your concise and relevant insight. This is such a great resource that you are providing and you give it away for free. 토토커뮤니티

A debt of gratitude is in order for sharing the information, keep doing awesome. I truly delighted in investigating your site. great asset. I really appreciate this wonderful post that you have provided for us. I assure this would be beneficial for most of the people. Thank you for another informative website. Where else could I get that type of information written in such a perfect way? I have a project that I’m just now working on, and I’ve been on the look out for such information. Usually dislike any form of commenting, but when you read an excellent publish occasionally you simply have to get from those lazy techniques. That is such a submit!

A debt of gratitude is in order for sharing the information, keep doing awesome. I truly delighted in investigating your site. great asset. I really appreciate this wonderful post that you have provided for us. I assure this would be beneficial for most of the people. Thank you for another informative website. Where else could I get that type of information written in such a perfect way? I have a project that I’m just now working on, and I’ve been on the look out for such information. Usually dislike any form of commenting, but when you read an excellent publish occasionally you simply have to get from those lazy techniques. That is such a submit!

this turned into honestly an interesting subject matter and i kinda consider what you have got cited here! Whats up, i have browsed most of your posts. This submit is probably wherein i got the most useful data for my studies. Thank you for posting, maybe we can see more in this. Are you aware of any other websites on this subject .
먹튀폴리스주소

hey there, i do think your website online is probably having browser compatibility issues. Every time i test your site in safari, it appears first-class but, if establishing in i. E., it has some overlapping troubles. I simply desired to offer you with a short heads up! Other than that, notable website! I’d want to thank you for the efforts you have got installed writing this site. I am hoping to peer the same high-grade content material by means of you afterward as properly. In fact, your creative writing skills has inspired me to get my personal web site now . it’s hard to find well-informed people approximately this subject matter, however, you sound like you know what you’re talking about! Thanks
먹튀검증

I have been looking for this information for a long time, this website retro bowl is so cool

I have read many other blogs, but yours is the only one that has persuaded me, and I hope that you will continue to share more insightful content with readers in the future.
papa’s freezeria

Thanks to your instructions I was able to make my site wordle website perfectly functional. Admittedly you are a very good programmer and I really like that.

I’ve been troubled for several days with this topic. 카지노사이트, But by chance looking at your post solved my problem! I will leave my blog, so when would you like to visit it?

Many thanks to the author AI Tool for sharing this article about Java, which made my website run smoothly.[url=https://aitoolmall.com/]AI Tool[/url]

Wow, is this a fake Facebook Inattv.icu? Damn it looks so real! Use the settings to the left to begin — You can also add comments & emoticons.

Hello there, I came into your blog while searching for such an educational post on Google, and your post appears to be extremely intriguing to me. wordle today

It took me a long time to find a website with so many good articles krunker and interesting information. tetris unblocked

Hello. Reading this article reminded me of the past. I want to talk again with the person who saw your post and told me about it. I’ll pass it on so he can read it. Thanks for sharing.메이저사이트

I visit the blog every day to see new posts and articles. I saw a good article on your site and took notes. We sincerely appreciate your information.먹튀신고

Is it just me or does anyone else feel it? Reading your blog, I wondered how you came up with such an article. Please be the one who always writes amazing articles until the end.먹튀검증

You can tell from the articles on your blog that you are a person who thinks more deeply than anyone else. If you agree with that idea, I hope you will visit my site as well.토토사이트

Active cheat codes updated roblox codes 2023

I can’t believe I didn’t know about your post until now. The information you share is very important to me because it is important documents slither io to complement the topic I am studying.

Ваш пост меня удивил, он очень познавательный eggy car

Your ideas inspired me very much. 온라인바카라사이트 It’s amazing. I want to learn your writing skills. In fact, I also have a website. If you are okay, please visit once and leave your opinion. Thank you.

whoah this weblog is excellent i like studying your articles. 메이저사이트

Хорошим подходом при работе с событиями является использование делегирования событий, когда обработчик события добавляется к родительскому элементу, который «слушает» события всех своих дочерних элементов. bluey

Supreme Vision CCTV is a provider of CCTV installation and repair services, access control, and transmission security systems. Supreme Vision Stay updated with construction site security and the latest trends and technologies in the security industry.

Steam Innovation was formed as an innovation academy to reveal kids’ usual creativity and curiosity with the help of learning kits while helping parents who want to bring enriching experiences to their children. We hope monthly stem kits will produce the problem-solving skills and creative sureness that kids gain today and will help them tackle the experiments and breaks of tomorrow.

Hello, I read the post well. 토토사이트추천 It’s a really interesting topic and it has helped me a lot. In fact, I also run a website with similar content to your posting. Please visit once

Your ideas inspired me very much.토토사이트순위 It’s amazing. I want to learn your writing skills. In fact, I also have a website. If you are okay, please visit once and leave your opinion. Thank you.

I’m not sure exactly why but this weblog is loading incredibly slow for me. Is anyone else having this problem or is it a problem on my end? I’ll check back later on and see if the problem still exists. 다바오홀덤

While looking for articles on these topics, I came across this article on the site here. As I read your article, I felt like an expert in this field. I have several articles on these topics posted on my site. Could you please visit my homepage? 안전놀이터

Your ideas inspired me very much. 토토사이트순위 It’s amazing. I want to learn your writing skills. In fact, I also have a website. If you are okay, please visit once and leave your opinion. Thank you.

I accidentally searched and visited your site. I still saw several posts during my visit, but the text was neat and readable. I will quote this post and post it on my blog. Would you like to visit my blog later? 스포츠토토사이트

I am usually to blogging i genuinely appreciate your content. Your content has really peaks my interest. 메이저놀이터

Well I truly enjoyed reading it. This subject offered by you is very helpful and accurate:) 토토사이트추천

Well I truly enjoyed reading it. This subject offered by you is very helpful and accurate:) 토토사이트추천

Outstanding information flow. We should take the five minutes it will take to read this text while lying down. (: 토토사이트

team helps you to guide in all aspects of Technology, Business, Gadgets, Marketing and Apps related news. Our goal is to provide all the latest information to our audience. 먹튀검증

I am very glad to see such excellent info being shared freely out there. Youre so cool! I dont suppose Ive read anything like this before (: 메이저사이트

I am hoping for the same best effort from you in the future as well. In fact, your creative writing skills have inspired me. (: 토토사이트 추천

Many people say it surrounds the simul. I’m afraid to see more than I can imagine먹튀검증사이트

Your post is awesome. Don’t miss mapquest directions if you’re looking for a good navigational tool.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *